changeset 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 2989ed7b8608
children c6d12878ea93
files blastem.c z80_to_x86.c
diffstat 2 files changed, 34 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Tue Apr 30 20:36:15 2013 -0700
+++ b/blastem.c	Wed May 01 20:09:53 2013 -0700
@@ -150,10 +150,7 @@
 				z_context->int_cycle = ZVINT_CYCLE;
 			}
 			z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle;
-			printf("Running Z80 from cycle %d to cycle %d\n", z_context->current_cycle, z_context->sync_cycle);
-			printf("HL: %X, Native PC: %p\n", (z_context->regs[Z80_H] << 8) | z_context->regs[Z80_L], z_context->native_pc);
 			z80_run(z_context);
-			printf("Z80 returned at cycle %d\n", z_context->current_cycle);
 		}
 	}
 	if (mclks >= MCLKS_PER_FRAME) {
--- 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) {