comparison 68kinst.c @ 18:3e7bfde7606e

M68K to x86 translation works for a limited subset of instructions and addressing modes
author Mike Pavone <pavone@retrodev.com>
date Tue, 04 Dec 2012 19:13:12 -0800
parents c0f339564819
children f2aaaf36c875
comparison
equal deleted inserted replaced
17:de0085d4ea40 18:3e7bfde7606e
84 void m68k_decode_cond(uint16_t op, m68kinst * decoded) 84 void m68k_decode_cond(uint16_t op, m68kinst * decoded)
85 { 85 {
86 decoded->extra.cond = (op >> 0x8) & 0xF; 86 decoded->extra.cond = (op >> 0x8) & 0xF;
87 } 87 }
88 88
89 uint8_t m68K_reg_quick_field(uint16_t op) 89 uint8_t m68k_reg_quick_field(uint16_t op)
90 { 90 {
91 return (op >> 9) & 0x7; 91 return (op >> 9) & 0x7;
92 } 92 }
93 93
94 uint16_t * m68K_decode(uint16_t * istream, m68kinst * decoded) 94 uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
95 { 95 {
96 uint8_t optype = *istream >> 12; 96 uint8_t optype = *istream >> 12;
97 uint8_t size; 97 uint8_t size;
98 uint8_t reg; 98 uint8_t reg;
99 uint8_t opmode; 99 uint8_t opmode;
100 uint32_t immed; 100 uint32_t immed;
101 decoded->op = M68K_INVALID; 101 decoded->op = M68K_INVALID;
102 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED; 102 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED;
103 decoded->variant = VAR_NORMAL; 103 decoded->variant = VAR_NORMAL;
104 decoded->address = address;
104 switch(optype) 105 switch(optype)
105 { 106 {
106 case BIT_MOVEP_IMMED: 107 case BIT_MOVEP_IMMED:
107 if (*istream & 0x100) { 108 if (*istream & 0x100) {
108 //BTST, BCHG, BCLR, BSET 109 //BTST, BCHG, BCLR, BSET
120 case 3: 121 case 3:
121 decoded->op = M68K_BSET; 122 decoded->op = M68K_BSET;
122 break; 123 break;
123 } 124 }
124 decoded->src.addr_mode = MODE_REG; 125 decoded->src.addr_mode = MODE_REG;
125 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); 126 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
126 decoded->extra.size = OPSIZE_LONG; 127 decoded->extra.size = OPSIZE_LONG;
127 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->dst)); 128 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->dst));
128 } else if ((*istream & 0xF00) == 0x800) { 129 } else if ((*istream & 0xF00) == 0x800) {
129 //BTST, BCHG, BCLR, BSET 130 //BTST, BCHG, BCLR, BSET
130 switch ((*istream >> 6) & 0x3) 131 switch ((*istream >> 6) & 0x3)
351 decoded->op = M68K_MOVEP; 352 decoded->op = M68K_MOVEP;
352 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; 353 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
353 if (*istream & 0x80) { 354 if (*istream & 0x80) {
354 //memory dest 355 //memory dest
355 decoded->src.addr_mode = MODE_REG; 356 decoded->src.addr_mode = MODE_REG;
356 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); 357 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
357 decoded->dst.addr_mode = MODE_AREG_DISPLACE; 358 decoded->dst.addr_mode = MODE_AREG_DISPLACE;
358 decoded->dst.params.regs.pri = *istream & 0x7; 359 decoded->dst.params.regs.pri = *istream & 0x7;
359 } else { 360 } else {
360 //memory source 361 //memory source
361 decoded->dst.addr_mode = MODE_REG; 362 decoded->dst.addr_mode = MODE_REG;
362 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 363 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
363 decoded->src.addr_mode = MODE_AREG_DISPLACE; 364 decoded->src.addr_mode = MODE_AREG_DISPLACE;
364 decoded->src.params.regs.pri = *istream & 0x7; 365 decoded->src.params.regs.pri = *istream & 0x7;
365 } 366 }
366 immed = *(++istream); 367 immed = *(++istream);
367 368
372 case MOVE_BYTE: 373 case MOVE_BYTE:
373 case MOVE_LONG: 374 case MOVE_LONG:
374 case MOVE_WORD: 375 case MOVE_WORD:
375 decoded->op = M68K_MOVE; 376 decoded->op = M68K_MOVE;
376 decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG); 377 decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG);
378 opmode = (*istream >> 6) & 0x7;
379 reg = m68k_reg_quick_field(*istream);
377 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 380 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
378 istream = m68k_decode_op_ex(istream, (*istream >> 6) & 0x7, m68K_reg_quick_field(*istream), decoded->extra.size, &(decoded->dst)); 381 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
379 break; 382 break;
380 case MISC: 383 case MISC:
381 384
382 if ((*istream & 0x1C0) == 0x1C0) { 385 if ((*istream & 0x1C0) == 0x1C0) {
383 decoded->op = M68K_LEA; 386 decoded->op = M68K_LEA;
384 decoded->extra.size = OPSIZE_LONG; 387 decoded->extra.size = OPSIZE_LONG;
385 decoded->dst.addr_mode = MODE_AREG; 388 decoded->dst.addr_mode = MODE_AREG;
386 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 389 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
387 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 390 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
388 } else { 391 } else {
389 if (*istream & 0x100) { 392 if (*istream & 0x100) {
390 decoded->op = M68K_CHK; 393 decoded->op = M68K_CHK;
391 if ((*istream & 0x180) == 0x180) { 394 if ((*istream & 0x180) == 0x180) {
399 break; 402 break;
400 #endif 403 #endif
401 } 404 }
402 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 405 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
403 decoded->dst.addr_mode = MODE_REG; 406 decoded->dst.addr_mode = MODE_REG;
404 decoded->dst.addr_mode = m68K_reg_quick_field(*istream); 407 decoded->dst.addr_mode = m68k_reg_quick_field(*istream);
405 } else { 408 } else {
406 opmode = (*istream >> 3) & 0x7; 409 opmode = (*istream >> 3) & 0x7;
407 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG && opmode != MODE_AREG_POSTINC) { 410 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG && opmode != MODE_AREG_POSTINC) {
408 decoded->op = M68K_MOVEM; 411 decoded->op = M68K_MOVEM;
409 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; 412 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
682 //ADDQ, SUBQ 685 //ADDQ, SUBQ
683 decoded->variant = VAR_QUICK; 686 decoded->variant = VAR_QUICK;
684 decoded->extra.size = size; 687 decoded->extra.size = size;
685 decoded->src.addr_mode = MODE_IMMEDIATE; 688 decoded->src.addr_mode = MODE_IMMEDIATE;
686 istream = m68k_decode_op(istream, size, &(decoded->dst)); 689 istream = m68k_decode_op(istream, size, &(decoded->dst));
687 immed = m68K_reg_quick_field(*istream); 690 immed = m68k_reg_quick_field(*istream);
688 if (!immed) { 691 if (!immed) {
689 immed = 8; 692 immed = 8;
690 } 693 }
691 decoded->src.params.immed = immed; 694 decoded->src.params.immed = immed;
692 if (*istream & 0x100) { 695 if (*istream & 0x100) {
720 decoded->variant = VAR_QUICK; 723 decoded->variant = VAR_QUICK;
721 decoded->extra.size = OPSIZE_LONG; 724 decoded->extra.size = OPSIZE_LONG;
722 decoded->src.addr_mode = MODE_IMMEDIATE; 725 decoded->src.addr_mode = MODE_IMMEDIATE;
723 decoded->src.params.immed = sign_extend8(*istream & 0xFF); 726 decoded->src.params.immed = sign_extend8(*istream & 0xFF);
724 decoded->dst.addr_mode = MODE_REG; 727 decoded->dst.addr_mode = MODE_REG;
725 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 728 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
726 immed = *istream & 0xFF; 729 immed = *istream & 0xFF;
727 break; 730 break;
728 case OR_DIV_SBCD: 731 case OR_DIV_SBCD:
729 //for OR, if opmode bit 2 is 1, then src = Dn, dst = <ea> 732 //for OR, if opmode bit 2 is 1, then src = Dn, dst = <ea>
730 opmode = (*istream >> 6) & 0x7; 733 opmode = (*istream >> 6) & 0x7;
783 if (*istream & 0x6) { 786 if (*istream & 0x6) {
784 if (size == OPSIZE_INVALID) { 787 if (size == OPSIZE_INVALID) {
785 //SUBA.l 788 //SUBA.l
786 decoded->extra.size = OPSIZE_LONG; 789 decoded->extra.size = OPSIZE_LONG;
787 decoded->dst.addr_mode = MODE_AREG; 790 decoded->dst.addr_mode = MODE_AREG;
791 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
788 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); 792 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
789 } else { 793 } else {
790 decoded->extra.size = size; 794 decoded->extra.size = size;
791 decoded->src.addr_mode = MODE_REG; 795 decoded->src.addr_mode = MODE_REG;
796 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
792 istream = m68k_decode_op(istream, size, &(decoded->dst)); 797 istream = m68k_decode_op(istream, size, &(decoded->dst));
793 } 798 }
794 } else { 799 } else {
795 //SUBX 800 //SUBX
796 decoded->op = M68K_SUBX; 801 decoded->op = M68K_SUBX;
797 decoded->extra.size = size; 802 decoded->extra.size = size;
798 istream = m68k_decode_op(istream, size, &(decoded->src)); 803 istream = m68k_decode_op(istream, size, &(decoded->src));
799 decoded->dst.addr_mode = decoded->src.addr_mode; 804 decoded->dst.addr_mode = decoded->src.addr_mode;
800 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 805 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
801 } 806 }
802 } else { 807 } else {
803 if (size == OPSIZE_INVALID) { 808 if (size == OPSIZE_INVALID) {
804 //SUBA.w 809 //SUBA.w
805 decoded->extra.size = OPSIZE_WORD; 810 decoded->extra.size = OPSIZE_WORD;
806 decoded->dst.addr_mode = MODE_AREG; 811 decoded->dst.addr_mode = MODE_AREG;
807 } else { 812 } else {
808 decoded->extra.size = size; 813 decoded->extra.size = size;
809 decoded->dst.addr_mode = MODE_REG; 814 decoded->dst.addr_mode = MODE_REG;
810 } 815 }
811 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 816 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
812 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 817 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
813 } 818 }
814 break; 819 break;
815 case RESERVED: 820 case RESERVED:
816 break; 821 break;
822 istream = m68k_decode_op(istream, size, &(decoded->dst)); 827 istream = m68k_decode_op(istream, size, &(decoded->dst));
823 if (decoded->src.addr_mode == MODE_AREG) { 828 if (decoded->src.addr_mode == MODE_AREG) {
824 //CMPM 829 //CMPM
825 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; 830 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC;
826 decoded->src.params.regs.pri = decoded->dst.params.regs.pri; 831 decoded->src.params.regs.pri = decoded->dst.params.regs.pri;
827 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 832 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
828 } else { 833 } else {
829 //EOR 834 //EOR
830 decoded->op = M68K_EOR; 835 decoded->op = M68K_EOR;
831 decoded->extra.size = size; 836 decoded->extra.size = size;
832 decoded->src.addr_mode = MODE_REG; 837 decoded->src.addr_mode = MODE_REG;
833 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); 838 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
834 } 839 }
835 } else { 840 } else {
836 //CMP 841 //CMP
837 decoded->extra.size = size; 842 decoded->extra.size = size;
838 decoded->dst.addr_mode = MODE_REG; 843 decoded->dst.addr_mode = MODE_REG;
839 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 844 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
840 istream = m68k_decode_op(istream, size, &(decoded->src)); 845 istream = m68k_decode_op(istream, size, &(decoded->src));
841 } 846 }
842 break; 847 break;
843 case AND_MUL_ABCD_EXG: 848 case AND_MUL_ABCD_EXG:
844 //page 575 for summary 849 //page 575 for summary
853 if (*istream & 0x100) { 858 if (*istream & 0x100) {
854 if ((*istream & 0xC0) == 0xC0) { 859 if ((*istream & 0xC0) == 0xC0) {
855 decoded->op = M68K_MULS; 860 decoded->op = M68K_MULS;
856 decoded->extra.size = OPSIZE_WORD; 861 decoded->extra.size = OPSIZE_WORD;
857 decoded->dst.addr_mode = MODE_REG; 862 decoded->dst.addr_mode = MODE_REG;
858 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 863 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
859 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); 864 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
860 } else if(!(*istream & 0xF0)) { 865 } else if(!(*istream & 0xF0)) {
861 decoded->op = M68K_ABCD; 866 decoded->op = M68K_ABCD;
862 decoded->extra.size = OPSIZE_BYTE; 867 decoded->extra.size = OPSIZE_BYTE;
863 decoded->src.params.regs.pri = *istream & 0x7; 868 decoded->src.params.regs.pri = *istream & 0x7;
864 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 869 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
865 decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG; 870 decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG;
866 } else if(!(*istream & 0x30)) { 871 } else if(!(*istream & 0x30)) {
867 decoded->op = M68K_EXG; 872 decoded->op = M68K_EXG;
868 decoded->extra.size = OPSIZE_LONG; 873 decoded->extra.size = OPSIZE_LONG;
869 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); 874 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
870 decoded->dst.params.regs.pri = *istream & 0x7; 875 decoded->dst.params.regs.pri = *istream & 0x7;
871 if (*istream & 0x8) { 876 if (*istream & 0x8) {
872 if (*istream & 0x80) { 877 if (*istream & 0x80) {
873 decoded->src.addr_mode = MODE_REG; 878 decoded->src.addr_mode = MODE_REG;
874 decoded->dst.addr_mode = MODE_AREG; 879 decoded->dst.addr_mode = MODE_AREG;
880 } 885 }
881 } else { 886 } else {
882 decoded->op = M68K_AND; 887 decoded->op = M68K_AND;
883 decoded->extra.size = (*istream >> 6); 888 decoded->extra.size = (*istream >> 6);
884 decoded->dst.addr_mode = MODE_REG; 889 decoded->dst.addr_mode = MODE_REG;
885 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 890 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
886 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 891 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
887 } 892 }
888 } else { 893 } else {
889 if ((*istream & 0xC0) == 0xC0) { 894 if ((*istream & 0xC0) == 0xC0) {
890 decoded->op = M68K_MULU; 895 decoded->op = M68K_MULU;
891 decoded->extra.size = OPSIZE_WORD; 896 decoded->extra.size = OPSIZE_WORD;
892 decoded->dst.addr_mode = MODE_REG; 897 decoded->dst.addr_mode = MODE_REG;
893 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 898 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
894 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); 899 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
895 } else { 900 } else {
896 decoded->op = M68K_AND; 901 decoded->op = M68K_AND;
897 decoded->extra.size = (*istream >> 6); 902 decoded->extra.size = (*istream >> 6);
898 decoded->src.addr_mode = MODE_REG; 903 decoded->src.addr_mode = MODE_REG;
899 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); 904 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
900 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); 905 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
901 } 906 }
902 } 907 }
903 break; 908 break;
904 case ADD_ADDX: 909 case ADD_ADDX:
909 if (*istream & 0x6) { 914 if (*istream & 0x6) {
910 if (size == OPSIZE_INVALID) { 915 if (size == OPSIZE_INVALID) {
911 //ADDA.l 916 //ADDA.l
912 decoded->extra.size = OPSIZE_LONG; 917 decoded->extra.size = OPSIZE_LONG;
913 decoded->dst.addr_mode = MODE_AREG; 918 decoded->dst.addr_mode = MODE_AREG;
919 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
914 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); 920 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
915 } else { 921 } else {
916 decoded->extra.size = size; 922 decoded->extra.size = size;
917 decoded->src.addr_mode = MODE_REG; 923 decoded->src.addr_mode = MODE_REG;
924 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
918 istream = m68k_decode_op(istream, size, &(decoded->dst)); 925 istream = m68k_decode_op(istream, size, &(decoded->dst));
919 } 926 }
920 } else { 927 } else {
921 //ADDX 928 //ADDX
922 decoded->op = M68K_ADDX; 929 decoded->op = M68K_ADDX;
923 //FIXME: Size is not technically correct 930 //FIXME: Size is not technically correct
924 decoded->extra.size = size; 931 decoded->extra.size = size;
925 istream = m68k_decode_op(istream, size, &(decoded->src)); 932 istream = m68k_decode_op(istream, size, &(decoded->src));
926 decoded->dst.addr_mode = decoded->src.addr_mode; 933 decoded->dst.addr_mode = decoded->src.addr_mode;
927 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 934 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
928 } 935 }
929 } else { 936 } else {
930 if (size == OPSIZE_INVALID) { 937 if (size == OPSIZE_INVALID) {
931 //ADDA.w 938 //ADDA.w
932 decoded->extra.size = OPSIZE_WORD; 939 decoded->extra.size = OPSIZE_WORD;
933 decoded->dst.addr_mode = MODE_AREG; 940 decoded->dst.addr_mode = MODE_AREG;
934 } else { 941 } else {
935 decoded->extra.size = size; 942 decoded->extra.size = size;
936 decoded->dst.addr_mode = MODE_REG; 943 decoded->dst.addr_mode = MODE_REG;
937 } 944 }
938 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); 945 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
939 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); 946 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
940 } 947 }
941 break; 948 break;
942 case SHIFT_ROTATE: 949 case SHIFT_ROTATE:
943 if ((*istream & 0x8C0) == 0xC0) { 950 if ((*istream & 0x8C0) == 0xC0) {