All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org
Subject: [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation
Date: Sat, 21 Jun 2014 14:58:16 +0200	[thread overview]
Message-ID: <1403355502-12288-6-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1403355502-12288-1-git-send-email-pbonzini@redhat.com>

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

  parent reply	other threads:[~2014-06-21 12:59 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Paolo Bonzini [this message]
2014-06-26 14:21   ` [Qemu-devel] [PATCH v3 05/11] linux-user: arm: handle CPSR.E correctly in strex emulation 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403355502-12288-6-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.