All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Blue Swirl" <blauwirbel@gmail.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] RFC: reverse-endian softmmu memory accessors
Date: Mon, 15 Oct 2007 20:45:52 +0300	[thread overview]
Message-ID: <f43fc5580710151045r6d4116d3tf095c5692fb57752@mail.gmail.com> (raw)
In-Reply-To: <f43fc5580710150902l39848603q95b36c9f734295f1@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1538 bytes --]

On 10/15/07, Blue Swirl <blauwirbel@gmail.com> wrote:
> On 10/15/07, J. Mayer <l_indien@magic.fr> wrote:
> > On Sun, 2007-10-14 at 15:59 +0300, Blue Swirl wrote:
> > > On 10/14/07, J. Mayer <l_indien@magic.fr> 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.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: sparc_reverse_endian.diff --]
[-- Type: text/x-diff; name="sparc_reverse_endian.diff", Size: 15509 bytes --]

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	other threads:[~2007-10-15 17:45 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-14 11:49 [Qemu-devel] RFC: reverse-endian softmmu memory accessors J. Mayer
2007-10-14 12:59 ` Blue Swirl
2007-10-15 12:10   ` J. Mayer
2007-10-15 16:02     ` Blue Swirl
2007-10-15 17:45       ` Blue Swirl [this message]
2007-10-16 20:27         ` J. Mayer
2007-11-23 12:55           ` Tero Kaarlela
2007-10-15 21:06       ` J. Mayer
  -- strict thread matches above, loose matches on Subject: below --
2007-10-13  9:56 J. Mayer
2007-10-13 10:47 ` Blue Swirl
2007-10-13 12:43   ` J. Mayer
2007-10-13 13:07     ` Blue Swirl
2007-10-13 14:17       ` J. Mayer
2007-10-13 22:07         ` J. Mayer
2007-10-13 22:53           ` Thiemo Seufer
2007-10-14  8:19           ` Blue Swirl
2007-10-14 10:14             ` J. Mayer
2007-10-14 13:22               ` Thiemo Seufer
2007-10-15 11:55                 ` J. Mayer
2007-10-13 13:02   ` Thiemo Seufer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f43fc5580710151045r6d4116d3tf095c5692fb57752@mail.gmail.com \
    --to=blauwirbel@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.