diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2013-12-17 19:42:31 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2013-12-17 19:42:31 +0000 |
commit | 40f860cd6c1aa0d3399e3f8158f20bdc5b2bfbfe (patch) | |
tree | 3a1f548e37e35bb9a329fdc37452b39fe932027b /target-arm/translate.c | |
parent | 013424d436b83f7ba8366b1d40bf82c4f6716f5e (diff) |
target-arm: Split A64 from A32/T32 gen_intermediate_code_internal()
The A32/T32 gen_intermediate_code_internal() is complicated because it
has to deal with:
* conditionally executed instructions
* Thumb IT blocks
* kernel helper page
* M profile exception-exit special casing
None of these apply to A64, so putting the "this is A64 so
call the A64 decoder" check in the middle of the A32/T32
loop is confusing and means the A64 decoder's handling of
things like conditional jump and singlestepping has to take
account of the conditional-execution jumps the main loop
might emit.
Refactor the code to give A64 its own gen_intermediate_code_internal
function instead.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 62 |
1 files changed, 24 insertions, 38 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 913146752a..679b3c3451 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -56,11 +56,6 @@ static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE]; #define IS_USER(s) (s->user) #endif -/* These instructions trap after executing, so defer them until after the - conditional execution state has been updated. */ -#define DISAS_WFI 4 -#define DISAS_SWI 5 - TCGv_ptr cpu_env; /* We reuse the same 64-bit temporaries for efficiency. */ static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; @@ -900,11 +895,7 @@ DO_GEN_ST(32, MO_TEUL) static inline void gen_set_pc_im(DisasContext *s, target_ulong val) { - if (s->aarch64) { - gen_a64_set_pc_im(val); - } else { - tcg_gen_movi_i32(cpu_R[15], val); - } + tcg_gen_movi_i32(cpu_R[15], val); } /* Force a TB lookup after an instruction that changes the CPU state. */ @@ -10243,6 +10234,15 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, int max_insns; /* generate intermediate code */ + + /* The A64 decoder has its own top level loop, because it doesn't need + * 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); + return; + } + pc_start = tb->pc; dc->tb = tb; @@ -10254,31 +10254,18 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, dc->singlestep_enabled = cs->singlestep_enabled; dc->condjmp = 0; - if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) { - dc->aarch64 = 1; - dc->thumb = 0; - dc->bswap_code = 0; - dc->condexec_mask = 0; - dc->condexec_cond = 0; + dc->aarch64 = 0; + dc->thumb = ARM_TBFLAG_THUMB(tb->flags); + dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags); + dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1; + dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4; #if !defined(CONFIG_USER_ONLY) - dc->user = 0; + dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); #endif - dc->vfp_enabled = 0; - dc->vec_len = 0; - dc->vec_stride = 0; - } else { - dc->aarch64 = 0; - dc->thumb = ARM_TBFLAG_THUMB(tb->flags); - dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags); - dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1; - dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4; -#if !defined(CONFIG_USER_ONLY) - dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); -#endif - dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); - dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); - dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); - } + dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); + dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); + dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); + cpu_F0s = tcg_temp_new_i32(); cpu_F1s = tcg_temp_new_i32(); cpu_F0d = tcg_temp_new_i64(); @@ -10340,7 +10327,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, do { #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ - if (!dc->aarch64 && dc->pc >= 0xffff0000) { + if (dc->pc >= 0xffff0000) { /* We always get here via a jump, so know we are not in a conditional execution block. */ gen_exception(EXCP_KERNEL_TRAP); @@ -10388,9 +10375,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, tcg_gen_debug_insn_start(dc->pc); } - if (dc->aarch64) { - disas_a64_insn(env, dc); - } else if (dc->thumb) { + if (dc->thumb) { disas_thumb_insn(env, dc); if (dc->condexec_mask) { dc->condexec_cond = (dc->condexec_cond & 0xe) @@ -10585,8 +10570,9 @@ void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos) { if (is_a64(env)) { env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + 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->condexec_bits = gen_opc_condexec_bits[pc_pos]; } |