diff --git a/cpu-all.h b/cpu-all.h index 3df0fb8..821118f 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -810,7 +810,7 @@ extern uint8_t *phys_ram_dirty; /* physical memory access */ #define TLB_INVALID_MASK (1 << 3) #define IO_MEM_SHIFT 4 -#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) +#define IO_MEM_NB_ENTRIES 1024 #define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ diff --git a/exec.c b/exec.c index ab3f9c1..1850572 100644 --- a/exec.c +++ b/exec.c @@ -1657,7 +1657,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, { if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { /* IO memory case */ - address = vaddr | pd; + address = vaddr | (pd & ~TARGET_PAGE_MASK); addend = paddr; } else { /* standard memory */ @@ -1691,7 +1691,9 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, } else { te->addr_read = -1; } - if (prot & PAGE_EXEC) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { + te->addr_code = pd; + } else if (prot & PAGE_EXEC) { te->addr_code = address; } else { te->addr_code = -1; @@ -2486,7 +2488,9 @@ int cpu_register_io_memory(int io_index, if (io_index <= 0) { if (io_mem_nb >= IO_MEM_NB_ENTRIES) return -1; - io_index = io_mem_nb++; + do io_index = io_mem_nb++; + while (((io_index << IO_MEM_SHIFT) & ~TARGET_PAGE_MASK) + <= IO_MEM_NOTDIRTY); } else { if (io_index >= IO_MEM_NB_ENTRIES) return -1; diff --git a/softmmu_template.h b/softmmu_template.h index 45fcd4e..e975a52 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -51,12 +51,15 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, int mmu_idx, void *retaddr); static inline DATA_TYPE glue(io_read, SUFFIX)(target_phys_addr_t physaddr, - target_ulong tlb_addr) + target_ulong tlb_addr, + target_ulong tlb_io) { DATA_TYPE res; int index; - index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT; + if (index > 4) + index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); #if SHIFT <= 2 res = io_mem_read[index][SHIFT](io_mem_opaque[index], physaddr); #else @@ -95,7 +98,9 @@ DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - res = glue(io_read, SUFFIX)(physaddr, tlb_addr); + res = glue(io_read, SUFFIX)(physaddr, tlb_addr, + env->tlb_table[mmu_idx] + [index].addr_code); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { /* slow unaligned access (it spans two pages or IO) */ do_unaligned_access: @@ -147,7 +152,9 @@ static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(target_ulong addr, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - res = glue(io_read, SUFFIX)(physaddr, tlb_addr); + res = glue(io_read, SUFFIX)(physaddr, tlb_addr, + env->tlb_table[mmu_idx] + [index].addr_code); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: /* slow unaligned access (it spans two pages) */ @@ -186,11 +193,14 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, static inline void glue(io_write, SUFFIX)(target_phys_addr_t physaddr, DATA_TYPE val, target_ulong tlb_addr, - void *retaddr) + void *retaddr, + target_ulong tlb_io) { int index; - index = (tlb_addr >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + index = (tlb_addr & ~TARGET_PAGE_MASK) >> IO_MEM_SHIFT; + if (index > 4) + index = (tlb_io >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); env->mem_write_vaddr = tlb_addr; env->mem_write_pc = (unsigned long)retaddr; #if SHIFT <= 2 @@ -228,7 +238,8 @@ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; retaddr = GETPC(); - glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); + glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr, + env->tlb_table[mmu_idx][index].addr_code); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: retaddr = GETPC(); @@ -278,7 +289,8 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(target_ulong addr, /* IO access */ if ((addr & (DATA_SIZE - 1)) != 0) goto do_unaligned_access; - glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr); + glue(io_write, SUFFIX)(physaddr, val, tlb_addr, retaddr, + env->tlb_table[mmu_idx][index].addr_code); } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { do_unaligned_access: /* XXX: not efficient, but simple */