Mercurial > repos > blastem
diff z80_to_x86.c @ 264:8fd6652e56f8
Fix a crash bug in instruction retranslation
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 01 May 2013 20:09:53 -0700 |
parents | d97c9eca49f4 |
children | 376df762ddf5 |
line wrap: on
line diff
--- a/z80_to_x86.c Tue Apr 30 20:36:15 2013 -0700 +++ b/z80_to_x86.c Wed May 01 20:09:53 2013 -0700 @@ -1223,6 +1223,7 @@ if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) { return NULL; } + //printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]); return map->base + map->offsets[address]; } @@ -1301,12 +1302,26 @@ 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); + //printf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address); dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D); dst = jmp(dst, (uint8_t *)z80_retrans_stub); } return context; } +uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) +{ + uint8_t * addr = z80_get_native_address(context, address); + if (!addr) { + translate_z80_stream(context, address); + addr = z80_get_native_address(context, address); + if (!addr) { + printf("Failed to translate %X to native code\n", address); + } + } + return addr; +} + void * z80_retranslate_inst(uint32_t address, z80_context * context) { x86_z80_options * opts = context->options; @@ -1328,41 +1343,34 @@ } 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 + uint8_t * native_next = z80_get_native_address(context, address + after-inst); + if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) { + native_end = translate_z80inst(&instbuf, orig_start, context, address); + if (native_next == orig_start + orig_size) { + while (native_end < orig_start + orig_size) { + *(native_end++) = 0x90; //NOP + } + } else { + jmp(native_end, native_next); + } + return orig_start; } - 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; } + 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_trans(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)); + dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst)); } return orig_start; } } -uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address) -{ - uint8_t * addr = z80_get_native_address(context, address); - if (!addr) { - translate_z80_stream(context, address); - addr = z80_get_native_address(context, address); - if (!addr) { - printf("Failed to translate %X to native code\n", address); - } - } - return addr; -} - void translate_z80_stream(z80_context * context, uint32_t address) { char disbuf[80]; @@ -1379,7 +1387,7 @@ while (encoded != NULL) { z80inst inst; - printf("translating Z80 code at address %X\n", address); + //printf("translating Z80 code at address %X\n", address); do { if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) { if (opts->code_end-opts->cur_code < 5) {