changeset 1060:56713dac6a69

Implement INI
author Michael Pavone <pavone@retrodev.com>
date Mon, 01 Aug 2016 09:48:10 -0700
parents 8da967779710
children 9b5bb50098d2
files z80_to_x86.c ztestrun.c
diffstat 2 files changed, 63 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/z80_to_x86.c	Sun Jul 31 15:20:00 2016 -0700
+++ b/z80_to_x86.c	Mon Aug 01 09:48:10 2016 -0700
@@ -2336,8 +2336,64 @@
 		}
 		z80_save_reg(inst, opts);
 		break;
-	/*case Z80_INI:
-	case Z80_INIR:
+	case Z80_INI:
+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
+		//read from IO (C)
+		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
+		call(code, opts->read_io);//T states 3
+		
+		//undocumented N flag behavior
+		//flag set on bit 7 of value written
+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
+		//save value to be written for flag calculation, as the write func does not
+		//guarantee that it's preserved across the call
+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
+		
+		//write to (HL)
+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
+		call(code, opts->write_8);//T states 4
+		cycles(&opts->gen, 1);
+		
+		//increment HL
+		if (opts->regs[Z80_HL] >= 0) {
+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
+		} else {
+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
+		}
+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
+		if (opts->regs[Z80_C] >= 0) {
+			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
+		} else {
+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
+		}
+		add_ir(code, 1, opts->gen.scratch1, SZ_B);
+		//undocumented C and H flag behavior
+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
+		//decrement B
+		if (opts->regs[Z80_B] >= 0) {
+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
+			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
+		} else {
+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
+		}
+		//undocumented Z and S flag behavior, set based on decrement of B
+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
+		//crazy undocumented P/V flag behavior
+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
+		if (opts->regs[Z80_B] >= 0) {
+			//deal with silly x86-64 restrictions on *H registers
+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
+		} else {
+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
+		}
+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+		break;
+	/*case Z80_INIR:
 	case Z80_IND:
 	case Z80_INDR:*/
 	case Z80_OUT:
--- a/ztestrun.c	Sun Jul 31 15:20:00 2016 -0700
+++ b/ztestrun.c	Mon Aug 01 09:48:10 2016 -0700
@@ -38,6 +38,10 @@
 	{ 0x4000, 0x10000, 0xFFFF, 0, 0,                                  NULL,    NULL, NULL, z80_unmapped_read, z80_unmapped_write}
 };
 
+const memmap_chunk port_map[] = {
+	{ 0x0000, 0x100, 0xFF, 0, 0,                                  NULL,    NULL, NULL, z80_unmapped_read, z80_unmapped_write}
+};
+
 void z80_next_int_pulse(z80_context * context)
 {
 	context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER;
@@ -85,7 +89,7 @@
 		exit(1);
 	}
 	fclose(f);
-	init_z80_opts(&opts, z80_map, 2, NULL, 0, 1);
+	init_z80_opts(&opts, z80_map, 2, port_map, 1, 1);
 	init_z80_context(&context, &opts);
 	//Z80 RAM
 	context.mem_pointers[0] = z80_ram;