On 10/15/07, Blue Swirl <[EMAIL PROTECTED]> wrote:
> On 10/15/07, J. Mayer <[EMAIL PROTECTED]> wrote:
> > On Sun, 2007-10-14 at 15:59 +0300, Blue Swirl wrote:
> > > On 10/14/07, J. Mayer <[EMAIL PROTECTED]> wrote:
> > > > Here's an updated version of the patch against current CVS.
> > > > This patches provides reverse-endian, little-endian and big-endian
> > > > memory accessors, available with and without softmmu. It also provides
> > > > an IO_MEM_REVERSE TLB flag to allow future support of per-page
> > > > endianness control, which is required by some targets CPU emulations.
> > > > Having reverse-endian memory accessors also make it possible to optimise
> > > > reverse-endian memory access when the target CPU has dedicated
> > > > instructions. For now, it includes optimisations for the PowerPC target.
> > >
> > > This breaks Sparc32 softmmu, I get a black screen. Your changes to
> > > target-sparc and hw/sun4m.c look fine, so the problem could be in IO?
> >
> > Did it worked before my commits ? I may have done something wrong during
> > the merge...
> > I will do more checks and more tests...
>
> If I disable the IOSWAP code, black screen is gone. I think this is
> logical: the io accessors return host CPU values, therefore no byte
> swapping need to be performed.
>
> The attached version works for me.

This patch takes the reverse endian functions into use for Sparc.

I added hypervisor versions of the functions. This is getting a bit
ugly, time for #include magic? Physical versions could be useful too.
Index: qemu/target-sparc/op_helper.c
===================================================================
--- qemu.orig/target-sparc/op_helper.c	2007-10-15 16:47:11.000000000 +0000
+++ qemu/target-sparc/op_helper.c	2007-10-15 17:34:28.000000000 +0000
@@ -649,8 +649,6 @@
     switch (asi) {
     case 0x80: // Primary
     case 0x82: // Primary no-fault
-    case 0x88: // Primary LE
-    case 0x8a: // Primary no-fault LE
         {
             switch(size) {
             case 1:
@@ -669,6 +667,26 @@
             }
         }
         break;
+    case 0x88: // Primary LE
+    case 0x8a: // Primary no-fault LE
+        {
+            switch(size) {
+            case 1:
+                ret = ldub_raw(T0);
+                break;
+            case 2:
+                ret = lduwr_raw(T0 & ~1);
+                break;
+            case 4:
+                ret = ldulr_raw(T0 & ~3);
+                break;
+            default:
+            case 8:
+                ret = ldqr_raw(T0 & ~7);
+                break;
+            }
+        }
+        break;
     case 0x81: // Secondary
     case 0x83: // Secondary no-fault
     case 0x89: // Secondary LE
@@ -679,29 +697,6 @@
         break;
     }
 
