diff options
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/cpu.h | 32 | ||||
-rw-r--r-- | target-arm/helper.c | 9 | ||||
-rw-r--r-- | target-arm/translate.c | 11 |
3 files changed, 42 insertions, 10 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index e176c5f65c..c208c804aa 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -216,6 +216,9 @@ typedef struct CPUARMState { uint32_t cregs[16]; } iwmmxt; + /* For mixed endian mode. */ + bool bswap_code; + #if defined(CONFIG_USER_ONLY) /* For usermode syscall translation. */ int eabi; @@ -491,7 +494,9 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) #define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT) #define ARM_TBFLAG_CONDEXEC_SHIFT 8 #define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT) -/* Bits 31..16 are currently unused. */ +#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16 +#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT) +/* Bits 31..17 are currently unused. */ /* some convenience accessor macros */ #define ARM_TBFLAG_THUMB(F) \ @@ -506,6 +511,8 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT) #define ARM_TBFLAG_CONDEXEC(F) \ (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT) +#define ARM_TBFLAG_BSWAP_CODE(F) \ + (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT) static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, int *flags) @@ -516,7 +523,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT) | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT) - | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT); + | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT) + | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT); if (arm_feature(env, ARM_FEATURE_M)) { privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1)); } else { @@ -543,4 +551,24 @@ static inline void cpu_pc_from_tb(CPUARMState *env, TranslationBlock *tb) env->regs[15] = tb->pc; } +/* Load an instruction and return it in the standard little-endian order */ +static inline uint32_t arm_ldl_code(uint32_t addr, bool do_swap) +{ + uint32_t insn = ldl_code(addr); + if (do_swap) { + return bswap32(insn); + } + return insn; +} + +/* Ditto, for a halfword (Thumb) instruction */ +static inline uint16_t arm_lduw_code(uint32_t addr, bool do_swap) +{ + uint16_t insn = lduw_code(addr); + if (do_swap) { + return bswap16(insn); + } + return insn; +} + #endif diff --git a/target-arm/helper.c b/target-arm/helper.c index d974b579dc..28f127baf8 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -842,7 +842,7 @@ static void do_interrupt_v7m(CPUARMState *env) case EXCP_BKPT: if (semihosting_enabled) { int nr; - nr = lduw_code(env->regs[15]) & 0xff; + nr = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff; if (nr == 0xab) { env->regs[15] += 2; env->regs[0] = do_arm_semihosting(env); @@ -914,9 +914,10 @@ void do_interrupt(CPUARMState *env) if (semihosting_enabled) { /* Check for semihosting interrupt. */ if (env->thumb) { - mask = lduw_code(env->regs[15] - 2) & 0xff; + mask = arm_lduw_code(env->regs[15] - 2, env->bswap_code) & 0xff; } else { - mask = ldl_code(env->regs[15] - 4) & 0xffffff; + mask = arm_ldl_code(env->regs[15] - 4, env->bswap_code) + & 0xffffff; } /* Only intercept calls from privileged modes, to provide some semblance of security. */ @@ -936,7 +937,7 @@ void do_interrupt(CPUARMState *env) case EXCP_BKPT: /* See if this is a semihosting syscall. */ if (env->thumb && semihosting_enabled) { - mask = lduw_code(env->regs[15]) & 0xff; + mask = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff; if (mask == 0xab && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) { env->regs[15] += 2; diff --git a/target-arm/translate.c b/target-arm/translate.c index 46d1d3ef9f..7a3c7d650c 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -59,6 +59,7 @@ typedef struct DisasContext { struct TranslationBlock *tb; int singlestep_enabled; int thumb; + int bswap_code; #if !defined(CONFIG_USER_ONLY) int user; #endif @@ -6705,7 +6706,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) TCGv addr; TCGv_i64 tmp64; - insn = ldl_code(s->pc); + insn = arm_ldl_code(s->pc, s->bswap_code); s->pc += 4; /* M variants do not implement ARM mode. */ @@ -8133,7 +8134,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw /* Fall through to 32-bit decode. */ } - insn = lduw_code(s->pc); + insn = arm_lduw_code(s->pc, s->bswap_code); s->pc += 2; insn |= (uint32_t)insn_hw1 << 16; @@ -9163,7 +9164,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) } } - insn = lduw_code(s->pc); + insn = arm_lduw_code(s->pc, s->bswap_code); s->pc += 2; switch (insn >> 12) { @@ -9872,6 +9873,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env, dc->singlestep_enabled = env->singlestep_enabled; dc->condjmp = 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) @@ -10105,7 +10107,8 @@ done_generating: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("----------------\n"); qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(pc_start, dc->pc - pc_start, dc->thumb); + log_target_disas(pc_start, dc->pc - pc_start, + dc->thumb | (dc->bswap_code << 1)); qemu_log("\n"); } #endif |