qemu-devel.nongnu.org archive mirror
 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 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).