summaryrefslogtreecommitdiff
path: root/z80_to_x86.c
diff options
context:
space:
mode:
Diffstat (limited to 'z80_to_x86.c')
-rw-r--r--z80_to_x86.c2131
1 files changed, 1192 insertions, 939 deletions
diff --git a/z80_to_x86.c b/z80_to_x86.c
index b529766..6da2321 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -28,23 +28,7 @@
#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 * zbreakpoint_patch(z80_context * context, uint16_t address, uint8_t * native);
+uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst);
uint8_t z80_size(z80inst * inst)
{
@@ -56,24 +40,9 @@ uint8_t z80_size(z80inst * inst)
return SZ_B;
}
-uint8_t * zcycles(uint8_t * dst, uint32_t num_cycles)
-{
- return add_ir(dst, num_cycles, ZCYCLES, SZ_D);
-}
-
-uint8_t * z80_check_cycles_int(uint8_t * dst, uint16_t address)
-{
- dst = cmp_rr(dst, ZCYCLES, ZLIMIT, SZ_D);
- uint8_t * jmp_off = dst+1;
- dst = jcc(dst, CC_NC, dst + 7);
- dst = mov_ir(dst, address, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_handle_cycle_limit_int);
- *jmp_off = dst - (jmp_off+1);
- return dst;
-}
-
-uint8_t * translate_z80_reg(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts)
+void translate_z80_reg(z80inst * inst, host_ea * ea, z80_options * opts)
{
+ code_info *code = &opts->gen.code;
if (inst->reg == Z80_USE_IMMED) {
ea->mode = MODE_IMMED;
ea->disp = inst->immed;
@@ -83,12 +52,12 @@ uint8_t * translate_z80_reg(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_
ea->mode = MODE_REG_DIRECT;
if (inst->reg == Z80_IYH) {
if ((inst->addr_mode & 0x1F) == Z80_REG && inst->ea_reg == Z80_IYL) {
- dst = mov_rr(dst, opts->regs[Z80_IY], SCRATCH1, SZ_W);
- dst = ror_ir(dst, 8, SCRATCH1, SZ_W);
- ea->base = SCRATCH1;
+ mov_rr(code, opts->regs[Z80_IY], opts->gen.scratch1, SZ_W);
+ ror_ir(code, 8, opts->gen.scratch1, SZ_W);
+ ea->base = opts->gen.scratch1;
} else {
ea->base = opts->regs[Z80_IYL];
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
}
} else if(opts->regs[inst->reg] >= 0) {
ea->base = opts->regs[inst->reg];
@@ -98,64 +67,64 @@ uint8_t * translate_z80_reg(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_
if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
//we can't mix an *H reg with a register that requires the REX prefix
ea->base = opts->regs[z80_low_reg(inst->reg)];
- dst = ror_ir(dst, 8, ea->base, SZ_W);
+ ror_ir(code, 8, ea->base, SZ_W);
}
} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
//temp regs require REX prefix too
ea->base = opts->regs[z80_low_reg(inst->reg)];
- dst = ror_ir(dst, 8, ea->base, SZ_W);
+ ror_ir(code, 8, ea->base, SZ_W);
}
}
} else {
ea->mode = MODE_REG_DISPLACE8;
- ea->base = CONTEXT;
+ ea->base = opts->gen.context_reg;
ea->disp = offsetof(z80_context, regs) + inst->reg;
}
}
- return dst;
}
-uint8_t * z80_save_reg(uint8_t * dst, z80inst * inst, x86_z80_options * opts)
+void z80_save_reg(z80inst * inst, z80_options * opts)
{
+ code_info *code = &opts->gen.code;
if (inst->reg == Z80_IYH) {
if ((inst->addr_mode & 0x1F) == Z80_REG && inst->ea_reg == Z80_IYL) {
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
- dst = mov_rr(dst, SCRATCH1, opts->regs[Z80_IYL], SZ_B);
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
+ mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
} else {
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
}
} else if (opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) {
if ((inst->addr_mode & 0x1F) == Z80_REG) {
uint8_t other_reg = opts->regs[inst->ea_reg];
if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
//we can't mix an *H reg with a register that requires the REX prefix
- dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
+ ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
}
} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
//temp regs require REX prefix too
- dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
+ ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
}
}
- return dst;
}
-uint8_t * translate_z80_ea(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_options * opts, uint8_t read, uint8_t modify)
+void translate_z80_ea(z80inst * inst, host_ea * ea, z80_options * opts, uint8_t read, uint8_t modify)
{
+ code_info *code = &opts->gen.code;
uint8_t size, reg, areg;
ea->mode = MODE_REG_DIRECT;
- areg = read ? SCRATCH1 : SCRATCH2;
+ areg = read ? opts->gen.scratch1 : opts->gen.scratch2;
switch(inst->addr_mode & 0x1F)
{
case Z80_REG:
if (inst->ea_reg == Z80_IYH) {
if (inst->reg == Z80_IYL) {
- dst = mov_rr(dst, opts->regs[Z80_IY], SCRATCH1, SZ_W);
- dst = ror_ir(dst, 8, SCRATCH1, SZ_W);
- ea->base = SCRATCH1;
+ mov_rr(code, opts->regs[Z80_IY], opts->gen.scratch1, SZ_W);
+ ror_ir(code, 8, opts->gen.scratch1, SZ_W);
+ ea->base = opts->gen.scratch1;
} else {
ea->base = opts->regs[Z80_IYL];
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
}
} else if(opts->regs[inst->ea_reg] >= 0) {
ea->base = opts->regs[inst->ea_reg];
@@ -164,7 +133,7 @@ uint8_t * translate_z80_ea(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_o
if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
//we can't mix an *H reg with a register that requires the REX prefix
ea->base = opts->regs[z80_low_reg(inst->ea_reg)];
- dst = ror_ir(dst, 8, ea->base, SZ_W);
+ ror_ir(code, 8, ea->base, SZ_W);
}
}
} else {
@@ -174,70 +143,70 @@ uint8_t * translate_z80_ea(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_o
}
break;
case Z80_REG_INDIRECT:
- dst = mov_rr(dst, opts->regs[inst->ea_reg], areg, SZ_W);
+ mov_rr(code, opts->regs[inst->ea_reg], areg, SZ_W);
size = z80_size(inst);
if (read) {
if (modify) {
- //dst = push_r(dst, SCRATCH1);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(z80_context, scratch1), SZ_W);
+ //push_r(code, opts->gen.scratch1);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
}
if (size == SZ_B) {
- dst = call(dst, (uint8_t *)z80_read_byte);
+ call(code, opts->read_8);
} else {
- dst = call(dst, (uint8_t *)z80_read_word);
+ call(code, opts->read_16);
}
if (modify) {
- //dst = pop_r(dst, SCRATCH2);
- dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, scratch1), SCRATCH2, SZ_W);
+ //pop_r(code, opts->gen.scratch2);
+ mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
}
}
- ea->base = SCRATCH1;
+ ea->base = opts->gen.scratch1;
break;
case Z80_IMMED:
ea->mode = MODE_IMMED;
ea->disp = inst->immed;
break;
case Z80_IMMED_INDIRECT:
- dst = mov_ir(dst, inst->immed, areg, SZ_W);
+ mov_ir(code, inst->immed, areg, SZ_W);
size = z80_size(inst);
if (read) {
/*if (modify) {
- dst = push_r(dst, SCRATCH1);
+ push_r(code, opts->gen.scratch1);
}*/
if (size == SZ_B) {
- dst = call(dst, (uint8_t *)z80_read_byte);
+ call(code, opts->read_8);
} else {
- dst = call(dst, (uint8_t *)z80_read_word);
+ call(code, opts->read_16);
}
if (modify) {
- //dst = pop_r(dst, SCRATCH2);
- dst = mov_ir(dst, inst->immed, SCRATCH2, SZ_W);
+ //pop_r(code, opts->gen.scratch2);
+ mov_ir(code, inst->immed, opts->gen.scratch2, SZ_W);
}
}
- ea->base = SCRATCH1;
+ ea->base = opts->gen.scratch1;
break;
case Z80_IX_DISPLACE:
case Z80_IY_DISPLACE:
reg = opts->regs[(inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY];
- dst = mov_rr(dst, reg, areg, SZ_W);
- dst = add_ir(dst, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, areg, SZ_W);
+ mov_rr(code, reg, areg, SZ_W);
+ add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, areg, SZ_W);
size = z80_size(inst);
if (read) {
if (modify) {
- //dst = push_r(dst, SCRATCH1);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, offsetof(z80_context, scratch1), SZ_W);
+ //push_r(code, opts->gen.scratch1);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
}
if (size == SZ_B) {
- dst = call(dst, (uint8_t *)z80_read_byte);
+ call(code, opts->read_8);
} else {
- dst = call(dst, (uint8_t *)z80_read_word);
+ call(code, opts->read_16);
}
if (modify) {
- //dst = pop_r(dst, SCRATCH2);
- dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, scratch1), SCRATCH2, SZ_W);
+ //pop_r(code, opts->gen.scratch2);
+ mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
}
}
- ea->base = SCRATCH1;
+ ea->base = opts->gen.scratch1;
break;
case Z80_UNUSED:
ea->mode = MODE_UNUSED;
@@ -246,32 +215,30 @@ uint8_t * translate_z80_ea(z80inst * inst, x86_ea * ea, uint8_t * dst, x86_z80_o
fprintf(stderr, "Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F);
exit(1);
}
- return dst;
}
-uint8_t * z80_save_ea(uint8_t * dst, z80inst * inst, x86_z80_options * opts)
+void z80_save_ea(code_info *code, z80inst * inst, z80_options * opts)
{
if ((inst->addr_mode & 0x1F) == Z80_REG) {
if (inst->ea_reg == Z80_IYH) {
if (inst->reg == Z80_IYL) {
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
- dst = mov_rr(dst, SCRATCH1, opts->regs[Z80_IYL], SZ_B);
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
+ mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
} else {
- dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W);
+ ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
}
} else if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
uint8_t other_reg = opts->regs[inst->reg];
if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
//we can't mix an *H reg with a register that requires the REX prefix
- dst = ror_ir(dst, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W);
+ ror_ir(code, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W);
}
}
}
- return dst;
}
-uint8_t * z80_save_result(uint8_t * dst, z80inst * inst)
+void z80_save_result(z80_options *opts, z80inst * inst)
{
switch(inst->addr_mode & 0x1f)
{
@@ -280,12 +247,11 @@ uint8_t * z80_save_result(uint8_t * dst, z80inst * inst)
case Z80_IX_DISPLACE:
case Z80_IY_DISPLACE:
if (z80_size(inst) == SZ_B) {
- dst = call(dst, (uint8_t *)z80_write_byte);
+ call(&opts->gen.code, opts->write_8);
} else {
- dst = call(dst, (uint8_t *)z80_write_word_lowfirst);
+ call(&opts->gen.code, opts->write_16_lowfirst);
}
}
- return dst;
}
enum {
@@ -332,15 +298,16 @@ void z80_print_regs_exit(z80_context * context)
exit(0);
}
-uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address, uint8_t interp)
+void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address, uint8_t interp)
{
- uint32_t cycles;
- x86_ea src_op, dst_op;
+ uint32_t num_cycles;
+ host_ea src_op, dst_op;
uint8_t size;
- x86_z80_options *opts = context->options;
- uint8_t * start = dst;
+ z80_options *opts = context->options;
+ uint8_t * start = opts->gen.code.cur;
+ code_info *code = &opts->gen.code;
if (!interp) {
- dst = z80_check_cycles_int(dst, address);
+ check_cycles_int(&opts->gen, address);
if (context->breakpoint_flags[address / sizeof(uint8_t)] & (1 << (address % sizeof(uint8_t)))) {
zbreakpoint_patch(context, address, start);
}
@@ -353,253 +320,253 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
{
case Z80_REG:
case Z80_REG_INDIRECT:
- cycles = size == SZ_B ? 4 : 6;
+ num_cycles = size == SZ_B ? 4 : 6;
if (inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) {
- cycles += 4;
+ num_cycles += 4;
}
if (inst->reg == Z80_I || inst->ea_reg == Z80_I) {
- cycles += 5;
+ num_cycles += 5;
}
break;
case Z80_IMMED:
- cycles = size == SZ_B ? 7 : 10;
+ num_cycles = size == SZ_B ? 7 : 10;
break;
case Z80_IMMED_INDIRECT:
- cycles = 10;
+ num_cycles = 10;
break;
case Z80_IX_DISPLACE:
case Z80_IY_DISPLACE:
- cycles = 16;
+ num_cycles = 16;
break;
}
if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode & Z80_DIR) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, DONT_READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts);
+ translate_z80_ea(inst, &dst_op, opts, DONT_READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts);
} else {
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
+ translate_z80_reg(inst, &dst_op, opts);
}
if (src_op.mode == MODE_REG_DIRECT) {
if(dst_op.mode == MODE_REG_DISPLACE8) {
- dst = mov_rrdisp8(dst, src_op.base, dst_op.base, dst_op.disp, size);
+ mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
} else {
- dst = mov_rr(dst, src_op.base, dst_op.base, size);
+ mov_rr(code, src_op.base, dst_op.base, size);
}
} else if(src_op.mode == MODE_IMMED) {
- dst = mov_ir(dst, src_op.disp, dst_op.base, size);
+ mov_ir(code, src_op.disp, dst_op.base, size);
} else {
- dst = mov_rdisp8r(dst, src_op.base, src_op.disp, dst_op.base, size);
+ mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
}
if (inst->ea_reg == Z80_I && inst->addr_mode == Z80_REG) {
//ld a, i sets some flags
//TODO: Implement half-carry flag
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);;
- dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, iff2), SCRATCH1, SZ_B);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zf_off(ZF_PV), SZ_B);
- }
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ cmp_ir(code, 0, dst_op.base, SZ_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));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);;
+ mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), SCRATCH1, SZ_B);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
+ }
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
if (inst->addr_mode & Z80_DIR) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
}
break;
case Z80_PUSH:
- dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5);
- dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
+ cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5);
+ sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
if (inst->reg == Z80_AF) {
- dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH1, SZ_B);
- dst = shl_ir(dst, 8, SCRATCH1, SZ_W);
- dst = mov_rdisp8r(dst, CONTEXT, zf_off(ZF_S), SCRATCH1, SZ_B);
- dst = shl_ir(dst, 1, SCRATCH1, SZ_B);
- dst = or_rdisp8r(dst, CONTEXT, zf_off(ZF_Z), SCRATCH1, SZ_B);
- dst = shl_ir(dst, 2, SCRATCH1, SZ_B);
- dst = or_rdisp8r(dst, CONTEXT, zf_off(ZF_H), SCRATCH1, SZ_B);
- dst = shl_ir(dst, 2, SCRATCH1, SZ_B);
- dst = or_rdisp8r(dst, CONTEXT, zf_off(ZF_PV), SCRATCH1, SZ_B);
- dst = shl_ir(dst, 1, SCRATCH1, SZ_B);
- dst = or_rdisp8r(dst, CONTEXT, zf_off(ZF_N), SCRATCH1, SZ_B);
- dst = shl_ir(dst, 1, SCRATCH1, SZ_B);
- dst = or_rdisp8r(dst, CONTEXT, zf_off(ZF_C), SCRATCH1, SZ_B);
+ mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
+ shl_ir(code, 8, opts->gen.scratch1, SZ_W);
+ mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B);
+ shl_ir(code, 1, opts->gen.scratch1, SZ_B);
+ or_rdispr(code, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B);
+ shl_ir(code, 2, opts->gen.scratch1, SZ_B);
+ or_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B);
+ shl_ir(code, 2, opts->gen.scratch1, SZ_B);
+ or_rdispr(code, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B);
+ shl_ir(code, 1, opts->gen.scratch1, SZ_B);
+ or_rdispr(code, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B);
+ shl_ir(code, 1, opts->gen.scratch1, SZ_B);
+ or_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B);
} else {
- dst = translate_z80_reg(inst, &src_op, dst, opts);
- dst = mov_rr(dst, src_op.base, SCRATCH1, SZ_W);
+ translate_z80_reg(inst, &src_op, opts);
+ mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W);
}
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_word_highfirst);
+ mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
+ 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:
- dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_word);
- dst = add_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
+ 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, opts->read_16);
+ add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
if (inst->reg == Z80_AF) {
- dst = bt_ir(dst, 0, SCRATCH1, SZ_W);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = bt_ir(dst, 1, SCRATCH1, SZ_W);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_N));
- dst = bt_ir(dst, 2, SCRATCH1, SZ_W);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_PV));
- dst = bt_ir(dst, 4, SCRATCH1, SZ_W);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_H));
- dst = bt_ir(dst, 6, SCRATCH1, SZ_W);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_Z));
- dst = bt_ir(dst, 7, SCRATCH1, SZ_W);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_S));
- dst = shr_ir(dst, 8, SCRATCH1, SZ_W);
- dst = mov_rr(dst, SCRATCH1, opts->regs[Z80_A], SZ_B);
+ bt_ir(code, 0, opts->gen.scratch1, SZ_W);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ bt_ir(code, 1, opts->gen.scratch1, SZ_W);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
+ bt_ir(code, 2, opts->gen.scratch1, SZ_W);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_PV));
+ bt_ir(code, 4, opts->gen.scratch1, SZ_W);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
+ bt_ir(code, 6, opts->gen.scratch1, SZ_W);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_Z));
+ bt_ir(code, 7, opts->gen.scratch1, SZ_W);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_S));
+ shr_ir(code, 8, opts->gen.scratch1, SZ_W);
+ mov_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
} else {
- dst = translate_z80_reg(inst, &src_op, dst, opts);
- dst = mov_rr(dst, SCRATCH1, src_op.base, SZ_W);
+ translate_z80_reg(inst, &src_op, opts);
+ mov_rr(code, opts->gen.scratch1, src_op.base, SZ_W);
}
//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_EX:
if (inst->addr_mode == Z80_REG || inst->reg == Z80_HL) {
- cycles = 4;
+ num_cycles = 4;
} else {
- cycles = 8;
+ num_cycles = 8;
}
- dst = zcycles(dst, cycles);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode == Z80_REG) {
if(inst->reg == Z80_AF) {
- dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH1, SZ_B);
- dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_A), opts->regs[Z80_A], SZ_B);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_A), SZ_B);
+ mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
+ mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_A), opts->regs[Z80_A], SZ_B);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_A), SZ_B);
//Flags are currently word aligned, so we can move
//them efficiently a word at a time
for (int f = ZF_C; f < ZF_NUM; f+=2) {
- dst = mov_rdisp8r(dst, CONTEXT, zf_off(f), SCRATCH1, SZ_W);
- dst = mov_rdisp8r(dst, CONTEXT, zaf_off(f), SCRATCH2, SZ_W);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zaf_off(f), SZ_W);
- dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, zf_off(f), SZ_W);
+ mov_rdispr(code, opts->gen.context_reg, zf_off(f), opts->gen.scratch1, SZ_W);
+ mov_rdispr(code, opts->gen.context_reg, zaf_off(f), opts->gen.scratch2, SZ_W);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zaf_off(f), SZ_W);
+ mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(f), SZ_W);
}
} else {
- dst = xchg_rr(dst, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W);
+ xchg_rr(code, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W);
}
} else {
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
- dst = xchg_rr(dst, opts->regs[inst->reg], SCRATCH1, SZ_B);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
- dst = zcycles(dst, 1);
+ mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
+ 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, opts->write_8);
+ cycles(&opts->gen, 1);
uint8_t high_reg = z80_high_reg(inst->reg);
uint8_t use_reg;
//even though some of the upper halves can be used directly
//the limitations on mixing *H regs with the REX prefix
//prevent us from taking advantage of it
use_reg = opts->regs[inst->reg];
- dst = ror_ir(dst, 8, use_reg, SZ_W);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W);
- dst = add_ir(dst, 1, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
- dst = xchg_rr(dst, use_reg, SCRATCH1, SZ_B);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W);
- dst = add_ir(dst, 1, SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
+ 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, 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, opts->write_8);
//restore reg to normal rotation
- dst = ror_ir(dst, 8, use_reg, SZ_W);
- dst = zcycles(dst, 2);
+ ror_ir(code, 8, use_reg, SZ_W);
+ cycles(&opts->gen, 2);
}
break;
case Z80_EXX:
- dst = zcycles(dst, 4);
- dst = mov_rr(dst, opts->regs[Z80_BC], SCRATCH1, SZ_W);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W);
- dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_C), opts->regs[Z80_BC], SZ_W);
- dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_L), opts->regs[Z80_HL], SZ_W);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_C), SZ_W);
- dst = mov_rrdisp8(dst, SCRATCH2, CONTEXT, zar_off(Z80_L), SZ_W);
- dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH1, SZ_W);
- dst = mov_rdisp8r(dst, CONTEXT, zar_off(Z80_E), opts->regs[Z80_DE], SZ_W);
- dst = mov_rrdisp8(dst, SCRATCH1, CONTEXT, zar_off(Z80_E), SZ_W);
+ cycles(&opts->gen, 4);
+ mov_rr(code, opts->regs[Z80_BC], opts->gen.scratch1, SZ_W);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
+ mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_C), opts->regs[Z80_BC], SZ_W);
+ mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_L), opts->regs[Z80_HL], SZ_W);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_C), SZ_W);
+ mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zar_off(Z80_L), SZ_W);
+ mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch1, SZ_W);
+ mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_E), opts->regs[Z80_DE], SZ_W);
+ mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_E), SZ_W);
break;
case Z80_LDI: {
- dst = zcycles(dst, 8);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
- dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
- dst = zcycles(dst, 2);
- dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W);
- dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W);
- dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W);
+ cycles(&opts->gen, 8);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
+ mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
+ 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);
+ sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
//TODO: Implement half-carry
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = setcc_rdisp8(dst, CC_NZ, CONTEXT, zf_off(ZF_PV));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
break;
}
case Z80_LDIR: {
- dst = zcycles(dst, 8);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
- dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
- dst = add_ir(dst, 1, opts->regs[Z80_DE], SZ_W);
- dst = add_ir(dst, 1, opts->regs[Z80_HL], SZ_W);
-
- dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W);
- uint8_t * cont = dst+1;
- dst = jcc(dst, CC_Z, dst+2);
- dst = zcycles(dst, 7);
+ cycles(&opts->gen, 8);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
+ mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
+ 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);
+
+ sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
+ uint8_t * cont = code->cur+1;
+ jcc(code, CC_Z, code->cur+2);
+ cycles(&opts->gen, 7);
//TODO: Figure out what the flag state should be here
//TODO: Figure out whether an interrupt can interrupt this
- dst = jmp(dst, start);
- *cont = dst - (cont + 1);
- dst = zcycles(dst, 2);
+ jmp(code, start);
+ *cont = code->cur - (cont + 1);
+ cycles(&opts->gen, 2);
//TODO: Implement half-carry
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_PV), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
break;
}
case Z80_LDD: {
- dst = zcycles(dst, 8);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
- dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
- dst = zcycles(dst, 2);
- dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W);
- dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W);
- dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W);
+ cycles(&opts->gen, 8);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
+ mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
+ 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);
+ sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
//TODO: Implement half-carry
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = setcc_rdisp8(dst, CC_NZ, CONTEXT, zf_off(ZF_PV));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
break;
}
case Z80_LDDR: {
- dst = zcycles(dst, 8);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
- dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
- dst = sub_ir(dst, 1, opts->regs[Z80_DE], SZ_W);
- dst = sub_ir(dst, 1, opts->regs[Z80_HL], SZ_W);
-
- dst = sub_ir(dst, 1, opts->regs[Z80_BC], SZ_W);
- uint8_t * cont = dst+1;
- dst = jcc(dst, CC_Z, dst+2);
- dst = zcycles(dst, 7);
+ cycles(&opts->gen, 8);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
+ mov_rr(code, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W);
+ 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);
+
+ sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
+ uint8_t * cont = code->cur+1;
+ jcc(code, CC_Z, code->cur+2);
+ cycles(&opts->gen, 7);
//TODO: Figure out what the flag state should be here
//TODO: Figure out whether an interrupt can interrupt this
- dst = jmp(dst, start);
- *cont = dst - (cont + 1);
- dst = zcycles(dst, 2);
+ jmp(code, start);
+ *cont = code->cur - (cont + 1);
+ cycles(&opts->gen, 2);
//TODO: Implement half-carry
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_PV), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
break;
}
/*case Z80_CPI:
@@ -608,634 +575,644 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
case Z80_CPDR:
break;*/
case Z80_ADD:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
} else if(z80_size(inst) == SZ_W) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = add_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ add_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = add_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ add_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (z80_size(inst) == SZ_B) {
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
}
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_ADC:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
} else if(z80_size(inst) == SZ_W) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
- dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
+ bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = adc_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ adc_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = adc_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ adc_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_SUB:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = sub_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ sub_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = sub_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ sub_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ 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));
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_SBC:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
} else if(z80_size(inst) == SZ_W) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
- dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
+ bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = sbb_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ sbb_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = sbb_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ sbb_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_AND:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
} else if(z80_size(inst) == SZ_W) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = and_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ and_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = and_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ and_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
//TODO: Cleanup flags
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (z80_size(inst) == SZ_B) {
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
}
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_OR:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
} else if(z80_size(inst) == SZ_W) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = or_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ or_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = or_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ or_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
//TODO: Cleanup flags
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (z80_size(inst) == SZ_B) {
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
}
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_XOR:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
} else if(z80_size(inst) == SZ_W) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = xor_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ xor_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = xor_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ xor_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
//TODO: Cleanup flags
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (z80_size(inst) == SZ_B) {
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
}
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_CP:
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 12;
+ num_cycles += 12;
} else if(inst->addr_mode == Z80_IMMED) {
- cycles += 3;
+ num_cycles += 3;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
+ translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
if (src_op.mode == MODE_REG_DIRECT) {
- dst = cmp_rr(dst, src_op.base, dst_op.base, z80_size(inst));
+ cmp_rr(code, src_op.base, dst_op.base, z80_size(inst));
} else {
- dst = cmp_ir(dst, src_op.disp, dst_op.base, z80_size(inst));
+ cmp_ir(code, src_op.disp, dst_op.base, z80_size(inst));
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
+ 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));
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
break;
case Z80_INC:
- cycles = 4;
+ num_cycles = 4;
if (inst->reg == Z80_IX || inst->reg == Z80_IY) {
- cycles += 6;
+ num_cycles += 6;
} else if(z80_size(inst) == SZ_W) {
- cycles += 2;
+ num_cycles += 2;
} else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
if (dst_op.mode == MODE_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
}
- dst = add_ir(dst, 1, dst_op.base, z80_size(inst));
+ add_ir(code, 1, dst_op.base, z80_size(inst));
if (z80_size(inst) == SZ_B) {
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
}
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
- dst = z80_save_result(dst, inst);
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
+ z80_save_result(opts, inst);
break;
case Z80_DEC:
- cycles = 4;
+ num_cycles = 4;
if (inst->reg == Z80_IX || inst->reg == Z80_IY) {
- cycles += 6;
+ num_cycles += 6;
} else if(z80_size(inst) == SZ_W) {
- cycles += 2;
+ num_cycles += 2;
} else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ cycles(&opts->gen, num_cycles);
+ translate_z80_reg(inst, &dst_op, opts);
if (dst_op.mode == MODE_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
}
- dst = sub_ir(dst, 1, dst_op.base, z80_size(inst));
+ sub_ir(code, 1, dst_op.base, z80_size(inst));
if (z80_size(inst) == SZ_B) {
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_B);
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
}
- dst = z80_save_reg(dst, inst, opts);
- dst = z80_save_ea(dst, inst, opts);
- dst = z80_save_result(dst, inst);
+ z80_save_reg(inst, opts);
+ z80_save_ea(code, inst, opts);
+ z80_save_result(opts, inst);
break;
//case Z80_DAA:
case Z80_CPL:
- dst = zcycles(dst, 4);
- dst = not_r(dst, opts->regs[Z80_A], SZ_B);
+ cycles(&opts->gen, 4);
+ not_r(code, opts->regs[Z80_A], SZ_B);
//TODO: Implement half-carry flag
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_B);
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
break;
case Z80_NEG:
- dst = zcycles(dst, 8);
- dst = neg_r(dst, opts->regs[Z80_A], SZ_B);
+ cycles(&opts->gen, 8);
+ neg_r(code, opts->regs[Z80_A], SZ_B);
//TODO: Implement half-carry flag
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = setcc_rdisp8(dst, CC_O, CONTEXT, zf_off(ZF_PV));
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_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));
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
break;
case Z80_CCF:
- dst = zcycles(dst, 4);
- dst = xor_irdisp8(dst, 1, CONTEXT, zf_off(ZF_C), SZ_B);
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ cycles(&opts->gen, 4);
+ xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
break;
case Z80_SCF:
- dst = zcycles(dst, 4);
- dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_C), SZ_B);
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ cycles(&opts->gen, 4);
+ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
break;
case Z80_NOP:
if (inst->immed == 42) {
- dst = call(dst, (uint8_t *)z80_save_context);
- dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
- dst = jmp(dst, (uint8_t *)z80_print_regs_exit);
+ 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 {
- dst = zcycles(dst, 4 * inst->immed);
+ cycles(&opts->gen, 4 * inst->immed);
}
break;
- case Z80_HALT:
- dst = zcycles(dst, 4);
- dst = mov_ir(dst, address, SCRATCH1, SZ_W);
- uint8_t * call_inst = dst;
- dst = call(dst, (uint8_t *)z80_halt);
- dst = jmp(dst, call_inst);
+ case Z80_HALT: {
+ cycles(&opts->gen, 4);
+ mov_ir(code, address, opts->gen.scratch1, SZ_W);
+ uint8_t * call_inst = code->cur;
+ 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_NB, code->cur+2);
+ 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:
- dst = zcycles(dst, 4);
- dst = mov_irdisp8(dst, 0, CONTEXT, offsetof(z80_context, iff1), SZ_B);
- dst = mov_irdisp8(dst, 0, CONTEXT, offsetof(z80_context, iff2), SZ_B);
- dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, sync_cycle), ZLIMIT, SZ_D);
- dst = mov_irdisp8(dst, 0xFFFFFFFF, CONTEXT, offsetof(z80_context, int_cycle), SZ_D);
+ cycles(&opts->gen, 4);
+ mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
+ mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D);
+ mov_irdisp(code, 0xFFFFFFFF, opts->gen.context_reg, offsetof(z80_context, int_cycle), SZ_D);
break;
case Z80_EI:
- dst = zcycles(dst, 4);
- dst = mov_rrdisp32(dst, ZCYCLES, CONTEXT, offsetof(z80_context, int_enable_cycle), SZ_D);
- dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff1), SZ_B);
- dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff2), SZ_B);
+ cycles(&opts->gen, 4);
+ mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
+ mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
+ 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
- dst = add_irdisp32(dst, 4, CONTEXT, offsetof(z80_context, int_enable_cycle), SZ_D);
- dst = call(dst, (uint8_t *)z80_do_sync);
+ add_irdisp(code, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
+ call(code, opts->do_sync);
break;
case Z80_IM:
- dst = zcycles(dst, 4);
- dst = mov_irdisp8(dst, inst->immed, CONTEXT, offsetof(z80_context, im), SZ_B);
+ cycles(&opts->gen, 4);
+ mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B);
break;
case Z80_RLC:
- cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
- dst = zcycles(dst, cycles);
+ num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = rol_ir(dst, 1, dst_op.base, SZ_B);
+ rol_ir(code, 1, dst_op.base, SZ_B);
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (inst->immed) {
//rlca does not set these flags
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_RL:
- cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
- dst = zcycles(dst, cycles);
+ num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
- dst = rcl_ir(dst, 1, dst_op.base, SZ_B);
+ bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
+ rcl_ir(code, 1, dst_op.base, SZ_B);
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (inst->immed) {
//rla does not set these flags
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_RRC:
- cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
- dst = zcycles(dst, cycles);
+ num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = ror_ir(dst, 1, dst_op.base, SZ_B);
+ ror_ir(code, 1, dst_op.base, SZ_B);
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (inst->immed) {
//rrca does not set these flags
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_RR:
- cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
- dst = zcycles(dst, cycles);
+ num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
- dst = rcr_ir(dst, 1, dst_op.base, SZ_B);
+ bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
+ rcr_ir(code, 1, dst_op.base, SZ_B);
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
if (inst->immed) {
//rra does not set these flags
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_SLA:
case Z80_SLL:
- cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
- dst = zcycles(dst, cycles);
+ num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = shl_ir(dst, 1, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
+ shl_ir(code, 1, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
if (inst->op == Z80_SLL) {
- dst = or_ir(dst, 1, dst_op.base, SZ_B);
+ or_ir(code, 1, dst_op.base, SZ_B);
}
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_SRA:
- cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
- dst = zcycles(dst, cycles);
+ num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = sar_ir(dst, 1, dst_op.base, SZ_B);
+ sar_ir(code, 1, dst_op.base, SZ_B);
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_SRL:
- cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
- dst = zcycles(dst, cycles);
+ num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8;
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_UNUSED) {
- dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY);
- dst = translate_z80_reg(inst, &src_op, dst, opts); //For IX/IY variants that also write to a register
- dst = zcycles(dst, 1);
+ translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
+ translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
+ cycles(&opts->gen, 1);
} else {
src_op.mode = MODE_UNUSED;
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
- dst = shr_ir(dst, 1, dst_op.base, SZ_B);
+ shr_ir(code, 1, dst_op.base, SZ_B);
if (src_op.mode != MODE_UNUSED) {
- dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B);
+ mov_rr(code, dst_op.base, src_op.base, SZ_B);
}
- dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
//TODO: Implement half-carry flag
- dst = cmp_ir(dst, 0, dst_op.base, SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, dst_op.base, SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (src_op.mode != MODE_UNUSED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
} else {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
break;
case Z80_RLD:
- dst = zcycles(dst, 8);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
+ cycles(&opts->gen, 8);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
//Before: (HL) = 0x12, A = 0x34
//After: (HL) = 0x24, A = 0x31
- dst = mov_rr(dst, opts->regs[Z80_A], SCRATCH2, SZ_B);
- dst = shl_ir(dst, 4, SCRATCH1, SZ_W);
- dst = and_ir(dst, 0xF, SCRATCH2, SZ_W);
- dst = and_ir(dst, 0xFFF, SCRATCH1, SZ_W);
- dst = and_ir(dst, 0xF0, opts->regs[Z80_A], SZ_B);
- dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_W);
- //SCRATCH1 = 0x0124
- dst = ror_ir(dst, 8, SCRATCH1, SZ_W);
- dst = zcycles(dst, 4);
- dst = or_rr(dst, SCRATCH1, opts->regs[Z80_A], SZ_B);
+ mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
+ shl_ir(code, 4, opts->gen.scratch1, SZ_W);
+ and_ir(code, 0xF, opts->gen.scratch2, SZ_W);
+ and_ir(code, 0xFFF, opts->gen.scratch1, SZ_W);
+ and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
+ or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
+ //opts->gen.scratch1 = 0x0124
+ ror_ir(code, 8, opts->gen.scratch1, SZ_W);
+ cycles(&opts->gen, 4);
+ or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
//set flags
//TODO: Implement half-carry flag
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
-
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W);
- dst = ror_ir(dst, 8, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
+
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
+ ror_ir(code, 8, opts->gen.scratch1, SZ_W);
+ call(code, opts->write_8);
break;
case Z80_RRD:
- dst = zcycles(dst, 8);
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
+ cycles(&opts->gen, 8);
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
//Before: (HL) = 0x12, A = 0x34
//After: (HL) = 0x41, A = 0x32
- dst = movzx_rr(dst, opts->regs[Z80_A], SCRATCH2, SZ_B, SZ_W);
- dst = ror_ir(dst, 4, SCRATCH1, SZ_W);
- dst = shl_ir(dst, 4, SCRATCH2, SZ_W);
- dst = and_ir(dst, 0xF00F, SCRATCH1, SZ_W);
- dst = and_ir(dst, 0xF0, opts->regs[Z80_A], SZ_B);
- //SCRATCH1 = 0x2001
- //SCRATCH2 = 0x0040
- dst = or_rr(dst, SCRATCH2, SCRATCH1, SZ_W);
- //SCRATCH1 = 0x2041
- dst = ror_ir(dst, 8, SCRATCH1, SZ_W);
- dst = zcycles(dst, 4);
- dst = shr_ir(dst, 4, SCRATCH1, SZ_B);
- dst = or_rr(dst, SCRATCH1, opts->regs[Z80_A], SZ_B);
+ movzx_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W);
+ ror_ir(code, 4, opts->gen.scratch1, SZ_W);
+ shl_ir(code, 4, opts->gen.scratch2, SZ_W);
+ and_ir(code, 0xF00F, opts->gen.scratch1, SZ_W);
+ and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
+ //opts->gen.scratch1 = 0x2001
+ //opts->gen.scratch2 = 0x0040
+ or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
+ //opts->gen.scratch1 = 0x2041
+ ror_ir(code, 8, opts->gen.scratch1, SZ_W);
+ cycles(&opts->gen, 4);
+ shr_ir(code, 4, opts->gen.scratch1, SZ_B);
+ or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
//set flags
//TODO: Implement half-carry flag
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
- dst = setcc_rdisp8(dst, CC_P, CONTEXT, zf_off(ZF_PV));
- dst = setcc_rdisp8(dst, CC_Z, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
-
- dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W);
- dst = ror_ir(dst, 8, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_byte);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
+ setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
+ 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));
+
+ mov_rr(code, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W);
+ ror_ir(code, 8, opts->gen.scratch1, SZ_W);
+ call(code, opts->write_8);
break;
case Z80_BIT: {
- cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
- dst = zcycles(dst, cycles);
+ num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
+ cycles(&opts->gen, num_cycles);
uint8_t bit;
if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
@@ -1244,27 +1221,27 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
} else {
size = SZ_B;
bit = inst->immed;
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY);
+ translate_z80_ea(inst, &src_op, 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);
+ cycles(&opts->gen, 1);
}
- dst = bt_ir(dst, bit, src_op.base, size);
- dst = setcc_rdisp8(dst, CC_NC, CONTEXT, zf_off(ZF_Z));
- dst = setcc_rdisp8(dst, CC_NC, CONTEXT, zf_off(ZF_PV));
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B);
+ bt_ir(code, bit, src_op.base, size);
+ setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_Z));
+ setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_PV));
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
if (inst->immed == 7) {
- dst = cmp_ir(dst, 0, src_op.base, size);
- dst = setcc_rdisp8(dst, CC_S, CONTEXT, zf_off(ZF_S));
+ cmp_ir(code, 0, src_op.base, size);
+ setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
} else {
- dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_S), SZ_B);
+ mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
}
break;
}
case Z80_SET: {
- cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
- dst = zcycles(dst, cycles);
+ num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
+ cycles(&opts->gen, num_cycles);
uint8_t bit;
if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
@@ -1273,40 +1250,40 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
} else {
size = SZ_B;
bit = inst->immed;
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, MODIFY);
+ translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
}
if (inst->reg != Z80_USE_IMMED) {
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
if (inst->addr_mode != Z80_REG) {
//Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
- dst = zcycles(dst, 1);
+ cycles(&opts->gen, 1);
}
- dst = bts_ir(dst, bit, src_op.base, size);
+ bts_ir(code, bit, src_op.base, size);
if (inst->reg != Z80_USE_IMMED) {
if (size == SZ_W) {
if (dst_op.base >= R8) {
- dst = ror_ir(dst, 8, src_op.base, SZ_W);
- dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
- dst = ror_ir(dst, 8, src_op.base, SZ_W);
+ ror_ir(code, 8, src_op.base, SZ_W);
+ mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
+ ror_ir(code, 8, src_op.base, SZ_W);
} else {
- dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B);
+ mov_rr(code, opts->regs[inst->ea_reg], dst_op.base, SZ_B);
}
} else {
- dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B);
+ mov_rr(code, src_op.base, dst_op.base, SZ_B);
}
}
if ((inst->addr_mode & 0x1F) != Z80_REG) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (inst->reg != Z80_USE_IMMED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
}
break;
}
case Z80_RES: {
- cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
- dst = zcycles(dst, cycles);
+ num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16;
+ cycles(&opts->gen, num_cycles);
uint8_t bit;
if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
@@ -1315,361 +1292,361 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
} else {
size = SZ_B;
bit = inst->immed;
- dst = translate_z80_ea(inst, &src_op, dst, opts, READ, MODIFY);
+ translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
}
if (inst->reg != Z80_USE_IMMED) {
- dst = translate_z80_reg(inst, &dst_op, dst, opts);
+ translate_z80_reg(inst, &dst_op, opts);
}
if (inst->addr_mode != Z80_REG) {
//Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
- dst = zcycles(dst, 1);
+ cycles(&opts->gen, 1);
}
- dst = btr_ir(dst, bit, src_op.base, size);
+ btr_ir(code, bit, src_op.base, size);
if (inst->reg != Z80_USE_IMMED) {
if (size == SZ_W) {
if (dst_op.base >= R8) {
- dst = ror_ir(dst, 8, src_op.base, SZ_W);
- dst = mov_rr(dst, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
- dst = ror_ir(dst, 8, src_op.base, SZ_W);
+ ror_ir(code, 8, src_op.base, SZ_W);
+ mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
+ ror_ir(code, 8, src_op.base, SZ_W);
} else {
- dst = mov_rr(dst, opts->regs[inst->ea_reg], dst_op.base, SZ_B);
+ mov_rr(code, opts->regs[inst->ea_reg], dst_op.base, SZ_B);
}
} else {
- dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B);
+ mov_rr(code, src_op.base, dst_op.base, SZ_B);
}
}
if (inst->addr_mode != Z80_REG) {
- dst = z80_save_result(dst, inst);
+ z80_save_result(opts, inst);
if (inst->reg != Z80_USE_IMMED) {
- dst = z80_save_reg(dst, inst, opts);
+ z80_save_reg(inst, opts);
}
}
break;
}
case Z80_JP: {
- cycles = 4;
+ num_cycles = 4;
if (inst->addr_mode != Z80_REG_INDIRECT) {
- cycles += 6;
+ num_cycles += 6;
} else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) {
- cycles += 4;
+ num_cycles += 4;
}
- dst = zcycles(dst, cycles);
+ cycles(&opts->gen, num_cycles);
if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) {
- uint8_t * call_dst = z80_get_native_address(context, inst->immed);
+ code_ptr call_dst = z80_get_native_address(context, inst->immed);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, call_dst);
} else {
if (inst->addr_mode == Z80_REG_INDIRECT) {
- dst = mov_rr(dst, opts->regs[inst->ea_reg], SCRATCH1, SZ_W);
+ mov_rr(code, opts->regs[inst->ea_reg], opts->gen.scratch1, SZ_W);
} else {
- dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W);
+ mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
}
- dst = call(dst, (uint8_t *)z80_native_addr);
- dst = jmp_r(dst, SCRATCH1);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
break;
}
case Z80_JPCC: {
- dst = zcycles(dst, 7);//T States: 4,3
+ cycles(&opts->gen, 7);//T States: 4,3
uint8_t cond = CC_Z;
switch (inst->reg)
{
case Z80_CC_NZ:
cond = CC_NZ;
case Z80_CC_Z:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_Z), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
break;
case Z80_CC_NC:
cond = CC_NZ;
case Z80_CC_C:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
break;
case Z80_CC_PO:
cond = CC_NZ;
case Z80_CC_PE:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_PV), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
break;
case Z80_CC_P:
cond = CC_NZ;
case Z80_CC_M:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_S), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
break;
}
- uint8_t *no_jump_off = dst+1;
- dst = jcc(dst, cond, dst+2);
- dst = zcycles(dst, 5);//T States: 5
+ uint8_t *no_jump_off = code->cur+1;
+ jcc(code, cond, code->cur+2);
+ cycles(&opts->gen, 5);//T States: 5
uint16_t dest_addr = inst->immed;
if (dest_addr < 0x4000) {
- uint8_t * call_dst = z80_get_native_address(context, dest_addr);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, 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);
+ mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
- *no_jump_off = dst - (no_jump_off+1);
+ *no_jump_off = code->cur - (no_jump_off+1);
break;
}
case Z80_JR: {
- dst = zcycles(dst, 12);//T States: 4,3,5
+ cycles(&opts->gen, 12);//T States: 4,3,5
uint16_t dest_addr = address + inst->immed + 2;
if (dest_addr < 0x4000) {
- uint8_t * call_dst = z80_get_native_address(context, dest_addr);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, 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);
+ mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
break;
}
case Z80_JRCC: {
- dst = zcycles(dst, 7);//T States: 4,3
+ cycles(&opts->gen, 7);//T States: 4,3
uint8_t cond = CC_Z;
switch (inst->reg)
{
case Z80_CC_NZ:
cond = CC_NZ;
case Z80_CC_Z:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_Z), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
break;
case Z80_CC_NC:
cond = CC_NZ;
case Z80_CC_C:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
break;
}
- uint8_t *no_jump_off = dst+1;
- dst = jcc(dst, cond, dst+2);
- dst = zcycles(dst, 5);//T States: 5
+ uint8_t *no_jump_off = code->cur+1;
+ jcc(code, cond, code->cur+2);
+ cycles(&opts->gen, 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);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, 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);
+ mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
- *no_jump_off = dst - (no_jump_off+1);
+ *no_jump_off = code->cur - (no_jump_off+1);
break;
}
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
+ cycles(&opts->gen, 8);//T States: 5,3
+ sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
+ uint8_t *no_jump_off = code->cur+1;
+ jcc(code, CC_Z, code->cur+2);
+ cycles(&opts->gen, 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);
+ code_ptr call_dst = z80_get_native_address(context, dest_addr);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, dest_addr, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, 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);
+ mov_ir(code, dest_addr, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
- *no_jump_off = dst - (no_jump_off+1);
+ *no_jump_off = code->cur - (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);
- dst = mov_ir(dst, address + 3, SCRATCH1, SZ_W);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3
+ cycles(&opts->gen, 11);//T States: 4,3,4
+ 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, opts->write_16_highfirst);//T States: 3, 3
if (inst->immed < 0x4000) {
- uint8_t * call_dst = z80_get_native_address(context, inst->immed);
+ code_ptr call_dst = z80_get_native_address(context, inst->immed);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, call_dst);
} else {
- dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_native_addr);
- dst = jmp_r(dst, SCRATCH1);
+ mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
break;
}
case Z80_CALLCC:
- dst = zcycles(dst, 10);//T States: 4,3,3 (false case)
+ cycles(&opts->gen, 10);//T States: 4,3,3 (false case)
uint8_t cond = CC_Z;
switch (inst->reg)
{
case Z80_CC_NZ:
cond = CC_NZ;
case Z80_CC_Z:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_Z), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
break;
case Z80_CC_NC:
cond = CC_NZ;
case Z80_CC_C:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
break;
case Z80_CC_PO:
cond = CC_NZ;
case Z80_CC_PE:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_PV), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
break;
case Z80_CC_P:
cond = CC_NZ;
case Z80_CC_M:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_S), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
break;
}
- uint8_t *no_call_off = dst+1;
- dst = jcc(dst, cond, dst+2);
- dst = zcycles(dst, 1);//Last of the above T states takes an extra cycle in the true case
- dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
- dst = mov_ir(dst, address + 3, SCRATCH1, SZ_W);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3
+ uint8_t *no_call_off = code->cur+1;
+ jcc(code, cond, code->cur+2);
+ cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case
+ 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, opts->write_16_highfirst);//T States: 3, 3
if (inst->immed < 0x4000) {
- uint8_t * call_dst = z80_get_native_address(context, inst->immed);
+ code_ptr call_dst = z80_get_native_address(context, inst->immed);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, call_dst);
} else {
- dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_native_addr);
- dst = jmp_r(dst, SCRATCH1);
+ mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
- *no_call_off = dst - (no_call_off+1);
+ *no_call_off = code->cur - (no_call_off+1);
break;
case Z80_RET:
- dst = zcycles(dst, 4);//T States: 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);
+ cycles(&opts->gen, 4);//T States: 4
+ mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_16);//T STates: 3, 3
+ add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
break;
case Z80_RETCC: {
- dst = zcycles(dst, 5);//T States: 5
+ cycles(&opts->gen, 5);//T States: 5
uint8_t cond = CC_Z;
switch (inst->reg)
{
case Z80_CC_NZ:
cond = CC_NZ;
case Z80_CC_Z:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_Z), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
break;
case Z80_CC_NC:
cond = CC_NZ;
case Z80_CC_C:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
break;
case Z80_CC_PO:
cond = CC_NZ;
case Z80_CC_PE:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_PV), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
break;
case Z80_CC_P:
cond = CC_NZ;
case Z80_CC_M:
- dst = cmp_irdisp8(dst, 0, CONTEXT, zf_off(ZF_S), SZ_B);
+ cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
break;
}
- uint8_t *no_call_off = dst+1;
- dst = jcc(dst, cond, dst+2);
- 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);
- *no_call_off = dst - (no_call_off+1);
+ 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, opts->read_16);//T STates: 3, 3
+ add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
+ *no_call_off = code->cur - (no_call_off+1);
break;
}
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);
+ cycles(&opts->gen, 8);//T States: 4, 4
+ mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
+ call(code, opts->read_16);//T STates: 3, 3
+ add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.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);
+ cycles(&opts->gen, 8);//T States: 4, 4
+ 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, opts->read_16);//T STates: 3, 3
+ add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
break;
case Z80_RST: {
//RST is basically CALL to an address in page 0
- dst = zcycles(dst, 5);//T States: 5
- dst = sub_ir(dst, 2, opts->regs[Z80_SP], SZ_W);
- dst = mov_ir(dst, address + 1, SCRATCH1, SZ_W);
- dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W);
- dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3
- uint8_t * call_dst = z80_get_native_address(context, inst->immed);
+ cycles(&opts->gen, 5);//T States: 5
+ 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, opts->write_16_highfirst);//T States: 3, 3
+ code_ptr call_dst = z80_get_native_address(context, inst->immed);
if (!call_dst) {
- opts->deferred = defer_address(opts->deferred, inst->immed, dst + 1);
+ opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
//fake address to force large displacement
- call_dst = dst + 256;
+ call_dst = code->cur + 256;
}
- dst = jmp(dst, call_dst);
+ jmp(code, call_dst);
break;
}
case Z80_IN:
- dst = zcycles(dst, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4
+ cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4
if (inst->addr_mode == Z80_IMMED_INDIRECT) {
- dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_B);
+ mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B);
} else {
- dst = mov_rr(dst, opts->regs[Z80_C], SCRATCH1, SZ_B);
+ mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
}
- dst = call(dst, (uint8_t *)z80_io_read);
- translate_z80_reg(inst, &dst_op, dst, opts);
- dst = mov_rr(dst, SCRATCH1, dst_op.base, SZ_B);
- dst = z80_save_reg(dst, inst, opts);
+ 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);
break;
/*case Z80_INI:
case Z80_INIR:
case Z80_IND:
case Z80_INDR:*/
case Z80_OUT:
- dst = zcycles(dst, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4
+ cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4
if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) {
- dst = mov_ir(dst, inst->immed, SCRATCH2, SZ_B);
+ mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B);
} else {
- dst = mov_rr(dst, opts->regs[Z80_C], SCRATCH2, SZ_B);
+ mov_rr(code, opts->regs[Z80_C], opts->gen.scratch2, SZ_B);
}
- translate_z80_reg(inst, &src_op, dst, opts);
- dst = mov_rr(dst, dst_op.base, SCRATCH1, SZ_B);
- dst = call(dst, (uint8_t *)z80_io_write);
- dst = z80_save_reg(dst, inst, opts);
+ translate_z80_reg(inst, &src_op, opts);
+ mov_rr(code, dst_op.base, opts->gen.scratch1, SZ_B);
+ call(code, opts->write_io);
+ z80_save_reg(inst, opts);
break;
/*case Z80_OUTI:
case Z80_OTIR:
@@ -1685,7 +1662,6 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
exit(1);
}
}
- return dst;
}
uint8_t * z80_interp_handler(uint8_t opcode, z80_context * context)
@@ -1704,45 +1680,45 @@ uint8_t * z80_interp_handler(uint8_t opcode, z80_context * context)
fprintf(stderr, "Encountered multi-byte Z80 instruction at %X. Z80 interpeter doesn't support those yet.", context->pc);
exit(1);
}
- x86_z80_options * opts = context->options;
- if (opts->code_end - opts->cur_code < ZMAX_NATIVE_SIZE) {
- size_t size = 1024*1024;
- opts->cur_code = alloc_code(&size);
- opts->code_end = opts->cur_code + size;
- }
- context->interp_code[opcode] = opts->cur_code;
- opts->cur_code = translate_z80inst(&inst, opts->cur_code, context, 0, 1);
- opts->cur_code = mov_rdisp8r(opts->cur_code, CONTEXT, offsetof(z80_context, pc), SCRATCH1, SZ_W);
- opts->cur_code = add_ir(opts->cur_code, after - codebuf, SCRATCH1, SZ_W);
- opts->cur_code = call(opts->cur_code, (uint8_t *)z80_native_addr);
- opts->cur_code = jmp_r(opts->cur_code, SCRATCH1);
+
+ z80_options * opts = context->options;
+ code_info *code = &opts->gen.code;
+ check_alloc_code(code, ZMAX_NATIVE_SIZE);
+ context->interp_code[opcode] = code->cur;
+ translate_z80inst(&inst, context, 0, 1);
+ mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, pc), opts->gen.scratch1, SZ_W);
+ add_ir(code, after - codebuf, opts->gen.scratch1, SZ_W);
+ call(code, opts->native_addr);
+ jmp_r(code, opts->gen.scratch1);
}
return context->interp_code[opcode];
}
-uint8_t * z80_make_interp_stub(z80_context * context, uint16_t address)
+code_info z80_make_interp_stub(z80_context * context, uint16_t address)
{
- x86_z80_options *opts = context->options;
- uint8_t *dst = opts->cur_code;
+ z80_options *opts = context->options;
+ code_info * code = &opts->gen.code;
+ check_alloc_code(code, 32);
+ code_info stub = {code->cur, NULL};
//TODO: make this play well with the breakpoint code
- dst = mov_ir(dst, address, SCRATCH1, SZ_W);
- dst = call(dst, (uint8_t *)z80_read_byte);
+ mov_ir(code, address, opts->gen.scratch1, SZ_W);
+ call(code, opts->read_8);
//normal opcode fetch is already factored into instruction timing
//back out the base 3 cycles from a read here
//not quite perfect, but it will have to do for now
- dst = sub_ir(dst, 3, ZCYCLES, SZ_D);
- dst = z80_check_cycles_int(dst, address);
- dst = call(dst, (uint8_t *)z80_save_context);
- dst = mov_rr(dst, SCRATCH1, RDI, SZ_B);
- dst = mov_irdisp8(dst, address, CONTEXT, offsetof(z80_context, pc), SZ_W);
- dst = push_r(dst, CONTEXT);
- dst = call(dst, (uint8_t *)z80_interp_handler);
- dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q);
- dst = pop_r(dst, CONTEXT);
- dst = call(dst, (uint8_t *)z80_load_context);
- dst = jmp_r(dst, SCRATCH1);
- opts->code_end = dst;
- return dst;
+ cycles(&opts->gen, -3);
+ check_cycles_int(&opts->gen, address);
+ call(code, opts->gen.save_context);
+ mov_rr(code, opts->gen.scratch1, RDI, SZ_B);
+ mov_irdisp(code, address, opts->gen.context_reg, offsetof(z80_context, pc), SZ_W);
+ push_r(code, opts->gen.context_reg);
+ call(code, (code_ptr)z80_interp_handler);
+ mov_rr(code, RAX, opts->gen.scratch1, SZ_Q);
+ pop_r(code, opts->gen.context_reg);
+ call(code, opts->gen.load_context);
+ jmp_r(code, opts->gen.scratch1);
+ stub.last = code->cur;
+ return stub;
}
@@ -1764,24 +1740,24 @@ uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
return map->base + map->offsets[address];
}
-uint8_t z80_get_native_inst_size(x86_z80_options * opts, uint32_t address)
+uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address)
{
//TODO: Fix for addresses >= 0x4000
if (address >= 0x4000) {
return 0;
}
- return opts->ram_inst_sizes[address & 0x1FFF];
+ return opts->gen.ram_inst_sizes[0][address & 0x1FFF];
}
void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size)
{
uint32_t orig_address = address;
native_map_slot *map;
- x86_z80_options * opts = context->options;
+ z80_options * opts = context->options;
if (address < 0x4000) {
address &= 0x1FFF;
map = context->static_code_map;
- opts->ram_inst_sizes[address] = native_size;
+ opts->gen.ram_inst_sizes[0][address] = native_size;
context->ram_code_flags[(address & 0x1C00) >> 10] |= 1 << ((address & 0x380) >> 7);
context->ram_code_flags[((address + size) & 0x1C00) >> 10] |= 1 << (((address + size) & 0x380) >> 7);
} else {
@@ -1837,10 +1813,12 @@ z80_context * z80_handle_code_write(uint32_t address, z80_context * context)
{
uint32_t inst_start = z80_get_instruction_start(context->static_code_map, address);
if (inst_start != INVALID_INSTRUCTION_START) {
- uint8_t * dst = z80_get_native_address(context, inst_start);
- dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", dst, inst_start, address);
- dst = mov_ir(dst, inst_start, SCRATCH1, SZ_D);
- dst = call(dst, (uint8_t *)z80_retrans_stub);
+ code_ptr dst = z80_get_native_address(context, inst_start);
+ code_info code = {dst, dst+16};
+ 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, opts->retrans_stub);
}
return context;
}
@@ -1860,22 +1838,21 @@ uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address)
void z80_handle_deferred(z80_context * context)
{
- x86_z80_options * opts = context->options;
- process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address);
- if (opts->deferred) {
- translate_z80_stream(context, opts->deferred->address);
+ z80_options * opts = context->options;
+ process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
+ if (opts->gen.deferred) {
+ translate_z80_stream(context, opts->gen.deferred->address);
}
}
void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start)
{
char disbuf[80];
- x86_z80_options * opts = context->options;
+ z80_options * opts = context->options;
uint8_t orig_size = z80_get_native_inst_size(opts, address);
uint32_t orig = address;
address &= 0x1FFF;
- uint8_t * dst = opts->cur_code;
- uint8_t * dst_end = opts->code_end;
+ code_info *code = &opts->gen.code;
uint8_t *after, *inst = context->mem_pointers[0] + address;
z80inst instbuf;
dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
@@ -1889,19 +1866,15 @@ void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * o
}
#endif
if (orig_size != ZMAX_NATIVE_SIZE) {
- if (dst_end - dst < ZMAX_NATIVE_SIZE) {
- size_t size = 1024*1024;
- dst = alloc_code(&size);
- opts->code_end = dst_end = dst + size;
- opts->cur_code = dst;
- }
- deferred_addr * orig_deferred = opts->deferred;
- uint8_t * native_end = translate_z80inst(&instbuf, dst, context, address, 0);
+ check_alloc_code(code, ZMAX_NATIVE_SIZE);
+ code_ptr start = code->cur;
+ deferred_addr * orig_deferred = opts->gen.deferred;
+ translate_z80inst(&instbuf, context, address, 0);
/*
if ((native_end - dst) <= orig_size) {
uint8_t * native_next = z80_get_native_address(context, address + after-inst);
if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) {
- remove_deferred_until(&opts->deferred, orig_deferred);
+ remove_deferred_until(&opts->gen.deferred, orig_deferred);
native_end = translate_z80inst(&instbuf, orig_start, context, address, 0);
if (native_next == orig_start + orig_size && (native_next-native_end) < 2) {
while (native_end < orig_start + orig_size) {
@@ -1913,20 +1886,27 @@ void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * o
z80_handle_deferred(context);
return orig_start;
}
- }
- */
- z80_map_native_address(context, address, dst, after-inst, ZMAX_NATIVE_SIZE);
- opts->cur_code = dst+ZMAX_NATIVE_SIZE;
- jmp(orig_start, dst);
+ }*/
+ z80_map_native_address(context, address, start, after-inst, ZMAX_NATIVE_SIZE);
+ code_info tmp_code = {orig_start, orig_start + 16};
+ jmp(&tmp_code, start);
+ tmp_code = *code;
+ code->cur = start + ZMAX_NATIVE_SIZE;
if (!z80_is_terminal(&instbuf)) {
- jmp(native_end, z80_get_native_address_trans(context, address + after-inst));
+ jmp(&tmp_code, z80_get_native_address_trans(context, address + after-inst));
}
z80_handle_deferred(context);
- return dst;
+ return start;
} else {
- dst = translate_z80inst(&instbuf, orig_start, context, address, 0);
+ code_info tmp_code = *code;
+ code->cur = orig_start;
+ code->last = orig_start + ZMAX_NATIVE_SIZE;
+ translate_z80inst(&instbuf, context, address, 0);
+ code_info tmp2 = *code;
+ *code = tmp_code;
if (!z80_is_terminal(&instbuf)) {
- dst = jmp(dst, z80_get_native_address_trans(context, address + after-inst));
+
+ jmp(&tmp2, z80_get_native_address_trans(context, address + after-inst));
}
z80_handle_deferred(context);
return orig_start;
@@ -1939,7 +1919,7 @@ void translate_z80_stream(z80_context * context, uint32_t address)
if (z80_get_native_address(context, address)) {
return;
}
- x86_z80_options * opts = context->options;
+ z80_options * opts = context->options;
uint32_t start_address = address;
uint8_t * encoded = NULL, *next;
if (address < 0x4000) {
@@ -1951,27 +1931,18 @@ void translate_z80_stream(z80_context * context, uint32_t address)
z80inst inst;
dprintf("translating Z80 code at address %X\n", address);
do {
- if (opts->code_end-opts->cur_code < ZMAX_NATIVE_SIZE) {
- if (opts->code_end-opts->cur_code < 5) {
- puts("out of code memory, not enough space for jmp to next chunk");
- exit(1);
- }
- size_t size = 1024*1024;
- opts->cur_code = alloc_code(&size);
- opts->code_end = opts->cur_code + size;
- jmp(opts->cur_code, opts->cur_code);
- }
if (address >= 0x4000) {
- uint8_t *native_start = opts->cur_code;
- uint8_t *after = z80_make_interp_stub(context, address);
- z80_map_native_address(context, address, opts->cur_code, 1, after - native_start);
+ code_info stub = z80_make_interp_stub(context, address);
+ z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
break;
}
uint8_t * existing = z80_get_native_address(context, address);
if (existing) {
- opts->cur_code = jmp(opts->cur_code, existing);
+ jmp(&opts->gen.code, existing);
break;
}
+ //make sure prologue is in a contiguous chunk of code
+ check_code_prologue(&opts->gen.code);
next = z80_decode(encoded, &inst);
#ifdef DO_DEBUG_PRINT
z80_disasm(&inst, disbuf, address);
@@ -1981,9 +1952,9 @@ void translate_z80_stream(z80_context * context, uint32_t address)
printf("%X\t%s\n", address, disbuf);
}
#endif
- uint8_t *after = translate_z80inst(&inst, opts->cur_code, context, address, 0);
- z80_map_native_address(context, address, opts->cur_code, next-encoded, after - opts->cur_code);
- opts->cur_code = after;
+ code_ptr start = opts->gen.code.cur;
+ translate_z80inst(&inst, context, address, 0);
+ z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start);
address += next-encoded;
if (address > 0xFFFF) {
address &= 0xFFFF;
@@ -1992,9 +1963,9 @@ void translate_z80_stream(z80_context * context, uint32_t address)
encoded = next;
}
} while (!z80_is_terminal(&inst));
- process_deferred(&opts->deferred, context, (native_addr_func)z80_get_native_address);
- if (opts->deferred) {
- address = opts->deferred->address;
+ process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
+ if (opts->gen.deferred) {
+ address = opts->gen.deferred->address;
dprintf("defferred address: %X\n", address);
if (address < 0x4000) {
encoded = context->mem_pointers[0] + (address & 0x1FFF);
@@ -2008,8 +1979,18 @@ void translate_z80_stream(z80_context * context, uint32_t address)
}
}
-void init_x86_z80_opts(x86_z80_options * options)
+void init_x86_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks)
{
+ memset(options, 0, sizeof(*options));
+
+ options->gen.address_size = SZ_W;
+ options->gen.address_mask = 0xFFFF;
+ options->gen.max_address = 0x10000;
+ options->gen.bus_cycles = 3;
+ options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers);
+ options->gen.ram_flags_off = offsetof(z80_context, ram_code_flags);
+ options->gen.ram_flags_shift = 7;
+
options->flags = 0;
options->regs[Z80_B] = BH;
options->regs[Z80_C] = RBX;
@@ -2031,15 +2012,285 @@ void init_x86_z80_opts(x86_z80_options * options)
options->regs[Z80_AF] = -1;
options->regs[Z80_IX] = RDX;
options->regs[Z80_IY] = R8;
- size_t size = 1024 * 1024;
- options->cur_code = alloc_code(&size);
- options->code_end = options->cur_code + size;
- options->ram_inst_sizes = malloc(sizeof(uint8_t) * 0x2000);
- memset(options->ram_inst_sizes, 0, sizeof(uint8_t) * 0x2000);
- options->deferred = NULL;
+
+ options->bank_reg = R15;
+ options->bank_pointer = R12;
+
+ options->gen.context_reg = RSI;
+ options->gen.cycles = RBP;
+ options->gen.limit = RDI;
+ options->gen.scratch1 = R13;
+ options->gen.scratch2 = R14;
+
+ options->gen.native_code_map = malloc(sizeof(native_map_slot));
+ memset(options->gen.native_code_map, 0, sizeof(native_map_slot));
+ options->gen.deferred = NULL;
+ options->gen.ram_inst_sizes = malloc(sizeof(uint8_t) * 0x2000 + sizeof(uint8_t *));
+ options->gen.ram_inst_sizes[0] = (uint8_t *)(options->gen.ram_inst_sizes + 1);
+ memset(options->gen.ram_inst_sizes[0], 0, sizeof(uint8_t) * 0x2000);
+
+ code_info *code = &options->gen.code;
+ init_code_info(code);
+
+ options->save_context_scratch = code->cur;
+ mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
+ mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, scratch2), SZ_W);
+
+ options->gen.save_context = code->cur;
+ for (int i = 0; i <= Z80_A; i++)
+ {
+ int reg;
+ uint8_t size;
+ if (i < Z80_I) {
+ reg = i /2 + Z80_BC + (i > Z80_H ? 2 : 0);
+ size = SZ_W;
+ } else {
+ reg = i;
+ size = SZ_B;
}
+ if (options->regs[reg] >= 0) {
+ mov_rrdisp(code, options->regs[reg], options->gen.context_reg, offsetof(z80_context, regs) + i, size);
+ }
+ if (size == SZ_W) {
+ i++;
+ }
+ }
+ if (options->regs[Z80_SP] >= 0) {
+ mov_rrdisp(code, options->regs[Z80_SP], options->gen.context_reg, offsetof(z80_context, sp), SZ_W);
+ }
+ mov_rrdisp(code, options->gen.limit, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
+ 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);
+ mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch2, SZ_W);
+ options->gen.load_context = code->cur;
+ for (int i = 0; i <= Z80_A; i++)
+ {
+ int reg;
+ uint8_t size;
+ if (i < Z80_I) {
+ reg = i /2 + Z80_BC + (i > Z80_H ? 2 : 0);
+ size = SZ_W;
+ } else {
+ reg = i;
+ size = SZ_B;
+ }
+ if (options->regs[reg] >= 0) {
+ mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + i, options->regs[reg], size);
+ }
+ if (size == SZ_W) {
+ i++;
+ }
+ }
+ if (options->regs[Z80_SP] >= 0) {
+ mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sp), options->regs[Z80_SP], SZ_W);
+ }
+ mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.limit, SZ_D);
+ 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);
+ code_ptr no_sync = code->cur+1;
+ jcc(code, CC_B, no_sync);
+ mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, pc), SZ_W);
+ call(code, options->save_context_scratch);
+ pop_r(code, RAX); //return address in read/write func
+ pop_r(code, RBX); //return address in translated code
+ sub_ir(code, 5, RAX, SZ_PTR); //adjust return address to point to the call that got us here
+ mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
+ mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR);
+ //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);
+ *no_sync = code->cur - (no_sync + 1);
+ //return to caller of z80_run
+ retn(code);
+
+ options->gen.handle_code_write = (code_ptr)z80_handle_code_write;
-void init_z80_context(z80_context * context, x86_z80_options * options)
+ options->read_8 = gen_mem_fun(&options->gen, chunks, num_chunks, READ_8, &options->read_8_noinc);
+ options->write_8 = gen_mem_fun(&options->gen, chunks, num_chunks, WRITE_8, &options->write_8_noinc);
+
+ options->gen.handle_cycle_limit_int = code->cur;
+ cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D);
+ code_ptr skip_int = code->cur+1;
+ jcc(code, CC_B, skip_int);
+ //set limit to the cycle limit
+ mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.limit, SZ_D);
+ //disable interrupts
+ mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
+ mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
+ cycles(&options->gen, 7);
+ //save return address (in scratch1) to Z80 stack
+ sub_ir(code, 2, options->regs[Z80_SP], SZ_W);
+ mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
+ //we need to do check_cycles and cycles outside of the write_8 call
+ //so that the stack has the correct depth if we need to return to C
+ //for a synchronization
+ check_cycles(&options->gen);
+ cycles(&options->gen, 3);
+ //save word to write before call to write_8_noinc
+ push_r(code, options->gen.scratch1);
+ call(code, options->write_8_noinc);
+ //restore word to write
+ pop_r(code, options->gen.scratch1);
+ //write high byte to SP+1
+ mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
+ add_ir(code, 1, options->gen.scratch2, SZ_W);
+ shr_ir(code, 8, options->gen.scratch1, SZ_W);
+ check_cycles(&options->gen);
+ cycles(&options->gen, 3);
+ call(code, options->write_8_noinc);
+ //dispose of return address as we'll be jumping somewhere else
+ pop_r(code, options->gen.scratch2);
+ //TODO: Support interrupt mode 0 and 2
+ mov_ir(code, 0x38, options->gen.scratch1, SZ_W);
+ 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->read_16 = code->cur;
+ cycles(&options->gen, 3);
+ check_cycles(&options->gen);
+ //TODO: figure out how to handle the extra wait state for word reads to bank area
+ //may also need special handling to avoid too much stack depth when acces is blocked
+ push_r(code, options->gen.scratch1);
+ call(code, options->read_8_noinc);
+ mov_rr(code, options->gen.scratch1, options->gen.scratch2, SZ_B);
+ pop_r(code, options->gen.scratch1);
+ add_ir(code, 1, options->gen.scratch1, SZ_W);
+ cycles(&options->gen, 3);
+ check_cycles(&options->gen);
+ call(code, options->read_8_noinc);
+ shl_ir(code, 8, options->gen.scratch1, SZ_W);
+ mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_B);
+ retn(code);
+
+ options->write_16_highfirst = code->cur;
+ cycles(&options->gen, 3);
+ check_cycles(&options->gen);
+ push_r(code, options->gen.scratch2);
+ push_r(code, options->gen.scratch1);
+ add_ir(code, 1, options->gen.scratch2, SZ_W);
+ shr_ir(code, 8, options->gen.scratch1, SZ_W);
+ call(code, options->write_8_noinc);
+ pop_r(code, options->gen.scratch1);
+ pop_r(code, options->gen.scratch2);
+ cycles(&options->gen, 3);
+ check_cycles(&options->gen);
+ //TODO: Check if we can get away with TCO here
+ call(code, options->write_8_noinc);
+ retn(code);
+
+ options->write_16_lowfirst = code->cur;
+ cycles(&options->gen, 3);
+ check_cycles(&options->gen);
+ push_r(code, options->gen.scratch2);
+ push_r(code, options->gen.scratch1);
+ call(code, options->write_8_noinc);
+ pop_r(code, options->gen.scratch1);
+ pop_r(code, options->gen.scratch2);
+ add_ir(code, 1, options->gen.scratch2, SZ_W);
+ shr_ir(code, 8, options->gen.scratch1, SZ_W);
+ cycles(&options->gen, 3);
+ check_cycles(&options->gen);
+ //TODO: Check if we can get away with TCO here
+ call(code, options->write_8_noinc);
+ 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);
+ call(code, options->load_context_scratch);
+ 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)
+{
+ z80_options * options = voptions;
+ //TODO: Handle writes to bank register
+ return options;
+}
+
+void init_z80_context(z80_context * context, z80_options * options)
{
memset(context, 0, sizeof(*context));
context->static_code_map = malloc(sizeof(*context->static_code_map));
@@ -2052,6 +2303,7 @@ void init_z80_context(z80_context * context, x86_z80_options * options)
context->int_cycle = 0xFFFFFFFF;
context->int_pulse_start = 0xFFFFFFFF;
context->int_pulse_end = 0xFFFFFFFF;
+ context->run = options->run;
}
void z80_reset(z80_context * context)
@@ -2062,55 +2314,52 @@ void z80_reset(z80_context * context)
context->extra_pc = NULL;
}
-uint8_t * zbreakpoint_patch(z80_context * context, uint16_t address, uint8_t * native)
+uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst)
{
- native = mov_ir(native, address, SCRATCH1, SZ_W);
- native = call(native, context->bp_stub);
- return native;
+ code_info code = {dst, dst+16};
+ mov_ir(&code, address, SCRATCH1, SZ_W);
+ call(&code, context->bp_stub);
+ return code.cur-dst;
}
void zcreate_stub(z80_context * context)
{
- x86_z80_options * opts = context->options;
- uint8_t * dst = opts->cur_code;
- uint8_t * dst_end = opts->code_end;
- if (dst_end - dst < 128) {
- size_t size = 1024*1024;
- dst = alloc_code(&size);
- opts->code_end = dst_end = dst + size;
- }
- context->bp_stub = dst;
+ z80_options * opts = context->options;
+ code_info *code = &opts->gen.code;
+ check_code_prologue(code);
+ context->bp_stub = code->cur;
//Calculate length of prologue
- int check_int_size = z80_check_cycles_int(dst, 0) - dst;
+ check_cycles_int(&opts->gen, 0);
+ int check_int_size = code->cur-context->bp_stub;
+ code->cur = context->bp_stub;
//Calculate length of patch
- int patch_size = zbreakpoint_patch(context, 0, dst) - dst;
+ int patch_size = zbreakpoint_patch(context, 0, code->cur);
//Save context and call breakpoint handler
- dst = call(dst, (uint8_t *)z80_save_context);
- dst = push_r(dst, SCRATCH1);
- dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
- dst = mov_rr(dst, SCRATCH1, RSI, SZ_W);
- dst = call(dst, context->bp_handler);
- dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+ 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, context->bp_handler);
+ mov_rr(code, RAX, opts->gen.context_reg, SZ_Q);
//Restore context
- dst = call(dst, (uint8_t *)z80_load_context);
- dst = pop_r(dst, SCRATCH1);
+ call(code, opts->gen.load_context);
+ pop_r(code, opts->gen.scratch1);
//do prologue stuff
- dst = cmp_rr(dst, ZCYCLES, ZLIMIT, SZ_D);
- uint8_t * jmp_off = dst+1;
- dst = jcc(dst, CC_NC, dst + 7);
- dst = pop_r(dst, SCRATCH1);
- dst = add_ir(dst, check_int_size - patch_size, SCRATCH1, SZ_Q);
- dst = push_r(dst, SCRATCH1);
- dst = jmp(dst, (uint8_t *)z80_handle_cycle_limit_int);
- *jmp_off = dst - (jmp_off+1);
+ cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
+ uint8_t * jmp_off = code->cur+1;
+ jcc(code, CC_NC, code->cur + 7);
+ pop_r(code, opts->gen.scratch1);
+ add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_Q);
+ push_r(code, opts->gen.scratch1);
+ jmp(code, opts->gen.handle_cycle_limit_int);
+ *jmp_off = code->cur - (jmp_off+1);
//jump back to body of translated instruction
- dst = pop_r(dst, SCRATCH1);
- dst = add_ir(dst, check_int_size - patch_size, SCRATCH1, SZ_Q);
- dst = jmp_r(dst, SCRATCH1);
- opts->cur_code = dst;
+ pop_r(code, opts->gen.scratch1);
+ add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_Q);
+ jmp_r(code, opts->gen.scratch1);
}
void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler)
@@ -2134,8 +2383,12 @@ void zremove_breakpoint(z80_context * context, uint16_t address)
context->breakpoint_flags[address / sizeof(uint8_t)] &= ~(1 << (address % sizeof(uint8_t)));
uint8_t * native = z80_get_native_address(context, address);
if (native) {
- z80_check_cycles_int(native, address);
+ z80_options * opts = context->options;
+ code_info tmp_code = opts->gen.code;
+ opts->gen.code.cur = native;
+ opts->gen.code.last = native + 16;
+ check_cycles_int(&opts->gen, address);
+ opts->gen.code = tmp_code;
}
}
-