# HG changeset patch # User Michael Pavone # Date 1420151815 28800 # Node ID a18e3923481ef4f92c4576c4287d925a21575872 # Parent f822d92169685bbcb6566585adf1e18151352da3 Remove some of the hard coded assumptions about the memory map from the CPU cores diff -r f822d9216968 -r a18e3923481e backend.c --- a/backend.c Tue Dec 30 19:11:34 2014 -0800 +++ b/backend.c Thu Jan 01 14:36:55 2015 -0800 @@ -51,3 +51,24 @@ } } +void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts) +{ + memmap_chunk * memmap = opts->memmap; + address &= opts->address_mask; + for (uint32_t chunk = 0; chunk < opts->memmap_chunks; chunk++) + { + if (address >= memmap[chunk].start && address < memmap[chunk].end) { + if (!(memmap[chunk].flags & MMAP_READ)) { + return NULL; + } + uint8_t * base = memmap[chunk].flags & MMAP_PTR_IDX + ? mem_pointers[memmap[chunk].ptr_index] + : memmap[chunk].buffer; + if (!base) { + return NULL; + } + return base + (address & memmap[chunk].mask); + } + } + return NULL; +} diff -r f822d9216968 -r a18e3923481e backend.h --- a/backend.h Tue Dec 30 19:11:34 2014 -0800 +++ b/backend.h Thu Jan 01 14:36:55 2015 -0800 @@ -46,33 +46,6 @@ WRITE_8 } ftype; -typedef struct { - uint32_t flags; - native_map_slot *native_code_map; - deferred_addr *deferred; - code_info code; - uint8_t **ram_inst_sizes; - code_ptr save_context; - code_ptr load_context; - code_ptr handle_cycle_limit; - code_ptr handle_cycle_limit_int; - code_ptr handle_code_write; - uint32_t address_mask; - uint32_t max_address; - uint32_t bus_cycles; - int32_t mem_ptr_off; - int32_t ram_flags_off; - uint8_t ram_flags_shift; - uint8_t address_size; - uint8_t byte_swap; - uint8_t context_reg; - uint8_t cycles; - uint8_t limit; - uint8_t scratch1; - uint8_t scratch2; -} cpu_options; - - #define MMAP_READ 0x01 #define MMAP_WRITE 0x02 #define MMAP_CODE 0x04 @@ -100,6 +73,34 @@ write_8_fun write_8; } memmap_chunk; +typedef struct { + uint32_t flags; + native_map_slot *native_code_map; + deferred_addr *deferred; + code_info code; + uint8_t **ram_inst_sizes; + memmap_chunk const *memmap; + code_ptr save_context; + code_ptr load_context; + code_ptr handle_cycle_limit; + code_ptr handle_cycle_limit_int; + code_ptr handle_code_write; + uint32_t memmap_chunks; + uint32_t address_mask; + uint32_t max_address; + uint32_t bus_cycles; + int32_t mem_ptr_off; + int32_t ram_flags_off; + uint8_t ram_flags_shift; + uint8_t address_size; + uint8_t byte_swap; + uint8_t context_reg; + uint8_t cycles; + uint8_t limit; + uint8_t scratch1; + uint8_t scratch2; +} cpu_options; + typedef uint8_t * (*native_addr_func)(void * context, uint32_t address); deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest); @@ -112,6 +113,7 @@ void check_code_prologue(code_info *code); code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk const * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc); +void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts); #endif //BACKEND_H_ diff -r f822d9216968 -r a18e3923481e m68k_core.c --- a/m68k_core.c Tue Dec 30 19:11:34 2014 -0800 +++ b/m68k_core.c Thu Jan 01 14:36:55 2015 -0800 @@ -754,26 +754,17 @@ m68kinst instbuf; m68k_options * opts = context->options; code_info *code = &opts->gen.code; - address &= 0xFFFFFF; if(get_native_address(opts->gen.native_code_map, address)) { return; } - char disbuf[1024]; uint16_t *encoded, *next; - if ((address & 0xFFFFFF) < 0x400000) { - encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2; - } else if ((address & 0xFFFFFF) > 0xE00000) { - encoded = context->mem_pointers[1] + (address & 0xFFFF)/2; - } else { - printf("attempt to translate non-memory address: %X\n", address); - exit(1); - } do { if (opts->address_log) { fprintf(opts->address_log, "%X\n", address); } do { - if (address >= 0x400000 && address < 0xE00000) { + encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); + if (!encoded) { translate_out_of_bounds(code); break; } @@ -788,7 +779,7 @@ } uint16_t m68k_size = (next-encoded)*2; address += m68k_size; - encoded = next; + //char disbuf[1024]; //m68k_disasm(&instbuf, disbuf); //printf("%X: %s\n", instbuf.address, disbuf); @@ -802,18 +793,8 @@ process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); if (opts->gen.deferred) { address = opts->gen.deferred->address; - if ((address & 0xFFFFFF) < 0x400000) { - encoded = context->mem_pointers[0] + (address & 0xFFFFFF)/2; - } else if ((address & 0xFFFFFF) > 0xE00000) { - encoded = context->mem_pointers[1] + (address & 0xFFFF)/2; - } else { - printf("attempt to translate non-memory address: %X\n", address); - exit(1); - } - } else { - encoded = NULL; } - } while(encoded != NULL); + } while(opts->gen.deferred); } void * m68k_retranslate_inst(uint32_t address, m68k_context * context) @@ -826,8 +807,7 @@ code_info orig_code; orig_code.cur = orig_start; orig_code.last = orig_start + orig_size + 5; - address &= 0xFFFF; - uint16_t *after, *inst = context->mem_pointers[1] + address/2; + uint16_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); m68kinst instbuf; after = m68k_decode(inst, &instbuf, orig); if (orig_size != MAX_NATIVE_SIZE) { @@ -910,7 +890,7 @@ void remove_breakpoint(m68k_context * context, uint32_t address) { code_ptr native = get_native_address(context->native_code_map, address); - check_cycles_int(context->options, address); + check_cycles_int(&context->options->gen, address); } void start_68k_context(m68k_context * context, uint32_t address) @@ -922,9 +902,10 @@ void m68k_reset(m68k_context * context) { - //TODO: Make this actually use the normal read functions - context->aregs[7] = context->mem_pointers[0][0] << 16 | context->mem_pointers[0][1]; - uint32_t address = context->mem_pointers[0][2] << 16 | context->mem_pointers[0][3]; + //TODO: Actually execute the M68K reset vector rather than simulating some of its behavior + uint16_t *reset_vec = get_native_pointer(0, (void **)context->mem_pointers, &context->options->gen); + context->aregs[7] = reset_vec[0] << 16 | reset_vec[1]; + uint32_t address = reset_vec[2] << 16 | reset_vec[3]; start_68k_context(context, address); } diff -r f822d9216968 -r a18e3923481e m68k_core.h --- a/m68k_core.h Tue Dec 30 19:11:34 2014 -0800 +++ b/m68k_core.h Thu Jan 01 14:36:55 2015 -0800 @@ -59,7 +59,7 @@ uint16_t reserved; native_map_slot *native_code_map; - void *options; + m68k_options *options; uint8_t ram_code_flags[32/8]; void *system; } m68k_context; diff -r f822d9216968 -r a18e3923481e m68k_core_x86.c --- a/m68k_core_x86.c Tue Dec 30 19:11:34 2014 -0800 +++ b/m68k_core_x86.c Thu Jan 01 14:36:55 2015 -0800 @@ -1464,7 +1464,7 @@ set_flag_cond(opts, CC_O, FLAG_V); *no_adjust = code->cur - (no_adjust+1); flag_to_flag(opts, FLAG_C, FLAG_X); - + cmp_ir(code, 0, opts->gen.scratch1, SZ_B); set_flag_cond(opts, CC_S, FLAG_N); jcc(code, CC_Z, code->cur + 4); @@ -1664,7 +1664,7 @@ case MODE_ABSOLUTE_SHORT: case MODE_PC_INDEX_DISP8: case MODE_IMMEDIATE: - isize = 4; + isize = 4; break; case MODE_ABSOLUTE: isize = 6; @@ -2230,6 +2230,8 @@ void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks) { memset(opts, 0, sizeof(*opts)); + opts->gen.memmap = memmap; + opts->gen.memmap_chunks = num_chunks; opts->gen.address_size = SZ_D; opts->gen.address_mask = 0xFFFFFF; opts->gen.byte_swap = 1; diff -r f822d9216968 -r a18e3923481e z80_to_x86.c --- a/z80_to_x86.c Tue Dec 30 19:11:34 2014 -0800 +++ b/z80_to_x86.c Thu Jan 01 14:36:55 2015 -0800 @@ -1331,7 +1331,7 @@ num_cycles += 4; } cycles(&opts->gen, num_cycles); - if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) { + if (inst->addr_mode != Z80_REG_INDIRECT) { code_ptr call_dst = z80_get_native_address(context, inst->immed); if (!call_dst) { opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); @@ -1380,38 +1380,26 @@ jcc(code, cond, code->cur+2); cycles(&opts->gen, 5);//T States: 5 uint16_t dest_addr = inst->immed; - if (dest_addr < 0x4000) { - code_ptr call_dst = z80_get_native_address(context, dest_addr); - if (!call_dst) { - opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); - //fake address to force large displacement - call_dst = code->cur + 256; - } - jmp(code, call_dst); - } else { - mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + code_ptr call_dst = z80_get_native_address(context, dest_addr); + if (!call_dst) { + opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); + //fake address to force large displacement + call_dst = code->cur + 256; } + jmp(code, call_dst); *no_jump_off = code->cur - (no_jump_off+1); break; } case Z80_JR: { cycles(&opts->gen, 12);//T States: 4,3,5 uint16_t dest_addr = address + inst->immed + 2; - if (dest_addr < 0x4000) { - code_ptr call_dst = z80_get_native_address(context, dest_addr); - if (!call_dst) { - opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); - //fake address to force large displacement - call_dst = code->cur + 256; - } - jmp(code, call_dst); - } else { - mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + code_ptr call_dst = z80_get_native_address(context, dest_addr); + if (!call_dst) { + opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); + //fake address to force large displacement + call_dst = code->cur + 256; } + jmp(code, call_dst); break; } case Z80_JRCC: { @@ -1434,66 +1422,49 @@ jcc(code, cond, code->cur+2); cycles(&opts->gen, 5);//T States: 5 uint16_t dest_addr = address + inst->immed + 2; - if (dest_addr < 0x4000) { - code_ptr call_dst = z80_get_native_address(context, dest_addr); - if (!call_dst) { - opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); - //fake address to force large displacement - call_dst = code->cur + 256; - } - jmp(code, call_dst); - } else { - mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + code_ptr call_dst = z80_get_native_address(context, dest_addr); + if (!call_dst) { + opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); + //fake address to force large displacement + call_dst = code->cur + 256; } + jmp(code, call_dst); *no_jump_off = code->cur - (no_jump_off+1); break; } - case Z80_DJNZ: + case Z80_DJNZ: { cycles(&opts->gen, 8);//T States: 5,3 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); uint8_t *no_jump_off = code->cur+1; jcc(code, CC_Z, code->cur+2); cycles(&opts->gen, 5);//T States: 5 uint16_t dest_addr = address + inst->immed + 2; - if (dest_addr < 0x4000) { - code_ptr call_dst = z80_get_native_address(context, dest_addr); - if (!call_dst) { - opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); - //fake address to force large displacement - call_dst = code->cur + 256; - } - jmp(code, call_dst); - } else { - mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + code_ptr call_dst = z80_get_native_address(context, dest_addr); + if (!call_dst) { + opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1); + //fake address to force large displacement + call_dst = code->cur + 256; } + jmp(code, call_dst); *no_jump_off = code->cur - (no_jump_off+1); break; + } case Z80_CALL: { cycles(&opts->gen, 11);//T States: 4,3,4 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); call(code, opts->write_16_highfirst);//T States: 3, 3 - if (inst->immed < 0x4000) { - code_ptr call_dst = z80_get_native_address(context, inst->immed); - if (!call_dst) { - opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); - //fake address to force large displacement - call_dst = code->cur + 256; - } - jmp(code, call_dst); - } else { - mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + code_ptr call_dst = z80_get_native_address(context, inst->immed); + if (!call_dst) { + opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); + //fake address to force large displacement + call_dst = code->cur + 256; } + jmp(code, call_dst); break; } - case Z80_CALLCC: + case Z80_CALLCC: { cycles(&opts->gen, 10);//T States: 4,3,3 (false case) uint8_t cond = CC_Z; switch (inst->reg) @@ -1526,21 +1497,16 @@ mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); call(code, opts->write_16_highfirst);//T States: 3, 3 - if (inst->immed < 0x4000) { - code_ptr call_dst = z80_get_native_address(context, inst->immed); - if (!call_dst) { - opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); - //fake address to force large displacement - call_dst = code->cur + 256; - } - jmp(code, call_dst); - } else { - mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); - call(code, opts->native_addr); - jmp_r(code, opts->gen.scratch1); + code_ptr call_dst = z80_get_native_address(context, inst->immed); + if (!call_dst) { + opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); + //fake address to force large displacement + call_dst = code->cur + 256; } + jmp(code, call_dst); *no_call_off = code->cur - (no_call_off+1); break; + } case Z80_RET: cycles(&opts->gen, 4);//T States: 4 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); @@ -1850,10 +1816,8 @@ char disbuf[80]; z80_options * opts = context->options; uint8_t orig_size = z80_get_native_inst_size(opts, address); - uint32_t orig = address; - address &= 0x1FFF; code_info *code = &opts->gen.code; - uint8_t *after, *inst = context->mem_pointers[0] + address; + uint8_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); z80inst instbuf; dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start); after = z80_decode(inst, &instbuf); @@ -1921,26 +1885,24 @@ } z80_options * opts = context->options; uint32_t start_address = address; - uint8_t * encoded = NULL, *next; - if (address < 0x4000) { - encoded = context->mem_pointers[0] + (address & 0x1FFF); - } - while (encoded != NULL || address >= 0x4000) + do { z80inst inst; dprintf("translating Z80 code at address %X\n", address); do { - if (address >= 0x4000) { - code_info stub = z80_make_interp_stub(context, address); - z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur); - break; - } uint8_t * existing = z80_get_native_address(context, address); if (existing) { jmp(&opts->gen.code, existing); break; } + uint8_t * encoded, *next; + encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen); + if (!encoded) { + code_info stub = z80_make_interp_stub(context, address); + z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur); + break; + } //make sure prologue is in a contiguous chunk of code check_code_prologue(&opts->gen.code); next = z80_decode(encoded, &inst); @@ -1956,33 +1918,22 @@ translate_z80inst(&inst, context, address, 0); z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start); address += next-encoded; - if (address > 0xFFFF) { - address &= 0xFFFF; - - } else { - encoded = next; - } + address &= 0xFFFF; } while (!z80_is_terminal(&inst)); process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address); if (opts->gen.deferred) { address = opts->gen.deferred->address; dprintf("defferred address: %X\n", address); - if (address < 0x4000) { - encoded = context->mem_pointers[0] + (address & 0x1FFF); - } else { - encoded = NULL; - } - } else { - encoded = NULL; - address = 0; } - } + } while (opts->gen.deferred); } void init_x86_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks) { memset(options, 0, sizeof(*options)); + options->gen.memmap = chunks; + options->gen.memmap_chunks = num_chunks; options->gen.address_size = SZ_W; options->gen.address_mask = 0xFFFF; options->gen.max_address = 0x10000;