changeset 268:6c2d7e003a55

Sync Z80 on writes to busreq/reset ports. NULL out extra_pc on z80 reset
author Mike Pavone <pavone@retrodev.com>
date Thu, 02 May 2013 21:54:04 -0700
parents 1788e3f29c28
children 3c054d977175
files blastem.c z80_to_x86.c
diffstat 2 files changed, 64 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Thu May 02 00:10:24 2013 -0700
+++ b/blastem.c	Thu May 02 21:54:04 2013 -0700
@@ -134,12 +134,14 @@
 uint32_t busack_cycle = CYCLE_NEVER;
 uint8_t new_busack = 0;
 
-m68k_context * sync_components(m68k_context * context, uint32_t address)
+#ifdef DO_DEBUG_PRINT
+#define dprintf printf
+#else
+#define dprintf
+#endif
+
+void sync_z80(z80_context * z_context, uint32_t mclks)
 {
-	//TODO: Handle sync targets smaller than a single frame
-	z80_context * z_context = context->next_cpu;
-	vdp_context * v_context = context->video_context;
-	uint32_t mclks = context->current_cycle * MCLKS_PER_68K;
 	if (z80_enabled && !reset && !busreq) {
 		if (need_reset) {
 			z80_reset(z_context);
@@ -151,11 +153,20 @@
 				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. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc);
+			dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc);
 			z80_run(z_context);
-			//printf("Z80 ran to cycle %d\n", z_context->current_cycle);
+			dprintf("Z80 ran to cycle %d\n", z_context->current_cycle);
 		}
 	}
