target/arm: Replace s->pc with s->base.pc_next

We must update s->base.pc_next when we return from the translate_insn
hook to the main translator loop.  By incrementing s->base.pc_next
immediately after reading the insn word, "pc_next" contains the address
of the next instruction throughout translation.

All remaining uses of s->pc are referencing the address of the next insn,
so this is now a simple global replacement.  Remove the "s->pc" field.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: 20190807045335.1361-7-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2019-08-15 09:46:44 +01:00 committed by Peter Maydell
parent 4818c3743b
commit a04159166b
3 changed files with 72 additions and 83 deletions

View File

@ -255,7 +255,7 @@ static void gen_exception_internal(int excp)
static void gen_exception_internal_insn(DisasContext *s, int offset, int excp) static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
{ {
gen_a64_set_pc_im(s->pc - offset); gen_a64_set_pc_im(s->base.pc_next - offset);
gen_exception_internal(excp); gen_exception_internal(excp);
s->base.is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
@ -263,7 +263,7 @@ static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
static void gen_exception_insn(DisasContext *s, int offset, int excp, static void gen_exception_insn(DisasContext *s, int offset, int excp,
uint32_t syndrome, uint32_t target_el) uint32_t syndrome, uint32_t target_el)
{ {
gen_a64_set_pc_im(s->pc - offset); gen_a64_set_pc_im(s->base.pc_next - offset);
gen_exception(excp, syndrome, target_el); gen_exception(excp, syndrome, target_el);
s->base.is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
@ -273,7 +273,7 @@ static void gen_exception_bkpt_insn(DisasContext *s, int offset,
{ {
TCGv_i32 tcg_syn; TCGv_i32 tcg_syn;
gen_a64_set_pc_im(s->pc - offset); gen_a64_set_pc_im(s->base.pc_next - offset);
tcg_syn = tcg_const_i32(syndrome); tcg_syn = tcg_const_i32(syndrome);
gen_helper_exception_bkpt_insn(cpu_env, tcg_syn); gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
tcg_temp_free_i32(tcg_syn); tcg_temp_free_i32(tcg_syn);
@ -1238,7 +1238,7 @@ static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
if (insn & (1U << 31)) { if (insn & (1U << 31)) {
/* BL Branch with link */ /* BL Branch with link */
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc); tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
} }
/* B Branch / BL Branch with link */ /* B Branch / BL Branch with link */
@ -1271,7 +1271,7 @@ static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ, tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
tcg_cmp, 0, label_match); tcg_cmp, 0, label_match);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
gen_set_label(label_match); gen_set_label(label_match);
gen_goto_tb(s, 1, addr); gen_goto_tb(s, 1, addr);
} }
@ -1302,7 +1302,7 @@ static void disas_test_b_imm(DisasContext *s, uint32_t insn)
tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ, tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
tcg_cmp, 0, label_match); tcg_cmp, 0, label_match);
tcg_temp_free_i64(tcg_cmp); tcg_temp_free_i64(tcg_cmp);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
gen_set_label(label_match); gen_set_label(label_match);
gen_goto_tb(s, 1, addr); gen_goto_tb(s, 1, addr);
} }
@ -1330,7 +1330,7 @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
/* genuinely conditional branches */ /* genuinely conditional branches */
TCGLabel *label_match = gen_new_label(); TCGLabel *label_match = gen_new_label();
arm_gen_test_cc(cond, label_match); arm_gen_test_cc(cond, label_match);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
gen_set_label(label_match); gen_set_label(label_match);
gen_goto_tb(s, 1, addr); gen_goto_tb(s, 1, addr);
} else { } else {
@ -1491,7 +1491,7 @@ static void handle_sync(DisasContext *s, uint32_t insn,
* any pending interrupts immediately. * any pending interrupts immediately.
*/ */
reset_btype(s); reset_btype(s);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
return; return;
case 7: /* SB */ case 7: /* SB */
@ -1503,7 +1503,7 @@ static void handle_sync(DisasContext *s, uint32_t insn,
* MB and end the TB instead. * MB and end the TB instead.
*/ */
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
return; return;
default: default:
@ -2015,7 +2015,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
gen_a64_set_pc(s, dst); gen_a64_set_pc(s, dst);
/* BLR also needs to load return address */ /* BLR also needs to load return address */
if (opc == 1) { if (opc == 1) {
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc); tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
} }
break; break;
@ -2042,7 +2042,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
gen_a64_set_pc(s, dst); gen_a64_set_pc(s, dst);
/* BLRAA also needs to load return address */ /* BLRAA also needs to load return address */
if (opc == 9) { if (opc == 9) {
tcg_gen_movi_i64(cpu_reg(s, 30), s->pc); tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
} }
break; break;
@ -14030,10 +14030,10 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{ {
uint32_t insn; uint32_t insn;
s->pc_curr = s->pc; s->pc_curr = s->base.pc_next;
insn = arm_ldl_code(env, s->pc, s->sctlr_b); insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
s->insn = insn; s->insn = insn;
s->pc += 4; s->base.pc_next += 4;
s->fp_access_checked = false; s->fp_access_checked = false;
@ -14130,7 +14130,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
int bound, core_mmu_idx; int bound, core_mmu_idx;
dc->isar = &arm_cpu->isar; dc->isar = &arm_cpu->isar;
dc->pc = dc->base.pc_first;
dc->condjmp = 0; dc->condjmp = 0;
dc->aarch64 = 1; dc->aarch64 = 1;
@ -14203,7 +14202,7 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{ {
DisasContext *dc = container_of(dcbase, DisasContext, base); DisasContext *dc = container_of(dcbase, DisasContext, base);
tcg_gen_insn_start(dc->pc, 0, 0); tcg_gen_insn_start(dc->base.pc_next, 0, 0);
dc->insn_start = tcg_last_op(); dc->insn_start = tcg_last_op();
} }
@ -14213,7 +14212,7 @@ static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
DisasContext *dc = container_of(dcbase, DisasContext, base); DisasContext *dc = container_of(dcbase, DisasContext, base);
if (bp->flags & BP_CPU) { if (bp->flags & BP_CPU) {
gen_a64_set_pc_im(dc->pc); gen_a64_set_pc_im(dc->base.pc_next);
gen_helper_check_breakpoints(cpu_env); gen_helper_check_breakpoints(cpu_env);
/* End the TB early; it likely won't be executed */ /* End the TB early; it likely won't be executed */
dc->base.is_jmp = DISAS_TOO_MANY; dc->base.is_jmp = DISAS_TOO_MANY;
@ -14224,7 +14223,7 @@ static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
to for it to be properly cleared -- thus we to for it to be properly cleared -- thus we
increment the PC here so that the logic setting increment the PC here so that the logic setting
tb->size below does the right thing. */ tb->size below does the right thing. */
dc->pc += 4; dc->base.pc_next += 4;
dc->base.is_jmp = DISAS_NORETURN; dc->base.is_jmp = DISAS_NORETURN;
} }
@ -14254,7 +14253,6 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
disas_a64_insn(env, dc); disas_a64_insn(env, dc);
} }
dc->base.pc_next = dc->pc;
translator_loop_temp_check(&dc->base); translator_loop_temp_check(&dc->base);
} }
@ -14270,7 +14268,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
*/ */
switch (dc->base.is_jmp) { switch (dc->base.is_jmp) {
default: default:
gen_a64_set_pc_im(dc->pc); gen_a64_set_pc_im(dc->base.pc_next);
/* fall through */ /* fall through */
case DISAS_EXIT: case DISAS_EXIT:
case DISAS_JUMP: case DISAS_JUMP:
@ -14287,11 +14285,11 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
switch (dc->base.is_jmp) { switch (dc->base.is_jmp) {
case DISAS_NEXT: case DISAS_NEXT:
case DISAS_TOO_MANY: case DISAS_TOO_MANY:
gen_goto_tb(dc, 1, dc->pc); gen_goto_tb(dc, 1, dc->base.pc_next);
break; break;
default: default:
case DISAS_UPDATE: case DISAS_UPDATE:
gen_a64_set_pc_im(dc->pc); gen_a64_set_pc_im(dc->base.pc_next);
/* fall through */ /* fall through */
case DISAS_EXIT: case DISAS_EXIT:
tcg_gen_exit_tb(NULL, 0); tcg_gen_exit_tb(NULL, 0);
@ -14303,11 +14301,11 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
case DISAS_SWI: case DISAS_SWI:
break; break;
case DISAS_WFE: case DISAS_WFE:
gen_a64_set_pc_im(dc->pc); gen_a64_set_pc_im(dc->base.pc_next);
gen_helper_wfe(cpu_env); gen_helper_wfe(cpu_env);
break; break;
case DISAS_YIELD: case DISAS_YIELD:
gen_a64_set_pc_im(dc->pc); gen_a64_set_pc_im(dc->base.pc_next);
gen_helper_yield(cpu_env); gen_helper_yield(cpu_env);
break; break;
case DISAS_WFI: case DISAS_WFI:
@ -14317,7 +14315,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
*/ */
TCGv_i32 tmp = tcg_const_i32(4); TCGv_i32 tmp = tcg_const_i32(4);
gen_a64_set_pc_im(dc->pc); gen_a64_set_pc_im(dc->base.pc_next);
gen_helper_wfi(cpu_env, tmp); gen_helper_wfi(cpu_env, tmp);
tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp);
/* The helper doesn't necessarily throw an exception, but we /* The helper doesn't necessarily throw an exception, but we
@ -14328,9 +14326,6 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
} }
} }
} }
/* Functions above can change dc->pc, so re-align db->pc_next */
dc->base.pc_next = dc->pc;
} }
static void aarch64_tr_disas_log(const DisasContextBase *dcbase, static void aarch64_tr_disas_log(const DisasContextBase *dcbase,

View File

@ -1036,7 +1036,7 @@ static inline void gen_blxns(DisasContext *s, int rm)
* We do however need to set the PC, because the blxns helper reads it. * We do however need to set the PC, because the blxns helper reads it.
* The blxns helper may throw an exception. * The blxns helper may throw an exception.
*/ */
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
gen_helper_v7m_blxns(cpu_env, var); gen_helper_v7m_blxns(cpu_env, var);
tcg_temp_free_i32(var); tcg_temp_free_i32(var);
s->base.is_jmp = DISAS_EXIT; s->base.is_jmp = DISAS_EXIT;
@ -1222,7 +1222,7 @@ static inline void gen_hvc(DisasContext *s, int imm16)
* for single stepping.) * for single stepping.)
*/ */
s->svc_imm = imm16; s->svc_imm = imm16;
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->base.is_jmp = DISAS_HVC; s->base.is_jmp = DISAS_HVC;
} }
@ -1237,14 +1237,14 @@ static inline void gen_smc(DisasContext *s)
tmp = tcg_const_i32(syn_aa32_smc()); tmp = tcg_const_i32(syn_aa32_smc());
gen_helper_pre_smc(cpu_env, tmp); gen_helper_pre_smc(cpu_env, tmp);
tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp);
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->base.is_jmp = DISAS_SMC; s->base.is_jmp = DISAS_SMC;
} }
static void gen_exception_internal_insn(DisasContext *s, int offset, int excp) 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->base.pc_next - offset);
gen_exception_internal(excp); gen_exception_internal(excp);
s->base.is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
@ -1253,7 +1253,7 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
int syn, uint32_t target_el) int syn, uint32_t target_el)
{ {
gen_set_condexec(s); gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset); gen_set_pc_im(s, s->base.pc_next - offset);
gen_exception(excp, syn, target_el); gen_exception(excp, syn, target_el);
s->base.is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
@ -1263,7 +1263,7 @@ static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
TCGv_i32 tcg_syn; TCGv_i32 tcg_syn;
gen_set_condexec(s); gen_set_condexec(s);
gen_set_pc_im(s, s->pc - offset); gen_set_pc_im(s, s->base.pc_next - offset);
tcg_syn = tcg_const_i32(syn); tcg_syn = tcg_const_i32(syn);
gen_helper_exception_bkpt_insn(cpu_env, tcg_syn); gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
tcg_temp_free_i32(tcg_syn); tcg_temp_free_i32(tcg_syn);
@ -1273,7 +1273,7 @@ static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
/* Force a TB lookup after an instruction that changes the CPU state. */ /* Force a TB lookup after an instruction that changes the CPU state. */
static inline void gen_lookup_tb(DisasContext *s) static inline void gen_lookup_tb(DisasContext *s)
{ {
tcg_gen_movi_i32(cpu_R[15], s->pc); tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
s->base.is_jmp = DISAS_EXIT; s->base.is_jmp = DISAS_EXIT;
} }
@ -2909,7 +2909,7 @@ static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
{ {
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) || return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
#else #else
return true; return true;
#endif #endif
@ -3279,17 +3279,17 @@ static void gen_nop_hint(DisasContext *s, int val)
*/ */
case 1: /* yield */ case 1: /* yield */
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) { if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->base.is_jmp = DISAS_YIELD; s->base.is_jmp = DISAS_YIELD;
} }
break; break;
case 3: /* wfi */ case 3: /* wfi */
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->base.is_jmp = DISAS_WFI; s->base.is_jmp = DISAS_WFI;
break; break;
case 2: /* wfe */ case 2: /* wfe */
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) { if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->base.is_jmp = DISAS_WFE; s->base.is_jmp = DISAS_WFE;
} }
break; break;
@ -7240,7 +7240,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
if (isread) { if (isread) {
return 1; return 1;
} }
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->base.is_jmp = DISAS_WFI; s->base.is_jmp = DISAS_WFI;
return 0; return 0;
default: default:
@ -7804,7 +7804,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
* self-modifying code correctly and also to take * self-modifying code correctly and also to take
* any pending interrupts immediately. * any pending interrupts immediately.
*/ */
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
return; return;
case 7: /* sb */ case 7: /* sb */
if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) { if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
@ -7815,7 +7815,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
* for TCG; MB and end the TB instead. * for TCG; MB and end the TB instead.
*/ */
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
return; return;
default: default:
goto illegal_op; goto illegal_op;
@ -7871,7 +7871,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
int32_t offset; int32_t offset;
tmp = tcg_temp_new_i32(); tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, s->pc); tcg_gen_movi_i32(tmp, s->base.pc_next);
store_reg(s, 14, tmp); store_reg(s, 14, tmp);
/* Sign-extend the 24-bit offset */ /* Sign-extend the 24-bit offset */
offset = (((int32_t)insn) << 8) >> 8; offset = (((int32_t)insn) << 8) >> 8;
@ -8056,7 +8056,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
/* branch link/exchange thumb (blx) */ /* branch link/exchange thumb (blx) */
tmp = load_reg(s, rm); tmp = load_reg(s, rm);
tmp2 = tcg_temp_new_i32(); tmp2 = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp2, s->pc); tcg_gen_movi_i32(tmp2, s->base.pc_next);
store_reg(s, 14, tmp2); store_reg(s, 14, tmp2);
gen_bx(s, tmp); gen_bx(s, tmp);
break; break;
@ -9222,7 +9222,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
/* branch (and link) */ /* branch (and link) */
if (insn & (1 << 24)) { if (insn & (1 << 24)) {
tmp = tcg_temp_new_i32(); tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, s->pc); tcg_gen_movi_i32(tmp, s->base.pc_next);
store_reg(s, 14, tmp); store_reg(s, 14, tmp);
} }
offset = sextract32(insn << 2, 0, 26); offset = sextract32(insn << 2, 0, 26);
@ -9244,7 +9244,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
break; break;
case 0xf: case 0xf:
/* swi */ /* swi */
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->svc_imm = extract32(insn, 0, 24); s->svc_imm = extract32(insn, 0, 24);
s->base.is_jmp = DISAS_SWI; s->base.is_jmp = DISAS_SWI;
break; break;
@ -10326,7 +10326,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
if (insn & (1 << 14)) { if (insn & (1 << 14)) {
/* Branch and link. */ /* Branch and link. */
tcg_gen_movi_i32(cpu_R[14], s->pc | 1); tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
} }
offset += read_pc(s); offset += read_pc(s);
@ -10449,7 +10449,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
* and also to take any pending interrupts * and also to take any pending interrupts
* immediately. * immediately.
*/ */
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
break; break;
case 7: /* sb */ case 7: /* sb */
if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) { if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
@ -10460,7 +10460,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
* for TCG; MB and end the TB instead. * for TCG; MB and end the TB instead.
*/ */
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
gen_goto_tb(s, 0, s->pc); gen_goto_tb(s, 0, s->base.pc_next);
break; break;
default: default:
goto illegal_op; goto illegal_op;
@ -11121,7 +11121,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
/* BLX/BX */ /* BLX/BX */
tmp = load_reg(s, rm); tmp = load_reg(s, rm);
if (link) { if (link) {
val = (uint32_t)s->pc | 1; val = (uint32_t)s->base.pc_next | 1;
tmp2 = tcg_temp_new_i32(); tmp2 = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp2, val); tcg_gen_movi_i32(tmp2, val);
store_reg(s, 14, tmp2); store_reg(s, 14, tmp2);
@ -11695,7 +11695,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
if (cond == 0xf) { if (cond == 0xf) {
/* swi */ /* swi */
gen_set_pc_im(s, s->pc); gen_set_pc_im(s, s->base.pc_next);
s->svc_imm = extract32(insn, 0, 8); s->svc_imm = extract32(insn, 0, 8);
s->base.is_jmp = DISAS_SWI; s->base.is_jmp = DISAS_SWI;
break; break;
@ -11724,7 +11724,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
tmp2 = tcg_temp_new_i32(); tmp2 = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp2, s->pc | 1); tcg_gen_movi_i32(tmp2, s->base.pc_next | 1);
store_reg(s, 14, tmp2); store_reg(s, 14, tmp2);
gen_bx(s, tmp); gen_bx(s, tmp);
break; break;
@ -11749,7 +11749,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
tcg_gen_addi_i32(tmp, tmp, offset); tcg_gen_addi_i32(tmp, tmp, offset);
tmp2 = tcg_temp_new_i32(); tmp2 = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp2, s->pc | 1); tcg_gen_movi_i32(tmp2, s->base.pc_next | 1);
store_reg(s, 14, tmp2); store_reg(s, 14, tmp2);
gen_bx(s, tmp); gen_bx(s, tmp);
} else { } else {
@ -11769,16 +11769,16 @@ undef:
static bool insn_crosses_page(CPUARMState *env, DisasContext *s) static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
{ {
/* Return true if the insn at dc->pc might cross a page boundary. /* Return true if the insn at dc->base.pc_next might cross a page boundary.
* (False positives are OK, false negatives are not.) * (False positives are OK, false negatives are not.)
* We know this is a Thumb insn, and our caller ensures we are * We know this is a Thumb insn, and our caller ensures we are
* only called if dc->pc is less than 4 bytes from the page * only called if dc->base.pc_next is less than 4 bytes from the page
* boundary, so we cross the page if the first 16 bits indicate * boundary, so we cross the page if the first 16 bits indicate
* that this is a 32 bit insn. * that this is a 32 bit insn.
*/ */
uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b); uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
return !thumb_insn_is_16bit(s, s->pc, insn); return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
} }
static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
@ -11790,7 +11790,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
uint32_t condexec, core_mmu_idx; uint32_t condexec, core_mmu_idx;
dc->isar = &cpu->isar; dc->isar = &cpu->isar;
dc->pc = dc->base.pc_first;
dc->condjmp = 0; dc->condjmp = 0;
dc->aarch64 = 0; dc->aarch64 = 0;
@ -11922,7 +11921,7 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{ {
DisasContext *dc = container_of(dcbase, DisasContext, base); DisasContext *dc = container_of(dcbase, DisasContext, base);
tcg_gen_insn_start(dc->pc, tcg_gen_insn_start(dc->base.pc_next,
(dc->condexec_cond << 4) | (dc->condexec_mask >> 1), (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
0); 0);
dc->insn_start = tcg_last_op(); dc->insn_start = tcg_last_op();
@ -11935,7 +11934,7 @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
if (bp->flags & BP_CPU) { if (bp->flags & BP_CPU) {
gen_set_condexec(dc); gen_set_condexec(dc);
gen_set_pc_im(dc, dc->pc); gen_set_pc_im(dc, dc->base.pc_next);
gen_helper_check_breakpoints(cpu_env); gen_helper_check_breakpoints(cpu_env);
/* End the TB early; it's likely not going to be executed */ /* End the TB early; it's likely not going to be executed */
dc->base.is_jmp = DISAS_TOO_MANY; dc->base.is_jmp = DISAS_TOO_MANY;
@ -11948,7 +11947,7 @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
tb->size below does the right thing. */ tb->size below does the right thing. */
/* TODO: Advance PC by correct instruction length to /* TODO: Advance PC by correct instruction length to
* avoid disassembler error messages */ * avoid disassembler error messages */
dc->pc += 2; dc->base.pc_next += 2;
dc->base.is_jmp = DISAS_NORETURN; dc->base.is_jmp = DISAS_NORETURN;
} }
@ -11959,7 +11958,7 @@ static bool arm_pre_translate_insn(DisasContext *dc)
{ {
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
/* Intercept jump to the magic kernel page. */ /* Intercept jump to the magic kernel page. */
if (dc->pc >= 0xffff0000) { if (dc->base.pc_next >= 0xffff0000) {
/* 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(EXCP_KERNEL_TRAP); gen_exception_internal(EXCP_KERNEL_TRAP);
@ -11994,7 +11993,6 @@ static void arm_post_translate_insn(DisasContext *dc)
gen_set_label(dc->condlabel); gen_set_label(dc->condlabel);
dc->condjmp = 0; dc->condjmp = 0;
} }
dc->base.pc_next = dc->pc;
translator_loop_temp_check(&dc->base); translator_loop_temp_check(&dc->base);
} }
@ -12008,10 +12006,10 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
return; return;
} }
dc->pc_curr = dc->pc; dc->pc_curr = dc->base.pc_next;
insn = arm_ldl_code(env, dc->pc, dc->sctlr_b); insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
dc->insn = insn; dc->insn = insn;
dc->pc += 4; dc->base.pc_next += 4;
disas_arm_insn(dc, insn); disas_arm_insn(dc, insn);
arm_post_translate_insn(dc); arm_post_translate_insn(dc);
@ -12077,15 +12075,15 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
return; return;
} }
dc->pc_curr = dc->pc; dc->pc_curr = dc->base.pc_next;
insn = arm_lduw_code(env, dc->pc, dc->sctlr_b); insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
is_16bit = thumb_insn_is_16bit(dc, dc->pc, insn); is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
dc->pc += 2; dc->base.pc_next += 2;
if (!is_16bit) { if (!is_16bit) {
uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b); uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
insn = insn << 16 | insn2; insn = insn << 16 | insn2;
dc->pc += 2; dc->base.pc_next += 2;
} }
dc->insn = insn; dc->insn = insn;
@ -12133,8 +12131,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
* but isn't very efficient). * but isn't very efficient).
*/ */
if (dc->base.is_jmp == DISAS_NEXT if (dc->base.is_jmp == DISAS_NEXT
&& (dc->pc - dc->page_start >= TARGET_PAGE_SIZE && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
|| (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
&& insn_crosses_page(env, dc)))) { && insn_crosses_page(env, dc)))) {
dc->base.is_jmp = DISAS_TOO_MANY; dc->base.is_jmp = DISAS_TOO_MANY;
} }
@ -12179,7 +12177,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
case DISAS_NEXT: case DISAS_NEXT:
case DISAS_TOO_MANY: case DISAS_TOO_MANY:
case DISAS_UPDATE: case DISAS_UPDATE:
gen_set_pc_im(dc, dc->pc); gen_set_pc_im(dc, dc->base.pc_next);
/* fall through */ /* fall through */
default: default:
/* FIXME: Single stepping a WFI insn will not halt the CPU. */ /* FIXME: Single stepping a WFI insn will not halt the CPU. */
@ -12200,13 +12198,13 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
switch(dc->base.is_jmp) { switch(dc->base.is_jmp) {
case DISAS_NEXT: case DISAS_NEXT:
case DISAS_TOO_MANY: case DISAS_TOO_MANY:
gen_goto_tb(dc, 1, dc->pc); gen_goto_tb(dc, 1, dc->base.pc_next);
break; break;
case DISAS_JUMP: case DISAS_JUMP:
gen_goto_ptr(); gen_goto_ptr();
break; break;
case DISAS_UPDATE: case DISAS_UPDATE:
gen_set_pc_im(dc, dc->pc); gen_set_pc_im(dc, dc->base.pc_next);
/* fall through */ /* fall through */
default: default:
/* 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 */
@ -12252,15 +12250,12 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_set_label(dc->condlabel); gen_set_label(dc->condlabel);
gen_set_condexec(dc); gen_set_condexec(dc);
if (unlikely(is_singlestepping(dc))) { if (unlikely(is_singlestepping(dc))) {
gen_set_pc_im(dc, dc->pc); gen_set_pc_im(dc, dc->base.pc_next);
gen_singlestep_exception(dc); gen_singlestep_exception(dc);
} else { } else {
gen_goto_tb(dc, 1, dc->pc); gen_goto_tb(dc, 1, dc->base.pc_next);
} }
} }
/* Functions above can change dc->pc, so re-align db->pc_next */
dc->base.pc_next = dc->pc;
} }
static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)

View File

@ -10,7 +10,6 @@ typedef struct DisasContext {
DisasContextBase base; DisasContextBase base;
const ARMISARegisters *isar; const ARMISARegisters *isar;
target_ulong pc;
/* The address of the current instruction being translated. */ /* The address of the current instruction being translated. */
target_ulong pc_curr; target_ulong pc_curr;
target_ulong page_start; target_ulong page_start;