# HG changeset patch # User Michael Pavone # Date 1469517093 25200 # Node ID e0489abfdab0f0cc447025fd34ad7403421d6e3b # Parent 1625555e346e123528b5ddc015f83eaf9a89397f Implement half-carry for INC, DEC and NEG diff -r 1625555e346e -r e0489abfdab0 z80_to_x86.c --- a/z80_to_x86.c Mon Jul 25 23:16:04 2016 -0700 +++ b/z80_to_x86.c Tue Jul 26 00:11:33 2016 -0700 @@ -202,10 +202,6 @@ } else { call(code, opts->read_16); } - if (modify) { - //pop_r(code, opts->gen.scratch2); - mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); - } } ea->base = opts->gen.scratch1; break; @@ -225,10 +221,6 @@ } else { call(code, opts->read_16); } - if (modify) { - //pop_r(code, opts->gen.scratch2); - mov_ir(code, inst->immed, opts->gen.scratch2, SZ_W); - } } ea->base = opts->gen.scratch1; break; @@ -247,10 +239,6 @@ } else { call(code, opts->read_16); } - if (modify) { - //pop_r(code, opts->gen.scratch2); - mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); - } } ea->base = opts->gen.scratch1; break; @@ -293,6 +281,9 @@ case Z80_IMMED_INDIRECT: case Z80_IX_DISPLACE: case Z80_IY_DISPLACE: + if (inst->op != Z80_LD) { + mov_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W); + } if (z80_size(inst) == SZ_B) { call(&opts->gen.code, opts->write_8); } else { @@ -1043,30 +1034,6 @@ z80_save_ea(code, inst, opts); break; case Z80_INC: - if(z80_size(inst) == SZ_W) { - num_cycles += 2; - } - cycles(&opts->gen, num_cycles); - translate_z80_reg(inst, &dst_op, opts); - if (dst_op.mode == MODE_UNUSED) { - translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); - } - if (dst_op.mode == MODE_REG_DIRECT) { - add_ir(code, 1, dst_op.base, z80_size(inst)); - } else { - add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); - } - if (z80_size(inst) == SZ_B) { - mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); - //TODO: Implement half-carry flag - setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); - setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); - setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); - } - z80_save_reg(inst, opts); - z80_save_ea(code, inst, opts); - z80_save_result(opts, inst); - break; case Z80_DEC: if(z80_size(inst) == SZ_W) { num_cycles += 2; @@ -1076,18 +1043,48 @@ if (dst_op.mode == MODE_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); } - if (dst_op.mode == MODE_REG_DIRECT) { - sub_ir(code, 1, dst_op.base, z80_size(inst)); - } else { - sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); + if (z80_size(inst) == SZ_B) { + if (dst_op.mode == MODE_REG_DIRECT) { + if (dst_op.base >= AH && dst_op.base <= BH) { + mov_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W); + } else { + mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_B); + } + } else { + mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B); + } } - + if (inst->op == Z80_INC) { + if (dst_op.mode == MODE_REG_DIRECT) { + add_ir(code, 1, dst_op.base, z80_size(inst)); + } else { + add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); + } + } else { + if (dst_op.mode == MODE_REG_DIRECT) { + sub_ir(code, 1, dst_op.base, z80_size(inst)); + } else { + sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); + } + } if (z80_size(inst) == SZ_B) { - mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); - //TODO: Implement half-carry flag + mov_irdisp(code, inst->op == Z80_DEC, opts->gen.context_reg, zf_off(ZF_N), SZ_B); setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); + int bit = 4; + if (dst_op.mode == MODE_REG_DIRECT) { + if (dst_op.base >= AH && dst_op.base <= BH) { + bit = 12; + xor_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W); + } else { + xor_rr(code, dst_op.base, opts->gen.scratch2, SZ_B); + } + } else { + xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B); + } + bt_ir(code, bit, opts->gen.scratch2, SZ_W); + setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); @@ -1107,7 +1104,6 @@ jcc(code, CC_C, code->cur+2); *corf_low = code->cur - (corf_low + 1); mov_ir(code, 6, opts->gen.scratch2, SZ_B); - //TODO: Deal with edge case of 9 in high nibble mov_ir(code, 0x90, opts->gen.scratch1, SZ_B); code_ptr after_cmp_set = code->cur+1; jmp(code, code->cur+2); @@ -1148,13 +1144,16 @@ break; case Z80_NEG: cycles(&opts->gen, num_cycles); + mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); neg_r(code, opts->regs[Z80_A], SZ_B); - //TODO: Implement half-carry flag setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); + xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B); + bt_ir(code, 4, opts->gen.scratch2, SZ_B); + setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); break; case Z80_CCF: cycles(&opts->gen, num_cycles);