target/openrisc: Link more translation blocks
Track direct jumps via dc->jmp_pc_imm. Use that in preference to jmp_pc when possible. Emit goto_tb in that case, and lookup_and_goto_tb otherwise. Reviewed-by: Stafford Horne <shorne@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Stafford Horne <shorne@gmail.com>
This commit is contained in:
parent
e0a369cf88
commit
8000ba56cc
|
@ -38,13 +38,16 @@
|
|||
|
||||
/* is_jmp field values */
|
||||
#define DISAS_EXIT DISAS_TARGET_0 /* force exit to main loop */
|
||||
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
|
||||
#define DISAS_JUMP DISAS_TARGET_1 /* exit via jmp_pc/jmp_pc_imm */
|
||||
|
||||
typedef struct DisasContext {
|
||||
DisasContextBase base;
|
||||
uint32_t mem_idx;
|
||||
uint32_t tb_flags;
|
||||
uint32_t delayed_branch;
|
||||
|
||||
/* If not -1, jmp_pc contains this value and so is a direct jump. */
|
||||
target_ulong jmp_pc_imm;
|
||||
} DisasContext;
|
||||
|
||||
/* Include the auto-generated decoder. */
|
||||
|
@ -160,34 +163,6 @@ static void check_ov64s(DisasContext *dc)
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
|
||||
{
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
{
|
||||
if (use_goto_tb(dc, dest)) {
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_exit_tb(dc->base.tb, n);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
if (dc->base.singlestep_enabled) {
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
}
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_ove_cy(DisasContext *dc)
|
||||
{
|
||||
if (dc->tb_flags & SR_OVE) {
|
||||
|
@ -621,6 +596,7 @@ static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn)
|
|||
target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
|
||||
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
dc->jmp_pc_imm = tmp_pc;
|
||||
dc->delayed_branch = 2;
|
||||
return true;
|
||||
}
|
||||
|
@ -634,6 +610,7 @@ static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn)
|
|||
/* Optimize jal being used to load the PC for PIC. */
|
||||
if (tmp_pc != ret_pc) {
|
||||
tcg_gen_movi_tl(jmp_pc, tmp_pc);
|
||||
dc->jmp_pc_imm = tmp_pc;
|
||||
dc->delayed_branch = 2;
|
||||
}
|
||||
return true;
|
||||
|
@ -1267,6 +1244,8 @@ static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
|
|||
dc->mem_idx = cpu_mmu_index(env, false);
|
||||
dc->tb_flags = dc->base.tb->flags;
|
||||
dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
|
||||
dc->jmp_pc_imm = -1;
|
||||
|
||||
bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
|
||||
dc->base.max_insns = MIN(dc->base.max_insns, bound);
|
||||
}
|
||||
|
@ -1319,37 +1298,72 @@ static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
|||
}
|
||||
dc->base.pc_next += 4;
|
||||
|
||||
/* delay slot */
|
||||
if (dc->delayed_branch) {
|
||||
dc->delayed_branch--;
|
||||
if (!dc->delayed_branch) {
|
||||
tcg_gen_mov_tl(cpu_pc, jmp_pc);
|
||||
tcg_gen_discard_tl(jmp_pc);
|
||||
dc->base.is_jmp = DISAS_UPDATE;
|
||||
return;
|
||||
}
|
||||
/* When exiting the delay slot normally, exit via jmp_pc.
|
||||
* For DISAS_NORETURN, we have raised an exception and already exited.
|
||||
* For DISAS_EXIT, we found l.rfe in a delay slot. There's nothing
|
||||
* in the manual saying this is illegal, but it surely it should.
|
||||
* At least or1ksim overrides pcnext and ignores the branch.
|
||||
*/
|
||||
if (dc->delayed_branch
|
||||
&& --dc->delayed_branch == 0
|
||||
&& dc->base.is_jmp == DISAS_NEXT) {
|
||||
dc->base.is_jmp = DISAS_JUMP;
|
||||
}
|
||||
}
|
||||
|
||||
static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||
target_ulong jmp_dest;
|
||||
|
||||
/* If we have already exited the TB, nothing following has effect. */
|
||||
if (dc->base.is_jmp == DISAS_NORETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Adjust the delayed branch state for the next TB. */
|
||||
if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
|
||||
tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
|
||||
}
|
||||
|
||||
tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4);
|
||||
/* For DISAS_TOO_MANY, jump to the next insn. */
|
||||
jmp_dest = dc->base.pc_next;
|
||||
tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
|
||||
|
||||
switch (dc->base.is_jmp) {
|
||||
case DISAS_JUMP:
|
||||
jmp_dest = dc->jmp_pc_imm;
|
||||
if (jmp_dest == -1) {
|
||||
/* The jump destination is indirect/computed; use jmp_pc. */
|
||||
tcg_gen_mov_tl(cpu_pc, jmp_pc);
|
||||
tcg_gen_discard_tl(jmp_pc);
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
} else {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* The jump destination is direct; use jmp_pc_imm.
|
||||
However, we will have stored into jmp_pc as well;
|
||||
we know now that it wasn't needed. */
|
||||
tcg_gen_discard_tl(jmp_pc);
|
||||
/* fallthru */
|
||||
|
||||
case DISAS_TOO_MANY:
|
||||
gen_goto_tb(dc, 0, dc->base.pc_next);
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
} else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
} else {
|
||||
tcg_gen_goto_tb(0);
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
tcg_gen_exit_tb(dc->base.tb, 0);
|
||||
}
|
||||
break;
|
||||
case DISAS_UPDATE:
|
||||
|
||||
case DISAS_EXIT:
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
|
|
Loading…
Reference in a new issue