/* Force fraction to correct class. */
fraction = src->fraction;
fraction >>= NR_GUARDS;
-#ifdef SIM_QUIET_NAN_NEGATED
- fraction |= QUIET_NAN - 1;
-#else
- fraction |= QUIET_NAN;
-#endif
+ if (sim_fpu_quiet_nan_inverted)
+ fraction |= QUIET_NAN - 1;
+ else
+ fraction |= QUIET_NAN;
break;
case sim_fpu_class_snan:
sign = src->sign;
/* Force fraction to correct class. */
fraction = src->fraction;
fraction >>= NR_GUARDS;
-#ifdef SIM_QUIET_NAN_NEGATED
- fraction |= QUIET_NAN;
-#else
- fraction &= ~QUIET_NAN;
-#endif
+ if (sim_fpu_quiet_nan_inverted)
+ fraction |= QUIET_NAN;
+ else
+ fraction &= ~QUIET_NAN;
break;
case sim_fpu_class_infinity:
sign = src->sign;
/* Non zero fraction, means NaN. */
dst->sign = sign;
dst->fraction = (fraction << NR_GUARDS);
-#ifdef SIM_QUIET_NAN_NEGATED
- qnan = (fraction & QUIET_NAN) == 0;
-#else
- qnan = fraction >= QUIET_NAN;
-#endif
+ if (sim_fpu_quiet_nan_inverted)
+ qnan = (fraction & QUIET_NAN) == 0;
+ else
+ qnan = fraction >= QUIET_NAN;
if (qnan)
dst->class = sim_fpu_class_qnan;
else
/* A number of useful constants */
#if EXTERN_SIM_FPU_P
+sim_fpu_state _sim_fpu = {
+ .quiet_nan_inverted = false,
+};
+
const sim_fpu sim_fpu_zero = {
sim_fpu_class_zero, 0, 0, 0
};
#define SIM_FPU_H
+#include <stdbool.h>
+
/* The FPU intermediate type - this object, passed by reference,
should be treated as opaque.
+/* State used by the FPU.
+
+ FIXME: This state is global, but should be moved to SIM_CPU. */
+
+typedef struct _sim_fpu_state {
+ bool quiet_nan_inverted; /* Toggle quiet NaN semantics. */
+} sim_fpu_state;
+
+
+
+
/* Directly map between a 32/64 bit register and the sim_fpu internal
type.
INLINE_SIM_FPU (int) sim_fpu_is (const sim_fpu *l);
INLINE_SIM_FPU (int) sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r);
+/* Global FPU state. */
+
+extern sim_fpu_state _sim_fpu;
+
+
+/* IEEE 754-1985 specifies the top bit of the mantissa as an indicator
+ of signalling vs. quiet NaN, but does not specify the semantics.
+ Most architectures treat this bit as quiet NaN, but legacy (pre-R6)
+ MIPS goes the other way and treats it as signalling. This variable
+ tracks the current semantics of the NaN bit and allows differentiation
+ between pre-R6 and R6 MIPS cores. */
+#define sim_fpu_quiet_nan_inverted _sim_fpu.quiet_nan_inverted
/* A number of useful constants. */
#define fcsr_RM_mask (0x00000003)
#define fcsr_RM_shift (0)
+/* FCSR bits for IEEE754-2008 compliance. */
+#define fcsr_NAN2008_mask (0x00040000)
+#define fcsr_NAN2008_shift (18)
+
#define fenr_FS (0x00000004)
/* Macros to update and retrieve the FCSR condition-code bits. This
{
if (! COP_Usable (1))
SignalExceptionCoProcessorUnusable (1);
+
+ FCSR &= ~fcsr_NAN2008_mask;
+ sim_fpu_quiet_nan_inverted = true;
}
#ifndef SIM_MAIN_H
#define SIM_MAIN_H
-/* MIPS uses an unusual format for floating point quiet NaNs. */
-#define SIM_QUIET_NAN_NEGATED
-
#define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
mips_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))