diff z80_to_x86.c @ 283:61f5d88ea01a

Implement RETI and RETN (untested). Cleanup tests for "terminal" instructions.
author Mike Pavone <pavone@retrodev.com>
date Sat, 04 May 2013 15:15:55 -0700
parents 7b8a49220e3b
children ed7098f717d7
line wrap: on
line diff
--- a/z80_to_x86.c	Sat May 04 14:36:50 2013 -0700
+++ b/z80_to_x86.c	Sat May 04 15:15:55 2013 -0700
@@ -1372,8 +1372,25 @@
 		*no_call_off = dst - (no_call_off+1);
 		break;
 	}
-	/*case Z80_RETI:
-	case Z80_RETN:*/
+	case Z80_RETI:
+		//For some systems, this may need a callback for signalling interrupt routine completion
+		dst = zcycles(dst, 8);//T States: 4, 4
+		dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W);
+		dst = call(dst, (uint8_t *)z80_read_word);//T STates: 3, 3
+		dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
+		dst = call(dst, (uint8_t *)z80_native_addr);
+		dst = jmp_r(dst, SCRATCH1);
+		break;
+	case Z80_RETN:
+		dst = zcycles(dst, 8);//T States: 4, 4
+		dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, iff2), SCRATCH2, SZ_B);
+		dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W);
+		dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, offsetof(z80_context, iff1), SZ_B);
+		dst = call(dst, (uint8_t *)z80_read_word);//T STates: 3, 3
+		dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
+		dst = call(dst, (uint8_t *)z80_native_addr);
+		dst = jmp_r(dst, SCRATCH1);
+		break;
 	case Z80_RST: {
 		//RST is basically CALL to an address in page 0
 		dst = zcycles(dst, 5);//T States: 5
@@ -1413,6 +1430,12 @@
 	return dst;
 }
 
+uint8_t z80_is_terminal(z80inst * inst)
+{
+	return inst->op == Z80_RET || inst->op == Z80_RETI || inst->op == Z80_RETN || inst->op == Z80_JP
+		|| inst->op == Z80_JR || inst->op == Z80_HALT || (inst->op == Z80_NOP && inst->immed == 42);
+}
+
 uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
 {
 	native_map_slot *map;
@@ -1588,14 +1611,14 @@
 		z80_map_native_address(context, address, dst, after-inst, ZMAX_NATIVE_SIZE);
 		opts->cur_code = dst+ZMAX_NATIVE_SIZE;
 		jmp(orig_start, dst);
-		if(!(instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_JP || (instbuf.op == Z80_NOP && instbuf.immed == 42))) {
+		if (!z80_is_terminal(&instbuf)) {
 			jmp(native_end, z80_get_native_address_trans(context, address + after-inst));
 		}
 		z80_handle_deferred(context);
 		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))) {
+		if (!z80_is_terminal(&instbuf)) {
 			dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst));
 		}
 		z80_handle_deferred(context);
@@ -1660,7 +1683,7 @@
 			} else {
 				encoded = next;
 			}
-		} while (!(inst.op == Z80_RET || inst.op == Z80_RETI || inst.op == Z80_RETN || inst.op == Z80_JP || (inst.op == Z80_NOP && inst.immed == 42)));
+		} while (!z80_is_terminal(&inst));
 		process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address);
 		if (opts->deferred) {
 			address = opts->deferred->address;