diff z80_to_x86.c @ 239:a5bea9711a46

Implement BIT and DJNZ (tested). Fix register mapping for IYL.
author Mike Pavone <pavone@retrodev.com>
date Fri, 26 Apr 2013 22:27:17 -0700
parents 827ebce557bf
children 2586d49ddd46
line wrap: on
line diff
--- a/z80_to_x86.c	Fri Apr 26 09:51:57 2013 -0700
+++ b/z80_to_x86.c	Fri Apr 26 22:27:17 2013 -0700
@@ -530,19 +530,29 @@
 	case Z80_SLL:
 	case Z80_SRL:
 	case Z80_RLD:
-	case Z80_RRD:
+	case Z80_RRD:*/
 	case Z80_BIT:
-	case Z80_SET:
-	case Z80_RES:*/
+		cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
+		dst = zcycles(dst, cycles);
+		dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+		if (inst->addr_mode != Z80_REG) {
+			//Reads normally take 3 cycles, but the read at the end of a bit instruction takes 4
+			dst = zcycles(dst, 1);
+		}
+		dst = bt_ir(dst, inst->immed, src_op.base, SZ_B);
+		dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_Z));
+		break;
+	//case Z80_SET:
+	//case Z80_RES:
 	case Z80_JP: {
 		cycles = 4;
-		if (inst->addr_mode != MODE_REG_INDIRECT) {
+		if (inst->addr_mode != Z80_REG) {
 			cycles += 6;
 		} else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) {
 			cycles += 4;
 		}
 		dst = zcycles(dst, cycles);
-		if (inst->addr_mode != MODE_REG_INDIRECT && inst->immed < 0x4000) {
+		if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) {
 			uint8_t * call_dst = z80_get_native_address(context, inst->immed);
 			if (!call_dst) {
 				opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1);
@@ -551,7 +561,7 @@
 			}
 			dst = jmp(dst, call_dst);
 		} else {
-			if (inst->addr_mode == MODE_REG_INDIRECT) {
+			if (inst->addr_mode == Z80_REG_INDIRECT) {
 				dst = mov_rr(dst, opts->regs[inst->ea_reg], SCRATCH1, SZ_W);
 			} else {
 				dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W);
@@ -660,7 +670,28 @@
 		*no_jump_off = dst - (no_jump_off+1);
 		break;
 	}
-	//case Z80_DJNZ:*/
+	case Z80_DJNZ:
+		dst = zcycles(dst, 8);//T States: 5,3
+		dst = sub_ir(dst, 1, opts->regs[Z80_B], SZ_B);
+		uint8_t *no_jump_off = dst+1;
+		dst = jcc(dst, CC_Z, dst+2);
+		dst = zcycles(dst, 5);//T States: 5
+		uint16_t dest_addr = address + inst->immed + 2;
+		if (dest_addr < 0x4000) {
+			uint8_t * call_dst = z80_get_native_address(context, dest_addr);
+			if (!call_dst) {
+				opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1);
+				//fake address to force large displacement
+				call_dst = dst + 256;
+			}
+			dst = jmp(dst, call_dst);
+		} else {
+			dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W);
+			dst = call(dst, (uint8_t *)z80_native_addr);
+			dst = jmp_r(dst, SCRATCH1);
+		}
+		*no_jump_off = dst - (no_jump_off+1);
+		break;
 	case Z80_CALL: {
 		dst = zcycles(dst, 11);//T States: 4,3,4
 		dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
@@ -892,7 +923,7 @@
 	options->regs[Z80_IXH] = DH;
 	options->regs[Z80_IXL] = RDX;
 	options->regs[Z80_IYH] = -1;
-	options->regs[Z80_IYL] = -1;
+	options->regs[Z80_IYL] = R8;
 	options->regs[Z80_I] = -1;
 	options->regs[Z80_R] = -1;
 	options->regs[Z80_A] = R10;