qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [4759] Convert unaligned load/store to TCG.


From: Thiemo Seufer
Subject: [Qemu-devel] [4759] Convert unaligned load/store to TCG.
Date: Fri, 20 Jun 2008 15:12:14 +0000

Revision: 4759
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4759
Author:   ths
Date:     2008-06-20 15:12:14 +0000 (Fri, 20 Jun 2008)

Log Message:
-----------
Convert unaligned load/store to TCG.

Modified Paths:
--------------
    trunk/configure
    trunk/target-mips/helper.h
    trunk/target-mips/op.c
    trunk/target-mips/op_helper.c
    trunk/target-mips/translate.c

Modified: trunk/configure
===================================================================
--- trunk/configure     2008-06-20 15:06:42 UTC (rev 4758)
+++ trunk/configure     2008-06-20 15:12:14 UTC (rev 4759)
@@ -1280,28 +1280,22 @@
   ;;
   mips|mipsel)
     echo "TARGET_ARCH=mips" >> $config_mak
-    echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
     echo "#define TARGET_ARCH \"mips\"" >> $config_h
     echo "#define TARGET_MIPS 1" >> $config_h
     echo "#define TARGET_ABI_MIPSO32 1" >> $config_h
-    echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
   ;;
   mipsn32|mipsn32el)
     echo "TARGET_ARCH=mipsn32" >> $config_mak
-    echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
     echo "#define TARGET_ARCH \"mipsn32\"" >> $config_h
     echo "#define TARGET_MIPS 1" >> $config_h
     echo "#define TARGET_ABI_MIPSN32 1" >> $config_h
-    echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
   ;;
   mips64|mips64el)
     echo "TARGET_ARCH=mips64" >> $config_mak
-    echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
     echo "#define TARGET_ARCH \"mips64\"" >> $config_h
     echo "#define TARGET_MIPS 1" >> $config_h
     echo "#define TARGET_MIPS64 1" >> $config_h
     echo "#define TARGET_ABI_MIPSN64 1" >> $config_h
-    echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
   ;;
   ppc)
     echo "TARGET_ARCH=ppc" >> $config_mak

Modified: trunk/target-mips/helper.h
===================================================================
--- trunk/target-mips/helper.h  2008-06-20 15:06:42 UTC (rev 4758)
+++ trunk/target-mips/helper.h  2008-06-20 15:12:14 UTC (rev 4759)
@@ -6,6 +6,17 @@
 DEF_HELPER(void, do_raise_exception, (int excp))
 DEF_HELPER(void, do_interrupt_restart, (void))
 
+#ifdef TARGET_MIPS64
+DEF_HELPER(void, do_ldl, (int mem_idx))
+DEF_HELPER(void, do_ldr, (int mem_idx))
+DEF_HELPER(void, do_sdl, (int mem_idx))
+DEF_HELPER(void, do_sdr, (int mem_idx))
+#endif
+DEF_HELPER(void, do_lwl, (int mem_idx))
+DEF_HELPER(void, do_lwr, (int mem_idx))
+DEF_HELPER(void, do_swl, (int mem_idx))
+DEF_HELPER(void, do_swr, (int mem_idx))
+
 DEF_HELPER(void, do_clo, (void))
 DEF_HELPER(void, do_clz, (void))
 #ifdef TARGET_MIPS64

Modified: trunk/target-mips/op.c
===================================================================
--- trunk/target-mips/op.c      2008-06-20 15:06:42 UTC (rev 4758)
+++ trunk/target-mips/op.c      2008-06-20 15:12:14 UTC (rev 4759)
@@ -19,29 +19,3 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
-#include "config.h"
-#include "exec.h"
-#include "host-utils.h"
-
-#ifndef CALL_FROM_TB0
-#define CALL_FROM_TB0(func) func()
-#endif
-
-/* Load and store */
-#define MEMSUFFIX _raw
-#include "op_mem.c"
-#undef MEMSUFFIX
-#if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _user
-#include "op_mem.c"
-#undef MEMSUFFIX
-
-#define MEMSUFFIX _super
-#include "op_mem.c"
-#undef MEMSUFFIX
-
-#define MEMSUFFIX _kernel
-#include "op_mem.c"
-#undef MEMSUFFIX
-#endif

Modified: trunk/target-mips/op_helper.c
===================================================================
--- trunk/target-mips/op_helper.c       2008-06-20 15:06:42 UTC (rev 4758)
+++ trunk/target-mips/op_helper.c       2008-06-20 15:12:14 UTC (rev 4759)
@@ -308,7 +308,344 @@
 }
 #endif
 
