diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index dbb8ca5692..7a3a61cab3 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -189,43 +189,48 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) } } -int ieee_ex_to_mips(int xcpt) +static inline int ieee_to_mips_xcpt(int ieee_xcpt) { - int ret = 0; - if (xcpt) { - if (xcpt & float_flag_invalid) { - ret |= FP_INVALID; - } - if (xcpt & float_flag_overflow) { - ret |= FP_OVERFLOW; - } - if (xcpt & float_flag_underflow) { - ret |= FP_UNDERFLOW; - } - if (xcpt & float_flag_divbyzero) { - ret |= FP_DIV0; - } - if (xcpt & float_flag_inexact) { - ret |= FP_INEXACT; - } + int mips_xcpt = 0; + + if (ieee_xcpt & float_flag_invalid) { + mips_xcpt |= FP_INVALID; } - return ret; + if (ieee_xcpt & float_flag_overflow) { + mips_xcpt |= FP_OVERFLOW; + } + if (ieee_xcpt & float_flag_underflow) { + mips_xcpt |= FP_UNDERFLOW; + } + if (ieee_xcpt & float_flag_divbyzero) { + mips_xcpt |= FP_DIV0; + } + if (ieee_xcpt & float_flag_inexact) { + mips_xcpt |= FP_INEXACT; + } + + return mips_xcpt; } static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc) { - int tmp = ieee_ex_to_mips(get_float_exception_flags( - &env->active_fpu.fp_status)); + int ieee_exception_flags = get_float_exception_flags( + &env->active_fpu.fp_status); + int mips_exception_flags = 0; - SET_FP_CAUSE(env->active_fpu.fcr31, tmp); + if (ieee_exception_flags) { + mips_exception_flags = ieee_to_mips_xcpt(ieee_exception_flags); + } - if (tmp) { + SET_FP_CAUSE(env->active_fpu.fcr31, mips_exception_flags); + + if (mips_exception_flags) { set_float_exception_flags(0, &env->active_fpu.fp_status); - if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) { + if (GET_FP_ENABLE(env->active_fpu.fcr31) & mips_exception_flags) { do_raise_exception(env, EXCP_FPE, pc); } else { - UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); + UPDATE_FP_FLAGS(env->active_fpu.fcr31, mips_exception_flags); } } } diff --git a/target/mips/internal.h b/target/mips/internal.h index 1bf274b3ef..684356e309 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -224,7 +224,6 @@ uint32_t float_class_s(uint32_t arg, float_status *fst); uint64_t float_class_d(uint64_t arg, float_status *fst); extern unsigned int ieee_rm[]; -int ieee_ex_to_mips(int xcpt); void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask); static inline void restore_rounding_mode(CPUMIPSState *env) diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c index 3c7012c0b8..c3b271934a 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/msa_helper.c @@ -5419,54 +5419,81 @@ static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr) #define CLEAR_IS_INEXACT 2 #define RECIPROCAL_INEXACT 4 + +static inline int ieee_to_mips_xcpt_msa(int ieee_xcpt) +{ + int mips_xcpt = 0; + + if (ieee_xcpt & float_flag_invalid) { + mips_xcpt |= FP_INVALID; + } + if (ieee_xcpt & float_flag_overflow) { + mips_xcpt |= FP_OVERFLOW; + } + if (ieee_xcpt & float_flag_underflow) { + mips_xcpt |= FP_UNDERFLOW; + } + if (ieee_xcpt & float_flag_divbyzero) { + mips_xcpt |= FP_DIV0; + } + if (ieee_xcpt & float_flag_inexact) { + mips_xcpt |= FP_INEXACT; + } + + return mips_xcpt; +} + static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) { - int ieee_ex; - - int c; + int ieee_exception_flags; + int mips_exception_flags = 0; int cause; int enable; - ieee_ex = get_float_exception_flags(&env->active_tc.msa_fp_status); + ieee_exception_flags = get_float_exception_flags( + &env->active_tc.msa_fp_status); /* QEMU softfloat does not signal all underflow cases */ if (denormal) { - ieee_ex |= float_flag_underflow; + ieee_exception_flags |= float_flag_underflow; + } + if (ieee_exception_flags) { + mips_exception_flags = ieee_to_mips_xcpt_msa(ieee_exception_flags); } - - c = ieee_ex_to_mips(ieee_ex); enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED; /* Set Inexact (I) when flushing inputs to zero */ - if ((ieee_ex & float_flag_input_denormal) && + if ((ieee_exception_flags & float_flag_input_denormal) && (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) { if (action & CLEAR_IS_INEXACT) { - c &= ~FP_INEXACT; + mips_exception_flags &= ~FP_INEXACT; } else { - c |= FP_INEXACT; + mips_exception_flags |= FP_INEXACT; } } /* Set Inexact (I) and Underflow (U) when flushing outputs to zero */ - if ((ieee_ex & float_flag_output_denormal) && + if ((ieee_exception_flags & float_flag_output_denormal) && (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) { - c |= FP_INEXACT; + mips_exception_flags |= FP_INEXACT; if (action & CLEAR_FS_UNDERFLOW) { - c &= ~FP_UNDERFLOW; + mips_exception_flags &= ~FP_UNDERFLOW; } else { - c |= FP_UNDERFLOW; + mips_exception_flags |= FP_UNDERFLOW; } } /* Set Inexact (I) when Overflow (O) is not enabled */ - if ((c & FP_OVERFLOW) != 0 && (enable & FP_OVERFLOW) == 0) { - c |= FP_INEXACT; + if ((mips_exception_flags & FP_OVERFLOW) != 0 && + (enable & FP_OVERFLOW) == 0) { + mips_exception_flags |= FP_INEXACT; } /* Clear Exact Underflow when Underflow (U) is not enabled */ - if ((c & FP_UNDERFLOW) != 0 && (enable & FP_UNDERFLOW) == 0 && - (c & FP_INEXACT) == 0) { - c &= ~FP_UNDERFLOW; + if ((mips_exception_flags & FP_UNDERFLOW) != 0 && + (enable & FP_UNDERFLOW) == 0 && + (mips_exception_flags & FP_INEXACT) == 0) { + mips_exception_flags &= ~FP_UNDERFLOW; } /* @@ -5474,11 +5501,11 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) * divide by zero */ if ((action & RECIPROCAL_INEXACT) && - (c & (FP_INVALID | FP_DIV0)) == 0) { - c = FP_INEXACT; + (mips_exception_flags & (FP_INVALID | FP_DIV0)) == 0) { + mips_exception_flags = FP_INEXACT; } - cause = c & enable; /* all current enabled exceptions */ + cause = mips_exception_flags & enable; /* all current enabled exceptions */ if (cause == 0) { /* @@ -5486,7 +5513,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) * with all current exceptions */ SET_FP_CAUSE(env->active_tc.msacsr, - (GET_FP_CAUSE(env->active_tc.msacsr) | c)); + (GET_FP_CAUSE(env->active_tc.msacsr) | mips_exception_flags)); } else { /* Current exceptions are enabled */ if ((env->active_tc.msacsr & MSACSR_NX_MASK) == 0) { @@ -5495,11 +5522,11 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) * with all enabled exceptions */ SET_FP_CAUSE(env->active_tc.msacsr, - (GET_FP_CAUSE(env->active_tc.msacsr) | c)); + (GET_FP_CAUSE(env->active_tc.msacsr) | mips_exception_flags)); } } - return c; + return mips_exception_flags; } static inline int get_enabled_exceptions(const CPUMIPSState *env, int c)