aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-01-14 20:39:18 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-01-14 20:39:18 +0100
commit39ea3d4eaf1ff300ee55946108394729bc053dfa (patch)
tree4e0e7fa61544f4fbf38693ac0fa0cfd331caa007 /target-arm
parent718269667ab60c878940ab7a4e3e0ef1e984d784 (diff)
downloadqemu-39ea3d4eaf1ff300ee55946108394729bc053dfa.zip
qemu-39ea3d4eaf1ff300ee55946108394729bc053dfa.tar.gz
qemu-39ea3d4eaf1ff300ee55946108394729bc053dfa.tar.bz2
target-arm: Don't generate code specific to current CPU mode for SRS
When translating the SRS instruction, handle the "store registers to stack of current mode" case in the helper function rather than inline. This means the generated code does not make assumptions about the current CPU mode which might not be valid when the TB is executed later. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/helper.c12
-rw-r--r--target-arm/translate.c46
2 files changed, 25 insertions, 33 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 8186500..b562767 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1849,12 +1849,20 @@ bad_reg:
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
{
- env->banked_r13[bank_number(mode)] = val;
+ if ((env->uncached_cpsr & CPSR_M) == mode) {
+ env->regs[13] = val;
+ } else {
+ env->banked_r13[bank_number(mode)] = val;
+ }
}
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
{
- return env->banked_r13[bank_number(mode)];
+ if ((env->uncached_cpsr & CPSR_M) == mode) {
+ return env->regs[13];
+ } else {
+ return env->banked_r13[bank_number(mode)];
+ }
}
uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 57664bc..ee19d76 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6122,14 +6122,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
goto illegal_op;
ARCH(6);
op1 = (insn & 0x1f);
- if (op1 == (env->uncached_cpsr & CPSR_M)) {
- addr = load_reg(s, 13);
- } else {
- addr = new_tmp();
- tmp = tcg_const_i32(op1);
- gen_helper_get_r13_banked(addr, cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- }
+ addr = new_tmp();
+ tmp = tcg_const_i32(op1);
+ gen_helper_get_r13_banked(addr, cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
i = (insn >> 23) & 3;
switch (i) {
case 0: offset = -4; break; /* DA */
@@ -6156,14 +6152,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
}
if (offset)
tcg_gen_addi_i32(addr, addr, offset);
- if (op1 == (env->uncached_cpsr & CPSR_M)) {
- store_reg(s, 13, addr);
- } else {
- tmp = tcg_const_i32(op1);
- gen_helper_set_r13_banked(cpu_env, tmp, addr);
- tcg_temp_free_i32(tmp);
- dead_tmp(addr);
- }
+ tmp = tcg_const_i32(op1);
+ gen_helper_set_r13_banked(cpu_env, tmp, addr);
+ tcg_temp_free_i32(tmp);
+ dead_tmp(addr);
} else {
dead_tmp(addr);
}
@@ -7575,14 +7567,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
} else {
/* srs */
op = (insn & 0x1f);
- if (op == (env->uncached_cpsr & CPSR_M)) {
- addr = load_reg(s, 13);
- } else {
- addr = new_tmp();
- tmp = tcg_const_i32(op);
- gen_helper_get_r13_banked(addr, cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- }
+ addr = new_tmp();
+ tmp = tcg_const_i32(op);
+ gen_helper_get_r13_banked(addr, cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
if ((insn & (1 << 24)) == 0) {
tcg_gen_addi_i32(addr, addr, -8);
}
@@ -7598,13 +7586,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
} else {
tcg_gen_addi_i32(addr, addr, 4);
}
- if (op == (env->uncached_cpsr & CPSR_M)) {
- store_reg(s, 13, addr);
- } else {
- tmp = tcg_const_i32(op);
- gen_helper_set_r13_banked(cpu_env, tmp, addr);
- tcg_temp_free_i32(tmp);
- }
+ tmp = tcg_const_i32(op);
+ gen_helper_set_r13_banked(cpu_env, tmp, addr);
+ tcg_temp_free_i32(tmp);
} else {
dead_tmp(addr);
}