+}
+
+m68k_context * sync_components(m68k_context * context, uint32_t address)
+{
+	//TODO: Handle sync targets smaller than a single frame
+	vdp_context * v_context = context->video_context;
+	z80_context * z_context = context->next_cpu;
+	uint32_t mclks = context->current_cycle * MCLKS_PER_68K;
+	sync_z80(z_context, mclks);
 	if (mclks >= MCLKS_PER_FRAME) {
 		//printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks);
 		vdp_run_context(v_context, MCLKS_PER_FRAME);
@@ -373,11 +384,13 @@
 			}
 		} else {
 			if (location == 0x1100) {
+				sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K);
 				if (busack_cycle > context->current_cycle) {
 					busack = new_busack;
 					busack_cycle = CYCLE_NEVER;
 				}
 				if (value & 1) {
+					puts("bus requesting Z80");
 					busreq = 1;
 					if(!reset) {
 						busack_cycle = context->current_cycle + Z80_ACK_DELAY;
@@ -385,6 +398,7 @@
 					}
 				} else {
 					if (busreq) {
+						puts("releasing z80 bus");
 						z80_context * z_context = context->next_cpu;
 						//TODO: Add necessary delay between release of busreq and resumption of execution
 						z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
@@ -394,6 +408,7 @@
 					busack = 1;
 				}
 			} else if (location == 0x1200) {
+				sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K);
 				if (value & 1) {
 					if (reset && busreq) {
 						new_busack = 0;
@@ -453,11 +468,13 @@
 		} else {
 			//printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle);
 			if (location == 0x1100) {
+				sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K);
 				if (busack_cycle > context->current_cycle) {
 					busack = new_busack;
 					busack_cycle = CYCLE_NEVER;
 				}
 				if (value & 0x100) {
+					printf("bus requesting Z80 @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80);
 					busreq = 1;
 					if(!reset) {
 						busack_cycle = context->current_cycle + Z80_ACK_DELAY;
@@ -465,6 +482,7 @@
 					}
 				} else {
 					if (busreq) {
+						printf("releasing Z80 bus @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80);
 						z80_context * z_context = context->next_cpu;
 						//TODO: Add necessary delay between release of busreq and resumption of execution
 						z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
@@ -474,6 +492,7 @@
 					busack = 1;
 				}
 			} else if (location == 0x1200) {
+				sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K);
 				if (value & 0x100) {
 					if (reset && busreq) {
 						new_busack = 0;
--- a/z80_to_x86.c	Thu May 02 00:10:24 2013 -0700
+++ b/z80_to_x86.c	Thu May 02 21:54:04 2013 -0700
@@ -15,6 +15,12 @@
 #define SCRATCH2 R14
 #define CONTEXT RSI
 
+#ifdef DO_DEBUG_PRINT
+#define dprintf printf
+#else
+#define dprintf
+#endif
+
 void z80_read_byte();
 void z80_read_word();
 void z80_write_byte();
@@ -114,10 +120,16 @@
 			dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
 		} else if(opts->regs[inst->reg] >= 0) {
 			ea->base = opts->regs[inst->reg];
-			if (ea->base >= AH && ea->base <= BH && (inst->addr_mode & 0x1F) == Z80_REG) {
-				uint8_t other_reg = opts->regs[inst->ea_reg];
-				if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) {
-					//we can't mix an *H reg with a register that requires the REX prefix
+			if (ea->base >= AH && ea->base <= BH) {
+				if ((inst->addr_mode & 0x1F) == Z80_REG) {
+					uint8_t other_reg = opts->regs[inst->ea_reg];
+					if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) {
+						//we can't mix an *H reg with a register that requires the REX prefix
+						ea->base = opts->regs[z80_low_reg(inst->reg)];
+						dst = ror_ir(dst, 8, ea->base, SZ_W);
+					}
+				} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
+					//temp regs require REX prefix too
 					ea->base = opts->regs[z80_low_reg(inst->reg)];
 					dst = ror_ir(dst, 8, ea->base, SZ_W);
 				}
@@ -135,10 +147,15 @@
 {
 	if (inst->reg == Z80_IYH) {
 		dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
-	} else if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) {
-		uint8_t other_reg = opts->regs[inst->ea_reg];
-		if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) {
-			//we can't mix an *H reg with a register that requires the REX prefix
+	} else if (opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) {
+		if ((inst->addr_mode & 0x1F) == Z80_REG) {
+			uint8_t other_reg = opts->regs[inst->ea_reg];
+			if (other_reg > R8 || (other_reg >= RSP && other_reg <= RDI)) {
+				//we can't mix an *H reg with a register that requires the REX prefix
+				dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
+			}
+		} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
+			//temp regs require REX prefix too
 			dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
 		}
 	}
@@ -1272,14 +1289,14 @@
 		address &= 0x7FFF;
 		map = context->banked_code_map + (context->bank_reg << 15);
 	} else {
-		printf("z80_get_native_address: %X NULL\n", address);
+		dprintf("z80_get_native_address: %X NULL\n", address);
 		return NULL;
 	}
-	if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET) {
-		printf("z80_get_native_address: %X NULL\n", address);
+	if (!map->base || !map->offsets || map->offsets[address] == INVALID_OFFSET || map->offsets[address] == EXTENSION_WORD) {
+		dprintf("z80_get_native_address: %X NULL\n", address);
 		return NULL;
 	}
-	printf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]);
+	dprintf("z80_get_native_address: %X %p\n", address, map->base + map->offsets[address]);
 	return map->base + map->offsets[address];
 }
 
@@ -1358,7 +1375,7 @@
 	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);
+		dprintf("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);
 	}
@@ -1399,14 +1416,16 @@
 	uint8_t * dst_end = opts->code_end;
 	uint8_t *after, *inst = context->mem_pointers[0] + address;
 	z80inst instbuf;
-	printf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
+	dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
 	after = z80_decode(inst, &instbuf);
+	#ifdef DO_DEBUG_PRINT
 	z80_disasm(&instbuf, disbuf);
 	if (instbuf.op == Z80_NOP) {
 		printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed);
 	} else {
 		printf("%X\t%s\n", address, disbuf);
 	}
+	#endif
 	if (orig_size != ZMAX_NATIVE_SIZE) {
 		if (dst_end - dst < ZMAX_NATIVE_SIZE) {
 			size_t size = 1024*1024;
@@ -1464,7 +1483,7 @@
 	while (encoded != NULL)
 	{
 		z80inst inst;
-		printf("translating Z80 code at address %X\n", address);
+		dprintf("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) {
@@ -1487,12 +1506,14 @@
 				break;
 			}
 			next = z80_decode(encoded, &inst);
+			#ifdef DO_DEBUG_PRINT
 			z80_disasm(&inst, disbuf);
 			if (inst.op == Z80_NOP) {
 				printf("%X\t%s(%d)\n", address, disbuf, inst.immed);
 			} else {
 				printf("%X\t%s\n", address, disbuf);
 			}
+			#endif
 			uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address);
 			z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code);
 			opts->cur_code = after;
@@ -1507,7 +1528,7 @@
 		process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address);
 		if (opts->deferred) {
 			address = opts->deferred->address;
-			printf("defferred address: %X\n", address);
+			dprintf("defferred address: %X\n", address);
 			if (address < 0x4000) {
 				encoded = context->mem_pointers[0] + (address & 0x1FFF);
 			} else if (address > 0x8000 && context->mem_pointers[1]) {
@@ -1570,6 +1591,7 @@
 	context->im = 0;
 	context->iff1 = context->iff2 = 0;
 	context->native_pc = z80_get_native_address_trans(context, 0);
+	context->extra_pc = NULL;
 }