# HG changeset patch # User Mike Pavone # Date 1367297208 25200 # Node ID 63b9a500a00b5bf95532a5074f0c79eb88f7cadc # Parent 4a7ac10ac2d98fe0c00e75118fc7c5181f87f7f9 Implement retranslating code when written to. Possibly broken, need to fix some other bugs before a proper test. diff -r 4a7ac10ac2d9 -r 63b9a500a00b m68k_to_x86.h --- a/m68k_to_x86.h Mon Apr 29 01:14:24 2013 -0700 +++ b/m68k_to_x86.h Mon Apr 29 21:46:48 2013 -0700 @@ -9,7 +9,6 @@ #define NUM_MEM_AREAS 4 #define NATIVE_MAP_CHUNKS (64*1024) #define NATIVE_CHUNK_SIZE ((16 * 1024 * 1024 / NATIVE_MAP_CHUNKS)/2) -#define EXTENSION_WORD 0xFFFFFFFE #define MAX_NATIVE_SIZE 255 #define OPT_NATIVE_CALL_STACK 0x1 diff -r 4a7ac10ac2d9 -r 63b9a500a00b x86_backend.h --- a/x86_backend.h Mon Apr 29 01:14:24 2013 -0700 +++ b/x86_backend.h Mon Apr 29 21:46:48 2013 -0700 @@ -4,6 +4,7 @@ #include #define INVALID_OFFSET 0xFFFFFFFF +#define EXTENSION_WORD 0xFFFFFFFE typedef struct { int32_t disp; diff -r 4a7ac10ac2d9 -r 63b9a500a00b z80_to_x86.c --- a/z80_to_x86.c Mon Apr 29 01:14:24 2013 -0700 +++ b/z80_to_x86.c Mon Apr 29 21:46:48 2013 -0700 @@ -15,9 +15,6 @@ #define SCRATCH2 R14 #define CONTEXT RSI -//TODO: Find out the actual value for this -#define MAX_NATIVE_SIZE 128 - void z80_read_byte(); void z80_read_word(); void z80_write_byte(); @@ -27,6 +24,7 @@ void z80_native_addr(); void z80_do_sync(); void z80_handle_cycle_limit_int(); +void z80_retrans_stub(); uint8_t z80_size(z80inst * inst) { @@ -1167,7 +1165,7 @@ map = context->static_code_map; } else if (address >= 0x8000) { address &= 0x7FFF; - map = context->banked_code_map + context->bank_reg; + map = context->banked_code_map + (context->bank_reg << 15); } else { return NULL; } @@ -1177,16 +1175,28 @@ return map->base + map->offsets[address]; } -//TODO: Record z80 instruction size and code size for addresses to support modification of translated code -void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address) +uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address) { + if (address >= 0x4000) { + return 0; + } + return opts->ram_inst_sizes[address & 0x1FFF]; +} + +void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size) +{ + uint32_t orig_address = address; native_map_slot *map; + x86_z80_options * opts = context->options; if (address < 0x4000) { address &= 0x1FFF; map = context->static_code_map; + opts->ram_inst_sizes[address] = native_size; + context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7); + context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7); } else if (address >= 0x8000) { address &= 0x7FFF; - map = context->banked_code_map + context->bank_reg; + map = context->banked_code_map + (context->bank_reg << 15); if (!map->offsets) { map->offsets = malloc(sizeof(int32_t) * 0x8000); memset(map->offsets, 0xFF, sizeof(int32_t) * 0x8000); @@ -1198,6 +1208,95 @@ map->base = native_address; } map->offsets[address] = native_address - map->base; + for(--size; size; --size, orig_address++) { + address = orig_address; + if (address < 0x4000) { + address &= 0x1FFF; + map = context->static_code_map; + } else if (address >= 0x8000) { + address &= 0x7FFF; + map = context->banked_code_map + (context->bank_reg << 15); + } else { + return; + } + if (!map->offsets) { + map->offsets = malloc(sizeof(int32_t) * 0x8000); + memset(map->offsets, 0xFF, sizeof(int32_t) * 0x8000); + } + map->offsets[address] = EXTENSION_WORD; + } +} + +#define INVALID_INSTRUCTION_START 0xFEEDFEED + +uint32_t z80_get_instruction_start(native_map_slot * static_code_map, uint32_t address) +{ + if (!static_code_map->base || address >= 0x4000) { + return INVALID_INSTRUCTION_START; + } + address &= 0x1FFF; + if (static_code_map->offsets[address] == INVALID_OFFSET) { + return INVALID_INSTRUCTION_START; + } + while (static_code_map->offsets[address] == EXTENSION_WORD) { + --address; + address &= 0x1FFF; + } + return address; +} + +z80_context * z80_handle_code_write(uint32_t address, z80_context * context) +{ + uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address); + if (inst_start != INVALID_INSTRUCTION_START) { + uint8_t * dst = z80_get_native_address(context, inst_start); + dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); + dst = jmp(dst, (uint8_t *)z80_retrans_stub); + } + return context; +} + +void * z80_retranslate_inst(uint32_t address, z80_context * context) +{ + x86_z80_options * opts = context->options; + uint8_t orig_size = z80_get_native_inst_size(opts, address); + uint8_t * orig_start = z80_get_native_address(context, address); + uint32_t orig = address; + address &= 0x1FFF; + uint8_t * dst = opts->cur_code; + uint8_t * dst_end = opts->code_end; + uint8_t *after, *inst = context->mem_pointers[0] + address; + z80inst instbuf; + after = z80_decode(inst, &instbuf); + if (orig_size != ZMAX_NATIVE_SIZE) { + if (dst_end - dst < ZMAX_NATIVE_SIZE) { + size_t size = 1024*1024; + dst = alloc_code(&size); + opts->code_end = dst_end = dst + size; + opts->cur_code = dst; + } + uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address); + if ((native_end - dst) <= orig_size) { + native_end = translate_z80inst(&instbuf, orig_start, context, address); + while (native_end < orig_start + orig_size) { + *(native_end++) = 0x90; //NOP + } + return orig_start; + } else { + z80_map_native_address(context, address, dst, after-inst, ZMAX_NATIVE_SIZE); + opts->code_end = dst+ZMAX_NATIVE_SIZE; + if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op = Z80_NOP && instbuf.immed == 42))) { + jmp(native_end, z80_get_native_address(context, address + after-inst)); + } + return dst; + } + } else { + dst = translate_z80inst(&instbuf, orig_start, context, address); + if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op = Z80_NOP && instbuf.immed == 42))) { + dst = jmp(dst, z80_get_native_address(context, address + after-inst)); + } + return orig_start; + } } uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) @@ -1213,8 +1312,6 @@ return addr; } -//uint32_t max_size = 0; - void translate_z80_stream(z80_context * context, uint32_t address) { char disbuf[80]; @@ -1233,7 +1330,7 @@ z80inst inst; printf("translating Z80 code at address %X\n", address); do { - if (opts->code_end-opts->cur_code < MAX_NATIVE_SIZE) { + if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { if (opts->code_end-opts->cur_code < 5) { puts("out of code memory, not enough space for jmp to next chunk"); exit(1); @@ -1260,9 +1357,8 @@ } else { printf("%X\t%s\n", address, disbuf); } - z80_map_native_address(context, address, opts->cur_code); uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address); - //max_size = (after - opts->cur_code) > max_size ? (after - opts->cur_code) : max_size; + z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code); opts->cur_code = after; address += next-encoded; encoded = next; @@ -1311,6 +1407,8 @@ size_t size = 1024 * 1024; options->cur_code = alloc_code(&size); options->code_end = options->cur_code + size; + options->ram_inst_sizes = malloc(sizeof(uint8_t) * 0x2000); + memset(options->ram_inst_sizes, 0, sizeof(uint8_t) * 0x2000); options->deferred = NULL; } diff -r 4a7ac10ac2d9 -r 63b9a500a00b z80_to_x86.h --- a/z80_to_x86.h Mon Apr 29 01:14:24 2013 -0700 +++ b/z80_to_x86.h Mon Apr 29 21:46:48 2013 -0700 @@ -4,6 +4,7 @@ #include "x86_backend.h" #define ZNUM_MEM_AREAS 4 +#define ZMAX_NATIVE_SIZE 128 enum { ZF_C = 0, @@ -18,6 +19,7 @@ typedef struct { uint8_t * cur_code; uint8_t * code_end; + uint8_t *ram_inst_sizes; deferred_addr * deferred; uint32_t flags; int8_t regs[Z80_UNUSED]; @@ -46,6 +48,7 @@ native_map_slot * banked_code_map; void * options; void * next_context; + uint8_t ram_code_flags[(8 * 1024)/128/8]; } z80_context; void translate_z80_stream(z80_context * context, uint32_t address); diff -r 4a7ac10ac2d9 -r 63b9a500a00b zruntime.S --- a/zruntime.S Mon Apr 29 01:14:24 2013 -0700 +++ b/zruntime.S Mon Apr 29 21:46:48 2013 -0700 @@ -99,6 +99,15 @@ z80_write_ram: and $0x1FFF, %r13 mov %r14b, (%r11, %r13) + mov %r13d, %r14d + shr $7, %r14d + bt %r14d, 152(%rsi) + jnc not_code + call z80_save_context + mov %r13d, %edi + call z80_handle_code_write + mov %rax, %rsi +not_code: ret z80_write_bank: and $0x7FFF, %r13 @@ -167,6 +176,17 @@ call z_inccycles call z80_write_byte_noinc ret + + .global z80_retrans_stub +z80_retrans_stub: + call z80_save_context + mov %r13d, %edi + push %rsi + call z80_retranslate_inst + pop %rsi + mov %rax, %r13 + call z80_load_context + jmp *%r13 .global z80_native_addr z80_native_addr: