diff options
-rw-r--r-- | cpu-all.h | 4 | ||||
-rw-r--r-- | exec-all.h | 2 | ||||
-rw-r--r-- | exec.c | 17 |
3 files changed, 16 insertions, 7 deletions
@@ -828,6 +828,10 @@ extern uint8_t *phys_ram_dirty; #define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ #define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) #define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */ +/* acts like a ROM when read and like a device when written. As an + exception, the write memory callback gets the ram offset instead of + the physical address */ +#define IO_MEM_ROMD (1) typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); @@ -570,7 +570,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) ldub_code(addr); } pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; - if (pd > IO_MEM_ROM) { + if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr); } return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; @@ -1488,7 +1488,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, if (is_softmmu) #endif { - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { /* IO memory case */ address = vaddr | pd; addend = paddr; @@ -1785,7 +1785,8 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr, for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) { p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1); p->phys_offset = phys_offset; - if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) + if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM || + (phys_offset & IO_MEM_ROMD)) phys_offset += TARGET_PAGE_SIZE; } } @@ -2048,7 +2049,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } } else { - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* I/O case */ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); if (l >= 4 && ((addr & 3) == 0)) { @@ -2103,7 +2105,8 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, } if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM && - (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM) { + (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* do nothing */ } else { unsigned long addr1; @@ -2135,7 +2138,8 @@ uint32_t ldl_phys(target_phys_addr_t addr) pd = p->phys_offset; } - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* I/O case */ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr); @@ -2164,7 +2168,8 @@ uint64_t ldq_phys(target_phys_addr_t addr) pd = p->phys_offset; } - if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) { /* I/O case */ io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); #ifdef TARGET_WORDS_BIGENDIAN |