qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 2/5] target-tricore: Added MADD.F and MSUB.F


From: Richard Henderson
Subject: Re: [Qemu-devel] [PATCH v2 2/5] target-tricore: Added MADD.F and MSUB.F instructions
Date: Tue, 8 Nov 2016 12:42:38 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0

On 11/07/2016 03:44 PM, Bastian Koppelmann wrote:
Multiplies D[a] and D[b] and adds/subtracts the result to/from D[d].
The result is put in D[c]. All operands are floating-point numbers.

Signed-off-by: Bastian Koppelmann <address@hidden>
---
 target-tricore/fpu_helper.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-
 target-tricore/helper.h     |  2 +
 target-tricore/translate.c  |  8 ++++
 3 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c
index f717b53..d530a0b 100644
--- a/target-tricore/fpu_helper.c
+++ b/target-tricore/fpu_helper.c
@@ -21,7 +21,8 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"

-#define ADD_NAN   0x7cf00001
+#define QUIET_NAN 0x7fc00000
+#define ADD_NAN   0x7fc00001
 #define DIV_NAN   0x7fc00008
 #define MUL_NAN   0x7fc00002
 #define FPU_FS PSW_USB_C
@@ -47,6 +48,42 @@ static inline bool f_is_denormal(float32 arg)
     return float32_is_zero_or_denormal(arg) && !float32_is_zero(arg);
 }

+static inline float32 f_maddsub_nan_result(float32 arg1, float32 arg2,
+                                           float32 arg3, float32 result,
+                                           uint32_t flags)
+{
+    uint32_t aSign, bSign, cSign;
+    uint32_t aExp, bExp, cExp;
+
+    if (float32_is_any_nan(arg1) || float32_is_any_nan(arg2) ||
+        float32_is_any_nan(arg3)) {
+        return QUIET_NAN;
+    } else if (float32_is_infinity(arg1) && float32_is_zero(arg2)) {
+        return MUL_NAN;
+    } else if (float32_is_zero(arg1) && float32_is_infinity(arg2)) {
+        return MUL_NAN;
+    } else {
+        aSign = arg1 >> 31;
+        bSign = arg2 >> 31;
+        cSign = arg3 >> 31;
+
+        aExp = (arg1 >> 23) & 0xff;
+        bExp = (arg2 >> 23) & 0xff;
+        cExp = (arg3 >> 23) & 0xff;
+
+        if (flags & float_muladd_negate_c) {

flags here is muladd argument,

+    flags = f_get_excp_flags(env);
+    if (flags) {
+        if (flags & float_flag_invalid) {
+            arg1 = float32_squash_input_denormal(arg1, &env->fp_status);
+            arg2 = float32_squash_input_denormal(arg2, &env->fp_status);
+            arg3 = float32_squash_input_denormal(arg3, &env->fp_status);
+            f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, flags);

but passed here as exception bits.

+        }
+        f_update_psw_flags(env, flags);
+    } else {
+        env->FPU_FS = 0;
+    }
+    return (uint32_t)f_result;
+}
+
+uint32_t helper_fmsub(CPUTriCoreState *env, uint32_t r1,
+                      uint32_t r2, uint32_t r3)
+{
+    uint32_t flags;
+    float32 arg1 = make_float32(r1);
+    float32 arg2 = make_float32(r2);
+    float32 arg3 = make_float32(r3);
+    float32 f_result;
+
+    f_result = float32_muladd(arg1, arg2, arg3, float_muladd_negate_product,
+                              &env->fp_status);
+
+    flags = f_get_excp_flags(env);
+    if (flags) {
+        if (flags & float_flag_invalid) {
+            arg1 = float32_squash_input_denormal(arg1, &env->fp_status);
+            arg2 = float32_squash_input_denormal(arg2, &env->fp_status);
+            arg3 = float32_squash_input_denormal(arg3, &env->fp_status);
+
+            f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, flags);

Same. Also, nan_result needs to check float_muladd_negate_product as used here, not float_muladd_negate_c as used above.


r~





reply via email to

[Prev in Thread] Current Thread [Next in Thread]