+#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 do_lwl(int mem_idx)
+{
+    target_ulong tmp;
+
 #ifdef CONFIG_USER_ONLY
+#define ldfun ldub_raw
+#else
+    int (*ldfun)(target_ulong);
+
+    switch (mem_idx)
+    {
+    case 0: ldfun = ldub_kernel; break;
+    case 1: ldfun = ldub_super; break;
+    default:
+    case 2: ldfun = ldub_user; break;
+    }
+#endif
+    tmp = ldfun(T0);
+    T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
+
+    if (GET_LMASK(T0) <= 2) {
+        tmp = ldfun(GET_OFFSET(T0, 1));
+        T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+    }
+
+    if (GET_LMASK(T0) <= 1) {
+        tmp = ldfun(GET_OFFSET(T0, 2));
+        T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+    }
+
+    if (GET_LMASK(T0) == 0) {
+        tmp = ldfun(GET_OFFSET(T0, 3));
+        T1 = (T1 & 0xFFFFFF00) | tmp;
+    }
+    T1 = (int32_t)T1;
+}
+
+void do_lwr(int mem_idx)
+{
+    target_ulong tmp;
+
+#ifdef CONFIG_USER_ONLY
+#define ldfun ldub_raw
+#else
+    int (*ldfun)(target_ulong);
+
+    switch (mem_idx)
+    {
+    case 0: ldfun = ldub_kernel; break;
+    case 1: ldfun = ldub_super; break;
+    default:
+    case 2: ldfun = ldub_user; break;
+    }
+#endif
+    tmp = ldfun(T0);
+    T1 = (T1 & 0xFFFFFF00) | tmp;
+
+    if (GET_LMASK(T0) >= 1) {
+        tmp = ldfun(GET_OFFSET(T0, -1));
+        T1 = (T1 & 0xFFFF00FF) | (tmp << 8);
+    }
+
+    if (GET_LMASK(T0) >= 2) {
+        tmp = ldfun(GET_OFFSET(T0, -2));
+        T1 = (T1 & 0xFF00FFFF) | (tmp << 16);
+    }
+
+    if (GET_LMASK(T0) == 3) {
+        tmp = ldfun(GET_OFFSET(T0, -3));
+        T1 = (T1 & 0x00FFFFFF) | (tmp << 24);
+    }
+    T1 = (int32_t)T1;
+}
+
+void do_swl(int mem_idx)
+{
+#ifdef CONFIG_USER_ONLY
+#define stfun stb_raw
+#else
+    void (*stfun)(target_ulong, int);
+
+    switch (mem_idx)
+    {
+    case 0: stfun = stb_kernel; break;
+    case 1: stfun = stb_super; break;
+    default:
+    case 2: stfun = stb_user; break;
+    }
+#endif
+    stfun(T0, (uint8_t)(T1 >> 24));
+
+    if (GET_LMASK(T0) <= 2)
+        stfun(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK(T0) <= 1)
+        stfun(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK(T0) == 0)
+        stfun(GET_OFFSET(T0, 3), (uint8_t)T1);
+}
+
+void do_swr(int mem_idx)
+{
+#ifdef CONFIG_USER_ONLY
+#define stfun stb_raw
+#else
+    void (*stfun)(target_ulong, int);
+
+    switch (mem_idx)
+    {
+    case 0: stfun = stb_kernel; break;
+    case 1: stfun = stb_super; break;
+    default:
+    case 2: stfun = stb_user; break;
+    }
+#endif
+    stfun(T0, (uint8_t)T1);
+
+    if (GET_LMASK(T0) >= 1)
+        stfun(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK(T0) >= 2)
+        stfun(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK(T0) == 3)
+        stfun(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+}
+
+#if defined(TARGET_MIPS64)
+/* "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 do_ldl(int mem_idx)
+{
+    uint64_t tmp;
+
+#ifdef CONFIG_USER_ONLY
+#define ldfun ldub_raw
+#else
+    target_ulong (*ldfun)(target_ulong);
+
+    switch (mem_idx)
+    {
+    case 0: ldfun = ldub_kernel; break;
+    case 1: ldfun = ldub_super; break;
+    default:
+    case 2: ldfun = ldub_user; break;
+    }
+#endif
+    tmp = ldfun(T0);
+    T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+
+    if (GET_LMASK64(T0) <= 6) {
+        tmp = ldfun(GET_OFFSET(T0, 1));
+        T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+    }
+
+    if (GET_LMASK64(T0) <= 5) {
+        tmp = ldfun(GET_OFFSET(T0, 2));
+        T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+    }
+
+    if (GET_LMASK64(T0) <= 4) {
+        tmp = ldfun(GET_OFFSET(T0, 3));
+        T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+    }
+
+    if (GET_LMASK64(T0) <= 3) {
+        tmp = ldfun(GET_OFFSET(T0, 4));
+        T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+    }
+
+    if (GET_LMASK64(T0) <= 2) {
+        tmp = ldfun(GET_OFFSET(T0, 5));
+        T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+    }
+
+    if (GET_LMASK64(T0) <= 1) {
+        tmp = ldfun(GET_OFFSET(T0, 6));
+        T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
+    }
+
+    if (GET_LMASK64(T0) == 0) {
+        tmp = ldfun(GET_OFFSET(T0, 7));
+        T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+    }
+}
+
+void do_ldr(int mem_idx)
+{
+    uint64_t tmp;
+
+#ifdef CONFIG_USER_ONLY
+#define ldfun ldub_raw
+#else
+    target_ulong (*ldfun)(target_ulong);
+
+    switch (mem_idx)
+    {
+    case 0: ldfun = ldub_kernel; break;
+    case 1: ldfun = ldub_super; break;
+    default:
+    case 2: ldfun = ldub_user; break;
+    }
+#endif
+    tmp = ldfun(T0);
+    T1 = (T1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
+
+    if (GET_LMASK64(T0) >= 1) {
+        tmp = ldfun(GET_OFFSET(T0, -1));
+        T1 = (T1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
+    }
+
+    if (GET_LMASK64(T0) >= 2) {
+        tmp = ldfun(GET_OFFSET(T0, -2));
+        T1 = (T1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
+    }
+
+    if (GET_LMASK64(T0) >= 3) {
+        tmp = ldfun(GET_OFFSET(T0, -3));
+        T1 = (T1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
+    }
+
+    if (GET_LMASK64(T0) >= 4) {
+        tmp = ldfun(GET_OFFSET(T0, -4));
+        T1 = (T1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
+    }
+
+    if (GET_LMASK64(T0) >= 5) {
+        tmp = ldfun(GET_OFFSET(T0, -5));
+        T1 = (T1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
+    }
+
+    if (GET_LMASK64(T0) >= 6) {
+        tmp = ldfun(GET_OFFSET(T0, -6));
+        T1 = (T1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
+    }
+
+    if (GET_LMASK64(T0) == 7) {
+        tmp = ldfun(GET_OFFSET(T0, -7));
+        T1 = (T1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
+    }
+}
+
+void do_sdl(int mem_idx)
+{
+#ifdef CONFIG_USER_ONLY
+#define stfun stb_raw
+#else
+    void (*stfun)(target_ulong, int);
+
+    switch (mem_idx)
+    {
+    case 0: stfun = stb_kernel; break;
+    case 1: stfun = stb_super; break;
+    default:
+    case 2: stfun = stb_user; break;
+    }
+#endif
+    stfun(T0, (uint8_t)(T1 >> 56));
+
+    if (GET_LMASK64(T0) <= 6)
+        stfun(GET_OFFSET(T0, 1), (uint8_t)(T1 >> 48));
+
+    if (GET_LMASK64(T0) <= 5)
+        stfun(GET_OFFSET(T0, 2), (uint8_t)(T1 >> 40));
+
+    if (GET_LMASK64(T0) <= 4)
+        stfun(GET_OFFSET(T0, 3), (uint8_t)(T1 >> 32));
+
+    if (GET_LMASK64(T0) <= 3)
+        stfun(GET_OFFSET(T0, 4), (uint8_t)(T1 >> 24));
+
+    if (GET_LMASK64(T0) <= 2)
+        stfun(GET_OFFSET(T0, 5), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK64(T0) <= 1)
+        stfun(GET_OFFSET(T0, 6), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK64(T0) <= 0)
+        stfun(GET_OFFSET(T0, 7), (uint8_t)T1);
+}
+
+void do_sdr(int mem_idx)
+{
+#ifdef CONFIG_USER_ONLY
+#define stfun stb_raw
+#else
+    void (*stfun)(target_ulong, int);
+
+    switch (mem_idx)
+    {
+    case 0: stfun = stb_kernel; break;
+    case 1: stfun = stb_super; break;
+     default:
+    case 2: stfun = stb_user; break;
+    }
+#endif
+    stfun(T0, (uint8_t)T1);
+
+    if (GET_LMASK64(T0) >= 1)
+        stfun(GET_OFFSET(T0, -1), (uint8_t)(T1 >> 8));
+
+    if (GET_LMASK64(T0) >= 2)
+        stfun(GET_OFFSET(T0, -2), (uint8_t)(T1 >> 16));
+
+    if (GET_LMASK64(T0) >= 3)
+        stfun(GET_OFFSET(T0, -3), (uint8_t)(T1 >> 24));
+
+    if (GET_LMASK64(T0) >= 4)
+        stfun(GET_OFFSET(T0, -4), (uint8_t)(T1 >> 32));
+
+    if (GET_LMASK64(T0) >= 5)
+        stfun(GET_OFFSET(T0, -5), (uint8_t)(T1 >> 40));
+
+    if (GET_LMASK64(T0) >= 6)
+        stfun(GET_OFFSET(T0, -6), (uint8_t)(T1 >> 48));
+
+    if (GET_LMASK64(T0) == 7)
+        stfun(GET_OFFSET(T0, -7), (uint8_t)(T1 >> 56));
+}
+#endif /* TARGET_MIPS64 */
+
+#ifdef CONFIG_USER_ONLY
 void do_mfc0_random (void)
 {
     cpu_abort(env, "mfc0 random\n");

Modified: trunk/target-mips/translate.c
===================================================================
--- trunk/target-mips/translate.c       2008-06-20 15:06:42 UTC (rev 4758)
+++ trunk/target-mips/translate.c       2008-06-20 15:12:14 UTC (rev 4759)
@@ -945,37 +945,6 @@
 }
 
 /* load/store instructions. */
-#if defined(CONFIG_USER_ONLY)
-#define op_ldst(name)        gen_op_##name##_raw()
-#define OP_LD_TABLE(width)
-#define OP_ST_TABLE(width)
-#else
-#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
-#define OP_LD_TABLE(width)                                                    \
-static GenOpFunc *gen_op_l##width[] = {                                       \
-    &gen_op_l##width##_kernel,                                                \
-    &gen_op_l##width##_super,                                                 \
-    &gen_op_l##width##_user,                                                  \
-}
-#define OP_ST_TABLE(width)                                                    \
-static GenOpFunc *gen_op_s##width[] = {                                       \
-    &gen_op_s##width##_kernel,                                                \
-    &gen_op_s##width##_super,                                                 \
-    &gen_op_s##width##_user,                                                  \
-}
-#endif
-
-#if defined(TARGET_MIPS64)
-OP_LD_TABLE(dl);
-OP_LD_TABLE(dr);
-OP_ST_TABLE(dl);
-OP_ST_TABLE(dr);
-#endif
-OP_LD_TABLE(wl);
-OP_LD_TABLE(wr);
-OP_ST_TABLE(wl);
-OP_ST_TABLE(wr);
-
 #define OP_LD(insn,fname)                                        \
 void inline op_ldst_##insn(DisasContext *ctx)                    \
 {                                                                \
@@ -1094,25 +1063,29 @@
         opn = "scd";
         break;
     case OPC_LDL:
+        save_cpu_state(ctx, 1);
         gen_load_gpr(cpu_T[1], rt);
-        op_ldst(ldl);
+        tcg_gen_helper_0_1i(do_ldl, ctx->mem_idx);
         gen_store_gpr(cpu_T[1], rt);
         opn = "ldl";
         break;
     case OPC_SDL:
+        save_cpu_state(ctx, 1);
         gen_load_gpr(cpu_T[1], rt);
-        op_ldst(sdl);
+        tcg_gen_helper_0_1i(do_sdl, ctx->mem_idx);
         opn = "sdl";
         break;
     case OPC_LDR:
+        save_cpu_state(ctx, 1);
         gen_load_gpr(cpu_T[1], rt);
-        op_ldst(ldr);
+        tcg_gen_helper_0_1i(do_ldr, ctx->mem_idx);
         gen_store_gpr(cpu_T[1], rt);
         opn = "ldr";
         break;
     case OPC_SDR:
+        save_cpu_state(ctx, 1);
         gen_load_gpr(cpu_T[1], rt);
-        op_ldst(sdr);
+        tcg_gen_helper_0_1i(do_sdr, ctx->mem_idx);
         opn = "sdr";
         break;
 #endif
@@ -1157,25 +1130,29 @@
         opn = "lbu";
         break;
     case OPC_LWL:
+        save_cpu_state(ctx, 1);
        gen_load_gpr(cpu_T[1], rt);
-        op_ldst(lwl);
+        tcg_gen_helper_0_1i(do_lwl, ctx->mem_idx);
         gen_store_gpr(cpu_T[1], rt);
         opn = "lwl";
         break;
     case OPC_SWL:
+        save_cpu_state(ctx, 1);
         gen_load_gpr(cpu_T[1], rt);
-        op_ldst(swl);
+        tcg_gen_helper_0_1i(do_swl, ctx->mem_idx);
         opn = "swr";
         break;
     case OPC_LWR:
+        save_cpu_state(ctx, 1);
        gen_load_gpr(cpu_T[1], rt);
-        op_ldst(lwr);
+        tcg_gen_helper_0_1i(do_lwr, ctx->mem_idx);
         gen_store_gpr(cpu_T[1], rt);
         opn = "lwr";
         break;
     case OPC_SWR:
+        save_cpu_state(ctx, 1);
         gen_load_gpr(cpu_T[1], rt);
-        op_ldst(swr);
+        tcg_gen_helper_0_1i(do_swr, ctx->mem_idx);
         opn = "swr";
         break;
     case OPC_LL:






reply via email to

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