@@ -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 */
@@ -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
@@ -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;
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