Mercurial > repos > blastem
comparison z80_to_x86.c @ 730:38e9bee03749
More bugfixes for the 32-bit build of the Z80 core
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 24 May 2015 15:05:18 -0700 |
parents | 9ef6db986982 |
children | 0835cd3dfc36 |
comparison
equal
deleted
inserted
replaced
729:9ef6db986982 | 730:38e9bee03749 |
---|---|
107 } | 107 } |
108 | 108 |
109 void translate_z80_ea(z80inst * inst, host_ea * ea, z80_options * opts, uint8_t read, uint8_t modify) | 109 void translate_z80_ea(z80inst * inst, host_ea * ea, z80_options * opts, uint8_t read, uint8_t modify) |
110 { | 110 { |
111 code_info *code = &opts->gen.code; | 111 code_info *code = &opts->gen.code; |
112 uint8_t size, reg, areg; | 112 uint8_t size, areg; |
113 int8_t reg; | |
113 ea->mode = MODE_REG_DIRECT; | 114 ea->mode = MODE_REG_DIRECT; |
114 areg = read ? opts->gen.scratch1 : opts->gen.scratch2; | 115 areg = read ? opts->gen.scratch1 : opts->gen.scratch2; |
115 switch(inst->addr_mode & 0x1F) | 116 switch(inst->addr_mode & 0x1F) |
116 { | 117 { |
117 case Z80_REG: | 118 case Z80_REG: |
395 mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); | 396 mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size); |
396 } else { | 397 } else { |
397 mov_rr(code, src_op.base, dst_op.base, size); | 398 mov_rr(code, src_op.base, dst_op.base, size); |
398 } | 399 } |
399 } else if(src_op.mode == MODE_IMMED) { | 400 } else if(src_op.mode == MODE_IMMED) { |
400 mov_ir(code, src_op.disp, dst_op.base, size); | 401 if(dst_op.mode == MODE_REG_DISPLACE8) { |
401 } else { | 402 mov_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size); |
402 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size); | 403 } else { |
404 mov_ir(code, src_op.disp, dst_op.base, size); | |
405 } | |
406 } else { | |
407 if(dst_op.mode == MODE_REG_DISPLACE8) { | |
408 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, size); | |
409 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, size); | |
410 } else { | |
411 mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size); | |
412 } | |
403 } | 413 } |
404 if (inst->ea_reg == Z80_I && inst->addr_mode == Z80_REG) { | 414 if (inst->ea_reg == Z80_I && inst->addr_mode == Z80_REG) { |
405 //ld a, i sets some flags | 415 //ld a, i sets some flags |
406 //TODO: Implement half-carry flag | 416 //TODO: Implement half-carry flag |
407 cmp_ir(code, 0, dst_op.base, SZ_B); | 417 cmp_ir(code, 0, dst_op.base, SZ_B); |
694 num_cycles += 4; | 704 num_cycles += 4; |
695 } | 705 } |
696 cycles(&opts->gen, num_cycles); | 706 cycles(&opts->gen, num_cycles); |
697 translate_z80_reg(inst, &dst_op, opts); | 707 translate_z80_reg(inst, &dst_op, opts); |
698 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 708 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
699 if (src_op.mode == MODE_REG_DIRECT) { | 709 if (dst_op.mode == MODE_REG_DIRECT) { |
700 add_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 710 if (src_op.mode == MODE_REG_DIRECT) { |
701 } else { | 711 add_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
702 add_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 712 } else if (src_op.mode == MODE_IMMED) { |
713 add_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | |
714 } else { | |
715 add_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
716 } | |
717 } else { | |
718 if (src_op.mode == MODE_REG_DIRECT) { | |
719 add_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); | |
720 } else if (src_op.mode == MODE_IMMED) { | |
721 add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst)); | |
722 } else { | |
723 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); | |
724 add_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); | |
725 } | |
703 } | 726 } |
704 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 727 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
705 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 728 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
706 //TODO: Implement half-carry flag | 729 //TODO: Implement half-carry flag |
707 if (z80_size(inst) == SZ_B) { | 730 if (z80_size(inst) == SZ_B) { |
723 } | 746 } |
724 cycles(&opts->gen, num_cycles); | 747 cycles(&opts->gen, num_cycles); |
725 translate_z80_reg(inst, &dst_op, opts); | 748 translate_z80_reg(inst, &dst_op, opts); |
726 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 749 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
727 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 750 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
728 if (src_op.mode == MODE_REG_DIRECT) { | 751 if (dst_op.mode == MODE_REG_DIRECT) { |
729 adc_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 752 if (src_op.mode == MODE_REG_DIRECT) { |
730 } else { | 753 adc_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
731 adc_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 754 } else if (src_op.mode == MODE_IMMED) { |
755 adc_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | |
756 } else { | |
757 adc_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
758 } | |
759 } else { | |
760 if (src_op.mode == MODE_REG_DIRECT) { | |
761 adc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); | |
762 } else if (src_op.mode == MODE_IMMED) { | |
763 adc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst)); | |
764 } else { | |
765 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); | |
766 adc_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); | |
767 } | |
732 } | 768 } |
733 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 769 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
734 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 770 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
735 //TODO: Implement half-carry flag | 771 //TODO: Implement half-carry flag |
736 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 772 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
747 num_cycles += 3; | 783 num_cycles += 3; |
748 } | 784 } |
749 cycles(&opts->gen, num_cycles); | 785 cycles(&opts->gen, num_cycles); |
750 translate_z80_reg(inst, &dst_op, opts); | 786 translate_z80_reg(inst, &dst_op, opts); |
751 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 787 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
752 if (src_op.mode == MODE_REG_DIRECT) { | 788 if (dst_op.mode == MODE_REG_DIRECT) { |
753 sub_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 789 if (src_op.mode == MODE_REG_DIRECT) { |
754 } else { | 790 sub_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
755 sub_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 791 } else if (src_op.mode == MODE_IMMED) { |
792 sub_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | |
793 } else { | |
794 sub_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
795 } | |
796 } else { | |
797 if (src_op.mode == MODE_REG_DIRECT) { | |
798 sub_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); | |
799 } else if (src_op.mode == MODE_IMMED) { | |
800 sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst)); | |
801 } else { | |
802 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); | |
803 sub_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); | |
804 } | |
756 } | 805 } |
757 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 806 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
758 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 807 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
759 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 808 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
760 //TODO: Implement half-carry flag | 809 //TODO: Implement half-carry flag |
774 } | 823 } |
775 cycles(&opts->gen, num_cycles); | 824 cycles(&opts->gen, num_cycles); |
776 translate_z80_reg(inst, &dst_op, opts); | 825 translate_z80_reg(inst, &dst_op, opts); |
777 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 826 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
778 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 827 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
779 if (src_op.mode == MODE_REG_DIRECT) { | 828 if (dst_op.mode == MODE_REG_DIRECT) { |
780 sbb_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 829 if (src_op.mode == MODE_REG_DIRECT) { |
781 } else { | 830 sbb_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
782 sbb_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 831 } else if (src_op.mode == MODE_IMMED) { |
832 sbb_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | |
833 } else { | |
834 sbb_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
835 } | |
836 } else { | |
837 if (src_op.mode == MODE_REG_DIRECT) { | |
838 sbb_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst)); | |
839 } else if (src_op.mode == MODE_IMMED) { | |
840 sbb_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst)); | |
841 } else { | |
842 mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst)); | |
843 sbb_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst)); | |
844 } | |
783 } | 845 } |
784 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 846 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
785 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 847 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
786 //TODO: Implement half-carry flag | 848 //TODO: Implement half-carry flag |
787 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 849 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
802 cycles(&opts->gen, num_cycles); | 864 cycles(&opts->gen, num_cycles); |
803 translate_z80_reg(inst, &dst_op, opts); | 865 translate_z80_reg(inst, &dst_op, opts); |
804 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 866 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
805 if (src_op.mode == MODE_REG_DIRECT) { | 867 if (src_op.mode == MODE_REG_DIRECT) { |
806 and_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 868 and_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
807 } else { | 869 } else if (src_op.mode == MODE_IMMED) { |
808 and_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 870 and_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
871 } else { | |
872 and_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
809 } | 873 } |
810 //TODO: Cleanup flags | 874 //TODO: Cleanup flags |
811 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 875 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
812 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 876 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
813 //TODO: Implement half-carry flag | 877 //TODO: Implement half-carry flag |
831 cycles(&opts->gen, num_cycles); | 895 cycles(&opts->gen, num_cycles); |
832 translate_z80_reg(inst, &dst_op, opts); | 896 translate_z80_reg(inst, &dst_op, opts); |
833 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 897 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
834 if (src_op.mode == MODE_REG_DIRECT) { | 898 if (src_op.mode == MODE_REG_DIRECT) { |
835 or_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 899 or_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
836 } else { | 900 } else if (src_op.mode == MODE_IMMED) { |
837 or_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 901 or_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
902 } else { | |
903 or_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
838 } | 904 } |
839 //TODO: Cleanup flags | 905 //TODO: Cleanup flags |
840 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 906 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
841 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 907 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
842 //TODO: Implement half-carry flag | 908 //TODO: Implement half-carry flag |
860 cycles(&opts->gen, num_cycles); | 926 cycles(&opts->gen, num_cycles); |
861 translate_z80_reg(inst, &dst_op, opts); | 927 translate_z80_reg(inst, &dst_op, opts); |
862 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 928 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
863 if (src_op.mode == MODE_REG_DIRECT) { | 929 if (src_op.mode == MODE_REG_DIRECT) { |
864 xor_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 930 xor_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
865 } else { | 931 } else if (src_op.mode == MODE_IMMED) { |
866 xor_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 932 xor_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
933 } else { | |
934 xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
867 } | 935 } |
868 //TODO: Cleanup flags | 936 //TODO: Cleanup flags |
869 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 937 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
870 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 938 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
871 //TODO: Implement half-carry flag | 939 //TODO: Implement half-carry flag |
887 cycles(&opts->gen, num_cycles); | 955 cycles(&opts->gen, num_cycles); |
888 translate_z80_reg(inst, &dst_op, opts); | 956 translate_z80_reg(inst, &dst_op, opts); |
889 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); | 957 translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY); |
890 if (src_op.mode == MODE_REG_DIRECT) { | 958 if (src_op.mode == MODE_REG_DIRECT) { |
891 cmp_rr(code, src_op.base, dst_op.base, z80_size(inst)); | 959 cmp_rr(code, src_op.base, dst_op.base, z80_size(inst)); |
892 } else { | 960 } else if (src_op.mode == MODE_IMMED) { |
893 cmp_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 961 cmp_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
962 } else { | |
963 cmp_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | |
894 } | 964 } |
895 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 965 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
896 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 966 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
897 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 967 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
898 //TODO: Implement half-carry flag | 968 //TODO: Implement half-carry flag |
913 cycles(&opts->gen, num_cycles); | 983 cycles(&opts->gen, num_cycles); |
914 translate_z80_reg(inst, &dst_op, opts); | 984 translate_z80_reg(inst, &dst_op, opts); |
915 if (dst_op.mode == MODE_UNUSED) { | 985 if (dst_op.mode == MODE_UNUSED) { |
916 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); | 986 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); |
917 } | 987 } |
918 add_ir(code, 1, dst_op.base, z80_size(inst)); | 988 if (dst_op.mode == MODE_REG_DIRECT) { |
989 add_ir(code, 1, dst_op.base, z80_size(inst)); | |
990 } else { | |
991 add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); | |
992 } | |
919 if (z80_size(inst) == SZ_B) { | 993 if (z80_size(inst) == SZ_B) { |
920 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 994 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
921 //TODO: Implement half-carry flag | 995 //TODO: Implement half-carry flag |
922 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 996 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
923 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 997 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
939 cycles(&opts->gen, num_cycles); | 1013 cycles(&opts->gen, num_cycles); |
940 translate_z80_reg(inst, &dst_op, opts); | 1014 translate_z80_reg(inst, &dst_op, opts); |
941 if (dst_op.mode == MODE_UNUSED) { | 1015 if (dst_op.mode == MODE_UNUSED) { |
942 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); | 1016 translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); |
943 } | 1017 } |
944 sub_ir(code, 1, dst_op.base, z80_size(inst)); | 1018 if (dst_op.mode == MODE_REG_DIRECT) { |
1019 sub_ir(code, 1, dst_op.base, z80_size(inst)); | |
1020 } else { | |
1021 sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst)); | |
1022 } | |
1023 | |
945 if (z80_size(inst) == SZ_B) { | 1024 if (z80_size(inst) == SZ_B) { |
946 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1025 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
947 //TODO: Implement half-carry flag | 1026 //TODO: Implement half-carry flag |
948 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 1027 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
949 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1028 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1027 cycles(&opts->gen, 1); | 1106 cycles(&opts->gen, 1); |
1028 } else { | 1107 } else { |
1029 src_op.mode = MODE_UNUSED; | 1108 src_op.mode = MODE_UNUSED; |
1030 translate_z80_reg(inst, &dst_op, opts); | 1109 translate_z80_reg(inst, &dst_op, opts); |
1031 } | 1110 } |
1032 rol_ir(code, 1, dst_op.base, SZ_B); | 1111 if (dst_op.mode == MODE_REG_DIRECT) { |
1033 if (src_op.mode != MODE_UNUSED) { | 1112 rol_ir(code, 1, dst_op.base, SZ_B); |
1113 } else { | |
1114 rol_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1115 } | |
1116 if (src_op.mode == MODE_REG_DIRECT) { | |
1034 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1117 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1118 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1119 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1035 } | 1120 } |
1036 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1121 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1037 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1122 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1038 //TODO: Implement half-carry flag | 1123 //TODO: Implement half-carry flag |
1039 if (inst->immed) { | 1124 if (inst->immed) { |
1040 //rlca does not set these flags | 1125 //rlca does not set these flags |
1041 cmp_ir(code, 0, dst_op.base, SZ_B); | 1126 cmp_ir(code, 0, dst_op.base, SZ_B); |
1042 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1127 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1043 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1128 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1044 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1129 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1045 } | 1130 } |
1046 if (inst->addr_mode != Z80_UNUSED) { | 1131 if (inst->addr_mode != Z80_UNUSED) { |
1047 z80_save_result(opts, inst); | 1132 z80_save_result(opts, inst); |
1048 if (src_op.mode != MODE_UNUSED) { | 1133 if (src_op.mode != MODE_UNUSED) { |
1049 z80_save_reg(inst, opts); | 1134 z80_save_reg(inst, opts); |
1062 } else { | 1147 } else { |
1063 src_op.mode = MODE_UNUSED; | 1148 src_op.mode = MODE_UNUSED; |
1064 translate_z80_reg(inst, &dst_op, opts); | 1149 translate_z80_reg(inst, &dst_op, opts); |
1065 } | 1150 } |
1066 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1151 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
1067 rcl_ir(code, 1, dst_op.base, SZ_B); | 1152 if (dst_op.mode == MODE_REG_DIRECT) { |
1068 if (src_op.mode != MODE_UNUSED) { | 1153 rcl_ir(code, 1, dst_op.base, SZ_B); |
1154 } else { | |
1155 rcl_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1156 } | |
1157 if (src_op.mode == MODE_REG_DIRECT) { | |
1069 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1158 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1159 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1160 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1070 } | 1161 } |
1071 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1162 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1072 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1163 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1073 //TODO: Implement half-carry flag | 1164 //TODO: Implement half-carry flag |
1074 if (inst->immed) { | 1165 if (inst->immed) { |
1075 //rla does not set these flags | 1166 //rla does not set these flags |
1076 cmp_ir(code, 0, dst_op.base, SZ_B); | 1167 cmp_ir(code, 0, dst_op.base, SZ_B); |
1077 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1168 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1078 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1169 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1079 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1170 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1080 } | 1171 } |
1081 if (inst->addr_mode != Z80_UNUSED) { | 1172 if (inst->addr_mode != Z80_UNUSED) { |
1082 z80_save_result(opts, inst); | 1173 z80_save_result(opts, inst); |
1083 if (src_op.mode != MODE_UNUSED) { | 1174 if (src_op.mode != MODE_UNUSED) { |
1084 z80_save_reg(inst, opts); | 1175 z80_save_reg(inst, opts); |
1096 cycles(&opts->gen, 1); | 1187 cycles(&opts->gen, 1); |
1097 } else { | 1188 } else { |
1098 src_op.mode = MODE_UNUSED; | 1189 src_op.mode = MODE_UNUSED; |
1099 translate_z80_reg(inst, &dst_op, opts); | 1190 translate_z80_reg(inst, &dst_op, opts); |
1100 } | 1191 } |
1101 ror_ir(code, 1, dst_op.base, SZ_B); | 1192 if (dst_op.mode == MODE_REG_DIRECT) { |
1102 if (src_op.mode != MODE_UNUSED) { | 1193 ror_ir(code, 1, dst_op.base, SZ_B); |
1194 } else { | |
1195 ror_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1196 } | |
1197 if (src_op.mode == MODE_REG_DIRECT) { | |
1103 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1198 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1199 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1200 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1104 } | 1201 } |
1105 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1202 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1106 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1203 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1107 //TODO: Implement half-carry flag | 1204 //TODO: Implement half-carry flag |
1108 if (inst->immed) { | 1205 if (inst->immed) { |
1109 //rrca does not set these flags | 1206 //rrca does not set these flags |
1110 cmp_ir(code, 0, dst_op.base, SZ_B); | 1207 cmp_ir(code, 0, dst_op.base, SZ_B); |
1111 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1208 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1112 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1209 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1113 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1210 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1114 } | 1211 } |
1115 if (inst->addr_mode != Z80_UNUSED) { | 1212 if (inst->addr_mode != Z80_UNUSED) { |
1116 z80_save_result(opts, inst); | 1213 z80_save_result(opts, inst); |
1117 if (src_op.mode != MODE_UNUSED) { | 1214 if (src_op.mode != MODE_UNUSED) { |
1118 z80_save_reg(inst, opts); | 1215 z80_save_reg(inst, opts); |
1131 } else { | 1228 } else { |
1132 src_op.mode = MODE_UNUSED; | 1229 src_op.mode = MODE_UNUSED; |
1133 translate_z80_reg(inst, &dst_op, opts); | 1230 translate_z80_reg(inst, &dst_op, opts); |
1134 } | 1231 } |
1135 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1232 bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
1136 rcr_ir(code, 1, dst_op.base, SZ_B); | 1233 if (dst_op.mode == MODE_REG_DIRECT) { |
1137 if (src_op.mode != MODE_UNUSED) { | 1234 rcr_ir(code, 1, dst_op.base, SZ_B); |
1235 } else { | |
1236 rcr_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1237 } | |
1238 if (src_op.mode == MODE_REG_DIRECT) { | |
1138 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1239 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1240 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1241 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1139 } | 1242 } |
1140 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1243 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1141 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1244 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1142 //TODO: Implement half-carry flag | 1245 //TODO: Implement half-carry flag |
1143 if (inst->immed) { | 1246 if (inst->immed) { |
1144 //rra does not set these flags | 1247 //rra does not set these flags |
1145 cmp_ir(code, 0, dst_op.base, SZ_B); | 1248 cmp_ir(code, 0, dst_op.base, SZ_B); |
1146 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1249 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1147 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1250 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1148 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1251 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1149 } | 1252 } |
1150 if (inst->addr_mode != Z80_UNUSED) { | 1253 if (inst->addr_mode != Z80_UNUSED) { |
1151 z80_save_result(opts, inst); | 1254 z80_save_result(opts, inst); |
1152 if (src_op.mode != MODE_UNUSED) { | 1255 if (src_op.mode != MODE_UNUSED) { |
1153 z80_save_reg(inst, opts); | 1256 z80_save_reg(inst, opts); |
1166 cycles(&opts->gen, 1); | 1269 cycles(&opts->gen, 1); |
1167 } else { | 1270 } else { |
1168 src_op.mode = MODE_UNUSED; | 1271 src_op.mode = MODE_UNUSED; |
1169 translate_z80_reg(inst, &dst_op, opts); | 1272 translate_z80_reg(inst, &dst_op, opts); |
1170 } | 1273 } |
1171 shl_ir(code, 1, dst_op.base, SZ_B); | 1274 if (dst_op.mode == MODE_REG_DIRECT) { |
1275 shl_ir(code, 1, dst_op.base, SZ_B); | |
1276 } else { | |
1277 shl_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1278 } | |
1172 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1279 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1173 if (inst->op == Z80_SLL) { | 1280 if (inst->op == Z80_SLL) { |
1174 or_ir(code, 1, dst_op.base, SZ_B); | 1281 or_ir(code, 1, dst_op.base, SZ_B); |
1175 } | 1282 } |
1176 if (src_op.mode != MODE_UNUSED) { | 1283 if (src_op.mode == MODE_REG_DIRECT) { |
1177 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1284 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1285 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1286 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1178 } | 1287 } |
1179 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1288 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1180 //TODO: Implement half-carry flag | 1289 //TODO: Implement half-carry flag |
1181 cmp_ir(code, 0, dst_op.base, SZ_B); | 1290 cmp_ir(code, 0, dst_op.base, SZ_B); |
1182 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1291 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1200 cycles(&opts->gen, 1); | 1309 cycles(&opts->gen, 1); |
1201 } else { | 1310 } else { |
1202 src_op.mode = MODE_UNUSED; | 1311 src_op.mode = MODE_UNUSED; |
1203 translate_z80_reg(inst, &dst_op, opts); | 1312 translate_z80_reg(inst, &dst_op, opts); |
1204 } | 1313 } |
1205 sar_ir(code, 1, dst_op.base, SZ_B); | 1314 if (dst_op.mode == MODE_REG_DIRECT) { |
1206 if (src_op.mode != MODE_UNUSED) { | 1315 sar_ir(code, 1, dst_op.base, SZ_B); |
1316 } else { | |
1317 sar_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1318 } | |
1319 if (src_op.mode == MODE_REG_DIRECT) { | |
1207 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1320 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1321 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1322 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1208 } | 1323 } |
1209 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1324 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1210 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1325 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1211 //TODO: Implement half-carry flag | 1326 //TODO: Implement half-carry flag |
1212 cmp_ir(code, 0, dst_op.base, SZ_B); | 1327 cmp_ir(code, 0, dst_op.base, SZ_B); |
1231 cycles(&opts->gen, 1); | 1346 cycles(&opts->gen, 1); |
1232 } else { | 1347 } else { |
1233 src_op.mode = MODE_UNUSED; | 1348 src_op.mode = MODE_UNUSED; |
1234 translate_z80_reg(inst, &dst_op, opts); | 1349 translate_z80_reg(inst, &dst_op, opts); |
1235 } | 1350 } |
1236 shr_ir(code, 1, dst_op.base, SZ_B); | 1351 if (dst_op.mode == MODE_REG_DIRECT) { |
1237 if (src_op.mode != MODE_UNUSED) { | 1352 shr_ir(code, 1, dst_op.base, SZ_B); |
1353 } else { | |
1354 shr_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B); | |
1355 } | |
1356 if (src_op.mode == MODE_REG_DIRECT) { | |
1238 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1357 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1358 } else if(src_op.mode == MODE_REG_DISPLACE8) { | |
1359 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | |
1239 } | 1360 } |
1240 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1361 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1241 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1362 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1242 //TODO: Implement half-carry flag | 1363 //TODO: Implement half-carry flag |
1243 cmp_ir(code, 0, dst_op.base, SZ_B); | 1364 cmp_ir(code, 0, dst_op.base, SZ_B); |
1540 *no_jump_off = code->cur - (no_jump_off+1); | 1661 *no_jump_off = code->cur - (no_jump_off+1); |
1541 break; | 1662 break; |
1542 } | 1663 } |
1543 case Z80_DJNZ: { | 1664 case Z80_DJNZ: { |
1544 cycles(&opts->gen, 8);//T States: 5,3 | 1665 cycles(&opts->gen, 8);//T States: 5,3 |
1545 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | 1666 if (opts->regs[Z80_B] >= 0) { |
1667 sub_ir(code, 1, opts->regs[Z80_B], SZ_B); | |
1668 } else { | |
1669 sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B); | |
1670 } | |
1546 uint8_t *no_jump_off = code->cur+1; | 1671 uint8_t *no_jump_off = code->cur+1; |
1547 jcc(code, CC_Z, code->cur+2); | 1672 jcc(code, CC_Z, code->cur+2); |
1548 cycles(&opts->gen, 5);//T States: 5 | 1673 cycles(&opts->gen, 5);//T States: 5 |
1549 uint16_t dest_addr = address + inst->immed + 2; | 1674 uint16_t dest_addr = address + inst->immed + 2; |
1550 code_ptr call_dst = z80_get_native_address(context, dest_addr); | 1675 code_ptr call_dst = z80_get_native_address(context, dest_addr); |
2309 options->retrans_stub = code->cur; | 2434 options->retrans_stub = code->cur; |
2310 //pop return address | 2435 //pop return address |
2311 pop_r(code, options->gen.scratch2); | 2436 pop_r(code, options->gen.scratch2); |
2312 call(code, options->gen.save_context); | 2437 call(code, options->gen.save_context); |
2313 //adjust pointer before move and call instructions that got us here | 2438 //adjust pointer before move and call instructions that got us here |
2314 sub_ir(code, 11, options->gen.scratch2, SZ_PTR); | 2439 sub_ir(code, options->gen.scratch1 >= R8 ? 11 : 10, options->gen.scratch2, SZ_PTR); |
2315 push_r(code, options->gen.context_reg); | 2440 push_r(code, options->gen.context_reg); |
2316 call_args(code, (code_ptr)z80_retranslate_inst, 3, options->gen.scratch1, options->gen.context_reg, options->gen.scratch2); | 2441 call_args(code, (code_ptr)z80_retranslate_inst, 3, options->gen.scratch1, options->gen.context_reg, options->gen.scratch2); |
2317 pop_r(code, options->gen.context_reg); | 2442 pop_r(code, options->gen.context_reg); |
2318 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); | 2443 mov_rr(code, RAX, options->gen.scratch1, SZ_PTR); |
2319 call(code, options->gen.load_context); | 2444 call(code, options->gen.load_context); |