aboutsummaryrefslogtreecommitdiff
path: root/target-arm/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r--target-arm/translate.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index da3246a952..92ceacd873 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);