All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
@ 2014-06-21 12:58 Paolo Bonzini
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions Paolo Bonzini
                   ` (12 more replies)
  0 siblings, 13 replies; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

This fixes the Raspberry Pi optimized memcmp library (with both user-mode
and system-mode emulation).

Compared to the previous submission, the main changes are:

- I track access endianness by taking into account both SCTLR.B and CPSR.E,
  to make the code easier to understand (though a little bit more
  convoluted)

- because of this, I prevent execution of BE32 executables with ARMv7 or v8
  CPUs.  These CPUs do not have SCTLR.B.

- because of this, I also included an untested patch to implement BE32
  mode in system emulation (BE8 should already work with the previous
  versions of the series).

Note that I also tested the rest only with BE32, since BE8 is not included
in linux-user-test-0.3 (it may be possible to convert BE32 to BE8 using
ld -r?  I haven't tried yet and I'm going to travel for the rest of the
weekend).

It is a bit late for 2.1, so I wouldn't complain if this is pushed out
to the next version.

Thanks,

Paolo

Paolo Bonzini (11):
  linux-user: arm: fix coding style for some linux-user signal functions
  linux-user: arm: pass env to get_user_code_*
  target-arm: implement SCTLR.B, drop bswap_code
  linux-user: arm: set CPSR.E correctly for BE8 mode
  linux-user: arm: handle CPSR.E correctly in strex emulation
  target-arm: implement SCTLR.EE
  target-arm: pass DisasContext to gen_aa32_ld*/st*
  target-arm: introduce tbflag for CPSR.E
  target-arm: implement setend
  target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation
  target-arm: implement BE32 mode in system emulation

 linux-user/arm/target_cpu.h |   2 +
 linux-user/main.c           |  81 ++++++--
 linux-user/signal.c         | 114 ++++++------
 target-arm/arm_ldst.h       |   8 +-
 target-arm/cpu.h            |  85 ++++++++-
 target-arm/helper.c         |  46 ++++-
 target-arm/helper.h         |   1 +
 target-arm/op_helper.c      |   5 +
 target-arm/translate-a64.c  |   6 +-
 target-arm/translate.c      | 444 +++++++++++++++++++++++++++-----------------
 target-arm/translate.h      |   4 +-
 11 files changed, 525 insertions(+), 271 deletions(-)

-- 
1.9.3

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:22   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 02/11] linux-user: arm: pass env to get_user_code_* Paolo Bonzini
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 linux-user/signal.c | 112 ++++++++++++++++++++++++++--------------------------
 1 file changed, 57 insertions(+), 55 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index f3b4378..624c34d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1550,82 +1550,84 @@ static void
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
                  CPUARMState *env, abi_ulong mask)
 {
-	__put_user(env->regs[0], &sc->arm_r0);
-	__put_user(env->regs[1], &sc->arm_r1);
-	__put_user(env->regs[2], &sc->arm_r2);
-	__put_user(env->regs[3], &sc->arm_r3);
-	__put_user(env->regs[4], &sc->arm_r4);
-	__put_user(env->regs[5], &sc->arm_r5);
-	__put_user(env->regs[6], &sc->arm_r6);
-	__put_user(env->regs[7], &sc->arm_r7);
-	__put_user(env->regs[8], &sc->arm_r8);
-	__put_user(env->regs[9], &sc->arm_r9);
-	__put_user(env->regs[10], &sc->arm_r10);
-	__put_user(env->regs[11], &sc->arm_fp);
-	__put_user(env->regs[12], &sc->arm_ip);
-	__put_user(env->regs[13], &sc->arm_sp);
-	__put_user(env->regs[14], &sc->arm_lr);
-	__put_user(env->regs[15], &sc->arm_pc);
+    __put_user(env->regs[0], &sc->arm_r0);
+    __put_user(env->regs[1], &sc->arm_r1);
+    __put_user(env->regs[2], &sc->arm_r2);
+    __put_user(env->regs[3], &sc->arm_r3);
+    __put_user(env->regs[4], &sc->arm_r4);
+    __put_user(env->regs[5], &sc->arm_r5);
+    __put_user(env->regs[6], &sc->arm_r6);
+    __put_user(env->regs[7], &sc->arm_r7);
+    __put_user(env->regs[8], &sc->arm_r8);
+    __put_user(env->regs[9], &sc->arm_r9);
+    __put_user(env->regs[10], &sc->arm_r10);
+    __put_user(env->regs[11], &sc->arm_fp);
+    __put_user(env->regs[12], &sc->arm_ip);
+    __put_user(env->regs[13], &sc->arm_sp);
+    __put_user(env->regs[14], &sc->arm_lr);
+    __put_user(env->regs[15], &sc->arm_pc);
 #ifdef TARGET_CONFIG_CPU_32
-	__put_user(cpsr_read(env), &sc->arm_cpsr);
+    __put_user(cpsr_read(env), &sc->arm_cpsr);
 #endif
 
-	__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
-	__put_user(/* current->thread.error_code */ 0, &sc->error_code);
-	__put_user(/* current->thread.address */ 0, &sc->fault_address);
-	__put_user(mask, &sc->oldmask);
+    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
+    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
+    __put_user(/* current->thread.address */ 0, &sc->fault_address);
+    __put_user(mask, &sc->oldmask);
 }
 
 static inline abi_ulong
 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 {
-	unsigned long sp = regs->regs[13];
+    unsigned long sp = regs->regs[13];
 
-	/*
-	 * This is the X/Open sanctioned signal stack switching.
-	 */
-	if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
-            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
-	/*
-	 * ATPCS B01 mandates 8-byte alignment
-	 */
-	return (sp - framesize) & ~7;
+    /*
+     * This is the X/Open sanctioned signal stack switching.
+     */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+    /*
+     * ATPCS B01 mandates 8-byte alignment
+     */
+    return (sp - framesize) & ~7;
 }
 
 static void
 setup_return(CPUARMState *env, struct target_sigaction *ka,
 	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 {
-	abi_ulong handler = ka->_sa_handler;
-	abi_ulong retcode;
-	int thumb = handler & 1;
-	uint32_t cpsr = cpsr_read(env);
+    abi_ulong handler = ka->_sa_handler;
+    abi_ulong retcode;
+    int thumb = handler & 1;
+    uint32_t cpsr = cpsr_read(env);
 
-	cpsr &= ~CPSR_IT;
-	if (thumb) {
-		cpsr |= CPSR_T;
-	} else {
-		cpsr &= ~CPSR_T;
-	}
+    cpsr &= ~CPSR_IT;
+    if (thumb) {
+        cpsr |= CPSR_T;
+    } else {
+        cpsr &= ~CPSR_T;
+    }
 
-	if (ka->sa_flags & TARGET_SA_RESTORER) {
-		retcode = ka->sa_restorer;
-	} else {
-		unsigned int idx = thumb;
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
+        retcode = ka->sa_restorer;
+    } else {
+        unsigned int idx = thumb;
 
-		if (ka->sa_flags & TARGET_SA_SIGINFO)
-			idx += 2;
+        if (ka->sa_flags & TARGET_SA_SIGINFO) {
+            idx += 2;
+        }
 
         __put_user(retcodes[idx], rc);
 
-		retcode = rc_addr + thumb;
-	}
+        retcode = rc_addr + thumb;
+    }
 
-	env->regs[0] = usig;
-	env->regs[13] = frame_addr;
-	env->regs[14] = retcode;
-	env->regs[15] = handler & (thumb ? ~1 : ~3);
-	cpsr_write(env, cpsr, 0xffffffff);
+    env->regs[0] = usig;
+    env->regs[13] = frame_addr;
+    env->regs[14] = retcode;
+    env->regs[15] = handler & (thumb ? ~1 : ~3);
+    cpsr_write(env, cpsr, 0xffffffff);
 }
 
 static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 02/11] linux-user: arm: pass env to get_user_code_*
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:23   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code Paolo Bonzini
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

This matches the idiom used by get_user_data_* later in the series,
and will help when bswap_code will be replaced by SCTLR.B.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 linux-user/main.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index a87c6f7..fb6c2c0 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -433,17 +433,17 @@ void cpu_loop(CPUX86State *env)
 
 #ifdef TARGET_ARM
 
-#define get_user_code_u32(x, gaddr, doswap)             \
+#define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
-        if (!__r && (doswap)) {                         \
+        if (!__r && (env)->bswap_code) {                \
             (x) = bswap32(x);                           \
         }                                               \
         __r;                                            \
     })
 
-#define get_user_code_u16(x, gaddr, doswap)             \
+#define get_user_code_u16(x, gaddr, env)                \
     ({ abi_long __r = get_user_u16((x), (gaddr));       \
-        if (!__r && (doswap)) {                         \
+        if (!__r && (env)->bswap_code) {                \
             (x) = bswap16(x);                           \
         }                                               \
         __r;                                            \
@@ -692,7 +692,7 @@ void cpu_loop(CPUARMState *env)
                 /* we handle the FPU emulation here, as Linux */
                 /* we get the opcode */
                 /* FIXME - what to do if get_user() fails? */
-                get_user_code_u32(opcode, env->regs[15], env->bswap_code);
+                get_user_code_u32(opcode, env->regs[15], env);
 
                 rc = EmulateAll(opcode, &ts->fpa, env);
                 if (rc == 0) { /* illegal instruction */
@@ -762,25 +762,23 @@ void cpu_loop(CPUARMState *env)
                 if (trapnr == EXCP_BKPT) {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u16(insn, env->regs[15], env->bswap_code);
+                        get_user_code_u16(insn, env->regs[15], env);
                         n = insn & 0xff;
                         env->regs[15] += 2;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u32(insn, env->regs[15], env->bswap_code);
+                        get_user_code_u32(insn, env->regs[15], env);
                         n = (insn & 0xf) | ((insn >> 4) & 0xff0);
                         env->regs[15] += 4;
                     }
                 } else {
                     if (env->thumb) {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u16(insn, env->regs[15] - 2,
-                                          env->bswap_code);
+                        get_user_code_u16(insn, env->regs[15] - 2, env);
                         n = insn & 0xff;
                     } else {
                         /* FIXME - what to do if get_user() fails? */
-                        get_user_code_u32(insn, env->regs[15] - 4,
-                                          env->bswap_code);
+                        get_user_code_u32(insn, env->regs[15] - 4, env);
                         n = insn & 0xffffff;
                     }
                 }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions Paolo Bonzini
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 02/11] linux-user: arm: pass env to get_user_code_* Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:01   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode Paolo Bonzini
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

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 <pbonzini@redhat.com>
---
 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

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (2 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:15   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation Paolo Bonzini
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Set it on startup, in signal handler frames and in new threads.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 linux-user/arm/target_cpu.h | 2 ++
 linux-user/main.c           | 3 ++-
 linux-user/signal.c         | 2 ++
 target-arm/cpu.h            | 3 +++
 4 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
index 39d65b6..d0411c7 100644
--- a/linux-user/arm/target_cpu.h
+++ b/linux-user/arm/target_cpu.h
@@ -25,6 +25,8 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
         env->regs[13] = newsp;
     }
     env->regs[0] = 0;
+    env->uncached_cpsr &= ~CPSR_E;
+    env->uncached_cpsr |= env->signal_cpsr_e;
 }
 
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
diff --git a/linux-user/main.c b/linux-user/main.c
index dbaa42a..795a407 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4195,7 +4195,8 @@ int main(int argc, char **argv, char **envp)
         /* Enable BE8.  */
         if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
             && (info->elf_flags & EF_ARM_BE8)) {
-            /* nothing for now, CPSR.E not emulated yet */
+            env->uncached_cpsr |= CPSR_E;
+            env->signal_cpsr_e = CPSR_E;
         } else {
             if (arm_feature(env, ARM_FEATURE_V7)) {
                 fprintf(stderr, "BE32 binaries only supported until ARMv6\n");
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 624c34d..87ddabd 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1609,6 +1609,8 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
         cpsr &= ~CPSR_T;
     }
 
+    cpsr |= env->signal_cpsr_e;
+
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         retcode = ka->sa_restorer;
     } else {
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 4a9d2a8..cb5be84 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -316,6 +316,9 @@ typedef struct CPUARMState {
 #if defined(CONFIG_USER_ONLY)
     /* For usermode syscall translation.  */
     int eabi;
+
+    /* CPSR.E value for new threads and signal handlers.  */
+    uint32_t signal_cpsr_e;
 #endif
 
     CPU_COMMON
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (3 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:21   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE Paolo Bonzini
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Now that CPSR.E is set correctly, prepare for when setend will be able
to change it; bswap data in and out of strex manually by comparing
SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
of using TCGMemOps).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 linux-user/main.c | 50 +++++++++++++++++++++++++++++++++++++++++++-------
 target-arm/cpu.h  | 28 ++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 795a407..9782c13 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -449,6 +449,38 @@ void cpu_loop(CPUX86State *env)
         __r;                                            \
     })
 
+#define get_user_data_u32(x, gaddr, env)                \
+    ({ abi_long __r = get_user_u32((x), (gaddr));       \
+        if (!__r && arm_cpu_bswap_data(env)) {          \
+            (x) = bswap32(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
+#define get_user_data_u16(x, gaddr, env)                \
+    ({ abi_long __r = get_user_u16((x), (gaddr));       \
+        if (!__r && arm_cpu_bswap_data(env)) {          \
+            (x) = bswap16(x);                           \
+        }                                               \
+        __r;                                            \
+    })
+
+#define put_user_data_u32(x, gaddr, env)                \
+    ({ typeof(x) __x = (x);                             \
+        if (arm_cpu_bswap_data(env)) {                  \
+            __x = bswap32(__x);                         \
+        }                                               \
+        put_user_u32(__x, (gaddr));                     \
+    })
+
+#define put_user_data_u16(x, gaddr, env)                \
+    ({ typeof(x) __x = (x);                             \
+        if (arm_cpu_bswap_data(env)) {                  \
+            __x = bswap16(__x);                         \
+        }                                               \
+        put_user_u16(__x, (gaddr));                     \
+    })
+
 #ifdef TARGET_ABI32
 /* Commpage handling -- there is no commpage for AArch64 */
 
@@ -610,11 +642,11 @@ static int do_strex(CPUARMState *env)
         segv = get_user_u8(val, addr);
         break;
     case 1:
-        segv = get_user_u16(val, addr);
+        segv = get_user_data_u16(val, addr, env);
         break;
     case 2:
     case 3:
-        segv = get_user_u32(val, addr);
+        segv = get_user_data_u32(val, addr, env);
         break;
     default:
         abort();
@@ -625,12 +657,16 @@ static int do_strex(CPUARMState *env)
     }
     if (size == 3) {
         uint32_t valhi;
-        segv = get_user_u32(valhi, addr + 4);
+        segv = get_user_data_u32(valhi, addr + 4, env);
         if (segv) {
             env->exception.vaddress = addr + 4;
             goto done;
         }
-        val = deposit64(val, 32, 32, valhi);
+        if (arm_cpu_bswap_data(env)) {
+            val = deposit64((uint64_t)valhi, 32, 32, val);
+        } else {
+            val = deposit64(val, 32, 32, valhi);
+        }
     }
     if (val != env->exclusive_val) {
         goto fail;
@@ -642,11 +678,11 @@ static int do_strex(CPUARMState *env)
         segv = put_user_u8(val, addr);
         break;
     case 1:
-        segv = put_user_u16(val, addr);
+        segv = put_user_data_u16(val, addr, env);
         break;
     case 2:
     case 3:
-        segv = put_user_u32(val, addr);
+        segv = put_user_data_u32(val, addr, env);
         break;
     }
     if (segv) {
@@ -655,7 +691,7 @@ static int do_strex(CPUARMState *env)
     }
     if (size == 3) {
         val = env->regs[(env->exclusive_info >> 12) & 0xf];
-        segv = put_user_u32(val, addr + 4);
+        segv = put_user_data_u32(val, addr + 4, env);
         if (segv) {
             env->exception.vaddress = addr + 4;
             goto done;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cb5be84..defd65e 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1192,6 +1192,34 @@ static inline bool bswap_code(bool sctlr_b)
 #endif
 }
 
+#ifdef CONFIG_USER_ONLY
+/* get_user and put_user respectivaly return and expect data according
+ * to TARGET_WORDS_BIGENDIAN, but ldrex/strex emulation needs to take
+ * into account CPSR.E.  Similar to bwap_code, a XOR gives exactly the
+ * required result, we just throw CPSR.E into the mix too:
+ *
+ *            TARGET_WORDS_BIGENDIAN  SCTLR.B  CPSR.E    need swap?
+ *   LE/LE                 no             0      0          no
+ *   LE/BE                 no             0      1          yes
+ *   BE8/LE                yes            0      0          yes
+ *   BE8/BE                yes            0      1          no
+ *   BE32/BE               yes            1      0          no
+ *  (BE32/LE)              yes            1      1          yes
+ *
+ * Officially, BE32 with CPSR.E=1 has "unpredictable" results.  We
+ * implement it as big-endian code, little-endian data.
+ */
+static inline bool arm_cpu_bswap_data(CPUARMState *env)
+{
+    return
+#ifdef TARGET_WORDS_BIGENDIAN
+       1 ^
+#endif
+       arm_sctlr_b(env) ^
+       !!(env->uncached_cpsr & CPSR_E);
+}
+#endif
+
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (4 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:29   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 07/11] target-arm: pass DisasContext to gen_aa32_ld*/st* Paolo Bonzini
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Set CPSR.E to SCTLR.EE on exception, and use SCTLR.EE also to
determine endianness for loads during TLB misses.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/helper.c | 38 ++++++++++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6e4fc55..2e3816d 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3213,6 +3213,30 @@ void switch_mode(CPUARMState *env, int mode)
     env->spsr = env->banked_spsr[i];
 }
 
+static uint32_t ldl_ptw_phys(CPUState *cs, target_ulong physaddr)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    if (unlikely(env->cp15.c1_sys & SCTLR_EE)) {
+        return ldl_be_phys(cs->as, physaddr);
+    } else {
+        return ldl_le_phys(cs->as, physaddr);
+    }
+}
+
+static uint64_t ldq_ptw_phys(CPUState *cs, target_ulong physaddr)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    if (unlikely(env->cp15.c1_sys & SCTLR_EE)) {
+        return ldq_be_phys(cs->as, physaddr);
+    } else {
+        return ldq_le_phys(cs->as, physaddr);
+    }
+}
+
 static void v7m_push(CPUARMState *env, uint32_t val)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
@@ -3483,7 +3507,9 @@ void arm_cpu_do_interrupt(CPUState *cs)
     /* Clear IT bits.  */
     env->condexec_bits = 0;
     /* Switch to the new mode, and to the correct instruction set.  */
-    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
+    env->uncached_cpsr = (env->uncached_cpsr & ~(CPSR_M | CPSR_E))
+        | new_mode
+        | (env->cp15.c1_sys & SCTLR_EE ? CPSR_E : 0);
     env->daif |= mask;
     /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
      * and we should just guard the thumb mode on V4 */
@@ -3592,7 +3618,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
         code = 5;
         goto do_fault;
     }
-    desc = ldl_phys(cs->as, table);
+    desc = ldl_ptw_phys(cs, table);
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
     domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
@@ -3623,7 +3649,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
 	    /* Fine pagetable.  */
 	    table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
 	}
-        desc = ldl_phys(cs->as, table);
+        desc = ldl_ptw_phys(cs, table);
         switch (desc & 3) {
         case 0: /* Page translation fault.  */
             code = 7;
@@ -3694,7 +3720,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
         code = 5;
         goto do_fault;
     }
-    desc = ldl_phys(cs->as, table);
+    desc = ldl_ptw_phys(cs, table);
     type = (desc & 3);
     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
         /* Section translation fault, or attempt to use the encoding
@@ -3736,7 +3762,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
         }
         /* Lookup l2 entry.  */
         table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
-        desc = ldl_phys(cs->as, table);
+        desc = ldl_ptw_phys(cs, table);
         ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
         switch (desc & 3) {
         case 0: /* Page translation fault.  */
@@ -3930,7 +3956,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
 
         descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
         descaddr &= ~7ULL;
-        descriptor = ldq_phys(cs->as, descaddr);
+        descriptor = ldq_ptw_phys(cs, descaddr);
         if (!(descriptor & 1) ||
             (!(descriptor & 2) && (level == 3))) {
             /* Invalid, or the Reserved level 3 encoding */
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 07/11] target-arm: pass DisasContext to gen_aa32_ld*/st*
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (5 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:31   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 08/11] target-arm: introduce tbflag for CPSR.E Paolo Bonzini
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

We'll need the DisasContext in the next patch to retrieve the
desired endianness, so pass it as a whole to gen_aa32_ld*/st*.

Unfortunately we cannot let those functions call get_mem_index,
because of user-mode load/store instructions.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/translate.c | 256 ++++++++++++++++++++++++-------------------------
 1 file changed, 128 insertions(+), 128 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 460150d..4f36d48 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -838,23 +838,23 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
 #if TARGET_LONG_BITS == 32
 
 #define DO_GEN_LD(SUFF, OPC)                                             \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     tcg_gen_qemu_ld_i32(val, addr, index, OPC);                          \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     tcg_gen_qemu_st_i32(val, addr, index, OPC);                          \
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
     tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
     tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 }
@@ -862,7 +862,7 @@ static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 #else
 
 #define DO_GEN_LD(SUFF, OPC)                                             \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
@@ -871,7 +871,7 @@ static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
@@ -879,7 +879,7 @@ static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
     tcg_temp_free(addr64);                                               \
 }
 
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
@@ -887,7 +887,7 @@ static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
     tcg_temp_free(addr64);
 }
 
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
@@ -1165,18 +1165,18 @@ VFP_GEN_FIX(ulto, )
 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
 {
     if (dp) {
-        gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
+        gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
     } else {
-        gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
     }
 }
 
 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
 {
     if (dp) {
-        gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
+        gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
     } else {
-        gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
+        gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
     }
 }
 
@@ -1512,24 +1512,24 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
         if (insn & ARM_CP_RW_BIT) {
             if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
                 tmp = tcg_temp_new_i32();
-                gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                 iwmmxt_store_creg(wrd, tmp);
             } else {
                 i = 1;
                 if (insn & (1 << 8)) {
                     if (insn & (1 << 22)) {		/* WLDRD */
-                        gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
+                        gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
                         i = 0;
                     } else {				/* WLDRW wRd */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     }
                 } else {
                     tmp = tcg_temp_new_i32();
                     if (insn & (1 << 22)) {		/* WLDRH */
-                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                     } else {				/* WLDRB */
-                        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                     }
                 }
                 if (i) {
@@ -1541,24 +1541,24 @@ static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
         } else {
             if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
                 tmp = iwmmxt_load_creg(wrd);
-                gen_aa32_st32(tmp, addr, get_mem_index(s));
+                gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             } else {
                 gen_op_iwmmxt_movq_M0_wRn(wrd);
                 tmp = tcg_temp_new_i32();
                 if (insn & (1 << 8)) {
                     if (insn & (1 << 22)) {		/* WSTRD */
-                        gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
+                        gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
                     } else {				/* WSTRW wRd */
                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     }
                 } else {
                     if (insn & (1 << 22)) {		/* WSTRH */
                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
-                        gen_aa32_st16(tmp, addr, get_mem_index(s));
+                        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                     } else {				/* WSTRB */
                         tcg_gen_trunc_i64_i32(tmp, cpu_M0);
-                        gen_aa32_st8(tmp, addr, get_mem_index(s));
+                        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                     }
                 }
             }
@@ -2623,15 +2623,15 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
     TCGv_i32 tmp = tcg_temp_new_i32();
     switch (size) {
     case 0:
-        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
         gen_neon_dup_u8(tmp, 0);
         break;
     case 1:
-        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
         gen_neon_dup_low16(tmp);
         break;
     case 2:
-        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
         break;
     default: /* Avoid compiler warnings.  */
         abort();
@@ -4302,11 +4302,11 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
             if (size == 3) {
                 tmp64 = tcg_temp_new_i64();
                 if (load) {
-                    gen_aa32_ld64(tmp64, addr, get_mem_index(s));
+                    gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
                     neon_store_reg64(tmp64, rd);
                 } else {
                     neon_load_reg64(tmp64, rd);
-                    gen_aa32_st64(tmp64, addr, get_mem_index(s));
+                    gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
                 }
                 tcg_temp_free_i64(tmp64);
                 tcg_gen_addi_i32(addr, addr, stride);
@@ -4315,21 +4315,21 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                     if (size == 2) {
                         if (load) {
                             tmp = tcg_temp_new_i32();
-                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                             neon_store_reg(rd, pass, tmp);
                         } else {
                             tmp = neon_load_reg(rd, pass);
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp);
                         }
                         tcg_gen_addi_i32(addr, addr, stride);
                     } else if (size == 1) {
                         if (load) {
                             tmp = tcg_temp_new_i32();
-                            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                             tcg_gen_addi_i32(addr, addr, stride);
                             tmp2 = tcg_temp_new_i32();
-                            gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
+                            gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
                             tcg_gen_addi_i32(addr, addr, stride);
                             tcg_gen_shli_i32(tmp2, tmp2, 16);
                             tcg_gen_or_i32(tmp, tmp, tmp2);
@@ -4339,10 +4339,10 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                             tmp = neon_load_reg(rd, pass);
                             tmp2 = tcg_temp_new_i32();
                             tcg_gen_shri_i32(tmp2, tmp, 16);
-                            gen_aa32_st16(tmp, addr, get_mem_index(s));
+                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp);
                             tcg_gen_addi_i32(addr, addr, stride);
-                            gen_aa32_st16(tmp2, addr, get_mem_index(s));
+                            gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp2);
                             tcg_gen_addi_i32(addr, addr, stride);
                         }
@@ -4351,7 +4351,7 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                             TCGV_UNUSED_I32(tmp2);
                             for (n = 0; n < 4; n++) {
                                 tmp = tcg_temp_new_i32();
-                                gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                                gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                                 tcg_gen_addi_i32(addr, addr, stride);
                                 if (n == 0) {
                                     tmp2 = tmp;
@@ -4371,7 +4371,7 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                                 } else {
                                     tcg_gen_shri_i32(tmp, tmp2, n * 8);
                                 }
-                                gen_aa32_st8(tmp, addr, get_mem_index(s));
+                                gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                                 tcg_temp_free_i32(tmp);
                                 tcg_gen_addi_i32(addr, addr, stride);
                             }
@@ -4495,13 +4495,13 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                     tmp = tcg_temp_new_i32();
                     switch (size) {
                     case 0:
-                        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                         break;
                     case 1:
-                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                         break;
                     case 2:
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         break;
                     default: /* Avoid compiler warnings.  */
                         abort();
@@ -4519,13 +4519,13 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
                         tcg_gen_shri_i32(tmp, tmp, shift);
                     switch (size) {
                     case 0:
-                        gen_aa32_st8(tmp, addr, get_mem_index(s));
+                        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                         break;
                     case 1:
-                        gen_aa32_st16(tmp, addr, get_mem_index(s));
+                        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                         break;
                     case 2:
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         break;
                     }
                     tcg_temp_free_i32(tmp);
@@ -7279,14 +7279,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
 
     switch (size) {
     case 0:
-        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
         break;
     case 1:
-        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
         break;
     case 2:
     case 3:
-        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
         break;
     default:
         abort();
@@ -7297,7 +7297,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
         TCGv_i32 tmp3 = tcg_temp_new_i32();
 
         tcg_gen_addi_i32(tmp2, addr, 4);
-        gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
         tcg_temp_free_i32(tmp2);
         tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
         store_reg(s, rt2, tmp3);
@@ -7348,14 +7348,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tmp = tcg_temp_new_i32();
     switch (size) {
     case 0:
-        gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
         break;
     case 1:
-        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
         break;
     case 2:
     case 3:
-        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
         break;
     default:
         abort();
@@ -7366,7 +7366,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
         TCGv_i32 tmp2 = tcg_temp_new_i32();
         TCGv_i32 tmp3 = tcg_temp_new_i32();
         tcg_gen_addi_i32(tmp2, addr, 4);
-        gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
+        gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
         tcg_temp_free_i32(tmp2);
         tcg_gen_concat_i32_i64(val64, tmp, tmp3);
         tcg_temp_free_i32(tmp3);
@@ -7381,14 +7381,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     tmp = load_reg(s, rt);
     switch (size) {
     case 0:
-        gen_aa32_st8(tmp, addr, get_mem_index(s));
+        gen_aa32_st8(s, tmp, addr, get_mem_index(s));
         break;
     case 1:
-        gen_aa32_st16(tmp, addr, get_mem_index(s));
+        gen_aa32_st16(s, tmp, addr, get_mem_index(s));
         break;
     case 2:
     case 3:
-        gen_aa32_st32(tmp, addr, get_mem_index(s));
+        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
         break;
     default:
         abort();
@@ -7397,7 +7397,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     if (size == 3) {
         tcg_gen_addi_i32(addr, addr, 4);
         tmp = load_reg(s, rt2);
-        gen_aa32_st32(tmp, addr, get_mem_index(s));
+        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
         tcg_temp_free_i32(tmp);
     }
     tcg_gen_movi_i32(cpu_R[rd], 0);
@@ -7444,11 +7444,11 @@ static void gen_srs(DisasContext *s,
     }
     tcg_gen_addi_i32(addr, addr, offset);
     tmp = load_reg(s, 14);
-    gen_aa32_st32(tmp, addr, get_mem_index(s));
+    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
     tcg_temp_free_i32(tmp);
     tmp = load_cpu_field(spsr);
     tcg_gen_addi_i32(addr, addr, 4);
-    gen_aa32_st32(tmp, addr, get_mem_index(s));
+    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
     tcg_temp_free_i32(tmp);
     if (writeback) {
         switch (amode) {
@@ -7601,10 +7601,10 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                 tcg_gen_addi_i32(addr, addr, offset);
             /* Load PC into tmp and CPSR into tmp2.  */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             tcg_gen_addi_i32(addr, addr, 4);
             tmp2 = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
             if (insn & (1 << 21)) {
                 /* Base writeback.  */
                 switch (i) {
@@ -8198,13 +8198,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                                 tmp = tcg_temp_new_i32();
                                 switch (op1) {
                                 case 0: /* lda */
-                                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                                     break;
                                 case 2: /* ldab */
-                                    gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                                    gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                                     break;
                                 case 3: /* ldah */
-                                    gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                                    gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                                     break;
                                 default:
                                     abort();
@@ -8215,13 +8215,13 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                                 tmp = load_reg(s, rm);
                                 switch (op1) {
                                 case 0: /* stl */
-                                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                                     break;
                                 case 2: /* stlb */
-                                    gen_aa32_st8(tmp, addr, get_mem_index(s));
+                                    gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                                     break;
                                 case 3: /* stlh */
-                                    gen_aa32_st16(tmp, addr, get_mem_index(s));
+                                    gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                                     break;
                                 default:
                                     abort();
@@ -8276,11 +8276,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                         tmp = load_reg(s, rm);
                         tmp2 = tcg_temp_new_i32();
                         if (insn & (1 << 22)) {
-                            gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
-                            gen_aa32_st8(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld8u(s, tmp2, addr, get_mem_index(s));
+                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                         } else {
-                            gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         }
                         tcg_temp_free_i32(tmp);
                         tcg_temp_free_i32(addr);
@@ -8302,14 +8302,14 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                     tmp = tcg_temp_new_i32();
                     switch(sh) {
                     case 1:
-                        gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                         break;
                     case 2:
-                        gen_aa32_ld8s(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
                         break;
                     default:
                     case 3:
-                        gen_aa32_ld16s(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
                         break;
                     }
                     load = 1;
@@ -8319,21 +8319,21 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                     if (sh & 1) {
                         /* store */
                         tmp = load_reg(s, rd);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                         tcg_gen_addi_i32(addr, addr, 4);
                         tmp = load_reg(s, rd + 1);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                         load = 0;
                     } else {
                         /* load */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         store_reg(s, rd, tmp);
                         tcg_gen_addi_i32(addr, addr, 4);
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         rd++;
                         load = 1;
                     }
@@ -8341,7 +8341,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                 } else {
                     /* store */
                     tmp = load_reg(s, rd);
-                    gen_aa32_st16(tmp, addr, get_mem_index(s));
+                    gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                     load = 0;
                 }
@@ -8691,17 +8691,17 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                 /* load */
                 tmp = tcg_temp_new_i32();
                 if (insn & (1 << 22)) {
-                    gen_aa32_ld8u(tmp, tmp2, i);
+                    gen_aa32_ld8u(s, tmp, tmp2, i);
                 } else {
-                    gen_aa32_ld32u(tmp, tmp2, i);
+                    gen_aa32_ld32u(s, tmp, tmp2, i);
                 }
             } else {
                 /* store */
                 tmp = load_reg(s, rd);
                 if (insn & (1 << 22)) {
-                    gen_aa32_st8(tmp, tmp2, i);
+                    gen_aa32_st8(s, tmp, tmp2, i);
                 } else {
-                    gen_aa32_st32(tmp, tmp2, i);
+                    gen_aa32_st32(s, tmp, tmp2, i);
                 }
                 tcg_temp_free_i32(tmp);
             }
@@ -8768,7 +8768,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                         if (insn & (1 << 20)) {
                             /* load */
                             tmp = tcg_temp_new_i32();
-                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                             if (user) {
                                 tmp2 = tcg_const_i32(i);
                                 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
@@ -8795,7 +8795,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
                             } else {
                                 tmp = load_reg(s, i);
                             }
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                             tcg_temp_free_i32(tmp);
                         }
                         j++;
@@ -9061,20 +9061,20 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                 if (insn & (1 << 20)) {
                     /* ldrd */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     store_reg(s, rs, tmp);
                     tcg_gen_addi_i32(addr, addr, 4);
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     store_reg(s, rd, tmp);
                 } else {
                     /* strd */
                     tmp = load_reg(s, rs);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                     tcg_gen_addi_i32(addr, addr, 4);
                     tmp = load_reg(s, rd);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 if (insn & (1 << 21)) {
@@ -9112,11 +9112,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     tcg_gen_add_i32(addr, addr, tmp);
                     tcg_temp_free_i32(tmp);
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                 } else { /* tbb */
                     tcg_temp_free_i32(tmp);
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                 }
                 tcg_temp_free_i32(addr);
                 tcg_gen_shli_i32(tmp, tmp, 1);
@@ -9153,13 +9153,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                         tmp = tcg_temp_new_i32();
                         switch (op) {
                         case 0: /* ldab */
-                            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
                             break;
                         case 1: /* ldah */
-                            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
                             break;
                         case 2: /* lda */
-                            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                             break;
                         default:
                             abort();
@@ -9169,13 +9169,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                         tmp = load_reg(s, rs);
                         switch (op) {
                         case 0: /* stlb */
-                            gen_aa32_st8(tmp, addr, get_mem_index(s));
+                            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
                             break;
                         case 1: /* stlh */
-                            gen_aa32_st16(tmp, addr, get_mem_index(s));
+                            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
                             break;
                         case 2: /* stl */
-                            gen_aa32_st32(tmp, addr, get_mem_index(s));
+                            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                             break;
                         default:
                             abort();
@@ -9203,10 +9203,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                         tcg_gen_addi_i32(addr, addr, -8);
                     /* Load PC into tmp and CPSR into tmp2.  */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     tcg_gen_addi_i32(addr, addr, 4);
                     tmp2 = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
                     if (insn & (1 << 21)) {
                         /* Base writeback.  */
                         if (insn & (1 << 24)) {
@@ -9245,7 +9245,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     if (insn & (1 << 20)) {
                         /* Load.  */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         if (i == 15) {
                             gen_bx(s, tmp);
                         } else if (i == rn) {
@@ -9257,7 +9257,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     } else {
                         /* Store.  */
                         tmp = load_reg(s, i);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                     }
                     tcg_gen_addi_i32(addr, addr, 4);
@@ -10070,19 +10070,19 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
             tmp = tcg_temp_new_i32();
             switch (op) {
             case 0:
-                gen_aa32_ld8u(tmp, addr, memidx);
+                gen_aa32_ld8u(s, tmp, addr, memidx);
                 break;
             case 4:
-                gen_aa32_ld8s(tmp, addr, memidx);
+                gen_aa32_ld8s(s, tmp, addr, memidx);
                 break;
             case 1:
-                gen_aa32_ld16u(tmp, addr, memidx);
+                gen_aa32_ld16u(s, tmp, addr, memidx);
                 break;
             case 5:
-                gen_aa32_ld16s(tmp, addr, memidx);
+                gen_aa32_ld16s(s, tmp, addr, memidx);
                 break;
             case 2:
-                gen_aa32_ld32u(tmp, addr, memidx);
+                gen_aa32_ld32u(s, tmp, addr, memidx);
                 break;
             default:
                 tcg_temp_free_i32(tmp);
@@ -10099,13 +10099,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
             tmp = load_reg(s, rs);
             switch (op) {
             case 0:
-                gen_aa32_st8(tmp, addr, memidx);
+                gen_aa32_st8(s, tmp, addr, memidx);
                 break;
             case 1:
-                gen_aa32_st16(tmp, addr, memidx);
+                gen_aa32_st16(s, tmp, addr, memidx);
                 break;
             case 2:
-                gen_aa32_st32(tmp, addr, memidx);
+                gen_aa32_st32(s, tmp, addr, memidx);
                 break;
             default:
                 tcg_temp_free_i32(tmp);
@@ -10242,7 +10242,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             addr = tcg_temp_new_i32();
             tcg_gen_movi_i32(addr, val);
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(addr);
             store_reg(s, rd, tmp);
             break;
@@ -10445,28 +10445,28 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 
         switch (op) {
         case 0: /* str */
-            gen_aa32_st32(tmp, addr, get_mem_index(s));
+            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             break;
         case 1: /* strh */
-            gen_aa32_st16(tmp, addr, get_mem_index(s));
+            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
             break;
         case 2: /* strb */
-            gen_aa32_st8(tmp, addr, get_mem_index(s));
+            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
             break;
         case 3: /* ldrsb */
-            gen_aa32_ld8s(tmp, addr, get_mem_index(s));
+            gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
             break;
         case 4: /* ldr */
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             break;
         case 5: /* ldrh */
-            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
             break;
         case 6: /* ldrb */
-            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
             break;
         case 7: /* ldrsh */
-            gen_aa32_ld16s(tmp, addr, get_mem_index(s));
+            gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
             break;
         }
         if (op >= 3) { /* load */
@@ -10488,12 +10488,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st32(tmp, addr, get_mem_index(s));
+            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10510,12 +10510,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st8(tmp, addr, get_mem_index(s));
+            gen_aa32_st8(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10532,12 +10532,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st16(tmp, addr, get_mem_index(s));
+            gen_aa32_st16(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10553,12 +10553,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
         if (insn & (1 << 11)) {
             /* load */
             tmp = tcg_temp_new_i32();
-            gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
             store_reg(s, rd, tmp);
         } else {
             /* store */
             tmp = load_reg(s, rd);
-            gen_aa32_st32(tmp, addr, get_mem_index(s));
+            gen_aa32_st32(s, tmp, addr, get_mem_index(s));
             tcg_temp_free_i32(tmp);
         }
         tcg_temp_free_i32(addr);
@@ -10626,12 +10626,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                     if (insn & (1 << 11)) {
                         /* pop */
                         tmp = tcg_temp_new_i32();
-                        gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                         store_reg(s, i, tmp);
                     } else {
                         /* push */
                         tmp = load_reg(s, i);
-                        gen_aa32_st32(tmp, addr, get_mem_index(s));
+                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                         tcg_temp_free_i32(tmp);
                     }
                     /* advance to the next address.  */
@@ -10643,13 +10643,13 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 if (insn & (1 << 11)) {
                     /* pop pc */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     /* don't set the pc until the rest of the instruction
                        has completed */
                 } else {
                     /* push lr */
                     tmp = load_reg(s, 14);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 tcg_gen_addi_i32(addr, addr, 4);
@@ -10778,7 +10778,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 if (insn & (1 << 11)) {
                     /* load */
                     tmp = tcg_temp_new_i32();
-                    gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
                     if (i == rn) {
                         loaded_var = tmp;
                     } else {
@@ -10787,7 +10787,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 } else {
                     /* store */
                     tmp = load_reg(s, i);
-                    gen_aa32_st32(tmp, addr, get_mem_index(s));
+                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));
                     tcg_temp_free_i32(tmp);
                 }
                 /* advance to the next address */
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 08/11] target-arm: introduce tbflag for CPSR.E
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (6 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 07/11] target-arm: pass DisasContext to gen_aa32_ld*/st* Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:33   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 09/11] target-arm: implement setend Paolo Bonzini
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Together with the existing tb flag for SCTLR.B, this governs the
endianness of data accesses.  Note that TARGET_WORDS_BIGENDIAN is
not used, the two flags are enough because linux-user/main.c
initializes SCTRL.B and CPSR.E correctly.

Similar to bswap_code, the new predicate arm_tbflag_is_data_be only
honors SCTLR.B in user-mode emulation.  For system-mode emulation,
SCTLR.B only affects the bottom two bits of the address and all accesses
are little endian.

Now that CPSR.E is handled at translation time, implementing setend will
be trivial.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/cpu.h       | 17 +++++++++++++++++
 target-arm/translate.c | 40 +++++++++++++++++++++++++---------------
 target-arm/translate.h |  2 ++
 3 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index defd65e..a91fb4d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1136,6 +1136,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
 #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)
+#define ARM_TBFLAG_CPSR_E_SHIFT     18
+#define ARM_TBFLAG_CPSR_E_MASK      (1 << ARM_TBFLAG_CPSR_E_SHIFT)
 
 /* Bit usage when in AArch64 state */
 #define ARM_TBFLAG_AA64_EL_SHIFT    0
@@ -1162,6 +1164,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
     (((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_CPSR_E(F) \
+    (((F) & ARM_TBFLAG_CPSR_E_MASK) >> ARM_TBFLAG_CPSR_E_SHIFT)
 #define ARM_TBFLAG_AA64_EL(F) \
     (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
 #define ARM_TBFLAG_AA64_FPEN(F) \
@@ -1192,6 +1196,7 @@ static inline bool bswap_code(bool sctlr_b)
 #endif
 }
 
+
 #ifdef CONFIG_USER_ONLY
 /* get_user and put_user respectivaly return and expect data according
  * to TARGET_WORDS_BIGENDIAN, but ldrex/strex emulation needs to take
@@ -1220,6 +1225,15 @@ static inline bool arm_cpu_bswap_data(CPUARMState *env)
 }
 #endif
 
+static inline bool arm_tbflag_is_data_be(unsigned tbflags)
+{
+    return
+#ifdef CONFIG_USER_ONLY
+        ARM_TBFLAG_SCTLR_B(tbflags) ^
+#endif
+        ARM_TBFLAG_CPSR_E(tbflags);
+}
+
 static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
@@ -1255,6 +1269,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
         if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
             *flags |= ARM_TBFLAG_CPACR_FPEN_MASK;
         }
+        if (env->uncached_cpsr & CPSR_E) {
+            *flags |= ARM_TBFLAG_CPSR_E_MASK;
+        }
     }
 
     *cs_base = 0;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 4f36d48..8be8f21 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -840,23 +840,27 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
 #define DO_GEN_LD(SUFF, OPC)                                             \
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
-    tcg_gen_qemu_ld_i32(val, addr, index, OPC);                          \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
+    tcg_gen_qemu_ld_i32(val, addr, index, opc);                          \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
-    tcg_gen_qemu_st_i32(val, addr, index, OPC);                          \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
+    tcg_gen_qemu_st_i32(val, addr, index, opc);                          \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
-    tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
+    TCGMemOp opc = MO_Q | s->mo_endianness;
+    tcg_gen_qemu_ld_i64(val, addr, index, opc);
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
-    tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
+    TCGMemOp opc = MO_Q | s->mo_endianness;
+    tcg_gen_qemu_st_i64(val, addr, index, opc);
 }
 
 #else
@@ -864,34 +868,38 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
 #define DO_GEN_LD(SUFF, OPC)                                             \
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_ld_i32(val, addr64, index, OPC);                        \
+    tcg_gen_qemu_ld_i32(val, addr64, index, opc);                        \
     tcg_temp_free(addr64);                                               \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
+    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
     TCGv addr64 = tcg_temp_new();                                        \
     tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_st_i32(val, addr64, index, OPC);                        \
+    tcg_gen_qemu_st_i32(val, addr64, index, opc);                        \
     tcg_temp_free(addr64);                                               \
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
+    TCGMemOp opc = MO_Q | s->mo_endianness;
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
+    tcg_gen_qemu_ld_i64(val, addr64, index, opc);
     tcg_temp_free(addr64);
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
+    TCGMemOp opc = MO_Q | s->mo_endianness;
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
+    tcg_gen_qemu_st_i64(val, addr64, index, opc);
     tcg_temp_free(addr64);
 }
 
@@ -899,12 +907,12 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
 
 DO_GEN_LD(8s, MO_SB)
 DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_TESW)
-DO_GEN_LD(16u, MO_TEUW)
-DO_GEN_LD(32u, MO_TEUL)
+DO_GEN_LD(16s, MO_SW)
+DO_GEN_LD(16u, MO_UW)
+DO_GEN_LD(32u, MO_UL)
 DO_GEN_ST(8, MO_UB)
-DO_GEN_ST(16, MO_TEUW)
-DO_GEN_ST(32, MO_TEUL)
+DO_GEN_ST(16, MO_UW)
+DO_GEN_ST(32, MO_UL)
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 {
@@ -7552,7 +7560,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
         if ((insn & 0x0ffffdff) == 0x01010000) {
             ARCH(6);
             /* setend */
-            if (((insn >> 9) & 1) != bswap_code(s->sctlr_b)) {
+            if (((insn >> 9) & 1) != s->cpsr_e) {
                 /* Dynamic endianness switching not implemented. */
                 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
                 goto illegal_op;
@@ -10719,7 +10727,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             case 2:
                 /* setend */
                 ARCH(6);
-                if (((insn >> 3) & 1) != bswap_code(s->sctlr_b)) {
+                if (((insn >> 3) & 1) != s->cpsr_e) {
                     /* Dynamic endianness switching not implemented. */
                     qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
                     goto illegal_op;
@@ -10900,6 +10908,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
     dc->aarch64 = 0;
     dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
     dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
+    dc->cpsr_e = ARM_TBFLAG_CPSR_E(tb->flags);
+    dc->mo_endianness = arm_tbflag_is_data_be(tb->flags) ? MO_BE : MO_LE;
     dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
     dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 19f794c..928c1c3 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -17,6 +17,8 @@ typedef struct DisasContext {
     int singlestep_enabled;
     int thumb;
     int sctlr_b;
+    int cpsr_e;
+    TCGMemOp mo_endianness;
 #if !defined(CONFIG_USER_ONLY)
     int user;
 #endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 09/11] target-arm: implement setend
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (7 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 08/11] target-arm: introduce tbflag for CPSR.E Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:35   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 10/11] target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation Paolo Bonzini
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Since this is not a high-performance path, just use a helper to
flip the E bit and force a lookup in the hash table since the
flags have changed.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/helper.h    |  1 +
 target-arm/op_helper.c |  5 +++++
 target-arm/translate.c | 12 ++++++------
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/target-arm/helper.h b/target-arm/helper.h
index facfcd2..c7e3949 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
                    i32, i32, i32, i32)
 DEF_HELPER_2(exception_internal, void, env, i32)
 DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
+DEF_HELPER_1(setend, void, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 9c1ef52..30eea14 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -209,6 +209,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
     return res;
 }
 
+void HELPER(setend)(CPUARMState *env)
+{
+    env->uncached_cpsr ^= CPSR_E;
+}
+
 void HELPER(wfi)(CPUARMState *env)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 8be8f21..30e3586 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7561,9 +7561,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
             ARCH(6);
             /* setend */
             if (((insn >> 9) & 1) != s->cpsr_e) {
-                /* Dynamic endianness switching not implemented. */
-                qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-                goto illegal_op;
+                gen_helper_setend(cpu_env);
+                gen_set_pc_im(s, s->pc);
+                s->is_jmp = DISAS_JUMP;
             }
             return;
         } else if ((insn & 0x0fffff00) == 0x057ff000) {
@@ -10728,9 +10728,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 /* setend */
                 ARCH(6);
                 if (((insn >> 3) & 1) != s->cpsr_e) {
-                    /* Dynamic endianness switching not implemented. */
-                    qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-                    goto illegal_op;
+                    gen_helper_setend(cpu_env);
+                    gen_set_pc_im(s, s->pc);
+                    s->is_jmp = DISAS_JUMP;
                 }
                 break;
             case 3:
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 10/11] target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (8 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 09/11] target-arm: implement setend Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-26 14:38   ` Peter Maydell
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in " Paolo Bonzini
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

