Mercurial > repos > blastem
comparison 68kinst.c @ 1463:63f309cfbef9
Fix what are hopefully th elast of the 68K instruction decoder bugs revealed by r57shell/realmonster's test ROM
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 08 Sep 2017 00:38:10 -0700 |
parents | d276ec2fff11 |
children | dc1eab3ec092 |
comparison
equal
deleted
inserted
replaced
1462:d276ec2fff11 | 1463:63f309cfbef9 |
---|---|
393 reg = *istream & 0x7; | 393 reg = *istream & 0x7; |
394 decoded->src.addr_mode = MODE_IMMEDIATE_WORD; | 394 decoded->src.addr_mode = MODE_IMMEDIATE_WORD; |
395 decoded->src.params.immed = *(++istream) & 0xFF; | 395 decoded->src.params.immed = *(++istream) & 0xFF; |
396 decoded->extra.size = OPSIZE_BYTE; | 396 decoded->extra.size = OPSIZE_BYTE; |
397 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | 397 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
398 if (!istream || !m68k_valid_immed_dst(&decoded->dst)) { | 398 if ( |
399 !istream || !m68k_valid_immed_dst(&decoded->dst) | |
400 || (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst)) | |
401 ) { | |
399 decoded->op = M68K_INVALID; | 402 decoded->op = M68K_INVALID; |
400 break; | 403 break; |
401 } | 404 } |
402 if (decoded->dst.addr_mode == MODE_REG) { | 405 if (decoded->dst.addr_mode == MODE_REG) { |
403 decoded->extra.size = OPSIZE_LONG; | 406 decoded->extra.size = OPSIZE_LONG; |
627 immed = *(++istream); | 630 immed = *(++istream); |
628 decoded->src.params.immed = (immed << 16) | *(++istream); | 631 decoded->src.params.immed = (immed << 16) | *(++istream); |
629 break; | 632 break; |
630 } | 633 } |
631 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | 634 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
632 if (!istream || !m68k_valid_immed_dst(&(decoded->dst))) { | 635 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { |
633 decoded->op = M68K_INVALID; | 636 decoded->op = M68K_INVALID; |
634 break; | 637 break; |
635 } | 638 } |
636 break; | 639 break; |
637 case 7: | 640 case 7: |
895 } else { | 898 } else { |
896 if (size == OPSIZE_INVALID) { | 899 if (size == OPSIZE_INVALID) { |
897 decoded->op = M68K_TAS; | 900 decoded->op = M68K_TAS; |
898 decoded->extra.size = OPSIZE_BYTE; | 901 decoded->extra.size = OPSIZE_BYTE; |
899 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); | 902 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); |
900 if (!istream) { | 903 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) { |
901 decoded->op = M68K_INVALID; | 904 decoded->op = M68K_INVALID; |
902 break; | 905 break; |
903 } | 906 } |
904 } else { | 907 } else { |
905 decoded->op = M68K_TST; | 908 decoded->op = M68K_TST; |
1196 decoded->extra.size = size; | 1199 decoded->extra.size = size; |
1197 if (opmode & 0x4) { | 1200 if (opmode & 0x4) { |
1198 decoded->src.addr_mode = MODE_REG; | 1201 decoded->src.addr_mode = MODE_REG; |
1199 decoded->src.params.regs.pri = (*istream >> 9) & 0x7; | 1202 decoded->src.params.regs.pri = (*istream >> 9) & 0x7; |
1200 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1203 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
1201 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { | 1204 if (!istream || !m68k_valid_full_arith_dst(&(decoded->dst))) { |
1202 decoded->op = M68K_INVALID; | 1205 decoded->op = M68K_INVALID; |
1203 break; | 1206 break; |
1204 } | 1207 } |
1205 } else { | 1208 } else { |
1206 decoded->dst.addr_mode = MODE_REG; | 1209 decoded->dst.addr_mode = MODE_REG; |
1317 decoded->extra.size = size; | 1320 decoded->extra.size = size; |
1318 decoded->dst.addr_mode = MODE_REG; | 1321 decoded->dst.addr_mode = MODE_REG; |
1319 } | 1322 } |
1320 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1323 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1321 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1324 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1322 if (!istream) { | 1325 if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) { |
1323 decoded->op = M68K_INVALID; | 1326 decoded->op = M68K_INVALID; |
1324 break; | 1327 break; |
1325 } | 1328 } |
1326 } | 1329 } |
1327 break; | 1330 break; |
1340 decoded->op = M68K_MULS; | 1343 decoded->op = M68K_MULS; |
1341 decoded->extra.size = OPSIZE_WORD; | 1344 decoded->extra.size = OPSIZE_WORD; |
1342 decoded->dst.addr_mode = MODE_REG; | 1345 decoded->dst.addr_mode = MODE_REG; |
1343 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1346 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1344 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); | 1347 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); |
1345 if (!istream) { | 1348 if (!istream || decoded->src.addr_mode == MODE_AREG) { |
1346 decoded->op = M68K_INVALID; | 1349 decoded->op = M68K_INVALID; |
1347 break; | 1350 break; |
1348 } | 1351 } |
1349 } else if(!(*istream & 0xF0)) { | 1352 } else if(!(*istream & 0xF0)) { |
1350 decoded->op = M68K_ABCD; | 1353 decoded->op = M68K_ABCD; |
1362 decoded->src.addr_mode = MODE_REG; | 1365 decoded->src.addr_mode = MODE_REG; |
1363 decoded->dst.addr_mode = MODE_AREG; | 1366 decoded->dst.addr_mode = MODE_AREG; |
1364 } else { | 1367 } else { |
1365 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG; | 1368 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG; |
1366 } | 1369 } |
1370 } else if (*istream & 0x40) { | |
1371 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG; | |
1367 } else { | 1372 } else { |
1368 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG; | 1373 decoded->op = M68K_INVALID; |
1374 break; | |
1369 } | 1375 } |
1370 } else { | 1376 } else { |
1371 decoded->op = M68K_AND; | 1377 decoded->op = M68K_AND; |
1372 decoded->extra.size = (*istream >> 6) & 0x3; | 1378 decoded->extra.size = (*istream >> 6) & 0x3; |
1373 decoded->src.addr_mode = MODE_REG; | 1379 decoded->src.addr_mode = MODE_REG; |
1374 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 1380 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
1375 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); | 1381 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); |
1376 if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) { | 1382 if (!istream || !m68k_valid_full_arith_dst(&(decoded->dst))) { |
1377 decoded->op = M68K_INVALID; | 1383 decoded->op = M68K_INVALID; |
1378 break; | 1384 break; |
1379 } | 1385 } |
1380 } | 1386 } |
1381 } else { | 1387 } else { |
1383 decoded->op = M68K_MULU; | 1389 decoded->op = M68K_MULU; |
1384 decoded->extra.size = OPSIZE_WORD; | 1390 decoded->extra.size = OPSIZE_WORD; |
1385 decoded->dst.addr_mode = MODE_REG; | 1391 decoded->dst.addr_mode = MODE_REG; |
1386 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1392 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1387 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); | 1393 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); |
1388 if (!istream) { | 1394 if (!istream || decoded->src.addr_mode == MODE_AREG) { |
1389 decoded->op = M68K_INVALID; | 1395 decoded->op = M68K_INVALID; |
1390 break; | 1396 break; |
1391 } | 1397 } |
1392 } else { | 1398 } else { |
1393 decoded->op = M68K_AND; | 1399 decoded->op = M68K_AND; |