Mercurial > repos > blastem
diff z80_to_x86.c @ 593:5ef3fe516da9
Z80 core is sort of working again
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 22 Dec 2014 20:55:10 -0800 |
parents | 4ff7bbb3943b |
children | 086de8692932 |
line wrap: on
line diff
--- a/z80_to_x86.c Wed Dec 17 23:03:19 2014 -0800 +++ b/z80_to_x86.c Mon Dec 22 20:55:10 2014 -0800 @@ -28,22 +28,6 @@ #define dprintf #endif -void z80_read_byte(); -void z80_read_word(); -void z80_write_byte(); -void z80_write_word_highfirst(); -void z80_write_word_lowfirst(); -void z80_save_context(); -void z80_native_addr(); -void z80_do_sync(); -void z80_handle_cycle_limit_int(); -void z80_retrans_stub(); -void z80_io_read(); -void z80_io_write(); -void z80_halt(); -void z80_save_context(); -void z80_load_context(); - uint8_t z80_size(z80inst * inst) { uint8_t reg = (inst->reg & 0x1F); @@ -184,9 +168,9 @@ push_r(code, opts->gen.scratch1); }*/ if (size == SZ_B) { - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); } else { - call(code, (uint8_t *)z80_read_word); + call(code, opts->read_16); } if (modify) { //pop_r(code, opts->gen.scratch2); @@ -207,9 +191,9 @@ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W); } if (size == SZ_B) { - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); } else { - call(code, (uint8_t *)z80_read_word); + call(code, opts->read_16); } if (modify) { //pop_r(code, opts->gen.scratch2); @@ -248,7 +232,7 @@ } } -void z80_save_result(code_info *code, z80inst * inst) +void z80_save_result(z80_options *opts, z80inst * inst) { switch(inst->addr_mode & 0x1f) { @@ -257,9 +241,9 @@ case Z80_IX_DISPLACE: case Z80_IY_DISPLACE: if (z80_size(inst) == SZ_B) { - call(code, (uint8_t *)z80_write_byte); + call(&opts->gen.code, opts->write_8); } else { - call(code, (uint8_t *)z80_write_word_lowfirst); + call(&opts->gen.code, opts->write_16_lowfirst); } } } @@ -369,7 +353,7 @@ z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); if (inst->addr_mode & Z80_DIR) { - z80_save_result(code, inst); + z80_save_result(opts, inst); } break; case Z80_PUSH: @@ -394,14 +378,14 @@ mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W); } mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_word_highfirst); + call(code, opts->write_16_highfirst); //no call to save_z80_reg needed since there's no chance we'll use the only //the upper half of a register pair break; case Z80_POP: cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_word); + call(code, opts->read_16); add_ir(code, 2, opts->regs[Z80_SP], SZ_W); if (inst->reg == Z80_AF) { @@ -452,10 +436,10 @@ } } else { mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); xchg_rr(code, opts->regs[inst->reg], opts->gen.scratch1, SZ_B); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); cycles(&opts->gen, 1); uint8_t high_reg = z80_high_reg(inst->reg); uint8_t use_reg; @@ -466,11 +450,11 @@ ror_ir(code, 8, use_reg, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); add_ir(code, 1, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); xchg_rr(code, use_reg, opts->gen.scratch1, SZ_B); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); add_ir(code, 1, opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); //restore reg to normal rotation ror_ir(code, 8, use_reg, SZ_W); cycles(&opts->gen, 2); @@ -491,9 +475,9 @@ case Z80_LDI: { cycles(&opts->gen, 8); mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); cycles(&opts->gen, 2); add_ir(code, 1, opts->regs[Z80_DE], SZ_W); add_ir(code, 1, opts->regs[Z80_HL], SZ_W); @@ -506,9 +490,9 @@ case Z80_LDIR: { cycles(&opts->gen, 8); mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); add_ir(code, 1, opts->regs[Z80_DE], SZ_W); add_ir(code, 1, opts->regs[Z80_HL], SZ_W); @@ -529,9 +513,9 @@ case Z80_LDD: { cycles(&opts->gen, 8); mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); cycles(&opts->gen, 2); sub_ir(code, 1, opts->regs[Z80_DE], SZ_W); sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); @@ -544,9 +528,9 @@ case Z80_LDDR: { cycles(&opts->gen, 8); mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); sub_ir(code, 1, opts->regs[Z80_DE], SZ_W); sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); @@ -810,7 +794,7 @@ } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); - z80_save_result(code, inst); + z80_save_result(opts, inst); break; case Z80_DEC: num_cycles = 4; @@ -836,7 +820,7 @@ } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); - z80_save_result(code, inst); + z80_save_result(opts, inst); break; //case Z80_DAA: case Z80_CPL: @@ -869,20 +853,30 @@ break; case Z80_NOP: if (inst->immed == 42) { - call(code, (uint8_t *)z80_save_context); + call(code, opts->gen.save_context); mov_rr(code, opts->gen.context_reg, RDI, SZ_Q); jmp(code, (uint8_t *)z80_print_regs_exit); } else { cycles(&opts->gen, 4 * inst->immed); } break; - case Z80_HALT: + case Z80_HALT: { cycles(&opts->gen, 4); mov_ir(code, address, opts->gen.scratch1, SZ_W); uint8_t * call_inst = code->cur; - call(code, (uint8_t *)z80_halt); + mov_rr(code, opts->gen.limit, opts->gen.scratch2, SZ_D); + sub_rr(code, opts->gen.cycles, opts->gen.scratch2, SZ_D); + and_ir(code, 0xFFFFFFFC, opts->gen.scratch2, SZ_D); + add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D); + cmp_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D); + code_ptr skip_last = code->cur+1; + jcc(code, CC_B, opts->gen.handle_cycle_limit_int); + cycles(&opts->gen, 4); + *skip_last = code->cur - (skip_last+1); + call(code, opts->gen.handle_cycle_limit_int); jmp(code, call_inst); break; + } case Z80_DI: cycles(&opts->gen, 4); mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); @@ -897,7 +891,7 @@ mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); //interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles add_irdisp(code, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); - call(code, (uint8_t *)z80_do_sync); + call(code, opts->do_sync); break; case Z80_IM: cycles(&opts->gen, 4); @@ -926,7 +920,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -958,7 +952,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -989,7 +983,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -1021,7 +1015,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -1056,7 +1050,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -1087,7 +1081,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -1118,7 +1112,7 @@ 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)); if (inst->addr_mode != Z80_UNUSED) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (src_op.mode != MODE_UNUSED) { z80_save_reg(inst, opts); } @@ -1129,7 +1123,7 @@ case Z80_RLD: cycles(&opts->gen, 8); mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); //Before: (HL) = 0x12, A = 0x34 //After: (HL) = 0x24, A = 0x31 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); @@ -1151,12 +1145,12 @@ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); ror_ir(code, 8, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); break; case Z80_RRD: cycles(&opts->gen, 8); mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_byte); + call(code, opts->read_8); //Before: (HL) = 0x12, A = 0x34 //After: (HL) = 0x41, A = 0x32 movzx_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W); @@ -1181,7 +1175,7 @@ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); ror_ir(code, 8, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_write_byte); + call(code, opts->write_8); break; case Z80_BIT: { num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; @@ -1247,7 +1241,7 @@ } } if ((inst->addr_mode & 0x1F) != Z80_REG) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (inst->reg != Z80_USE_IMMED) { z80_save_reg(inst, opts); } @@ -1289,7 +1283,7 @@ } } if (inst->addr_mode != Z80_REG) { - z80_save_result(code, inst); + z80_save_result(opts, inst); if (inst->reg != Z80_USE_IMMED) { z80_save_reg(inst, opts); } @@ -1318,7 +1312,7 @@ } else { mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); } - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } break; @@ -1363,7 +1357,7 @@ jmp(code, call_dst); } else { mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } *no_jump_off = code->cur - (no_jump_off+1); @@ -1382,7 +1376,7 @@ jmp(code, call_dst); } else { mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } break; @@ -1417,7 +1411,7 @@ jmp(code, call_dst); } else { mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } *no_jump_off = code->cur - (no_jump_off+1); @@ -1440,7 +1434,7 @@ jmp(code, call_dst); } else { mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } *no_jump_off = code->cur - (no_jump_off+1); @@ -1450,7 +1444,7 @@ sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 + call(code, opts->write_16_highfirst);//T States: 3, 3 if (inst->immed < 0x4000) { code_ptr call_dst = z80_get_native_address(context, inst->immed); if (!call_dst) { @@ -1461,7 +1455,7 @@ jmp(code, call_dst); } else { mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } break; @@ -1498,7 +1492,7 @@ sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 + call(code, opts->write_16_highfirst);//T States: 3, 3 if (inst->immed < 0x4000) { code_ptr call_dst = z80_get_native_address(context, inst->immed); if (!call_dst) { @@ -1509,7 +1503,7 @@ jmp(code, call_dst); } else { mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); } *no_call_off = code->cur - (no_call_off+1); @@ -1517,9 +1511,9 @@ case Z80_RET: cycles(&opts->gen, 4);//T States: 4 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 + call(code, opts->read_16);//T STates: 3, 3 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); break; case Z80_RETCC: { @@ -1551,9 +1545,9 @@ uint8_t *no_call_off = code->cur+1; jcc(code, cond, code->cur+2); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 + call(code, opts->read_16);//T STates: 3, 3 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); *no_call_off = code->cur - (no_call_off+1); break; @@ -1562,9 +1556,9 @@ //For some systems, this may need a callback for signalling interrupt routine completion cycles(&opts->gen, 8);//T States: 4, 4 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); - call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 + call(code, opts->read_16);//T STates: 3, 3 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); break; case Z80_RETN: @@ -1572,9 +1566,9 @@ mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); - call(code, (uint8_t *)z80_read_word);//T STates: 3, 3 + call(code, opts->read_16);//T STates: 3, 3 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); - call(code, (uint8_t *)z80_native_addr); + call(code, opts->native_addr); jmp_r(code, opts->gen.scratch1); break; case Z80_RST: { @@ -1583,7 +1577,7 @@ sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); mov_ir(code, address + 1, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); - call(code, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 + call(code, opts->write_16_highfirst);//T States: 3, 3 code_ptr call_dst = z80_get_native_address(context, inst->immed); if (!call_dst) { opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1); @@ -1600,7 +1594,7 @@ } else { mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); } - call(code, (uint8_t *)z80_io_read); + call(code, opts->read_io); translate_z80_reg(inst, &dst_op, opts); mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); z80_save_reg(inst, opts); @@ -1618,7 +1612,7 @@ } translate_z80_reg(inst, &src_op, opts); mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B); - call(code, (uint8_t *)z80_io_write); + call(code, opts->write_io); z80_save_reg(inst, opts); break; /*case Z80_OUTI: @@ -1737,7 +1731,7 @@ z80_options * opts = context->options; dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code, inst_start, address); mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D); - call(&code, (uint8_t *)z80_retrans_stub); + call(&code, opts->retrans_stub); } return context; } @@ -1959,8 +1953,9 @@ int reg; uint8_t size; if (i < Z80_I) { - int reg = i /2 + Z80_BC; + reg = i /2 + Z80_BC; size = SZ_W; + i++; } else { reg = i; @@ -1977,6 +1972,7 @@ mov_rrdisp(code, options->gen.cycles, options->gen.context_reg, offsetof(z80_context, current_cycle), SZ_D); mov_rrdisp(code, options->bank_reg, options->gen.context_reg, offsetof(z80_context, bank_reg), SZ_W); mov_rrdisp(code, options->bank_pointer, options->gen.context_reg, offsetof(z80_context, mem_pointers) + sizeof(uint8_t *) * 1, SZ_PTR); + retn(code); options->load_context_scratch = code->cur; mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch1), options->gen.scratch1, SZ_W); @@ -2005,6 +2001,18 @@ mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, current_cycle), options->gen.cycles, SZ_D); mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, bank_reg), options->bank_reg, SZ_W); mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, mem_pointers) + sizeof(uint8_t *) * 1, options->bank_pointer, SZ_PTR); + retn(code); + + options->native_addr = code->cur; + call(code, options->gen.save_context); + push_r(code, options->gen.context_reg); + mov_rr(code, options->gen.context_reg, RDI, SZ_PTR); + movzx_rr(code, options->gen.scratch1, RSI, SZ_W, SZ_D); + call(code, (code_ptr)z80_get_native_address_trans); + mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); + pop_r(code, options->gen.context_reg); + call(code, options->gen.load_context); + retn(code); options->gen.handle_cycle_limit = code->cur; cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); @@ -2065,8 +2073,70 @@ pop_r(code, options->gen.scratch2); //TODO: Support interrupt mode 0 and 2 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); - call(code, (code_ptr)z80_native_addr); + call(code, options->native_addr); jmp_r(code, options->gen.scratch1); + *skip_int = code->cur - (skip_int+1); + cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D); + code_ptr skip_sync = code->cur + 1; + jcc(code, CC_B, skip_sync); + options->do_sync = code->cur; + call(code, options->gen.save_context); + pop_rind(code, options->gen.context_reg); + //restore callee saved registers + pop_r(code, R15); + pop_r(code, R14); + pop_r(code, R13); + pop_r(code, R12); + pop_r(code, RBP); + pop_r(code, RBX); + //return to caller of z80_run + *skip_sync = code->cur - (skip_sync+1); + retn(code); + + options->read_io = code->cur; + check_cycles(&options->gen); + cycles(&options->gen, 4); + //Genesis has no IO hardware and always returns FF + //eventually this should use a second memory map array + mov_ir(code, 0xFF, options->gen.scratch1, SZ_B); + retn(code); + + options->write_io = code->cur; + check_cycles(&options->gen); + cycles(&options->gen, 4); + retn(code); + + options->retrans_stub = code->cur; + //pop return address + pop_r(code, options->gen.scratch2); + call(code, options->gen.save_context); + //adjust pointer before move and call instructions that got us here + sub_ir(code, 11, options->gen.scratch2, SZ_PTR); + mov_rr(code, options->gen.scratch1, RDI, SZ_D); + mov_rr(code, options->gen.scratch2, RDX, SZ_PTR); + push_r(code, options->gen.context_reg); + call(code, (code_ptr)z80_retranslate_inst); + pop_r(code, options->gen.context_reg); + mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); + call(code, options->gen.load_context); + jmp_r(code, options->gen.scratch1); + + options->run = (z80_run_fun)code->cur; + //save callee save registers + push_r(code, RBX); + push_r(code, RBP); + push_r(code, R12); + push_r(code, R13); + push_r(code, R14); + push_r(code, R15); + mov_rr(code, RDI, options->gen.context_reg, SZ_PTR); + cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); + code_ptr no_extra = code->cur+1; + jcc(code, CC_Z, no_extra); + push_rdisp(code, options->gen.context_reg, offsetof(z80_context, extra_pc)); + mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR); + *no_extra = code->cur - (no_extra + 1); + jmp_rind(code, options->gen.context_reg); } void * z80_gen_bank_write(uint32_t start_address, void * voptions) @@ -2086,6 +2156,7 @@ context->banked_code_map = malloc(sizeof(native_map_slot) * (1 << 9)); memset(context->banked_code_map, 0, sizeof(native_map_slot) * (1 << 9)); context->options = options; + context->run = options->run; } void z80_reset(z80_context * context) @@ -2115,14 +2186,14 @@ code->cur = bp_stub; //Save context and call breakpoint handler - call(code, (uint8_t *)z80_save_context); + call(code, opts->gen.save_context); push_r(code, opts->gen.scratch1); mov_rr(code, opts->gen.context_reg, RDI, SZ_Q); mov_rr(code, opts->gen.scratch1, RSI, SZ_W); call(code, bp_handler); mov_rr(code, RAX, opts->gen.context_reg, SZ_Q); //Restore context - call(code, (uint8_t *)z80_load_context); + call(code, opts->gen.load_context); pop_r(code, opts->gen.scratch1); //do prologue stuff cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D); @@ -2131,7 +2202,7 @@ pop_r(code, opts->gen.scratch1); add_ir(code, check_int_size - (code->cur-native), opts->gen.scratch1, SZ_Q); push_r(code, opts->gen.scratch1); - jmp(code, (uint8_t *)z80_handle_cycle_limit_int); + jmp(code, opts->gen.handle_cycle_limit_int); *jmp_off = code->cur - (jmp_off+1); //jump back to body of translated instruction pop_r(code, opts->gen.scratch1);