diff options
-rw-r--r-- | sim/common/sim-fpu.c | 31 | ||||
-rw-r--r-- | sim/common/sim-fpu.h | 25 | ||||
-rw-r--r-- | sim/mips/cp1.h | 4 | ||||
-rw-r--r-- | sim/mips/mips.igen | 3 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 3 |
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)) |