From fb856928570ff3a962a9e9d10e51ba476ff1b306 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Blue Swirl Date: Mon, 19 Mar 2012 20:43:56 +0000 Subject: [PATCH 2/6] arm: move saturating arithmetic to helper.c Add an explicit CPUARMState parameter instead of relying on AREG0 and move saturating arithmetic to helper.c. Signed-off-by: Blue Swirl --- 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.2.5