diff mbox

[RFC,3/4] Implement byte swapped MMIO type

Message ID AANLkTimCLp7GZ_FyONY3mb6slmfd6DyZAm0JfFOaMIPw@mail.gmail.com
State New
Headers show

Commit Message

Blue Swirl May 23, 2010, 8:34 p.m. UTC
BROKEN

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 cpu-common.h       |    3 +-
 softmmu_template.h |   69 ++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 63 insertions(+), 9 deletions(-)

+    }
 #endif /* SHIFT > 2 */
     return res;
 }
@@ -174,6 +199,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX),
MMUSUFFIX)(target_ulong addr,
             res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
 #endif
             res = (DATA_TYPE)res;
+            if (tlb_addr & IO_MEM_BSWAP) {
+                res = SWAP(res);
+            }
         } else {
             /* unaligned/aligned access in the same page */
             addend = env->tlb_table[mmu_idx][index].addend;
@@ -209,16 +237,37 @@ static inline void glue(io_write,
SUFFIX)(target_phys_addr_t physaddr,

     env->mem_io_vaddr = addr;
     env->mem_io_pc = (unsigned long)retaddr;
+    if (index & IO_MEM_BSWAP) {
+        val = SWAP(val);
+    }
 #if SHIFT <= 2
     io_mem_write[index][SHIFT](io_mem_opaque[index], physaddr, val);
+    if (index & IO_MEM_BSWAP) {
+        val = SWAP(val);
+    }
 #else
+    {
+        DATA_TYPE tmp;
 #ifdef TARGET_WORDS_BIGENDIAN
-    io_mem_write[index][2](io_mem_opaque[index], physaddr, val >> 32);
-    io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val);
+        if (index & IO_MEM_BSWAP) {
+            tmp = bswap32(val >> 32);
+        }
+        io_mem_write[index][2](io_mem_opaque[index], physaddr, tmp);
+        if (index & IO_MEM_BSWAP) {
+            tmp = bswap32(val);
+        }
+        io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, tmp);
 #else
-    io_mem_write[index][2](io_mem_opaque[index], physaddr, val);
-    io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, val >> 32);
+        if (index & IO_MEM_BSWAP) {
+            tmp = bswap32(val);
+        }
+        io_mem_write[index][2](io_mem_opaque[index], physaddr, tmp);
+        if (index & IO_MEM_BSWAP) {
+            tmp = bswap32(val >> 32);
+        }
+        io_mem_write[index][2](io_mem_opaque[index], physaddr + 4, tmp);
 #endif
+    }
 #endif /* SHIFT > 2 */
 }

@@ -297,6 +346,9 @@ static void glue(glue(slow_st, SUFFIX),
MMUSUFFIX)(target_ulong addr,
             glue(io_write, SUFFIX)(ioaddr, val, addr, retaddr);
         } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >=
