Convert the register shifted by register form of the data
processing insns. For A32, we cannot yet remove any code
because the legacy decoder intertwines the immediate form.
Signed-off-by: Richard Henderson
---
target/arm/translate.c | 74 ++
target/arm/a32.decode | 27 +++
target/arm/t32.decode | 6
3 files changed, 87 insertions(+), 20 deletions(-)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index be8e7685e3..a32fe4b222 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7773,17 +7773,66 @@ static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi
*a,
return store_reg_kind(s, a->rd, tmp, kind);
}
+/*
+ * Data-processing (register-shifted register)
+ *
+ * Operate, with set flags, one register source,
+ * one register shifted register source, and a destination.
+ */
+static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
+ void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
+ int logic_cc, StoreRegKind kind)
+{
+TCGv_i32 tmp1, tmp2;
+
+tmp1 = load_reg(s, a->rs);
+tmp2 = load_reg(s, a->rm);
+gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
+tmp1 = load_reg(s, a->rn);
+
+gen(tmp1, tmp1, tmp2);
+tcg_temp_free_i32(tmp2);
+
+if (logic_cc) {
+gen_logic_CC(tmp1);
+}
+return store_reg_kind(s, a->rd, tmp1, kind);
+}
+
+static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
+ void (*gen)(TCGv_i32, TCGv_i32),
+ int logic_cc, StoreRegKind kind)
+{
+TCGv_i32 tmp1, tmp2;
+
+tmp1 = load_reg(s, a->rs);
+tmp2 = load_reg(s, a->rm);
+gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
+
+gen(tmp2, tmp2);
+if (logic_cc) {
+gen_logic_CC(tmp2);
+}
+return store_reg_kind(s, a->rd, tmp2, kind);
+}
+
#define DO_ANY3(NAME, OP, L, K) \
static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
-{ StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); }
+{ StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
+static bool trans_##NAME##_(DisasContext *s, arg_s_rrr_shr *a) \
+{ StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); }
#define DO_ANY2(NAME, OP, L, K) \
static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
-{ StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); }
+{ StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
+static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
+{ StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); }
#define DO_CMP2(NAME, OP, L)\
static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
-{ return op_s_rrr_shi(s, a, OP, L, STREG_NONE); }
+{ return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
+static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
+{ return op_s_rrr_shr(s, a, OP, L, STREG_NONE); }
DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
@@ -9555,7 +9604,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t
insn)
TCGv_i32 addr;
TCGv_i64 tmp64;
int op;
-int logic_cc;
/*
* ARMv6-M supports a limited subset of Thumb2 instructions.
@@ -9993,22 +10041,8 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t
insn)
if (op < 4 && (insn & 0xf000) != 0xf000)
goto illegal_op;
switch (op) {
-case 0: /* Register controlled shift. */
-tmp = load_reg(s, rn);
-tmp2 = load_reg(s, rm);
-if ((insn & 0x70) != 0)
-goto illegal_op;
-/*
- * 0b_1010_0xxx_____:
- * - MOV, MOVS (register-shifted register), flagsetting
- */
-op = (insn >> 21) & 3;
-logic_cc = (insn & (1 << 20)) != 0;
-gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
-if (logic_cc)
-gen_logic_CC(tmp);
-store_reg(s, rd, tmp);
-break;
+case 0: /* Register controlled shift, in decodetree */
+goto illegal_op;
case 1: /* Sign/zero extend. */
op = (insn >> 20) & 7;
switch (op) {
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
index b23e83f17c..8e0fb06d05 100644
--- a/target/arm/a32.decode
+++ b/target/arm/a32.decode
@@ -23,6 +23,7 @@
#
_rrr_shi s rd rn rm shim shty
+_rrr_shr s rn rd rm rs shty
# Data-processing (register)
@@ -49,3 +50,29 @@ ORR_rrri 000 1100 . . .. 0
@s_rrr_shi
MOV_rxri 000 1101 . . .. 0 @s_rxr_shi
BIC_rrri 000