target/nios2: Add DisasContextBase to DisasContext
Migrate the is_jmp, tb and singlestep_enabled fields from DisasContext into the base. Use pc_first instead of tb->pc. Increment pc_next prior to decode, leaving the address of the current insn in dc->pc. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
438aabed0a
commit
e9150ea523
@ -97,12 +97,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct DisasContext {
|
typedef struct DisasContext {
|
||||||
|
DisasContextBase base;
|
||||||
TCGv_i32 zero;
|
TCGv_i32 zero;
|
||||||
int is_jmp;
|
|
||||||
target_ulong pc;
|
target_ulong pc;
|
||||||
TranslationBlock *tb;
|
|
||||||
int mem_idx;
|
int mem_idx;
|
||||||
bool singlestep_enabled;
|
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
static TCGv cpu_R[NUM_CORE_REGS];
|
static TCGv cpu_R[NUM_CORE_REGS];
|
||||||
@ -149,17 +147,17 @@ static void t_gen_helper_raise_exception(DisasContext *dc,
|
|||||||
tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
|
tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
|
||||||
gen_helper_raise_exception(cpu_env, tmp);
|
gen_helper_raise_exception(cpu_env, tmp);
|
||||||
tcg_temp_free_i32(tmp);
|
tcg_temp_free_i32(tmp);
|
||||||
dc->is_jmp = DISAS_NORETURN;
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool use_goto_tb(DisasContext *dc, uint32_t dest)
|
static bool use_goto_tb(DisasContext *dc, uint32_t dest)
|
||||||
{
|
{
|
||||||
if (unlikely(dc->singlestep_enabled)) {
|
if (unlikely(dc->base.singlestep_enabled)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
return (dc->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -167,7 +165,7 @@ static bool use_goto_tb(DisasContext *dc, uint32_t dest)
|
|||||||
|
|
||||||
static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
|
static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
|
||||||
{
|
{
|
||||||
TranslationBlock *tb = dc->tb;
|
const TranslationBlock *tb = dc->base.tb;
|
||||||
|
|
||||||
if (use_goto_tb(dc, dest)) {
|
if (use_goto_tb(dc, dest)) {
|
||||||
tcg_gen_goto_tb(n);
|
tcg_gen_goto_tb(n);
|
||||||
@ -186,7 +184,7 @@ static void gen_excp(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
|
|
||||||
static void gen_check_supervisor(DisasContext *dc)
|
static void gen_check_supervisor(DisasContext *dc)
|
||||||
{
|
{
|
||||||
if (dc->tb->flags & CR_STATUS_U) {
|
if (dc->base.tb->flags & CR_STATUS_U) {
|
||||||
/* CPU in user mode, privileged instruction called, stop. */
|
/* CPU in user mode, privileged instruction called, stop. */
|
||||||
t_gen_helper_raise_exception(dc, EXCP_SUPERI);
|
t_gen_helper_raise_exception(dc, EXCP_SUPERI);
|
||||||
}
|
}
|
||||||
@ -208,7 +206,7 @@ static void jmpi(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
{
|
{
|
||||||
J_TYPE(instr, code);
|
J_TYPE(instr, code);
|
||||||
gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr.imm26 << 2));
|
gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr.imm26 << 2));
|
||||||
dc->is_jmp = DISAS_NORETURN;
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void call(DisasContext *dc, uint32_t code, uint32_t flags)
|
static void call(DisasContext *dc, uint32_t code, uint32_t flags)
|
||||||
@ -268,7 +266,7 @@ static void br(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
I_TYPE(instr, code);
|
I_TYPE(instr, code);
|
||||||
|
|
||||||
gen_goto_tb(dc, 0, dc->pc + 4 + (instr.imm16.s & -4));
|
gen_goto_tb(dc, 0, dc->pc + 4 + (instr.imm16.s & -4));
|
||||||
dc->is_jmp = DISAS_NORETURN;
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
|
static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
|
||||||
@ -280,7 +278,7 @@ static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
gen_goto_tb(dc, 0, dc->pc + 4);
|
gen_goto_tb(dc, 0, dc->pc + 4);
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
gen_goto_tb(dc, 1, dc->pc + 4 + (instr.imm16.s & -4));
|
gen_goto_tb(dc, 1, dc->pc + 4 + (instr.imm16.s & -4));
|
||||||
dc->is_jmp = DISAS_NORETURN;
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Comparison instructions */
|
/* Comparison instructions */
|
||||||
@ -402,7 +400,7 @@ static void eret(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
tcg_gen_mov_tl(cpu_R[CR_STATUS], cpu_R[CR_ESTATUS]);
|
tcg_gen_mov_tl(cpu_R[CR_STATUS], cpu_R[CR_ESTATUS]);
|
||||||
tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_EA]);
|
tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_EA]);
|
||||||
|
|
||||||
dc->is_jmp = DISAS_JUMP;
|
dc->base.is_jmp = DISAS_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PC <- ra */
|
/* PC <- ra */
|
||||||
@ -410,7 +408,7 @@ static void ret(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
{
|
{
|
||||||
tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_RA]);
|
tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_RA]);
|
||||||
|
|
||||||
dc->is_jmp = DISAS_JUMP;
|
dc->base.is_jmp = DISAS_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PC <- ba */
|
/* PC <- ba */
|
||||||
@ -418,7 +416,7 @@ static void bret(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
{
|
{
|
||||||
tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_BA]);
|
tcg_gen_mov_tl(cpu_R[R_PC], cpu_R[R_BA]);
|
||||||
|
|
||||||
dc->is_jmp = DISAS_JUMP;
|
dc->base.is_jmp = DISAS_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PC <- rA */
|
/* PC <- rA */
|
||||||
@ -428,7 +426,7 @@ static void jmp(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
|
|
||||||
tcg_gen_mov_tl(cpu_R[R_PC], load_gpr(dc, instr.a));
|
tcg_gen_mov_tl(cpu_R[R_PC], load_gpr(dc, instr.a));
|
||||||
|
|
||||||
dc->is_jmp = DISAS_JUMP;
|
dc->base.is_jmp = DISAS_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rC <- PC + 4 */
|
/* rC <- PC + 4 */
|
||||||
@ -452,7 +450,7 @@ static void callr(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
tcg_gen_mov_tl(cpu_R[R_PC], load_gpr(dc, instr.a));
|
tcg_gen_mov_tl(cpu_R[R_PC], load_gpr(dc, instr.a));
|
||||||
tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
|
tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
|
||||||
|
|
||||||
dc->is_jmp = DISAS_JUMP;
|
dc->base.is_jmp = DISAS_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rC <- ctlN */
|
/* rC <- ctlN */
|
||||||
@ -516,11 +514,11 @@ static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||||||
/* If interrupts were enabled using WRCTL, trigger them. */
|
/* If interrupts were enabled using WRCTL, trigger them. */
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
if ((instr.imm5 + CR_BASE) == CR_STATUS) {
|
if ((instr.imm5 + CR_BASE) == CR_STATUS) {
|
||||||
if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
|
if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
|
||||||
gen_io_start();
|
gen_io_start();
|
||||||
}
|
}
|
||||||
gen_helper_check_interrupts(cpu_env);
|
gen_helper_check_interrupts(cpu_env);
|
||||||
dc->is_jmp = DISAS_UPDATE;
|
dc->base.is_jmp = DISAS_UPDATE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -801,7 +799,7 @@ static void gen_exception(DisasContext *dc, uint32_t excp)
|
|||||||
tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
|
tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
|
||||||
gen_helper_raise_exception(cpu_env, tmp);
|
gen_helper_raise_exception(cpu_env, tmp);
|
||||||
tcg_temp_free_i32(tmp);
|
tcg_temp_free_i32(tmp);
|
||||||
dc->is_jmp = DISAS_NORETURN;
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
@ -812,11 +810,14 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
|||||||
int num_insns;
|
int num_insns;
|
||||||
|
|
||||||
/* Initialize DC */
|
/* Initialize DC */
|
||||||
dc->is_jmp = DISAS_NEXT;
|
|
||||||
dc->pc = tb->pc;
|
dc->base.tb = tb;
|
||||||
dc->tb = tb;
|
dc->base.singlestep_enabled = cs->singlestep_enabled;
|
||||||
|
dc->base.is_jmp = DISAS_NEXT;
|
||||||
|
dc->base.pc_first = tb->pc;
|
||||||
|
dc->base.pc_next = tb->pc;
|
||||||
|
|
||||||
dc->mem_idx = cpu_mmu_index(env, false);
|
dc->mem_idx = cpu_mmu_index(env, false);
|
||||||
dc->singlestep_enabled = cs->singlestep_enabled;
|
|
||||||
|
|
||||||
/* Set up instruction counts */
|
/* Set up instruction counts */
|
||||||
num_insns = 0;
|
num_insns = 0;
|
||||||
@ -829,10 +830,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
|||||||
|
|
||||||
gen_tb_start(tb);
|
gen_tb_start(tb);
|
||||||
do {
|
do {
|
||||||
tcg_gen_insn_start(dc->pc);
|
tcg_gen_insn_start(dc->base.pc_next);
|
||||||
num_insns++;
|
num_insns++;
|
||||||
|
|
||||||
if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
|
if (unlikely(cpu_breakpoint_test(cs, dc->base.pc_next, BP_ANY))) {
|
||||||
gen_exception(dc, EXCP_DEBUG);
|
gen_exception(dc, EXCP_DEBUG);
|
||||||
/* The address covered by the breakpoint must be included in
|
/* The address covered by the breakpoint must be included in
|
||||||
[tb->pc, tb->pc + tb->size) in order to for it to be
|
[tb->pc, tb->pc + tb->size) in order to for it to be
|
||||||
@ -846,25 +847,26 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
|||||||
gen_io_start();
|
gen_io_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc->pc = dc->base.pc_next;
|
||||||
|
dc->base.pc_next += 4;
|
||||||
|
|
||||||
/* Decode an instruction */
|
/* Decode an instruction */
|
||||||
handle_instruction(dc, env);
|
handle_instruction(dc, env);
|
||||||
|
|
||||||
dc->pc += 4;
|
|
||||||
|
|
||||||
/* Translation stops when a conditional branch is encountered.
|
/* Translation stops when a conditional branch is encountered.
|
||||||
* Otherwise the subsequent code could get translated several times.
|
* Otherwise the subsequent code could get translated several times.
|
||||||
* Also stop translation when a page boundary is reached. This
|
* Also stop translation when a page boundary is reached. This
|
||||||
* ensures prefetch aborts occur at the right place. */
|
* ensures prefetch aborts occur at the right place. */
|
||||||
} while (!dc->is_jmp &&
|
} while (!dc->base.is_jmp &&
|
||||||
!tcg_op_buf_full() &&
|
!tcg_op_buf_full() &&
|
||||||
num_insns < max_insns);
|
num_insns < max_insns);
|
||||||
|
|
||||||
/* Indicate where the next block should start */
|
/* Indicate where the next block should start */
|
||||||
switch (dc->is_jmp) {
|
switch (dc->base.is_jmp) {
|
||||||
case DISAS_NEXT:
|
case DISAS_NEXT:
|
||||||
case DISAS_UPDATE:
|
case DISAS_UPDATE:
|
||||||
/* Save the current PC back into the CPU register */
|
/* Save the current PC back into the CPU register */
|
||||||
tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
|
tcg_gen_movi_tl(cpu_R[R_PC], dc->base.pc_next);
|
||||||
tcg_gen_exit_tb(NULL, 0);
|
tcg_gen_exit_tb(NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -883,15 +885,15 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
|||||||
gen_tb_end(tb, num_insns);
|
gen_tb_end(tb, num_insns);
|
||||||
|
|
||||||
/* Mark instruction starts for the final generated instruction */
|
/* Mark instruction starts for the final generated instruction */
|
||||||
tb->size = dc->pc - tb->pc;
|
tb->size = dc->base.pc_next - dc->base.pc_first;
|
||||||
tb->icount = num_insns;
|
tb->icount = num_insns;
|
||||||
|
|
||||||
#ifdef DEBUG_DISAS
|
#ifdef DEBUG_DISAS
|
||||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||||
&& qemu_log_in_addr_range(tb->pc)) {
|
&& qemu_log_in_addr_range(dc->base.pc_first)) {
|
||||||
FILE *logfile = qemu_log_lock();
|
FILE *logfile = qemu_log_lock();
|
||||||
qemu_log("IN: %s\n", lookup_symbol(tb->pc));
|
qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
|
||||||
log_target_disas(cs, tb->pc, dc->pc - tb->pc);
|
log_target_disas(cs, tb->pc, tb->size);
|
||||||
qemu_log("\n");
|
qemu_log("\n");
|
||||||
qemu_log_unlock(logfile);
|
qemu_log_unlock(logfile);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user