Mercurial > repos > blastem
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); |