# HG changeset patch # User Mike Pavone # Date 1368078363 25200 # Node ID 42e1a986f2d0cdc764b29af529ea67dc725641a4 # Parent 170722e80fc010c2152b54da958765ee9f7a7faa Fix calcuation of IX/IY dipslacements. Fix a bunch of stuff related to the IX/IY bit/shift/rotate instructions. diff -r 170722e80fc0 -r 42e1a986f2d0 z80_to_x86.c --- a/z80_to_x86.c Wed May 08 22:45:29 2013 -0700 +++ b/z80_to_x86.c Wed May 08 22:46:03 2013 -0700 @@ -189,7 +189,7 @@ case Z80_IY_DISPLACE: reg = opts->regs[inst->addr_mode == Z80_IX_DISPLACE ? Z80_IX : Z80_IY]; dst = mov_rr(dst, reg, areg, SZ_W); - dst = add_ir(dst, inst->immed, areg, SZ_W); + dst = add_ir(dst, inst->ea_reg, areg, SZ_W); size = z80_size(inst); if (read) { if (modify) { @@ -880,13 +880,18 @@ 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); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = rol_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //TODO: Implement half-carry flag @@ -894,8 +899,11 @@ 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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -903,14 +911,19 @@ 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); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B); dst = rcl_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //TODO: Implement half-carry flag @@ -918,8 +931,11 @@ 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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -927,13 +943,18 @@ 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); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = ror_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //TODO: Implement half-carry flag @@ -941,8 +962,11 @@ 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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -950,14 +974,19 @@ 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); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = bt_irdisp8(dst, 0, CONTEXT, zf_off(ZF_C), SZ_B); dst = rcr_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //TODO: Implement half-carry flag @@ -965,8 +994,11 @@ 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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -975,21 +1007,29 @@ case Z80_SLL: cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; dst = zcycles(dst, cycles); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = shl_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -997,21 +1037,29 @@ case Z80_SRA: cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; dst = zcycles(dst, cycles); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = sar_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -1019,21 +1067,29 @@ case Z80_SRL: cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; dst = zcycles(dst, cycles); - if (inst->reg == Z80_UNUSED) { + 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); } else { + src_op.mode = Z80_UNUSED; dst = translate_z80_reg(inst, &dst_op, dst, opts); } dst = shr_ir(dst, 1, dst_op.base, SZ_B); + if (src_op.mode != Z80_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); //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)); - if (inst->reg == Z80_UNUSED) { + if (inst->addr_mode != Z80_UNUSED) { dst = z80_save_result(dst, inst); + if (src_op.mode != MODE_UNUSED) { + dst = z80_save_reg(dst, inst, opts); + } } else { dst = z80_save_reg(dst, inst, opts); } @@ -1108,27 +1164,45 @@ case Z80_SET: cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; dst = zcycles(dst, cycles); - dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); + dst = translate_z80_ea(inst, &src_op, dst, opts, READ, MODIFY); + if (inst->reg != Z80_USE_IMMED) { + dst = translate_z80_reg(inst, &dst_op, dst, 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); } dst = bts_ir(dst, inst->immed, src_op.base, SZ_B); + if (inst->reg != Z80_USE_IMMED) { + dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); + } if (inst->addr_mode != Z80_REG) { dst = z80_save_result(dst, inst); + if (inst->reg != Z80_USE_IMMED) { + dst = z80_save_reg(dst, 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); - dst = translate_z80_ea(inst, &src_op, dst, opts, READ, DONT_MODIFY); + dst = translate_z80_ea(inst, &src_op, dst, opts, READ, MODIFY); + if (inst->reg != Z80_USE_IMMED) { + dst = translate_z80_reg(inst, &dst_op, dst, 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); } dst = btr_ir(dst, inst->immed, src_op.base, SZ_B); + if (inst->reg != Z80_USE_IMMED) { + dst = mov_rr(dst, src_op.base, dst_op.base, SZ_B); + } if (inst->addr_mode != Z80_REG) { dst = z80_save_result(dst, inst); + if (inst->reg != Z80_USE_IMMED) { + dst = z80_save_reg(dst, inst, opts); + } } break; case Z80_JP: {