[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 1/5] target/mips: MSA instructions ld, big endian
From: |
Mateja Marjanovic |
Subject: |
[Qemu-devel] [PATCH v3 1/5] target/mips: MSA instructions ld, big endian host fix |
Date: |
Fri, 29 Mar 2019 08:36:36 +0100 |
From: Mateja Marjanovic <address@hidden>
Fix the case when the host is running on a big endian machine,
and change the approach toward ld instruction helpers.
Signed-off-by: Mateja Marjanovic <address@hidden>
---
target/mips/op_helper.c | 188 ++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 168 insertions(+), 20 deletions(-)
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index 0f272a5..0f1973e 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -4371,31 +4371,179 @@ 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)); \
+void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
+ target_ulong addr)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ MEMOP_IDX(DF_BYTE)
+#if !defined(CONFIG_USER_ONLY)
+#if !defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
+ pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
+ pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
+ pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
+ pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
+ pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
+ pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
+ pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
+ pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
+ pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
+ pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
+ pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
+ pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
+ pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
+ pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
+ pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
+#else
+ pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
+ pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
+ pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
+ pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
+ pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
+ pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
+ pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
+ pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
+ pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
+ pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
+ pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
+ pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
+ pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
+ pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
+ pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
+ pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
+#endif
+#else
+#if !defined(HOST_WORDS_BIGENDIAN)
+ pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
+ pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
+ pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
+ pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
+ pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
+ pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
+ pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
+ pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
+ pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
+ pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
+ pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
+ pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
+ pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
+ pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
+ pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
+ pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
+#else
+ pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
+ pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
+ pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
+ pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
+ pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
+ pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
+ pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
+ pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
+ pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
+ pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
+ pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
+ pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
+ pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
+ pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
+ pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
+ pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
+#endif
+#endif
}
+void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
+ target_ulong addr)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ MEMOP_IDX(DF_HALF)
#if !defined(CONFIG_USER_ONLY)
-MSA_LD_DF(DF_BYTE, b, helper_ret_ldub_mmu, oi, GETPC())
-MSA_LD_DF(DF_HALF, h, helper_ret_lduw_mmu, oi, GETPC())
-MSA_LD_DF(DF_WORD, w, helper_ret_ldul_mmu, oi, GETPC())
-MSA_LD_DF(DF_DOUBLE, d, helper_ret_ldq_mmu, oi, GETPC())
+#if !defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
+ pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
+ pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
+ pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
+ pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
+ pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
+ pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
+ pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
+#else
+ pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
+ pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
+ pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
+ pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
+ pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
+ pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
+ pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
+ pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
+#endif
+#else
+#if !defined(HOST_WORDS_BIGENDIAN)
+ pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
+ pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
+ pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
+ pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
+ pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
+ pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
+ pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
+ pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
#else
-MSA_LD_DF(DF_BYTE, b, cpu_ldub_data)
-MSA_LD_DF(DF_HALF, h, cpu_lduw_data)
-MSA_LD_DF(DF_WORD, w, cpu_ldl_data)
-MSA_LD_DF(DF_DOUBLE, d, cpu_ldq_data)
+ pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
+ pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
+ pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
+ pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
+ pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
+ pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
+ pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
+ pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
#endif
+#endif
+}
+
+void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
+ target_ulong addr)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ MEMOP_IDX(DF_WORD)
+#if !defined(CONFIG_USER_ONLY)
+#if !defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
+ pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
+ pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
+ pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
+#else
+ pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
+ pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
+ pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
+ pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
+#endif
+#else
+#if !defined(HOST_WORDS_BIGENDIAN)
+ pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
+ pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
+ pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
+ pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
+#else
+ pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
+ pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
+ pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
+ pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
+#endif
+#endif
+}
+
+void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
+ target_ulong addr)
+{
+ wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
+ MEMOP_IDX(DF_DOUBLE)
+#if !defined(CONFIG_USER_ONLY)
+ pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
+ pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
+#else
+ pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
+ pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
+#endif
+}
#define MSA_PAGESPAN(x) \
((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN/8 - 1) >= TARGET_PAGE_SIZE)
--
2.7.4
- [Qemu-devel] [PATCH v3 0/5] Add support for MSA instructions on a big endian host, Mateja Marjanovic, 2019/03/29
- [Qemu-devel] [PATCH v3 2/5] target/mips: MSA instructions st, big endian host fix, Mateja Marjanovic, 2019/03/29
- [Qemu-devel] [PATCH v3 5/5] target/mips: Different approach toward INSERT MSA instr. and big endian fix, Mateja Marjanovic, 2019/03/29
- [Qemu-devel] [PATCH v3 3/5] target/mips: Different approach toward COPY_S MSA instr. and big endian fix, Mateja Marjanovic, 2019/03/29
- [Qemu-devel] [PATCH v3 4/5] target/mips: Different approach toward COPY_U MSA instr. and big endian fix, Mateja Marjanovic, 2019/03/29
- [Qemu-devel] [PATCH v3 1/5] target/mips: MSA instructions ld, big endian host fix,
Mateja Marjanovic <=