diff options
Diffstat (limited to 'target/sh4/op_helper.c')
-rw-r--r-- | target/sh4/op_helper.c | 93 |
1 files changed, 44 insertions, 49 deletions
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c index 528a40ac1d..d798f239cf 100644 --- a/target/sh4/op_helper.c +++ b/target/sh4/op_helper.c @@ -115,6 +115,12 @@ void helper_trapa(CPUSH4State *env, uint32_t tra) raise_exception(env, 0x160, 0); } +void helper_exclusive(CPUSH4State *env) +{ + /* We do not want cpu_restore_state to run. */ + cpu_loop_exit_atomic(ENV_GET_CPU(env), 0); +} + void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value) { if (cpu_sh4_is_cached (env, address)) @@ -219,29 +225,29 @@ static void update_fpscr(CPUSH4State *env, uintptr_t retaddr) xcpt = get_float_exception_flags(&env->fp_status); - /* Clear the flag entries */ - env->fpscr &= ~FPSCR_FLAG_MASK; + /* Clear the cause entries */ + env->fpscr &= ~FPSCR_CAUSE_MASK; if (unlikely(xcpt)) { if (xcpt & float_flag_invalid) { - env->fpscr |= FPSCR_FLAG_V; + env->fpscr |= FPSCR_CAUSE_V; } if (xcpt & float_flag_divbyzero) { - env->fpscr |= FPSCR_FLAG_Z; + env->fpscr |= FPSCR_CAUSE_Z; } if (xcpt & float_flag_overflow) { - env->fpscr |= FPSCR_FLAG_O; + env->fpscr |= FPSCR_CAUSE_O; } if (xcpt & float_flag_underflow) { - env->fpscr |= FPSCR_FLAG_U; + env->fpscr |= FPSCR_CAUSE_U; } if (xcpt & float_flag_inexact) { - env->fpscr |= FPSCR_FLAG_I; + env->fpscr |= FPSCR_CAUSE_I; } - /* Accumulate in cause entries */ - env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK) - << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT); + /* Accumulate in flag entries */ + env->fpscr |= (env->fpscr & FPSCR_CAUSE_MASK) + >> (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT); /* Generate an exception if enabled */ cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT; @@ -252,16 +258,6 @@ static void update_fpscr(CPUSH4State *env, uintptr_t retaddr) } } -float32 helper_fabs_FT(float32 t0) -{ - return float32_abs(t0); -} - -float64 helper_fabs_DT(float64 t0) -{ - return float64_abs(t0); -} - float32 helper_fadd_FT(CPUSH4State *env, float32 t0, float32 t1) { set_float_exception_flags(0, &env->fp_status); @@ -278,56 +274,44 @@ float64 helper_fadd_DT(CPUSH4State *env, float64 t0, float64 t1) return t0; } -void helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1) +uint32_t helper_fcmp_eq_FT(CPUSH4State *env, float32 t0, float32 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float32_compare(t0, t1, &env->fp_status); - if (unlikely(relation == float_relation_unordered)) { - update_fpscr(env, GETPC()); - } else { - env->sr_t = (relation == float_relation_equal); - } + update_fpscr(env, GETPC()); + return relation == float_relation_equal; } -void helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1) +uint32_t helper_fcmp_eq_DT(CPUSH4State *env, float64 t0, float64 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float64_compare(t0, t1, &env->fp_status); - if (unlikely(relation == float_relation_unordered)) { - update_fpscr(env, GETPC()); - } else { - env->sr_t = (relation == float_relation_equal); - } + update_fpscr(env, GETPC()); + return relation == float_relation_equal; } -void helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1) +uint32_t helper_fcmp_gt_FT(CPUSH4State *env, float32 t0, float32 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float32_compare(t0, t1, &env->fp_status); - if (unlikely(relation == float_relation_unordered)) { - update_fpscr(env, GETPC()); - } else { - env->sr_t = (relation == float_relation_greater); - } + update_fpscr(env, GETPC()); + return relation == float_relation_greater; } -void helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1) +uint32_t helper_fcmp_gt_DT(CPUSH4State *env, float64 t0, float64 t1) { int relation; set_float_exception_flags(0, &env->fp_status); relation = float64_compare(t0, t1, &env->fp_status); - if (unlikely(relation == float_relation_unordered)) { - update_fpscr(env, GETPC()); - } else { - env->sr_t = (relation == float_relation_greater); - } + update_fpscr(env, GETPC()); + return relation == float_relation_greater; } float64 helper_fcnvsd_FT_DT(CPUSH4State *env, float32 t0) @@ -406,11 +390,6 @@ float64 helper_fmul_DT(CPUSH4State *env, float64 t0, float64 t1) return t0; } -float32 helper_fneg_T(float32 t0) -{ - return float32_chs(t0); -} - float32 helper_fsqrt_FT(CPUSH4State *env, float32 t0) { set_float_exception_flags(0, &env->fp_status); @@ -427,6 +406,22 @@ float64 helper_fsqrt_DT(CPUSH4State *env, float64 t0) return t0; } +float32 helper_fsrra_FT(CPUSH4State *env, float32 t0) +{ + set_float_exception_flags(0, &env->fp_status); + /* "Approximate" 1/sqrt(x) via actual computation. */ + t0 = float32_sqrt(t0, &env->fp_status); + t0 = float32_div(float32_one, t0, &env->fp_status); + /* Since this is supposed to be an approximation, an imprecision + exception is required. One supposes this also follows the usual + IEEE rule that other exceptions take precidence. */ + if (get_float_exception_flags(&env->fp_status) == 0) { + set_float_exception_flags(float_flag_inexact, &env->fp_status); + } + update_fpscr(env, GETPC()); + return t0; +} + float32 helper_fsub_FT(CPUSH4State *env, float32 t0, float32 t1) { set_float_exception_flags(0, &env->fp_status); |