Extract everything to an inline function and simplify DO_GEN_LD/DO_GEN_ST.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/translate.c | 66 +++++++++++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 27 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 30e3586..044facb 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -837,18 +837,18 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
  */
 #if TARGET_LONG_BITS == 32
 
-#define DO_GEN_LD(SUFF, OPC)                                             \
-static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
-{                                                                        \
-    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
-    tcg_gen_qemu_ld_i32(val, addr, index, opc);                          \
+static inline void gen_aa32_ld(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
+                               TCGMemOp opc)
+{
+    opc |= s->mo_endianness;
+    tcg_gen_qemu_ld_i32(val, addr, index, opc);
 }
 
-#define DO_GEN_ST(SUFF, OPC)                                             \
-static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
-{                                                                        \
-    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
-    tcg_gen_qemu_st_i32(val, addr, index, opc);                          \
+static inline void gen_aa32_st(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
+                               TCGMemOp opc)
+{
+    opc |= s->mo_endianness;
+    tcg_gen_qemu_st_i32(val, addr, index, opc);
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
@@ -865,24 +865,24 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
 
 #else
 
-#define DO_GEN_LD(SUFF, OPC)                                             \
-static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
-{                                                                        \
-    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
-    TCGv addr64 = tcg_temp_new();                                        \
-    tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_ld_i32(val, addr64, index, opc);                        \
-    tcg_temp_free(addr64);                                               \
+static inline void gen_aa32_ld(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
+                               TCGMemOp opc)
+{
+    TCGv addr64 = tcg_temp_new();
+    opc |= s->mo_endianness;
+    tcg_gen_extu_i32_i64(addr64, addr);
+    tcg_gen_qemu_ld_i32(val, addr64, index, opc);
+    tcg_temp_free(addr64);
 }
 
-#define DO_GEN_ST(SUFF, OPC)                                             \
-static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
-{                                                                        \
-    TCGMemOp opc = (OPC) | s->mo_endianness;                             \
-    TCGv addr64 = tcg_temp_new();                                        \
-    tcg_gen_extu_i32_i64(addr64, addr);                                  \
-    tcg_gen_qemu_st_i32(val, addr64, index, opc);                        \
-    tcg_temp_free(addr64);                                               \
+static inline void gen_aa32_st(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
+                               TCGMemOp opc)
+{
+    TCGv addr64 = tcg_temp_new();
+    opc |= s->mo_endianness;
+    tcg_gen_extu_i32_i64(addr64, addr);
+    tcg_gen_qemu_st_i32(val, addr64, index, opc);
+    tcg_temp_free(addr64);
 }
 
 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
@@ -905,13 +905,25 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
 
 #endif
 
+#define DO_GEN_LD(SUFF, OPC)                                             \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
+{                                                                        \
+    gen_aa32_ld(s, val, addr, index, OPC);                               \
+}
+
+#define DO_GEN_ST(SUFF, OPC)                                             \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
+{                                                                        \
+    gen_aa32_st(s, val, addr, index, OPC);                               \
+}
+
 DO_GEN_LD(8s, MO_SB)
 DO_GEN_LD(8u, MO_UB)
 DO_GEN_LD(16s, MO_SW)
 DO_GEN_LD(16u, MO_UW)
-DO_GEN_LD(32u, MO_UL)
 DO_GEN_ST(8, MO_UB)
 DO_GEN_ST(16, MO_UW)
+DO_GEN_LD(32u, MO_UL)
 DO_GEN_ST(32, MO_UL)
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in system emulation
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (9 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 10/11] target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation Paolo Bonzini
@ 2014-06-21 12:58 ` Paolo Bonzini
  2014-06-21 20:16   ` Richard Henderson
  2014-06-26 14:43   ` Peter Maydell
  2014-12-28 12:12 ` [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Stefan Weil
  2015-06-18 18:37 ` Peter Crosthwaite
  12 siblings, 2 replies; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-21 12:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell

System emulation only has a little-endian target; BE32 mode
is implemented by adjusting the low bits of the address
for every byte and halfword load and store.  64-bit accesses
flip the low and high words.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/cpu.h       |   5 +--
 target-arm/translate.c | 114 +++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 99 insertions(+), 20 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index a91fb4d..069250f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1188,9 +1188,8 @@ static inline bool bswap_code(bool sctlr_b)
 #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.
+    /* BE32 mode is word-invariant.  In system-mode emulation,
+     * always do little-endian accesses with no swaps.
      */
     return 0;
 #endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 044facb..982bff0 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -838,16 +838,39 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
 #if TARGET_LONG_BITS == 32
 
 static inline void gen_aa32_ld(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
-                               TCGMemOp opc)
+                               TCGMemOp opc, int be32_xor)
 {
     opc |= s->mo_endianness;
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b && be32_xor) {
+        TCGv addr_be = tcg_temp_new();
+        tcg_gen_xori_i32(addr_be, addr, be32_xor);
+        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);
+        tcg_temp_free(addr_be);
+        return;
+    }
+#endif
     tcg_gen_qemu_ld_i32(val, addr, index, opc);
 }
 
 static inline void gen_aa32_st(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
-                               TCGMemOp opc)
+                               TCGMemOp opc, int be32_xor)
 {
     opc |= s->mo_endianness;
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b && be32_xor) {
+        TCGv addr_be = tcg_temp_new();
+        tcg_gen_xori_i32(addr_be, addr, be32_xor);
+        tcg_gen_qemu_st_i32(val, addr_be, index, opc);
+        tcg_temp_free(addr_be);
+    }
+#endif
     tcg_gen_qemu_st_i32(val, addr, index, opc);
 }
 
@@ -855,32 +878,68 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
 {
     TCGMemOp opc = MO_Q | s->mo_endianness;
     tcg_gen_qemu_ld_i64(val, addr, index, opc);
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b) {
+        tcg_gen_rotri_i32(val, val, 32);
+    }
+#endif
 }
 
 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
 {
     TCGMemOp opc = MO_Q | s->mo_endianness;
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b) {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_rotri_i32(tmp, val, 32);
+        tcg_gen_qemu_st_i64(tmp, addr, index, opc);
+        tcg_temp_free(tmp);
+        return;
+    }
+#endif
     tcg_gen_qemu_st_i64(val, addr, index, opc);
 }
 
 #else
 
 static inline void gen_aa32_ld(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
-                               TCGMemOp opc)
+                               TCGMemOp opc, int be32_xor)
 {
     TCGv addr64 = tcg_temp_new();
     opc |= s->mo_endianness;
     tcg_gen_extu_i32_i64(addr64, addr);
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b && be32_xor) {
+        tcg_gen_xori_i32(addr64, addr64, be32_xor);
+    }
+#endif
     tcg_gen_qemu_ld_i32(val, addr64, index, opc);
     tcg_temp_free(addr64);
 }
 
 static inline void gen_aa32_st(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
-                               TCGMemOp opc)
+                               TCGMemOp opc, int be32_xor)
 {
     TCGv addr64 = tcg_temp_new();
     opc |= s->mo_endianness;
     tcg_gen_extu_i32_i64(addr64, addr);
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b && be32_xor) {
+        tcg_gen_xori_i32(addr64, addr64, be32_xor);
+    }
+#endif
     tcg_gen_qemu_st_i32(val, addr64, index, opc);
     tcg_temp_free(addr64);
 }
@@ -891,6 +950,14 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
     tcg_gen_qemu_ld_i64(val, addr64, index, opc);
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b) {
+        tcg_gen_rotri_i32(val, val, 32);
+    }
+#endif
     tcg_temp_free(addr64);
 }
 
@@ -899,32 +966,45 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
     TCGMemOp opc = MO_Q | s->mo_endianness;
     TCGv addr64 = tcg_temp_new();
     tcg_gen_extu_i32_i64(addr64, addr);
-    tcg_gen_qemu_st_i64(val, addr64, index, opc);
+#ifndef CONFIG_USER_ONLY
+    /* Not needed for user-mode BE32 emulation, where we use MO_BE
+     * instead.
+     */
+    if (s->sctlr_b) {
+        TCGv tmp = tcg_temp_new();
+        tcg_gen_rotri_i32(tmp, val, 32);
+        tcg_gen_qemu_st_i64(tmp, addr64, index, opc);
+        tcg_temp_free(tmp);
+    } else
+#endif
+    {
+        tcg_gen_qemu_st_i64(val, addr64, index, opc);
+    }
     tcg_temp_free(addr64);
 }
 
 #endif
 
-#define DO_GEN_LD(SUFF, OPC)                                             \
+#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
-    gen_aa32_ld(s, val, addr, index, OPC);                               \
+    gen_aa32_ld(s, val, addr, index, OPC, BE32_XOR);                     \
 }
 
-#define DO_GEN_ST(SUFF, OPC)                                             \
+#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
-    gen_aa32_st(s, val, addr, index, OPC);                               \
+    gen_aa32_st(s, val, addr, index, OPC, BE32_XOR);                     \
 }
 
-DO_GEN_LD(8s, MO_SB)
-DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_SW)
-DO_GEN_LD(16u, MO_UW)
-DO_GEN_ST(8, MO_UB)
-DO_GEN_ST(16, MO_UW)
-DO_GEN_LD(32u, MO_UL)
-DO_GEN_ST(32, MO_UL)
+DO_GEN_LD(8s, MO_SB, 3)
+DO_GEN_LD(8u, MO_UB, 3)
+DO_GEN_LD(16s, MO_SW, 2)
+DO_GEN_LD(16u, MO_UW, 2)
+DO_GEN_ST(8, MO_UB, 3)
+DO_GEN_ST(16, MO_UW, 2)
+DO_GEN_LD(32u, MO_UL, 0)
+DO_GEN_ST(32, MO_UL, 0)
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 {
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in system emulation
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in " Paolo Bonzini
@ 2014-06-21 20:16   ` Richard Henderson
  2014-06-26 14:43   ` Peter Maydell
  1 sibling, 0 replies; 46+ messages in thread
From: Richard Henderson @ 2014-06-21 20:16 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: peter.maydell

On 06/21/2014 05:58 AM, Paolo Bonzini wrote:
> @@ -855,32 +878,68 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
>  {
>      TCGMemOp opc = MO_Q | s->mo_endianness;
>      tcg_gen_qemu_ld_i64(val, addr, index, opc);
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b) {
> +        tcg_gen_rotri_i32(val, val, 32);

_i64.  Would have been caught with --enable-debug-tcg.


r~

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code Paolo Bonzini
@ 2014-06-26 14:01   ` Peter Maydell
  2014-06-26 14:15     ` Paolo Bonzini
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:01 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> 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 <pbonzini@redhat.com>

> @@ -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;

This will break running BE32 binaries with "-cpu any"
(which sets all the features we know about, including
ARM_FEATURE_V7).

> +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).

Huh? LE8 is SCTLR.B == 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
> +}

> --- 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);

This is now slightly odd to read because by definition any
CPU with the A64 instruction set won't have BE32 and A64
insns are always loaded little-endian... Still, it's a
mechanical code transform so I guess it's ok.
We can clean that up later.

> @@ -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));

Don't we need a call to bswap_code() here, since we're
telling the disassembler which endianness to assume?

>          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

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode Paolo Bonzini
@ 2014-06-26 14:15   ` Peter Maydell
  2014-06-26 14:18     ` Paolo Bonzini
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:15 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Set it on startup, in signal handler frames and in new threads.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  linux-user/arm/target_cpu.h | 2 ++
>  linux-user/main.c           | 3 ++-
>  linux-user/signal.c         | 2 ++
>  target-arm/cpu.h            | 3 +++
>  4 files changed, 9 insertions(+), 1 deletions(-)
>
> diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
> index 39d65b6..d0411c7 100644
> --- a/linux-user/arm/target_cpu.h
> +++ b/linux-user/arm/target_cpu.h
> @@ -25,6 +25,8 @@ static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
>          env->regs[13] = newsp;
>      }
>      env->regs[0] = 0;
> +    env->uncached_cpsr &= ~CPSR_E;
> +    env->uncached_cpsr |= env->signal_cpsr_e;

Where does this come from? I can't see anything in the
kernel's handling of clone that changes CPSR.E...
http://lxr.free-electrons.com/source/arch/arm/kernel/process.c#L346

(There is code for handling CPSR_E in the kernel's start_thread()
macro but that is actually only called for starting new
processes, AFAICT.)

>  }
>
>  static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
> diff --git a/linux-user/main.c b/linux-user/main.c
> index dbaa42a..795a407 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -4195,7 +4195,8 @@ int main(int argc, char **argv, char **envp)
>          /* Enable BE8.  */
>          if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
>              && (info->elf_flags & EF_ARM_BE8)) {
> -            /* nothing for now, CPSR.E not emulated yet */
> +            env->uncached_cpsr |= CPSR_E;
> +            env->signal_cpsr_e = CPSR_E;
>          } else {
>              if (arm_feature(env, ARM_FEATURE_V7)) {
>                  fprintf(stderr, "BE32 binaries only supported until ARMv6\n");
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 624c34d..87ddabd 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -1609,6 +1609,8 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
>          cpsr &= ~CPSR_T;
>      }
>
> +    cpsr |= env->signal_cpsr_e;

This won't clear CPSR.E if it happened to be set;
you should probably make the earlier 'cpsr &= ~CPSR_IT;'
be 'cpsr &= ~(CPSR_IT | CPSR_E);'

> +
>      if (ka->sa_flags & TARGET_SA_RESTORER) {
>          retcode = ka->sa_restorer;
>      } else {
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 4a9d2a8..cb5be84 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -316,6 +316,9 @@ typedef struct CPUARMState {
>  #if defined(CONFIG_USER_ONLY)
>      /* For usermode syscall translation.  */
>      int eabi;
> +
> +    /* CPSR.E value for new threads and signal handlers.  */

I think "new threads and" should be deleted here, see above.

> +    uint32_t signal_cpsr_e;
>  #endif
>
>      CPU_COMMON
> --
> 1.9.3

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code
  2014-06-26 14:01   ` Peter Maydell
@ 2014-06-26 14:15     ` Paolo Bonzini
  2014-06-26 14:53       ` Peter Maydell
  0 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-26 14:15 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

Il 26/06/2014 16:01, Peter Maydell ha scritto:
> On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> 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 <pbonzini@redhat.com>
> 
>> @@ -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;
> 
> This will break running BE32 binaries with "-cpu any"
> (which sets all the features we know about, including
> ARM_FEATURE_V7).

Yes, this was on purpose.

>> +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).
> 
> Huh? LE8 is SCTLR.B == 0...

I think LE8 is an R core with SCTLR.IE=1 SCTLR.EE=1 but CPSR.E=0, i.e. 
little endian data and big-endian code.  I put it in quotes because I 
get this with SCTLR.B=1 CPSR.E=1.  The difference is user visible due 
to CPSR.E.

I can modify the comment to:

    /* BE8 (SCTLR.B = 0, TARGET_WORDS_BIGENDIAN = 1) is mixed endian.
     * The invalid combination SCTLR.B=1/CPSR.E=1/TARGET_WORDS_BIGENDIAN=0
     * would also end up as a mixed-endian mode with BE code, LE data.
     */

>> @@ -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));
> 
> Don't we need a call to bswap_code() here, since we're
> telling the disassembler which endianness to assume?

Yes, I misread the code in disas.c.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2014-06-26 14:15   ` Peter Maydell
@ 2014-06-26 14:18     ` Paolo Bonzini
  2015-06-22 22:48       ` Peter Crosthwaite
  0 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-26 14:18 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

Il 26/06/2014 16:15, Peter Maydell ha scritto:
> (There is code for handling CPSR_E in the kernel's start_thread()
> macro but that is actually only called for starting new
> processes, AFAICT.)

Yes, you're right.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation Paolo Bonzini
@ 2014-06-26 14:21   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:21 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Now that CPSR.E is set correctly, prepare for when setend will be able
> to change it; bswap data in and out of strex manually by comparing
> SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
> of using TCGMemOps).
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1192,6 +1192,34 @@ static inline bool bswap_code(bool sctlr_b)
>  #endif
>  }
>
> +#ifdef CONFIG_USER_ONLY
> +/* get_user and put_user respectivaly return and expect data according

"respectively"

> + * to TARGET_WORDS_BIGENDIAN, but ldrex/strex emulation needs to take
> + * into account CPSR.E.  Similar to bwap_code, a XOR gives exactly the

"bswap_code"

> + * required result, we just throw CPSR.E into the mix too:
> + *
> + *            TARGET_WORDS_BIGENDIAN  SCTLR.B  CPSR.E    need swap?
> + *   LE/LE                 no             0      0          no
> + *   LE/BE                 no             0      1          yes
> + *   BE8/LE                yes            0      0          yes
> + *   BE8/BE                yes            0      1          no
> + *   BE32/BE               yes            1      0          no
> + *  (BE32/LE)              yes            1      1          yes
> + *
> + * Officially, BE32 with CPSR.E=1 has "unpredictable" results.  We
> + * implement it as big-endian code, little-endian data.
> + */
> +static inline bool arm_cpu_bswap_data(CPUARMState *env)
> +{
> +    return
> +#ifdef TARGET_WORDS_BIGENDIAN
> +       1 ^
> +#endif
> +       arm_sctlr_b(env) ^
> +       !!(env->uncached_cpsr & CPSR_E);
> +}
> +#endif

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions Paolo Bonzini
@ 2014-06-26 14:22   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:22 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  linux-user/signal.c | 112 ++++++++++++++++++++++++++--------------------------
>  1 file changed, 57 insertions(+), 55 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/11] linux-user: arm: pass env to get_user_code_*
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 02/11] linux-user: arm: pass env to get_user_code_* Paolo Bonzini
@ 2014-06-26 14:23   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:23 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> This matches the idiom used by get_user_data_* later in the series,
> and will help when bswap_code will be replaced by SCTLR.B.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE Paolo Bonzini
@ 2014-06-26 14:29   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:29 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Set CPSR.E to SCTLR.EE on exception, and use SCTLR.EE also to
> determine endianness for loads during TLB misses.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/11] target-arm: pass DisasContext to gen_aa32_ld*/st*
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 07/11] target-arm: pass DisasContext to gen_aa32_ld*/st* Paolo Bonzini
@ 2014-06-26 14:31   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:31 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> We'll need the DisasContext in the next patch to retrieve the
> desired endianness, so pass it as a whole to gen_aa32_ld*/st*.
>
> Unfortunately we cannot let those functions call get_mem_index,
> because of user-mode load/store instructions.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

This pushes some lines over 80 columns; can you wrap those,
please? Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 08/11] target-arm: introduce tbflag for CPSR.E
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 08/11] target-arm: introduce tbflag for CPSR.E Paolo Bonzini
@ 2014-06-26 14:33   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Together with the existing tb flag for SCTLR.B, this governs the
> endianness of data accesses.  Note that TARGET_WORDS_BIGENDIAN is
> not used, the two flags are enough because linux-user/main.c
> initializes SCTRL.B and CPSR.E correctly.
>
> Similar to bswap_code, the new predicate arm_tbflag_is_data_be only
> honors SCTLR.B in user-mode emulation.  For system-mode emulation,
> SCTLR.B only affects the bottom two bits of the address and all accesses
> are little endian.
>
> Now that CPSR.E is handled at translation time, implementing setend will
> be trivial.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 09/11] target-arm: implement setend
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 09/11] target-arm: implement setend Paolo Bonzini
@ 2014-06-26 14:35   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:35 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Since this is not a high-performance path, just use a helper to
> flip the E bit and force a lookup in the hash table since the
> flags have changed.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 10/11] target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 10/11] target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation Paolo Bonzini
@ 2014-06-26 14:38   ` Peter Maydell
  0 siblings, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:38 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Extract everything to an inline function and simplify DO_GEN_LD/DO_GEN_ST.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

>  DO_GEN_LD(8s, MO_SB)
>  DO_GEN_LD(8u, MO_UB)
>  DO_GEN_LD(16s, MO_SW)
>  DO_GEN_LD(16u, MO_UW)
> -DO_GEN_LD(32u, MO_UL)
>  DO_GEN_ST(8, MO_UB)
>  DO_GEN_ST(16, MO_UW)
> +DO_GEN_LD(32u, MO_UL)
>  DO_GEN_ST(32, MO_UL)

Why move this DO_GEN_LD invocation in amongst the DO_GEN_STs?

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in system emulation
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in " Paolo Bonzini
  2014-06-21 20:16   ` Richard Henderson
@ 2014-06-26 14:43   ` Peter Maydell
  2014-06-26 14:51     ` Paolo Bonzini
  1 sibling, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:43 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> System emulation only has a little-endian target; BE32 mode
> is implemented by adjusting the low bits of the address
> for every byte and halfword load and store.  64-bit accesses
> flip the low and high words.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  target-arm/cpu.h       |   5 +--
>  target-arm/translate.c | 114 +++++++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 99 insertions(+), 20 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index a91fb4d..069250f 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1188,9 +1188,8 @@ static inline bool bswap_code(bool sctlr_b)
>  #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.
> +    /* BE32 mode is word-invariant.  In system-mode emulation,
> +     * always do little-endian accesses with no swaps.
>       */
>      return 0;
>  #endif
> diff --git a/target-arm/translate.c b/target-arm/translate.c
> index 044facb..982bff0 100644
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -838,16 +838,39 @@ static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
>  #if TARGET_LONG_BITS == 32
>
>  static inline void gen_aa32_ld(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
> -                               TCGMemOp opc)
> +                               TCGMemOp opc, int be32_xor)
>  {
>      opc |= s->mo_endianness;
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b && be32_xor) {
> +        TCGv addr_be = tcg_temp_new();
> +        tcg_gen_xori_i32(addr_be, addr, be32_xor);
> +        tcg_gen_qemu_ld_i32(val, addr_be, index, opc);
> +        tcg_temp_free(addr_be);
> +        return;
> +    }
> +#endif
>      tcg_gen_qemu_ld_i32(val, addr, index, opc);
>  }
>
>  static inline void gen_aa32_st(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
> -                               TCGMemOp opc)
> +                               TCGMemOp opc, int be32_xor)
>  {
>      opc |= s->mo_endianness;
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b && be32_xor) {
> +        TCGv addr_be = tcg_temp_new();
> +        tcg_gen_xori_i32(addr_be, addr, be32_xor);
> +        tcg_gen_qemu_st_i32(val, addr_be, index, opc);
> +        tcg_temp_free(addr_be);
> +    }
> +#endif
>      tcg_gen_qemu_st_i32(val, addr, index, opc);
>  }

Missing return inside the if {} ?

>
> @@ -855,32 +878,68 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
>  {
>      TCGMemOp opc = MO_Q | s->mo_endianness;
>      tcg_gen_qemu_ld_i64(val, addr, index, opc);
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b) {
> +        tcg_gen_rotri_i32(val, val, 32);
> +    }
> +#endif
>  }
>
>  static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, int index)
>  {
>      TCGMemOp opc = MO_Q | s->mo_endianness;
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b) {
> +        TCGv tmp = tcg_temp_new();
> +        tcg_gen_rotri_i32(tmp, val, 32);
> +        tcg_gen_qemu_st_i64(tmp, addr, index, opc);
> +        tcg_temp_free(tmp);
> +        return;
> +    }
> +#endif
>      tcg_gen_qemu_st_i64(val, addr, index, opc);
>  }
>
>  #else
>
>  static inline void gen_aa32_ld(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
> -                               TCGMemOp opc)
> +                               TCGMemOp opc, int be32_xor)
>  {
>      TCGv addr64 = tcg_temp_new();
>      opc |= s->mo_endianness;
>      tcg_gen_extu_i32_i64(addr64, addr);
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b && be32_xor) {
> +        tcg_gen_xori_i32(addr64, addr64, be32_xor);

_i32 op on a 64 bit val (and ditto below) ?

> +    }
> +#endif
>      tcg_gen_qemu_ld_i32(val, addr64, index, opc);
>      tcg_temp_free(addr64);
>  }
>
>  static inline void gen_aa32_st(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index,
> -                               TCGMemOp opc)
> +                               TCGMemOp opc, int be32_xor)
>  {
>      TCGv addr64 = tcg_temp_new();
>      opc |= s->mo_endianness;
>      tcg_gen_extu_i32_i64(addr64, addr);
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b && be32_xor) {
> +        tcg_gen_xori_i32(addr64, addr64, be32_xor);
> +    }
> +#endif
>      tcg_gen_qemu_st_i32(val, addr64, index, opc);
>      tcg_temp_free(addr64);
>  }
> @@ -891,6 +950,14 @@ static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
>      TCGv addr64 = tcg_temp_new();
>      tcg_gen_extu_i32_i64(addr64, addr);
>      tcg_gen_qemu_ld_i64(val, addr64, index, opc);
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b) {
> +        tcg_gen_rotri_i32(val, val, 32);
> +    }
> +#endif
>      tcg_temp_free(addr64);
>  }
>
> @@ -899,32 +966,45 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 addr, i
>      TCGMemOp opc = MO_Q | s->mo_endianness;
>      TCGv addr64 = tcg_temp_new();
>      tcg_gen_extu_i32_i64(addr64, addr);
> -    tcg_gen_qemu_st_i64(val, addr64, index, opc);
> +#ifndef CONFIG_USER_ONLY
> +    /* Not needed for user-mode BE32 emulation, where we use MO_BE
> +     * instead.
> +     */
> +    if (s->sctlr_b) {
> +        TCGv tmp = tcg_temp_new();
> +        tcg_gen_rotri_i32(tmp, val, 32);
> +        tcg_gen_qemu_st_i64(tmp, addr64, index, opc);
> +        tcg_temp_free(tmp);
> +    } else
> +#endif
> +    {
> +        tcg_gen_qemu_st_i64(val, addr64, index, opc);
> +    }
>      tcg_temp_free(addr64);
>  }
>
>  #endif
>
> -#define DO_GEN_LD(SUFF, OPC)                                             \
> +#define DO_GEN_LD(SUFF, OPC, BE32_XOR)                                   \
>  static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
>  {                                                                        \
> -    gen_aa32_ld(s, val, addr, index, OPC);                               \
> +    gen_aa32_ld(s, val, addr, index, OPC, BE32_XOR);                     \
>  }
>
> -#define DO_GEN_ST(SUFF, OPC)                                             \
> +#define DO_GEN_ST(SUFF, OPC, BE32_XOR)                                   \
>  static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, TCGv_i32 addr, int index) \
>  {                                                                        \
> -    gen_aa32_st(s, val, addr, index, OPC);                               \
> +    gen_aa32_st(s, val, addr, index, OPC, BE32_XOR);                     \
>  }
>
> -DO_GEN_LD(8s, MO_SB)
> -DO_GEN_LD(8u, MO_UB)
> -DO_GEN_LD(16s, MO_SW)
> -DO_GEN_LD(16u, MO_UW)
> -DO_GEN_ST(8, MO_UB)
> -DO_GEN_ST(16, MO_UW)
> -DO_GEN_LD(32u, MO_UL)
> -DO_GEN_ST(32, MO_UL)
> +DO_GEN_LD(8s, MO_SB, 3)
> +DO_GEN_LD(8u, MO_UB, 3)
> +DO_GEN_LD(16s, MO_SW, 2)
> +DO_GEN_LD(16u, MO_UW, 2)
> +DO_GEN_ST(8, MO_UB, 3)
> +DO_GEN_ST(16, MO_UW, 2)
> +DO_GEN_LD(32u, MO_UL, 0)
> +DO_GEN_ST(32, MO_UL, 0)
>
>  static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
>  {
> --
> 1.9.3

I wasn't expecting you to bother with the BE32 system emulation
support :-) Did you have a test case for this?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in system emulation
  2014-06-26 14:43   ` Peter Maydell
@ 2014-06-26 14:51     ` Paolo Bonzini
  0 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-26 14:51 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

Il 26/06/2014 16:43, Peter Maydell ha scritto:
> I wasn't expecting you to bother with the BE32 system emulation
> support :-) Did you have a test case for this?

No, I didn't as shown by the generally hideous quality of this patch. 
They asked for it on the mailing list and it was fairly easy to do, so I 
posted it as an addendum after the parts I actually care about for rpi. :)

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code
  2014-06-26 14:15     ` Paolo Bonzini
@ 2014-06-26 14:53       ` Peter Maydell
  2014-06-26 16:14         ` Paolo Bonzini
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2014-06-26 14:53 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: QEMU Developers

On 26 June 2014 15:15, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 26/06/2014 16:01, Peter Maydell ha scritto:
>> On 21 June 2014 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> 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 <pbonzini@redhat.com>
>>
>>> @@ -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;
>>
>> This will break running BE32 binaries with "-cpu any"
>> (which sets all the features we know about, including
>> ARM_FEATURE_V7).
>
> Yes, this was on purpose.

I would expect that anybody running BE32 binaries is
probably running them with -cpu any, since it's the
default. So breaking them is a bit harsh...

>>> +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).
>>
>> Huh? LE8 is SCTLR.B == 0...
>
> I think LE8 is an R core with SCTLR.IE=1 SCTLR.EE=1 but CPSR.E=0, i.e.
> little endian data and big-endian code.  I put it in quotes because I
> get this with SCTLR.B=1 CPSR.E=1.  The difference is user visible due
> to CPSR.E.

That's not what I would interpret "LE8" to mean... (I don't
actually think we define that term at all, but I would have
taken it to mean 'a BE8-capable system in little-endian mode',
ie CPSR.E==0 SCTLR.B==0).

SCTLR.B==1 CPSR.E==1 is UNPREDICTABLE and so we need not care
at all what it does.

If you want you can add a remark about our not supporting SCTLR.IE
since we don't support any ARMv6/ARMv7 R-class cores, but I don't
think that's really necessary.

> I can modify the comment to:
>
>     /* BE8 (SCTLR.B = 0, TARGET_WORDS_BIGENDIAN = 1) is mixed endian.
>      * The invalid combination SCTLR.B=1/CPSR.E=1/TARGET_WORDS_BIGENDIAN=0
>      * would also end up as a mixed-endian mode with BE code, LE data.
>      */

Yeah, that's fine.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code
  2014-06-26 14:53       ` Peter Maydell
@ 2014-06-26 16:14         ` Paolo Bonzini
  0 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2014-06-26 16:14 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

Il 26/06/2014 16:53, Peter Maydell ha scritto:
>>> >> This will break running BE32 binaries with "-cpu any"
>>> >> (which sets all the features we know about, including
>>> >> ARM_FEATURE_V7).
>> >
>> > Yes, this was on purpose.
> I would expect that anybody running BE32 binaries is
> probably running them with -cpu any, since it's the
> default. So breaking them is a bit harsh...
>

Yeah, it is.  I guess I can do

static inline bool arm_sctlr_b(CPUARMState *env)
{
     return
#ifndef TARGET_USER_ONLY
       !arm_feature(env, ARM_FEATURE_V7) &&
#endif
       (env->cp15.c1_sys & SCTLR_B) != 0;
}

instead.  Plus a comment of course.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (10 preceding siblings ...)
  2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in " Paolo Bonzini
@ 2014-12-28 12:12 ` Stefan Weil
  2014-12-28 21:26   ` Paolo Bonzini
  2015-06-18 18:37 ` Peter Crosthwaite
  12 siblings, 1 reply; 46+ messages in thread
From: Stefan Weil @ 2014-12-28 12:12 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: peter.maydell

Am 21.06.2014 um 14:58 schrieb Paolo Bonzini:
> This fixes the Raspberry Pi optimized memcmp library (with both user-mode
> and system-mode emulation).
>
> Compared to the previous submission, the main changes are:
>
> - I track access endianness by taking into account both SCTLR.B and CPSR.E,
>    to make the code easier to understand (though a little bit more
>    convoluted)
>
> - because of this, I prevent execution of BE32 executables with ARMv7 or v8
>    CPUs.  These CPUs do not have SCTLR.B.
>
> - because of this, I also included an untested patch to implement BE32
>    mode in system emulation (BE8 should already work with the previous
>    versions of the series).
>
> Note that I also tested the rest only with BE32, since BE8 is not included
> in linux-user-test-0.3 (it may be possible to convert BE32 to BE8 using
> ld -r?  I haven't tried yet and I'm going to travel for the rest of the
> weekend).
>
> It is a bit late for 2.1, so I wouldn't complain if this is pushed out
> to the next version.
>
> Thanks,
>
> Paolo
>
> Paolo Bonzini (11):
>    linux-user: arm: fix coding style for some linux-user signal functions
>    linux-user: arm: pass env to get_user_code_*
>    target-arm: implement SCTLR.B, drop bswap_code
>    linux-user: arm: set CPSR.E correctly for BE8 mode
>    linux-user: arm: handle CPSR.E correctly in strex emulation
>    target-arm: implement SCTLR.EE
>    target-arm: pass DisasContext to gen_aa32_ld*/st*
>    target-arm: introduce tbflag for CPSR.E
>    target-arm: implement setend
>    target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation
>    target-arm: implement BE32 mode in system emulation
>
>   linux-user/arm/target_cpu.h |   2 +
>   linux-user/main.c           |  81 ++++++--
>   linux-user/signal.c         | 114 ++++++------
>   target-arm/arm_ldst.h       |   8 +-
>   target-arm/cpu.h            |  85 ++++++++-
>   target-arm/helper.c         |  46 ++++-
>   target-arm/helper.h         |   1 +
>   target-arm/op_helper.c      |   5 +
>   target-arm/translate-a64.c  |   6 +-
>   target-arm/translate.c      | 444 +++++++++++++++++++++++++++-----------------
>   target-arm/translate.h      |   4 +-
>   11 files changed, 525 insertions(+), 271 deletions(-)

Hi Paolo,

did you abandon this patch series or are there plans for an updated 
version? I'd appreciate a fix for the Raspberry Pi memcmp issue.

Regards
Stefan

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
  2014-12-28 12:12 ` [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Stefan Weil
@ 2014-12-28 21:26   ` Paolo Bonzini
  0 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2014-12-28 21:26 UTC (permalink / raw)
  To: Stefan Weil, qemu-devel, Peter Maydell



On 28/12/2014 13:12, Stefan Weil wrote:
> Hi Paolo,
> 
> did you abandon this patch series or are there plans for an updated
> version? I'd appreciate a fix for the Raspberry Pi memcmp issue.

I hope to send it during the Christmas break.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
  2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
                   ` (11 preceding siblings ...)
  2014-12-28 12:12 ` [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Stefan Weil
@ 2015-06-18 18:37 ` Peter Crosthwaite
  2015-06-18 19:00   ` Paolo Bonzini
  12 siblings, 1 reply; 46+ messages in thread
From: Peter Crosthwaite @ 2015-06-18 18:37 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Maydell, qemu-devel@nongnu.org Developers

On Sat, Jun 21, 2014 at 5:58 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> This fixes the Raspberry Pi optimized memcmp library (with both user-mode
> and system-mode emulation).
>
> Compared to the previous submission, the main changes are:
>
> - I track access endianness by taking into account both SCTLR.B and CPSR.E,
>   to make the code easier to understand (though a little bit more
>   convoluted)
>
> - because of this, I prevent execution of BE32 executables with ARMv7 or v8
>   CPUs.  These CPUs do not have SCTLR.B.
>
> - because of this, I also included an untested patch to implement BE32
>   mode in system emulation (BE8 should already work with the previous
>   versions of the series).
>
> Note that I also tested the rest only with BE32, since BE8 is not included
> in linux-user-test-0.3 (it may be possible to convert BE32 to BE8 using
> ld -r?  I haven't tried yet and I'm going to travel for the rest of the
> weekend).
>
> It is a bit late for 2.1, so I wouldn't complain if this is pushed out
> to the next version.
>

I'm playing with this patch series to see if I can get it working for
a BE ARMv8 guest I have but there are complications now that we
support multiple ELs.

I'll make some notes on the patches.

In my rebasing, I am dropping the BE32 support for the moment to see
if I can just get a minimal BE8 thing going.

> Thanks,
>
> Paolo
>
> Paolo Bonzini (11):
>   linux-user: arm: fix coding style for some linux-user signal functions

Can we send this through to trivial as a single?

>   linux-user: arm: pass env to get_user_code_*
>   target-arm: implement SCTLR.B, drop bswap_code

Dropped these for the moment.

>   linux-user: arm: set CPSR.E correctly for BE8 mode
>   linux-user: arm: handle CPSR.E correctly in strex emulation
>   target-arm: implement SCTLR.EE
>   target-arm: pass DisasContext to gen_aa32_ld*/st*
>   target-arm: introduce tbflag for CPSR.E
>   target-arm: implement setend

>   target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation
>   target-arm: implement BE32 mode in system emulation

Dropped these two.

Regards,
Peter

>
>  linux-user/arm/target_cpu.h |   2 +
>  linux-user/main.c           |  81 ++++++--
>  linux-user/signal.c         | 114 ++++++------
>  target-arm/arm_ldst.h       |   8 +-
>  target-arm/cpu.h            |  85 ++++++++-
>  target-arm/helper.c         |  46 ++++-
>  target-arm/helper.h         |   1 +
>  target-arm/op_helper.c      |   5 +
>  target-arm/translate-a64.c  |   6 +-
>  target-arm/translate.c      | 444 +++++++++++++++++++++++++++-----------------
>  target-arm/translate.h      |   4 +-
>  11 files changed, 525 insertions(+), 271 deletions(-)
>
> --
> 1.9.3
>
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
  2015-06-18 18:37 ` Peter Crosthwaite
@ 2015-06-18 19:00   ` Paolo Bonzini
  2015-06-18 20:24     ` Peter Crosthwaite
  0 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2015-06-18 19:00 UTC (permalink / raw)
  To: Peter Crosthwaite; +Cc: Peter Maydell, qemu-devel@nongnu.org Developers



On 18/06/2015 20:37, Peter Crosthwaite wrote:
> I'm playing with this patch series to see if I can get it working for
> a BE ARMv8 guest I have but there are complications now that we
> support multiple ELs.
> 
> I'll make some notes on the patches.
> 
> In my rebasing, I am dropping the BE32 support for the moment to see
> if I can just get a minimal BE8 thing going.

I'm pushing everything I have to tcg-arm-setend on my github repo.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
  2015-06-18 19:00   ` Paolo Bonzini
@ 2015-06-18 20:24     ` Peter Crosthwaite
  2015-06-19  7:07       ` Paolo Bonzini
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Crosthwaite @ 2015-06-18 20:24 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Maydell, qemu-devel@nongnu.org Developers

On Thu, Jun 18, 2015 at 12:00 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 18/06/2015 20:37, Peter Crosthwaite wrote:
>> I'm playing with this patch series to see if I can get it working for
>> a BE ARMv8 guest I have but there are complications now that we
>> support multiple ELs.
>>
>> I'll make some notes on the patches.
>>
>> In my rebasing, I am dropping the BE32 support for the moment to see
>> if I can just get a minimal BE8 thing going.
>
> I'm pushing everything I have to tcg-arm-setend on my github repo.
>

Already found that branch and have rebased it. It looks like since
yesterday your merge base has changed but is not fully up to date. I
have rebased to the latest. Anything to look out for specifically
other than than the regime_el change?

Regards,
Peter

> Paolo
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching
  2015-06-18 20:24     ` Peter Crosthwaite
@ 2015-06-19  7:07       ` Paolo Bonzini
  0 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2015-06-19  7:07 UTC (permalink / raw)
  To: Peter Crosthwaite; +Cc: Peter Maydell, qemu-devel@nongnu.org Developers



On 18/06/2015 22:24, Peter Crosthwaite wrote:
>> >
>> > I'm pushing everything I have to tcg-arm-setend on my github repo.
>> >
> Already found that branch and have rebased it. It looks like since
> yesterday your merge base has changed but is not fully up to date.

Yes, the one before was tested but older.  This one is not tested but
includes the EL2/EL3 chanes.

> I have rebased to the latest. Anything to look out for specifically
> other than than the regime_el change?

I can't think of anything else.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2014-06-26 14:18     ` Paolo Bonzini
@ 2015-06-22 22:48       ` Peter Crosthwaite
  2015-06-23  8:04         ` Peter Maydell
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Crosthwaite @ 2015-06-22 22:48 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Maydell, QEMU Developers

On Thu, Jun 26, 2014 at 7:18 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 26/06/2014 16:15, Peter Maydell ha scritto:
>>
>> (There is code for handling CPSR_E in the kernel's start_thread()
>> macro but that is actually only called for starting new
>> processes, AFAICT.)
>
>
> Yes, you're right.
>

So I am struggling on figuring out the need to have this extra state
of signal_cpsr_e. Is it still needed and to follow up, would something
similar be needed for SCTLR.E0E on AA64 support?

Regards,
Peter

> Paolo
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-22 22:48       ` Peter Crosthwaite
@ 2015-06-23  8:04         ` Peter Maydell
  2015-06-23 18:43           ` Peter Crosthwaite
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2015-06-23  8:04 UTC (permalink / raw)
  To: Peter Crosthwaite; +Cc: Paolo Bonzini, QEMU Developers

On 22 June 2015 at 23:48, Peter Crosthwaite
<peter.crosthwaite@xilinx.com> wrote:
> On Thu, Jun 26, 2014 at 7:18 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Il 26/06/2014 16:15, Peter Maydell ha scritto:
>>>
>>> (There is code for handling CPSR_E in the kernel's start_thread()
>>> macro but that is actually only called for starting new
>>> processes, AFAICT.)
>>
>>
>> Yes, you're right.
>>
>
> So I am struggling on figuring out the need to have this extra state
> of signal_cpsr_e. Is it still needed and to follow up, would something
> similar be needed for SCTLR.E0E on AA64 support?

The Linux userland ABI says:
 (1) the ELF file defines whether an executable is BE8 or not
 (2) this setting affects:
    (a) whether we start at the process entry point in BE or LE
    (b) whether we run signal handlers in BE or LE
    (c) whether newly cloned threads start in BE or LE

signal_cpsr_e is how this patch implements that -- we set it
based on the ELF file flags, then set CPSR.E based on it:
 * in main, for the initial thread
 * in cpu_clone_regs, for subsequent threads
 * in signal.c, for signal handlers

For AArch64 BE we will need something similar. I don't know if
there's somewhere more appropriate to store this "what's the
ELF file endianness" state, but we do need to keep it somewhere...

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-23  8:04         ` Peter Maydell
@ 2015-06-23 18:43           ` Peter Crosthwaite
  2015-06-23 18:54             ` Peter Maydell
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Crosthwaite @ 2015-06-23 18:43 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, QEMU Developers

On Tue, Jun 23, 2015 at 1:04 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 22 June 2015 at 23:48, Peter Crosthwaite
> <peter.crosthwaite@xilinx.com> wrote:
>> On Thu, Jun 26, 2014 at 7:18 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> Il 26/06/2014 16:15, Peter Maydell ha scritto:
>>>>
>>>> (There is code for handling CPSR_E in the kernel's start_thread()
>>>> macro but that is actually only called for starting new
>>>> processes, AFAICT.)
>>>
>>>
>>> Yes, you're right.
>>>
>>
>> So I am struggling on figuring out the need to have this extra state
>> of signal_cpsr_e. Is it still needed and to follow up, would something
>> similar be needed for SCTLR.E0E on AA64 support?
>
> The Linux userland ABI says:
>  (1) the ELF file defines whether an executable is BE8 or not
>  (2) this setting affects:
>     (a) whether we start at the process entry point in BE or LE
>     (b) whether we run signal handlers in BE or LE
>     (c) whether newly cloned threads start in BE or LE
>
> signal_cpsr_e is how this patch implements that -- we set it
> based on the ELF file flags, then set CPSR.E based on it:
>  * in main, for the initial thread
>  * in cpu_clone_regs, for subsequent threads
>  * in signal.c, for signal handlers
>
> For AArch64 BE we will need something similar. I don't know if
> there's somewhere more appropriate to store this "what's the
> ELF file endianness" state, but we do need to keep it somewhere...
>

So my current thinking is the new state captured in TB flags,
disas-context and this thing is just a bool for endianess. No sense of
CPSR.E or SCTLR.xx in the newly added state across the series. The TB
flag is then based on SCTLR.EE, SCTLR.E0E or CPSR.E depending on
processor mode. We already have arm_cpu_is_big_endian() to calculate
this.

That means that this logic would change signal_cpsr_e to a generic
endianess bool that will set both SCTLR_EL1.E0E and CPSR.E at all the
points Paolo is patching. SCTLR.EEs shouldn't need patching as
usermode shouldn't be affected (maybe add an assert in
arm_cpu_big_endian for usermode).

Regards,
Peter

> thanks
> -- PMM
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-23 18:43           ` Peter Crosthwaite
@ 2015-06-23 18:54             ` Peter Maydell
  2015-06-23 20:30               ` Peter Crosthwaite
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2015-06-23 18:54 UTC (permalink / raw)
  To: Peter Crosthwaite; +Cc: Paolo Bonzini, QEMU Developers

On 23 June 2015 at 19:43, Peter Crosthwaite
<peter.crosthwaite@xilinx.com> wrote:
> On Tue, Jun 23, 2015 at 1:04 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>> The Linux userland ABI says:
>>  (1) the ELF file defines whether an executable is BE8 or not
>>  (2) this setting affects:
>>     (a) whether we start at the process entry point in BE or LE
>>     (b) whether we run signal handlers in BE or LE
>>     (c) whether newly cloned threads start in BE or LE
>>
>> signal_cpsr_e is how this patch implements that -- we set it
>> based on the ELF file flags, then set CPSR.E based on it:
>>  * in main, for the initial thread
>>  * in cpu_clone_regs, for subsequent threads

Aside: this is a bug in the patch which I noted first time
round with code review -- new threads don't get CPSR.E reset
like this, they inherit the CPSR.E of the thread they're
cloned from.

>>  * in signal.c, for signal handlers

This is what the flag is really for.

>> For AArch64 BE we will need something similar. I don't know if
>> there's somewhere more appropriate to store this "what's the
>> ELF file endianness" state, but we do need to keep it somewhere...
>>
>
> So my current thinking is the new state captured in TB flags,
> disas-context and this thing is just a bool for endianess. No sense of
> CPSR.E or SCTLR.xx in the newly added state across the series. The TB
> flag is then based on SCTLR.EE, SCTLR.E0E or CPSR.E depending on
> processor mode. We already have arm_cpu_is_big_endian() to calculate
> this.

I'm confused. arm_cpu_is_big_endian() tells you whether the CPU
is *currently* big-endian or not. That doesn't help you with
answering the question "I'm about to run a signal handler; what
should I set the CPSR.E bit to?" in linux-user mode. That's
what signal_cpsr_e does.

> That means that this logic would change signal_cpsr_e to a generic
> endianess bool that will set both SCTLR_EL1.E0E and CPSR.E at all the
> points Paolo is patching. SCTLR.EEs shouldn't need patching as
> usermode shouldn't be affected (maybe add an assert in
> arm_cpu_big_endian for usermode).

I'm not entirely sure what you're suggesting here, but
a "generic endianness bool" sounds more confusing than something
that's specific about exactly what it's trying to control.
"endianness for data accesses", "endianness for code accesses",
"BE8 vs BE32", "setting of TARGET_WORDS_BIGENDIAN", "endianness
to use for signal handlers", "exception endianness" and so on
are all different concepts which can't necessarily be collapsed
into a single "endianness bool".

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-23 18:54             ` Peter Maydell
@ 2015-06-23 20:30               ` Peter Crosthwaite
  2015-06-23 21:34                 ` Peter Maydell
  2015-06-24 10:09                 ` Paolo Bonzini
  0 siblings, 2 replies; 46+ messages in thread
From: Peter Crosthwaite @ 2015-06-23 20:30 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, QEMU Developers

On Tue, Jun 23, 2015 at 11:54 AM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 23 June 2015 at 19:43, Peter Crosthwaite
> <peter.crosthwaite@xilinx.com> wrote:
>> On Tue, Jun 23, 2015 at 1:04 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> The Linux userland ABI says:
>>>  (1) the ELF file defines whether an executable is BE8 or not
>>>  (2) this setting affects:
>>>     (a) whether we start at the process entry point in BE or LE
>>>     (b) whether we run signal handlers in BE or LE
>>>     (c) whether newly cloned threads start in BE or LE
>>>
>>> signal_cpsr_e is how this patch implements that -- we set it
>>> based on the ELF file flags, then set CPSR.E based on it:
>>>  * in main, for the initial thread
>>>  * in cpu_clone_regs, for subsequent threads
>
> Aside: this is a bug in the patch which I noted first time
> round with code review -- new threads don't get CPSR.E reset
> like this, they inherit the CPSR.E of the thread they're
> cloned from.
>
>>>  * in signal.c, for signal handlers
>
> This is what the flag is really for.
>
>>> For AArch64 BE we will need something similar. I don't know if
>>> there's somewhere more appropriate to store this "what's the
>>> ELF file endianness" state, but we do need to keep it somewhere...
>>>
>>
>> So my current thinking is the new state captured in TB flags,
>> disas-context and this thing is just a bool for endianess. No sense of
>> CPSR.E or SCTLR.xx in the newly added state across the series. The TB
>> flag is then based on SCTLR.EE, SCTLR.E0E or CPSR.E depending on
>> processor mode. We already have arm_cpu_is_big_endian() to calculate
>> this.
>
> I'm confused. arm_cpu_is_big_endian() tells you whether the CPU
> is *currently* big-endian or not. That doesn't help you with
> answering the question "I'm about to run a signal handler; what
> should I set the CPSR.E bit to?" in linux-user mode. That's
> what signal_cpsr_e does.
>

arm_cpu_is_bigendian is the consumer of this information. We still
need some state for signal_cpsr_e, just the question is what state
does that set. If we reuse arm_cpu_is_big_endian, then signal_cpsr_e
(or its rename) needs to drive CPSR.E as well as SCTLR.E0E.

>> That means that this logic would change signal_cpsr_e to a generic
>> endianess bool that will set both SCTLR_EL1.E0E and CPSR.E at all the
>> points Paolo is patching. SCTLR.EEs shouldn't need patching as
>> usermode shouldn't be affected (maybe add an assert in
>> arm_cpu_big_endian for usermode).
>
> I'm not entirely sure what you're suggesting here, but
> a "generic endianness bool" sounds more confusing than something
> that's specific about exactly what it's trying to control.

Agree, what I am trying to get away from though is using "CPSR" or any
other regs in the naming scheme.

> "endianness for data accesses",

This can work.

 "endianness for code accesses",
> "BE8 vs BE32",

This is probably more complete, as could be an enum for LE, BE8 and BE32.

Regards,
Peter

 "setting of TARGET_WORDS_BIGENDIAN", "endianness
> to use for signal handlers", "exception endianness" and so on
> are all different concepts which can't necessarily be collapsed
> into a single "endianness bool".
>
> thanks
> -- PMM
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-23 20:30               ` Peter Crosthwaite
@ 2015-06-23 21:34                 ` Peter Maydell
  2015-06-24 10:09                 ` Paolo Bonzini
  1 sibling, 0 replies; 46+ messages in thread
From: Peter Maydell @ 2015-06-23 21:34 UTC (permalink / raw)
  To: Peter Crosthwaite; +Cc: Paolo Bonzini, QEMU Developers

On 23 June 2015 at 21:30, Peter Crosthwaite
<peter.crosthwaite@xilinx.com> wrote:
> On Tue, Jun 23, 2015 at 11:54 AM, Peter Maydell
> <peter.maydell@linaro.org> wrote:
>> On 23 June 2015 at 19:43, Peter Crosthwaite
>> <peter.crosthwaite@xilinx.com> wrote:
>> I'm confused. arm_cpu_is_big_endian() tells you whether the CPU
>> is *currently* big-endian or not. That doesn't help you with
>> answering the question "I'm about to run a signal handler; what
>> should I set the CPSR.E bit to?" in linux-user mode. That's
>> what signal_cpsr_e does.
>>
>
> arm_cpu_is_bigendian is the consumer of this information. We still
> need some state for signal_cpsr_e, just the question is what state
> does that set. If we reuse arm_cpu_is_big_endian, then signal_cpsr_e
> (or its rename) needs to drive CPSR.E as well as SCTLR.E0E.

That doesn't make sense to me. arm_cpu_is_bigendian() is asking
a runtime question about the current state of the CPU.
signal_cpsr_e is a set-once-at-startup bit of information about
the environment we're trying to run the program in. The point
at which we want to ask the question "what should we set CPSR.E
to for signal delivery" is when we try to deliver the signal;
it doesn't depend upon the current state of the CPU at all.
And (except at that exact point when we've just set CPSR.E but
haven't run any guest code) the current state of the CPU doesn't
depend on signal_cpsr_e.

>>> That means that this logic would change signal_cpsr_e to a generic
>>> endianess bool that will set both SCTLR_EL1.E0E and CPSR.E at all the
>>> points Paolo is patching. SCTLR.EEs shouldn't need patching as
>>> usermode shouldn't be affected (maybe add an assert in
>>> arm_cpu_big_endian for usermode).
>>
>> I'm not entirely sure what you're suggesting here, but
>> a "generic endianness bool" sounds more confusing than something
>> that's specific about exactly what it's trying to control.
>
> Agree, what I am trying to get away from though is using "CPSR" or any
> other regs in the naming scheme.

Certainly we can fix the naming to be less AArch32-ish. But
in general I think the logic in Paolo's patchset for AArch32
was exactly correct, and we should be trying to extend it
to cover the (actually much simpler) AArch64 cases, not
rewriting it.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-23 20:30               ` Peter Crosthwaite
  2015-06-23 21:34                 ` Peter Maydell
@ 2015-06-24 10:09                 ` Paolo Bonzini
  2015-06-24 10:21                   ` Peter Maydell
  1 sibling, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2015-06-24 10:09 UTC (permalink / raw)
  To: Peter Crosthwaite, Peter Maydell; +Cc: QEMU Developers



On 23/06/2015 22:30, Peter Crosthwaite wrote:
> > I'm confused. arm_cpu_is_big_endian() tells you whether the CPU
> > is *currently* big-endian or not. That doesn't help you with
> > answering the question "I'm about to run a signal handler; what
> > should I set the CPSR.E bit to?" in linux-user mode. That's
> > what signal_cpsr_e does.
>
> arm_cpu_is_bigendian is the consumer of this information. We still
> need some state for signal_cpsr_e, just the question is what state
> does that set. If we reuse arm_cpu_is_big_endian, then signal_cpsr_e
> (or its rename) needs to drive CPSR.E as well as SCTLR.E0E.

I think signal_cpsr_e is exactly what you want for AArch32.  It sets
CPSR.E in main and setup_return for AArch32.

For AArch64 you don't need anything because, even though the kernel does
trap setend and tweak SCTLR.E0E in response to it, setup_return doesn't
try to restore the native endianness.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-24 10:09                 ` Paolo Bonzini
@ 2015-06-24 10:21                   ` Peter Maydell
  2015-06-24 10:34                     ` Paolo Bonzini
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2015-06-24 10:21 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Crosthwaite, QEMU Developers

On 24 June 2015 at 11:09, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 23/06/2015 22:30, Peter Crosthwaite wrote:
>> > I'm confused. arm_cpu_is_big_endian() tells you whether the CPU
>> > is *currently* big-endian or not. That doesn't help you with
>> > answering the question "I'm about to run a signal handler; what
>> > should I set the CPSR.E bit to?" in linux-user mode. That's
>> > what signal_cpsr_e does.
>>
>> arm_cpu_is_bigendian is the consumer of this information. We still
>> need some state for signal_cpsr_e, just the question is what state
>> does that set. If we reuse arm_cpu_is_big_endian, then signal_cpsr_e
>> (or its rename) needs to drive CPSR.E as well as SCTLR.E0E.
>
> I think signal_cpsr_e is exactly what you want for AArch32.  It sets
> CPSR.E in main and setup_return for AArch32.
>
> For AArch64 you don't need anything because, even though the kernel does
> trap setend and tweak SCTLR.E0E in response to it, setup_return doesn't
> try to restore the native endianness.

I didn't think SETEND existed at all in AArch64? It's a 32-bit only
instruction. So the AArch64 setup is anyway much simpler because
you don't have to worry about the userspace code being a different
endianness to what you want to run the signal handler as.

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-24 10:21                   ` Peter Maydell
@ 2015-06-24 10:34                     ` Paolo Bonzini
  2015-06-24 10:48                       ` Peter Maydell
  0 siblings, 1 reply; 46+ messages in thread
From: Paolo Bonzini @ 2015-06-24 10:34 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Peter Crosthwaite, QEMU Developers



On 24/06/2015 12:21, Peter Maydell wrote:
> > I think signal_cpsr_e is exactly what you want for AArch32.  It sets
> > CPSR.E in main and setup_return for AArch32.
> >
> > For AArch64 you don't need anything because, even though the kernel does
> > trap setend and tweak SCTLR.E0E in response to it, setup_return doesn't
> > try to restore the native endianness.
>
> I didn't think SETEND existed at all in AArch64?

No, but the kernel traps it and flips SCTLR.E0E.  We don't have to
emulate that, and anyway you're right that userspace code will always be
the same endianness as the signal handler: the kernel expects it that way.

Paolo

> It's a 32-bit only
> instruction. So the AArch64 setup is anyway much simpler because
> you don't have to worry about the userspace code being a different
> endianness to what you want to run the signal handler as.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-24 10:34                     ` Paolo Bonzini
@ 2015-06-24 10:48                       ` Peter Maydell
  2015-06-24 10:49                         ` Paolo Bonzini
  0 siblings, 1 reply; 46+ messages in thread
From: Peter Maydell @ 2015-06-24 10:48 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Crosthwaite, QEMU Developers

On 24 June 2015 at 11:34, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 24/06/2015 12:21, Peter Maydell wrote:
>> > I think signal_cpsr_e is exactly what you want for AArch32.  It sets
>> > CPSR.E in main and setup_return for AArch32.
>> >
>> > For AArch64 you don't need anything because, even though the kernel does
>> > trap setend and tweak SCTLR.E0E in response to it, setup_return doesn't
>> > try to restore the native endianness.
>>
>> I didn't think SETEND existed at all in AArch64?
>
> No, but the kernel traps it and flips SCTLR.E0E.

Traps what? There is no encoding in A64, unless I'm missing something...

-- PMM

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode
  2015-06-24 10:48                       ` Peter Maydell
@ 2015-06-24 10:49                         ` Paolo Bonzini
  0 siblings, 0 replies; 46+ messages in thread
From: Paolo Bonzini @ 2015-06-24 10:49 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Peter Crosthwaite, QEMU Developers



On 24/06/2015 12:48, Peter Maydell wrote:
> > > I didn't think SETEND existed at all in AArch64?
> >
> > No, but the kernel traps it and flips SCTLR.E0E.
>
> Traps what? There is no encoding in A64, unless I'm missing something...

Ah, it's the A64 kernel executing A32 code.  So no problem.

Paolo

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2015-06-24 10:49 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-21 12:58 [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Paolo Bonzini
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 01/11] linux-user: arm: fix coding style for some linux-user signal functions Paolo Bonzini
2014-06-26 14:22   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 02/11] linux-user: arm: pass env to get_user_code_* Paolo Bonzini
2014-06-26 14:23   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 03/11] target-arm: implement SCTLR.B, drop bswap_code Paolo Bonzini
2014-06-26 14:01   ` Peter Maydell
2014-06-26 14:15     ` Paolo Bonzini
2014-06-26 14:53       ` Peter Maydell
2014-06-26 16:14         ` Paolo Bonzini
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 04/11] linux-user: arm: set CPSR.E correctly for BE8 mode Paolo Bonzini
2014-06-26 14:15   ` Peter Maydell
2014-06-26 14:18     ` Paolo Bonzini
2015-06-22 22:48       ` Peter Crosthwaite
2015-06-23  8:04         ` Peter Maydell
2015-06-23 18:43           ` Peter Crosthwaite
2015-06-23 18:54             ` Peter Maydell
2015-06-23 20:30               ` Peter Crosthwaite
2015-06-23 21:34                 ` Peter Maydell
2015-06-24 10:09                 ` Paolo Bonzini
2015-06-24 10:21                   ` Peter Maydell
2015-06-24 10:34                     ` Paolo Bonzini
2015-06-24 10:48                       ` Peter Maydell
2015-06-24 10:49                         ` Paolo Bonzini
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation Paolo Bonzini
2014-06-26 14:21   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 06/11] target-arm: implement SCTLR.EE Paolo Bonzini
2014-06-26 14:29   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 07/11] target-arm: pass DisasContext to gen_aa32_ld*/st* Paolo Bonzini
2014-06-26 14:31   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 08/11] target-arm: introduce tbflag for CPSR.E Paolo Bonzini
2014-06-26 14:33   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 09/11] target-arm: implement setend Paolo Bonzini
2014-06-26 14:35   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 10/11] target-arm: reorganize gen_aa32_ld/st to prepare for BE32 system emulation Paolo Bonzini
2014-06-26 14:38   ` Peter Maydell
2014-06-21 12:58 ` [Qemu-devel] [PATCH v3 11/11] target-arm: implement BE32 mode in " Paolo Bonzini
2014-06-21 20:16   ` Richard Henderson
2014-06-26 14:43   ` Peter Maydell
2014-06-26 14:51     ` Paolo Bonzini
2014-12-28 12:12 ` [Qemu-devel] [PATCH v3 00/11] implement dynamic endianness switching Stefan Weil
2014-12-28 21:26   ` Paolo Bonzini
2015-06-18 18:37 ` Peter Crosthwaite
2015-06-18 19:00   ` Paolo Bonzini
2015-06-18 20:24     ` Peter Crosthwaite
2015-06-19  7:07       ` Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.