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);