aboutsummaryrefslogtreecommitdiff
path: root/target-arm/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r--target-arm/translate.c83
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];
}
}