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 */
next prev parent 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).