-    /* Convert from little endian */
-    switch (asi) {
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-    case 0x8a: // Primary no-fault LE
-    case 0x8b: // Secondary no-fault LE
-        switch(size) {
-        case 2:
-            ret = bswap16(ret);
-            break;
-        case 4:
-            ret = bswap32(ret);
-            break;
-        case 8:
-            ret = bswap64(ret);
-            break;
-        default:
-            break;
-        }
-    default:
-        break;
-    }
-
     /* Convert to signed number */
     if (sign) {
         switch(size) {
@@ -726,30 +721,8 @@
     if (asi < 0x80)
         raise_exception(TT_PRIV_ACT);
 
-    /* Convert to little endian */
-    switch (asi) {
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-        switch(size) {
-        case 2:
-            T0 = bswap16(T0);
-            break;
-        case 4:
-            T0 = bswap32(T0);
-            break;
-        case 8:
-            T0 = bswap64(T0);
-            break;
-        default:
-            break;
-        }
-    default:
-        break;
-    }
-
     switch(asi) {
     case 0x80: // Primary
-    case 0x88: // Primary LE
         {
             switch(size) {
             case 1:
@@ -768,6 +741,25 @@
             }
         }
         break;
+    case 0x88: // Primary LE
+        {
+            switch(size) {
+            case 1:
+                stb_raw(T0, T1);
+                break;
+            case 2:
+                stwr_raw(T0 & ~1, T1);
+                break;
+            case 4:
+                stlr_raw(T0 & ~3, T1);
+                break;
+            case 8:
+            default:
+                stqr_raw(T0 & ~7, T1);
+                break;
+            }
+        }
+        break;
     case 0x81: // Secondary
     case 0x89: // Secondary LE
         // XXX
@@ -795,11 +787,8 @@
 
     switch (asi) {
     case 0x10: // As if user primary
-    case 0x18: // As if user primary LE
     case 0x80: // Primary
     case 0x82: // Primary no-fault
-    case 0x88: // Primary LE
-    case 0x8a: // Primary no-fault LE
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (env->hpstate & HS_PRIV) {
                 switch(size) {
@@ -852,10 +841,63 @@
             }
         }
         break;
+    case 0x18: // As if user primary LE
+    case 0x88: // Primary LE
+    case 0x8a: // Primary no-fault LE
+        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
+            if (env->hpstate & HS_PRIV) {
+                switch(size) {
+                case 1:
+                    ret = ldub_hypv(T0);
+                    break;
+                case 2:
+                    ret = lduwr_hypv(T0 & ~1);
+                    break;
+                case 4:
+                    ret = ldulr_hypv(T0 & ~3);
+                    break;
+                default:
+                case 8:
+                    ret = ldqr_hypv(T0 & ~7);
+                    break;
+                }
+            } else {
+                switch(size) {
+                case 1:
+                    ret = ldub_kernel(T0);
+                    break;
+                case 2:
+                    ret = lduwr_kernel(T0 & ~1);
+                    break;
+                case 4:
+                    ret = ldulr_kernel(T0 & ~3);
+                    break;
+                default:
+                case 8:
+                    ret = ldqr_kernel(T0 & ~7);
+                    break;
+                }
+            }
+        } else {
+            switch(size) {
+            case 1:
+                ret = ldub_user(T0);
+                break;
+            case 2:
+                ret = lduwr_user(T0 & ~1);
+                break;
+            case 4:
+                ret = ldulr_user(T0 & ~3);
+                break;
+            default:
+            case 8:
+                ret = ldqr_user(T0 & ~7);
+                break;
+            }
+        }
+        break;
     case 0x14: // Bypass
     case 0x15: // Bypass, non-cacheable
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
         {
             switch(size) {
             case 1:
@@ -874,6 +916,26 @@
             }
             break;
         }
+    case 0x1c: // Bypass LE
+    case 0x1d: // Bypass, non-cacheable LE
+        {
+            switch(size) {
+            case 1:
+                ret = ldub_phys(T0);
+                break;
+            case 2:
+                ret = bswap16(lduw_phys(T0 & ~1));
+                break;
+            case 4:
+                ret = bswap32(ldul_phys(T0 & ~3));
+                break;
+            default:
+            case 8:
+                ret = bswap64(ldq_phys(T0 & ~7));
+                break;
+            }
+            break;
+        }
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
     case 0x11: // As if user secondary
@@ -957,34 +1019,6 @@
         break;
     }
 
-    /* Convert from little endian */
-    switch (asi) {
-    case 0x0c: // Nucleus Little Endian (LE)
-    case 0x18: // As if user primary LE
-    case 0x19: // As if user secondary LE
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-    case 0x8a: // Primary no-fault LE
-    case 0x8b: // Secondary no-fault LE
-        switch(size) {
-        case 2:
-            ret = bswap16(ret);
-            break;
-        case 4:
-            ret = bswap32(ret);
-            break;
-        case 8:
-            ret = bswap64(ret);
-            break;
-        default:
-            break;
-        }
-    default:
-        break;
-    }
-
     /* Convert to signed number */
     if (sign) {
         switch(size) {
@@ -1010,37 +1044,9 @@
         || (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV))
         raise_exception(TT_PRIV_ACT);
 
-    /* Convert to little endian */
-    switch (asi) {
-    case 0x0c: // Nucleus Little Endian (LE)
-    case 0x18: // As if user primary LE
-    case 0x19: // As if user secondary LE
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
-    case 0x88: // Primary LE
-    case 0x89: // Secondary LE
-        switch(size) {
-        case 2:
-            T0 = bswap16(T0);
-            break;
-        case 4:
-            T0 = bswap32(T0);
-            break;
-        case 8:
-            T0 = bswap64(T0);
-            break;
-        default:
-            break;
-        }
-    default:
-        break;
-    }
-
     switch(asi) {
     case 0x10: // As if user primary
-    case 0x18: // As if user primary LE
     case 0x80: // Primary
-    case 0x88: // Primary LE
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if (env->hpstate & HS_PRIV) {
                 switch(size) {
@@ -1093,10 +1099,62 @@
             }
         }
         break;
+    case 0x18: // As if user primary LE
+    case 0x88: // Primary LE
+        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
+            if (env->hpstate & HS_PRIV) {
+                switch(size) {
+                case 1:
+                    stb_hypv(T0, T1);
+                    break;
+                case 2:
+                    stwr_hypv(T0 & ~1, T1);
+                    break;
+                case 4:
+                    stlr_hypv(T0 & ~3, T1);
+                    break;
+                case 8:
+                default:
+                    stqr_hypv(T0 & ~7, T1);
+                    break;
+                }
+            } else {
+                switch(size) {
+                case 1:
+                    stb_kernel(T0, T1);
+                    break;
+                case 2:
+                    stwr_kernel(T0 & ~1, T1);
+                    break;
+                case 4:
+                    stlr_kernel(T0 & ~3, T1);
+                    break;
+                case 8:
+                default:
+                    stqr_kernel(T0 & ~7, T1);
+                    break;
+                }
+            }
+        } else {
+            switch(size) {
+            case 1:
+                stb_user(T0, T1);
+                break;
+            case 2:
+                stwr_user(T0 & ~1, T1);
+                break;
+            case 4:
+                stlr_user(T0 & ~3, T1);
+                break;
+            case 8:
+            default:
+                stqr_user(T0 & ~7, T1);
+                break;
+            }
+        }
+        break;
     case 0x14: // Bypass
     case 0x15: // Bypass, non-cacheable
-    case 0x1c: // Bypass LE
-    case 0x1d: // Bypass, non-cacheable LE
         {
             switch(size) {
             case 1:
@@ -1115,6 +1173,26 @@
             }
         }
         return;
+    case 0x1c: // Bypass LE
+    case 0x1d: // Bypass, non-cacheable LE
+        {
+            switch(size) {
+            case 1:
+                stb_phys(T0, T1);
+                break;
+            case 2:
+                stw_phys(T0 & ~1, bswap16(T1));
+                break;
+            case 4:
+                stl_phys(T0 & ~3, bswap32(T1));
+                break;
+            case 8:
+            default:
+                stq_phys(T0 & ~7, bswap64(T1));
+                break;
+            }
+        }
+        return;
     case 0x04: // Nucleus
     case 0x0c: // Nucleus Little Endian (LE)
     case 0x11: // As if user secondary
Index: qemu/target-sparc/op_mem.h
===================================================================
--- qemu.orig/target-sparc/op_mem.h	2007-10-15 16:47:11.000000000 +0000
+++ qemu/target-sparc/op_mem.h	2007-10-15 17:00:16.000000000 +0000
@@ -82,16 +82,8 @@
 }
 
 #ifdef TARGET_SPARC64
-void OPPROTO glue(op_lduw, MEMSUFFIX)(void)
-{
-    T1 = (uint64_t)(glue(ldul, MEMSUFFIX)(ADDR(T0)) & 0xffffffff);
-}
-
-void OPPROTO glue(op_ldsw, MEMSUFFIX)(void)
-{
-    T1 = (int64_t)(glue(ldul, MEMSUFFIX)(ADDR(T0)) & 0xffffffff);
-}
-
+SPARC_LD_OP(lduw, ldul);
+SPARC_LD_OP(ldsw, ldsl);
 SPARC_LD_OP(ldx, ldq);
 SPARC_ST_OP(stx, stq);
 #endif
Index: qemu/cpu-all.h
===================================================================
--- qemu.orig/cpu-all.h	2007-10-15 17:10:15.000000000 +0000
+++ qemu/cpu-all.h	2007-10-15 17:27:47.000000000 +0000
@@ -1128,6 +1128,118 @@
 #define stfq_le_kernel(p, vt) stfq_kernel(p, vt)
 #endif
 
+/* native-endian */
+#define ldub_hypv(p) ldub_raw(p)
+#define ldsb_hypv(p) ldsb_raw(p)
+#define lduw_hypv(p) lduw_raw(p)
+#define ldsw_hypv(p) ldsw_raw(p)
+#define ldul_hypv(p) ldul_raw(p)
+#if (TARGET_LONG_BITS == 64)
+#define ldsl_hypv(p) ldsl_raw(p)
+#endif
+#define ldq_hypv(p) ldq_raw(p)
+#define ldfl_hypv(p) ldfl_raw(p)
+#define ldfq_hypv(p) ldfq_raw(p)
+#define stb_hypv(p, v) stb_raw(p, v)
+#define stw_hypv(p, v) stw_raw(p, v)
+#define stl_hypv(p, v) stl_raw(p, v)
+#define stq_hypv(p, v) stq_raw(p, v)
+#define stfl_hypv(p, v) stfl_raw(p, v)
+#define stfq_hypv(p, vt) stfq_raw(p, v)
+/* reverse-endian */
+#define ldubr_hypv(p) ldub_raw(p)
+#define ldsbr_hypv(p) ldsb_raw(p)
+#define lduwr_hypv(p) lduwr_raw(p)
+#define ldswr_hypv(p) ldswr_raw(p)
+#define ldulr_hypv(p) ldulr_raw(p)
+#if (TARGET_LONG_BITS == 64)
+#define ldslr_hypv(p) ldslr_raw(p)
+#endif
+#define ldqr_hypv(p) ldqr_raw(p)
+#define ldflr_hypv(p) ldflr_raw(p)
+#define ldfqr_hypv(p) ldfqr_raw(p)
+#define stbr_hypv(p, v) stbr_raw(p, v)
+#define stwr_hypv(p, v) stwr_raw(p, v)
+#define stlr_hypv(p, v) stlr_raw(p, v)
+#define stqr_hypv(p, v) stqr_raw(p, v)
+#define stflr_hypv(p, v) stflr_raw(p, v)
+#define stfqr_hypv(p, vt) stfqr_raw(p, v)
+#if defined(TARGET_WORDS_BIGENDIAN)
+/* big-endian */
+#define ldub_be_hypv(p) ldub_hypv(p)
+#define ldsb_be_hypv(p) ldsb_hypv(p)
+#define lduw_be_hypv(p) lduw_hypv(p)
+#define ldsw_be_hypv(p) ldsw_hypv(p)
+#define ldul_be_hypv(p) ldul_hypv(p)
+#if (TARGET_LONG_BITS == 64)
+#define ldsl_be_hypv(p) ldsl_hypv(p)
+#endif
+#define ldq_be_hypv(p) ldq_hypv(p)
+#define ldfl_be_hypv(p) ldfl_hypv(p)
+#define ldfq_be_hypv(p) ldfq_hypv(p)
+#define stb_be_hypv(p, v) stb_hypv(p, v)
+#define stw_be_hypv(p, v) stw_hypv(p, v)
+#define stl_be_hypv(p, v) stl_hypv(p, v)
+#define stq_be_hypv(p, v) stq_hypv(p, v)
+#define stfl_be_hypv(p, v) stfl_hypv(p, v)
+#define stfq_be_hypv(p, vt) stfq_hypv(p, vt)
+/* little-endian */
+#define ldub_le_hypv(p) ldubr_hypv(p)
+#define ldsb_le_hypv(p) ldsbr_hypv(p)
+#define lduw_le_hypv(p) lduwr_hypv(p)
+#define ldsw_le_hypv(p) ldswr_hypv(p)
+#define ldul_le_hypv(p) ldulr_hypv(p)
+#if (TARGET_LONG_BITS == 64)
+#define ldsl_le_hypv(p) ldslr_hypv(p)
+#endif
+#define ldq_le_hypv(p) ldqr_hypv(p)
+#define ldfl_le_hypv(p) ldflr_hypv(p)
+#define ldfq_le_hypv(p) ldfqr_hypv(p)
+#define stb_le_hypv(p, v) stbr_hypv(p, v)
+#define stw_le_hypv(p, v) stwr_hypv(p, v)
+#define stl_le_hypv(p, v) stlr_hypv(p, v)
+#define stq_le_hypv(p, v) stqr_hypv(p, v)
+#define stfl_le_hypv(p, v) stflr_hypv(p, v)
+#define stfq_le_hypv(p, vt) stfqr_hypv(p, vt)
+#else
+/* big-endian */
+#define ldub_be_hypv(p) ldubr_hypv(p)
+#define ldsb_be_hypv(p) ldsbr_hypv(p)
+#define lduw_be_hypv(p) lduwr_hypv(p)
+#define ldsw_be_hypv(p) ldswr_hypv(p)
+#define ldul_be_hypv(p) ldulr_hypv(p)
+#if (TARGET_LONG_BITS == 64)
+#define ldsl_be_hypv(p) ldslr_hypv(p)
+#endif
+#define ldq_be_hypv(p) ldqr_hypv(p)
+#define ldfl_be_hypv(p) ldflr_hypv(p)
+#define ldfq_be_hypv(p) ldfqr_hypv(p)
+#define stb_be_hypv(p, v) stbr_hypv(p, v)
+#define stw_be_hypv(p, v) stwr_hypv(p, v)
+#define stl_be_hypv(p, v) stlr_hypv(p, v)
+#define stq_be_hypv(p, v) stqr_hypv(p, v)
+#define stfl_be_hypv(p, v) stflr_hypv(p, v)
+#define stfq_be_hypv(p, vt) stfqr_hypv(p, vt)
+/* little-endian */
+#define ldub_le_hypv(p) ldub_hypv(p)
+#define ldsb_le_hypv(p) ldsb_hypv(p)
+#define lduw_le_hypv(p) lduw_hypv(p)
+#define ldsw_le_hypv(p) ldsw_hypv(p)
+#define ldul_le_hypv(p) ldul_hypv(p)
+#if (TARGET_LONG_BITS == 64)
+#define ldsl_le_hypv(p) ldsl_hypv(p)
+#endif
+#define ldq_le_hypv(p) ldq_hypv(p)
+#define ldfl_le_hypv(p) ldfl_hypv(p)
+#define ldfq_le_hypv(p) ldfq_hypv(p)
+#define stb_le_hypv(p, v) stb_hypv(p, v)
+#define stw_le_hypv(p, v) stw_hypv(p, v)
+#define stl_le_hypv(p, v) stl_hypv(p, v)
+#define stq_le_hypv(p, v) stq_hypv(p, v)
+#define stfl_le_hypv(p, v) stfl_hypv(p, v)
+#define stfq_le_hypv(p, vt) stfq_hypv(p, vt)
+#endif
+
 #endif /* defined(CONFIG_USER_ONLY) */
 
 /* page related stuff */

Reply via email to