comparison z80_to_x86.c @ 1046:a27fdf43f1a7

Fix DAA and implement half-carry for remaining instructions. Z80 core now passes ZEXDOC!
author Michael Pavone <pavone@retrodev.com>
date Tue, 26 Jul 2016 23:12:23 -0700
parents e0489abfdab0
children 6b07af1515b5
comparison
equal deleted inserted replaced
1045:e0489abfdab0 1046:a27fdf43f1a7
665 } 665 }
666 case Z80_CPI: 666 case Z80_CPI:
667 cycles(&opts->gen, num_cycles);//T-States 4,4 667 cycles(&opts->gen, num_cycles);//T-States 4,4
668 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); 668 zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
669 call(code, opts->read_8);//T-States 3 669 call(code, opts->read_8);//T-States 3
670 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 670 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
671 sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
671 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 672 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
672 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 673 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
673 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 674 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
674 //TODO: Implement half-carry flag 675 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
676 xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
677 bt_ir(code, 4, opts->gen.scratch2, SZ_B);
678 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
675 cycles(&opts->gen, 5);//T-States 5 679 cycles(&opts->gen, 5);//T-States 5
676 if (opts->regs[Z80_HL] >= 0) { 680 if (opts->regs[Z80_HL] >= 0) {
677 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); 681 add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
678 } else { 682 } else {
679 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W); 683 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
687 break; 691 break;
688 case Z80_CPIR: { 692 case Z80_CPIR: {
689 cycles(&opts->gen, num_cycles);//T-States 4,4 693 cycles(&opts->gen, num_cycles);//T-States 4,4
690 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); 694 zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
691 call(code, opts->read_8);//T-States 3 695 call(code, opts->read_8);//T-States 3
692 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 696 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
697 sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
693 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 698 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
694 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 699 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
695 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 700 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
696 //TODO: Implement half-carry flag 701 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
702 xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
703 bt_ir(code, 4, opts->gen.scratch2, SZ_B);
704 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
697 cycles(&opts->gen, 5);//T-States 5 705 cycles(&opts->gen, 5);//T-States 5
698 if (opts->regs[Z80_HL] >= 0) { 706 if (opts->regs[Z80_HL] >= 0) {
699 add_ir(code, 1, opts->regs[Z80_HL], SZ_W); 707 add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
700 } else { 708 } else {
701 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W); 709 add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
720 } 728 }
721 case Z80_CPD: 729 case Z80_CPD:
722 cycles(&opts->gen, num_cycles);//T-States 4,4 730 cycles(&opts->gen, num_cycles);//T-States 4,4
723 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); 731 zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
724 call(code, opts->read_8);//T-States 3 732 call(code, opts->read_8);//T-States 3
725 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 733 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
734 sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
726 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 735 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
727 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 736 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
728 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 737 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
729 //TODO: Implement half-carry flag 738 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
739 xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
740 bt_ir(code, 4, opts->gen.scratch2, SZ_B);
741 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
730 cycles(&opts->gen, 5);//T-States 5 742 cycles(&opts->gen, 5);//T-States 5
731 if (opts->regs[Z80_HL] >= 0) { 743 if (opts->regs[Z80_HL] >= 0) {
732 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); 744 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
733 } else { 745 } else {
734 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W); 746 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
742 break; 754 break;
743 case Z80_CPDR: { 755 case Z80_CPDR: {
744 cycles(&opts->gen, num_cycles);//T-States 4,4 756 cycles(&opts->gen, num_cycles);//T-States 4,4
745 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); 757 zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
746 call(code, opts->read_8);//T-States 3 758 call(code, opts->read_8);//T-States 3
747 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 759 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
760 sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
748 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 761 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
749 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 762 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
750 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 763 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
751 //TODO: Implement half-carry flag 764 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
765 xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
766 bt_ir(code, 4, opts->gen.scratch2, SZ_B);
767 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
752 cycles(&opts->gen, 5);//T-States 5 768 cycles(&opts->gen, 5);//T-States 5
753 if (opts->regs[Z80_HL] >= 0) { 769 if (opts->regs[Z80_HL] >= 0) {
754 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W); 770 sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
755 } else { 771 } else {
756 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W); 772 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
783 } 799 }
784 cycles(&opts->gen, num_cycles); 800 cycles(&opts->gen, num_cycles);
785 translate_z80_reg(inst, &dst_op, opts); 801 translate_z80_reg(inst, &dst_op, opts);
786 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); 802 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
787 if (dst_op.mode == MODE_REG_DIRECT) { 803 if (dst_op.mode == MODE_REG_DIRECT) {
804 mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
805 } else {
806 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
807 }
808 if (src_op.mode == MODE_REG_DIRECT) {
809 xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
810 } else if (src_op.mode == MODE_IMMED) {
811 xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
812 } else {
813 xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
814 }
815 if (dst_op.mode == MODE_REG_DIRECT) {
788 if (src_op.mode == MODE_REG_DIRECT) { 816 if (src_op.mode == MODE_REG_DIRECT) {
789 add_rr(code, src_op.base, dst_op.base, z80_size(inst)); 817 add_rr(code, src_op.base, dst_op.base, z80_size(inst));
790 } else if (src_op.mode == MODE_IMMED) { 818 } else if (src_op.mode == MODE_IMMED) {
791 add_ir(code, src_op.disp, dst_op.base, z80_size(inst)); 819 add_ir(code, src_op.disp, dst_op.base, z80_size(inst));
792 } else { 820 } else {
802 add_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); 830 add_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
803 } 831 }
804 } 832 }
805 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 833 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
806 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 834 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
807 //TODO: Implement half-carry flag
808 if (z80_size(inst) == SZ_B) { 835 if (z80_size(inst) == SZ_B) {
809 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 836 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
810 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 837 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
811 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 838 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
812 } 839 }
840 if (dst_op.mode == MODE_REG_DIRECT) {
841 xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
842 } else {
843 xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
844 }
845 bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
846 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
813 z80_save_reg(inst, opts); 847 z80_save_reg(inst, opts);
814 z80_save_ea(code, inst, opts); 848 z80_save_ea(code, inst, opts);
815 break; 849 break;
816 case Z80_ADC: 850 case Z80_ADC:
817 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 851 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
822 num_cycles += 4; 856 num_cycles += 4;
823 } 857 }
824 cycles(&opts->gen, num_cycles); 858 cycles(&opts->gen, num_cycles);
825 translate_z80_reg(inst, &dst_op, opts); 859 translate_z80_reg(inst, &dst_op, opts);
826 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); 860 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
861 if (dst_op.mode == MODE_REG_DIRECT) {
862 mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
863 } else {
864 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
865 }
866 if (src_op.mode == MODE_REG_DIRECT) {
867 xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
868 } else if (src_op.mode == MODE_IMMED) {
869 xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
870 } else {
871 xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
872 }
827 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 873 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
828 if (dst_op.mode == MODE_REG_DIRECT) { 874 if (dst_op.mode == MODE_REG_DIRECT) {
829 if (src_op.mode == MODE_REG_DIRECT) { 875 if (src_op.mode == MODE_REG_DIRECT) {
830 adc_rr(code, src_op.base, dst_op.base, z80_size(inst)); 876 adc_rr(code, src_op.base, dst_op.base, z80_size(inst));
831 } else if (src_op.mode == MODE_IMMED) { 877 } else if (src_op.mode == MODE_IMMED) {
843 adc_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); 889 adc_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
844 } 890 }
845 } 891 }
846 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 892 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
847 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 893 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
848 //TODO: Implement half-carry flag
849 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 894 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
850 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 895 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
851 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 896 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
897 if (dst_op.mode == MODE_REG_DIRECT) {
898 xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
899 } else {
900 xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
901 }
902 bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
903 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
852 z80_save_reg(inst, opts); 904 z80_save_reg(inst, opts);
853 z80_save_ea(code, inst, opts); 905 z80_save_ea(code, inst, opts);
854 break; 906 break;
855 case Z80_SUB: 907 case Z80_SUB:
856 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 908 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
860 } 912 }
861 cycles(&opts->gen, num_cycles); 913 cycles(&opts->gen, num_cycles);
862 translate_z80_reg(inst, &dst_op, opts); 914 translate_z80_reg(inst, &dst_op, opts);
863 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); 915 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
864 if (dst_op.mode == MODE_REG_DIRECT) { 916 if (dst_op.mode == MODE_REG_DIRECT) {
917 mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
918 } else {
919 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
920 }
921 if (src_op.mode == MODE_REG_DIRECT) {
922 xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
923 } else if (src_op.mode == MODE_IMMED) {
924 xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
925 } else {
926 xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
927 }
928 if (dst_op.mode == MODE_REG_DIRECT) {
865 if (src_op.mode == MODE_REG_DIRECT) { 929 if (src_op.mode == MODE_REG_DIRECT) {
866 sub_rr(code, src_op.base, dst_op.base, z80_size(inst)); 930 sub_rr(code, src_op.base, dst_op.base, z80_size(inst));
867 } else if (src_op.mode == MODE_IMMED) { 931 } else if (src_op.mode == MODE_IMMED) {
868 sub_ir(code, src_op.disp, dst_op.base, z80_size(inst)); 932 sub_ir(code, src_op.disp, dst_op.base, z80_size(inst));
869 } else { 933 } else {
880 } 944 }
881 } 945 }
882 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 946 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
883 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 947 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
884 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 948 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
885 //TODO: Implement half-carry flag
886 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 949 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
887 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 950 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
951 if (dst_op.mode == MODE_REG_DIRECT) {
952 xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
953 } else {
954 xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
955 }
956 bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
957 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
888 z80_save_reg(inst, opts); 958 z80_save_reg(inst, opts);
889 z80_save_ea(code, inst, opts); 959 z80_save_ea(code, inst, opts);
890 break; 960 break;
891 case Z80_SBC: 961 case Z80_SBC:
892 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 962 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
897 num_cycles += 4; 967 num_cycles += 4;
898 } 968 }
899 cycles(&opts->gen, num_cycles); 969 cycles(&opts->gen, num_cycles);
900 translate_z80_reg(inst, &dst_op, opts); 970 translate_z80_reg(inst, &dst_op, opts);
901 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); 971 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
972 if (dst_op.mode == MODE_REG_DIRECT) {
973 mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
974 } else {
975 mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
976 }
977 if (src_op.mode == MODE_REG_DIRECT) {
978 xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
979 } else if (src_op.mode == MODE_IMMED) {
980 xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
981 } else {
982 xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
983 }
902 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 984 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
903 if (dst_op.mode == MODE_REG_DIRECT) { 985 if (dst_op.mode == MODE_REG_DIRECT) {
904 if (src_op.mode == MODE_REG_DIRECT) { 986 if (src_op.mode == MODE_REG_DIRECT) {
905 sbb_rr(code, src_op.base, dst_op.base, z80_size(inst)); 987 sbb_rr(code, src_op.base, dst_op.base, z80_size(inst));
906 } else if (src_op.mode == MODE_IMMED) { 988 } else if (src_op.mode == MODE_IMMED) {
918 sbb_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); 1000 sbb_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
919 } 1001 }
920 } 1002 }
921 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 1003 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
922 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1004 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
923 //TODO: Implement half-carry flag
924 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 1005 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
925 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1006 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
926 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1007 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1008 if (dst_op.mode == MODE_REG_DIRECT) {
1009 xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1010 } else {
1011 xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1012 }
1013 bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
1014 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
927 z80_save_reg(inst, opts); 1015 z80_save_reg(inst, opts);
928 z80_save_ea(code, inst, opts); 1016 z80_save_ea(code, inst, opts);
929 break; 1017 break;
930 case Z80_AND: 1018 case Z80_AND:
931 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { 1019 if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1015 num_cycles += 3; 1103 num_cycles += 3;
1016 } 1104 }
1017 cycles(&opts->gen, num_cycles); 1105 cycles(&opts->gen, num_cycles);
1018 translate_z80_reg(inst, &dst_op, opts); 1106 translate_z80_reg(inst, &dst_op, opts);
1019 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); 1107 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1108 mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1020 if (src_op.mode == MODE_REG_DIRECT) { 1109 if (src_op.mode == MODE_REG_DIRECT) {
1021 cmp_rr(code, src_op.base, dst_op.base, z80_size(inst)); 1110 sub_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1022 } else if (src_op.mode == MODE_IMMED) { 1111 } else if (src_op.mode == MODE_IMMED) {
1023 cmp_ir(code, src_op.disp, dst_op.base, z80_size(inst)); 1112 sub_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1024 } else { 1113 } else {
1025 cmp_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); 1114 sub_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1026 } 1115 }
1027 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); 1116 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1028 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1117 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1029 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); 1118 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1030 //TODO: Implement half-carry flag
1031 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1119 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1032 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1120 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1121 xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1122 if (src_op.mode == MODE_REG_DIRECT) {
1123 xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1124 } else if (src_op.mode == MODE_IMMED) {
1125 xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1126 } else {
1127 xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1128 }
1129 bt_ir(code, 4, opts->gen.scratch2, SZ_B);
1130 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1033 z80_save_reg(inst, opts); 1131 z80_save_reg(inst, opts);
1034 z80_save_ea(code, inst, opts); 1132 z80_save_ea(code, inst, opts);
1035 break; 1133 break;
1036 case Z80_INC: 1134 case Z80_INC:
1037 case Z80_DEC: 1135 case Z80_DEC:
1088 } 1186 }
1089 z80_save_reg(inst, opts); 1187 z80_save_reg(inst, opts);
1090 z80_save_ea(code, inst, opts); 1188 z80_save_ea(code, inst, opts);
1091 z80_save_result(opts, inst); 1189 z80_save_result(opts, inst);
1092 break; 1190 break;
1093 case Z80_DAA: 1191 case Z80_DAA: {
1094 cycles(&opts->gen, num_cycles); 1192 cycles(&opts->gen, num_cycles);
1095 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, SZ_B); 1193 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, SZ_B);
1096 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1097 code_ptr corf_low = code->cur+1;
1098 jcc(code, CC_NZ, code->cur+2);
1099 zreg_to_native(opts, Z80_A, opts->gen.scratch1); 1194 zreg_to_native(opts, Z80_A, opts->gen.scratch1);
1100 and_ir(code, 0xF, opts->gen.scratch1, SZ_B); 1195 and_ir(code, 0xF, opts->gen.scratch1, SZ_B);
1101 cmp_ir(code, 0xA, opts->gen.scratch1, SZ_B); 1196 cmp_ir(code, 0xA, opts->gen.scratch1, SZ_B);
1197 mov_ir(code, 0xA0, opts->gen.scratch1, SZ_B);
1198 code_ptr corf_low_range = code->cur + 1;
1199 jcc(code, CC_NC, code->cur+2);
1200 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1201 code_ptr corf_low = code->cur + 1;
1202 jcc(code, CC_NZ, code->cur+2);
1203 code_ptr no_corf_low = code->cur + 1;
1204 jmp(code, code->cur + 2);
1102 1205
1103 code_ptr no_corf_low = code->cur+1; 1206 *corf_low_range = code->cur - (corf_low_range + 1);
1104 jcc(code, CC_C, code->cur+2); 1207 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B);
1105 *corf_low = code->cur - (corf_low + 1); 1208 *corf_low = code->cur - (corf_low + 1);
1106 mov_ir(code, 6, opts->gen.scratch2, SZ_B); 1209 mov_ir(code, 0x06, opts->gen.scratch2, SZ_B);
1107 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B);
1108 code_ptr after_cmp_set = code->cur+1;
1109 jmp(code, code->cur+2);
1110 1210
1111 *no_corf_low = code->cur - (no_corf_low + 1); 1211 *no_corf_low = code->cur - (no_corf_low + 1);
1112 mov_ir(code, 0xA0, opts->gen.scratch1, SZ_B);
1113 *after_cmp_set = code->cur - (after_cmp_set + 1);
1114 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1212 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1115 code_ptr corf_high = code->cur+1; 1213 code_ptr corf_high = code->cur+1;
1116 jcc(code, CC_NZ, code->cur+2); 1214 jcc(code, CC_NZ, code->cur+2);
1117 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); 1215 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1118 code_ptr no_corf_high = code->cur+1; 1216 code_ptr no_corf_high = code->cur+1;
1119 jcc(code, CC_C, code->cur+2); 1217 jcc(code, CC_C, code->cur+2);
1120 *corf_high = code->cur - (corf_high + 1); 1218 *corf_high = code->cur - (corf_high + 1);
1121 or_ir(code, 0x60, opts->gen.scratch2, SZ_B); 1219 or_ir(code, 0x60, opts->gen.scratch2, SZ_B);
1220 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1122 *no_corf_high = code->cur - (no_corf_high + 1); 1221 *no_corf_high = code->cur - (no_corf_high + 1);
1222
1223 mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
1224 xor_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_B);
1123 1225
1124 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1226 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1125 code_ptr not_sub = code->cur+1; 1227 code_ptr not_sub = code->cur+1;
1126 jcc(code, CC_Z, code->cur+2); 1228 jcc(code, CC_Z, code->cur+2);
1127 neg_r(code, opts->gen.scratch2, SZ_B); 1229 neg_r(code, opts->gen.scratch2, SZ_B);
1128 *not_sub = code->cur - (not_sub + 1); 1230 *not_sub = code->cur - (not_sub + 1);
1231
1129 add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B); 1232 add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B);
1130 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); 1233 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1131 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); 1234 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1132 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); 1235 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1133 code_ptr no_carry = code->cur+1; 1236 xor_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
1134 jcc(code, CC_NC, code->cur+2); 1237 bt_ir(code, 4, opts->gen.scratch1, SZ_B);
1135 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); 1238 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1136 *no_carry = code->cur - (no_carry + 1); 1239 break;
1137 //TODO: Implement half-carry flag 1240 }
1138 break;
1139 case Z80_CPL: 1241 case Z80_CPL:
1140 cycles(&opts->gen, num_cycles); 1242 cycles(&opts->gen, num_cycles);
1141 not_r(code, opts->regs[Z80_A], SZ_B); 1243 not_r(code, opts->regs[Z80_A], SZ_B);
1142 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); 1244 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1143 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); 1245 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);