aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2012-10-05 15:04:44 +0100
committerPeter Maydell <peter.maydell@linaro.org>2012-10-05 15:04:44 +0100
commit365af80e47bf150506345cdfbcbf32120f18cdf6 (patch)
tree6fe81992eb8d77b7fe88aaf20764270efcd8cb70
parent72485ec4f63d86c428f9223fc966bd7d2cc8100c (diff)
target-arm: convert sar, shl and shr helpers to TCG
Now that the movcond TCG op is available, it's possible to replace shl and shr helpers by TCG code. The code generated by TCG is slightly longer than the code generated by GCC for the helper but is still worth it as this avoid all the consequences of using an helper: globals saved back to memory, no possible optimization, call overhead, etc. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target-arm/helper.h3
-rw-r--r--target-arm/op_helper.c24
-rw-r--r--target-arm/translate.c49
3 files changed, 43 insertions, 33 deletions
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 7151e28d4..794e2b186 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -145,9 +145,6 @@ DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
DEF_HELPER_3(adc_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)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 6095f2435..aef592ab8 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -355,30 +355,6 @@ uint32_t HELPER(sbc_cc)(CPUARMState *env, uint32_t a, uint32_t b)
/* 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;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index da3246a95..92ceacd87 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -440,6 +440,37 @@ static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1)
tcg_gen_mov_i32(dest, cpu_NF);
}
+#define GEN_SHIFT(name) \
+static void gen_##name(TCGv dest, TCGv t0, TCGv t1) \
+{ \
+ TCGv tmp1, tmp2, tmp3; \
+ tmp1 = tcg_temp_new_i32(); \
+ tcg_gen_andi_i32(tmp1, t1, 0xff); \
+ tmp2 = tcg_const_i32(0); \
+ tmp3 = tcg_const_i32(0x1f); \
+ tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
+ tcg_temp_free_i32(tmp3); \
+ tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
+ tcg_gen_##name##_i32(dest, tmp2, tmp1); \
+ tcg_temp_free_i32(tmp2); \
+ tcg_temp_free_i32(tmp1); \
+}
+GEN_SHIFT(shl)
+GEN_SHIFT(shr)
+#undef GEN_SHIFT
+
+static void gen_sar(TCGv dest, TCGv t0, TCGv t1)
+{
+ TCGv tmp1, tmp2;
+ tmp1 = tcg_temp_new_i32();
+ tcg_gen_andi_i32(tmp1, t1, 0xff);
+ tmp2 = tcg_const_i32(0x1f);
+ tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
+ tcg_temp_free_i32(tmp2);
+ tcg_gen_sar_i32(dest, t0, tmp1);
+ tcg_temp_free_i32(tmp1);
+}
+
/* FIXME: Implement this natively. */
#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
@@ -516,9 +547,15 @@ static inline void gen_arm_shift_reg(TCGv var, int shiftop,
}
} else {
switch (shiftop) {
- 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 0:
+ gen_shl(var, var, shift);
+ break;
+ case 1:
+ gen_shr(var, var, shift);
+ break;
+ case 2:
+ gen_sar(var, var, shift);
+ break;
case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
tcg_gen_rotr_i32(var, var, shift); break;
}
@@ -9161,7 +9198,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x2: /* lsl */
if (s->condexec_mask) {
- gen_helper_shl(tmp2, cpu_env, tmp2, tmp);
+ gen_shl(tmp2, tmp2, tmp);
} else {
gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
@@ -9169,7 +9206,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x3: /* lsr */
if (s->condexec_mask) {
- gen_helper_shr(tmp2, cpu_env, tmp2, tmp);
+ gen_shr(tmp2, tmp2, tmp);
} else {
gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);
@@ -9177,7 +9214,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0x4: /* asr */
if (s->condexec_mask) {
- gen_helper_sar(tmp2, cpu_env, tmp2, tmp);
+ gen_sar(tmp2, tmp2, tmp);
} else {
gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
gen_logic_CC(tmp2);