Patchwork target-mips: Unfuse {,N}M{ADD,SUB}.fmt

login
register
mail settings
Submitter Richard Sandiford
Date Jan. 22, 2013, 5:16 p.m.
Message ID <87r4ldjfzj.fsf@talisman.default>
Download mbox | patch
Permalink /patch/214607/
State New
Headers show

Comments

Richard Sandiford - Jan. 22, 2013, 5:16 p.m.
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>
---
 target-mips/op_helper.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)
Aurelien Jarno - Jan. 31, 2013, 11 p.m.
On Tue, Jan 22, 2013 at 05:16:00PM +0000, Richard Sandiford wrote:
> 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>
> ---
>  target-mips/op_helper.c | 25 +++++++++++++++++--------
>  1 file changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
> index 1bca4a1..526f84f 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;                           \
>  }
> -- 
> 1.7.11.7
> 
> 

Thanks, applied.

Patch

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 1bca4a1..526f84f 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;                           \
 }