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.c240
1 files changed, 149 insertions, 91 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e46cfb9ea1..f732f91e7d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -226,7 +226,6 @@ static void gen_smul_dual(TCGv a, TCGv b)
{
TCGv tmp1 = new_tmp();
TCGv tmp2 = new_tmp();
- TCGv res;
tcg_gen_ext8s_i32(tmp1, a);
tcg_gen_ext8s_i32(tmp2, b);
tcg_gen_mul_i32(tmp1, tmp1, tmp2);
@@ -495,49 +494,93 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
}
};
-#define PAS_OP(pfx) { \
- gen_op_ ## pfx ## add16_T0_T1, \
- gen_op_ ## pfx ## addsubx_T0_T1, \
- gen_op_ ## pfx ## subaddx_T0_T1, \
- gen_op_ ## pfx ## sub16_T0_T1, \
- gen_op_ ## pfx ## add8_T0_T1, \
- NULL, \
- NULL, \
- gen_op_ ## pfx ## sub8_T0_T1 }
-
-static GenOpFunc *gen_arm_parallel_addsub[8][8] = {
- {},
- PAS_OP(s),
- PAS_OP(q),
- PAS_OP(sh),
- {},
- PAS_OP(u),
- PAS_OP(uq),
- PAS_OP(uh),
-};
+#define PAS_OP(pfx) \
+ switch (op2) { \
+ case 0: gen_pas_helper(glue(pfx,add16)); break; \
+ case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
+ case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
+ case 3: gen_pas_helper(glue(pfx,sub16)); break; \
+ case 4: gen_pas_helper(glue(pfx,add8)); break; \
+ case 7: gen_pas_helper(glue(pfx,sub8)); break; \
+ }
+void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
+{
+ TCGv tmp;
+
+ switch (op1) {
+#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
+ case 1:
+ tmp = tcg_temp_new(TCG_TYPE_PTR);
+ tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+ PAS_OP(s)
+ break;
+ case 5:
+ tmp = tcg_temp_new(TCG_TYPE_PTR);
+ tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+ PAS_OP(u)
+ break;
+#undef gen_pas_helper
+#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
+ case 2:
+ PAS_OP(q);
+ break;
+ case 3:
+ PAS_OP(sh);
+ break;
+ case 6:
+ PAS_OP(uq);
+ break;
+ case 7:
+ PAS_OP(uh);
+ break;
+#undef gen_pas_helper
+ }
+}
#undef PAS_OP
-/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings. */
-#define PAS_OP(pfx) { \
- gen_op_ ## pfx ## add8_T0_T1, \
- gen_op_ ## pfx ## add16_T0_T1, \
- gen_op_ ## pfx ## addsubx_T0_T1, \
- NULL, \
- gen_op_ ## pfx ## sub8_T0_T1, \
- gen_op_ ## pfx ## sub16_T0_T1, \
- gen_op_ ## pfx ## subaddx_T0_T1, \
- NULL }
-
-static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = {
- PAS_OP(s),
- PAS_OP(q),
- PAS_OP(sh),
- {},
- PAS_OP(u),
- PAS_OP(uq),
- PAS_OP(uh),
- {}
-};
+/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
+#define PAS_OP(pfx) \
+ switch (op2) { \
+ case 0: gen_pas_helper(glue(pfx,add8)); break; \
+ case 1: gen_pas_helper(glue(pfx,add16)); break; \
+ case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
+ case 4: gen_pas_helper(glue(pfx,sub8)); break; \
+ case 5: gen_pas_helper(glue(pfx,sub16)); break; \
+ case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
+ }
+void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
+{
+ TCGv tmp;
+
+ switch (op1) {
+#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
+ case 0:
+ tmp = tcg_temp_new(TCG_TYPE_PTR);
+ tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+ PAS_OP(s)
+ break;
+ case 4:
+ tmp = tcg_temp_new(TCG_TYPE_PTR);
+ tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
+ PAS_OP(u)
+ break;
+#undef gen_pas_helper
+#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
+ case 1:
+ PAS_OP(q);
+ break;
+ case 2:
+ PAS_OP(sh);
+ break;
+ case 5:
+ PAS_OP(uq);
+ break;
+ case 6:
+ PAS_OP(uh);
+ break;
+#undef gen_pas_helper
+ }
+}
#undef PAS_OP
static GenOpFunc1 *gen_test_cc[14] = {
@@ -4906,6 +4949,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
TCGv tmp;
TCGv tmp2;
+ TCGv tmp3;
insn = ldl_code(s->pc);
s->pc += 4;
@@ -5591,13 +5635,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
switch ((insn >> 23) & 3) {
case 0: /* Parallel add/subtract. */
op1 = (insn >> 20) & 7;
- gen_movl_T0_reg(s, rn);
- gen_movl_T1_reg(s, rm);
+ tmp = load_reg(s, rn);
+ tmp2 = load_reg(s, rm);
sh = (insn >> 5) & 7;
if ((op1 & 3) == 0 || sh == 5 || sh == 6)
goto illegal_op;
- gen_arm_parallel_addsub[op1][sh]();
- gen_movl_reg_T0(s, rd);
+ gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
+ dead_tmp(tmp2);
+ store_reg(s, rd, tmp);
break;
case 1:
if ((insn & 0x00700020) == 0) {
@@ -5620,40 +5665,44 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
store_reg(s, rd, tmp);
} else if ((insn & 0x00200020) == 0x00200000) {
/* [us]sat */
- gen_movl_T1_reg(s, rm);
+ tmp = load_reg(s, rm);
shift = (insn >> 7) & 0x1f;
if (insn & (1 << 6)) {
if (shift == 0)
shift = 31;
- gen_op_sarl_T1_im(shift);
+ tcg_gen_sari_i32(tmp, tmp, shift);
} else {
- gen_op_shll_T1_im(shift);
+ tcg_gen_shli_i32(tmp, tmp, shift);
}
sh = (insn >> 16) & 0x1f;
if (sh != 0) {
if (insn & (1 << 22))
- gen_op_usat_T1(sh);
+ gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
else
- gen_op_ssat_T1(sh);
+ gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
}
- gen_movl_T1_reg(s, rd);
+ store_reg(s, rd, tmp);
} else if ((insn & 0x00300fe0) == 0x00200f20) {
/* [us]sat16 */
- gen_movl_T1_reg(s, rm);
+ tmp = load_reg(s, rm);
sh = (insn >> 16) & 0x1f;
if (sh != 0) {
if (insn & (1 << 22))
- gen_op_usat16_T1(sh);
+ gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
else
- gen_op_ssat16_T1(sh);
+ gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
}
- gen_movl_T1_reg(s, rd);
+ store_reg(s, rd, tmp);
} else if ((insn & 0x00700fe0) == 0x00000fa0) {
/* Select bytes. */
- gen_movl_T0_reg(s, rn);
- gen_movl_T1_reg(s, rm);
- gen_op_sel_T0_T1();
- gen_movl_reg_T0(s, rd);
+ tmp = load_reg(s, rn);
+ tmp2 = load_reg(s, rm);
+ tmp3 = new_tmp();
+ tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
+ gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
+ dead_tmp(tmp3);
+ dead_tmp(tmp2);
+ store_reg(s, rd, tmp);
} else if ((insn & 0x000003e0) == 0x00000060) {
gen_movl_T1_reg(s, rm);
shift = (insn >> 10) & 3;
@@ -5755,15 +5804,17 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
switch (op1) {
case 0: /* Unsigned sum of absolute differences. */
- goto illegal_op;
- gen_movl_T0_reg(s, rm);
- gen_movl_T1_reg(s, rs);
- gen_op_usad8_T0_T1();
+ ARCH(6);
+ tmp = load_reg(s, rm);
+ tmp2 = load_reg(s, rs);
+ gen_helper_usad8(tmp, tmp, tmp2);
+ dead_tmp(tmp2);
if (rn != 15) {
- gen_movl_T1_reg(s, rn);
- gen_op_addl_T0_T1();
+ tmp2 = load_reg(s, rn);
+ tcg_gen_add_i32(tmp, tmp, tmp2);
+ dead_tmp(tmp2);
}
- gen_movl_reg_T0(s, rd);
+ store_reg(s, rd, tmp);
break;
case 0x20: case 0x24: case 0x28: case 0x2c:
/* Bitfield insert/clear. */
@@ -6120,6 +6171,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
uint32_t insn, imm, shift, offset, addr;
uint32_t rd, rn, rm, rs;
TCGv tmp;
+ TCGv tmp2;
+ TCGv tmp3;
int op;
int shiftop;
int conds;
@@ -6464,10 +6517,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
shift = (insn >> 4) & 7;
if ((op & 3) == 3 || (shift & 3) == 3)
goto illegal_op;
- gen_movl_T0_reg(s, rn);
- gen_movl_T1_reg(s, rm);
- gen_thumb2_parallel_addsub[op][shift]();
- gen_movl_reg_T0(s, rd);
+ tmp = load_reg(s, rn);
+ tmp2 = load_reg(s, rm);
+ gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
+ dead_tmp(tmp2);
+ store_reg(s, rd, tmp);
break;
case 3: /* Other data processing. */
op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
@@ -6498,7 +6552,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
break;
case 0x10: /* sel */
gen_movl_T1_reg(s, rm);
- gen_op_sel_T0_T1();
+ tmp3 = new_tmp();
+ tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
+ gen_helper_sel_flags(cpu_T[0], tmp3, cpu_T[0], cpu_T[1]);
+ dead_tmp(tmp3);
break;
case 0x18: /* clz */
gen_helper_clz(cpu_T[0], cpu_T[0]);
@@ -6581,7 +6638,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
gen_movl_reg_T0(s, rd);
break;
case 7: /* Unsigned sum of absolute differences. */
- gen_op_usad8_T0_T1();
+ gen_helper_usad8(cpu_T[0], cpu_T[0], cpu_T[1]);
if (rs != 15) {
gen_movl_T1_reg(s, rs);
gen_op_addl_T0_T1();
@@ -6821,63 +6878,64 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
op = (insn >> 21) & 7;
imm = insn & 0x1f;
shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
- if (rn == 15)
- gen_op_movl_T1_im(0);
- else
- gen_movl_T1_reg(s, rn);
+ if (rn == 15) {
+ tmp = new_tmp();
+ tcg_gen_movi_i32(tmp, 0);
+ } else {
+ tmp = load_reg(s, rn);
+ }
switch (op) {
case 2: /* Signed bitfield extract. */
imm++;
if (shift + imm > 32)
goto illegal_op;
if (imm < 32)
- gen_sbfx(cpu_T[1], shift, imm);
+ gen_sbfx(tmp, shift, imm);
break;
case 6: /* Unsigned bitfield extract. */
imm++;
if (shift + imm > 32)
goto illegal_op;
if (imm < 32)
- gen_ubfx(cpu_T[1], shift, (1u << imm) - 1);
+ gen_ubfx(tmp, shift, (1u << imm) - 1);
break;
case 3: /* Bitfield insert/clear. */
if (imm < shift)
goto illegal_op;
imm = imm + 1 - shift;
if (imm != 32) {
- gen_movl_T0_reg(s, rd);
- gen_bfi(cpu_T[1], cpu_T[0], cpu_T[1],
+ tmp2 = load_reg(s, rd);
+ gen_bfi(tmp, tmp2, tmp,
shift, ((1u << imm) - 1) << shift);
+ dead_tmp(tmp2);
}
break;
case 7:
goto illegal_op;
default: /* Saturate. */
- gen_movl_T1_reg(s, rn);
if (shift) {
if (op & 1)
- gen_op_sarl_T1_im(shift);
+ tcg_gen_sari_i32(tmp, tmp, shift);
else
- gen_op_shll_T1_im(shift);
+ tcg_gen_shli_i32(tmp, tmp, shift);
}
+ tmp2 = tcg_const_i32(imm);
if (op & 4) {
/* Unsigned. */
- gen_op_ssat_T1(imm);
if ((op & 1) && shift == 0)
- gen_op_usat16_T1(imm);
+ gen_helper_usat16(tmp, tmp, tmp2);
else
- gen_op_usat_T1(imm);
+ gen_helper_usat(tmp, tmp, tmp2);
} else {
/* Signed. */
- gen_op_ssat_T1(imm);
if ((op & 1) && shift == 0)
- gen_op_ssat16_T1(imm);
+ gen_helper_ssat16(tmp, tmp, tmp2);
else
- gen_op_ssat_T1(imm);
+ gen_helper_ssat(tmp, tmp, tmp2);
}
break;
}
- gen_movl_reg_T1(s, rd);
+ store_reg(s, rd, tmp);
} else {
imm = ((insn & 0x04000000) >> 15)
| ((insn & 0x7000) >> 4) | (insn & 0xff);