diff options
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 83 |
1 files changed, 26 insertions, 57 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 84a21ace54..22c35877e5 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -52,7 +52,6 @@ #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) #include "translate.h" -static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE]; #if defined(CONFIG_USER_ONLY) #define IS_USER(s) 1 @@ -11168,17 +11167,12 @@ undef: } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for - basic block 'tb'. If search_pc is TRUE, also generate PC - information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(ARMCPU *cpu, - TranslationBlock *tb, - bool search_pc) + basic block 'tb'. */ +void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) { + ARMCPU *cpu = arm_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; - int j, lj; target_ulong pc_start; target_ulong next_page_start; int num_insns; @@ -11190,7 +11184,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * the A32/T32 complexity to do with conditional execution/IT blocks/etc. */ if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) { - gen_intermediate_code_internal_a64(cpu, tb, search_pc); + gen_intermediate_code_a64(cpu, tb); return; } @@ -11256,11 +11250,14 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, /* FIXME: cpu_M0 can probably be the same as cpu_V0. */ cpu_M0 = tcg_temp_new_i64(); next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); @@ -11286,10 +11283,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * (3) if we leave the TB unexpectedly (eg a data abort on a load) * then the CPUARMState will be wrong and we need to reset it. * This is handled in the same way as restoration of the - * PC in these situations: we will be called again with search_pc=1 - * and generate a mapping of the condexec bits for each PC in - * gen_opc_condexec_bits[]. restore_state_to_opc() then uses - * this to restore the condexec bits. + * PC in these situations; we save the value of the condexec bits + * for each PC via tcg_gen_insn_start(), and restore_state_to_opc() + * then uses this to restore them after an exception. * * Note that there are no instructions which can read the condexec * bits, and none which can write non-static values to them, so @@ -11306,6 +11302,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, store_cpu_field(tmp, condexec_bits); } do { + tcg_gen_insn_start(dc->pc, + (dc->condexec_cond << 4) | (dc->condexec_mask >> 1)); + num_insns++; + #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ if (dc->pc >= 0xffff0000) { @@ -11326,6 +11326,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, #endif if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { + CPUBreakpoint *bp; QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { if (bp->pc == dc->pc) { gen_exception_internal_insn(dc, 0, EXCP_DEBUG); @@ -11336,24 +11337,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, } } } - if (search_pc) { - j = tcg_op_buf_count(); - if (lj < j) { - lj++; - while (lj < j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - tcg_ctx.gen_opc_pc[lj] = dc->pc; - gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1); - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); - - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); } if (dc->ss_active && !dc->pstate_ss) { @@ -11367,7 +11353,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * "did not step an insn" case, and so the syndrome ISV and EX * bits should be zero. */ - assert(num_insns == 0); + assert(num_insns == 1); gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0), default_exception_el(dc)); goto done_generating; @@ -11403,7 +11389,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * Otherwise the subsequent code could get translated several times. * Also stop translation when a page boundary is reached. This * ensures prefetch aborts occur at the right place. */ - num_insns ++; } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && @@ -11533,25 +11518,8 @@ done_generating: qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } else { - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - } -} - -void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true); + tb->size = dc->pc - pc_start; + tb->icount = num_insns; } static const char *cpu_mode_names[16] = { @@ -11608,13 +11576,14 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, } } -void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, + target_ulong *data) { if (is_a64(env)) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; env->condexec_bits = 0; } else { - env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos]; - env->condexec_bits = gen_opc_condexec_bits[pc_pos]; + env->regs[15] = data[0]; + env->condexec_bits = data[1]; } } |