Message ID | AANLkTimCLp7GZ_FyONY3mb6slmfd6DyZAm0JfFOaMIPw@mail.gmail.com |
---|---|
State | New |
Headers | show |
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.
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 --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
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