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:
parent
49b49214f3
commit
609f5d7692
3 changed files with 75 additions and 0 deletions
|
|
@ -10601,6 +10601,8 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emit_delayed_exceptions(dc);
|
||||
}
|
||||
|
||||
const TranslatorOps aarch64_translator_ops = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue