target/arm: Use DISAS_NORETURN

Fold DISAS_EXC and DISAS_TB_JUMP into DISAS_NORETURN.

In both cases all following code is dead. In the first
case because we have exited the TB via exception; in the
second case because we have exited the TB via goto_tb
and its associated machinery.

Backports commit a0c231e651b249960906f250b8e5eef5ed9888c4 from qemu
This commit is contained in:
Richard Henderson 2018-03-04 13:54:35 -05:00 committed by Lioncash
parent b7ba55a5b5
commit 4a5b1aec34
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 30 additions and 29 deletions

View file

@ -320,7 +320,7 @@ static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
{ {
gen_a64_set_pc_im(s, s->pc - offset); gen_a64_set_pc_im(s, s->pc - offset);
gen_exception_internal(s, excp); gen_exception_internal(s, excp);
s->is_jmp = DISAS_EXC; s->is_jmp = DISAS_NORETURN;
} }
static void gen_exception_insn(DisasContext *s, int offset, int excp, static void gen_exception_insn(DisasContext *s, int offset, int excp,
@ -328,7 +328,7 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
{ {
gen_a64_set_pc_im(s, s->pc - offset); gen_a64_set_pc_im(s, s->pc - offset);
gen_exception(s, excp, syndrome, target_el); gen_exception(s, excp, syndrome, target_el);
s->is_jmp = DISAS_EXC; s->is_jmp = DISAS_NORETURN;
} }
static void gen_ss_advance(DisasContext *s) static void gen_ss_advance(DisasContext *s)
@ -357,7 +357,7 @@ static void gen_step_complete_exception(DisasContext *s)
gen_ss_advance(s); gen_ss_advance(s);
gen_exception(s, EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex), gen_exception(s, EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
default_exception_el(s)); default_exception_el(s));
s->is_jmp = DISAS_EXC; s->is_jmp = DISAS_NORETURN;
} }
static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest) static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
@ -389,7 +389,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
tcg_gen_goto_tb(tcg_ctx, n); tcg_gen_goto_tb(tcg_ctx, n);
gen_a64_set_pc_im(s, dest); gen_a64_set_pc_im(s, dest);
tcg_gen_exit_tb(tcg_ctx, (intptr_t)tb + n); tcg_gen_exit_tb(tcg_ctx, (intptr_t)tb + n);
s->is_jmp = DISAS_TB_JUMP; s->is_jmp = DISAS_NORETURN;
} else { } else {
gen_a64_set_pc_im(s, dest); gen_a64_set_pc_im(s, dest);
if (s->ss_active) { if (s->ss_active) {
@ -398,7 +398,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
gen_exception_internal(s, EXCP_DEBUG); gen_exception_internal(s, EXCP_DEBUG);
} else { } else {
tcg_gen_lookup_and_goto_ptr(tcg_ctx, tcg_ctx->cpu_pc); tcg_gen_lookup_and_goto_ptr(tcg_ctx, tcg_ctx->cpu_pc);
s->is_jmp = DISAS_TB_JUMP; s->is_jmp = DISAS_NORETURN;
} }
} }
} }
@ -11573,7 +11573,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
assert(num_insns == 1); assert(num_insns == 1);
gen_exception(dc, EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0), gen_exception(dc, EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
default_exception_el(dc)); default_exception_el(dc));
dc->is_jmp = DISAS_EXC; dc->is_jmp = DISAS_NORETURN;
break; break;
} }
@ -11605,21 +11605,25 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
//} //}
tb_end: tb_end:
if (unlikely(cs->singlestep_enabled || dc->ss_active) if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
&& dc->is_jmp != DISAS_EXC) {
/* Note that this means single stepping WFI doesn't halt the CPU. /* Note that this means single stepping WFI doesn't halt the CPU.
* For conditional branch insns this is harmless unreachable code as * For conditional branch insns this is harmless unreachable code as
* gen_goto_tb() has already handled emitting the debug exception * gen_goto_tb() has already handled emitting the debug exception
* (and thus a tb-jump is not possible when singlestepping). * (and thus a tb-jump is not possible when singlestepping).
*/ */
assert(dc->is_jmp != DISAS_TB_JUMP); switch (dc->is_jmp) {
if (dc->is_jmp != DISAS_JUMP) { default:
gen_a64_set_pc_im(dc, dc->pc); gen_a64_set_pc_im(dc, dc->pc);
} /* fall through */
if (cs->singlestep_enabled) { case DISAS_JUMP:
gen_exception_internal(dc, EXCP_DEBUG); if (cs->singlestep_enabled) {
} else { gen_exception_internal(dc, EXCP_DEBUG);
gen_step_complete_exception(dc); } else {
gen_step_complete_exception(dc);
}
break;
case DISAS_NORETURN:
break;
} }
} else { } else {
switch (dc->is_jmp) { switch (dc->is_jmp) {
@ -11629,8 +11633,7 @@ tb_end:
case DISAS_JUMP: case DISAS_JUMP:
tcg_gen_lookup_and_goto_ptr(tcg_ctx, tcg_ctx->cpu_pc); tcg_gen_lookup_and_goto_ptr(tcg_ctx, tcg_ctx->cpu_pc);
break; break;
case DISAS_TB_JUMP: case DISAS_NORETURN:
case DISAS_EXC:
case DISAS_SWI: case DISAS_SWI:
break; break;
case DISAS_WFE: case DISAS_WFE:

View file

@ -291,7 +291,7 @@ static void gen_step_complete_exception(DisasContext *s)
gen_ss_advance(s); gen_ss_advance(s);
gen_exception(s, EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex), gen_exception(s, EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
default_exception_el(s)); default_exception_el(s));
s->is_jmp = DISAS_EXC; s->is_jmp = DISAS_NORETURN;
} }
static void gen_singlestep_exception(DisasContext *s) static void gen_singlestep_exception(DisasContext *s)
@ -1222,7 +1222,7 @@ static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
gen_set_condexec(s); gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset); gen_set_pc_im(s, s->pc - offset);
gen_exception_internal(s, excp); gen_exception_internal(s, excp);
s->is_jmp = DISAS_EXC; s->is_jmp = DISAS_NORETURN;
} }
static void gen_exception_insn(DisasContext *s, int offset, int excp, static void gen_exception_insn(DisasContext *s, int offset, int excp,
@ -1231,7 +1231,7 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
gen_set_condexec(s); gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset); gen_set_pc_im(s, s->pc - offset);
gen_exception(s, excp, syn, target_el); gen_exception(s, excp, syn, target_el);
s->is_jmp = DISAS_EXC; s->is_jmp = DISAS_NORETURN;
} }
/* Force a TB lookup after an instruction that changes the CPU state. */ /* Force a TB lookup after an instruction that changes the CPU state. */
@ -12194,7 +12194,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
/* We always get here via a jump, so know we are not in a /* We always get here via a jump, so know we are not in a
conditional execution block. */ conditional execution block. */
gen_exception_internal(dc, EXCP_KERNEL_TRAP); gen_exception_internal(dc, EXCP_KERNEL_TRAP);
dc->is_jmp = DISAS_EXC; dc->is_jmp = DISAS_NORETURN;
break; break;
} }
#endif #endif
@ -12353,6 +12353,9 @@ tb_end:
default: default:
/* FIXME: Single stepping a WFI insn will not halt the CPU. */ /* FIXME: Single stepping a WFI insn will not halt the CPU. */
gen_singlestep_exception(dc); gen_singlestep_exception(dc);
break;
case DISAS_NORETURN:
break;
} }
} else { } else {
/* While branches must always occur at the end of an IT block, /* While branches must always occur at the end of an IT block,
@ -12377,8 +12380,7 @@ tb_end:
/* indicate that the hash table must be used to find the next TB */ /* indicate that the hash table must be used to find the next TB */
tcg_gen_exit_tb(tcg_ctx, 0); tcg_gen_exit_tb(tcg_ctx, 0);
break; break;
case DISAS_TB_JUMP: case DISAS_NORETURN:
case DISAS_EXC:
/* nothing more to generate */ /* nothing more to generate */
break; break;
case DISAS_WFI: case DISAS_WFI:

View file

@ -123,12 +123,8 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
* defer them until after the conditional execution state has been updated. * defer them until after the conditional execution state has been updated.
* WFI also needs special handling when single-stepping. * WFI also needs special handling when single-stepping.
*/ */
#define DISAS_WFI 4 #define DISAS_WFI 5
#define DISAS_SWI 5 #define DISAS_SWI 6
/* For instructions which unconditionally cause an exception we can skip
* emitting unreachable code at the end of the TB in the A64 decoder
*/
#define DISAS_EXC 6
/* WFE */ /* WFE */
#define DISAS_WFE 7 #define DISAS_WFE 7
#define DISAS_HVC 8 #define DISAS_HVC 8