|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Read 68000 CPU specs from file "table68k"
5: *
6: * Copyright 1995,1996 Bernd Schmidt
7: */
8:
9: #include "sysconfig.h"
10: #include "sysdeps.h"
11: #include <ctype.h>
12:
13: #include "config.h"
14: #include "options.h"
15: #include "readcpu.h"
16:
17: struct mnemolookup lookuptab[] = {
18: { i_ILLG, "ILLEGAL" },
19: { i_OR, "OR" },
20: { i_CHK, "CHK" },
21: { i_AND, "AND" },
22: { i_EOR, "EOR" },
23: { i_ORSR, "ORSR" },
24: { i_ANDSR, "ANDSR" },
25: { i_EORSR, "EORSR" },
26: { i_SUB, "SUB" },
27: { i_SUBA, "SUBA" },
28: { i_SUBX, "SUBX" },
29: { i_SBCD, "SBCD" },
30: { i_ADD, "ADD" },
31: { i_ADDA, "ADDA" },
32: { i_ADDX, "ADDX" },
33: { i_ABCD, "ABCD" },
34: { i_NEG, "NEG" },
35: { i_NEGX, "NEGX" },
36: { i_NBCD, "NBCD" },
37: { i_CLR, "CLR" },
38: { i_NOT, "NOT" },
39: { i_TST, "TST" },
40: { i_BTST, "BTST" },
41: { i_BCHG, "BCHG" },
42: { i_BCLR, "BCLR" },
43: { i_BSET, "BSET" },
44: { i_CMP, "CMP" },
45: { i_CMPM, "CMPM" },
46: { i_CMPA, "CMPA" },
47: { i_MVPRM, "MVPRM" },
48: { i_MVPMR, "MVPMR" },
49: { i_MOVE, "MOVE" },
50: { i_MOVEA, "MOVEA" },
51: { i_MVSR2, "MVSR2" },
52: { i_MV2SR, "MV2SR" },
53: { i_SWAP, "SWAP" },
54: { i_EXG, "EXG" },
55: { i_EXT, "EXT" },
56: { i_MVMEL, "MVMEL" },
57: { i_MVMLE, "MVMLE" },
58: { i_TRAP, "TRAP" },
59: { i_MVR2USP, "MVR2USP" },
60: { i_MVUSP2R, "MVUSP2R" },
61: { i_RESET, "RESET" },
62: { i_NOP, "NOP" },
63: { i_STOP, "STOP" },
64: { i_RTE, "RTE" },
65: { i_RTD, "RTD" },
66: { i_LINK, "LINK" },
67: { i_UNLK, "UNLK" },
68: { i_RTS, "RTS" },
69: { i_TRAPV, "TRAPV" },
70: { i_RTR, "RTR" },
71: { i_JSR, "JSR" },
72: { i_JMP, "JMP" },
73: { i_BSR, "BSR" },
74: { i_Bcc, "Bcc" },
75: { i_LEA, "LEA" },
76: { i_PEA, "PEA" },
77: { i_DBcc, "DBcc" },
78: { i_Scc, "Scc" },
79: { i_DIVU, "DIVU" },
80: { i_DIVS, "DIVS" },
81: { i_MULU, "MULU" },
82: { i_MULS, "MULS" },
83: { i_ASR, "ASR" },
84: { i_ASL, "ASL" },
85: { i_LSR, "LSR" },
86: { i_LSL, "LSL" },
87: { i_ROL, "ROL" },
88: { i_ROR, "ROR" },
89: { i_ROXL, "ROXL" },
90: { i_ROXR, "ROXR" },
91: { i_ASRW, "ASRW" },
92: { i_ASLW, "ASLW" },
93: { i_LSRW, "LSRW" },
94: { i_LSLW, "LSLW" },
95: { i_ROLW, "ROLW" },
96: { i_RORW, "RORW" },
97: { i_ROXLW, "ROXLW" },
98: { i_ROXRW, "ROXRW" },
99:
100: { i_MOVE2C, "MOVE2C" },
101: { i_MOVEC2, "MOVEC2" },
102: { i_CAS, "CAS" },
103: { i_MULL, "MULL" },
104: { i_DIVL, "DIVL" }
105: };
106:
107: struct instr *table68k;
108:
109: static amodes mode_from_str(const char *str)
110: {
111: if (strncmp(str,"Dreg",4) == 0) return Dreg;
112: if (strncmp(str,"Areg",4) == 0) return Areg;
113: if (strncmp(str,"Aind",4) == 0) return Aind;
114: if (strncmp(str,"Apdi",4) == 0) return Apdi;
115: if (strncmp(str,"Aipi",4) == 0) return Aipi;
116: if (strncmp(str,"Ad16",4) == 0) return Ad16;
117: if (strncmp(str,"Ad8r",4) == 0) return Ad8r;
118: if (strncmp(str,"absw",4) == 0) return absw;
119: if (strncmp(str,"absl",4) == 0) return absl;
120: if (strncmp(str,"PC16",4) == 0) return PC16;
121: if (strncmp(str,"PC8r",4) == 0) return PC8r;
122: if (strncmp(str,"Immd",4) == 0) return imm;
123: abort();
124: }
125:
126: static amodes mode_from_mr(int mode, int reg)
127: {
128: switch(mode) {
129: case 0: return Dreg;
130: case 1: return Areg;
131: case 2: return Aind;
132: case 3: return Aipi;
133: case 4: return Apdi;
134: case 5: return Ad16;
135: case 6: return Ad8r;
136: case 7:
137: switch(reg) {
138: case 0: return absw;
139: case 1: return absl;
140: case 2: return PC16;
141: case 3: return PC8r;
142: case 4: return imm;
143: case 5:
144: case 6:
145: case 7: return am_illg;
146: }
147: }
148: abort();
149: }
150:
151: static void build_insn(int insn)
152: {
153: int find;
154: long int opc;
155: int i, variants;
156: struct instr_def id = defs68k[insn];
157: const char *opcstr = id.opcstr;
158:
159: for (variants = 0; variants < (1 << id.n_variable); variants++) {
160: int bitcnt[lastbit];
161: int bitval[lastbit];
162: int bitpos[lastbit];
163: int i, j;
164: UWORD opc = id.bits;
165: UWORD msk, vmsk;
166: int pos = 0;
167: int mnp = 0;
168: int bitno = 0;
169: char mnemonic[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
170:
171: wordsizes sz = sz_unknown;
172: int srcgather = 0, dstgather = 0;
173: int usesrc = 0, usedst = 0;
174: int srctype = 0;
175: int srcpos, dstpos;
176:
177: amodes srcmode = am_unknown, destmode = am_unknown;
178: int srcreg, destreg;
179:
180: for(i = 0; i < lastbit; i++)
181: bitcnt[i] = bitval[i] = 0;
182:
183: vmsk = 1 << id.n_variable;
184:
185: for(i = 0, msk = 0x8000; i < 16; i++, msk >>= 1) {
186: if (!(msk & id.mask)) {
187: int currbit = id.bitpos[bitno++];
188: int bit_set;
189: vmsk >>= 1;
190: bit_set = variants & vmsk ? 1 : 0;
191: if (bit_set)
192: opc |= msk;
193: bitpos[currbit] = 15 - i;
194: bitcnt[currbit]++;
195: bitval[currbit] <<= 1;
196: bitval[currbit] |= bit_set;
197: }
198: }
199:
200: if (bitval[bitj] == 0) bitval[bitj] = 8;
201: /* first check whether this one does not match after all */
202: if (bitval[bitz] == 3 || bitval[bitC] == 1)
203: continue;
204: if (bitcnt[bitI] && bitval[bitI] == 0)
205: continue;
206:
207: /* bitI and bitC get copied to biti and bitc */
208: if (bitcnt[bitI]) {
209: bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI];
210: }
211: if (bitcnt[bitC])
212: bitval[bitc] = bitval[bitC];
213:
214: pos = 0;
215: while (opcstr[pos] && !isspace(opcstr[pos])) {
216: if (opcstr[pos] == '.') {
217: pos++;
218: switch(opcstr[pos]) {
219:
220: case 'B': sz = sz_byte; break;
221: case 'W': sz = sz_word; break;
222: case 'L': sz = sz_long; break;
223: case 'z':
224: switch(bitval[bitz]) {
225: case 0: sz = sz_byte; break;
226: case 1: sz = sz_word; break;
227: case 2: sz = sz_long; break;
228: default: abort();
229: }
230: break;
231: default: abort();
232: }
233: } else {
234: mnemonic[mnp] = opcstr[pos];
235: if(mnemonic[mnp] == 'f') {
236: switch(bitval[bitf]) {
237: case 0: mnemonic[mnp] = 'R'; break;
238: case 1: mnemonic[mnp] = 'L'; break;
239: default: abort();
240: }
241: }
242: mnp++;
243: }
244: pos++;
245: }
246:
247: /* now, we have read the mnemonic and the size */
248: while (opcstr[pos] && isspace(opcstr[pos]))
249: pos++;
250:
251: /* A goto a day keeps the D******a away. */
252: if (opcstr[pos] == 0)
253: goto endofline;
254:
255: /* parse the source address */
256: usesrc = 1;
257: switch(opcstr[pos++]) {
258: case 'D':
259: srcmode = Dreg;
260: switch (opcstr[pos++]) {
261: case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
262: case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
263: default: abort();
264: }
265:
266: break;
267: case 'A':
268: srcmode = Areg;
269: switch (opcstr[pos++]) {
270: case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
271: case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
272: default: abort();
273: }
274: switch (opcstr[pos]) {
275: case 'p': srcmode = Apdi; pos++; break;
276: case 'P': srcmode = Aipi; pos++; break;
277: }
278: break;
279: case '#':
280: switch(opcstr[pos++]) {
281: case 'z': srcmode = imm; break;
282: case '0': srcmode = imm0; break;
283: case '1': srcmode = imm1; break;
284: case '2': srcmode = imm2; break;
285: case 'i': srcmode = immi; srcreg = (LONG)(BYTE)bitval[biti];
286: if (CPU_EMU_SIZE < 4) {
287: /* Used for branch instructions */
288: srctype = 1;
289: srcgather = 1;
290: srcpos = bitpos[biti];
291: }
292: break;
293: case 'j': srcmode = immi; srcreg = bitval[bitj];
294: if (CPU_EMU_SIZE < 3) {
295: /* 1..8 for ADDQ/SUBQ and rotshi insns */
296: srcgather = 1;
297: srctype = 3;
298: srcpos = bitpos[bitj];
299: }
300: break;
301: case 'J': srcmode = immi; srcreg = bitval[bitJ];
302: if (CPU_EMU_SIZE < 5) {
303: /* 0..15 */
304: srcgather = 1;
305: srctype = 2;
306: srcpos = bitpos[bitJ];
307: }
308: break;
309: default: abort();
310: }
311: break;
312: case 'd':
313: srcreg = bitval[bitD];
314: srcmode = mode_from_mr(bitval[bitd],bitval[bitD]);
315: if (srcmode == am_illg) continue;
316: if (CPU_EMU_SIZE < 2 &&
317: (srcmode == Areg || srcmode == Dreg || srcmode == Aind
318: || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
319: || srcmode == Apdi))
320: {
321: srcgather = 1; srcpos = bitpos[bitD];
322: }
323: if (opcstr[pos] == '[') {
324: pos++;
325: if (opcstr[pos] == '!') {
326: /* exclusion */
327: do {
328: pos++;
329: if (mode_from_str(opcstr+pos) == srcmode)
330: goto nomatch;
331: pos += 4;
332: } while (opcstr[pos] == ',');
333: pos++;
334: } else {
335: if (opcstr[pos+4] == '-') {
336: /* replacement */
337: if (mode_from_str(opcstr+pos) == srcmode)
338: srcmode = mode_from_str(opcstr+pos+5);
339: else
340: goto nomatch;
341: pos += 10;
342: } else {
343: /* normal */
344: while(mode_from_str(opcstr+pos) != srcmode) {
345: pos += 4;
346: if (opcstr[pos] == ']')
347: goto nomatch;
348: pos++;
349: }
350: while(opcstr[pos] != ']') pos++;
351: pos++;
352: break;
353: }
354: }
355: }
356: /* Some addressing modes are invalid as destination */
357: if (srcmode == imm || srcmode == PC16 || srcmode == PC8r)
358: goto nomatch;
359: break;
360: case 's':
361: srcreg = bitval[bitS];
362: srcmode = mode_from_mr(bitval[bits],bitval[bitS]);
363:
364: if (srcmode == am_illg) continue;
365: if (CPU_EMU_SIZE < 2 &&
366: (srcmode == Areg || srcmode == Dreg || srcmode == Aind
367: || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
368: || srcmode == Apdi))
369: {
370: srcgather = 1; srcpos = bitpos[bitS];
371: }
372: if (opcstr[pos] == '[') {
373: pos++;
374: if (opcstr[pos] == '!') {
375: /* exclusion */
376: do {
377: pos++;
378: if (mode_from_str(opcstr+pos) == srcmode)
379: goto nomatch;
380: pos += 4;
381: } while (opcstr[pos] == ',');
382: pos++;
383: } else {
384: if (opcstr[pos+4] == '-') {
385: /* replacement */
386: if (mode_from_str(opcstr+pos) == srcmode)
387: srcmode = mode_from_str(opcstr+pos+5);
388: else
389: goto nomatch;
390: pos += 10;
391: } else {
392: /* normal */
393: while(mode_from_str(opcstr+pos) != srcmode) {
394: pos += 4;
395: if (opcstr[pos] == ']')
396: goto nomatch;
397: pos++;
398: }
399: while(opcstr[pos] != ']') pos++;
400: pos++;
401: }
402: }
403: }
404: break;
405: default: abort();
406: }
407: /* safety check - might have changed */
408: if (srcmode != Areg && srcmode != Dreg && srcmode != Aind
409: && srcmode != Ad16 && srcmode != Ad8r && srcmode != Aipi
410: && srcmode != Apdi && srcmode != immi)
411: {
412: srcgather = 0;
413: }
414: if (srcmode == Areg && sz == sz_byte)
415: goto nomatch;
416:
417: if (opcstr[pos] != ',')
418: goto endofline;
419: pos++;
420:
421: /* parse the destination address */
422: usedst = 1;
423: switch(opcstr[pos++]) {
424: case 'D':
425: destmode = Dreg;
426: switch (opcstr[pos++]) {
427: case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
428: case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
429: default: abort();
430: }
431: break;
432: case 'A':
433: destmode = Areg;
434: switch (opcstr[pos++]) {
435: case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
436: case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
437: default: abort();
438: }
439: switch (opcstr[pos]) {
440: case 'p': destmode = Apdi; pos++; break;
441: case 'P': destmode = Aipi; pos++; break;
442: }
443: break;
444: case '#':
445: switch(opcstr[pos++]) {
446: case 'z': destmode = imm; break;
447: case '0': destmode = imm0; break;
448: case '1': destmode = imm1; break;
449: case '2': destmode = imm2; break;
450: case 'i': destmode = immi; destreg = (LONG)(BYTE)bitval[biti]; break;
451: case 'j': destmode = immi; destreg = bitval[bitj]; break;
452: case 'J': destmode = immi; destreg = bitval[bitJ]; break;
453: default: abort();
454: }
455: break;
456: case 'd':
457: destreg = bitval[bitD];
458: destmode = mode_from_mr(bitval[bitd],bitval[bitD]);
459: if(destmode == am_illg) continue;
460: if (CPU_EMU_SIZE < 1 &&
461: (destmode == Areg || destmode == Dreg || destmode == Aind
462: || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
463: || destmode == Apdi))
464: {
465: dstgather = 1; dstpos = bitpos[bitD];
466: }
467:
468: if (opcstr[pos] == '[') {
469: pos++;
470: if (opcstr[pos] == '!') {
471: /* exclusion */
472: do {
473: pos++;
474: if (mode_from_str(opcstr+pos) == destmode)
475: goto nomatch;
476: pos += 4;
477: } while (opcstr[pos] == ',');
478: pos++;
479: } else {
480: if (opcstr[pos+4] == '-') {
481: /* replacement */
482: if (mode_from_str(opcstr+pos) == destmode)
483: destmode = mode_from_str(opcstr+pos+5);
484: else
485: goto nomatch;
486: pos += 10;
487: } else {
488: /* normal */
489: while(mode_from_str(opcstr+pos) != destmode) {
490: pos += 4;
491: if (opcstr[pos] == ']')
492: goto nomatch;
493: pos++;
494: }
495: while(opcstr[pos] != ']') pos++;
496: pos++;
497: break;
498: }
499: }
500: }
501: /* Some addressing modes are invalid as destination */
502: if (destmode == imm || destmode == PC16 || destmode == PC8r)
503: goto nomatch;
504: break;
505: case 's':
506: destreg = bitval[bitS];
507: destmode = mode_from_mr(bitval[bits],bitval[bitS]);
508:
509: if (destmode == am_illg) continue;
510: if (CPU_EMU_SIZE < 1 &&
511: (destmode == Areg || destmode == Dreg || destmode == Aind
512: || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
513: || destmode == Apdi))
514: {
515: dstgather = 1; dstpos = bitpos[bitS];
516: }
517:
518: if (opcstr[pos] == '[') {
519: pos++;
520: if (opcstr[pos] == '!') {
521: /* exclusion */
522: do {
523: pos++;
524: if (mode_from_str(opcstr+pos) == destmode)
525: goto nomatch;
526: pos += 4;
527: } while (opcstr[pos] == ',');
528: pos++;
529: } else {
530: if (opcstr[pos+4] == '-') {
531: /* replacement */
532: if (mode_from_str(opcstr+pos) == destmode)
533: destmode = mode_from_str(opcstr+pos+5);
534: else
535: goto nomatch;
536: pos += 10;
537: } else {
538: /* normal */
539: while(mode_from_str(opcstr+pos) != destmode) {
540: pos += 4;
541: if (opcstr[pos] == ']')
542: goto nomatch;
543: pos++;
544: }
545: while(opcstr[pos] != ']') pos++;
546: pos++;
547: }
548: }
549: }
550: break;
551: default: abort();
552: }
553: /* safety check - might have changed */
554: if (destmode != Areg && destmode != Dreg && destmode != Aind
555: && destmode != Ad16 && destmode != Ad8r && destmode != Aipi
556: && destmode != Apdi)
557: {
558: dstgather = 0;
559: }
560:
561: if (destmode == Areg && sz == sz_byte)
562: goto nomatch;
563: #if 0
564: if (sz == sz_byte && (destmode == Aipi || destmode == Apdi)) {
565: dstgather = 0;
566: }
567: #endif
568: endofline:
569: /* now, we have a match */
570: if (table68k[opc].mnemo != i_ILLG)
571: fprintf(stderr, "Double match: %x: %s\n", opc, opcstr);
572: for(find = 0;; find++) {
573: if (strcmp(mnemonic, lookuptab[find].name) == 0) {
574: table68k[opc].mnemo = lookuptab[find].mnemo;
575: break;
576: }
577: if (strlen(lookuptab[find].name) == 0) abort();
578: }
579: table68k[opc].cc = bitval[bitc];
580: if (table68k[opc].mnemo == i_BTST
581: || table68k[opc].mnemo == i_BSET
582: || table68k[opc].mnemo == i_BCLR
583: || table68k[opc].mnemo == i_BCHG)
584: {
585: sz = destmode == Dreg ? sz_long : sz_byte;
586: }
587: table68k[opc].size = sz;
588: table68k[opc].sreg = srcreg;
589: table68k[opc].dreg = destreg;
590: table68k[opc].smode = srcmode;
591: table68k[opc].dmode = destmode;
592: table68k[opc].spos = srcgather ? srcpos : -1;
593: table68k[opc].dpos = dstgather ? dstpos : -1;
594: table68k[opc].suse = usesrc;
595: table68k[opc].duse = usedst;
596: table68k[opc].stype = srctype;
597: table68k[opc].plev = id.plevel;
598: nomatch:
599: /* FOO! */;
600: }
601: }
602:
603:
604: void read_table68k ()
605: {
606: int i;
607:
608: table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
609: for(i = 0; i < 65536; i++) {
610: table68k[i].mnemo = i_ILLG;
611: table68k[i].handler = -1;
612: }
613: for (i = 0; i < n_defs68k; i++) {
614: build_insn (i);
615: }
616: }
617:
618: static int mismatch;
619:
620: static void handle_merges(long int opcode)
621: {
622: UWORD smsk;
623: UWORD dmsk;
624: int sbitsrc, sbitdst;
625: int srcreg, dstreg;
626:
627: switch (table68k[opcode].stype) {
628: case 0:
629: smsk = 7; sbitdst = 8; break;
630: case 1:
631: smsk = 255; sbitdst = 256; break;
632: case 2:
633: smsk = 15; sbitdst = 16; break;
634: case 3:
635: smsk = 7; sbitdst = 8; break;
636: }
637: smsk <<= table68k[opcode].spos;
638: dmsk = 7 << table68k[opcode].dpos;
639: sbitsrc = table68k[opcode].spos == -1 ? 0 : 0;
640: if (table68k[opcode].spos == -1) sbitdst = 1;
641: for (srcreg=sbitsrc; srcreg < sbitdst; srcreg++) {
642: for (dstreg=0; dstreg < (table68k[opcode].dpos == -1 ? 1 : 8); dstreg++) {
643: UWORD code = opcode;
644:
645: if (table68k[opcode].spos != -1) code &= ~(smsk << table68k[opcode].spos);
646: if (table68k[opcode].dpos != -1) code &= ~(dmsk << table68k[opcode].dpos);
647:
648: if (table68k[opcode].spos != -1) code |= srcreg << table68k[opcode].spos;
649: if (table68k[opcode].dpos != -1) code |= dstreg << table68k[opcode].dpos;
650:
651: /* Check whether this is in fact the same instruction.
652: * The instructions should never differ, except for the
653: * Bcc.(BW) case. */
654: if (table68k[code].mnemo != table68k[opcode].mnemo
655: || table68k[code].size != table68k[opcode].size
656: || table68k[code].suse != table68k[opcode].suse
657: || table68k[code].duse != table68k[opcode].duse)
658: {
659: mismatch++; continue;
660: }
661: if (table68k[opcode].suse
662: && (table68k[opcode].spos != table68k[code].spos
663: || table68k[opcode].smode != table68k[code].smode
664: || table68k[opcode].stype != table68k[code].stype))
665: {
666: mismatch++; continue;
667: }
668: if (table68k[opcode].duse
669: && (table68k[opcode].dpos != table68k[code].dpos
670: || table68k[opcode].dmode != table68k[code].dmode))
671: {
672: mismatch++; continue;
673: }
674:
675: if (code != opcode)
676: table68k[code].handler = opcode;
677: }
678: }
679: }
680:
681: void do_merges ()
682: {
683: long int opcode;
684: mismatch = 0;
685:
686: for (opcode = 0; opcode < 65536; opcode++) {
687: if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
688: continue;
689: handle_merges (opcode);
690: }
691:
692: }
693:
694: int get_no_mismatches ()
695: {
696: return mismatch;
697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.