4 |
|
* Read 68000 CPU specs from file "table68k" |
5 |
|
* |
6 |
|
* Copyright 1995,1996 Bernd Schmidt |
7 |
+ |
* |
8 |
+ |
* This program is free software; you can redistribute it and/or modify |
9 |
+ |
* it under the terms of the GNU General Public License as published by |
10 |
+ |
* the Free Software Foundation; either version 2 of the License, or |
11 |
+ |
* (at your option) any later version. |
12 |
+ |
* |
13 |
+ |
* This program is distributed in the hope that it will be useful, |
14 |
+ |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
+ |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
+ |
* GNU General Public License for more details. |
17 |
+ |
* |
18 |
+ |
* You should have received a copy of the GNU General Public License |
19 |
+ |
* along with this program; if not, write to the Free Software |
20 |
+ |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 |
|
*/ |
22 |
|
|
23 |
|
#include <stdio.h> |
144 |
|
{ i_FBcc, "FBcc" }, |
145 |
|
{ i_FSAVE, "FSAVE" }, |
146 |
|
{ i_FRESTORE, "FRESTORE" }, |
147 |
+ |
|
148 |
+ |
{ i_CINVL, "CINVL" }, |
149 |
+ |
{ i_CINVP, "CINVP" }, |
150 |
+ |
{ i_CINVA, "CINVA" }, |
151 |
+ |
{ i_CPUSHL, "CPUSHL" }, |
152 |
+ |
{ i_CPUSHP, "CPUSHP" }, |
153 |
+ |
{ i_CPUSHA, "CPUSHA" }, |
154 |
+ |
{ i_MOVE16, "MOVE16" }, |
155 |
+ |
|
156 |
+ |
{ i_EMULOP_RETURN, "EMULOP_RETURN" }, |
157 |
+ |
{ i_EMULOP, "EMULOP" }, |
158 |
+ |
|
159 |
|
{ i_MMUOP, "MMUOP" }, |
160 |
|
{ i_ILLG, "" }, |
161 |
|
}; |
212 |
|
int variants; |
213 |
|
struct instr_def id; |
214 |
|
const char *opcstr; |
215 |
< |
int i; |
215 |
> |
int i, n; |
216 |
|
|
217 |
|
int flaglive = 0, flagdead = 0; |
218 |
+ |
int cflow = 0; |
219 |
|
|
220 |
|
id = defs68k[insn]; |
221 |
|
|
222 |
+ |
// Control flow information |
223 |
+ |
cflow = id.cflow; |
224 |
+ |
|
225 |
+ |
// Mask of flags set/used |
226 |
+ |
unsigned char flags_set(0), flags_used(0); |
227 |
+ |
|
228 |
+ |
for (i = 0, n = 4; i < 5; i++, n--) { |
229 |
+ |
switch (id.flaginfo[i].flagset) { |
230 |
+ |
case fa_unset: case fa_isjmp: break; |
231 |
+ |
default: flags_set |= (1 << n); |
232 |
+ |
} |
233 |
+ |
|
234 |
+ |
switch (id.flaginfo[i].flaguse) { |
235 |
+ |
case fu_unused: case fu_isjmp: break; |
236 |
+ |
default: flags_used |= (1 << n); |
237 |
+ |
} |
238 |
+ |
} |
239 |
+ |
|
240 |
|
for (i = 0; i < 5; i++) { |
241 |
|
switch (id.flaginfo[i].flagset){ |
242 |
|
case fa_unset: break; |
198 |
– |
case fa_isjmp: break; |
243 |
|
case fa_zero: flagdead |= 1 << i; break; |
244 |
|
case fa_one: flagdead |= 1 << i; break; |
245 |
|
case fa_dontcare: flagdead |= 1 << i; break; |
252 |
|
for (i = 0; i < 5; i++) { |
253 |
|
switch (id.flaginfo[i].flaguse) { |
254 |
|
case fu_unused: break; |
211 |
– |
case fu_isjmp: flaglive |= 1 << i; break; |
212 |
– |
case fu_maybecc: flaglive |= 1 << i; break; |
255 |
|
case fu_unknown: flaglive = -1; goto out2; |
256 |
|
case fu_used: flaglive |= 1 << i; break; |
257 |
|
} |
269 |
|
int pos = 0; |
270 |
|
int mnp = 0; |
271 |
|
int bitno = 0; |
272 |
< |
char mnemonic[10]; |
272 |
> |
char mnemonic[64]; |
273 |
|
|
274 |
|
wordsizes sz = sz_long; |
275 |
|
int srcgather = 0, dstgather = 0; |
306 |
|
continue; |
307 |
|
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) |
308 |
|
continue; |
309 |
+ |
if (bitcnt[bitE] && (bitval[bitE] == 0x00)) |
310 |
+ |
continue; |
311 |
|
|
312 |
|
/* bitI and bitC get copied to biti and bitc */ |
313 |
|
if (bitcnt[bitI]) { |
346 |
|
} |
347 |
|
} |
348 |
|
mnp++; |
349 |
+ |
if ((unsigned)mnp >= sizeof(mnemonic) - 1) { |
350 |
+ |
mnemonic[sizeof(mnemonic) - 1] = 0; |
351 |
+ |
fprintf(stderr, "Instruction %s overflow\n", mnemonic); |
352 |
+ |
abort(); |
353 |
+ |
} |
354 |
|
} |
355 |
|
pos++; |
356 |
|
} |
388 |
|
case 'P': srcmode = Aipi; pos++; break; |
389 |
|
} |
390 |
|
break; |
391 |
+ |
case 'L': |
392 |
+ |
srcmode = absl; |
393 |
+ |
break; |
394 |
|
case '#': |
395 |
|
switch (opcstr[pos++]) { |
396 |
|
case 'z': srcmode = imm; break; |
436 |
|
srcpos = bitpos[bitK]; |
437 |
|
} |
438 |
|
break; |
439 |
+ |
case 'E': srcmode = immi; srcreg = bitval[bitE]; |
440 |
+ |
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? |
441 |
+ |
/* 1..255 */ |
442 |
+ |
srcgather = 1; |
443 |
+ |
srctype = 6; |
444 |
+ |
srcpos = bitpos[bitE]; |
445 |
+ |
} |
446 |
+ |
break; |
447 |
+ |
case 'p': srcmode = immi; srcreg = bitval[bitp]; |
448 |
+ |
if (CPU_EMU_SIZE < 5) { |
449 |
+ |
/* 0..3 */ |
450 |
+ |
srcgather = 1; |
451 |
+ |
srctype = 7; |
452 |
+ |
srcpos = bitpos[bitp]; |
453 |
+ |
} |
454 |
+ |
break; |
455 |
|
default: abort(); |
456 |
|
} |
457 |
|
break; |
576 |
|
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; |
577 |
|
default: abort(); |
578 |
|
} |
579 |
+ |
if (dstpos < 0 || dstpos >= 32) |
580 |
+ |
abort(); |
581 |
|
break; |
582 |
|
case 'A': |
583 |
|
destmode = Areg; |
584 |
|
switch (opcstr[pos++]) { |
585 |
|
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; |
586 |
|
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; |
587 |
+ |
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; |
588 |
|
default: abort(); |
589 |
|
} |
590 |
+ |
if (dstpos < 0 || dstpos >= 32) |
591 |
+ |
abort(); |
592 |
|
switch (opcstr[pos]) { |
593 |
|
case 'p': destmode = Apdi; pos++; break; |
594 |
|
case 'P': destmode = Aipi; pos++; break; |
595 |
|
} |
596 |
|
break; |
597 |
+ |
case 'L': |
598 |
+ |
destmode = absl; |
599 |
+ |
break; |
600 |
|
case '#': |
601 |
|
switch (opcstr[pos++]) { |
602 |
|
case 'z': destmode = imm; break; |
767 |
|
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; |
768 |
|
} |
769 |
|
#endif |
770 |
+ |
|
771 |
+ |
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions |
772 |
+ |
if ( table68k[opc].mnemo == i_Scc |
773 |
+ |
|| table68k[opc].mnemo == i_Bcc |
774 |
+ |
|| table68k[opc].mnemo == i_DBcc |
775 |
+ |
|| table68k[opc].mnemo == i_TRAPcc |
776 |
+ |
) { |
777 |
+ |
switch (table68k[opc].cc) { |
778 |
+ |
// CC mask: XNZVC |
779 |
+ |
// 8421 |
780 |
+ |
case 0: flags_used = 0x00; break; /* T */ |
781 |
+ |
case 1: flags_used = 0x00; break; /* F */ |
782 |
+ |
case 2: flags_used = 0x05; break; /* HI */ |
783 |
+ |
case 3: flags_used = 0x05; break; /* LS */ |
784 |
+ |
case 4: flags_used = 0x01; break; /* CC */ |
785 |
+ |
case 5: flags_used = 0x01; break; /* CS */ |
786 |
+ |
case 6: flags_used = 0x04; break; /* NE */ |
787 |
+ |
case 7: flags_used = 0x04; break; /* EQ */ |
788 |
+ |
case 8: flags_used = 0x02; break; /* VC */ |
789 |
+ |
case 9: flags_used = 0x02; break; /* VS */ |
790 |
+ |
case 10:flags_used = 0x08; break; /* PL */ |
791 |
+ |
case 11:flags_used = 0x08; break; /* MI */ |
792 |
+ |
case 12:flags_used = 0x0A; break; /* GE */ |
793 |
+ |
case 13:flags_used = 0x0A; break; /* LT */ |
794 |
+ |
case 14:flags_used = 0x0E; break; /* GT */ |
795 |
+ |
case 15:flags_used = 0x0E; break; /* LE */ |
796 |
+ |
} |
797 |
+ |
} |
798 |
+ |
|
799 |
+ |
#if 1 |
800 |
+ |
/* gb-- flagdead and flaglive would not have correct information */ |
801 |
+ |
table68k[opc].flagdead = flags_set; |
802 |
+ |
table68k[opc].flaglive = flags_used; |
803 |
+ |
#else |
804 |
|
table68k[opc].flagdead = flagdead; |
805 |
|
table68k[opc].flaglive = flaglive; |
806 |
+ |
#endif |
807 |
+ |
table68k[opc].cflow = cflow; |
808 |
|
nomatch: |
809 |
|
/* FOO! */; |
810 |
|
} |
850 |
|
smsk = 7; sbitdst = 8; break; |
851 |
|
case 5: |
852 |
|
smsk = 63; sbitdst = 64; break; |
853 |
+ |
case 6: |
854 |
+ |
smsk = 255; sbitdst = 256; break; |
855 |
+ |
case 7: |
856 |
+ |
smsk = 3; sbitdst = 4; break; |
857 |
|
default: |
858 |
|
smsk = 0; sbitdst = 0; |
859 |
|
abort(); |
922 |
|
{ |
923 |
|
return mismatch; |
924 |
|
} |
925 |
+ |
|
926 |
+ |
const char *get_instruction_name (unsigned int opcode) |
927 |
+ |
{ |
928 |
+ |
struct instr *ins = &table68k[opcode]; |
929 |
+ |
for (int i = 0; lookuptab[i].name[0]; i++) { |
930 |
+ |
if (ins->mnemo == lookuptab[i].mnemo) |
931 |
+ |
return lookuptab[i].name; |
932 |
+ |
} |
933 |
+ |
abort(); |
934 |
+ |
return NULL; |
935 |
+ |
} |
936 |
+ |
|
937 |
+ |
static char *get_ea_string (amodes mode, wordsizes size) |
938 |
+ |
{ |
939 |
+ |
static char buffer[80]; |
940 |
+ |
|
941 |
+ |
buffer[0] = 0; |
942 |
+ |
switch (mode){ |
943 |
+ |
case Dreg: |
944 |
+ |
strcpy (buffer,"Dn"); |
945 |
+ |
break; |
946 |
+ |
case Areg: |
947 |
+ |
strcpy (buffer,"An"); |
948 |
+ |
break; |
949 |
+ |
case Aind: |
950 |
+ |
strcpy (buffer,"(An)"); |
951 |
+ |
break; |
952 |
+ |
case Aipi: |
953 |
+ |
strcpy (buffer,"(An)+"); |
954 |
+ |
break; |
955 |
+ |
case Apdi: |
956 |
+ |
strcpy (buffer,"-(An)"); |
957 |
+ |
break; |
958 |
+ |
case Ad16: |
959 |
+ |
strcpy (buffer,"(d16,An)"); |
960 |
+ |
break; |
961 |
+ |
case Ad8r: |
962 |
+ |
strcpy (buffer,"(d8,An,Xn)"); |
963 |
+ |
break; |
964 |
+ |
case PC16: |
965 |
+ |
strcpy (buffer,"(d16,PC)"); |
966 |
+ |
break; |
967 |
+ |
case PC8r: |
968 |
+ |
strcpy (buffer,"(d8,PC,Xn)"); |
969 |
+ |
break; |
970 |
+ |
case absw: |
971 |
+ |
strcpy (buffer,"(xxx).W"); |
972 |
+ |
break; |
973 |
+ |
case absl: |
974 |
+ |
strcpy (buffer,"(xxx).L"); |
975 |
+ |
break; |
976 |
+ |
case imm: |
977 |
+ |
switch (size){ |
978 |
+ |
case sz_byte: |
979 |
+ |
strcpy (buffer,"#<data>.B"); |
980 |
+ |
break; |
981 |
+ |
case sz_word: |
982 |
+ |
strcpy (buffer,"#<data>.W"); |
983 |
+ |
break; |
984 |
+ |
case sz_long: |
985 |
+ |
strcpy (buffer,"#<data>.L"); |
986 |
+ |
break; |
987 |
+ |
default: |
988 |
+ |
break; |
989 |
+ |
} |
990 |
+ |
break; |
991 |
+ |
case imm0: |
992 |
+ |
strcpy (buffer,"#<data>.B"); |
993 |
+ |
break; |
994 |
+ |
case imm1: |
995 |
+ |
strcpy (buffer,"#<data>.W"); |
996 |
+ |
break; |
997 |
+ |
case imm2: |
998 |
+ |
strcpy (buffer,"#<data>.L"); |
999 |
+ |
break; |
1000 |
+ |
case immi: |
1001 |
+ |
strcpy (buffer,"#<data>"); |
1002 |
+ |
break; |
1003 |
+ |
|
1004 |
+ |
default: |
1005 |
+ |
break; |
1006 |
+ |
} |
1007 |
+ |
return buffer; |
1008 |
+ |
} |
1009 |
+ |
|
1010 |
+ |
const char *get_instruction_string (unsigned int opcode) |
1011 |
+ |
{ |
1012 |
+ |
static char out[100]; |
1013 |
+ |
struct instr *ins; |
1014 |
+ |
|
1015 |
+ |
strcpy (out, get_instruction_name (opcode)); |
1016 |
+ |
|
1017 |
+ |
ins = &table68k[opcode]; |
1018 |
+ |
if (ins->size == sz_byte) |
1019 |
+ |
strcat (out,".B"); |
1020 |
+ |
if (ins->size == sz_word) |
1021 |
+ |
strcat (out,".W"); |
1022 |
+ |
if (ins->size == sz_long) |
1023 |
+ |
strcat (out,".L"); |
1024 |
+ |
strcat (out," "); |
1025 |
+ |
if (ins->suse) |
1026 |
+ |
strcat (out, get_ea_string (ins->smode, ins->size)); |
1027 |
+ |
if (ins->duse) { |
1028 |
+ |
if (ins->suse) |
1029 |
+ |
strcat (out,","); |
1030 |
+ |
strcat (out, get_ea_string (ins->dmode, ins->size)); |
1031 |
+ |
} |
1032 |
+ |
return out; |
1033 |
+ |
} |