aboutsummaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
Diffstat (limited to 'sim')
-rw-r--r--sim/common/sim-fpu.c31
-rw-r--r--sim/common/sim-fpu.h25
-rw-r--r--sim/mips/cp1.h4
-rw-r--r--sim/mips/mips.igen3
-rw-r--r--sim/mips/sim-main.h3
5 files changed, 48 insertions, 18 deletions
diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index a05c578..276ad23 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -198,11 +198,10 @@ pack_fpu (const sim_fpu *src,
/* 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;
@@ -210,11 +209,10 @@ pack_fpu (const sim_fpu *src,
/* 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;
@@ -372,11 +370,10 @@ unpack_fpu (sim_fpu *dst, uint64_t packed, int is_double)
/* 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
@@ -2512,6 +2509,10 @@ sim_fpu_gt (int *is,
/* 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
};
diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h
index 447621b..b0b318c 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#define SIM_FPU_H
+#include <stdbool.h>
+
/* The FPU intermediate type - this object, passed by reference,
should be treated as opaque.
@@ -157,6 +159,17 @@ typedef enum
+/* 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.
@@ -375,7 +388,19 @@ enum {
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. */
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index 96c51a7..d6d8a88 100644
--- a/sim/mips/cp1.h
+++ b/sim/mips/cp1.h
@@ -40,6 +40,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#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
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index c5db5c2..b0c5e59 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -5050,6 +5050,9 @@
{
if (! COP_Usable (1))
SignalExceptionCoProcessorUnusable (1);
+
+ FCSR &= ~fcsr_NAN2008_mask;
+ sim_fpu_quiet_nan_inverted = true;
}
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index d724688..8e3e85f 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -20,9 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#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))