Mercurial > repos > blastem
comparison z80_to_x86.c @ 1042:a6c6b621d0dc
Implement Z80 DAA. Implement half-carry flag for the rest of the "easy" cases. Implement flags for IN instruction. Fix implementation of IN for IN F, (C) case
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 24 Jul 2016 17:17:59 -0700 |
parents | fbfb821e92a8 |
children | 3980ef0f6307 |
comparison
equal
deleted
inserted
replaced
1041:70338a4a9889 | 1042:a6c6b621d0dc |
---|---|
860 } else if (src_op.mode == MODE_IMMED) { | 860 } else if (src_op.mode == MODE_IMMED) { |
861 and_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 861 and_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
862 } else { | 862 } else { |
863 and_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | 863 and_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); |
864 } | 864 } |
865 //TODO: Cleanup flags | |
866 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
867 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 865 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
868 //TODO: Implement half-carry flag | 866 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
869 if (z80_size(inst) == SZ_B) { | 867 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
870 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 868 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
871 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 869 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
872 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 870 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
873 } | |
874 z80_save_reg(inst, opts); | 871 z80_save_reg(inst, opts); |
875 z80_save_ea(code, inst, opts); | 872 z80_save_ea(code, inst, opts); |
876 break; | 873 break; |
877 case Z80_OR: | 874 case Z80_OR: |
878 num_cycles = 4; | 875 num_cycles = 4; |
891 } else if (src_op.mode == MODE_IMMED) { | 888 } else if (src_op.mode == MODE_IMMED) { |
892 or_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 889 or_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
893 } else { | 890 } else { |
894 or_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | 891 or_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); |
895 } | 892 } |
896 //TODO: Cleanup flags | |
897 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
898 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); |
899 //TODO: Implement half-carry flag | 894 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
900 if (z80_size(inst) == SZ_B) { | 895 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
901 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 896 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
902 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 897 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
903 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 898 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
904 } | |
905 z80_save_reg(inst, opts); | 899 z80_save_reg(inst, opts); |
906 z80_save_ea(code, inst, opts); | 900 z80_save_ea(code, inst, opts); |
907 break; | 901 break; |
908 case Z80_XOR: | 902 case Z80_XOR: |
909 num_cycles = 4; | 903 num_cycles = 4; |
922 } else if (src_op.mode == MODE_IMMED) { | 916 } else if (src_op.mode == MODE_IMMED) { |
923 xor_ir(code, src_op.disp, dst_op.base, z80_size(inst)); | 917 xor_ir(code, src_op.disp, dst_op.base, z80_size(inst)); |
924 } else { | 918 } else { |
925 xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); | 919 xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst)); |
926 } | 920 } |
927 //TODO: Cleanup flags | |
928 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | |
929 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 921 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
930 //TODO: Implement half-carry flag | 922 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
931 if (z80_size(inst) == SZ_B) { | 923 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
932 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 924 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
933 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 925 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
934 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 926 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
935 } | |
936 z80_save_reg(inst, opts); | 927 z80_save_reg(inst, opts); |
937 z80_save_ea(code, inst, opts); | 928 z80_save_ea(code, inst, opts); |
938 break; | 929 break; |
939 case Z80_CP: | 930 case Z80_CP: |
940 num_cycles = 4; | 931 num_cycles = 4; |
1021 } | 1012 } |
1022 z80_save_reg(inst, opts); | 1013 z80_save_reg(inst, opts); |
1023 z80_save_ea(code, inst, opts); | 1014 z80_save_ea(code, inst, opts); |
1024 z80_save_result(opts, inst); | 1015 z80_save_result(opts, inst); |
1025 break; | 1016 break; |
1026 //case Z80_DAA: | 1017 case Z80_DAA: |
1018 cycles(&opts->gen, 4); | |
1019 xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, SZ_B); | |
1020 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); | |
1021 code_ptr corf_low = code->cur+1; | |
1022 jcc(code, CC_NZ, code->cur+2); | |
1023 zreg_to_native(opts, Z80_A, opts->gen.scratch1); | |
1024 and_ir(code, 0xF, opts->gen.scratch1, SZ_B); | |
1025 cmp_ir(code, 0xA, opts->gen.scratch1, SZ_B); | |
1026 | |
1027 code_ptr no_corf_low = code->cur+1; | |
1028 jcc(code, CC_C, code->cur+2); | |
1029 *corf_low = code->cur - (corf_low + 1); | |
1030 mov_ir(code, 6, opts->gen.scratch2, SZ_B); | |
1031 //TODO: Deal with edge case of 9 in high nibble | |
1032 mov_ir(code, 0x90, opts->gen.scratch1, SZ_B); | |
1033 code_ptr after_cmp_set = code->cur+1; | |
1034 jmp(code, code->cur+2); | |
1035 | |
1036 *no_corf_low = code->cur - (no_corf_low + 1); | |
1037 mov_ir(code, 0xA0, opts->gen.scratch1, SZ_B); | |
1038 *after_cmp_set = code->cur - (after_cmp_set + 1); | |
1039 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | |
1040 code_ptr corf_high = code->cur+1; | |
1041 jcc(code, CC_NZ, code->cur+2); | |
1042 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); | |
1043 code_ptr no_corf_high = code->cur+1; | |
1044 jcc(code, CC_C, code->cur+2); | |
1045 *corf_high = code->cur - (corf_high + 1); | |
1046 or_ir(code, 0x60, opts->gen.scratch2, SZ_B); | |
1047 *no_corf_high = code->cur - (no_corf_high + 1); | |
1048 | |
1049 cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | |
1050 code_ptr not_sub = code->cur+1; | |
1051 jcc(code, CC_Z, code->cur+2); | |
1052 neg_r(code, opts->gen.scratch2, SZ_B); | |
1053 *not_sub = code->cur - (not_sub + 1); | |
1054 add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B); | |
1055 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
1056 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
1057 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | |
1058 code_ptr no_carry = code->cur+1; | |
1059 jcc(code, CC_NC, code->cur+2); | |
1060 mov_ir(code, 1, opts->gen.context_reg, zf_off(ZF_C)); | |
1061 *no_carry = code->cur - (no_carry + 1); | |
1062 //TODO: Implement half-carry flag | |
1063 break; | |
1027 case Z80_CPL: | 1064 case Z80_CPL: |
1028 cycles(&opts->gen, 4); | 1065 cycles(&opts->gen, 4); |
1029 not_r(code, opts->regs[Z80_A], SZ_B); | 1066 not_r(code, opts->regs[Z80_A], SZ_B); |
1030 //TODO: Implement half-carry flag | 1067 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1031 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1068 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1032 break; | 1069 break; |
1033 case Z80_NEG: | 1070 case Z80_NEG: |
1034 cycles(&opts->gen, 8); | 1071 cycles(&opts->gen, 8); |
1035 neg_r(code, opts->regs[Z80_A], SZ_B); | 1072 neg_r(code, opts->regs[Z80_A], SZ_B); |
1040 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); | 1077 setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV)); |
1041 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1078 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1042 break; | 1079 break; |
1043 case Z80_CCF: | 1080 case Z80_CCF: |
1044 cycles(&opts->gen, 4); | 1081 cycles(&opts->gen, 4); |
1082 mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); | |
1045 xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1083 xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
1046 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1084 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1047 //TODO: Implement half-carry flag | 1085 mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1048 break; | 1086 break; |
1049 case Z80_SCF: | 1087 case Z80_SCF: |
1050 cycles(&opts->gen, 4); | 1088 cycles(&opts->gen, 4); |
1051 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); | 1089 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); |
1052 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1090 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1053 //TODO: Implement half-carry flag | 1091 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1054 break; | 1092 break; |
1055 case Z80_NOP: | 1093 case Z80_NOP: |
1056 if (inst->immed == 42) { | 1094 if (inst->immed == 42) { |
1057 call(code, opts->gen.save_context); | 1095 call(code, opts->gen.save_context); |
1058 call_args(code, (code_ptr)z80_print_regs_exit, 1, opts->gen.context_reg); | 1096 call_args(code, (code_ptr)z80_print_regs_exit, 1, opts->gen.context_reg); |
1109 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1147 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1110 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1148 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1111 } | 1149 } |
1112 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1150 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1113 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1151 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1114 //TODO: Implement half-carry flag | 1152 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1115 if (inst->immed) { | 1153 if (inst->immed) { |
1116 //rlca does not set these flags | 1154 //rlca does not set these flags |
1117 if (dst_op.mode == MODE_REG_DIRECT) { | 1155 if (dst_op.mode == MODE_REG_DIRECT) { |
1118 cmp_ir(code, 0, dst_op.base, SZ_B); | 1156 cmp_ir(code, 0, dst_op.base, SZ_B); |
1119 } else { | 1157 } else { |
1154 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1192 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1155 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1193 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1156 } | 1194 } |
1157 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1195 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1158 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1196 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1159 //TODO: Implement half-carry flag | 1197 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1160 if (inst->immed) { | 1198 if (inst->immed) { |
1161 //rla does not set these flags | 1199 //rla does not set these flags |
1162 if (dst_op.mode == MODE_REG_DIRECT) { | 1200 if (dst_op.mode == MODE_REG_DIRECT) { |
1163 cmp_ir(code, 0, dst_op.base, SZ_B); | 1201 cmp_ir(code, 0, dst_op.base, SZ_B); |
1164 } else { | 1202 } else { |
1198 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1236 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1199 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1237 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1200 } | 1238 } |
1201 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1239 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1202 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1240 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1203 //TODO: Implement half-carry flag | 1241 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1204 if (inst->immed) { | 1242 if (inst->immed) { |
1205 //rrca does not set these flags | 1243 //rrca does not set these flags |
1206 if (dst_op.mode == MODE_REG_DIRECT) { | 1244 if (dst_op.mode == MODE_REG_DIRECT) { |
1207 cmp_ir(code, 0, dst_op.base, SZ_B); | 1245 cmp_ir(code, 0, dst_op.base, SZ_B); |
1208 } else { | 1246 } else { |
1243 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1281 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1244 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1282 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1245 } | 1283 } |
1246 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1284 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1247 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1285 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1248 //TODO: Implement half-carry flag | 1286 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1249 if (inst->immed) { | 1287 if (inst->immed) { |
1250 //rra does not set these flags | 1288 //rra does not set these flags |
1251 if (dst_op.mode == MODE_REG_DIRECT) { | 1289 if (dst_op.mode == MODE_REG_DIRECT) { |
1252 cmp_ir(code, 0, dst_op.base, SZ_B); | 1290 cmp_ir(code, 0, dst_op.base, SZ_B); |
1253 } else { | 1291 } else { |
1295 mov_rr(code, dst_op.base, src_op.base, SZ_B); | 1333 mov_rr(code, dst_op.base, src_op.base, SZ_B); |
1296 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1334 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1297 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1335 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1298 } | 1336 } |
1299 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1337 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1300 //TODO: Implement half-carry flag | 1338 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1301 if (dst_op.mode == MODE_REG_DIRECT) { | 1339 if (dst_op.mode == MODE_REG_DIRECT) { |
1302 cmp_ir(code, 0, dst_op.base, SZ_B); | 1340 cmp_ir(code, 0, dst_op.base, SZ_B); |
1303 } else { | 1341 } else { |
1304 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); | 1342 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); |
1305 } | 1343 } |
1336 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1374 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1337 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1375 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1338 } | 1376 } |
1339 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1377 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1340 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1378 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1341 //TODO: Implement half-carry flag | 1379 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1342 if (dst_op.mode == MODE_REG_DIRECT) { | 1380 if (dst_op.mode == MODE_REG_DIRECT) { |
1343 cmp_ir(code, 0, dst_op.base, SZ_B); | 1381 cmp_ir(code, 0, dst_op.base, SZ_B); |
1344 } else { | 1382 } else { |
1345 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); | 1383 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); |
1346 } | 1384 } |
1377 } else if(src_op.mode == MODE_REG_DISPLACE8) { | 1415 } else if(src_op.mode == MODE_REG_DISPLACE8) { |
1378 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); | 1416 mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B); |
1379 } | 1417 } |
1380 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); | 1418 setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C)); |
1381 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1419 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1382 //TODO: Implement half-carry flag | 1420 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1383 if (dst_op.mode == MODE_REG_DIRECT) { | 1421 if (dst_op.mode == MODE_REG_DIRECT) { |
1384 cmp_ir(code, 0, dst_op.base, SZ_B); | 1422 cmp_ir(code, 0, dst_op.base, SZ_B); |
1385 } else { | 1423 } else { |
1386 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); | 1424 cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B); |
1387 } | 1425 } |
1412 //opts->gen.scratch1 = 0x0124 | 1450 //opts->gen.scratch1 = 0x0124 |
1413 ror_ir(code, 8, opts->gen.scratch1, SZ_W); | 1451 ror_ir(code, 8, opts->gen.scratch1, SZ_W); |
1414 cycles(&opts->gen, 4); | 1452 cycles(&opts->gen, 4); |
1415 or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); | 1453 or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); |
1416 //set flags | 1454 //set flags |
1417 //TODO: Implement half-carry flag | 1455 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1418 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1456 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1419 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1457 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1420 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1458 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1421 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1459 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1422 | 1460 |
1443 ror_ir(code, 8, opts->gen.scratch1, SZ_W); | 1481 ror_ir(code, 8, opts->gen.scratch1, SZ_W); |
1444 cycles(&opts->gen, 4); | 1482 cycles(&opts->gen, 4); |
1445 shr_ir(code, 4, opts->gen.scratch1, SZ_B); | 1483 shr_ir(code, 4, opts->gen.scratch1, SZ_B); |
1446 or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); | 1484 or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); |
1447 //set flags | 1485 //set flags |
1448 //TODO: Implement half-carry flag | 1486 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1449 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1487 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1450 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); | 1488 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1451 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | 1489 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); |
1452 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | 1490 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); |
1453 | 1491 |
1479 bt_irdisp(code, bit, src_op.base, src_op.disp, size); | 1517 bt_irdisp(code, bit, src_op.base, src_op.disp, size); |
1480 } | 1518 } |
1481 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_Z)); | 1519 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_Z)); |
1482 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_PV)); | 1520 setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_PV)); |
1483 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); | 1521 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1522 mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); | |
1484 if (inst->immed == 7) { | 1523 if (inst->immed == 7) { |
1485 if (src_op.mode == MODE_REG_DIRECT) { | 1524 if (src_op.mode == MODE_REG_DIRECT) { |
1486 cmp_ir(code, 0, src_op.base, size); | 1525 cmp_ir(code, 0, src_op.base, size); |
1487 } else { | 1526 } else { |
1488 cmp_irdisp(code, 0, src_op.base, src_op.disp, size); | 1527 cmp_irdisp(code, 0, src_op.base, src_op.disp, size); |
1893 } | 1932 } |
1894 jmp(code, call_dst); | 1933 jmp(code, call_dst); |
1895 break; | 1934 break; |
1896 } | 1935 } |
1897 case Z80_IN: | 1936 case Z80_IN: |
1898 cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 | 1937 cycles(&opts->gen, inst->reg == inst->addr_mode == Z80_IMMED_INDIRECT ? 7 : 8);//T States: 4 3/4 |
1899 if (inst->addr_mode == Z80_IMMED_INDIRECT) { | 1938 if (inst->addr_mode == Z80_IMMED_INDIRECT) { |
1900 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B); | 1939 mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B); |
1901 } else { | 1940 } else { |
1902 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); | 1941 mov_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B); |
1903 } | 1942 } |
1904 call(code, opts->read_io); | 1943 call(code, opts->read_io); |
1905 translate_z80_reg(inst, &dst_op, opts); | 1944 if (inst->addr_mode != Z80_IMMED_INDIRECT) { |
1906 if (dst_op.mode == MODE_REG_DIRECT) { | 1945 or_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B); |
1907 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); | 1946 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); |
1908 } else { | 1947 mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); |
1909 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B); | 1948 setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV)); |
1949 setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); | |
1950 setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S)); | |
1951 } | |
1952 if (inst->reg != Z80_UNUSED) { | |
1953 translate_z80_reg(inst, &dst_op, opts); | |
1954 if (dst_op.mode == MODE_REG_DIRECT) { | |
1955 mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B); | |
1956 } else { | |
1957 mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B); | |
1958 } | |
1910 } | 1959 } |
1911 z80_save_reg(inst, opts); | 1960 z80_save_reg(inst, opts); |
1912 break; | 1961 break; |
1913 /*case Z80_INI: | 1962 /*case Z80_INI: |
1914 case Z80_INIR: | 1963 case Z80_INIR: |