qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/6] arm: move saturating arithmetic to helper.c


From: Blue Swirl
Subject: [Qemu-devel] [PATCH 2/6] arm: move saturating arithmetic to helper.c
Date: Mon, 19 Mar 2012 21:56:36 +0000

Add an explicit CPUARMState parameter instead of relying on AREG0
and move saturating arithmetic to helper.c.

Signed-off-by: Blue Swirl <address@hidden>
---
 target-arm/helper.c    |  133 +++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/helper.h    |   20 ++++----
 target-arm/op_helper.c |  134 ------------------------------------------------
 target-arm/translate.c |   44 ++++++++--------
 4 files changed, 165 insertions(+), 166 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1314f23..f01bcb9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -7,6 +7,9 @@
 #endif
 #include "sysemu.h"

+#define SIGNBIT (uint32_t)0x80000000
+#define SIGNBIT64 ((uint64_t)1 << 63)
+
 static uint32_t cortexa15_cp15_c0_c1[8] = {
     0x00001131, 0x00011011, 0x02010555, 0x00000000,
     0x10201105, 0x20000000, 0x01240000, 0x02102211
@@ -2466,6 +2469,136 @@ static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
     return res;
 }

+uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a + b;
+    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
+        env->QF = 1;
+    }
+    return res;
+}
+
+uint32_t HELPER(add_saturate)(CPUARMState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a + b;
+    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
+        env->QF = 1;
+        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+    }
+    return res;
+}
+
+uint32_t HELPER(sub_saturate)(CPUARMState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a - b;
+    if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
+        env->QF = 1;
+        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+    }
+    return res;
+}
+
+uint32_t HELPER(double_saturate)(CPUARMState *env, int32_t val)
+{
+    uint32_t res;
+    if (val >= 0x40000000) {
+        res = ~SIGNBIT;
+        env->QF = 1;
+    } else if (val <= (int32_t)0xc0000000) {
+        res = SIGNBIT;
+        env->QF = 1;
+    } else {
+        res = val << 1;
+    }
+    return res;
+}
+
+uint32_t HELPER(add_usaturate)(CPUARMState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a + b;
+    if (res < a) {
+        env->QF = 1;
+        res = ~0;
+    }
+    return res;
+}
+
+uint32_t HELPER(sub_usaturate)(CPUARMState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a - b;
+    if (res > a) {
+        env->QF = 1;
+        res = 0;
+    }
+    return res;
+}
+
+/* Signed saturation.  */
+static inline uint32_t do_ssat(CPUARMState *env, int32_t val, int shift)
+{
+    int32_t top;
+    uint32_t mask;
+
+    top = val >> shift;
+    mask = (1u << shift) - 1;
+    if (top > 0) {
+        env->QF = 1;
+        return mask;
+    } else if (top < -1) {
+        env->QF = 1;
+        return ~mask;
+    }
+    return val;
+}
+
+/* Unsigned saturation.  */
+static inline uint32_t do_usat(CPUARMState *env, int32_t val, int shift)
+{
+    uint32_t max;
+
+    max = (1u << shift) - 1;
+    if (val < 0) {
+        env->QF = 1;
+        return 0;
+    } else if (val > max) {
+        env->QF = 1;
+        return max;
+    }
+    return val;
+}
+
+/* Signed saturate.  */
+uint32_t HELPER(ssat)(CPUARMState *env, uint32_t x, uint32_t shift)
+{
+    return do_ssat(env, x, shift);
+}
+
+/* Dual halfword signed saturate.  */
+uint32_t HELPER(ssat16)(CPUARMState *env, uint32_t x, uint32_t shift)
+{
+    uint32_t res;
+
+    res = (uint16_t)do_ssat(env, (int16_t)x, shift);
+    res |= do_ssat(env, ((int32_t)x) >> 16, shift) << 16;
+    return res;
+}
+
+/* Unsigned saturate.  */
+uint32_t HELPER(usat)(CPUARMState *env, uint32_t x, uint32_t shift)
+{
+    return do_usat(env, x, shift);
+}
+
+/* Dual halfword unsigned saturate.  */
+uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
+{
+    uint32_t res;
+
+    res = (uint16_t)do_usat(env, (int16_t)x, shift);
+    res |= do_usat(env, ((int32_t)x) >> 16, shift) << 16;
+    return res;
+}
+
 #define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
 #define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
 #define ADD8(a, b, n)  RESULT(add8_sat(a, b), n, 8);
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 40529eb..e71e8c2 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -4,12 +4,12 @@ DEF_HELPER_1(clz, i32, i32)
 DEF_HELPER_1(sxtb16, i32, i32)
 DEF_HELPER_1(uxtb16, i32, i32)