TARGET_PAGE_SIZE) {
         do_unaligned_access:
+            if (tlb_addr & IO_MEM_BSWAP) {
+                val = SWAP(val);
+            }
             /* XXX: not efficient, but simple */
             /* Note: relies on the fact that tlb_fill() does not remove the
              * previous page from the TLB cache.  */
@@ -330,3 +382,4 @@ static void glue(glue(slow_st, SUFFIX),
MMUSUFFIX)(target_ulong addr,
 #undef USUFFIX
 #undef DATA_SIZE
 #undef ADDR_READ
+#undef SWAP

Comments

Igor V. Kovalenko May 25, 2010, 7:45 p.m. UTC | #1
On Mon, May 24, 2010 at 12:34 AM, Blue Swirl <blauwirbel@gmail.com> wrote:
> BROKEN
>
> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
> ---
>  cpu-common.h       |    3 +-
>  softmmu_template.h |   69 ++++++++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 63 insertions(+), 9 deletions(-)

Changes to io_read and io_write seem to have issue with considering
wrong value bits, you should check physaddr instead since index is cut
off physaddr.

It's probably a good idea to instead do a byteswap at __ld*/__st*
level (a bit higher level than in your change.)
These two sets are directly entered from runtime, and this way you
need only two templates changed.
Not sure if it is a good idea to handle unaligned accesses.
Blue Swirl May 26, 2010, 7:22 p.m. UTC | #2
On Tue, May 25, 2010 at 7:45 PM, Igor Kovalenko
<igor.v.kovalenko@gmail.com> wrote:
> On Mon, May 24, 2010 at 12:34 AM, Blue Swirl <blauwirbel@gmail.com> wrote:
>> BROKEN
>>
>> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
>> ---
>>  cpu-common.h       |    3 +-
>>  softmmu_template.h |   69 ++++++++++++++++++++++++++++++++++++++++++++++------
>>  2 files changed, 63 insertions(+), 9 deletions(-)
>
> Changes to io_read and io_write seem to have issue with considering
> wrong value bits, you should check physaddr instead since index is cut
> off physaddr.

Thanks, good catch!

> It's probably a good idea to instead do a byteswap at __ld*/__st*
> level (a bit higher level than in your change.)
> These two sets are directly entered from runtime, and this way you
> need only two templates changed.
> Not sure if it is a good idea to handle unaligned accesses.

That's the difficulty with the __ld/__st case. I think an unaligned
word load on a byte swapped bus would consist of two loads, so there
should be two swaps as well. Perhaps the unaligned access code should
be changed to this way instead of current series of byte loads.
diff mbox

Patch

diff --git a/cpu-common.h b/cpu-common.h
index b24cecc..f96cea0 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -123,8 +123,9 @@  void cpu_physical_memory_write_rom(target_phys_addr_t addr,
 #define IO_MEM_NOTDIRTY    (3 << IO_MEM_SHIFT)

 /* Acts like a ROM when read and like a device when written.  */
-#define IO_MEM_ROMD        (1)
+#define IO_MEM_ROMD        (4)
 #define IO_MEM_SUBPAGE     (2)
+#define IO_MEM_BSWAP       (1)

 #endif

diff --git a/softmmu_template.h b/softmmu_template.h
index c2df9ec..feb5d85 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -24,18 +24,22 @@ 
 #define SUFFIX q
 #define USUFFIX q
 #define DATA_TYPE uint64_t
+#define SWAP(x) bswap64(x)
 #elif DATA_SIZE == 4
 #define SUFFIX l
 #define USUFFIX l
 #define DATA_TYPE uint32_t
+#define SWAP(x) bswap32(x)
 #elif DATA_SIZE == 2
 #define SUFFIX w
 #define USUFFIX uw
 #define DATA_TYPE uint16_t
+#define SWAP(x) bswap16(x)
 #elif DATA_SIZE == 1
 #define SUFFIX b
 #define USUFFIX ub
 #define DATA_TYPE uint8_t
+#define SWAP(x) (x)
 #else
 #error unsupported data size
 #endif
@@ -68,14 +72,35 @@  static inline DATA_TYPE glue(io_read,
SUFFIX)(target_phys_addr_t physaddr,
     env->mem_io_vaddr = addr;
 #if SHIFT <= 2
     res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr);
+    if (index & IO_MEM_BSWAP) {
+        res = SWAP(res);
+    }
 #else
+    {
+        DATA_TYPE tmp;
 #ifdef TARGET_WORDS_BIGENDIAN
-    res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index],
physaddr) << 32;
-    res |= io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
+        res = (uint64_t)io_mem_read[index][2](io_mem_opaque[index],
+                                              physaddr) << 32;
+        if (index & IO_MEM_BSWAP) {
+            res = bswap32(res);
+        }
+        tmp = io_mem_read[index][2](io_mem_opaque[index], physaddr + 4);
+        if (index & IO_MEM_BSWAP) {
+            tmp = bswap32(tmp);
+        }
+        res |= tmp;
 #else
-    res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
-    res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index],
physaddr + 4) << 32;
+        res = io_mem_read[index][2](io_mem_opaque[index], physaddr);
+        if (index & IO_MEM_BSWAP) {
+            res = bswap32(res);
+        }
+        tmp = (uint64_t)io_mem_read[index][2](io_mem_opaque[index],
physaddr + 4) << 32;
+        if (index & IO_MEM_BSWAP) {
+            tmp = bswap32(tmp);
+        }
+        res |= tmp;
 #endif