# HG changeset patch # User Mike Pavone # Date 1367705755 25200 # Node ID 61f5d88ea01abc9ece388e02d971beeb37060c7c # Parent 7b8a49220e3b5be885bde6404d1b2200d6a12f96 Implement RETI and RETN (untested). Cleanup tests for "terminal" instructions. diff -r 7b8a49220e3b -r 61f5d88ea01a z80_to_x86.c --- 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;