diff options
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/helper.c | 2 | ||||
-rw-r--r-- | target-arm/helpers.h | 37 | ||||
-rw-r--r-- | target-arm/op.c | 99 | ||||
-rw-r--r-- | target-arm/op_helper.c | 66 | ||||
-rw-r--r-- | target-arm/op_neon.h | 1 | ||||
-rw-r--r-- | target-arm/translate.c | 34 |
6 files changed, 121 insertions, 118 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c index 236aaed23b..2c35ea4baf 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -322,7 +322,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); } -#define HELPER(x) helper_##x /* Sign/zero extend */ uint32_t HELPER(sxtb16)(uint32_t x) { @@ -1894,4 +1893,3 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, } #endif - diff --git a/target-arm/helpers.h b/target-arm/helpers.h index 8f2e129162..3b9eca07e3 100644 --- a/target-arm/helpers.h +++ b/target-arm/helpers.h @@ -1,7 +1,36 @@ -#ifndef DEF_HELPER #define DEF_HELPER(name, ret, args) ret helper_##name args; + +#ifdef GEN_HELPER +#define DEF_HELPER_1_1(name, ret, args) \ +DEF_HELPER(name, ret, args) \ +static inline void gen_helper_##name(TCGv ret, TCGv arg1) \ +{ \ + tcg_gen_helper_1_1(helper_##name, ret, arg1); \ +} +#define DEF_HELPER_1_2(name, ret, args) \ +DEF_HELPER(name, ret, args) \ +static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \ +{ \ + tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \ +} +#else /* !GEN_HELPER */ +#define DEF_HELPER_1_1 DEF_HELPER +#define DEF_HELPER_1_2 DEF_HELPER +#define HELPER(x) helper_##x #endif -DEF_HELPER(clz, uint32_t, (uint32_t)) -DEF_HELPER(sxtb16, uint32_t, (uint32_t)) -DEF_HELPER(uxtb16, uint32_t, (uint32_t)) +DEF_HELPER_1_1(clz, uint32_t, (uint32_t)) +DEF_HELPER_1_1(sxtb16, uint32_t, (uint32_t)) +DEF_HELPER_1_1(uxtb16, uint32_t, (uint32_t)) + +DEF_HELPER_1_2(add_setq, uint32_t, (uint32_t, uint32_t)) +DEF_HELPER_1_2(add_saturate, uint32_t, (uint32_t, uint32_t)) +DEF_HELPER_1_2(sub_saturate, uint32_t, (uint32_t, uint32_t)) +DEF_HELPER_1_2(add_usaturate, uint32_t, (uint32_t, uint32_t)) +DEF_HELPER_1_2(sub_usaturate, uint32_t, (uint32_t, uint32_t)) +DEF_HELPER_1_1(double_saturate, uint32_t, (int32_t)) + +#undef DEF_HELPER +#undef DEF_HELPER_1_1 +#undef DEF_HELPER_1_2 +#undef GEN_HELPER diff --git a/target-arm/op.c b/target-arm/op.c index b8b45e9fa3..d8906b4477 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -425,105 +425,6 @@ void OPPROTO op_rorl_T1_T0_cc(void) FORCE_RET(); } -/* misc */ -#define SIGNBIT (uint32_t)0x80000000 -/* saturating arithmetic */ -void OPPROTO op_addl_T0_T1_setq(void) -{ - uint32_t res; - - res = T0 + T1; - if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) - env->QF = 1; - - T0 = res; - FORCE_RET(); -} - -void OPPROTO op_addl_T0_T1_saturate(void) -{ - uint32_t res; - - res = T0 + T1; - if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) { - env->QF = 1; - if (T0 & SIGNBIT) - T0 = 0x80000000; - else - T0 = 0x7fffffff; - } - else - T0 = res; - - FORCE_RET(); -} - -void OPPROTO op_subl_T0_T1_saturate(void) -{ - uint32_t res; - - res = T0 - T1; - if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) { - env->QF = 1; - if (T0 & SIGNBIT) - T0 = 0x80000000; - else - T0 = 0x7fffffff; - } - else - T0 = res; - - FORCE_RET(); -} - -void OPPROTO op_double_T1_saturate(void) -{ - int32_t val; - - val = T1; - if (val >= 0x40000000) { - T1 = 0x7fffffff; - env->QF = 1; - } else if (val <= (int32_t)0xc0000000) { - T1 = 0x80000000; - env->QF = 1; - } else { - T1 = val << 1; - } - FORCE_RET(); -} - -/* Unsigned saturating arithmetic for NEON. */ -void OPPROTO op_addl_T0_T1_usaturate(void) -{ - uint32_t res; - - res = T0 + T1; - if (res < T0) { - env->QF = 1; - T0 = 0xffffffff; - } else { - T0 = res; - } - - FORCE_RET(); -} - -void OPPROTO op_subl_T0_T1_usaturate(void) -{ - uint32_t res; - - res = T0 - T1; - if (res > T0) { - env->QF = 1; - T0 = 0; - } else { - T0 = res; - } - - FORCE_RET(); -} - /* exceptions */ void OPPROTO op_swi(void) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 2b9ec0fa75..1b90f58296 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "exec.h" +#include "helpers.h" void raise_exception(int tt) { @@ -303,3 +304,68 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) env = saved_env; } #endif + +#define SIGNBIT (uint32_t)0x80000000 +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; +} + diff --git a/target-arm/op_neon.h b/target-arm/op_neon.h index 232375e18f..e91dcc5278 100644 --- a/target-arm/op_neon.h +++ b/target-arm/op_neon.h @@ -9,6 +9,7 @@ /* Note that for NEON an "l" prefix means it is a wide operation, unlike scalar arm ops where it means a word size operation. */ +#define SIGNBIT (uint32_t)0x80000000 /* ??? NEON ops should probably have their own float status. */ #define NFS &env->vfp.fp_status #define NEON_OP(name) void OPPROTO op_neon_##name (void) diff --git a/target-arm/translate.c b/target-arm/translate.c index bb6d513d87..dcb9e48090 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -29,6 +29,8 @@ #include "exec-all.h" #include "disas.h" #include "tcg-op.h" + +#define GEN_HELPER 1 #include "helpers.h" #define ENABLE_ARCH_5J 0 @@ -200,13 +202,19 @@ static void store_reg(DisasContext *s, int reg, TCGv var) #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) #define gen_sxth(var) tcg_gen_ext16s_i32(var, var) -#define HELPER_ADDR(x) helper_##x - -#define gen_sxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(sxtb16), var, var) -#define gen_uxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(uxtb16), var, var) +#define gen_sxtb16(var) gen_helper_sxtb16(var, var) +#define gen_uxtb16(var) gen_helper_uxtb16(var, var) -#define gen_op_clz_T0(var) \ - tcg_gen_helper_1_1(HELPER_ADDR(clz), cpu_T[0], cpu_T[0]) +#define gen_op_addl_T0_T1_setq() \ + gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1]) +#define gen_op_addl_T0_T1_saturate() \ + gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1]) +#define gen_op_subl_T0_T1_saturate() \ + gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1]) +#define gen_op_addl_T0_T1_usaturate() \ + gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]) +#define gen_op_subl_T0_T1_usaturate() \ + gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]) /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. tmp = (t0 ^ t1) & 0x8000; @@ -4526,7 +4534,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) switch (size) { case 0: gen_op_neon_clz_u8(); break; case 1: gen_op_neon_clz_u16(); break; - case 2: gen_op_clz_T0(); break; + case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break; default: return 1; } break; @@ -5021,9 +5029,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) } else if (op1 == 3) { /* clz */ rd = (insn >> 12) & 0xf; - gen_movl_T0_reg(s, rm); - gen_op_clz_T0(); - gen_movl_reg_T0(s, rd); + tmp = load_reg(s, rm); + gen_helper_clz(tmp, tmp); + store_reg(s, rd, tmp); } else { goto illegal_op; } @@ -5055,7 +5063,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_movl_T0_reg(s, rm); gen_movl_T1_reg(s, rn); if (op1 & 2) - gen_op_double_T1_saturate(); + gen_helper_double_saturate(cpu_T[1], cpu_T[1]); if (op1 & 1) gen_op_subl_T0_T1_saturate(); else @@ -6317,7 +6325,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) gen_movl_T0_reg(s, rm); gen_movl_T1_reg(s, rn); if (op & 2) - gen_op_double_T1_saturate(); + gen_helper_double_saturate(cpu_T[1], cpu_T[1]); if (op & 1) gen_op_subl_T0_T1_saturate(); else @@ -6342,7 +6350,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) gen_op_sel_T0_T1(); break; case 0x18: /* clz */ - gen_op_clz_T0(); + gen_helper_clz(cpu_T[0], cpu_T[0]); break; default: goto illegal_op; |