qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/4] target/mips: Fix <ld|st>.<b|h|w|d> MSA instruct


From: Mateja Marjanovic
Subject: [Qemu-devel] [PATCH 1/4] target/mips: Fix <ld|st>.<b|h|w|d> MSA instructions for MIPS big endian host
Date: Fri, 22 Mar 2019 16:54:37 +0100

From: Mateja Marjanovic <address@hidden>

Load and store MSA instructions when executed on a MIPS
big endian CPU, didn't change the endianness, and were
behaving like on little endian.

Signed-off-by: Mateja Marjanovic <address@hidden>
---
 target/mips/op_helper.c | 79 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 24 deletions(-)

diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index 0f272a5..5441ab2 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -4371,18 +4371,37 @@ FOP_CONDN_S(sne,  (float32_lt(fst1, fst0, 
&env->active_fpu.fp_status)
 #define MEMOP_IDX(DF)
 #endif
 
-#define MSA_LD_DF(DF, TYPE, LD_INSN, ...)                               \
-void helper_msa_ld_ ## TYPE(CPUMIPSState *env, uint32_t wd,             \
-                            target_ulong addr)                          \
-{                                                                       \
-    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
-    wr_t wx;                                                            \
-    int i;                                                              \
-    MEMOP_IDX(DF)                                                       \
-    for (i = 0; i < DF_ELEMENTS(DF); i++) {                             \
-        wx.TYPE[i] = LD_INSN(env, addr + (i << DF), ##__VA_ARGS__);     \
-    }                                                                   \
-    memcpy(pwd, &wx, sizeof(wr_t));                                     \
+#if defined(HOST_WORDS_BIGENDIAN)
+    bool big_endian = 1;
+#else
+    bool big_endian = 0;
+#endif
+
+#define MSA_LD_DF(DF, TYPE, LD_INSN, ...)                                   \
+void helper_msa_ld_ ## TYPE(CPUMIPSState *env, uint32_t wd,                 \
+                            target_ulong addr)                              \
+{                                                                           \
+    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                              \
+    wr_t wx;                                                                \
+    int i, k;                                                               \
+    MEMOP_IDX(DF)                                                           \
+    if (!big_endian) {                                                      \
+        for (i = 0; i < DF_ELEMENTS(DF); i++) {                             \
+            wx.TYPE[i] = LD_INSN(env, addr + (i << DF), ##__VA_ARGS__);     \
+        }                                                                   \
+    } else {                                                                \
+        for (i = 0; i < DF_ELEMENTS(DF); i++) {                             \
+            if (i < DF_ELEMENTS(DF) / 2) {                                  \
+                k = DF_ELEMENTS(DF) / 2 - i - 1;                            \
+                wx.TYPE[i] = LD_INSN(env, addr + (k << DF), ##__VA_ARGS__); \
+            } else {                                                        \
+                k = 3 * DF_ELEMENTS(DF) / 2 - i - 1;                        \
+                wx.TYPE[i] = LD_INSN(env, addr + (k << DF), ##__VA_ARGS__); \
+            }                                                               \
+        }                                                                   \
+    }                                                                       \
+                                                                            \
+    memcpy(pwd, &wx, sizeof(wr_t));                                         \
 }
 
 #if !defined(CONFIG_USER_ONLY)
@@ -4417,18 +4436,30 @@ static inline void ensure_writable_pages(CPUMIPSState 
*env,
 #endif
 }
 
-#define MSA_ST_DF(DF, TYPE, ST_INSN, ...)                               \
-void helper_msa_st_ ## TYPE(CPUMIPSState *env, uint32_t wd,             \
-                            target_ulong addr)                          \
-{                                                                       \
-    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                          \
-    int mmu_idx = cpu_mmu_index(env, false);                           \
-    int i;                                                              \
-    MEMOP_IDX(DF)                                                       \
-    ensure_writable_pages(env, addr, mmu_idx, GETPC());                 \
-    for (i = 0; i < DF_ELEMENTS(DF); i++) {                             \
-        ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__);    \
-    }                                                                   \
+#define MSA_ST_DF(DF, TYPE, ST_INSN, ...)                                    \
+void helper_msa_st_ ## TYPE(CPUMIPSState *env, uint32_t wd,                  \
+                            target_ulong addr)                               \
+{                                                                            \
+    wr_t *pwd = &(env->active_fpu.fpr[wd].wr);                               \
+    int mmu_idx = cpu_mmu_index(env, false);                                 \
+    int i, k;                                                                \
+    MEMOP_IDX(DF)                                                            \
+    ensure_writable_pages(env, addr, mmu_idx, GETPC());                      \
+    if (!big_endian) {                                                       \
+        for (i = 0; i < DF_ELEMENTS(DF); i++) {                              \
+            ST_INSN(env, addr + (i << DF), pwd->TYPE[i], ##__VA_ARGS__);     \
+        }                                                                    \
+    } else {                                                                 \
+        for (i = 0; i < DF_ELEMENTS(DF); i++) {                              \
+            if (i < DF_ELEMENTS(DF) / 2) {                                   \
+                k = DF_ELEMENTS(DF) / 2 - i - 1;                             \
+                ST_INSN(env, addr + (k << DF), pwd->TYPE[i], ##__VA_ARGS__); \
+            } else {                                                         \
+                k = 3 * DF_ELEMENTS(DF) / 2 - i - 1;                         \
+                ST_INSN(env, addr + (k << DF), pwd->TYPE[i], ##__VA_ARGS__); \
+            }                                                                \
+        }                                                                    \
+    }                                                                        \
 }
 
 #if !defined(CONFIG_USER_ONLY)
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]