gen_bx(s, tmp);
}
+/* Variant of store_reg which uses branch&exchange logic when storing
+ to r15 in ARM architecture v7 and above. The source must be a temporary
+ and will be marked as dead. */
+static inline void store_reg_bx(CPUState *env, DisasContext *s,
+ int reg, TCGv var)
+{
+ if (reg == 15 && ENABLE_ARCH_7) {
+ gen_bx(s, var);
+ } else {
+ store_reg(s, reg, var);
+ }
+}
+
static inline TCGv gen_ld8s(TCGv addr, int index)
{
TCGv tmp = new_tmp();
if (logic_cc) {
gen_logic_CC(tmp);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x01:
tcg_gen_xor_i32(tmp, tmp, tmp2);
if (logic_cc) {
gen_logic_CC(tmp);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x02:
if (set_cc && rd == 15) {
} else {
tcg_gen_sub_i32(tmp, tmp, tmp2);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
}
break;
case 0x03:
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x04:
if (set_cc) {
} else {
tcg_gen_add_i32(tmp, tmp, tmp2);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x05:
if (set_cc) {
} else {
gen_add_carry(tmp, tmp, tmp2);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x06:
if (set_cc) {
} else {
gen_sub_carry(tmp, tmp, tmp2);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x07:
if (set_cc) {
} else {
gen_sub_carry(tmp, tmp2, tmp);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x08:
if (set_cc) {
if (logic_cc) {
gen_logic_CC(tmp);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 0x0d:
if (logic_cc && rd == 15) {
if (logic_cc) {
gen_logic_CC(tmp2);
}
- store_reg(s, rd, tmp2);
+ store_reg_bx(env, s, rd, tmp2);
}
break;
case 0x0e:
if (logic_cc) {
gen_logic_CC(tmp);
}
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
default:
case 0x0f:
if (logic_cc) {
gen_logic_CC(tmp2);
}
- store_reg(s, rd, tmp2);
+ store_reg_bx(env, s, rd, tmp2);
break;
}
if (op1 != 0x0f && op1 != 0x0d) {
gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
if (logic_cc)
gen_logic_CC(tmp);
- store_reg(s, rd, tmp);
+ store_reg_bx(env, s, rd, tmp);
break;
case 1: /* Sign/zero extend. */
tmp = load_reg(s, rm);