-DEF_HELPER_2(add_setq, i32, i32, i32)
-DEF_HELPER_2(add_saturate, i32, i32, i32)
-DEF_HELPER_2(sub_saturate, i32, i32, i32)
-DEF_HELPER_2(add_usaturate, i32, i32, i32)
-DEF_HELPER_2(sub_usaturate, i32, i32, i32)
-DEF_HELPER_1(double_saturate, i32, s32)
+DEF_HELPER_3(add_setq, i32, env, i32, i32)
+DEF_HELPER_3(add_saturate, i32, env, i32, i32)
+DEF_HELPER_3(sub_saturate, i32, env, i32, i32)
+DEF_HELPER_3(add_usaturate, i32, env, i32, i32)
+DEF_HELPER_3(sub_usaturate, i32, env, i32, i32)
+DEF_HELPER_2(double_saturate, i32, env, s32)
 DEF_HELPER_2(sdiv, s32, s32, s32)
 DEF_HELPER_2(udiv, i32, i32, i32)
 DEF_HELPER_1(rbit, i32, i32)
@@ -40,10 +40,10 @@ PAS_OP(uq)
 PAS_OP(uh)
 #undef PAS_OP

-DEF_HELPER_2(ssat, i32, i32, i32)
-DEF_HELPER_2(usat, i32, i32, i32)
-DEF_HELPER_2(ssat16, i32, i32, i32)
-DEF_HELPER_2(usat16, i32, i32, i32)
+DEF_HELPER_3(ssat, i32, env, i32, i32)
+DEF_HELPER_3(usat, i32, env, i32, i32)
+DEF_HELPER_3(ssat16, i32, env, i32, i32)
+DEF_HELPER_3(usat16, i32, env, i32, i32)

 DEF_HELPER_2(usad8, i32, i32, i32)

diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index f4c0123..9924d82 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -20,9 +20,6 @@
 #include "dyngen-exec.h"
 #include "helper.h"

