target/arm: Introduce delay_exception{_el}

Add infrastructure to raise an exception out of line.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20251008215613.300150-44-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2025-10-08 14:55:43 -07:00 committed by Peter Maydell
parent 49b49214f3
commit 609f5d7692
3 changed files with 75 additions and 0 deletions

View file

@ -10601,6 +10601,8 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
break;
}
}
emit_delayed_exceptions(dc);
}
const TranslatorOps aarch64_translator_ops = {

View file

@ -1088,6 +1088,57 @@ void gen_exception_insn(DisasContext *s, target_long pc_diff,
s->base.is_jmp = DISAS_NORETURN;
}
TCGLabel *delay_exception_el(DisasContext *s, int excp,
uint32_t syn, uint32_t target_el)
{
/* Use tcg_malloc for automatic release on longjmp out of translation. */
DisasDelayException *e = tcg_malloc(sizeof(DisasDelayException));
memset(e, 0, sizeof(*e));
/* Save enough of the current state to satisfy gen_exception_insn. */
e->pc_curr = s->pc_curr;
e->pc_save = s->pc_save;
if (!s->aarch64) {
e->condexec_cond = s->condexec_cond;
e->condexec_mask = s->condexec_mask;
}
e->excp = excp;
e->syn = syn;
e->target_el = target_el;
e->next = s->delay_excp_list;
s->delay_excp_list = e;
e->lab = gen_new_label();
return e->lab;
}
TCGLabel *delay_exception(DisasContext *s, int excp, uint32_t syn)
{
return delay_exception_el(s, excp, syn, 0);
}
void emit_delayed_exceptions(DisasContext *s)
{
for (DisasDelayException *e = s->delay_excp_list; e ; e = e->next) {
gen_set_label(e->lab);
/* Restore the insn state to satisfy gen_exception_insn. */
s->pc_curr = e->pc_curr;
s->pc_save = e->pc_save;
s->condexec_cond = e->condexec_cond;
s->condexec_mask = e->condexec_mask;
if (e->target_el) {
gen_exception_insn_el(s, 0, e->excp, e->syn, e->target_el);
} else {
gen_exception_insn(s, 0, e->excp, e->syn);
}
}
}
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
{
gen_set_condexec(s);
@ -6791,6 +6842,8 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_goto_tb(dc, 1, curr_insn_len(dc));
}
}
emit_delayed_exceptions(dc);
}
static const TranslatorOps arm_translator_ops = {

View file

@ -21,9 +21,25 @@ typedef struct DisasLabel {
target_ulong pc_save;
} DisasLabel;
/*
* Emit an exception call out of line.
*/
typedef struct DisasDelayException {
struct DisasDelayException *next;
TCGLabel *lab;
target_long pc_curr;
target_long pc_save;
int condexec_mask;
int condexec_cond;
uint32_t excp;
uint32_t syn;
uint32_t target_el;
} DisasDelayException;
typedef struct DisasContext {
DisasContextBase base;
const ARMISARegisters *isar;
DisasDelayException *delay_excp_list;
/* The address of the current instruction being translated. */
target_ulong pc_curr;
@ -365,6 +381,10 @@ void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
uint32_t syn, uint32_t target_el);
void gen_exception_insn(DisasContext *s, target_long pc_diff,
int excp, uint32_t syn);
TCGLabel *delay_exception_el(DisasContext *s, int excp,
uint32_t syn, uint32_t target_el);
TCGLabel *delay_exception(DisasContext *s, int excp, uint32_t syn);
void emit_delayed_exceptions(DisasContext *s);
/* Return state of Alternate Half-precision flag, caller frees result */
static inline TCGv_i32 get_ahp_flag(void)