# HG changeset patch # User Michael Pavone # Date 1469771949 25200 # Node ID ef7ee9919a73fe023becba00daf6d4313c3d98d0 # Parent 05ecef6c73b63f5cf33bf88186d4f6e9d3cc9279 Partial support for undocumented flag bits diff -r 05ecef6c73b6 -r ef7ee9919a73 z80_to_x86.c --- a/z80_to_x86.c Wed Jul 27 23:08:05 2016 -0700 +++ b/z80_to_x86.c Thu Jul 28 22:59:09 2016 -0700 @@ -425,17 +425,20 @@ if (inst->reg == Z80_AF) { zreg_to_native(opts, Z80_A, opts->gen.scratch1); shl_ir(code, 8, opts->gen.scratch1, SZ_W); - mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B); - shl_ir(code, 1, opts->gen.scratch1, SZ_B); - or_rdispr(code, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B); - shl_ir(code, 2, opts->gen.scratch1, SZ_B); + mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B); + and_ir(code, 0x28, opts->gen.scratch1, SZ_B); + or_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); + ror_ir(code, 1, opts->gen.scratch1, SZ_B); + or_rdispr(code, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B); + ror_ir(code, 1, opts->gen.scratch1, SZ_B); + or_rdispr(code, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B); + ror_ir(code, 2, opts->gen.scratch1, SZ_B); or_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B); - shl_ir(code, 2, opts->gen.scratch1, SZ_B); - or_rdispr(code, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B); - shl_ir(code, 1, opts->gen.scratch1, SZ_B); - or_rdispr(code, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B); - shl_ir(code, 1, opts->gen.scratch1, SZ_B); - or_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); + ror_ir(code, 2, opts->gen.scratch1, SZ_B); + or_rdispr(code, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B); + ror_ir(code, 1, opts->gen.scratch1, SZ_B); + or_rdispr(code, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B); + ror_ir(code, 1, opts->gen.scratch1, SZ_B); } else { zreg_to_native(opts, inst->reg, opts->gen.scratch1); } @@ -463,6 +466,7 @@ setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_Z)); bt_ir(code, 7, opts->gen.scratch1, SZ_W); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_S)); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); shr_ir(code, 8, opts->gen.scratch1, SZ_W); native_to_zreg(opts, opts->gen.scratch1, Z80_A); } else { @@ -829,6 +833,9 @@ } else { add_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + if (z80_size(inst) == SZ_B) { + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } } else { if (src_op.mode == MODE_REG_DIRECT) { add_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); @@ -838,6 +845,8 @@ mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); add_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); } + mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); @@ -853,6 +862,11 @@ } bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst)); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); + if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) { + mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W); + shr_ir(code, 8, opts->gen.scratch2, SZ_W); + mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); break; @@ -888,6 +902,9 @@ } else { adc_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + if (z80_size(inst) == SZ_B) { + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } } else { if (src_op.mode == MODE_REG_DIRECT) { adc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); @@ -897,6 +914,8 @@ mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); adc_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); } + mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); @@ -910,6 +929,11 @@ } bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst)); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); + if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) { + mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W); + shr_ir(code, 8, opts->gen.scratch2, SZ_W); + mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); break; @@ -942,6 +966,9 @@ } else { sub_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + if (z80_size(inst) == SZ_B) { + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } } else { if (src_op.mode == MODE_REG_DIRECT) { sub_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); @@ -951,6 +978,8 @@ mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); sub_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); } + mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); @@ -964,6 +993,11 @@ } bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst)); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); + if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) { + mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W); + shr_ir(code, 8, opts->gen.scratch2, SZ_W); + mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); break; @@ -999,6 +1033,9 @@ } else { sbb_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + if (z80_size(inst) == SZ_B) { + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } } else { if (src_op.mode == MODE_REG_DIRECT) { sbb_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); @@ -1008,6 +1045,8 @@ mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); sbb_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); } + mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); @@ -1021,6 +1060,11 @@ } bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst)); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); + if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) { + mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W); + shr_ir(code, 8, opts->gen.scratch2, SZ_W); + mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } z80_save_reg(inst, opts); z80_save_ea(code, inst, opts); break; @@ -1042,6 +1086,7 @@ } else { and_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); @@ -1069,6 +1114,7 @@ } else { or_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); @@ -1096,6 +1142,7 @@ } else { xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); } + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); @@ -1117,10 +1164,14 @@ mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst)); if (src_op.mode == MODE_REG_DIRECT) { sub_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst)); + mov_rrdisp(code, src_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } else if (src_op.mode == MODE_IMMED) { sub_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst)); + mov_irdisp(code, src_op.disp, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } else { sub_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst)); + mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); @@ -1181,6 +1232,7 @@ setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); int bit = 4; if (dst_op.mode == MODE_REG_DIRECT) { + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); if (dst_op.base >= AH && dst_op.base <= BH) { bit = 12; xor_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W); @@ -1188,7 +1240,9 @@ xor_rr(code, dst_op.base, opts->gen.scratch2, SZ_B); } } else { + mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B); xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); } bt_ir(code, bit, opts->gen.scratch2, SZ_W); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H)); @@ -1257,6 +1311,7 @@ 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); + mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); @@ -1737,6 +1792,26 @@ } else { mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B); } + + if ((inst->addr_mode & 0x1F) == Z80_REG) { + if (src_op.mode == MODE_REG_DIRECT) { + if (size == SZ_W) { + mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W); + shr_ir(code, 8, opts->gen.scratch1, SZ_W); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } else { + mov_rrdisp(code, src_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } + } else { + mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B); + mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } + } else if((inst->addr_mode & 0x1F) != Z80_REG_INDIRECT) { + zreg_to_native(opts, (inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY, opts->gen.scratch2); + add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, opts->gen.scratch2, SZ_W); + shr_ir(code, 8, opts->gen.scratch2, SZ_W); + mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B); + } break; } case Z80_SET: { diff -r 05ecef6c73b6 -r ef7ee9919a73 z80_to_x86.h --- a/z80_to_x86.h Wed Jul 27 23:08:05 2016 -0700 +++ b/z80_to_x86.h Thu Jul 28 22:59:09 2016 -0700 @@ -22,6 +22,7 @@ ZF_H, ZF_Z, ZF_S, + ZF_XY, ZF_NUM }; diff -r 05ecef6c73b6 -r ef7ee9919a73 ztestrun.c --- a/ztestrun.c Wed Jul 27 23:08:05 2016 -0700 +++ b/ztestrun.c Thu Jul 28 22:59:09 2016 -0700 @@ -108,8 +108,11 @@ (context.regs[Z80_IXH] << 8) | context.regs[Z80_IXL], (context.regs[Z80_IYH] << 8) | context.regs[Z80_IYL], context.sp, context.im, context.iff1, context.iff2); - printf("Flags: SZHVNC\n" - " %d%d%d%d%d%d\n", context.flags[ZF_S], context.flags[ZF_Z], context.flags[ZF_H], context.flags[ZF_PV], context.flags[ZF_N], context.flags[ZF_C]); + printf("Flags: SZYHXVNC\n" + " %d%d%d%d%d%d%d%d\n", + context.flags[ZF_S], context.flags[ZF_Z], context.flags[ZF_XY] >> 5 & 1, context.flags[ZF_H], + context.flags[ZF_XY] >> 3 & 1, context.flags[ZF_PV], context.flags[ZF_N], context.flags[ZF_C] + ); puts("--Alternate Regs--"); printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\n", context.alt_regs[Z80_A], context.alt_regs[Z80_B], context.alt_regs[Z80_C],