[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code |
Date: |
Sat, 21 Jun 2014 14:58:14 +0200 |
bswap_code is a CPU property of sorts ("is the iside endianness the
opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the
actual CPU state involved here which is SCTLR.B (set for BE32
binaries, clear for BE8).
Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code.
The next patches will make data fetches honor both SCTLR.B and
CPSR.E appropriately.
Signed-off-by: Paolo Bonzini <address@hidden>
---
linux-user/main.c | 14 +++++++++++---
target-arm/arm_ldst.h | 8 ++++----
target-arm/cpu.h | 38 ++++++++++++++++++++++++++++++--------
target-arm/helper.c | 8 ++++----
target-arm/translate-a64.c | 6 +++---
target-arm/translate.c | 14 +++++++-------
target-arm/translate.h | 2 +-
7 files changed, 60 insertions(+), 30 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index fb6c2c0..dbaa42a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -435,7 +435,7 @@ void cpu_loop(CPUX86State *env)
#define get_user_code_u32(x, gaddr, env) \
({ abi_long __r = get_user_u32((x), (gaddr)); \
- if (!__r && (env)->bswap_code) { \
+ if (!__r && bswap_code(arm_sctlr_b(env))) { \
(x) = bswap32(x); \
} \
__r; \
@@ -443,7 +443,7 @@ void cpu_loop(CPUX86State *env)
#define get_user_code_u16(x, gaddr, env) \
({ abi_long __r = get_user_u16((x), (gaddr)); \
- if (!__r && (env)->bswap_code) { \
+ if (!__r && bswap_code(arm_sctlr_b(env))) { \
(x) = bswap16(x); \
} \
__r; \
@@ -4191,11 +4191,19 @@ int main(int argc, char **argv, char **envp)
for(i = 0; i < 16; i++) {
env->regs[i] = regs->uregs[i];
}
+#ifdef TARGET_WORDS_BIGENDIAN
/* Enable BE8. */
if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
&& (info->elf_flags & EF_ARM_BE8)) {
- env->bswap_code = 1;
+ /* nothing for now, CPSR.E not emulated yet */
+ } else {
+ if (arm_feature(env, ARM_FEATURE_V7)) {
+ fprintf(stderr, "BE32 binaries only supported until ARMv6\n");
+ exit(1);
+ }
+ env->cp15.c1_sys |= SCTLR_B;
}
+#endif
}
#elif defined(TARGET_UNICORE32)
{
diff --git a/target-arm/arm_ldst.h b/target-arm/arm_ldst.h
index b1ece01..35c2c43 100644
--- a/target-arm/arm_ldst.h
+++ b/target-arm/arm_ldst.h
@@ -25,10 +25,10 @@
/* Load an instruction and return it in the standard little-endian order */
static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
- bool do_swap)
+ bool sctlr_b)
{
uint32_t insn = cpu_ldl_code(env, addr);
- if (do_swap) {
+ if (bswap_code(sctlr_b)) {
return bswap32(insn);
}
return insn;
@@ -36,10 +36,10 @@ static inline uint32_t arm_ldl_code(CPUARMState *env,
target_ulong addr,
/* Ditto, for a halfword (Thumb) instruction */
static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
- bool do_swap)
+ bool sctlr_b)
{
uint16_t insn = cpu_lduw_code(env, addr);
- if (do_swap) {
+ if (bswap_code(sctlr_b)) {
return bswap16(insn);
}
return insn;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 369d472..4a9d2a8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -313,9 +313,6 @@ 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;
@@ -1132,8 +1129,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
#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)
-#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
-#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_SCTLR_B_SHIFT 16
+#define ARM_TBFLAG_SCTLR_B_MASK (1 << ARM_TBFLAG_SCTLR_B_SHIFT)
#define ARM_TBFLAG_CPACR_FPEN_SHIFT 17
#define ARM_TBFLAG_CPACR_FPEN_MASK (1 << ARM_TBFLAG_CPACR_FPEN_SHIFT)
@@ -1158,8 +1155,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
(((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)
+#define ARM_TBFLAG_SCTLR_B(F) \
+ (((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
#define ARM_TBFLAG_CPACR_FPEN(F) \
(((F) & ARM_TBFLAG_CPACR_FPEN_MASK) >> ARM_TBFLAG_CPACR_FPEN_SHIFT)
#define ARM_TBFLAG_AA64_EL(F) \
@@ -1167,6 +1164,31 @@ static inline int cpu_mmu_index (CPUARMState *env)
#define ARM_TBFLAG_AA64_FPEN(F) \
(((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT)
+static inline bool arm_sctlr_b(CPUARMState *env)
+{
+ return !arm_feature(env, ARM_FEATURE_V7) && (env->cp15.c1_sys & SCTLR_B)
!= 0;
+}
+
+static inline bool bswap_code(bool sctlr_b)
+{
+#ifdef CONFIG_USER_ONLY
+ /* Mixed-endian modes are BE8 (SCTLR.B = 0, TARGET_WORDS_BIGENDIAN = 1)
+ * and "LE8" (SCTLR.B = 1, TARGET_WORDS_BIGENDIAN = 0).
+ */
+ return
+#ifdef TARGET_WORDS_BIGENDIAN
+ 1 ^
+#endif
+ sctlr_b;
+#else
+ /* We do not implement BE32 mode for system-mode emulation, but
+ * anyway it would always do little-endian accesses with
+ * TARGET_WORDS_BIGENDIAN = 0.
+ */
+ return 0;
+#endif
+}
+
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
@@ -1186,7 +1208,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env,
target_ulong *pc,
| (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
| (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
| (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
- | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
+ | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
if (arm_feature(env, ARM_FEATURE_M)) {
privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
} else {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index ed4d2bb..6e4fc55 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3312,7 +3312,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
case EXCP_BKPT:
if (semihosting_enabled) {
int nr;
- nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
+ nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
if (nr == 0xab) {
env->regs[15] += 2;
env->regs[0] = do_arm_semihosting(env);
@@ -3387,10 +3387,10 @@ void arm_cpu_do_interrupt(CPUState *cs)
if (semihosting_enabled) {
/* Check for semihosting interrupt. */
if (env->thumb) {
- mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
+ mask = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
& 0xff;
} else {
- mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
+ mask = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
& 0xffffff;
}
/* Only intercept calls from privileged modes, to provide some
@@ -3412,7 +3412,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
case EXCP_BKPT:
/* See if this is a semihosting syscall. */
if (env->thumb && semihosting_enabled) {
- mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
+ mask = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
if (mask == 0xab
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
env->regs[15] += 2;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 33b5025..e4115ba 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -10786,7 +10786,7 @@ static void disas_a64_insn(CPUARMState *env,
DisasContext *s)
{
uint32_t insn;
- insn = arm_ldl_code(env, s->pc, s->bswap_code);
+ insn = arm_ldl_code(env, s->pc, s->sctlr_b);
s->insn = insn;
s->pc += 4;
@@ -10853,7 +10853,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
dc->aarch64 = 1;
dc->thumb = 0;
- dc->bswap_code = 0;
+ dc->sctlr_b = 0;
dc->condexec_mask = 0;
dc->condexec_cond = 0;
#if !defined(CONFIG_USER_ONLY)
@@ -10988,7 +10988,7 @@ done_generating:
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(env, pc_start, dc->pc - pc_start,
- 4 | (dc->bswap_code << 1));
+ 4 | (dc->sctlr_b << 1));
qemu_log("\n");
}
#endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index cf4e767..460150d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7484,7 +7484,7 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
TCGv_i32 addr;
TCGv_i64 tmp64;
- insn = arm_ldl_code(env, s->pc, s->bswap_code);
+ insn = arm_ldl_code(env, s->pc, s->sctlr_b);
s->pc += 4;
/* M variants do not implement ARM mode. */
@@ -7552,7 +7552,7 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
if ((insn & 0x0ffffdff) == 0x01010000) {
ARCH(6);
/* setend */
- if (((insn >> 9) & 1) != s->bswap_code) {
+ if (((insn >> 9) & 1) != bswap_code(s->sctlr_b)) {
/* Dynamic endianness switching not implemented. */
qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
goto illegal_op;
@@ -9024,7 +9024,7 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
/* Fall through to 32-bit decode. */
}
- insn = arm_lduw_code(env, s->pc, s->bswap_code);
+ insn = arm_lduw_code(env, s->pc, s->sctlr_b);
s->pc += 2;
insn |= (uint32_t)insn_hw1 << 16;
@@ -10149,7 +10149,7 @@ static void disas_thumb_insn(CPUARMState *env,
DisasContext *s)
}
}
- insn = arm_lduw_code(env, s->pc, s->bswap_code);
+ insn = arm_lduw_code(env, s->pc, s->sctlr_b);
s->pc += 2;
switch (insn >> 12) {
@@ -10719,7 +10719,7 @@ static void disas_thumb_insn(CPUARMState *env,
DisasContext *s)
case 2:
/* setend */
ARCH(6);
- if (((insn >> 3) & 1) != s->bswap_code) {
+ if (((insn >> 3) & 1) != bswap_code(s->sctlr_b)) {
/* Dynamic endianness switching not implemented. */
qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
goto illegal_op;
@@ -10899,7 +10899,7 @@ static inline void
gen_intermediate_code_internal(ARMCPU *cpu,
dc->aarch64 = 0;
dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
- dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
+ dc->sctlr_b = ARM_TBFLAG_SCTLR_B(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)
@@ -11142,7 +11142,7 @@ done_generating:
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(env, pc_start, dc->pc - pc_start,
- dc->thumb | (dc->bswap_code << 1));
+ dc->thumb | (dc->sctlr_b << 1));
qemu_log("\n");
}
#endif
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 31a0104..19f794c 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -16,7 +16,7 @@ typedef struct DisasContext {
struct TranslationBlock *tb;
int singlestep_enabled;
int thumb;
- int bswap_code;
+ int sctlr_b;
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
--
1.9.3
[Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode, Paolo Bonzini, 2014/06/21
[Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE, Paolo Bonzini, 2014/06/21
[Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation, Paolo Bonzini, 2014/06/21