* [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions
@ 2007-09-26 9:23 Aurelien Jarno
2007-09-26 9:47 ` Fabrice Bellard
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Aurelien Jarno @ 2007-09-26 9:23 UTC (permalink / raw)
To: qemu-devel
Hi,
As written in the MIPS TODO file, the lwl, lwr, ldl, ldr, swl, swr,
sdl and sdr instructions are not correctly implemented. In case of
exception the BadVAddr register gets the aligned address instead of the
unaligned original address.
In addition to that, the store instructions are generating the wrong
exception, AdEl instead of AdEs, because the current implementation
first do a load.
The patch below fixes that by accessing the bytes one by one, starting
by the unaligned original address.
Bye,
Aurelien
Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.197
diff -u -d -p -r1.197 Makefile.target
--- Makefile.target 25 Sep 2007 01:17:03 -0000 1.197
+++ Makefile.target 26 Sep 2007 09:15:49 -0000
@@ -633,7 +633,7 @@ endif
ifeq ($(TARGET_BASE_ARCH), mips)
helper.o: cpu.h exec-all.h
op.o: op_template.c fop_template.c op_mem.c exec.h cpu.h
-op_helper.o: op_helper_mem.c exec.h softmmu_template.h cpu.h
+op_helper.o: exec.h softmmu_template.h cpu.h
translate.o: translate_init.c exec-all.h disas.h
endif
Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.33
diff -u -d -p -r1.33 exec.h
--- target-mips/exec.h 25 Sep 2007 16:53:15 -0000 1.33
+++ target-mips/exec.h 26 Sep 2007 09:15:49 -0000
@@ -100,36 +100,6 @@ void fpu_dump_state(CPUState *env, FILE
int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
int flags);
void dump_sc (void);
-void do_lwl_raw (uint32_t);
-void do_lwr_raw (uint32_t);
-uint32_t do_swl_raw (uint32_t);
-uint32_t do_swr_raw (uint32_t);
-#ifdef TARGET_MIPS64
-void do_ldl_raw (uint64_t);
-void do_ldr_raw (uint64_t);
-uint64_t do_sdl_raw (uint64_t);
-uint64_t do_sdr_raw (uint64_t);
-#endif
-#if !defined(CONFIG_USER_ONLY)
-void do_lwl_user (uint32_t);
-void do_lwl_kernel (uint32_t);
-void do_lwr_user (uint32_t);
-void do_lwr_kernel (uint32_t);
-uint32_t do_swl_user (uint32_t);
-uint32_t do_swl_kernel (uint32_t);
-uint32_t do_swr_user (uint32_t);
-uint32_t do_swr_kernel (uint32_t);
-#ifdef TARGET_MIPS64
-void do_ldl_user (uint64_t);
-void do_ldl_kernel (uint64_t);
-void do_ldr_user (uint64_t);
-void do_ldr_kernel (uint64_t);
-uint64_t do_sdl_user (uint64_t);
-uint64_t do_sdl_kernel (uint64_t);
-uint64_t do_sdr_user (uint64_t);
-uint64_t do_sdr_kernel (uint64_t);
-#endif
-#endif
void do_pmon (int function);
void dump_sc (void);
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.60
diff -u -d -p -r1.60 op_helper.c
--- target-mips/op_helper.c 25 Sep 2007 16:53:15 -0000 1.60
+++ target-mips/op_helper.c 26 Sep 2007 09:15:49 -0000
@@ -62,18 +62,6 @@ void do_raise_exception_direct (uint32_t
do_raise_exception_direct_err (exception, 0);
}
-#define MEMSUFFIX _raw
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _user
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#define MEMSUFFIX _kernel
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#endif
-
#ifdef TARGET_MIPS64
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* Those might call libgcc functions. */
Index: target-mips/op_helper_mem.c
===================================================================
RCS file: target-mips/op_helper_mem.c
diff -N target-mips/op_helper_mem.c
--- target-mips/op_helper_mem.c 5 May 2007 20:13:13 -0000 1.8
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,301 +0,0 @@
-#undef DEBUG_OP
-
-#ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK(v) ((v) & 3)
-#else
-#define GET_LMASK(v) (((v) & 3) ^ 3)
-#endif
-
-void glue(do_lwl, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- T0 = (int32_t)tmp;
- break;
- case 1:
- T0 = (int32_t)((tmp << 8) | (T1 & 0x000000FF));
- break;
- case 2:
- T0 = (int32_t)((tmp << 16) | (T1 & 0x0000FFFF));
- break;
- case 3:
- T0 = (int32_t)((tmp << 24) | (T1 & 0x00FFFFFF));
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-void glue(do_lwr, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- T0 = (int32_t)((tmp >> 24) | (T1 & 0xFFFFFF00));
- break;
- case 1:
- T0 = (int32_t)((tmp >> 16) | (T1 & 0xFFFF0000));
- break;
- case 2:
- T0 = (int32_t)((tmp >> 8) | (T1 & 0xFF000000));
- break;
- case 3:
- T0 = (int32_t)tmp;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-uint32_t glue(do_swl, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- tmp = (int32_t)T1;
- break;
- case 1:
- tmp = (int32_t)((tmp & 0xFF000000) | ((uint32_t)T1 >> 8));
- break;
- case 2:
- tmp = (int32_t)((tmp & 0xFFFF0000) | ((uint32_t)T1 >> 16));
- break;
- case 3:
- tmp = (int32_t)((tmp & 0xFFFFFF00) | ((uint32_t)T1 >> 24));
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-uint32_t glue(do_swr, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- tmp = (int32_t)((tmp & 0x00FFFFFF) | (T1 << 24));
- break;
- case 1:
- tmp = (int32_t)((tmp & 0x0000FFFF) | (T1 << 16));
- break;
- case 2:
- tmp = (int32_t)((tmp & 0x000000FF) | (T1 << 8));
- break;
- case 3:
- tmp = (int32_t)T1;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-#ifdef TARGET_MIPS64
-
-#ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK64(v) ((v) & 7)
-#else
-#define GET_LMASK64(v) (((v) & 7) ^ 7)
-#endif
-
-void glue(do_ldl, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- T0 = tmp;
- break;
- case 1:
- T0 = (tmp << 8) | (T1 & 0x00000000000000FFULL);
- break;
- case 2:
- T0 = (tmp << 16) | (T1 & 0x000000000000FFFFULL);
- break;
- case 3:
- T0 = (tmp << 24) | (T1 & 0x0000000000FFFFFFULL);
- break;
- case 4:
- T0 = (tmp << 32) | (T1 & 0x00000000FFFFFFFFULL);
- break;
- case 5:
- T0 = (tmp << 40) | (T1 & 0x000000FFFFFFFFFFULL);
- break;
- case 6:
- T0 = (tmp << 48) | (T1 & 0x0000FFFFFFFFFFFFULL);
- break;
- case 7:
- T0 = (tmp << 56) | (T1 & 0x00FFFFFFFFFFFFFFULL);
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-void glue(do_ldr, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- T0 = (tmp >> 56) | (T1 & 0xFFFFFFFFFFFFFF00ULL);
- break;
- case 1:
- T0 = (tmp >> 48) | (T1 & 0xFFFFFFFFFFFF0000ULL);
- break;
- case 2:
- T0 = (tmp >> 40) | (T1 & 0xFFFFFFFFFF000000ULL);
- break;
- case 3:
- T0 = (tmp >> 32) | (T1 & 0xFFFFFFFF00000000ULL);
- break;
- case 4:
- T0 = (tmp >> 24) | (T1 & 0xFFFFFF0000000000ULL);
- break;
- case 5:
- T0 = (tmp >> 16) | (T1 & 0xFFFF000000000000ULL);
- break;
- case 6:
- T0 = (tmp >> 8) | (T1 & 0xFF00000000000000ULL);
- break;
- case 7:
- T0 = tmp;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-uint64_t glue(do_sdl, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- tmp = T1;
- break;
- case 1:
- tmp = (tmp & 0xFF00000000000000ULL) | (T1 >> 8);
- break;
- case 2:
- tmp = (tmp & 0xFFFF000000000000ULL) | (T1 >> 16);
- break;
- case 3:
- tmp = (tmp & 0xFFFFFF0000000000ULL) | (T1 >> 24);
- break;
- case 4:
- tmp = (tmp & 0xFFFFFFFF00000000ULL) | (T1 >> 32);
- break;
- case 5:
- tmp = (tmp & 0xFFFFFFFFFF000000ULL) | (T1 >> 40);
- break;
- case 6:
- tmp = (tmp & 0xFFFFFFFFFFFF0000ULL) | (T1 >> 48);
- break;
- case 7:
- tmp = (tmp & 0xFFFFFFFFFFFFFF00ULL) | (T1 >> 56);
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-uint64_t glue(do_sdr, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- tmp = (tmp & 0x00FFFFFFFFFFFFFFULL) | (T1 << 56);
- break;
- case 1:
- tmp = (tmp & 0x0000FFFFFFFFFFFFULL) | (T1 << 48);
- break;
- case 2:
- tmp = (tmp & 0x000000FFFFFFFFFFULL) | (T1 << 40);
- break;
- case 3:
- tmp = (tmp & 0x00000000FFFFFFFFULL) | (T1 << 32);
- break;
- case 4:
- tmp = (tmp & 0x0000000000FFFFFFULL) | (T1 << 24);
- break;
- case 5:
- tmp = (tmp & 0x000000000000FFFFULL) | (T1 << 16);
- break;
- case 6:
- tmp = (tmp & 0x00000000000000FFULL) | (T1 << 8);
- break;
- case 7:
- tmp = T1;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-#endif /* TARGET_MIPS64 */
Index: target-mips/op_mem.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_mem.c,v
retrieving revision 1.12
diff -u -d -p -r1.12 op_mem.c
--- target-mips/op_mem.c 16 Sep 2007 21:08:04 -0000 1.12
+++ target-mips/op_mem.c 26 Sep 2007 09:15:49 -0000
@@ -75,34 +75,92 @@ void glue(op_sw, MEMSUFFIX) (void)
/* "half" load and stores. We must do the memory access inline,
or fault handling won't work. */
-/* XXX: This is broken, CP0_BADVADDR has the wrong (aligned) value. */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK(v) ((v) & 3)
+#define GET_OFFSET(addr, offset) (addr + (offset))
+#else
+#define GET_LMASK(v) (((v) & 3) ^ 3)
+#define GET_OFFSET(addr, offset) (addr - (offset))
+#endif
+
void glue(op_lwl, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
+ target_ulong tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (int32_t)((T1 & 0x00FFFFFF) | (tmp << 24));
+
+ if (GET_LMASK(T0) <= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
+ T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+ }
+
+ if (GET_LMASK(T0) <= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
+ T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+ }
+
+ if (GET_LMASK(T0) == 0) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
+ T1 = (T1 & 0xFFFFFF00) | tmp;
+ }
RETURN();
}
void glue(op_lwr, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
+ target_ulong tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (T1 & 0xFFFFFF00) | tmp;
+
+ if (GET_LMASK(T0) >= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
+ T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+ }
+
+ if (GET_LMASK(T0) >= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
+ T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+ }
+
+ if (GET_LMASK(T0) == 3) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
+ T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
+ }
RETURN();
}
void glue(op_swl, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
- glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
+
+ if (GET_LMASK(T0) <= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK(T0) <= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK(T0) == 0)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
+
RETURN();
}
void glue(op_swr, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
- glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
+
+ if (GET_LMASK(T0) >= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK(T0) >= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK(T0) == 3)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
RETURN();
}
@@ -145,33 +203,156 @@ void glue(op_sd, MEMSUFFIX) (void)
/* "half" load and stores. We must do the memory access inline,
or fault handling won't work. */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK64(v) ((v) & 7)
+#else
+#define GET_LMASK64(v) (((v) & 7) ^ 7)
+#endif
+
void glue(op_ldl, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- CALL_FROM_TB1(glue(do_ldl, MEMSUFFIX), tmp);
+ uint64_t tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+
+ if (GET_LMASK64(T0) <= 6) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
+ T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+ }
+
+ if (GET_LMASK64(T0) <= 5) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
+ T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+ }
+
+ if (GET_LMASK64(T0) <= 4) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
+ T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+ }
+
+ if (GET_LMASK64(T0) <= 3) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
+ T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+ }
+
+ if (GET_LMASK64(T0) <= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
+ T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+ }
+
+ if (GET_LMASK64(T0) <= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
+ T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
+ }
+
+ if (GET_LMASK64(T0) == 0) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
+ T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+ }
+
RETURN();
}
void glue(op_ldr, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- CALL_FROM_TB1(glue(do_ldr, MEMSUFFIX), tmp);
+ uint64_t tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+
+ if (GET_LMASK64(T0) >= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
+ T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
+ }
+
+ if (GET_LMASK64(T0) >= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
+ T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+ }
+
+ if (GET_LMASK64(T0) >= 3) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
+ T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+ }
+
+ if (GET_LMASK64(T0) >= 4) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
+ T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+ }
+
+ if (GET_LMASK64(T0) >= 5) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
+ T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+ }
+
+ if (GET_LMASK64(T0) >= 6) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
+ T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+ }
+
+ if (GET_LMASK64(T0) == 7) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
+ T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+ }
+
RETURN();
}
void glue(op_sdl, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- tmp = CALL_FROM_TB1(glue(do_sdl, MEMSUFFIX), tmp);
- glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
+
+ if (GET_LMASK64(T0) <= 6)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
+
+ if (GET_LMASK64(T0) <= 5)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
+
+ if (GET_LMASK64(T0) <= 4)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
+
+ if (GET_LMASK64(T0) <= 3)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
+
+ if (GET_LMASK64(T0) <= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK64(T0) <= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK64(T0) <= 0)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
+
RETURN();
}
void glue(op_sdr, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- tmp = CALL_FROM_TB1(glue(do_sdr, MEMSUFFIX), tmp);
- glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
+
+ if (GET_LMASK64(T0) >= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK64(T0) >= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK64(T0) >= 3)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
+ if (GET_LMASK64(T0) >= 4)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
+
+ if (GET_LMASK64(T0) >= 5)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
+
+ if (GET_LMASK64(T0) >= 6)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
+
+ if (GET_LMASK64(T0) == 7)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
+
RETURN();
}
Index: target-mips/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.102
diff -u -d -p -r1.102 translate.c
--- target-mips/translate.c 25 Sep 2007 14:49:47 -0000 1.102
+++ target-mips/translate.c 26 Sep 2007 09:15:49 -0000
@@ -889,7 +889,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LDL:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(ldl);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "ldl";
break;
case OPC_SDL:
@@ -900,7 +900,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LDR:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(ldr);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "ldr";
break;
case OPC_SDR:
@@ -952,7 +952,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LWL:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(lwl);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "lwl";
break;
case OPC_SWL:
@@ -963,7 +963,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LWR:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(lwr);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "lwr";
break;
case OPC_SWR:
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions
2007-09-26 9:23 [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions Aurelien Jarno
@ 2007-09-26 9:47 ` Fabrice Bellard
2007-09-26 10:45 ` Aurelien Jarno
2007-09-26 9:52 ` Fabrice Bellard
2007-10-06 11:19 ` Aurelien Jarno
2 siblings, 1 reply; 6+ messages in thread
From: Fabrice Bellard @ 2007-09-26 9:47 UTC (permalink / raw)
To: qemu-devel
Aurelien Jarno wrote:
> Hi,
>
> As written in the MIPS TODO file, the lwl, lwr, ldl, ldr, swl, swr,
> sdl and sdr instructions are not correctly implemented. In case of
> exception the BadVAddr register gets the aligned address instead of the
> unaligned original address.
>
> In addition to that, the store instructions are generating the wrong
> exception, AdEl instead of AdEs, because the current implementation
> first do a load.
>
> The patch below fixes that by accessing the bytes one by one, starting
> by the unaligned original address.
>
> Bye,
> Aurelien
[...]
BTW, you could simplify a lot the implementation :
switch (GET_LMASK(T0)) {
case 0:
T0 = (int32_t)tmp;
break;
case 1:
T0 = (int32_t)((tmp << 8) | (T1 & 0x000000FF));
break;
case 2:
T0 = (int32_t)((tmp << 16) | (T1 & 0x0000FFFF));
break;
case 3:
T0 = (int32_t)((tmp << 24) | (T1 & 0x00FFFFFF));
break;
}
->
v = GET_LMASK(T0);
if (v == 0) {
T0 = tmp;
} else {
TO = (int32_t)((tmp << (8 * v)) | (T1 & ((1 << (v * 8)) - 1)));
}
Fabrice.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions
2007-09-26 9:23 [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions Aurelien Jarno
2007-09-26 9:47 ` Fabrice Bellard
@ 2007-09-26 9:52 ` Fabrice Bellard
2007-09-26 10:45 ` Aurelien Jarno
2007-10-06 11:19 ` Aurelien Jarno
2 siblings, 1 reply; 6+ messages in thread
From: Fabrice Bellard @ 2007-09-26 9:52 UTC (permalink / raw)
To: qemu-devel
Aurelien Jarno wrote:
> Hi,
>
> As written in the MIPS TODO file, the lwl, lwr, ldl, ldr, swl, swr,
> sdl and sdr instructions are not correctly implemented. In case of
> exception the BadVAddr register gets the aligned address instead of the
> unaligned original address.
>
> In addition to that, the store instructions are generating the wrong
> exception, AdEl instead of AdEs, because the current implementation
> first do a load.
>
> The patch below fixes that by accessing the bytes one by one, starting
> by the unaligned original address.
> [...]
It would be a lot more efficient to add specific code in the MIPS
exception handling.
Fabrice.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions
2007-09-26 9:47 ` Fabrice Bellard
@ 2007-09-26 10:45 ` Aurelien Jarno
0 siblings, 0 replies; 6+ messages in thread
From: Aurelien Jarno @ 2007-09-26 10:45 UTC (permalink / raw)
To: qemu-devel
Fabrice Bellard a écrit :
> Aurelien Jarno wrote:
>> Hi,
>>
>> As written in the MIPS TODO file, the lwl, lwr, ldl, ldr, swl, swr,
>> sdl and sdr instructions are not correctly implemented. In case of
>> exception the BadVAddr register gets the aligned address instead of the
>> unaligned original address.
>>
>> In addition to that, the store instructions are generating the wrong
>> exception, AdEl instead of AdEs, because the current implementation
>> first do a load.
>>
>> The patch below fixes that by accessing the bytes one by one, starting
>> by the unaligned original address.
>>
>> Bye,
>> Aurelien
>
> [...]
>
> BTW, you could simplify a lot the implementation :
>
> switch (GET_LMASK(T0)) {
> case 0:
> T0 = (int32_t)tmp;
> break;
> case 1:
> T0 = (int32_t)((tmp << 8) | (T1 & 0x000000FF));
> break;
> case 2:
> T0 = (int32_t)((tmp << 16) | (T1 & 0x0000FFFF));
> break;
> case 3:
> T0 = (int32_t)((tmp << 24) | (T1 & 0x00FFFFFF));
> break;
> }
>
> ->
>
> v = GET_LMASK(T0);
> if (v == 0) {
> T0 = tmp;
> } else {
> TO = (int32_t)((tmp << (8 * v)) | (T1 & ((1 << (v * 8)) - 1)));
> }
>
Agreed, but this code is actually removed and not added by the patch I
posted.
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions
2007-09-26 9:52 ` Fabrice Bellard
@ 2007-09-26 10:45 ` Aurelien Jarno
0 siblings, 0 replies; 6+ messages in thread
From: Aurelien Jarno @ 2007-09-26 10:45 UTC (permalink / raw)
To: qemu-devel
Fabrice Bellard a écrit :
> Aurelien Jarno wrote:
>> Hi,
>>
>> As written in the MIPS TODO file, the lwl, lwr, ldl, ldr, swl, swr,
>> sdl and sdr instructions are not correctly implemented. In case of
>> exception the BadVAddr register gets the aligned address instead of the
>> unaligned original address.
>>
>> In addition to that, the store instructions are generating the wrong
>> exception, AdEl instead of AdEs, because the current implementation
>> first do a load.
>>
>> The patch below fixes that by accessing the bytes one by one, starting
>> by the unaligned original address.
> > [...]
>
> It would be a lot more efficient to add specific code in the MIPS
> exception handling.
>
That was the first approach I tried to follow, but it is not that easy.
Basically the solution is to add a new flag to CPUMIPSState to mark
instructions that need fix when an exception occurs and then fix the
exception type and address if needed.
Given those instructions are not used that often (unaligned memory
accesses have to be avoided), I am not sure it is worth adding too much
complexity in the mmu fault and exception handling code, which is used
by all instructions.
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions
2007-09-26 9:23 [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions Aurelien Jarno
2007-09-26 9:47 ` Fabrice Bellard
2007-09-26 9:52 ` Fabrice Bellard
@ 2007-10-06 11:19 ` Aurelien Jarno
2 siblings, 0 replies; 6+ messages in thread
From: Aurelien Jarno @ 2007-10-06 11:19 UTC (permalink / raw)
To: qemu-devel
On Wed, Sep 26, 2007 at 11:23:30AM +0200, Aurelien Jarno wrote:
> Hi,
>
> As written in the MIPS TODO file, the lwl, lwr, ldl, ldr, swl, swr,
> sdl and sdr instructions are not correctly implemented. In case of
> exception the BadVAddr register gets the aligned address instead of the
> unaligned original address.
>
> In addition to that, the store instructions are generating the wrong
> exception, AdEl instead of AdEs, because the current implementation
> first do a load.
>
> The patch below fixes that by accessing the bytes one by one, starting
> by the unaligned original address.
>
The patch doesn't apply anymore to the current CVS. Please find below an
updated version.
Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.204
diff -u -d -p -r1.204 Makefile.target
--- Makefile.target 4 Oct 2007 21:53:54 -0000 1.204
+++ Makefile.target 6 Oct 2007 10:52:41 -0000
@@ -641,7 +641,7 @@ endif
ifeq ($(TARGET_BASE_ARCH), mips)
helper.o: cpu.h exec-all.h
op.o: op_template.c fop_template.c op_mem.c exec.h cpu.h
-op_helper.o: op_helper_mem.c exec.h softmmu_template.h cpu.h
+op_helper.o: exec.h softmmu_template.h cpu.h
translate.o: translate_init.c exec-all.h disas.h
endif
Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.36
diff -u -d -p -r1.36 exec.h
--- target-mips/exec.h 30 Sep 2007 01:58:33 -0000 1.36
+++ target-mips/exec.h 6 Oct 2007 10:52:42 -0000
@@ -100,36 +100,6 @@ void fpu_dump_state(CPUState *env, FILE
int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
int flags);
void dump_sc (void);
-void do_lwl_raw (uint32_t);
-void do_lwr_raw (uint32_t);
-uint32_t do_swl_raw (uint32_t);
-uint32_t do_swr_raw (uint32_t);
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
-void do_ldl_raw (uint64_t);
-void do_ldr_raw (uint64_t);
-uint64_t do_sdl_raw (uint64_t);
-uint64_t do_sdr_raw (uint64_t);
-#endif
-#if !defined(CONFIG_USER_ONLY)
-void do_lwl_user (uint32_t);
-void do_lwl_kernel (uint32_t);
-void do_lwr_user (uint32_t);
-void do_lwr_kernel (uint32_t);
-uint32_t do_swl_user (uint32_t);
-uint32_t do_swl_kernel (uint32_t);
-uint32_t do_swr_user (uint32_t);
-uint32_t do_swr_kernel (uint32_t);
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
-void do_ldl_user (uint64_t);
-void do_ldl_kernel (uint64_t);
-void do_ldr_user (uint64_t);
-void do_ldr_kernel (uint64_t);
-uint64_t do_sdl_user (uint64_t);
-uint64_t do_sdl_kernel (uint64_t);
-uint64_t do_sdr_user (uint64_t);
-uint64_t do_sdr_kernel (uint64_t);
-#endif
-#endif
void do_pmon (int function);
void dump_sc (void);
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.63
diff -u -d -p -r1.63 op_helper.c
--- target-mips/op_helper.c 30 Sep 2007 01:58:33 -0000 1.63
+++ target-mips/op_helper.c 6 Oct 2007 10:52:42 -0000
@@ -62,18 +62,6 @@ void do_raise_exception_direct (uint32_t
do_raise_exception_direct_err (exception, 0);
}
-#define MEMSUFFIX _raw
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _user
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#define MEMSUFFIX _kernel
-#include "op_helper_mem.c"
-#undef MEMSUFFIX
-#endif
-
#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* Those might call libgcc functions. */
Index: target-mips/op_helper_mem.c
===================================================================
RCS file: target-mips/op_helper_mem.c
diff -N target-mips/op_helper_mem.c
--- target-mips/op_helper_mem.c 30 Sep 2007 01:58:33 -0000 1.9
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,301 +0,0 @@
-#undef DEBUG_OP
-
-#ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK(v) ((v) & 3)
-#else
-#define GET_LMASK(v) (((v) & 3) ^ 3)
-#endif
-
-void glue(do_lwl, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- T0 = (int32_t)tmp;
- break;
- case 1:
- T0 = (int32_t)((tmp << 8) | (T1 & 0x000000FF));
- break;
- case 2:
- T0 = (int32_t)((tmp << 16) | (T1 & 0x0000FFFF));
- break;
- case 3:
- T0 = (int32_t)((tmp << 24) | (T1 & 0x00FFFFFF));
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-void glue(do_lwr, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- T0 = (int32_t)((tmp >> 24) | (T1 & 0xFFFFFF00));
- break;
- case 1:
- T0 = (int32_t)((tmp >> 16) | (T1 & 0xFFFF0000));
- break;
- case 2:
- T0 = (int32_t)((tmp >> 8) | (T1 & 0xFF000000));
- break;
- case 3:
- T0 = (int32_t)tmp;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-uint32_t glue(do_swl, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- tmp = (int32_t)T1;
- break;
- case 1:
- tmp = (int32_t)((tmp & 0xFF000000) | ((uint32_t)T1 >> 8));
- break;
- case 2:
- tmp = (int32_t)((tmp & 0xFFFF0000) | ((uint32_t)T1 >> 16));
- break;
- case 3:
- tmp = (int32_t)((tmp & 0xFFFFFF00) | ((uint32_t)T1 >> 24));
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-uint32_t glue(do_swr, MEMSUFFIX) (uint32_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK(T0)) {
- case 0:
- tmp = (int32_t)((tmp & 0x00FFFFFF) | (T1 << 24));
- break;
- case 1:
- tmp = (int32_t)((tmp & 0x0000FFFF) | (T1 << 16));
- break;
- case 2:
- tmp = (int32_t)((tmp & 0x000000FF) | (T1 << 8));
- break;
- case 3:
- tmp = (int32_t)T1;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-#if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
-
-#ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK64(v) ((v) & 7)
-#else
-#define GET_LMASK64(v) (((v) & 7) ^ 7)
-#endif
-
-void glue(do_ldl, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- T0 = tmp;
- break;
- case 1:
- T0 = (tmp << 8) | (T1 & 0x00000000000000FFULL);
- break;
- case 2:
- T0 = (tmp << 16) | (T1 & 0x000000000000FFFFULL);
- break;
- case 3:
- T0 = (tmp << 24) | (T1 & 0x0000000000FFFFFFULL);
- break;
- case 4:
- T0 = (tmp << 32) | (T1 & 0x00000000FFFFFFFFULL);
- break;
- case 5:
- T0 = (tmp << 40) | (T1 & 0x000000FFFFFFFFFFULL);
- break;
- case 6:
- T0 = (tmp << 48) | (T1 & 0x0000FFFFFFFFFFFFULL);
- break;
- case 7:
- T0 = (tmp << 56) | (T1 & 0x00FFFFFFFFFFFFFFULL);
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-void glue(do_ldr, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = T0;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- T0 = (tmp >> 56) | (T1 & 0xFFFFFFFFFFFFFF00ULL);
- break;
- case 1:
- T0 = (tmp >> 48) | (T1 & 0xFFFFFFFFFFFF0000ULL);
- break;
- case 2:
- T0 = (tmp >> 40) | (T1 & 0xFFFFFFFFFF000000ULL);
- break;
- case 3:
- T0 = (tmp >> 32) | (T1 & 0xFFFFFFFF00000000ULL);
- break;
- case 4:
- T0 = (tmp >> 24) | (T1 & 0xFFFFFF0000000000ULL);
- break;
- case 5:
- T0 = (tmp >> 16) | (T1 & 0xFFFF000000000000ULL);
- break;
- case 6:
- T0 = (tmp >> 8) | (T1 & 0xFF00000000000000ULL);
- break;
- case 7:
- T0 = tmp;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, sav, tmp, T1, T0);
- }
-#endif
- RETURN();
-}
-
-uint64_t glue(do_sdl, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- tmp = T1;
- break;
- case 1:
- tmp = (tmp & 0xFF00000000000000ULL) | (T1 >> 8);
- break;
- case 2:
- tmp = (tmp & 0xFFFF000000000000ULL) | (T1 >> 16);
- break;
- case 3:
- tmp = (tmp & 0xFFFFFF0000000000ULL) | (T1 >> 24);
- break;
- case 4:
- tmp = (tmp & 0xFFFFFFFF00000000ULL) | (T1 >> 32);
- break;
- case 5:
- tmp = (tmp & 0xFFFFFFFFFF000000ULL) | (T1 >> 40);
- break;
- case 6:
- tmp = (tmp & 0xFFFFFFFFFFFF0000ULL) | (T1 >> 48);
- break;
- case 7:
- tmp = (tmp & 0xFFFFFFFFFFFFFF00ULL) | (T1 >> 56);
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-uint64_t glue(do_sdr, MEMSUFFIX) (uint64_t tmp)
-{
-#if defined (DEBUG_OP)
- target_ulong sav = tmp;
-#endif
-
- switch (GET_LMASK64(T0)) {
- case 0:
- tmp = (tmp & 0x00FFFFFFFFFFFFFFULL) | (T1 << 56);
- break;
- case 1:
- tmp = (tmp & 0x0000FFFFFFFFFFFFULL) | (T1 << 48);
- break;
- case 2:
- tmp = (tmp & 0x000000FFFFFFFFFFULL) | (T1 << 40);
- break;
- case 3:
- tmp = (tmp & 0x00000000FFFFFFFFULL) | (T1 << 32);
- break;
- case 4:
- tmp = (tmp & 0x0000000000FFFFFFULL) | (T1 << 24);
- break;
- case 5:
- tmp = (tmp & 0x000000000000FFFFULL) | (T1 << 16);
- break;
- case 6:
- tmp = (tmp & 0x00000000000000FFULL) | (T1 << 8);
- break;
- case 7:
- tmp = T1;
- break;
- }
-#if defined (DEBUG_OP)
- if (logfile) {
- fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
- __func__, T0, sav, T1, tmp);
- }
-#endif
- RETURN();
- return tmp;
-}
-
-#endif /* TARGET_MIPSN32 || TARGET_MIPS64 */
Index: target-mips/op_mem.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_mem.c,v
retrieving revision 1.13
diff -u -d -p -r1.13 op_mem.c
--- target-mips/op_mem.c 30 Sep 2007 01:58:33 -0000 1.13
+++ target-mips/op_mem.c 6 Oct 2007 10:52:42 -0000
@@ -75,34 +75,92 @@ void glue(op_sw, MEMSUFFIX) (void)
/* "half" load and stores. We must do the memory access inline,
or fault handling won't work. */
-/* XXX: This is broken, CP0_BADVADDR has the wrong (aligned) value. */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK(v) ((v) & 3)
+#define GET_OFFSET(addr, offset) (addr + (offset))
+#else
+#define GET_LMASK(v) (((v) & 3) ^ 3)
+#define GET_OFFSET(addr, offset) (addr - (offset))
+#endif
+
void glue(op_lwl, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- CALL_FROM_TB1(glue(do_lwl, MEMSUFFIX), tmp);
+ target_ulong tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (int32_t)((T1 & 0x00FFFFFF) | (tmp << 24));
+
+ if (GET_LMASK(T0) <= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
+ T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+ }
+
+ if (GET_LMASK(T0) <= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
+ T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+ }
+
+ if (GET_LMASK(T0) == 0) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
+ T1 = (T1 & 0xFFFFFF00) | tmp;
+ }
RETURN();
}
void glue(op_lwr, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- CALL_FROM_TB1(glue(do_lwr, MEMSUFFIX), tmp);
+ target_ulong tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (T1 & 0xFFFFFF00) | tmp;
+
+ if (GET_LMASK(T0) >= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
+ T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+ }
+
+ if (GET_LMASK(T0) >= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
+ T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+ }
+
+ if (GET_LMASK(T0) == 3) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
+ T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
+ }
RETURN();
}
void glue(op_swl, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- tmp = CALL_FROM_TB1(glue(do_swl, MEMSUFFIX), tmp);
- glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 24));
+
+ if (GET_LMASK(T0) <= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK(T0) <= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK(T0) == 0)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)T1);
+
RETURN();
}
void glue(op_swr, MEMSUFFIX) (void)
{
- uint32_t tmp = glue(ldl, MEMSUFFIX)(T0 & ~3);
- tmp = CALL_FROM_TB1(glue(do_swr, MEMSUFFIX), tmp);
- glue(stl, MEMSUFFIX)(T0 & ~3, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
+
+ if (GET_LMASK(T0) >= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK(T0) >= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK(T0) == 3)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
RETURN();
}
@@ -145,33 +203,156 @@ void glue(op_sd, MEMSUFFIX) (void)
/* "half" load and stores. We must do the memory access inline,
or fault handling won't work. */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK64(v) ((v) & 7)
+#else
+#define GET_LMASK64(v) (((v) & 7) ^ 7)
+#endif
+
void glue(op_ldl, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- CALL_FROM_TB1(glue(do_ldl, MEMSUFFIX), tmp);
+ uint64_t tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+
+ if (GET_LMASK64(T0) <= 6) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 1));
+ T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+ }
+
+ if (GET_LMASK64(T0) <= 5) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 2));
+ T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+ }
+
+ if (GET_LMASK64(T0) <= 4) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 3));
+ T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+ }
+
+ if (GET_LMASK64(T0) <= 3) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 4));
+ T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+ }
+
+ if (GET_LMASK64(T0) <= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 5));
+ T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+ }
+
+ if (GET_LMASK64(T0) <= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 6));
+ T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
+ }
+
+ if (GET_LMASK64(T0) == 0) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, 7));
+ T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+ }
+
RETURN();
}
void glue(op_ldr, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- CALL_FROM_TB1(glue(do_ldr, MEMSUFFIX), tmp);
+ uint64_t tmp;
+
+ tmp = glue(ldub, MEMSUFFIX)(T0);
+ T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+
+ if (GET_LMASK64(T0) >= 1) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -1));
+ T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
+ }
+
+ if (GET_LMASK64(T0) >= 2) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -2));
+ T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+ }
+
+ if (GET_LMASK64(T0) >= 3) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -3));
+ T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+ }
+
+ if (GET_LMASK64(T0) >= 4) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -4));
+ T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+ }
+
+ if (GET_LMASK64(T0) >= 5) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -5));
+ T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+ }
+
+ if (GET_LMASK64(T0) >= 6) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -6));
+ T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+ }
+
+ if (GET_LMASK64(T0) == 7) {
+ tmp = glue(ldub, MEMSUFFIX)(GET_OFFSET(T0, -7));
+ T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+ }
+
RETURN();
}
void glue(op_sdl, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- tmp = CALL_FROM_TB1(glue(do_sdl, MEMSUFFIX), tmp);
- glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)(T1 >> 56));
+
+ if (GET_LMASK64(T0) <= 6)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
+
+ if (GET_LMASK64(T0) <= 5)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
+
+ if (GET_LMASK64(T0) <= 4)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
+
+ if (GET_LMASK64(T0) <= 3)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
+
+ if (GET_LMASK64(T0) <= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK64(T0) <= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK64(T0) <= 0)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, 7), (uint8_t)T1);
+
RETURN();
}
void glue(op_sdr, MEMSUFFIX) (void)
{
- target_long tmp = glue(ldq, MEMSUFFIX)(T0 & ~7);
- tmp = CALL_FROM_TB1(glue(do_sdr, MEMSUFFIX), tmp);
- glue(stq, MEMSUFFIX)(T0 & ~7, tmp);
+ glue(stb, MEMSUFFIX)(T0, (uint8_t)T1);
+
+ if (GET_LMASK64(T0) >= 1)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+ if (GET_LMASK64(T0) >= 2)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+ if (GET_LMASK64(T0) >= 3)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
+ if (GET_LMASK64(T0) >= 4)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
+
+ if (GET_LMASK64(T0) >= 5)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
+
+ if (GET_LMASK64(T0) >= 6)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
+
+ if (GET_LMASK64(T0) == 7)
+ glue(stb, MEMSUFFIX)(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
+
RETURN();
}
Index: target-mips/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.104
diff -u -d -p -r1.104 translate.c
--- target-mips/translate.c 30 Sep 2007 01:58:33 -0000 1.104
+++ target-mips/translate.c 6 Oct 2007 10:52:42 -0000
@@ -889,7 +889,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LDL:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(ldl);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "ldl";
break;
case OPC_SDL:
@@ -900,7 +900,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LDR:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(ldr);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "ldr";
break;
case OPC_SDR:
@@ -952,7 +952,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LWL:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(lwl);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "lwl";
break;
case OPC_SWL:
@@ -963,7 +963,7 @@ static void gen_ldst (DisasContext *ctx,
case OPC_LWR:
GEN_LOAD_REG_TN(T1, rt);
op_ldst(lwr);
- GEN_STORE_TN_REG(rt, T0);
+ GEN_STORE_TN_REG(rt, T1);
opn = "lwr";
break;
case OPC_SWR:
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-10-06 11:19 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-26 9:23 [Qemu-devel] [PATCH][MIPS] Fix [ls][wd][lr] instructions Aurelien Jarno
2007-09-26 9:47 ` Fabrice Bellard
2007-09-26 10:45 ` Aurelien Jarno
2007-09-26 9:52 ` Fabrice Bellard
2007-09-26 10:45 ` Aurelien Jarno
2007-10-06 11:19 ` Aurelien Jarno
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).