From d438250184f6b088f02dfd87f178c50e602243b4 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Blue Swirl Date: Mon, 19 Mar 2012 20:59:04 +0000 Subject: [PATCH 3/6] arm: move other arithmetic to helper.c Add an explicit CPUARMState parameter instead of relying on AREG0 and move rest of the arithmetic to helper.c. Signed-off-by: Blue Swirl --- target-arm/helper.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ target-arm/helper.h | 24 ++++---- target-arm/op_helper.c | 140 ---------------------------------------------- target-arm/translate.c | 78 +++++++++++++------------- 4 files changed, 197 insertions(+), 191 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index f01bcb9..3b3d122 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -629,6 +629,152 @@ uint32_t HELPER(abs)(uint32_t x) return ((int32_t)x < 0) ? -x : x; } +/* ??? Flag setting arithmetic is awkward because we need to do comparisons. + The only way to do that in TCG is a conditional branch, which clobbers + all our temporaries. For now implement these as helper functions. */ + +uint32_t HELPER(add_cc)(CPUARMState *env, uint32_t a, uint32_t b) +{ + uint32_t result; + result = a + b; + env->NF = env->ZF = result; + env->CF = result < a; + env->VF = (a ^ b ^ -1) & (a ^ result); + return result; +} + +uint32_t HELPER(adc_cc)(CPUARMState *env, uint32_t a, uint32_t b) +{ + uint32_t result; + if (!env->CF) { + result = a + b; + env->CF = result < a; + } else { + result = a + b + 1; + env->CF = result <= a; + } + env->VF = (a ^ b ^ -1) & (a ^ result); + env->NF = env->ZF = result; + return result; +} + +uint32_t HELPER(sub_cc)(CPUARMState *env, uint32_t a, uint32_t b) +{ + uint32_t result; + result = a - b; + env->NF = env->ZF = result; + env->CF = a >= b; + env->VF = (a ^ b) & (a ^ result); + return result; +} + +uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b) +{ + uint32_t result; + if (!env->CF) { + result = a - b - 1; + env->CF = a > b; + } else { + result = a - b; + env->CF = a >= b; + } + env->VF = (a ^ b) & (a ^ result); + env->NF = env->ZF = result; + return result; +} + +/* Similarly for variable shift instructions. */ + +uint32_t HELPER(shl)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift = i & 0xff; + if (shift >= 32) { + return 0; + } + return x << shift; +} + +uint32_t HELPER(shr)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift = i & 0xff; + if (shift >= 32) { + return 0; + } + return (uint32_t)x >> shift; +} + +uint32_t HELPER(sar)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift = i & 0xff; + if (shift >= 32) { + shift = 31; + } + return (int32_t)x >> shift; +} + +uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift = i & 0xff; + if (shift >= 32) { + if (shift == 32) { + env->CF = x & 1; + } else { + env->CF = 0; + } + return 0; + } else if (shift != 0) { + env->CF = (x >> (32 - shift)) & 1; + return x << shift; + } + return x; +} + +uint32_t HELPER(shr_cc)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift = i & 0xff; + if (shift >= 32) { + if (shift == 32) { + env->CF = (x >> 31) & 1; + } else { + env->CF = 0; + } + return 0; + } else if (shift != 0) { + env->CF = (x >> (shift - 1)) & 1; + return x >> shift; + } + return x; +} + +uint32_t HELPER(sar_cc)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift = i & 0xff; + if (shift >= 32) { + env->CF = (x >> 31) & 1; + return (int32_t)x >> 31; + } else if (shift != 0) { + env->CF = (x >> (shift - 1)) & 1; + return (int32_t)x >> shift; + } + return x; +} + +uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i) +{ + int shift1, shift; + shift1 = i & 0xff; + shift = shift1 & 0x1f; + if (shift == 0) { + if (shift1 != 0) { + env->CF = (x >> 31) & 1; + } + return x; + } else { + env->CF = (x >> (shift - 1)) & 1; + return ((uint32_t)x >> shift) | (x << (32 - shift)); + } +} + #if defined(CONFIG_USER_ONLY) void do_interrupt (CPUARMState *env) diff --git a/target-arm/helper.h b/target-arm/helper.h index e71e8c2..e2ade6f 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -143,18 +143,18 @@ DEF_HELPER_2(recpe_u32, i32, i32, env) DEF_HELPER_2(rsqrte_u32, i32, i32, env) DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32) -DEF_HELPER_2(add_cc, i32, i32, i32) -DEF_HELPER_2(adc_cc, i32, i32, i32) -DEF_HELPER_2(sub_cc, i32, i32, i32) -DEF_HELPER_2(sbc_cc, i32, i32, i32) - -DEF_HELPER_2(shl, i32, i32, i32) -DEF_HELPER_2(shr, i32, i32, i32) -DEF_HELPER_2(sar, i32, i32, i32) -DEF_HELPER_2(shl_cc, i32, i32, i32) -DEF_HELPER_2(shr_cc, i32, i32, i32) -DEF_HELPER_2(sar_cc, i32, i32, i32) -DEF_HELPER_2(ror_cc, i32, i32, i32) +DEF_HELPER_3(add_cc, i32, env, i32, i32) +DEF_HELPER_3(adc_cc, i32, env, i32, i32) +DEF_HELPER_3(sub_cc, i32, env, i32, i32) +DEF_HELPER_3(sbc_cc, i32, env, i32, i32) + +DEF_HELPER_3(shl, i32, env, i32, i32) +DEF_HELPER_3(shr, i32, env, i32, i32) +DEF_HELPER_3(sar, i32, env, i32, i32) +DEF_HELPER_3(shl_cc, i32, env, i32, i32) +DEF_HELPER_3(shr_cc, i32, env, i32, i32) +DEF_HELPER_3(sar_cc, i32, env, i32, i32) +DEF_HELPER_3(ror_cc, i32, env, i32, i32) /* neon_helper.c */ DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 9924d82..fc1e7ef 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -132,143 +132,3 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val) env->regs[regno] = val; } } - -/* ??? Flag setting arithmetic is awkward because we need to do comparisons. - The only way to do that in TCG is a conditional branch, which clobbers - all our temporaries. For now implement these as helper functions. */ - -uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) -{ - uint32_t result; - result = a + b; - env->NF = env->ZF = result; - env->CF = result < a; - env->VF = (a ^ b ^ -1) & (a ^ result); - return result; -} - -uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) -{ - uint32_t result; - if (!env->CF) { - result = a + b; - env->CF = result < a; - } else { - result = a + b + 1; - env->CF = result <= a; - } - env->VF = (a ^ b ^ -1) & (a ^ result); - env->NF = env->ZF = result; - return result; -} - -uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) -{ - uint32_t result; - result = a - b; - env->NF = env->ZF = result; - env->CF = a >= b; - env->VF = (a ^ b) & (a ^ result); - return result; -} - -uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) -{ - uint32_t result; - if (!env->CF) { - result = a - b - 1; - env->CF = a > b; - } else { - result = a - b; - env->CF = a >= b; - } - env->VF = (a ^ b) & (a ^ result); - env->NF = env->ZF = result; - return result; -} - -/* Similarly for variable shift instructions. */ - -uint32_t HELPER(shl)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - return 0; - return x << shift; -} - -uint32_t HELPER(shr)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - return 0; - return (uint32_t)x >> shift; -} - -uint32_t HELPER(sar)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - shift = 31; - return (int32_t)x >> shift; -} - -uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - if (shift == 32) - env->CF = x & 1; - else - env->CF = 0; - return 0; - } else if (shift != 0) { - env->CF = (x >> (32 - shift)) & 1; - return x << shift; - } - return x; -} - -uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - if (shift == 32) - env->CF = (x >> 31) & 1; - else - env->CF = 0; - return 0; - } else if (shift != 0) { - env->CF = (x >> (shift - 1)) & 1; - return x >> shift; - } - return x; -} - -uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) { - env->CF = (x >> 31) & 1; - return (int32_t)x >> 31; - } else if (shift != 0) { - env->CF = (x >> (shift - 1)) & 1; - return (int32_t)x >> shift; - } - return x; -} - -uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) -{ - int shift1, shift; - shift1 = i & 0xff; - shift = shift1 & 0x1f; - if (shift == 0) { - if (shift1 != 0) - env->CF = (x >> 31) & 1; - return x; - } else { - env->CF = (x >> (shift - 1)) & 1; - return ((uint32_t)x >> shift) | (x << (32 - shift)); - } -} diff --git a/target-arm/translate.c b/target-arm/translate.c index a2b01d9..0a41dc8 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -489,16 +489,16 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop, { if (flags) { switch (shiftop) { - case 0: gen_helper_shl_cc(var, var, shift); break; - case 1: gen_helper_shr_cc(var, var, shift); break; - case 2: gen_helper_sar_cc(var, var, shift); break; - case 3: gen_helper_ror_cc(var, var, shift); break; + case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break; + case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break; + case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break; + case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break; } } else { switch (shiftop) { - case 0: gen_helper_shl(var, var, shift); break; - case 1: gen_helper_shr(var, var, shift); break; - case 2: gen_helper_sar(var, var, shift); break; + case 0: gen_helper_shl(var, cpu_env, var, shift); break; + case 1: gen_helper_shr(var, cpu_env, var, shift); break; + case 2: gen_helper_sar(var, cpu_env, var, shift); break; case 3: tcg_gen_andi_i32(shift, shift, 0x1f); tcg_gen_rotr_i32(var, var, shift); break; } @@ -7176,11 +7176,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) if (IS_USER(s)) { goto illegal_op; } - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); gen_exception_return(s, tmp); } else { if (set_cc) { - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } else { tcg_gen_sub_i32(tmp, tmp, tmp2); } @@ -7189,7 +7189,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x03: if (set_cc) { - gen_helper_sub_cc(tmp, tmp2, tmp); + gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp); } else { tcg_gen_sub_i32(tmp, tmp2, tmp); } @@ -7197,7 +7197,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x04: if (set_cc) { - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); } @@ -7205,7 +7205,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x05: if (set_cc) { - gen_helper_adc_cc(tmp, tmp, tmp2); + gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); } else { gen_add_carry(tmp, tmp, tmp2); } @@ -7213,7 +7213,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x06: if (set_cc) { - gen_helper_sbc_cc(tmp, tmp, tmp2); + gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); } else { gen_sub_carry(tmp, tmp, tmp2); } @@ -7221,7 +7221,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x07: if (set_cc) { - gen_helper_sbc_cc(tmp, tmp2, tmp); + gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp); } else { gen_sub_carry(tmp, tmp2, tmp); } @@ -7243,13 +7243,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) break; case 0x0a: if (set_cc) { - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp); break; case 0x0b: if (set_cc) { - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp); break; @@ -8036,31 +8036,31 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCG break; case 8: /* add */ if (conds) - gen_helper_add_cc(t0, t0, t1); + gen_helper_add_cc(t0, cpu_env, t0, t1); else tcg_gen_add_i32(t0, t0, t1); break; case 10: /* adc */ if (conds) - gen_helper_adc_cc(t0, t0, t1); + gen_helper_adc_cc(t0, cpu_env, t0, t1); else gen_adc(t0, t1); break; case 11: /* sbc */ if (conds) - gen_helper_sbc_cc(t0, t0, t1); + gen_helper_sbc_cc(t0, cpu_env, t0, t1); else gen_sub_carry(t0, t0, t1); break; case 13: /* sub */ if (conds) - gen_helper_sub_cc(t0, t0, t1); + gen_helper_sub_cc(t0, cpu_env, t0, t1); else tcg_gen_sub_i32(t0, t0, t1); break; case 14: /* rsb */ if (conds) - gen_helper_sub_cc(t0, t1, t0); + gen_helper_sub_cc(t0, cpu_env, t1, t0); else tcg_gen_sub_i32(t0, t1, t0); break; @@ -9188,12 +9188,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); } else { if (s->condexec_mask) tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); } tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); @@ -9224,7 +9224,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) tcg_gen_movi_i32(tmp2, insn & 0xff); switch (op) { case 1: /* cmp */ - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); break; @@ -9232,7 +9232,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_add_i32(tmp, tmp, tmp2); else - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -9240,7 +9240,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_sub_i32(tmp, tmp, tmp2); else - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(s, rd, tmp); break; @@ -9276,7 +9276,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) case 1: /* cmp */ tmp = load_reg(s, rd); tmp2 = load_reg(s, rm); - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); break; @@ -9337,25 +9337,25 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) break; case 0x2: /* lsl */ if (s->condexec_mask) { - gen_helper_shl(tmp2, tmp2, tmp); + gen_helper_shl(tmp2, cpu_env, tmp2, tmp); } else { - gen_helper_shl_cc(tmp2, tmp2, tmp); + gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x3: /* lsr */ if (s->condexec_mask) { - gen_helper_shr(tmp2, tmp2, tmp); + gen_helper_shr(tmp2, cpu_env, tmp2, tmp); } else { - gen_helper_shr_cc(tmp2, tmp2, tmp); + gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x4: /* asr */ if (s->condexec_mask) { - gen_helper_sar(tmp2, tmp2, tmp); + gen_helper_sar(tmp2, cpu_env, tmp2, tmp); } else { - gen_helper_sar_cc(tmp2, tmp2, tmp); + gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; @@ -9363,20 +9363,20 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) gen_adc(tmp, tmp2); else - gen_helper_adc_cc(tmp, tmp, tmp2); + gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); break; case 0x6: /* sbc */ if (s->condexec_mask) gen_sub_carry(tmp, tmp, tmp2); else - gen_helper_sbc_cc(tmp, tmp, tmp2); + gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); break; case 0x7: /* ror */ if (s->condexec_mask) { tcg_gen_andi_i32(tmp, tmp, 0x1f); tcg_gen_rotr_i32(tmp2, tmp2, tmp); } else { - gen_helper_ror_cc(tmp2, tmp2, tmp); + gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; @@ -9389,14 +9389,14 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) if (s->condexec_mask) tcg_gen_neg_i32(tmp, tmp2); else - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); break; case 0xa: /* cmp */ - gen_helper_sub_cc(tmp, tmp, tmp2); + gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); rd = 16; break; case 0xb: /* cmn */ - gen_helper_add_cc(tmp, tmp, tmp2); + gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); rd = 16; break; case 0xc: /* orr */ -- 1.7.2.5