aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/cpu.h16
-rw-r--r--target-mips/gdbstub.c8
-rw-r--r--target-mips/helper.h22
-rw-r--r--target-mips/msa_helper.c88
-rw-r--r--target-mips/op_helper.c400
-rw-r--r--target-mips/translate.c156
-rw-r--r--target-mips/translate_init.c29
7 files changed, 598 insertions, 121 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 30b4712c71..1037f9b7eb 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -111,7 +111,9 @@ struct CPUMIPSFPUContext {
#define FCR0_PRID 8
#define FCR0_REV 0
/* fcsr */
+ uint32_t fcr31_rw_bitmask;
uint32_t fcr31;
+#define FCR31_FS 24
#define FCR31_ABS2008 19
#define FCR31_NAN2008 18
#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
@@ -823,6 +825,11 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
/* helper.c */
int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
int mmu_idx);
+
+/* op_helper.c */
+uint32_t float_class_s(uint32_t arg, float_status *fst);
+uint64_t float_class_d(uint64_t arg, float_status *fst);
+
#if !defined(CONFIG_USER_ONLY)
void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
@@ -842,14 +849,21 @@ static inline void restore_rounding_mode(CPUMIPSState *env)
static inline void restore_flush_mode(CPUMIPSState *env)
{
- set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0,
+ set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
&env->active_fpu.fp_status);
}
+static inline void restore_snan_bit_mode(CPUMIPSState *env)
+{
+ set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0,
+ &env->active_fpu.fp_status);
+}
+
static inline void restore_fp_status(CPUMIPSState *env)
{
restore_rounding_mode(env);
restore_flush_mode(env);
+ restore_snan_bit_mode(env);
}
static inline void restore_msa_fp_status(CPUMIPSState *env)
diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c
index 2707ff5c2b..7c682289c2 100644
--- a/target-mips/gdbstub.c
+++ b/target-mips/gdbstub.c
@@ -90,11 +90,9 @@ int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
switch (n) {
case 70:
- env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
- /* set rounding mode */
- restore_rounding_mode(env);
- /* set flush-to-zero mode */
- restore_flush_mode(env);
+ env->active_fpu.fcr31 = (tmp & env->active_fpu.fcr31_rw_bitmask) |
+ (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
+ restore_fp_status(env);
break;
case 71:
/* FIR is read-only. Ignore writes. */
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 594341d258..666936c81b 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -207,8 +207,6 @@ DEF_HELPER_4(ctc1, void, env, tl, i32, i32)
DEF_HELPER_2(float_cvtd_s, i64, env, i32)
DEF_HELPER_2(float_cvtd_w, i64, env, i32)
DEF_HELPER_2(float_cvtd_l, i64, env, i64)
-DEF_HELPER_2(float_cvtl_d, i64, env, i64)
-DEF_HELPER_2(float_cvtl_s, i64, env, i32)
DEF_HELPER_2(float_cvtps_pw, i64, env, i64)
DEF_HELPER_2(float_cvtpw_ps, i64, env, i64)
DEF_HELPER_2(float_cvts_d, i32, env, i64)
@@ -216,14 +214,12 @@ DEF_HELPER_2(float_cvts_w, i32, env, i32)
DEF_HELPER_2(float_cvts_l, i32, env, i64)
DEF_HELPER_2(float_cvts_pl, i32, env, i32)
DEF_HELPER_2(float_cvts_pu, i32, env, i32)
-DEF_HELPER_2(float_cvtw_s, i32, env, i32)
-DEF_HELPER_2(float_cvtw_d, i32, env, i64)
DEF_HELPER_3(float_addr_ps, i64, env, i64, i64)
DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64)
-DEF_HELPER_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32)
-DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_FLAGS_2(float_class_s, TCG_CALL_NO_RWG_SE, i32, env, i32)
+DEF_HELPER_FLAGS_2(float_class_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
#define FOP_PROTO(op) \
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
@@ -242,14 +238,20 @@ FOP_PROTO(mina)
#undef FOP_PROTO
#define FOP_PROTO(op) \
-DEF_HELPER_2(float_ ## op ## l_s, i64, env, i32) \
-DEF_HELPER_2(float_ ## op ## l_d, i64, env, i64) \
-DEF_HELPER_2(float_ ## op ## w_s, i32, env, i32) \
-DEF_HELPER_2(float_ ## op ## w_d, i32, env, i64)
+DEF_HELPER_2(float_ ## op ## _l_s, i64, env, i32) \
+DEF_HELPER_2(float_ ## op ## _l_d, i64, env, i64) \
+DEF_HELPER_2(float_ ## op ## _w_s, i32, env, i32) \
+DEF_HELPER_2(float_ ## op ## _w_d, i32, env, i64)
+FOP_PROTO(cvt)
FOP_PROTO(round)
FOP_PROTO(trunc)
FOP_PROTO(ceil)
FOP_PROTO(floor)
+FOP_PROTO(cvt_2008)
+FOP_PROTO(round_2008)
+FOP_PROTO(trunc_2008)
+FOP_PROTO(ceil_2008)
+FOP_PROTO(floor_2008)
#undef FOP_PROTO
#define FOP_PROTO(op) \
diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c
index ae92fcbe28..1fdb0d9792 100644
--- a/target-mips/msa_helper.c
+++ b/target-mips/msa_helper.c
@@ -1495,11 +1495,11 @@ MSA_UNOP_DF(pcnt)
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
-#define FLOAT_SNAN16 (float16_default_nan ^ 0x0220)
+#define FLOAT_SNAN16(s) (float16_default_nan(s) ^ 0x0220)
/* 0x7c20 */
-#define FLOAT_SNAN32 (float32_default_nan ^ 0x00400020)
+#define FLOAT_SNAN32(s) (float32_default_nan(s) ^ 0x00400020)
/* 0x7f800020 */
-#define FLOAT_SNAN64 (float64_default_nan ^ 0x0008000000000020ULL)
+#define FLOAT_SNAN64(s) (float64_default_nan(s) ^ 0x0008000000000020ULL)
/* 0x7ff0000000000020 */
static inline void clear_msacsr_cause(CPUMIPSState *env)
@@ -1612,7 +1612,7 @@ static inline float16 float16_from_float32(int32_t a, flag ieee,
float16 f_val;
f_val = float32_to_float16((float32)a, ieee, status);
- f_val = float16_maybe_silence_nan(f_val);
+ f_val = float16_maybe_silence_nan(f_val, status);
return a < 0 ? (f_val | (1 << 15)) : f_val;
}
@@ -1622,7 +1622,7 @@ static inline float32 float32_from_float64(int64_t a, float_status *status)
float32 f_val;
f_val = float64_to_float32((float64)a, status);
- f_val = float32_maybe_silence_nan(f_val);
+ f_val = float32_maybe_silence_nan(f_val, status);
return a < 0 ? (f_val | (1 << 31)) : f_val;
}
@@ -1633,7 +1633,7 @@ static inline float32 float32_from_float16(int16_t a, flag ieee,
float32 f_val;
f_val = float16_to_float32((float16)a, ieee, status);
- f_val = float32_maybe_silence_nan(f_val);
+ f_val = float32_maybe_silence_nan(f_val, status);
return a < 0 ? (f_val | (1 << 31)) : f_val;
}
@@ -1643,7 +1643,7 @@ static inline float64 float64_from_float32(int32_t a, float_status *status)
float64 f_val;
f_val = float32_to_float64((float64)a, status);
- f_val = float64_maybe_silence_nan(f_val);
+ f_val = float64_maybe_silence_nan(f_val, status);
return a < 0 ? (f_val | (1ULL << 63)) : f_val;
}
@@ -1789,7 +1789,7 @@ static inline int32_t float64_to_q32(float64 a, float_status *status)
c = update_msacsr(env, CLEAR_IS_INEXACT, 0); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
@@ -2388,7 +2388,7 @@ void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
@@ -2524,7 +2524,7 @@ void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
@@ -2643,7 +2643,7 @@ void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
@@ -2694,7 +2694,7 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## XBITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## XBITS(status) >> 6) << 6) | c; \
} \
} while (0)
@@ -2731,9 +2731,9 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
msa_move_v(pwd, pwx);
}
-#define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS) \
- !float ## BITS ## _is_any_nan(ARG1) \
- && float ## BITS ## _is_quiet_nan(ARG2)
+#define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS, STATUS) \
+ !float ## BITS ## _is_any_nan(ARG1) \
+ && float ## BITS ## _is_quiet_nan(ARG2, STATUS)
#define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS) \
do { \
@@ -2745,18 +2745,18 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
c = update_msacsr(env, 0, 0); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
-#define FMAXMIN_A(F, G, X, _S, _T, BITS) \
+#define FMAXMIN_A(F, G, X, _S, _T, BITS, STATUS) \
do { \
uint## BITS ##_t S = _S, T = _T; \
uint## BITS ##_t as, at, xs, xt, xd; \
- if (NUMBER_QNAN_PAIR(S, T, BITS)) { \
+ if (NUMBER_QNAN_PAIR(S, T, BITS, STATUS)) { \
T = S; \
} \
- else if (NUMBER_QNAN_PAIR(T, S, BITS)) { \
+ else if (NUMBER_QNAN_PAIR(T, S, BITS, STATUS)) { \
S = T; \
} \
as = float## BITS ##_abs(S); \
@@ -2770,6 +2770,7 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
+ float_status *status = &env->active_tc.msa_fp_status;
wr_t wx, *pwx = &wx;
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2781,9 +2782,9 @@ void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
- if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32)) {
+ if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) {
MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pws->w[i], 32);
- } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32)) {
+ } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) {
MSA_FLOAT_MAXOP(pwx->w[i], min, pwt->w[i], pwt->w[i], 32);
} else {
MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pwt->w[i], 32);
@@ -2792,9 +2793,9 @@ void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
break;
case DF_DOUBLE:
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
- if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64)) {
+ if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) {
MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pws->d[i], 64);
- } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64)) {
+ } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) {
MSA_FLOAT_MAXOP(pwx->d[i], min, pwt->d[i], pwt->d[i], 64);
} else {
MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pwt->d[i], 64);
@@ -2813,6 +2814,7 @@ void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
+ float_status *status = &env->active_tc.msa_fp_status;
wr_t wx, *pwx = &wx;
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2824,12 +2826,12 @@ void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
- FMAXMIN_A(min, max, pwx->w[i], pws->w[i], pwt->w[i], 32);
+ FMAXMIN_A(min, max, pwx->w[i], pws->w[i], pwt->w[i], 32, status);
}
break;
case DF_DOUBLE:
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
- FMAXMIN_A(min, max, pwx->d[i], pws->d[i], pwt->d[i], 64);
+ FMAXMIN_A(min, max, pwx->d[i], pws->d[i], pwt->d[i], 64, status);
}
break;
default:
@@ -2844,6 +2846,7 @@ void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
+ float_status *status = &env->active_tc.msa_fp_status;
wr_t wx, *pwx = &wx;
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2855,9 +2858,9 @@ void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
- if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32)) {
+ if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) {
MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pws->w[i], 32);
- } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32)) {
+ } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) {
MSA_FLOAT_MAXOP(pwx->w[i], max, pwt->w[i], pwt->w[i], 32);
} else {
MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pwt->w[i], 32);
@@ -2866,9 +2869,9 @@ void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
break;
case DF_DOUBLE:
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
- if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64)) {
+ if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) {
MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pws->d[i], 64);
- } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64)) {
+ } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) {
MSA_FLOAT_MAXOP(pwx->d[i], max, pwt->d[i], pwt->d[i], 64);
} else {
MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pwt->d[i], 64);
@@ -2887,6 +2890,7 @@ void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
uint32_t ws, uint32_t wt)
{
+ float_status *status = &env->active_tc.msa_fp_status;
wr_t wx, *pwx = &wx;
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2898,12 +2902,12 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
switch (df) {
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
- FMAXMIN_A(max, min, pwx->w[i], pws->w[i], pwt->w[i], 32);
+ FMAXMIN_A(max, min, pwx->w[i], pws->w[i], pwt->w[i], 32, status);
}
break;
case DF_DOUBLE:
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
- FMAXMIN_A(max, min, pwx->d[i], pws->d[i], pwt->d[i], 64);
+ FMAXMIN_A(max, min, pwx->d[i], pws->d[i], pwt->d[i], 64, status);
}
break;
default:
@@ -2918,16 +2922,18 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df,
uint32_t wd, uint32_t ws)
{
+ float_status* status = &env->active_tc.msa_fp_status;
+
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr);
if (df == DF_WORD) {
- pwd->w[0] = helper_float_class_s(pws->w[0]);
- pwd->w[1] = helper_float_class_s(pws->w[1]);
- pwd->w[2] = helper_float_class_s(pws->w[2]);
- pwd->w[3] = helper_float_class_s(pws->w[3]);
+ pwd->w[0] = float_class_s(pws->w[0], status);
+ pwd->w[1] = float_class_s(pws->w[1], status);
+ pwd->w[2] = float_class_s(pws->w[2], status);
+ pwd->w[3] = float_class_s(pws->w[3], status);
} else {
- pwd->d[0] = helper_float_class_d(pws->d[0]);
- pwd->d[1] = helper_float_class_d(pws->d[1]);
+ pwd->d[0] = float_class_d(pws->d[0], status);
+ pwd->d[1] = float_class_d(pws->d[1], status);
}
}
@@ -2941,7 +2947,7 @@ void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df,
c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} else if (float ## BITS ## _is_any_nan(ARG)) { \
DEST = 0; \
} \
@@ -3045,12 +3051,12 @@ void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
set_float_exception_flags(0, status); \
DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, status); \
c = update_msacsr(env, float ## BITS ## _is_infinity(ARG) || \
- float ## BITS ## _is_quiet_nan(DEST) ? \
+ float ## BITS ## _is_quiet_nan(DEST, status) ? \
0 : RECIPROCAL_INEXACT, \
IS_DENORMAL(DEST, BITS)); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
@@ -3166,7 +3172,7 @@ void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
\
if (get_enabled_exceptions(env, c)) { \
- DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c; \
+ DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c; \
} \
} while (0)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 1ae1dda0af..69daade24e 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2447,6 +2447,7 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
#define FLOAT_TWO32 make_float32(1 << 30)
#define FLOAT_TWO64 make_float64(1ULL << 62)
+
#define FP_TO_INT32_OVERFLOW 0x7fffffff
#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
@@ -2574,21 +2575,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
((arg1 & 0x4) << 22);
break;
case 31:
- if (env->insn_flags & ISA_MIPS32R6) {
- uint32_t mask = 0xfefc0000;
- env->active_fpu.fcr31 = (arg1 & ~mask) |
- (env->active_fpu.fcr31 & mask);
- } else if (!(arg1 & 0x007c0000)) {
- env->active_fpu.fcr31 = arg1;
- }
+ env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) |
+ (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask));
break;
default:
return;
}
- /* set rounding mode */
- restore_rounding_mode(env);
- /* set flush-to-zero mode */
- restore_flush_mode(env);
+ restore_fp_status(env);
set_float_exception_flags(0, &env->active_fpu.fp_status);
if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
do_raise_exception(env, EXCP_FPE, GETPC());
@@ -2659,7 +2652,7 @@ uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0)
uint64_t fdt2;
fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
- fdt2 = float64_maybe_silence_nan(fdt2);
+ fdt2 = float64_maybe_silence_nan(fdt2, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fdt2;
}
@@ -2682,7 +2675,7 @@ uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0)
return fdt2;
}
-uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0)
+uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0)
{
uint64_t dt2;
@@ -2695,7 +2688,7 @@ uint64_t helper_float_cvtl_d(CPUMIPSState *env, uint64_t fdt0)
return dt2;
}
-uint64_t helper_float_cvtl_s(CPUMIPSState *env, uint32_t fst0)
+uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0)
{
uint64_t dt2;
@@ -2749,7 +2742,7 @@ uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0)
uint32_t fst2;
fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
- fst2 = float32_maybe_silence_nan(fst2);
+ fst2 = float32_maybe_silence_nan(fst2, &env->active_fpu.fp_status);
update_fcr31(env, GETPC());
return fst2;
}
@@ -2790,7 +2783,7 @@ uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0)
return wt2;
}
-uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0)
+uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0)
{
uint32_t wt2;
@@ -2803,7 +2796,7 @@ uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0)
return wt2;
}
-uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0)
+uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0)
{
uint32_t wt2;
@@ -2816,7 +2809,7 @@ uint32_t helper_float_cvtw_d(CPUMIPSState *env, uint64_t fdt0)
return wt2;
}
-uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0)
+uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0)
{
uint64_t dt2;
@@ -2831,7 +2824,7 @@ uint64_t helper_float_roundl_d(CPUMIPSState *env, uint64_t fdt0)
return dt2;
}
-uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0)
+uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0)
{
uint64_t dt2;
@@ -2846,7 +2839,7 @@ uint64_t helper_float_roundl_s(CPUMIPSState *env, uint32_t fst0)
return dt2;
}
-uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0)
+uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0)
{
uint32_t wt2;
@@ -2861,7 +2854,7 @@ uint32_t helper_float_roundw_d(CPUMIPSState *env, uint64_t fdt0)
return wt2;
}
-uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0)
+uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0)
{
uint32_t wt2;
@@ -2876,7 +2869,7 @@ uint32_t helper_float_roundw_s(CPUMIPSState *env, uint32_t fst0)
return wt2;
}
-uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0)
+uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0)
{
uint64_t dt2;
@@ -2889,7 +2882,7 @@ uint64_t helper_float_truncl_d(CPUMIPSState *env, uint64_t fdt0)
return dt2;
}
-uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0)
+uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0)
{
uint64_t dt2;
@@ -2902,7 +2895,7 @@ uint64_t helper_float_truncl_s(CPUMIPSState *env, uint32_t fst0)
return dt2;
}
-uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0)
+uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0)
{
uint32_t wt2;
@@ -2915,7 +2908,7 @@ uint32_t helper_float_truncw_d(CPUMIPSState *env, uint64_t fdt0)
return wt2;
}
-uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0)
+uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0)
{
uint32_t wt2;
@@ -2928,7 +2921,7 @@ uint32_t helper_float_truncw_s(CPUMIPSState *env, uint32_t fst0)
return wt2;
}
-uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0)
+uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0)
{
uint64_t dt2;
@@ -2943,7 +2936,7 @@ uint64_t helper_float_ceill_d(CPUMIPSState *env, uint64_t fdt0)
return dt2;
}
-uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0)
+uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0)
{
uint64_t dt2;
@@ -2958,7 +2951,7 @@ uint64_t helper_float_ceill_s(CPUMIPSState *env, uint32_t fst0)
return dt2;
}
-uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0)
+uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0)
{
uint32_t wt2;
@@ -2973,7 +2966,7 @@ uint32_t helper_float_ceilw_d(CPUMIPSState *env, uint64_t fdt0)
return wt2;
}
-uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0)
+uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0)
{
uint32_t wt2;
@@ -2988,7 +2981,7 @@ uint32_t helper_float_ceilw_s(CPUMIPSState *env, uint32_t fst0)
return wt2;
}
-uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0)
+uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0)
{
uint64_t dt2;
@@ -3003,7 +2996,7 @@ uint64_t helper_float_floorl_d(CPUMIPSState *env, uint64_t fdt0)
return dt2;
}
-uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0)
+uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0)
{
uint64_t dt2;
@@ -3018,7 +3011,7 @@ uint64_t helper_float_floorl_s(CPUMIPSState *env, uint32_t fst0)
return dt2;
}
-uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0)
+uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0)
{
uint32_t wt2;
@@ -3033,7 +3026,7 @@ uint32_t helper_float_floorw_d(CPUMIPSState *env, uint64_t fdt0)
return wt2;
}
-uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0)
+uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0)
{
uint32_t wt2;
@@ -3048,6 +3041,334 @@ uint32_t helper_float_floorw_s(CPUMIPSState *env, uint32_t fst0)
return wt2;
}
+uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint64_t dt2;
+
+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint64_t dt2;
+
+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint32_t wt2;
+
+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint32_t wt2;
+
+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint64_t dt2;
+
+ set_float_rounding_mode(float_round_nearest_even,
+ &env->active_fpu.fp_status);
+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint64_t dt2;
+
+ set_float_rounding_mode(float_round_nearest_even,
+ &env->active_fpu.fp_status);
+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint32_t wt2;
+
+ set_float_rounding_mode(float_round_nearest_even,
+ &env->active_fpu.fp_status);
+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint32_t wt2;
+
+ set_float_rounding_mode(float_round_nearest_even,
+ &env->active_fpu.fp_status);
+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint64_t dt2;
+
+ dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint64_t dt2;
+
+ dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint32_t wt2;
+
+ wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint32_t wt2;
+
+ wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint64_t dt2;
+
+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint64_t dt2;
+
+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint32_t wt2;
+
+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint32_t wt2;
+
+ set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint64_t dt2;
+
+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
+ dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint64_t dt2;
+
+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
+ dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ dt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return dt2;
+}
+
+uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0)
+{
+ uint32_t wt2;
+
+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
+ wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float64_is_any_nan(fdt0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
+uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0)
+{
+ uint32_t wt2;
+
+ set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
+ wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
+ restore_rounding_mode(env);
+ if (get_float_exception_flags(&env->active_fpu.fp_status)
+ & float_flag_invalid) {
+ if (float32_is_any_nan(fst0)) {
+ wt2 = 0;
+ }
+ }
+ update_fcr31(env, GETPC());
+ return wt2;
+}
+
/* unary operations, not modifying fp status */
#define FLOAT_UNOP(name) \
uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \
@@ -3199,11 +3520,12 @@ FLOAT_RINT(rint_d, 64)
#define FLOAT_CLASS_POSITIVE_ZERO 0x200
#define FLOAT_CLASS(name, bits) \
-uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg) \
+uint ## bits ## _t float_ ## name (uint ## bits ## _t arg, \
+ float_status *status) \
{ \
- if (float ## bits ## _is_signaling_nan(arg)) { \
+ if (float ## bits ## _is_signaling_nan(arg, status)) { \
return FLOAT_CLASS_SIGNALING_NAN; \
- } else if (float ## bits ## _is_quiet_nan(arg)) { \
+ } else if (float ## bits ## _is_quiet_nan(arg, status)) { \
return FLOAT_CLASS_QUIET_NAN; \
} else if (float ## bits ## _is_neg(arg)) { \
if (float ## bits ## _is_infinity(arg)) { \
@@ -3226,6 +3548,12 @@ uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg) \
return FLOAT_CLASS_POSITIVE_NORMAL; \
} \
} \
+} \
+ \
+uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
+ uint ## bits ## _t arg) \
+{ \
+ return float_ ## name(arg, &env->active_fpu.fp_status); \
}
FLOAT_CLASS(class_s, 32)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index aaa1d02683..cc321e9cce 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1435,6 +1435,8 @@ typedef struct DisasContext {
bool vp;
bool cmgcr;
bool mrp;
+ bool nan2008;
+ bool abs2008;
} DisasContext;
enum {
@@ -8890,7 +8892,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_abs_s(fp0, fp0);
+ if (ctx->abs2008) {
+ tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
+ } else {
+ gen_helper_float_abs_s(fp0, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -8909,7 +8915,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_chs_s(fp0, fp0);
+ if (ctx->abs2008) {
+ tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
+ } else {
+ gen_helper_float_chs_s(fp0, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -8921,7 +8931,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr32(ctx, fp32, fs);
- gen_helper_float_roundl_s(fp64, cpu_env, fp32);
+ if (ctx->nan2008) {
+ gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
+ } else {
+ gen_helper_float_round_l_s(fp64, cpu_env, fp32);
+ }
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
@@ -8934,7 +8948,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr32(ctx, fp32, fs);
- gen_helper_float_truncl_s(fp64, cpu_env, fp32);
+ if (ctx->nan2008) {
+ gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
+ } else {
+ gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
+ }
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
@@ -8947,7 +8965,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr32(ctx, fp32, fs);
- gen_helper_float_ceill_s(fp64, cpu_env, fp32);
+ if (ctx->nan2008) {
+ gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
+ } else {
+ gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
+ }
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
@@ -8960,7 +8982,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr32(ctx, fp32, fs);
- gen_helper_float_floorl_s(fp64, cpu_env, fp32);
+ if (ctx->nan2008) {
+ gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
+ } else {
+ gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
+ }
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
@@ -8971,7 +8997,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_roundw_s(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_round_w_s(fp0, cpu_env, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -8981,7 +9011,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_truncw_s(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -8991,7 +9025,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -9001,7 +9039,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_floorw_s(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -9121,7 +9163,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
{
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_class_s(fp0, fp0);
+ gen_helper_float_class_s(fp0, cpu_env, fp0);
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -9250,7 +9292,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i32 fp0 = tcg_temp_new_i32();
gen_load_fpr32(ctx, fp0, fs);
- gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
+ }
gen_store_fpr32(ctx, fp0, fd);
tcg_temp_free_i32(fp0);
}
@@ -9262,7 +9308,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr32(ctx, fp32, fs);
- gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
+ if (ctx->nan2008) {
+ gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
+ } else {
+ gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
+ }
tcg_temp_free_i32(fp32);
gen_store_fpr64(ctx, fp64, fd);
tcg_temp_free_i64(fp64);
@@ -9380,7 +9430,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_abs_d(fp0, fp0);
+ if (ctx->abs2008) {
+ tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
+ } else {
+ gen_helper_float_abs_d(fp0, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9401,7 +9455,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_chs_d(fp0, fp0);
+ if (ctx->abs2008) {
+ tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
+ } else {
+ gen_helper_float_chs_d(fp0, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9412,7 +9470,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_roundl_d(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_round_l_d(fp0, cpu_env, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9423,7 +9485,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_truncl_d(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9434,7 +9500,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_ceill_d(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9445,7 +9515,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_floorl_d(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9457,7 +9531,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp64, fs);
- gen_helper_float_roundw_d(fp32, cpu_env, fp64);
+ if (ctx->nan2008) {
+ gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
+ } else {
+ gen_helper_float_round_w_d(fp32, cpu_env, fp64);
+ }
tcg_temp_free_i64(fp64);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
@@ -9470,7 +9548,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp64, fs);
- gen_helper_float_truncw_d(fp32, cpu_env, fp64);
+ if (ctx->nan2008) {
+ gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
+ } else {
+ gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
+ }
tcg_temp_free_i64(fp64);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
@@ -9483,7 +9565,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp64, fs);
- gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
+ if (ctx->nan2008) {
+ gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
+ } else {
+ gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
+ }
tcg_temp_free_i64(fp64);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
@@ -9496,7 +9582,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp64, fs);
- gen_helper_float_floorw_d(fp32, cpu_env, fp64);
+ if (ctx->nan2008) {
+ gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
+ } else {
+ gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
+ }
tcg_temp_free_i64(fp64);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
@@ -9619,7 +9709,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
{
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_class_d(fp0, fp0);
+ gen_helper_float_class_d(fp0, cpu_env, fp0);
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -9769,7 +9859,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp64 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp64, fs);
- gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
+ if (ctx->nan2008) {
+ gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
+ } else {
+ gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
+ }
tcg_temp_free_i64(fp64);
gen_store_fpr32(ctx, fp32, fd);
tcg_temp_free_i32(fp32);
@@ -9781,7 +9875,11 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
TCGv_i64 fp0 = tcg_temp_new_i64();
gen_load_fpr64(ctx, fp0, fs);
- gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
+ if (ctx->nan2008) {
+ gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
+ } else {
+ gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
+ }
gen_store_fpr64(ctx, fp0, fd);
tcg_temp_free_i64(fp0);
}
@@ -19786,6 +19884,8 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
+ ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
+ ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
restore_cpu_state(env, &ctx);
#ifdef CONFIG_USER_ONLY
ctx.mem_idx = MIPS_HFLAG_UM;
@@ -20141,6 +20241,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
+ env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
env->msair = env->cpu_model->MSAIR;
env->insn_flags = env->cpu_model->insn_flags;
@@ -20251,8 +20352,7 @@ void cpu_state_reset(CPUMIPSState *env)
}
compute_hflags(env);
- restore_rounding_mode(env);
- restore_flush_mode(env);
+ restore_fp_status(env);
restore_pamask(env);
cs->exception_index = EXCP_NONE;
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 5af077d0de..b10284cc5d 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -84,6 +84,7 @@ struct mips_def_t {
int32_t CP0_TCStatus_rw_bitmask;
int32_t CP0_SRSCtl;
int32_t CP1_fcr0;
+ int32_t CP1_fcr31_rw_bitmask;
int32_t CP1_fcr31;
int32_t MSAIR;
int32_t SEGBITS;
@@ -273,6 +274,8 @@ static const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x3678FF1F,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
@@ -303,6 +306,8 @@ static const mips_def_t mips_defs[] =
(0xff << CP0TCSt_TASID),
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.CP0_SRSCtl = (0xf << CP0SRSCtl_HSS),
.CP0_SRSConf0_rw_bitmask = 0x3fffffff,
.CP0_SRSConf0 = (1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
@@ -343,6 +348,8 @@ static const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x3778FF1F,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
@@ -427,6 +434,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID),
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 32,
.PABITS = 40,
.insn_flags = CPU_MIPS32R5 | ASE_MSA,
@@ -465,6 +473,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
+ .CP1_fcr31_rw_bitmask = 0x0103FFFF,
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS,
@@ -485,6 +494,8 @@ static const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x3678FFFF,
/* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0x0183FFFF,
.SEGBITS = 40,
.PABITS = 36,
.insn_flags = CPU_MIPS3,
@@ -503,6 +514,8 @@ static const mips_def_t mips_defs[] =
.CP0_Status_rw_bitmask = 0x3678FFFF,
/* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
.CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 32,
.insn_flags = CPU_VR54XX,
@@ -548,6 +561,8 @@ static const mips_def_t mips_defs[] =
/* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 36,
.insn_flags = CPU_MIPS64,
@@ -575,6 +590,8 @@ static const mips_def_t mips_defs[] =
.CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
(1 << FCR0_D) | (1 << FCR0_S) |
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 36,
.insn_flags = CPU_MIPS64 | ASE_MIPS3D,
@@ -601,6 +618,8 @@ static const mips_def_t mips_defs[] =
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 36,
.insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
@@ -686,6 +705,7 @@ static const mips_def_t mips_defs[] =
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
+ .CP1_fcr31_rw_bitmask = 0x0103FFFF,
.SEGBITS = 48,
.PABITS = 48,
.insn_flags = CPU_MIPS64R6 | ASE_MSA,
@@ -704,6 +724,8 @@ static const mips_def_t mips_defs[] =
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x35D0FFFF,
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 40,
.insn_flags = CPU_LOONGSON2E,
@@ -722,6 +744,8 @@ static const mips_def_t mips_defs[] =
.CCRes = 2,
.CP0_Status_rw_bitmask = 0xF5D0FF1F, /* Bits 7:5 not writable. */
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 40,
.PABITS = 40,
.insn_flags = CPU_LOONGSON2F,
@@ -749,6 +773,8 @@ static const mips_def_t mips_defs[] =
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 36,
.insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
@@ -892,4 +918,7 @@ static void msa_reset(CPUMIPSState *env)
/* clear float_status nan mode */
set_default_nan_mode(0, &env->active_tc.msa_fp_status);
+
+ /* set proper signanling bit meaning ("1" means "quiet") */
+ set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
}