Mercurial > repos > blastem
comparison 68kinst.c @ 1462:d276ec2fff11
More instruction decoder fixes
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 07 Sep 2017 00:42:28 -0700 |
parents | b81428ef0396 |
children | 63f309cfbef9 |
comparison
equal
deleted
inserted
replaced
1461:aa945f1bdd71 | 1462:d276ec2fff11 |
---|---|
267 } | 267 } |
268 | 268 |
269 uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst) | 269 uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst) |
270 { | 270 { |
271 if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) { | 271 if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) { |
272 return 0; | |
273 } | |
274 return 1; | |
275 } | |
276 | |
277 uint8_t m68k_valid_full_arith_dst(m68k_op_info *dst) | |
278 { | |
279 if (dst->addr_mode < MODE_AREG_INDIRECT || dst->addr_mode > MODE_ABSOLUTE) { | |
272 return 0; | 280 return 0; |
273 } | 281 } |
274 return 1; | 282 return 1; |
275 } | 283 } |
276 | 284 |
653 decoded->op = M68K_MOVE; | 661 decoded->op = M68K_MOVE; |
654 decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG); | 662 decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG); |
655 opmode = (*istream >> 6) & 0x7; | 663 opmode = (*istream >> 6) & 0x7; |
656 reg = m68k_reg_quick_field(*istream); | 664 reg = m68k_reg_quick_field(*istream); |
657 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 665 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
658 if (!istream) { | 666 if (!istream || (decoded->src.addr_mode == MODE_AREG && optype == MOVE_BYTE)) { |
659 decoded->op = M68K_INVALID; | 667 decoded->op = M68K_INVALID; |
660 break; | 668 break; |
661 } | 669 } |
662 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | 670 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
663 if (!istream || decoded->dst.addr_mode > MODE_ABSOLUTE || (decoded->dst.addr_mode == MODE_AREG && optype == MOVE_BYTE)) { | 671 if (!istream || decoded->dst.addr_mode > MODE_ABSOLUTE || (decoded->dst.addr_mode == MODE_AREG && optype == MOVE_BYTE)) { |
935 decoded->op = M68K_INVALID; | 943 decoded->op = M68K_INVALID; |
936 break; | 944 break; |
937 } | 945 } |
938 } else { | 946 } else { |
939 //it would appear bit 6 needs to be set for it to be a valid instruction here | 947 //it would appear bit 6 needs to be set for it to be a valid instruction here |
948 if (!(*istream & 0x40)) { | |
949 decoded->op = M68K_INVALID; | |
950 break; | |
951 } | |
940 switch((*istream >> 3) & 0x7) | 952 switch((*istream >> 3) & 0x7) |
941 { | 953 { |
942 case 0: | 954 case 0: |
943 case 1: | 955 case 1: |
944 //TRAP | 956 //TRAP |
1070 #endif | 1082 #endif |
1071 } else { | 1083 } else { |
1072 decoded->op = M68K_SCC; | 1084 decoded->op = M68K_SCC; |
1073 decoded->extra.cond = (*istream >> 8) & 0xF; | 1085 decoded->extra.cond = (*istream >> 8) & 0xF; |
1074 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); | 1086 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); |
1075 if (!istream) { | 1087 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) { |
1076 decoded->op = M68K_INVALID; | 1088 decoded->op = M68K_INVALID; |
1077 break; | 1089 break; |
1078 } | 1090 } |
1079 } | 1091 } |
1080 } else { | 1092 } else { |
1091 decoded->op = M68K_SUB; | 1103 decoded->op = M68K_SUB; |
1092 } else { | 1104 } else { |
1093 decoded->op = M68K_ADD; | 1105 decoded->op = M68K_ADD; |
1094 } | 1106 } |
1095 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1107 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
1096 if (!istream) { | 1108 if (!istream || decoded->dst.addr_mode > MODE_ABSOLUTE || (size == OPSIZE_BYTE && decoded->dst.addr_mode == MODE_AREG)) { |
1097 decoded->op = M68K_INVALID; | 1109 decoded->op = M68K_INVALID; |
1098 break; | 1110 break; |
1099 } | 1111 } |
1100 } | 1112 } |
1101 break; | 1113 break; |
1220 } else { | 1232 } else { |
1221 decoded->extra.size = size; | 1233 decoded->extra.size = size; |
1222 decoded->src.addr_mode = MODE_REG; | 1234 decoded->src.addr_mode = MODE_REG; |
1223 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 1235 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
1224 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1236 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
1225 if (!istream) { | 1237 if (!istream || !m68k_valid_full_arith_dst(&decoded->dst)) { |
1226 decoded->op = M68K_INVALID; | 1238 decoded->op = M68K_INVALID; |
1227 break; | 1239 break; |
1228 } | 1240 } |
1229 } | 1241 } |
1230 } else { | 1242 } else { |
1248 decoded->extra.size = size; | 1260 decoded->extra.size = size; |
1249 decoded->dst.addr_mode = MODE_REG; | 1261 decoded->dst.addr_mode = MODE_REG; |
1250 } | 1262 } |
1251 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1263 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1252 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1264 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1253 if (!istream) { | 1265 if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) { |
1254 decoded->op = M68K_INVALID; | 1266 decoded->op = M68K_INVALID; |
1255 break; | 1267 break; |
1256 } | 1268 } |
1257 } | 1269 } |
1258 break; | 1270 break; |
1284 if (decoded->dst.addr_mode == MODE_AREG) { | 1296 if (decoded->dst.addr_mode == MODE_AREG) { |
1285 //CMPM | 1297 //CMPM |
1286 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; | 1298 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; |
1287 decoded->src.params.regs.pri = decoded->dst.params.regs.pri; | 1299 decoded->src.params.regs.pri = decoded->dst.params.regs.pri; |
1288 decoded->dst.params.regs.pri = reg; | 1300 decoded->dst.params.regs.pri = reg; |
1301 } else if (!m68k_valid_immed_limited_dst(&decoded->dst)){ | |
1302 decoded->op = M68K_INVALID; | |
1303 break; | |
1289 } else { | 1304 } else { |
1290 //EOR | 1305 //EOR |
1291 decoded->op = M68K_EOR; | 1306 decoded->op = M68K_EOR; |
1292 decoded->src.addr_mode = MODE_REG; | 1307 decoded->src.addr_mode = MODE_REG; |
1293 decoded->src.params.regs.pri = reg; | 1308 decoded->src.params.regs.pri = reg; |
1406 } else { | 1421 } else { |
1407 decoded->extra.size = size; | 1422 decoded->extra.size = size; |
1408 decoded->src.addr_mode = MODE_REG; | 1423 decoded->src.addr_mode = MODE_REG; |
1409 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 1424 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
1410 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1425 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
1411 if (!istream) { | 1426 if (!istream || !m68k_valid_full_arith_dst(&decoded->dst)) { |
1412 decoded->op = M68K_INVALID; | 1427 decoded->op = M68K_INVALID; |
1413 break; | 1428 break; |
1414 } | 1429 } |
1415 } | 1430 } |
1416 } else { | 1431 } else { |
1434 decoded->extra.size = size; | 1449 decoded->extra.size = size; |
1435 decoded->dst.addr_mode = MODE_REG; | 1450 decoded->dst.addr_mode = MODE_REG; |
1436 } | 1451 } |
1437 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1452 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1438 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1453 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1439 if (!istream) { | 1454 if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) { |
1440 decoded->op = M68K_INVALID; | 1455 decoded->op = M68K_INVALID; |
1441 break; | 1456 break; |
1442 } | 1457 } |
1443 } | 1458 } |
1444 break; | 1459 break; |
1471 decoded->op = M68K_ROL; | 1486 decoded->op = M68K_ROL; |
1472 break; | 1487 break; |
1473 } | 1488 } |
1474 decoded->extra.size = OPSIZE_WORD; | 1489 decoded->extra.size = OPSIZE_WORD; |
1475 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); | 1490 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); |
1476 if (!istream) { | 1491 if (!istream || !m68k_valid_full_arith_dst(&decoded->dst)) { |
1477 decoded->op = M68K_INVALID; | 1492 decoded->op = M68K_INVALID; |
1478 break; | 1493 break; |
1479 } | 1494 } |
1480 } else if((*istream & 0xC0) != 0xC0) { | 1495 } else if((*istream & 0xC0) != 0xC0) { |
1481 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) | 1496 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) |