-#define SIGNBIT (uint32_t)0x80000000
-#define SIGNBIT64 ((uint64_t)1 << 63)
-
 #if !defined(CONFIG_USER_ONLY)
 static void raise_exception(int tt)
 {
@@ -81,137 +78,6 @@ void tlb_fill(CPUARMState *env1, target_ulong
addr, int is_write, int mmu_idx,
 }
 #endif

-/* FIXME: Pass an axplicit pointer to QF to CPUARMState, and move saturating
-   instructions into helper.c  */
-uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
-{
-    uint32_t res = a + b;
-    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
-        env->QF = 1;
-    return res;
-}
-
-uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
-{
-    uint32_t res = a + b;
-    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
-        env->QF = 1;
-        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
-    }
-    return res;
-}
-
-uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
-{
-    uint32_t res = a - b;
-    if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
-        env->QF = 1;
-        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
-    }
-    return res;
-}
-
-uint32_t HELPER(double_saturate)(int32_t val)
-{
-    uint32_t res;
-    if (val >= 0x40000000) {
-        res = ~SIGNBIT;
-        env->QF = 1;
-    } else if (val <= (int32_t)0xc0000000) {
-        res = SIGNBIT;
-        env->QF = 1;
-    } else {
-        res = val << 1;
-    }
-    return res;
-}
-
-uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
-{
-    uint32_t res = a + b;
-    if (res < a) {
-        env->QF = 1;
-        res = ~0;
-    }
-    return res;
-}
-
-uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
-{
-    uint32_t res = a - b;
-    if (res > a) {
-        env->QF = 1;
-        res = 0;
-    }
-    return res;
-}
-
-/* Signed saturation.  */
-static inline uint32_t do_ssat(int32_t val, int shift)
-{
-    int32_t top;
-    uint32_t mask;
-
-    top = val >> shift;
-    mask = (1u << shift) - 1;
-    if (top > 0) {
-        env->QF = 1;
-        return mask;
-    } else if (top < -1) {
-        env->QF = 1;
-        return ~mask;
-    }
-    return val;
-}
-
-/* Unsigned saturation.  */
-static inline uint32_t do_usat(int32_t val, int shift)
-{
-    uint32_t max;
-
-    max = (1u << shift) - 1;
-    if (val < 0) {
-        env->QF = 1;
-        return 0;
-    } else if (val > max) {
-        env->QF = 1;
-        return max;
-    }
-    return val;
-}
-
-/* Signed saturate.  */
-uint32_t HELPER(ssat)(uint32_t x, uint32_t shift)
-{
-    return do_ssat(x, shift);
-}
-
-/* Dual halfword signed saturate.  */
-uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift)
-{
-    uint32_t res;
-
-    res = (uint16_t)do_ssat((int16_t)x, shift);
-    res |= do_ssat(((int32_t)x) >> 16, shift) << 16;
-    return res;
-}
-
-/* Unsigned saturate.  */
-uint32_t HELPER(usat)(uint32_t x, uint32_t shift)
-{
-    return do_usat(x, shift);
-}
-
-/* Dual halfword unsigned saturate.  */
-uint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
-{
-    uint32_t res;
-
-    res = (uint16_t)do_usat((int16_t)x, shift);
-    res |= do_usat(((int32_t)x) >> 16, shift) << 16;
-    return res;
-}
-
 void HELPER(wfi)(void)
 {
     env->exception_index = EXCP_HLT;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 99de85a..a2b01d9 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7040,11 +7040,11 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
             tmp = load_reg(s, rm);
             tmp2 = load_reg(s, rn);
             if (op1 & 2)
-                gen_helper_double_saturate(tmp2, tmp2);
+                gen_helper_double_saturate(tmp2, cpu_env, tmp2);
             if (op1 & 1)
-                gen_helper_sub_saturate(tmp, tmp, tmp2);
+                gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
             else
-                gen_helper_add_saturate(tmp, tmp, tmp2);
+                gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
             tcg_temp_free_i32(tmp2);
             store_reg(s, rd, tmp);
             break;
@@ -7082,7 +7082,7 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
                 tcg_temp_free_i64(tmp64);
                 if ((sh & 2) == 0) {
                     tmp2 = load_reg(s, rn);
-                    gen_helper_add_setq(tmp, tmp, tmp2);
+                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                     tcg_temp_free_i32(tmp2);
                 }
                 store_reg(s, rd, tmp);
@@ -7102,7 +7102,7 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
                 } else {
                     if (op1 == 0) {
                         tmp2 = load_reg(s, rn);
-                        gen_helper_add_setq(tmp, tmp, tmp2);
+                        gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                         tcg_temp_free_i32(tmp2);
                     }
                     store_reg(s, rd, tmp);
@@ -7566,9 +7566,9 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
                         sh = (insn >> 16) & 0x1f;
                         tmp2 = tcg_const_i32(sh);
                         if (insn & (1 << 22))
-                          gen_helper_usat(tmp, tmp, tmp2);
+                            gen_helper_usat(tmp, cpu_env, tmp, tmp2);
                         else
-                          gen_helper_ssat(tmp, tmp, tmp2);
+                            gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
                         tcg_temp_free_i32(tmp2);
                         store_reg(s, rd, tmp);
                     } else if ((insn & 0x00300fe0) == 0x00200f20) {
@@ -7577,9 +7577,9 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
                         sh = (insn >> 16) & 0x1f;
                         tmp2 = tcg_const_i32(sh);
                         if (insn & (1 << 22))
-                          gen_helper_usat16(tmp, tmp, tmp2);
+                            gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
                         else
-                          gen_helper_ssat16(tmp, tmp, tmp2);
+                            gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
                         tcg_temp_free_i32(tmp2);
                         store_reg(s, rd, tmp);
                     } else if ((insn & 0x00700fe0) == 0x00000fa0) {
@@ -7689,7 +7689,7 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
                              * however it may overflow considered as a signed
                              * operation, in which case we must set the Q flag.
                              */
-                            gen_helper_add_setq(tmp, tmp, tmp2);
+                            gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                         }
                         tcg_temp_free_i32(tmp2);
                         if (insn & (1 << 22)) {
@@ -7705,7 +7705,7 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
                             if (rd != 15)
                               {
                                 tmp2 = load_reg(s, rd);
-                                gen_helper_add_setq(tmp, tmp, tmp2);
+                                gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                                 tcg_temp_free_i32(tmp2);
                               }
                             store_reg(s, rn, tmp);
@@ -8464,11 +8464,11 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
                 tmp = load_reg(s, rn);
                 tmp2 = load_reg(s, rm);
                 if (op & 1)
-                    gen_helper_double_saturate(tmp, tmp);
+                    gen_helper_double_saturate(tmp, cpu_env, tmp);
                 if (op & 2)
-                    gen_helper_sub_saturate(tmp, tmp2, tmp);
+                    gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
                 else
-                    gen_helper_add_saturate(tmp, tmp, tmp2);
+                    gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
                 tcg_temp_free_i32(tmp2);
             } else {
                 tmp = load_reg(s, rn);
@@ -8524,7 +8524,7 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
                 tcg_temp_free_i32(tmp2);
                 if (rs != 15) {
                     tmp2 = load_reg(s, rs);
-                    gen_helper_add_setq(tmp, tmp, tmp2);
+                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                     tcg_temp_free_i32(tmp2);
                 }
                 break;
@@ -8541,13 +8541,13 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
                      * however it may overflow considered as a signed
                      * operation, in which case we must set the Q flag.
                      */
-                    gen_helper_add_setq(tmp, tmp, tmp2);
+                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                 }
                 tcg_temp_free_i32(tmp2);
                 if (rs != 15)
                   {
                     tmp2 = load_reg(s, rs);
-                    gen_helper_add_setq(tmp, tmp, tmp2);
+                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                     tcg_temp_free_i32(tmp2);
                   }
                 break;
@@ -8564,7 +8564,7 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
                 if (rs != 15)
                   {
                     tmp2 = load_reg(s, rs);
-                    gen_helper_add_setq(tmp, tmp, tmp2);
+                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
                     tcg_temp_free_i32(tmp2);
                   }
                 break;
@@ -8892,15 +8892,15 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
                         if (op & 4) {
                             /* Unsigned.  */
                             if ((op & 1) && shift == 0)
-                                gen_helper_usat16(tmp, tmp, tmp2);
+                                gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
                             else
-                                gen_helper_usat(tmp, tmp, tmp2);
+                                gen_helper_usat(tmp, cpu_env, tmp, tmp2);
                         } else {
                             /* Signed.  */
                             if ((op & 1) && shift == 0)
-                                gen_helper_ssat16(tmp, tmp, tmp2);
+                                gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
                             else
-                                gen_helper_ssat(tmp, tmp, tmp2);
+                                gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
                         }
                         tcg_temp_free_i32(tmp2);
                         break;
-- 
1.7.9

Attachment: 0002-arm-move-saturating-arithmetic-to-helper.c.patch
Description: Text document


reply via email to

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