Add a flag to indicate a byte swapped MMIO type. Signed-off-by: Blue Swirl <blauwir...@gmail.com> --- cpu-common.h | 4 +++- exec.c | 42 ++++++++++++++++++++++++++++++++++++++++++ softmmu_template.h | 16 +++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-)
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; 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 -- 1.6.2.4