target/sparc: Introduce DYNAMIC_PC_LOOKUP
Create a new artificial "next pc" which also indicates that nothing has changed within the cpu state which requires returning to the main loop. Pipe this new value though all pc/npc checks. Do not produce this new value yet. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230628071202.230991-5-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
This commit is contained in:
parent
0c2e96c170
commit
633c42834c
@ -37,9 +37,12 @@
|
||||
#include "exec/helper-info.c.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#define DYNAMIC_PC 1 /* dynamic pc value */
|
||||
#define JUMP_PC 2 /* dynamic pc value which takes only two values
|
||||
according to jump_pc[T2] */
|
||||
/* Dynamic PC, must exit to main loop. */
|
||||
#define DYNAMIC_PC 1
|
||||
/* Dynamic PC, one of two values according to jump_pc[T2]. */
|
||||
#define JUMP_PC 2
|
||||
/* Dynamic PC, may lookup next TB. */
|
||||
#define DYNAMIC_PC_LOOKUP 3
|
||||
|
||||
#define DISAS_EXIT DISAS_TARGET_0
|
||||
|
||||
@ -901,22 +904,25 @@ static void gen_branch_n(DisasContext *dc, target_ulong pc1)
|
||||
{
|
||||
target_ulong npc = dc->npc;
|
||||
|
||||
if (likely(npc != DYNAMIC_PC)) {
|
||||
if (npc & 3) {
|
||||
switch (npc) {
|
||||
case DYNAMIC_PC:
|
||||
case DYNAMIC_PC_LOOKUP:
|
||||
tcg_gen_mov_tl(cpu_pc, cpu_npc);
|
||||
tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc,
|
||||
cpu_cond, tcg_constant_tl(0),
|
||||
tcg_constant_tl(pc1), cpu_npc);
|
||||
dc->pc = npc;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
} else {
|
||||
dc->pc = npc;
|
||||
dc->jump_pc[0] = pc1;
|
||||
dc->jump_pc[1] = npc + 4;
|
||||
dc->npc = JUMP_PC;
|
||||
} else {
|
||||
TCGv t, z;
|
||||
|
||||
tcg_gen_mov_tl(cpu_pc, cpu_npc);
|
||||
|
||||
tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
|
||||
t = tcg_constant_tl(pc1);
|
||||
z = tcg_constant_tl(0);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc);
|
||||
|
||||
dc->pc = DYNAMIC_PC;
|
||||
}
|
||||
}
|
||||
|
||||
@ -941,10 +947,19 @@ static void flush_cond(DisasContext *dc)
|
||||
|
||||
static void save_npc(DisasContext *dc)
|
||||
{
|
||||
if (dc->npc == JUMP_PC) {
|
||||
gen_generic_branch(dc);
|
||||
dc->npc = DYNAMIC_PC;
|
||||
} else if (dc->npc != DYNAMIC_PC) {
|
||||
if (dc->npc & 3) {
|
||||
switch (dc->npc) {
|
||||
case JUMP_PC:
|
||||
gen_generic_branch(dc);
|
||||
dc->npc = DYNAMIC_PC;
|
||||
break;
|
||||
case DYNAMIC_PC:
|
||||
case DYNAMIC_PC_LOOKUP:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_npc, dc->npc);
|
||||
}
|
||||
}
|
||||
@ -977,13 +992,21 @@ static void gen_check_align(TCGv addr, int mask)
|
||||
|
||||
static void gen_mov_pc_npc(DisasContext *dc)
|
||||
{
|
||||
if (dc->npc == JUMP_PC) {
|
||||
gen_generic_branch(dc);
|
||||
tcg_gen_mov_tl(cpu_pc, cpu_npc);
|
||||
dc->pc = DYNAMIC_PC;
|
||||
} else if (dc->npc == DYNAMIC_PC) {
|
||||
tcg_gen_mov_tl(cpu_pc, cpu_npc);
|
||||
dc->pc = DYNAMIC_PC;
|
||||
if (dc->npc & 3) {
|
||||
switch (dc->npc) {
|
||||
case JUMP_PC:
|
||||
gen_generic_branch(dc);
|
||||
tcg_gen_mov_tl(cpu_pc, cpu_npc);
|
||||
dc->pc = DYNAMIC_PC;
|
||||
break;
|
||||
case DYNAMIC_PC:
|
||||
case DYNAMIC_PC_LOOKUP:
|
||||
tcg_gen_mov_tl(cpu_pc, cpu_npc);
|
||||
dc->pc = dc->npc;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
} else {
|
||||
dc->pc = dc->npc;
|
||||
}
|
||||
@ -5501,13 +5524,21 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
|
||||
break;
|
||||
}
|
||||
/* default case for non jump instructions */
|
||||
if (dc->npc == DYNAMIC_PC) {
|
||||
dc->pc = DYNAMIC_PC;
|
||||
gen_op_next_insn();
|
||||
} else if (dc->npc == JUMP_PC) {
|
||||
/* we can do a static jump */
|
||||
gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
|
||||
dc->base.is_jmp = DISAS_NORETURN;
|
||||
if (dc->npc & 3) {
|
||||
switch (dc->npc) {
|
||||
case DYNAMIC_PC:
|
||||
case DYNAMIC_PC_LOOKUP:
|
||||
dc->pc = dc->npc;
|
||||
gen_op_next_insn();
|
||||
break;
|
||||
case JUMP_PC:
|
||||
/* we can do a static jump */
|
||||
gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond);
|
||||
dc->base.is_jmp = DISAS_NORETURN;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
} else {
|
||||
dc->pc = dc->npc;
|
||||
dc->npc = dc->npc + 4;
|
||||
@ -5578,13 +5609,23 @@ static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
|
||||
static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||
target_ulong npc = dc->npc;
|
||||
|
||||
if (dc->npc == JUMP_PC) {
|
||||
assert(dc->jump_pc[1] == dc->pc + 4);
|
||||
tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC);
|
||||
} else {
|
||||
tcg_gen_insn_start(dc->pc, dc->npc);
|
||||
if (npc & 3) {
|
||||
switch (npc) {
|
||||
case JUMP_PC:
|
||||
assert(dc->jump_pc[1] == dc->pc + 4);
|
||||
npc = dc->jump_pc[0] | JUMP_PC;
|
||||
break;
|
||||
case DYNAMIC_PC:
|
||||
case DYNAMIC_PC_LOOKUP:
|
||||
npc = DYNAMIC_PC;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
tcg_gen_insn_start(dc->pc, npc);
|
||||
}
|
||||
|
||||
static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
@ -5608,19 +5649,37 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||
bool may_lookup;
|
||||
|
||||
switch (dc->base.is_jmp) {
|
||||
case DISAS_NEXT:
|
||||
case DISAS_TOO_MANY:
|
||||
if (dc->pc != DYNAMIC_PC &&
|
||||
(dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
|
||||
if (((dc->pc | dc->npc) & 3) == 0) {
|
||||
/* static PC and NPC: we can use direct chaining */
|
||||
gen_goto_tb(dc, 0, dc->pc, dc->npc);
|
||||
} else {
|
||||
if (dc->pc != DYNAMIC_PC) {
|
||||
tcg_gen_movi_tl(cpu_pc, dc->pc);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dc->pc & 3) {
|
||||
switch (dc->pc) {
|
||||
case DYNAMIC_PC_LOOKUP:
|
||||
may_lookup = true;
|
||||
break;
|
||||
case DYNAMIC_PC:
|
||||
may_lookup = false;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
save_npc(dc);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_pc, dc->pc);
|
||||
may_lookup = true;
|
||||
}
|
||||
|
||||
save_npc(dc);
|
||||
if (may_lookup) {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
} else {
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user