diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2013-01-22 17:16:00 +0000 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2013-01-31 23:42:02 +0100 |
commit | f54c35d1ea287beb26f6e929e2362cbc9dcfec07 (patch) | |
tree | a78392d0555040bc36ad92785899a446fb494b7c /target-mips/op_helper.c | |
parent | c728154bbbc1a86465a0fd6bfc839bc9710ac374 (diff) |
target-mips: Unfuse {,N}M{ADD,SUB}.fmt
Turn MADD.fmt, MSUB.fmt, NMADD.fmt and NMSUB.fmt from fused to unfused
operations, so that they behave in the same way as a separate multiplication
and addition. The instructions were only fused in early MIPS IV processors.
Signed-off-by: Richard Sandiford <rdsandiford@googlemail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-mips/op_helper.c')
-rw-r--r-- | target-mips/op_helper.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 1bca4a159e..526f84f136 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2878,14 +2878,26 @@ FLOAT_BINOP(mul) FLOAT_BINOP(div) #undef FLOAT_BINOP +#define UNFUSED_FMA(prefix, a, b, c, flags) \ +{ \ + a = prefix##_mul(a, b, &env->active_fpu.fp_status); \ + if ((flags) & float_muladd_negate_c) { \ + a = prefix##_sub(a, c, &env->active_fpu.fp_status); \ + } else { \ + a = prefix##_add(a, c, &env->active_fpu.fp_status); \ + } \ + if ((flags) & float_muladd_negate_result) { \ + a = prefix##_chs(a); \ + } \ +} + /* FMA based operations */ #define FLOAT_FMA(name, type) \ uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ uint64_t fdt0, uint64_t fdt1, \ uint64_t fdt2) \ { \ - fdt0 = float64_muladd(fdt0, fdt1, fdt2, type, \ - &env->active_fpu.fp_status); \ + UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type); \ update_fcr31(env, GETPC()); \ return fdt0; \ } \ @@ -2894,8 +2906,7 @@ uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ uint32_t fst0, uint32_t fst1, \ uint32_t fst2) \ { \ - fst0 = float32_muladd(fst0, fst1, fst2, type, \ - &env->active_fpu.fp_status); \ + UNFUSED_FMA(float32, fst0, fst1, fst2, type); \ update_fcr31(env, GETPC()); \ return fst0; \ } \ @@ -2911,10 +2922,8 @@ uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ uint32_t fsth2 = fdt2 >> 32; \ \ - fst0 = float32_muladd(fst0, fst1, fst2, type, \ - &env->active_fpu.fp_status); \ - fsth0 = float32_muladd(fsth0, fsth1, fsth2, type, \ - &env->active_fpu.fp_status); \ + UNFUSED_FMA(float32, fst0, fst1, fst2, type); \ + UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \ update_fcr31(env, GETPC()); \ return ((uint64_t)fsth0 << 32) | fst0; \ } |