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.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 0862f9e4aa..e27736ce5b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -4158,6 +4158,10 @@ static void gen_goto_ptr(void)
tcg_temp_free(addr);
}
+/* This will end the TB but doesn't guarantee we'll return to
+ * cpu_loop_exec. Any live exit_requests will be processed as we
+ * enter the next TB.
+ */
static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
{
if (use_goto_tb(s, dest)) {
@@ -4168,6 +4172,7 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
gen_set_pc_im(s, dest);
gen_goto_ptr();
}
+ s->is_jmp = DISAS_TB_JUMP;
}
static inline void gen_jmp (DisasContext *s, uint32_t dest)
@@ -4179,7 +4184,6 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
gen_bx_im(s, dest);
} else {
gen_goto_tb(s, 0, dest);
- s->is_jmp = DISAS_TB_JUMP;
}
}
@@ -4475,7 +4479,8 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
*/
gen_helper_cpsr_write_eret(cpu_env, cpsr);
tcg_temp_free_i32(cpsr);
- s->is_jmp = DISAS_JUMP;
+ /* Must exit loop to check un-masked IRQs */
+ s->is_jmp = DISAS_EXIT;
}
/* Generate an old-style exception return. Marks pc as dead. */
@@ -8165,7 +8170,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
* self-modifying code correctly and also to take
* any pending interrupts immediately.
*/
- gen_lookup_tb(s);
+ gen_goto_tb(s, 0, s->pc & ~1);
return;
default:
goto illegal_op;
@@ -9519,7 +9524,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = load_cpu_field(spsr);
gen_helper_cpsr_write_eret(cpu_env, tmp);
tcg_temp_free_i32(tmp);
- s->is_jmp = DISAS_JUMP;
+ /* Must exit loop to check un-masked IRQs */
+ s->is_jmp = DISAS_EXIT;
}
}
break;
@@ -10558,7 +10564,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
* and also to take any pending interrupts
* immediately.
*/
- gen_lookup_tb(s);
+ gen_goto_tb(s, 0, s->pc & ~1);
break;
default:
goto illegal_op;
@@ -12095,12 +12101,12 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
case DISAS_NEXT:
gen_goto_tb(dc, 1, dc->pc);
break;
- case DISAS_UPDATE:
- gen_set_pc_im(dc, dc->pc);
- /* fall through */
case DISAS_JUMP:
gen_goto_ptr();
break;
+ case DISAS_UPDATE:
+ gen_set_pc_im(dc, dc->pc);
+ /* fall through */
default:
/* indicate that the hash table must be used to find the next TB */
tcg_gen_exit_tb(0);