comparison 68kinst.c @ 1458:b81428ef0396

Fix a bunch of 68K instruction decoder bugs revealed by r57shell/realmonster's test ROM
author Michael Pavone <pavone@retrodev.com>
date Wed, 06 Sep 2017 22:14:51 -0700
parents 696a029d09e9
children d276ec2fff11
comparison
equal deleted inserted replaced
1457:bbba92f56f47 1458:b81428ef0396
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; 272 return 0;
273 } 273 }
274 return 1; 274 return 1;
275 }
276
277 uint8_t m68k_valid_movem_dst(m68k_op_info *dst)
278 {
279 if (dst->addr_mode == MODE_REG || dst->addr_mode == MODE_AREG_POSTINC) {
280 return 0;
281 }
282 return m68k_valid_immed_limited_dst(dst);
275 } 283 }
276 284
277 uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst) 285 uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst)
278 { 286 {
279 uint8_t mode = (*cur >> 3) & 0x7; 287 uint8_t mode = (*cur >> 3) & 0x7;
344 } 352 }
345 decoded->src.addr_mode = MODE_REG; 353 decoded->src.addr_mode = MODE_REG;
346 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); 354 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
347 decoded->extra.size = OPSIZE_BYTE; 355 decoded->extra.size = OPSIZE_BYTE;
348 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); 356 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
349 if (!istream) { 357 if (
358 !istream || decoded->dst.addr_mode == MODE_AREG
359 || (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst))
360 ) {
350 decoded->op = M68K_INVALID; 361 decoded->op = M68K_INVALID;
351 break; 362 break;
352 } 363 }
353 if (decoded->dst.addr_mode == MODE_REG) { 364 if (decoded->dst.addr_mode == MODE_REG) {
354 decoded->extra.size = OPSIZE_LONG; 365 decoded->extra.size = OPSIZE_LONG;
374 reg = *istream & 0x7; 385 reg = *istream & 0x7;
375 decoded->src.addr_mode = MODE_IMMEDIATE_WORD; 386 decoded->src.addr_mode = MODE_IMMEDIATE_WORD;
376 decoded->src.params.immed = *(++istream) & 0xFF; 387 decoded->src.params.immed = *(++istream) & 0xFF;
377 decoded->extra.size = OPSIZE_BYTE; 388 decoded->extra.size = OPSIZE_BYTE;
378 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); 389 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
379 if (!istream) { 390 if (!istream || !m68k_valid_immed_dst(&decoded->dst)) {
380 decoded->op = M68K_INVALID; 391 decoded->op = M68K_INVALID;
381 break; 392 break;
382 } 393 }
383 if (decoded->dst.addr_mode == MODE_REG) { 394 if (decoded->dst.addr_mode == MODE_REG) {
384 decoded->extra.size = OPSIZE_LONG; 395 decoded->extra.size = OPSIZE_LONG;
519 break; 530 break;
520 } 531 }
521 break; 532 break;
522 case 4: 533 case 4:
523 //BTST, BCHG, BCLR, BSET 534 //BTST, BCHG, BCLR, BSET
535 //Seems like this should be unnecessary since bit instructions are explicitly handled above
536 //Possible this is redundant or the case above is overly restrictive
537 //TODO: Investigate whether this can be removed
524 switch ((*istream >> 6) & 0x3) 538 switch ((*istream >> 6) & 0x3)
525 { 539 {
526 case 0: 540 case 0:
527 decoded->op = M68K_BTST; 541 decoded->op = M68K_BTST;
528 break; 542 break;
534 break; 548 break;
535 case 3: 549 case 3:
536 decoded->op = M68K_BSET; 550 decoded->op = M68K_BSET;
537 break; 551 break;
538 } 552 }
539 decoded->src.addr_mode = MODE_IMMEDIATE; 553 decoded->src.addr_mode = MODE_IMMEDIATE_WORD;
540 decoded->src.params.immed = *(++istream) & 0xFF; 554 decoded->src.params.immed = *(++istream) & 0xFF;
541 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); 555 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
542 if (!istream) { 556 if (
557 !istream || !m68k_valid_immed_dst(&decoded->dst)
558 || (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst))
559 ) {
543 decoded->op = M68K_INVALID; 560 decoded->op = M68K_INVALID;
544 break; 561 break;
545 } 562 }
546 break; 563 break;
547 case 5: 564 case 5:
641 if (!istream) { 658 if (!istream) {
642 decoded->op = M68K_INVALID; 659 decoded->op = M68K_INVALID;
643 break; 660 break;
644 } 661 }
645 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); 662 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
646 if (!istream || decoded->dst.addr_mode == MODE_IMMEDIATE) { 663 if (!istream || decoded->dst.addr_mode > MODE_ABSOLUTE || (decoded->dst.addr_mode == MODE_AREG && optype == MOVE_BYTE)) {
647 decoded->op = M68K_INVALID; 664 decoded->op = M68K_INVALID;
648 break; 665 break;
649 } 666 }
650 break; 667 break;
651 case MISC: 668 case MISC:
679 #endif 696 #endif
680 } 697 }
681 decoded->dst.addr_mode = MODE_REG; 698 decoded->dst.addr_mode = MODE_REG;
682 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); 699 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
683 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 700 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
684 if (!istream) { 701 if (!istream || decoded->src.addr_mode == MODE_AREG) {
685 decoded->op = M68K_INVALID; 702 decoded->op = M68K_INVALID;
686 break; 703 break;
687 } 704 }
688 } else { 705 } else {
689 opmode = (*istream >> 3) & 0x7; 706 opmode = (*istream >> 3) & 0x7;
706 } 723 }
707 } else { 724 } else {
708 decoded->src.addr_mode = MODE_REG; 725 decoded->src.addr_mode = MODE_REG;
709 decoded->src.params.immed = *(++istream); 726 decoded->src.params.immed = *(++istream);
710 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); 727 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
711 if (!istream) { 728 if (!istream || !m68k_valid_movem_dst(&decoded->dst)) {
712 decoded->op = M68K_INVALID; 729 decoded->op = M68K_INVALID;
713 break; 730 break;
714 } 731 }
715 } 732 }
716 } else { 733 } else {
726 } else { 743 } else {
727 decoded->op = M68K_NEGX; 744 decoded->op = M68K_NEGX;
728 } 745 }
729 decoded->extra.size = size; 746 decoded->extra.size = size;
730 istream= m68k_decode_op(istream, size, &(decoded->dst)); 747 istream= m68k_decode_op(istream, size, &(decoded->dst));
731 if (!istream) { 748 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
732 decoded->op = M68K_INVALID; 749 decoded->op = M68K_INVALID;
733 break; 750 break;
734 } 751 }
735 break; 752 break;
736 case 1: 753 case 1:
745 } else { 762 } else {
746 decoded->op = M68K_CLR; 763 decoded->op = M68K_CLR;
747 } 764 }
748 decoded->extra.size = size; 765 decoded->extra.size = size;
749 istream= m68k_decode_op(istream, size, &(decoded->dst)); 766 istream= m68k_decode_op(istream, size, &(decoded->dst));
750 if (!istream) { 767 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
751 decoded->op = M68K_INVALID; 768 decoded->op = M68K_INVALID;
752 break; 769 break;
753 } 770 }
754 break; 771 break;
755 case 2: 772 case 2:
756 //MOVE to CCR or NEG 773 //MOVE to CCR or NEG
757 if (size == OPSIZE_INVALID) { 774 if (size == OPSIZE_INVALID) {
758 decoded->op = M68K_MOVE_CCR; 775 decoded->op = M68K_MOVE_CCR;
759 size = OPSIZE_WORD; 776 size = OPSIZE_WORD;
760 istream= m68k_decode_op(istream, size, &(decoded->src)); 777 istream= m68k_decode_op(istream, size, &(decoded->src));
761 if (!istream) { 778 if (!istream || decoded->src.addr_mode == MODE_AREG) {
762 decoded->op = M68K_INVALID; 779 decoded->op = M68K_INVALID;
763 break; 780 break;
764 } 781 }
765 } else { 782 } else {
766 decoded->op = M68K_NEG; 783 decoded->op = M68K_NEG;
767 istream= m68k_decode_op(istream, size, &(decoded->dst)); 784 istream= m68k_decode_op(istream, size, &(decoded->dst));
768 if (!istream) { 785 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
769 decoded->op = M68K_INVALID; 786 decoded->op = M68K_INVALID;
770 break; 787 break;
771 } 788 }
772 } 789 }
773 decoded->extra.size = size; 790 decoded->extra.size = size;
776 //MOVE to SR or NOT 793 //MOVE to SR or NOT
777 if (size == OPSIZE_INVALID) { 794 if (size == OPSIZE_INVALID) {
778 decoded->op = M68K_MOVE_SR; 795 decoded->op = M68K_MOVE_SR;
779 size = OPSIZE_WORD; 796 size = OPSIZE_WORD;
780 istream= m68k_decode_op(istream, size, &(decoded->src)); 797 istream= m68k_decode_op(istream, size, &(decoded->src));
781 if (!istream) { 798 if (!istream || decoded->src.addr_mode == MODE_AREG) {
782 decoded->op = M68K_INVALID; 799 decoded->op = M68K_INVALID;
783 break; 800 break;
784 } 801 }
785 } else { 802 } else {
786 decoded->op = M68K_NOT; 803 decoded->op = M68K_NOT;
787 istream= m68k_decode_op(istream, size, &(decoded->dst)); 804 istream= m68k_decode_op(istream, size, &(decoded->dst));
788 if (!istream) { 805 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
789 decoded->op = M68K_INVALID; 806 decoded->op = M68K_INVALID;
790 break; 807 break;
791 } 808 }
792 } 809 }
793 decoded->extra.size = size; 810 decoded->extra.size = size;
838 default: 855 default:
839 if (!(*istream & 0x1C0)) { 856 if (!(*istream & 0x1C0)) {
840 decoded->op = M68K_NBCD; 857 decoded->op = M68K_NBCD;
841 decoded->extra.size = OPSIZE_BYTE; 858 decoded->extra.size = OPSIZE_BYTE;
842 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); 859 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
843 if (!istream) { 860 if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
844 decoded->op = M68K_INVALID; 861 decoded->op = M68K_INVALID;
845 break; 862 break;
846 } 863 }
847 } else if((*istream & 0x1C0) == 0x40) { 864 } else if((*istream & 0x1C0) == 0x40) {
848 decoded->op = M68K_PEA; 865 decoded->op = M68K_PEA;
882 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 899 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
883 if (!istream) { 900 if (!istream) {
884 decoded->op = M68K_INVALID; 901 decoded->op = M68K_INVALID;
885 break; 902 break;
886 } 903 }
904 #ifndef M68020
905 if (!m68k_valid_immed_limited_dst(&decoded->src)) {
906 decoded->op = M68K_INVALID;
907 break;
908 }
909 #endif
887 } 910 }
888 } 911 }
889 break; 912 break;
890 case 6: 913 case 6:
891 //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL 914 //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL