summaryrefslogtreecommitdiff
path: root/target/sh4/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/sh4/op_helper.c')
-rw-r--r--target/sh4/op_helper.c93
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);