# HG changeset patch # User Michael Pavone # Date 1418604323 28800 # Node ID ea80559c67cb9a6d824071f459bccb4636fc849d # Parent 2dde38c1744f54a9502fd1214f11c36757c16bc3 WIP effort to update z80 core for code gen changes diff -r 2dde38c1744f -r ea80559c67cb backend.h --- a/backend.h Tue Mar 11 09:44:47 2014 -0700 +++ b/backend.h Sun Dec 14 16:45:23 2014 -0800 @@ -108,7 +108,7 @@ void check_cycles_int(cpu_options *opts, uint32_t address); void check_cycles(cpu_options * opts); -code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type); +code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc); #endif //BACKEND_H_ diff -r 2dde38c1744f -r ea80559c67cb backend_x86.c --- a/backend_x86.c Tue Mar 11 09:44:47 2014 -0700 +++ b/backend_x86.c Sun Dec 14 16:45:23 2014 -0800 @@ -28,12 +28,15 @@ *jmp_off = code->cur - (jmp_off+1); } -code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type) +code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc) { code_info *code = &opts->code; code_ptr start = code->cur; check_cycles(opts); cycles(opts, opts->bus_cycles); + if (after_inc) { + *after_inc = code->cur; + } if (opts->address_size == SZ_D && opts->address_mask < 0xFFFFFFFF) { and_ir(code, opts->address_mask, opts->scratch1, SZ_D); } diff -r 2dde38c1744f -r ea80559c67cb blastem.c --- a/blastem.c Tue Mar 11 09:44:47 2014 -0700 +++ b/blastem.c Sun Dec 14 16:45:23 2014 -0800 @@ -1072,6 +1072,15 @@ } } } +#ifndef NO_Z80 +const memmap_chunk z80_map[] = { + { 0x0000, 0x4000, 0x1FFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL, NULL }, + { 0x8000, 0x10000, 0xFFFF, 1, MMAP_READ | MMAP_WRITE | MMAP_PTR_IDX | MMAP_FUNC_NULL, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, + { 0x4000, 0x6000, 0x0003, 0, MMAP_READ | MMAP_WRITE, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, + { 0x6000, 0x6100, 0xFFFF, 0, MMAP_WRITE | MMAP_CUSTOM, NULL, NULL, NULL, NULL, (write_8_fun)z80_gen_bank_write}, + { 0x7F00, 0x8000, 0x00FF, 0, MMAP_READ | MMAP_WRITE, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} +}; +#endif int main(int argc, char ** argv) { @@ -1237,9 +1246,9 @@ psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer()); z80_context z_context; - x86_z80_options z_opts; #ifndef NO_Z80 - init_x86_z80_opts(&z_opts); + z80_options z_opts; + init_x86_z80_opts(&z_opts, z80_map, 5); init_z80_context(&z_context, &z_opts); #endif diff -r 2dde38c1744f -r ea80559c67cb m68k_core_x86.c --- a/m68k_core_x86.c Tue Mar 11 09:44:47 2014 -0700 +++ b/m68k_core_x86.c Sun Dec 14 16:45:23 2014 -0800 @@ -2390,10 +2390,12 @@ *skip_sync = code->cur - (skip_sync+1); retn(code); - opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16); - opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8); - opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16); - opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8); + opts->gen.handle_code_write = (code_ptr)m68k_handle_code_write; + + opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16, NULL); + opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8, NULL); + opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16, NULL); + opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8, NULL); opts->read_32 = code->cur; push_r(code, opts->gen.scratch1); diff -r 2dde38c1744f -r ea80559c67cb z80_to_x86.c --- a/z80_to_x86.c Tue Mar 11 09:44:47 2014 -0700 +++ b/z80_to_x86.c Sun Dec 14 16:45:23 2014 -0800 @@ -54,24 +54,9 @@ 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) +void translate_z80_reg(z80inst * inst, x86_ea * ea, z80_options * opts) { - 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) -{ + code_info *code = &opts->gen.code; if (inst->reg == Z80_USE_IMMED) { ea->mode = MODE_IMMED; ea->disp = inst->immed; @@ -81,12 +66,12 @@ 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]; @@ -96,64 +81,64 @@ 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, x86_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 { ea->base = opts->regs[inst->ea_reg]; @@ -162,30 +147,30 @@ 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); } } } 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_rrdisp8(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); + dst = call(dst, 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_rdisp8r(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; @@ -196,7 +181,7 @@ size = z80_size(inst); if (read) { /*if (modify) { - dst = push_r(dst, SCRATCH1); + dst = push_r(dst, opts->gen.scratch1); }*/ if (size == SZ_B) { dst = call(dst, (uint8_t *)z80_read_byte); @@ -204,11 +189,11 @@ dst = call(dst, (uint8_t *)z80_read_word); } if (modify) { - //dst = pop_r(dst, SCRATCH2); - dst = mov_ir(dst, inst->immed, SCRATCH2, SZ_W); + //dst = pop_r(dst, opts->gen.scratch2); + dst = mov_ir(dst, inst->immed, opts->gen.scratch2, SZ_W); } } - ea->base = SCRATCH1; + ea->base = opts->gen.scratch1; break; case Z80_IX_DISPLACE: case Z80_IY_DISPLACE: @@ -218,8 +203,8 @@ 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); + //dst = push_r(dst, opts->gen.scratch1); + dst = mov_rrdisp8(dst, 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); @@ -227,11 +212,11 @@ dst = call(dst, (uint8_t *)z80_read_word); } if (modify) { - //dst = pop_r(dst, SCRATCH2); - dst = mov_rdisp8r(dst, CONTEXT, offsetof(z80_context, scratch1), SCRATCH2, SZ_W); + //dst = pop_r(dst, opts->gen.scratch2); + dst = mov_rdisp8r(dst, 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; @@ -243,13 +228,13 @@ return dst; } -uint8_t * z80_save_ea(uint8_t * dst, z80inst * inst, x86_z80_options * opts) +uint8_t * z80_save_ea(uint8_t * dst, 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 = mov_rr(dst, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B); dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); } else { dst = ror_ir(dst, 8, opts->regs[Z80_IY], SZ_W); @@ -326,14 +311,14 @@ exit(0); } -uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context, uint16_t address) +uint8_t * translate_z80inst(z80inst * inst, z80_context * context, uint16_t address) { uint32_t cycles; x86_ea src_op, dst_op; uint8_t size; - x86_z80_options *opts = context->options; - uint8_t * start = dst; - dst = z80_check_cycles_int(dst, address); + z80_options *opts = context->options; + uint8_t * start = opts->code.cur; + check_cycles_int(&opts->gen, address); switch(inst->op) { case Z80_LD: @@ -364,7 +349,7 @@ if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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); @@ -390,55 +375,55 @@ } break; case Z80_PUSH: - dst = zcycles(dst, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5); + dst = cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5); dst = sub_ir(dst, 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); + dst = mov_rr(dst, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); + dst = shl_ir(dst, 8, opts->gen.scratch1, SZ_W); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B); + dst = shl_ir(dst, 1, opts->gen.scratch1, SZ_B); + dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B); + dst = shl_ir(dst, 2, opts->gen.scratch1, SZ_B); + dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B); + dst = shl_ir(dst, 2, opts->gen.scratch1, SZ_B); + dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B); + dst = shl_ir(dst, 1, opts->gen.scratch1, SZ_B); + dst = or_rdisp8r(dst, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B); + dst = shl_ir(dst, 1, opts->gen.scratch1, SZ_B); + dst = or_rdisp8r(dst, 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); + dst = mov_rr(dst, src_op.base, opts->gen.scratch1, SZ_W); } - dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH2, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_word_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 = cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_word); dst = add_ir(dst, 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); + dst = bt_ir(dst, 0, opts->gen.scratch1, SZ_W); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = bt_ir(dst, 1, opts->gen.scratch1, SZ_W); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_N)); + dst = bt_ir(dst, 2, opts->gen.scratch1, SZ_W); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_PV)); + dst = bt_ir(dst, 4, opts->gen.scratch1, SZ_W); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_H)); + dst = bt_ir(dst, 6, opts->gen.scratch1, SZ_W); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_Z)); + dst = bt_ir(dst, 7, opts->gen.scratch1, SZ_W); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_S)); + dst = shr_ir(dst, 8, opts->gen.scratch1, SZ_W); + dst = mov_rr(dst, 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); + dst = mov_rr(dst, 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 @@ -449,31 +434,31 @@ } else { cycles = 8; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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); + dst = mov_rr(dst, opts->regs[Z80_A], opts->gen.scratch1, SZ_B); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_A), opts->regs[Z80_A], SZ_B); + dst = mov_rrdisp8(dst, 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); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zf_off(f), opts->gen.scratch1, SZ_W); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zaf_off(f), opts->gen.scratch2, SZ_W); + dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, zaf_off(f), SZ_W); + dst = mov_rrdisp8(dst, 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); } } else { - dst = mov_rr(dst, opts->regs[Z80_SP], SCRATCH1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.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 = xchg_rr(dst, opts->regs[inst->reg], opts->gen.scratch1, SZ_B); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); - dst = zcycles(dst, 1); + dst = 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 @@ -481,50 +466,50 @@ //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 = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); + dst = add_ir(dst, 1, opts->gen.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 = xchg_rr(dst, use_reg, opts->gen.scratch1, SZ_B); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); + dst = add_ir(dst, 1, opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); //restore reg to normal rotation dst = ror_ir(dst, 8, use_reg, SZ_W); - dst = zcycles(dst, 2); + dst = 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); + dst = cycles(&opts->gen, 4); + dst = mov_rr(dst, opts->regs[Z80_BC], opts->gen.scratch1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_C), opts->regs[Z80_BC], SZ_W); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_L), opts->regs[Z80_HL], SZ_W); + dst = mov_rrdisp8(dst, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_C), SZ_W); + dst = mov_rrdisp8(dst, opts->gen.scratch2, opts->gen.context_reg, zar_off(Z80_L), SZ_W); + dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch1, SZ_W); + dst = mov_rdisp8r(dst, opts->gen.context_reg, zar_off(Z80_E), opts->regs[Z80_DE], SZ_W); + dst = mov_rrdisp8(dst, 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 = cycles(&opts->gen, 8); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_byte); - dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); - dst = zcycles(dst, 2); + dst = cycles(&opts->gen, 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); //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)); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = setcc_rdisp8(dst, 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 = cycles(&opts->gen, 8); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_byte); - dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.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); @@ -532,37 +517,37 @@ 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); + dst = 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); + dst = 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); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = mov_irdisp8(dst, 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 = cycles(&opts->gen, 8); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_byte); - dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); - dst = zcycles(dst, 2); + dst = cycles(&opts->gen, 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); //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)); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = setcc_rdisp8(dst, 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 = cycles(&opts->gen, 8); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_byte); - dst = mov_rr(dst, opts->regs[Z80_DE], SCRATCH2, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_DE], opts->gen.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); @@ -570,15 +555,15 @@ 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); + dst = 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); + dst = 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); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B); break; } /*case Z80_CPI: @@ -595,7 +580,7 @@ } else if(z80_size(inst) == SZ_W) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); if (src_op.mode == MODE_REG_DIRECT) { @@ -603,13 +588,13 @@ } else { dst = add_ir(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); @@ -623,21 +608,21 @@ } else if(z80_size(inst) == SZ_W) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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); + dst = bt_irdisp8(dst, 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)); } else { dst = adc_ir(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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 = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); break; @@ -648,7 +633,7 @@ } else if(inst->addr_mode == Z80_IMMED) { cycles += 3; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); if (src_op.mode == MODE_REG_DIRECT) { @@ -656,12 +641,12 @@ } else { dst = sub_ir(dst, 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)); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = setcc_rdisp8(dst, 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 = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); break; @@ -674,21 +659,21 @@ } else if(z80_size(inst) == SZ_W) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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); + dst = bt_irdisp8(dst, 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)); } else { dst = sbb_ir(dst, 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_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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 = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); break; @@ -701,7 +686,7 @@ } else if(z80_size(inst) == SZ_W) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); if (src_op.mode == MODE_REG_DIRECT) { @@ -710,13 +695,13 @@ dst = and_ir(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); @@ -730,7 +715,7 @@ } else if(z80_size(inst) == SZ_W) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); if (src_op.mode == MODE_REG_DIRECT) { @@ -739,13 +724,13 @@ dst = or_ir(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); @@ -759,7 +744,7 @@ } else if(z80_size(inst) == SZ_W) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); if (src_op.mode == MODE_REG_DIRECT) { @@ -768,13 +753,13 @@ dst = xor_ir(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); @@ -786,7 +771,7 @@ } else if(inst->addr_mode == Z80_IMMED) { cycles += 3; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); if (src_op.mode == MODE_REG_DIRECT) { @@ -794,12 +779,12 @@ } else { dst = cmp_ir(dst, 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)); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = setcc_rdisp8(dst, 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 = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); break; @@ -812,18 +797,18 @@ } 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; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); if (dst_op.mode == MODE_UNUSED) { dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); } dst = add_ir(dst, 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); + dst = mov_irdisp8(dst, 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 = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); @@ -838,18 +823,18 @@ } 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; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); dst = translate_z80_reg(inst, &dst_op, dst, opts); if (dst_op.mode == MODE_UNUSED) { dst = translate_z80_ea(inst, &dst_op, dst, opts, READ, MODIFY); } dst = sub_ir(dst, 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); + dst = mov_irdisp8(dst, 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 = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } dst = z80_save_reg(dst, inst, opts); dst = z80_save_ea(dst, inst, opts); @@ -857,76 +842,76 @@ break; //case Z80_DAA: case Z80_CPL: - dst = zcycles(dst, 4); + dst = cycles(&opts->gen, 4); dst = not_r(dst, opts->regs[Z80_A], SZ_B); //TODO: Implement half-carry flag - dst = mov_irdisp8(dst, 1, CONTEXT, zf_off(ZF_N), SZ_B); + dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); break; case Z80_NEG: - dst = zcycles(dst, 8); + dst = cycles(&opts->gen, 8); dst = neg_r(dst, 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); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = setcc_rdisp8(dst, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); + dst = mov_irdisp8(dst, 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); + dst = cycles(&opts->gen, 4); + dst = xor_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); + dst = mov_irdisp8(dst, 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); + dst = cycles(&opts->gen, 4); + dst = mov_irdisp8(dst, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); + dst = mov_irdisp8(dst, 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 = mov_rr(dst, opts->gen.context_reg, RDI, SZ_Q); dst = jmp(dst, (uint8_t *)z80_print_regs_exit); } else { - dst = zcycles(dst, 4 * inst->immed); + dst = cycles(&opts->gen, 4 * inst->immed); } break; case Z80_HALT: - dst = zcycles(dst, 4); - dst = mov_ir(dst, address, SCRATCH1, SZ_W); + dst = cycles(&opts->gen, 4); + dst = mov_ir(dst, address, opts->gen.scratch1, SZ_W); uint8_t * call_inst = dst; dst = call(dst, (uint8_t *)z80_halt); dst = jmp(dst, 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); + dst = cycles(&opts->gen, 4); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); + dst = mov_irdisp8(dst, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); + dst = mov_rdisp8r(dst, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D); + dst = mov_irdisp8(dst, 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); + dst = cycles(&opts->gen, 4); + dst = mov_rrdisp32(dst, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); + dst = mov_irdisp8(dst, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); + dst = mov_irdisp8(dst, 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 = add_irdisp32(dst, 4, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); dst = call(dst, (uint8_t *)z80_do_sync); break; case Z80_IM: - dst = zcycles(dst, 4); - dst = mov_irdisp8(dst, inst->immed, CONTEXT, offsetof(z80_context, im), SZ_B); + dst = cycles(&opts->gen, 4); + dst = mov_irdisp8(dst, 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); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); @@ -935,13 +920,13 @@ if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -953,27 +938,27 @@ 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); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } - dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B); + dst = bt_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); dst = rcl_ir(dst, 1, dst_op.base, SZ_B); if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -985,11 +970,11 @@ 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); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); @@ -998,13 +983,13 @@ if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -1016,27 +1001,27 @@ 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); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } - dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B); + dst = bt_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); dst = rcr_ir(dst, 1, dst_op.base, SZ_B); if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -1049,29 +1034,29 @@ 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); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = shl_ir(dst, 1, dst_op.base, SZ_B); - dst = setcc_rdisp8(dst, CC_C, CONTEXT, zf_off(ZF_C)); + dst = setcc_rdisp8(dst, 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); } if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, dst_op.base, src_op.base, SZ_B); } - dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_N), SZ_B); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -1083,11 +1068,11 @@ break; case Z80_SRA: cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); @@ -1096,13 +1081,13 @@ if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -1114,11 +1099,11 @@ break; case Z80_SRL: cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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); + dst = cycles(&opts->gen, 1); } else { src_op.mode = MODE_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); @@ -1127,13 +1112,13 @@ if (src_op.mode != MODE_UNUSED) { dst = mov_rr(dst, 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); + dst = setcc_rdisp8(dst, CC_C, opts->gen.context_reg, zf_off(ZF_C)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); if (src_op.mode != MODE_UNUSED) { @@ -1144,65 +1129,65 @@ } break; case Z80_RLD: - dst = zcycles(dst, 8); - dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W); + dst = cycles(&opts->gen, 8); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_byte); //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 = mov_rr(dst, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); + dst = shl_ir(dst, 4, opts->gen.scratch1, SZ_W); + dst = and_ir(dst, 0xF, opts->gen.scratch2, SZ_W); + dst = and_ir(dst, 0xFFF, opts->gen.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); + dst = or_rr(dst, opts->gen.scratch2, opts->gen.scratch1, SZ_W); + //opts->gen.scratch1 = 0x0124 + dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); + dst = cycles(&opts->gen, 4); + dst = or_rr(dst, 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_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); - dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); - dst = ror_ir(dst, 8, SCRATCH1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); + dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); break; case Z80_RRD: - dst = zcycles(dst, 8); - dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH1, SZ_W); + dst = cycles(&opts->gen, 8); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_read_byte); //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 = movzx_rr(dst, opts->regs[Z80_A], opts->gen.scratch2, SZ_B, SZ_W); + dst = ror_ir(dst, 4, opts->gen.scratch1, SZ_W); + dst = shl_ir(dst, 4, opts->gen.scratch2, SZ_W); + dst = and_ir(dst, 0xF00F, opts->gen.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); + //opts->gen.scratch1 = 0x2001 + //opts->gen.scratch2 = 0x0040 + dst = or_rr(dst, opts->gen.scratch2, opts->gen.scratch1, SZ_W); + //opts->gen.scratch1 = 0x2041 + dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); + dst = cycles(&opts->gen, 4); + dst = shr_ir(dst, 4, opts->gen.scratch1, SZ_B); + dst = or_rr(dst, 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_irdisp8(dst, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + dst = setcc_rdisp8(dst, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); + dst = setcc_rdisp8(dst, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); - dst = mov_rr(dst, opts->regs[Z80_HL], SCRATCH2, SZ_W); - dst = ror_ir(dst, 8, SCRATCH1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_HL], opts->gen.scratch2, SZ_W); + dst = ror_ir(dst, 8, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_write_byte); break; case Z80_BIT: { cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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)]; @@ -1215,23 +1200,23 @@ } if (inst->addr_mode != Z80_REG) { //Reads normally take 3 cycles, but the read at the end of a bit instruction takes 4 - dst = zcycles(dst, 1); + dst = 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); + dst = setcc_rdisp8(dst, CC_NC, opts->gen.context_reg, zf_off(ZF_Z)); + dst = setcc_rdisp8(dst, CC_NC, opts->gen.context_reg, zf_off(ZF_PV)); + dst = mov_irdisp8(dst, 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)); + dst = setcc_rdisp8(dst, CC_S, opts->gen.context_reg, zf_off(ZF_S)); } else { - dst = mov_irdisp8(dst, 0, CONTEXT, zf_off(ZF_S), SZ_B); + dst = mov_irdisp8(dst, 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); + dst = cycles(&opts->gen, 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)]; @@ -1247,7 +1232,7 @@ } 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); + dst = cycles(&opts->gen, 1); } dst = bts_ir(dst, bit, src_op.base, size); if (inst->reg != Z80_USE_IMMED) { @@ -1273,7 +1258,7 @@ } case Z80_RES: { cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, 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)]; @@ -1289,7 +1274,7 @@ } 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); + dst = cycles(&opts->gen, 1); } dst = btr_ir(dst, bit, src_op.base, size); if (inst->reg != Z80_USE_IMMED) { @@ -1320,7 +1305,7 @@ } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { cycles += 4; } - dst = zcycles(dst, cycles); + dst = cycles(&opts->gen, cycles); if (inst->addr_mode != Z80_REG_INDIRECT && inst->immed < 0x4000) { uint8_t * call_dst = z80_get_native_address(context, inst->immed); if (!call_dst) { @@ -1331,44 +1316,44 @@ dst = jmp(dst, call_dst); } else { if (inst->addr_mode == Z80_REG_INDIRECT) { - dst = mov_rr(dst, opts->regs[inst->ea_reg], SCRATCH1, SZ_W); + dst = mov_rr(dst, opts->regs[inst->ea_reg], opts->gen.scratch1, SZ_W); } else { - dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W); + dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_W); } dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } break; } case Z80_JPCC: { - dst = zcycles(dst, 7);//T States: 4,3 + dst = 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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 + dst = 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); @@ -1379,15 +1364,15 @@ } dst = jmp(dst, call_dst); } else { - dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W); + dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } *no_jump_off = dst - (no_jump_off+1); break; } case Z80_JR: { - dst = zcycles(dst, 12);//T States: 4,3,5 + dst = 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); @@ -1398,31 +1383,31 @@ } dst = jmp(dst, call_dst); } else { - dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W); + dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } break; } case Z80_JRCC: { - dst = zcycles(dst, 7);//T States: 4,3 + dst = 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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 + dst = 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); @@ -1433,19 +1418,19 @@ } dst = jmp(dst, call_dst); } else { - dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W); + dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } *no_jump_off = dst - (no_jump_off+1); break; } case Z80_DJNZ: - dst = zcycles(dst, 8);//T States: 5,3 + dst = cycles(&opts->gen, 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 + dst = 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); @@ -1456,17 +1441,17 @@ } dst = jmp(dst, call_dst); } else { - dst = mov_ir(dst, dest_addr, SCRATCH1, SZ_W); + dst = mov_ir(dst, dest_addr, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } *no_jump_off = dst - (no_jump_off+1); break; case Z80_CALL: { - dst = zcycles(dst, 11);//T States: 4,3,4 + dst = cycles(&opts->gen, 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 = mov_ir(dst, address + 3, opts->gen.scratch1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 if (inst->immed < 0x4000) { uint8_t * call_dst = z80_get_native_address(context, inst->immed); @@ -1477,44 +1462,44 @@ } dst = jmp(dst, call_dst); } else { - dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W); + dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } break; } case Z80_CALLCC: - dst = zcycles(dst, 10);//T States: 4,3,3 (false case) + dst = 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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 = cycles(&opts->gen, 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 = mov_ir(dst, address + 3, opts->gen.scratch1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); dst = call(dst, (uint8_t *)z80_write_word_highfirst);//T States: 3, 3 if (inst->immed < 0x4000) { uint8_t * call_dst = z80_get_native_address(context, inst->immed); @@ -1525,81 +1510,81 @@ } dst = jmp(dst, call_dst); } else { - dst = mov_ir(dst, inst->immed, SCRATCH1, SZ_W); + dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_W); dst = call(dst, (uint8_t *)z80_native_addr); - dst = jmp_r(dst, SCRATCH1); + dst = jmp_r(dst, opts->gen.scratch1); } *no_call_off = dst - (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 = cycles(&opts->gen, 4);//T States: 4 + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.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); + dst = jmp_r(dst, opts->gen.scratch1); break; case Z80_RETCC: { - dst = zcycles(dst, 5);//T States: 5 + dst = 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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); + dst = cmp_irdisp8(dst, 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 = mov_rr(dst, opts->regs[Z80_SP], opts->gen.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); + dst = jmp_r(dst, opts->gen.scratch1); *no_call_off = dst - (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 = cycles(&opts->gen, 8);//T States: 4, 4 + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.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); + dst = jmp_r(dst, 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 = cycles(&opts->gen, 8);//T States: 4, 4 + dst = mov_rdisp8r(dst, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); + dst = mov_rrdisp8(dst, opts->gen.scratch2, opts->gen.context_reg, 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); + dst = jmp_r(dst, 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 = cycles(&opts->gen, 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 = mov_ir(dst, address + 1, opts->gen.scratch1, SZ_W); + dst = mov_rr(dst, opts->regs[Z80_SP], opts->gen.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); if (!call_dst) { @@ -1611,15 +1596,15 @@ break; } case Z80_IN: - dst = zcycles(dst, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 + dst = 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); + dst = mov_ir(dst, inst->immed, opts->gen.scratch1, SZ_B); } else { - dst = mov_rr(dst, opts->regs[Z80_C], SCRATCH1, SZ_B); + dst = mov_rr(dst, 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 = mov_rr(dst, opts->gen.scratch1, dst_op.base, SZ_B); dst = z80_save_reg(dst, inst, opts); break; /*case Z80_INI: @@ -1627,14 +1612,14 @@ case Z80_IND: case Z80_INDR:*/ case Z80_OUT: - dst = zcycles(dst, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 + dst = 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); + dst = mov_ir(dst, inst->immed, opts->gen.scratch2, SZ_B); } else { - dst = mov_rr(dst, opts->regs[Z80_C], SCRATCH2, SZ_B); + dst = mov_rr(dst, 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 = mov_rr(dst, dst_op.base, opts->gen.scratch1, SZ_B); dst = call(dst, (uint8_t *)z80_io_write); dst = z80_save_reg(dst, inst, opts); break; @@ -1676,7 +1661,7 @@ 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) { if (address >= 0x4000) { return 0; @@ -1688,7 +1673,7 @@ { 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; @@ -1752,7 +1737,7 @@ 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 = mov_ir(dst, inst_start, opts->gen.scratch1, SZ_D); dst = call(dst, (uint8_t *)z80_retrans_stub); } return context; @@ -1773,7 +1758,7 @@ void z80_handle_deferred(z80_context * context) { - x86_z80_options * opts = context->options; + 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); @@ -1783,7 +1768,7 @@ 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; @@ -1850,7 +1835,7 @@ 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) { @@ -1923,8 +1908,17 @@ } } -void init_x86_z80_opts(x86_z80_options * options) +void init_x86_z80_opts(z80_options * options, memmap_chunk * 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->flags = 0; options->regs[Z80_B] = BH; options->regs[Z80_C] = RBX; @@ -1946,15 +1940,146 @@ 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); + + 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); memset(options->ram_inst_sizes, 0, sizeof(uint8_t) * 0x2000); - options->deferred = NULL; + + 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) { + int reg = i /2 + Z80_BC; + 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 (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); + + 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) { + int reg = i /2 + Z80_BC; + 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 (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); + + 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; + //return to caller of z80_run + retn(code); + + options->gen.read_8 = gen_mem_fun(&options->gen, chunks, num_chunks, READ_8, NULL); + options->gen.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 + move_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); + move_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(options->gen.scratch2); + //TODO: Support interrupt mode 0 and 2 + mov_ir(code, 0x38, options->gen.scratch1, SZ_W); + call(code, (code_ptr)z80_native_addr); + jmp_r(code, options->gen.scratch1); } -void init_z80_context(z80_context * context, x86_z80_options * 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)); @@ -1979,9 +2104,9 @@ static uint8_t * bp_stub = NULL; uint8_t * native = z80_get_native_address_trans(context, address); uint8_t * start_native = native; - native = mov_ir(native, address, SCRATCH1, SZ_W); + native = mov_ir(native, address, opts->gen.scratch1, SZ_W); if (!bp_stub) { - x86_z80_options * opts = context->options; + z80_options * opts = context->options; uint8_t * dst = opts->cur_code; uint8_t * dst_end = opts->code_end; if (dst_end - dst < 128) { @@ -1999,27 +2124,27 @@ //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 = push_r(dst, opts->gen.scratch1); + dst = mov_rr(dst, opts->gen.context_reg, RDI, SZ_Q); + dst = mov_rr(dst, opts->gen.scratch1, RSI, SZ_W); dst = call(dst, bp_handler); - dst = mov_rr(dst, RAX, CONTEXT, SZ_Q); + dst = mov_rr(dst, RAX, opts->gen.context_reg, SZ_Q); //Restore context dst = call(dst, (uint8_t *)z80_load_context); - dst = pop_r(dst, SCRATCH1); + dst = pop_r(dst, opts->gen.scratch1); //do prologue stuff - dst = cmp_rr(dst, ZCYCLES, ZLIMIT, SZ_D); + dst = cmp_rr(dst, opts->gen.cycles, opts->gen.limit, 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 - (native-start_native), SCRATCH1, SZ_Q); - dst = push_r(dst, SCRATCH1); + dst = pop_r(dst, opts->gen.scratch1); + dst = add_ir(dst, check_int_size - (native-start_native), opts->gen.scratch1, SZ_Q); + dst = push_r(dst, opts->gen.scratch1); dst = jmp(dst, (uint8_t *)z80_handle_cycle_limit_int); *jmp_off = dst - (jmp_off+1); //jump back to body of translated instruction - dst = pop_r(dst, SCRATCH1); - dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_Q); - dst = jmp_r(dst, SCRATCH1); + dst = pop_r(dst, opts->gen.scratch1); + dst = add_ir(dst, check_int_size - (native-start_native), opts->gen.scratch1, SZ_Q); + dst = jmp_r(dst, opts->gen.scratch1); opts->cur_code = dst; } else { native = call(native, bp_stub); diff -r 2dde38c1744f -r ea80559c67cb z80_to_x86.h --- a/z80_to_x86.h Tue Mar 11 09:44:47 2014 -0700 +++ b/z80_to_x86.h Sun Dec 14 16:45:23 2014 -0800 @@ -22,13 +22,14 @@ }; typedef struct { - uint8_t * cur_code; - uint8_t * code_end; - uint8_t *ram_inst_sizes; - deferred_addr * deferred; + cpu_options gen; + code_ptr save_context_scratch; + code_ptr load_context_scratch; + code_ptr write_8_noinc; + uint32_t flags; int8_t regs[Z80_UNUSED]; -} x86_z80_options; +} z80_options; typedef struct { void * native_pc; @@ -51,7 +52,7 @@ uint32_t int_cycle; native_map_slot * static_code_map; native_map_slot * banked_code_map; - void * options; + z80_options * options; void * system; uint8_t ram_code_flags[(8 * 1024)/128/8]; uint32_t int_enable_cycle; @@ -59,8 +60,8 @@ } z80_context; void translate_z80_stream(z80_context * context, uint32_t address); -void init_x86_z80_opts(x86_z80_options * options); -void init_z80_context(z80_context * context, x86_z80_options * options); +void init_x86_z80_opts(z80_options * options, memmap_chunk * chunks, uint32_t num_chunks); +void init_z80_context(z80_context * context, z80_options * options); uint8_t * z80_get_native_address(z80_context * context, uint32_t address); uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address); z80_context * z80_handle_code_write(uint32_t address, z80_context * context);