Since jump_pc[1] is always npc + 4, and since we only continue translation when pc + 4 == npc, we can infer that jump_pc[1] == pc + 8.
Because of that, we can encode the branch destination into a single word, and store that in npc. Signed-off-by: Richard Henderson <r...@twiddle.net> --- target-sparc/translate.c | 50 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 8aa19e1..b1e533f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -39,7 +39,7 @@ #define DYNAMIC_PC 1 /* dynamic pc value */ #define JUMP_PC 2 /* dynamic pc value which takes only two values - according to jump_pc[T2] */ + according to npc & ~3 and pc + 4. */ /* global register indexes */ static TCGv_ptr cpu_env, cpu_regwptr; @@ -65,14 +65,12 @@ static TCGv cpu_wim; static TCGv_i64 cpu_fpr[TARGET_DPREGS]; static target_ulong gen_opc_npc[OPC_BUF_SIZE]; -static target_ulong gen_opc_jump_pc[2]; #include "exec/gen-icount.h" typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ - target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ int is_br; int mem_idx; int fpu_enabled; @@ -976,9 +974,7 @@ static void gen_branch_n(DisasContext *dc, target_ulong pc1) if (likely(npc != DYNAMIC_PC)) { dc->pc = npc; - dc->jump_pc[0] = pc1; - dc->jump_pc[1] = npc + 4; - dc->npc = JUMP_PC; + dc->npc = pc1 | JUMP_PC; } else { TCGv t, z; @@ -997,12 +993,15 @@ static void gen_branch_n(DisasContext *dc, target_ulong pc1) static inline void gen_generic_branch(DisasContext *dc) { - TCGv npc0 = tcg_const_tl(dc->jump_pc[0]); - TCGv npc1 = tcg_const_tl(dc->jump_pc[1]); - TCGv zero = tcg_const_tl(0); + TCGv npc0, npc1, zero; - tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1); + assert((dc->npc & 3) == JUMP_PC); + assert((dc->pc & 3) == 0); + npc0 = tcg_const_tl(dc->npc & ~3); + npc1 = tcg_const_tl(dc->pc + 4); + zero = tcg_const_tl(0); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1); tcg_temp_free(npc0); tcg_temp_free(npc1); tcg_temp_free(zero); @@ -1012,7 +1011,7 @@ static inline void gen_generic_branch(DisasContext *dc) have been set for a jump */ static inline void flush_cond(DisasContext *dc) { - if (dc->npc == JUMP_PC) { + if (dc->npc & JUMP_PC) { gen_generic_branch(dc); dc->npc = DYNAMIC_PC; } @@ -1020,7 +1019,7 @@ static inline void flush_cond(DisasContext *dc) static inline void save_npc(DisasContext *dc) { - if (dc->npc == JUMP_PC) { + if (dc->npc & JUMP_PC) { gen_generic_branch(dc); dc->npc = DYNAMIC_PC; } else if (dc->npc != DYNAMIC_PC) { @@ -1044,7 +1043,7 @@ static inline void save_state(DisasContext *dc) static inline void gen_mov_pc_npc(DisasContext *dc) { - if (dc->npc == JUMP_PC) { + if (dc->npc & JUMP_PC) { gen_generic_branch(dc); tcg_gen_mov_tl(cpu_pc, cpu_npc); dc->pc = DYNAMIC_PC; @@ -5122,9 +5121,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) 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); + } else if (dc->npc & JUMP_PC) { + assert((dc->pc & 3) == 0); + gen_branch2(dc, dc->npc & ~3, dc->pc + 4, cpu_cond); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -5324,8 +5323,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, #if 0 log_page_dump(); #endif - gen_opc_jump_pc[0] = dc->jump_pc[0]; - gen_opc_jump_pc[1] = dc->jump_pc[1]; } else { tb->size = last_pc + 4 - pc_start; tb->icount = num_insns; @@ -5453,17 +5450,18 @@ void gen_intermediate_code_init(CPUSPARCState *env) void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos) { - target_ulong npc; - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + target_ulong pc, npc; + + env->pc = pc = tcg_ctx.gen_opc_pc[pc_pos]; npc = gen_opc_npc[pc_pos]; - if (npc == 1) { - /* dynamic NPC: already stored */ - } else if (npc == 2) { - /* jump PC: use 'cond' and the jump targets of the translation */ + if (npc == DYNAMIC_PC) { + /* already stored */ + } else if (npc & JUMP_PC) { + /* use 'cond' and the jump targets of the translation */ if (env->cond) { - env->npc = gen_opc_jump_pc[0]; + env->npc = npc & ~3; } else { - env->npc = gen_opc_jump_pc[1]; + env->npc = pc + 8; } } else { env->npc = npc; -- 2.4.3