Patchwork [28/34] Implement byte swapped MMIO type

login
register
mail settings
Submitter Blue Swirl
Date July 22, 2010, 10:02 p.m.
Message ID <AANLkTiklnvz7zTe5T31FydwV4d71iv1mMJSlUcK_FzHe@mail.gmail.com>
Download mbox | patch
Permalink /patch/59669/
State New
Headers show

Comments

Blue Swirl - July 22, 2010, 10:02 p.m.
Add a flag to indicate a byte swapped MMIO type.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 cpu-common.h       |    4 +++-
 exec.c             |   42 ++++++++++++++++++++++++++++++++++++++++++
 softmmu_template.h |   16 +++++++++++++++-
 3 files changed, 60 insertions(+), 2 deletions(-)

     env->mem_io_pc = (unsigned long)retaddr;
@@ -77,6 +83,9 @@ static inline DATA_TYPE glue(io_read,
SUFFIX)(target_phys_addr_t physaddr,
     res |= (uint64_t)io_mem_read[index][2](io_mem_opaque[index],
physaddr + 4) << 32;
 #endif
 #endif /* SHIFT > 2 */
+    if (do_bswap) {
+        res = SWAP(res);
+    }
     return res;
 }

@@ -200,6 +209,10 @@ static inline void glue(io_write,
SUFFIX)(target_phys_addr_t physaddr,
                                           void *retaddr)
 {
     int index;
+
+    if (physaddr & IO_MEM_BSWAP) {
+        val = SWAP(val);
+    }
     index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
     if (index > (IO_MEM_NOTDIRTY >> IO_MEM_SHIFT)
@@ -330,3 +343,4 @@ static void glue(glue(slow_st, SUFFIX),
MMUSUFFIX)(target_ulong addr,
 #undef USUFFIX
 #undef DATA_SIZE
 #undef ADDR_READ
+#undef SWAP

Patch

diff --git a/cpu-common.h b/cpu-common.h
index 71e7933..16bb467 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -123,9 +123,11 @@  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)

+int cpu_physical_memory_toggle_bswap(int ix);
 #endif

 #endif /* !CPU_COMMON_H */
diff --git a/exec.c b/exec.c
index 868cd7f..7d39747 100644
--- a/exec.c
+++ b/exec.c
@@ -3473,11 +3473,17 @@  void cpu_physical_memory_rw(target_phys_addr_t
addr, uint8_t *buf,
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit write access */
                     val = ldl_p(buf);
+                    if (pd & IO_MEM_BSWAP) {
+                        val = bswap32(val);
+                    }

io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
                     l = 4;
                 } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit write access */
                     val = lduw_p(buf);
+                    if (pd & IO_MEM_BSWAP) {
+                        val = bswap16(val);
+                    }

io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
                     l = 2;
                 } else {
@@ -3511,11 +3517,17 @@  void cpu_physical_memory_rw(target_phys_addr_t
addr, uint8_t *buf,
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
                     val =
io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
+                    if (pd & IO_MEM_BSWAP) {
+                        val = bswap32(val);
+                    }
                     stl_p(buf, val);
                     l = 4;
                 } else if (l >= 2 && ((addr1 & 1) == 0)) {
                     /* 16 bit read access */
                     val =
io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
+                    if (pd & IO_MEM_BSWAP) {
+                        val = bswap16(val);
+                    }
                     stw_p(buf, val);
                     l = 2;
                 } else {
@@ -3743,6 +3755,9 @@  uint32_t ldl_phys(target_phys_addr_t addr)
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
         val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap32(val);
+        }
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -3781,6 +3796,9 @@  uint64_t ldq_phys(target_phys_addr_t addr)
         val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
         val |=
(uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4)
<< 32;
 #endif
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap64(val);
+        }
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -3821,6 +3839,9 @@  uint32_t lduw_phys(target_phys_addr_t addr)
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
         val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap16(val);
+        }
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
@@ -3851,6 +3872,9 @@  void stl_phys_notdirty(target_phys_addr_t addr,
uint32_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap32(val);
+        }
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr &
~TARGET_PAGE_MASK);
@@ -3887,6 +3911,9 @@  void stq_phys_notdirty(target_phys_addr_t addr,
uint64_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap64(val);
+        }
 #ifdef TARGET_WORDS_BIGENDIAN
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
@@ -3920,6 +3947,9 @@  void stl_phys(target_phys_addr_t addr, uint32_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap32(val);
+        }
         io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1;
@@ -3963,6 +3993,9 @@  void stw_phys(target_phys_addr_t addr, uint32_t val)
         io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
         if (p)
             addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
+        if (pd & IO_MEM_BSWAP) {
+            val = bswap16(val);
+        }
         io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
     } else {
         unsigned long addr1;
@@ -4015,6 +4048,15 @@  int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
     }
     return 0;
 }
+
+int cpu_physical_memory_toggle_bswap(int ix)
+{
+    /* Don't toggle for memory backed pages */
+    if ((ix & ~TARGET_PAGE_MASK) != 0) {
+        ix ^= IO_MEM_BSWAP;
+    }
+    return ix;
+}
 #endif

 /* in deterministic execution mode, instructions doing device I/Os
diff --git a/softmmu_template.h b/softmmu_template.h
index c2df9ec..5500408 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
@@ -56,7 +60,9 @@  static inline DATA_TYPE glue(io_read,
SUFFIX)(target_phys_addr_t physaddr,
                                               void *retaddr)
 {
     DATA_TYPE res;
-    int index;
+    int index, do_bswap;
+
+    do_bswap = physaddr & IO_MEM_BSWAP;
     index = (physaddr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;