ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/readcpu.cpp
Revision: 1.7
Committed: 2002-10-03T15:05:01Z (21 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.6: +5 -0 lines
Log Message:
- Turn on runtime detection of loop and jump alignment as Aranym people
  reported they got some improvement with it and larger loops. Small
  loops are an issue for now until unrolling is implemented for DBcc.
- Const jumps are identified in readcpu. I don't want to duplicate code
  uselessly. Rather, it's the JIT job to know whether we are doing block
  inlining and un-marking those instructions as end-of-block.

File Contents

# User Rev Content
1 cebix 1.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 <stdio.h>
10     #include <stdlib.h>
11     #include <string.h>
12     #include <ctype.h>
13    
14     #include "sysdeps.h"
15     #include "readcpu.h"
16    
17     int nr_cpuop_funcs;
18    
19     struct mnemolookup lookuptab[] = {
20     { i_ILLG, "ILLEGAL" },
21     { i_OR, "OR" },
22     { i_CHK, "CHK" },
23     { i_CHK2, "CHK2" },
24     { i_AND, "AND" },
25     { i_EOR, "EOR" },
26     { i_ORSR, "ORSR" },
27     { i_ANDSR, "ANDSR" },
28     { i_EORSR, "EORSR" },
29     { i_SUB, "SUB" },
30     { i_SUBA, "SUBA" },
31     { i_SUBX, "SUBX" },
32     { i_SBCD, "SBCD" },
33     { i_ADD, "ADD" },
34     { i_ADDA, "ADDA" },
35     { i_ADDX, "ADDX" },
36     { i_ABCD, "ABCD" },
37     { i_NEG, "NEG" },
38     { i_NEGX, "NEGX" },
39     { i_NBCD, "NBCD" },
40     { i_CLR, "CLR" },
41     { i_NOT, "NOT" },
42     { i_TST, "TST" },
43     { i_BTST, "BTST" },
44     { i_BCHG, "BCHG" },
45     { i_BCLR, "BCLR" },
46     { i_BSET, "BSET" },
47     { i_CMP, "CMP" },
48     { i_CMPM, "CMPM" },
49     { i_CMPA, "CMPA" },
50     { i_MVPRM, "MVPRM" },
51     { i_MVPMR, "MVPMR" },
52     { i_MOVE, "MOVE" },
53     { i_MOVEA, "MOVEA" },
54     { i_MVSR2, "MVSR2" },
55     { i_MV2SR, "MV2SR" },
56     { i_SWAP, "SWAP" },
57     { i_EXG, "EXG" },
58     { i_EXT, "EXT" },
59     { i_MVMEL, "MVMEL" },
60     { i_MVMLE, "MVMLE" },
61     { i_TRAP, "TRAP" },
62     { i_MVR2USP, "MVR2USP" },
63     { i_MVUSP2R, "MVUSP2R" },
64     { i_NOP, "NOP" },
65     { i_RESET, "RESET" },
66     { i_RTE, "RTE" },
67     { i_RTD, "RTD" },
68     { i_LINK, "LINK" },
69     { i_UNLK, "UNLK" },
70     { i_RTS, "RTS" },
71     { i_STOP, "STOP" },
72     { i_TRAPV, "TRAPV" },
73     { i_RTR, "RTR" },
74     { i_JSR, "JSR" },
75     { i_JMP, "JMP" },
76     { i_BSR, "BSR" },
77     { i_Bcc, "Bcc" },
78     { i_LEA, "LEA" },
79     { i_PEA, "PEA" },
80     { i_DBcc, "DBcc" },
81     { i_Scc, "Scc" },
82     { i_DIVU, "DIVU" },
83     { i_DIVS, "DIVS" },
84     { i_MULU, "MULU" },
85     { i_MULS, "MULS" },
86     { i_ASR, "ASR" },
87     { i_ASL, "ASL" },
88     { i_LSR, "LSR" },
89     { i_LSL, "LSL" },
90     { i_ROL, "ROL" },
91     { i_ROR, "ROR" },
92     { i_ROXL, "ROXL" },
93     { i_ROXR, "ROXR" },
94     { i_ASRW, "ASRW" },
95     { i_ASLW, "ASLW" },
96     { i_LSRW, "LSRW" },
97     { i_LSLW, "LSLW" },
98     { i_ROLW, "ROLW" },
99     { i_RORW, "RORW" },
100     { i_ROXLW, "ROXLW" },
101     { i_ROXRW, "ROXRW" },
102    
103     { i_MOVE2C, "MOVE2C" },
104     { i_MOVEC2, "MOVEC2" },
105     { i_CAS, "CAS" },
106     { i_CAS2, "CAS2" },
107     { i_MULL, "MULL" },
108     { i_DIVL, "DIVL" },
109     { i_BFTST, "BFTST" },
110     { i_BFEXTU, "BFEXTU" },
111     { i_BFCHG, "BFCHG" },
112     { i_BFEXTS, "BFEXTS" },
113     { i_BFCLR, "BFCLR" },
114     { i_BFFFO, "BFFFO" },
115     { i_BFSET, "BFSET" },
116     { i_BFINS, "BFINS" },
117     { i_PACK, "PACK" },
118     { i_UNPK, "UNPK" },
119     { i_TAS, "TAS" },
120     { i_BKPT, "BKPT" },
121     { i_CALLM, "CALLM" },
122     { i_RTM, "RTM" },
123     { i_TRAPcc, "TRAPcc" },
124     { i_MOVES, "MOVES" },
125     { i_FPP, "FPP" },
126     { i_FDBcc, "FDBcc" },
127     { i_FScc, "FScc" },
128     { i_FTRAPcc, "FTRAPcc" },
129     { i_FBcc, "FBcc" },
130     { i_FBcc, "FBcc" },
131     { i_FSAVE, "FSAVE" },
132     { i_FRESTORE, "FRESTORE" },
133 cebix 1.2
134     { i_CINVL, "CINVL" },
135     { i_CINVP, "CINVP" },
136     { i_CINVA, "CINVA" },
137     { i_CPUSHL, "CPUSHL" },
138     { i_CPUSHP, "CPUSHP" },
139     { i_CPUSHA, "CPUSHA" },
140     { i_MOVE16, "MOVE16" },
141    
142 gbeauche 1.5 { i_EMULOP_RETURN, "EMULOP_RETURN" },
143     { i_EMULOP, "EMULOP" },
144    
145 cebix 1.1 { i_MMUOP, "MMUOP" },
146     { i_ILLG, "" },
147     };
148    
149     struct instr *table68k;
150    
151     static __inline__ amodes mode_from_str (const char *str)
152     {
153     if (strncmp (str, "Dreg", 4) == 0) return Dreg;
154     if (strncmp (str, "Areg", 4) == 0) return Areg;
155     if (strncmp (str, "Aind", 4) == 0) return Aind;
156     if (strncmp (str, "Apdi", 4) == 0) return Apdi;
157     if (strncmp (str, "Aipi", 4) == 0) return Aipi;
158     if (strncmp (str, "Ad16", 4) == 0) return Ad16;
159     if (strncmp (str, "Ad8r", 4) == 0) return Ad8r;
160     if (strncmp (str, "absw", 4) == 0) return absw;
161     if (strncmp (str, "absl", 4) == 0) return absl;
162     if (strncmp (str, "PC16", 4) == 0) return PC16;
163     if (strncmp (str, "PC8r", 4) == 0) return PC8r;
164     if (strncmp (str, "Immd", 4) == 0) return imm;
165     abort ();
166     return (amodes)0;
167     }
168    
169     static __inline__ amodes mode_from_mr (int mode, int reg)
170     {
171     switch (mode) {
172     case 0: return Dreg;
173     case 1: return Areg;
174     case 2: return Aind;
175     case 3: return Aipi;
176     case 4: return Apdi;
177     case 5: return Ad16;
178     case 6: return Ad8r;
179     case 7:
180     switch (reg) {
181     case 0: return absw;
182     case 1: return absl;
183     case 2: return PC16;
184     case 3: return PC8r;
185     case 4: return imm;
186     case 5:
187     case 6:
188     case 7: return am_illg;
189     }
190     }
191     abort ();
192     return (amodes)0;
193     }
194    
195     static void build_insn (int insn)
196     {
197     int find = -1;
198     int variants;
199     struct instr_def id;
200     const char *opcstr;
201 gbeauche 1.5 int i, n;
202 cebix 1.1
203     int flaglive = 0, flagdead = 0;
204 gbeauche 1.5 int cflow = 0;
205 cebix 1.1
206     id = defs68k[insn];
207    
208 gbeauche 1.5 // Control flow information
209     cflow = id.cflow;
210    
211     // Mask of flags set/used
212     unsigned char flags_set(0), flags_used(0);
213    
214     for (i = 0, n = 4; i < 5; i++, n--) {
215     switch (id.flaginfo[i].flagset) {
216     case fa_unset: case fa_isjmp: break;
217     default: flags_set |= (1 << n);
218     }
219    
220     switch (id.flaginfo[i].flaguse) {
221     case fu_unused: case fu_isjmp: break;
222     default: flags_used |= (1 << n);
223     }
224     }
225    
226 cebix 1.1 for (i = 0; i < 5; i++) {
227     switch (id.flaginfo[i].flagset){
228     case fa_unset: break;
229     case fa_zero: flagdead |= 1 << i; break;
230     case fa_one: flagdead |= 1 << i; break;
231     case fa_dontcare: flagdead |= 1 << i; break;
232     case fa_unknown: flagdead = -1; goto out1;
233     case fa_set: flagdead |= 1 << i; break;
234     }
235     }
236    
237     out1:
238     for (i = 0; i < 5; i++) {
239     switch (id.flaginfo[i].flaguse) {
240     case fu_unused: break;
241     case fu_unknown: flaglive = -1; goto out2;
242     case fu_used: flaglive |= 1 << i; break;
243     }
244     }
245     out2:
246    
247     opcstr = id.opcstr;
248     for (variants = 0; variants < (1 << id.n_variable); variants++) {
249     int bitcnt[lastbit];
250     int bitval[lastbit];
251     int bitpos[lastbit];
252     int i;
253     uae_u16 opc = id.bits;
254     uae_u16 msk, vmsk;
255     int pos = 0;
256     int mnp = 0;
257     int bitno = 0;
258     char mnemonic[10];
259    
260     wordsizes sz = sz_long;
261     int srcgather = 0, dstgather = 0;
262     int usesrc = 0, usedst = 0;
263     int srctype = 0;
264     int srcpos = -1, dstpos = -1;
265    
266     amodes srcmode = am_unknown, destmode = am_unknown;
267     int srcreg = -1, destreg = -1;
268    
269     for (i = 0; i < lastbit; i++)
270     bitcnt[i] = bitval[i] = 0;
271    
272     vmsk = 1 << id.n_variable;
273    
274     for (i = 0, msk = 0x8000; i < 16; i++, msk >>= 1) {
275     if (!(msk & id.mask)) {
276     int currbit = id.bitpos[bitno++];
277     int bit_set;
278     vmsk >>= 1;
279     bit_set = variants & vmsk ? 1 : 0;
280     if (bit_set)
281     opc |= msk;
282     bitpos[currbit] = 15 - i;
283     bitcnt[currbit]++;
284     bitval[currbit] <<= 1;
285     bitval[currbit] |= bit_set;
286     }
287     }
288    
289     if (bitval[bitj] == 0) bitval[bitj] = 8;
290     /* first check whether this one does not match after all */
291     if (bitval[bitz] == 3 || bitval[bitC] == 1)
292     continue;
293     if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
294     continue;
295 gbeauche 1.5 if (bitcnt[bitE] && (bitval[bitE] == 0x00))
296     continue;
297 cebix 1.1
298     /* bitI and bitC get copied to biti and bitc */
299     if (bitcnt[bitI]) {
300     bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI];
301     }
302     if (bitcnt[bitC])
303     bitval[bitc] = bitval[bitC];
304    
305     pos = 0;
306     while (opcstr[pos] && !isspace(opcstr[pos])) {
307     if (opcstr[pos] == '.') {
308     pos++;
309     switch (opcstr[pos]) {
310    
311     case 'B': sz = sz_byte; break;
312     case 'W': sz = sz_word; break;
313     case 'L': sz = sz_long; break;
314     case 'z':
315     switch (bitval[bitz]) {
316     case 0: sz = sz_byte; break;
317     case 1: sz = sz_word; break;
318     case 2: sz = sz_long; break;
319     default: abort();
320     }
321     break;
322     default: abort();
323     }
324     } else {
325     mnemonic[mnp] = opcstr[pos];
326     if (mnemonic[mnp] == 'f') {
327     find = -1;
328     switch (bitval[bitf]) {
329     case 0: mnemonic[mnp] = 'R'; break;
330     case 1: mnemonic[mnp] = 'L'; break;
331     default: abort();
332     }
333     }
334     mnp++;
335     }
336     pos++;
337     }
338     mnemonic[mnp] = 0;
339    
340     /* now, we have read the mnemonic and the size */
341     while (opcstr[pos] && isspace(opcstr[pos]))
342     pos++;
343    
344     /* A goto a day keeps the D******a away. */
345     if (opcstr[pos] == 0)
346     goto endofline;
347    
348     /* parse the source address */
349     usesrc = 1;
350     switch (opcstr[pos++]) {
351     case 'D':
352     srcmode = Dreg;
353     switch (opcstr[pos++]) {
354     case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
355     case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
356     default: abort();
357     }
358    
359     break;
360     case 'A':
361     srcmode = Areg;
362     switch (opcstr[pos++]) {
363     case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
364     case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
365     default: abort();
366     }
367     switch (opcstr[pos]) {
368     case 'p': srcmode = Apdi; pos++; break;
369     case 'P': srcmode = Aipi; pos++; break;
370     }
371     break;
372 gbeauche 1.4 case 'L':
373     srcmode = absl;
374     break;
375 cebix 1.1 case '#':
376     switch (opcstr[pos++]) {
377     case 'z': srcmode = imm; break;
378     case '0': srcmode = imm0; break;
379     case '1': srcmode = imm1; break;
380     case '2': srcmode = imm2; break;
381     case 'i': srcmode = immi; srcreg = (uae_s32)(uae_s8)bitval[biti];
382     if (CPU_EMU_SIZE < 4) {
383     /* Used for branch instructions */
384     srctype = 1;
385     srcgather = 1;
386     srcpos = bitpos[biti];
387     }
388     break;
389     case 'j': srcmode = immi; srcreg = bitval[bitj];
390     if (CPU_EMU_SIZE < 3) {
391     /* 1..8 for ADDQ/SUBQ and rotshi insns */
392     srcgather = 1;
393     srctype = 3;
394     srcpos = bitpos[bitj];
395     }
396     break;
397     case 'J': srcmode = immi; srcreg = bitval[bitJ];
398     if (CPU_EMU_SIZE < 5) {
399     /* 0..15 */
400     srcgather = 1;
401     srctype = 2;
402     srcpos = bitpos[bitJ];
403     }
404     break;
405     case 'k': srcmode = immi; srcreg = bitval[bitk];
406     if (CPU_EMU_SIZE < 3) {
407     srcgather = 1;
408     srctype = 4;
409     srcpos = bitpos[bitk];
410     }
411     break;
412     case 'K': srcmode = immi; srcreg = bitval[bitK];
413     if (CPU_EMU_SIZE < 5) {
414     /* 0..15 */
415     srcgather = 1;
416     srctype = 5;
417     srcpos = bitpos[bitK];
418     }
419     break;
420 gbeauche 1.5 case 'E': srcmode = immi; srcreg = bitval[bitE];
421     if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
422     /* 1..255 */
423     srcgather = 1;
424     srctype = 6;
425     srcpos = bitpos[bitE];
426     }
427     break;
428 gbeauche 1.3 case 'p': srcmode = immi; srcreg = bitval[bitp];
429 gbeauche 1.4 if (CPU_EMU_SIZE < 5) {
430 gbeauche 1.3 /* 0..3 */
431     srcgather = 1;
432     srctype = 7;
433     srcpos = bitpos[bitp];
434     }
435     break;
436 cebix 1.1 default: abort();
437     }
438     break;
439     case 'd':
440     srcreg = bitval[bitD];
441     srcmode = mode_from_mr(bitval[bitd],bitval[bitD]);
442     if (srcmode == am_illg)
443     continue;
444     if (CPU_EMU_SIZE < 2 &&
445     (srcmode == Areg || srcmode == Dreg || srcmode == Aind
446     || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
447     || srcmode == Apdi))
448     {
449     srcgather = 1; srcpos = bitpos[bitD];
450     }
451     if (opcstr[pos] == '[') {
452     pos++;
453     if (opcstr[pos] == '!') {
454     /* exclusion */
455     do {
456     pos++;
457     if (mode_from_str(opcstr+pos) == srcmode)
458     goto nomatch;
459     pos += 4;
460     } while (opcstr[pos] == ',');
461     pos++;
462     } else {
463     if (opcstr[pos+4] == '-') {
464     /* replacement */
465     if (mode_from_str(opcstr+pos) == srcmode)
466     srcmode = mode_from_str(opcstr+pos+5);
467     else
468     goto nomatch;
469     pos += 10;
470     } else {
471     /* normal */
472     while(mode_from_str(opcstr+pos) != srcmode) {
473     pos += 4;
474     if (opcstr[pos] == ']')
475     goto nomatch;
476     pos++;
477     }
478     while(opcstr[pos] != ']') pos++;
479     pos++;
480     break;
481     }
482     }
483     }
484     /* Some addressing modes are invalid as destination */
485     if (srcmode == imm || srcmode == PC16 || srcmode == PC8r)
486     goto nomatch;
487     break;
488     case 's':
489     srcreg = bitval[bitS];
490     srcmode = mode_from_mr(bitval[bits],bitval[bitS]);
491    
492     if (srcmode == am_illg)
493     continue;
494     if (CPU_EMU_SIZE < 2 &&
495     (srcmode == Areg || srcmode == Dreg || srcmode == Aind
496     || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi
497     || srcmode == Apdi))
498     {
499     srcgather = 1; srcpos = bitpos[bitS];
500     }
501     if (opcstr[pos] == '[') {
502     pos++;
503     if (opcstr[pos] == '!') {
504     /* exclusion */
505     do {
506     pos++;
507     if (mode_from_str(opcstr+pos) == srcmode)
508     goto nomatch;
509     pos += 4;
510     } while (opcstr[pos] == ',');
511     pos++;
512     } else {
513     if (opcstr[pos+4] == '-') {
514     /* replacement */
515     if (mode_from_str(opcstr+pos) == srcmode)
516     srcmode = mode_from_str(opcstr+pos+5);
517     else
518     goto nomatch;
519     pos += 10;
520     } else {
521     /* normal */
522     while(mode_from_str(opcstr+pos) != srcmode) {
523     pos += 4;
524     if (opcstr[pos] == ']')
525     goto nomatch;
526     pos++;
527     }
528     while(opcstr[pos] != ']') pos++;
529     pos++;
530     }
531     }
532     }
533     break;
534     default: abort();
535     }
536     /* safety check - might have changed */
537     if (srcmode != Areg && srcmode != Dreg && srcmode != Aind
538     && srcmode != Ad16 && srcmode != Ad8r && srcmode != Aipi
539     && srcmode != Apdi && srcmode != immi)
540     {
541     srcgather = 0;
542     }
543     if (srcmode == Areg && sz == sz_byte)
544     goto nomatch;
545    
546     if (opcstr[pos] != ',')
547     goto endofline;
548     pos++;
549    
550     /* parse the destination address */
551     usedst = 1;
552     switch (opcstr[pos++]) {
553     case 'D':
554     destmode = Dreg;
555     switch (opcstr[pos++]) {
556     case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
557     case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
558     default: abort();
559     }
560 gbeauche 1.4 if (dstpos < 0 || dstpos >= 32)
561     abort();
562 cebix 1.1 break;
563     case 'A':
564     destmode = Areg;
565     switch (opcstr[pos++]) {
566     case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
567     case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
568 gbeauche 1.4 case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
569 cebix 1.1 default: abort();
570     }
571 gbeauche 1.4 if (dstpos < 0 || dstpos >= 32)
572     abort();
573 cebix 1.1 switch (opcstr[pos]) {
574     case 'p': destmode = Apdi; pos++; break;
575     case 'P': destmode = Aipi; pos++; break;
576     }
577     break;
578 gbeauche 1.4 case 'L':
579     destmode = absl;
580     break;
581 cebix 1.1 case '#':
582     switch (opcstr[pos++]) {
583     case 'z': destmode = imm; break;
584     case '0': destmode = imm0; break;
585     case '1': destmode = imm1; break;
586     case '2': destmode = imm2; break;
587     case 'i': destmode = immi; destreg = (uae_s32)(uae_s8)bitval[biti]; break;
588     case 'j': destmode = immi; destreg = bitval[bitj]; break;
589     case 'J': destmode = immi; destreg = bitval[bitJ]; break;
590     case 'k': destmode = immi; destreg = bitval[bitk]; break;
591     case 'K': destmode = immi; destreg = bitval[bitK]; break;
592     default: abort();
593     }
594     break;
595     case 'd':
596     destreg = bitval[bitD];
597     destmode = mode_from_mr(bitval[bitd],bitval[bitD]);
598     if (destmode == am_illg)
599     continue;
600     if (CPU_EMU_SIZE < 1 &&
601     (destmode == Areg || destmode == Dreg || destmode == Aind
602     || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
603     || destmode == Apdi))
604     {
605     dstgather = 1; dstpos = bitpos[bitD];
606     }
607    
608     if (opcstr[pos] == '[') {
609     pos++;
610     if (opcstr[pos] == '!') {
611     /* exclusion */
612     do {
613     pos++;
614     if (mode_from_str(opcstr+pos) == destmode)
615     goto nomatch;
616     pos += 4;
617     } while (opcstr[pos] == ',');
618     pos++;
619     } else {
620     if (opcstr[pos+4] == '-') {
621     /* replacement */
622     if (mode_from_str(opcstr+pos) == destmode)
623     destmode = mode_from_str(opcstr+pos+5);
624     else
625     goto nomatch;
626     pos += 10;
627     } else {
628     /* normal */
629     while(mode_from_str(opcstr+pos) != destmode) {
630     pos += 4;
631     if (opcstr[pos] == ']')
632     goto nomatch;
633     pos++;
634     }
635     while(opcstr[pos] != ']') pos++;
636     pos++;
637     break;
638     }
639     }
640     }
641     /* Some addressing modes are invalid as destination */
642     if (destmode == imm || destmode == PC16 || destmode == PC8r)
643     goto nomatch;
644     break;
645     case 's':
646     destreg = bitval[bitS];
647     destmode = mode_from_mr(bitval[bits],bitval[bitS]);
648    
649     if (destmode == am_illg)
650     continue;
651     if (CPU_EMU_SIZE < 1 &&
652     (destmode == Areg || destmode == Dreg || destmode == Aind
653     || destmode == Ad16 || destmode == Ad8r || destmode == Aipi
654     || destmode == Apdi))
655     {
656     dstgather = 1; dstpos = bitpos[bitS];
657     }
658    
659     if (opcstr[pos] == '[') {
660     pos++;
661     if (opcstr[pos] == '!') {
662     /* exclusion */
663     do {
664     pos++;
665     if (mode_from_str(opcstr+pos) == destmode)
666     goto nomatch;
667     pos += 4;
668     } while (opcstr[pos] == ',');
669     pos++;
670     } else {
671     if (opcstr[pos+4] == '-') {
672     /* replacement */
673     if (mode_from_str(opcstr+pos) == destmode)
674     destmode = mode_from_str(opcstr+pos+5);
675     else
676     goto nomatch;
677     pos += 10;
678     } else {
679     /* normal */
680     while(mode_from_str(opcstr+pos) != destmode) {
681     pos += 4;
682     if (opcstr[pos] == ']')
683     goto nomatch;
684     pos++;
685     }
686     while(opcstr[pos] != ']') pos++;
687     pos++;
688     }
689     }
690     }
691     break;
692     default: abort();
693     }
694     /* safety check - might have changed */
695     if (destmode != Areg && destmode != Dreg && destmode != Aind
696     && destmode != Ad16 && destmode != Ad8r && destmode != Aipi
697     && destmode != Apdi)
698     {
699     dstgather = 0;
700     }
701    
702     if (destmode == Areg && sz == sz_byte)
703     goto nomatch;
704     #if 0
705     if (sz == sz_byte && (destmode == Aipi || destmode == Apdi)) {
706     dstgather = 0;
707     }
708     #endif
709     endofline:
710     /* now, we have a match */
711     if (table68k[opc].mnemo != i_ILLG)
712     fprintf(stderr, "Double match: %x: %s\n", opc, opcstr);
713     if (find == -1) {
714     for (find = 0;; find++) {
715     if (strcmp(mnemonic, lookuptab[find].name) == 0) {
716     table68k[opc].mnemo = lookuptab[find].mnemo;
717     break;
718     }
719     if (strlen(lookuptab[find].name) == 0) abort();
720     }
721     }
722     else {
723     table68k[opc].mnemo = lookuptab[find].mnemo;
724     }
725     table68k[opc].cc = bitval[bitc];
726     if (table68k[opc].mnemo == i_BTST
727     || table68k[opc].mnemo == i_BSET
728     || table68k[opc].mnemo == i_BCLR
729     || table68k[opc].mnemo == i_BCHG)
730     {
731     sz = destmode == Dreg ? sz_long : sz_byte;
732     }
733     table68k[opc].size = sz;
734     table68k[opc].sreg = srcreg;
735     table68k[opc].dreg = destreg;
736     table68k[opc].smode = srcmode;
737     table68k[opc].dmode = destmode;
738     table68k[opc].spos = srcgather ? srcpos : -1;
739     table68k[opc].dpos = dstgather ? dstpos : -1;
740     table68k[opc].suse = usesrc;
741     table68k[opc].duse = usedst;
742     table68k[opc].stype = srctype;
743     table68k[opc].plev = id.plevel;
744     table68k[opc].clev = id.cpulevel;
745     #if 0
746     for (i = 0; i < 5; i++) {
747     table68k[opc].flaginfo[i].flagset = id.flaginfo[i].flagset;
748     table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
749     }
750     #endif
751 gbeauche 1.5
752     #if 1
753     /* gb-- flagdead and flaglive would not have correct information */
754     table68k[opc].flagdead = flags_set;
755     table68k[opc].flaglive = flags_used;
756     #else
757 cebix 1.1 table68k[opc].flagdead = flagdead;
758     table68k[opc].flaglive = flaglive;
759 gbeauche 1.5 #endif
760     table68k[opc].cflow = cflow;
761 cebix 1.1 nomatch:
762     /* FOO! */;
763     }
764     }
765    
766    
767     void read_table68k (void)
768     {
769     int i;
770    
771     table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
772     for (i = 0; i < 65536; i++) {
773     table68k[i].mnemo = i_ILLG;
774     table68k[i].handler = -1;
775     }
776     for (i = 0; i < n_defs68k; i++) {
777     build_insn (i);
778     }
779 gbeauche 1.5
780     /* Extra fixes in table68k for control flow information and flag usage */
781     for (i = 0; i < 65536; i++) {
782     instrmnem mnemo = (instrmnem)(table68k[i].mnemo);
783    
784     #define IS_CONST_JUMP(opc) \
785     ( ((table68k[opc].mnemo == i_Bcc) && (table68k[opc].cc < 2)) \
786     || (table68k[opc].mnemo == i_BSR) \
787     )
788    
789 gbeauche 1.7 // Precise const jumps as such. The JIT compiler will take
790     // care to actually enable that optimization or not
791     if (IS_CONST_JUMP(i))
792     table68k[i].cflow |= fl_const_jump;
793    
794 gbeauche 1.5 // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
795     int flags_used = table68k[i].flaglive;
796     if ( (mnemo == i_Scc)
797     || (mnemo == i_Bcc)
798     || (mnemo == i_DBcc)
799     || (mnemo == i_TRAPcc)
800     ) {
801     switch (table68k[i].cc) {
802     // CC mask: XNZVC
803     // 8421
804     case 0: flags_used = 0x00; break; /* T */
805     case 1: flags_used = 0x00; break; /* F */
806     case 2: flags_used = 0x05; break; /* HI */
807     case 3: flags_used = 0x05; break; /* LS */
808     case 4: flags_used = 0x01; break; /* CC */
809     case 5: flags_used = 0x01; break; /* CS */
810     case 6: flags_used = 0x04; break; /* NE */
811     case 7: flags_used = 0x04; break; /* EQ */
812     case 8: flags_used = 0x02; break; /* VC */
813     case 9: flags_used = 0x02; break; /* VS */
814     case 10:flags_used = 0x08; break; /* PL */
815     case 11:flags_used = 0x08; break; /* MI */
816     case 12:flags_used = 0x0A; break; /* GE */
817     case 13:flags_used = 0x0A; break; /* LT */
818     case 14:flags_used = 0x0E; break; /* GT */
819     case 15:flags_used = 0x0E; break; /* LE */
820     }
821     }
822    
823     /* Unconditional jumps don't evaluate condition codes, so they
824     don't actually use any flags themselves */
825     if (IS_CONST_JUMP(i))
826     flags_used = 0;
827    
828     table68k[i].flaglive = flags_used;
829     }
830 cebix 1.1 }
831    
832     static int mismatch;
833    
834     static void handle_merges (long int opcode)
835     {
836     uae_u16 smsk;
837     uae_u16 dmsk;
838     int sbitdst, dstend;
839     int srcreg, dstreg;
840    
841     if (table68k[opcode].spos == -1) {
842     sbitdst = 1; smsk = 0;
843     } else {
844     switch (table68k[opcode].stype) {
845     case 0:
846     smsk = 7; sbitdst = 8; break;
847     case 1:
848     smsk = 255; sbitdst = 256; break;
849     case 2:
850     smsk = 15; sbitdst = 16; break;
851     case 3:
852     smsk = 7; sbitdst = 8; break;
853     case 4:
854     smsk = 7; sbitdst = 8; break;
855     case 5:
856     smsk = 63; sbitdst = 64; break;
857 gbeauche 1.5 case 6:
858     smsk = 255; sbitdst = 256; break;
859 gbeauche 1.3 case 7:
860     smsk = 3; sbitdst = 4; break;
861 cebix 1.1 default:
862     smsk = 0; sbitdst = 0;
863     abort();
864     break;
865     }
866     smsk <<= table68k[opcode].spos;
867     }
868     if (table68k[opcode].dpos == -1) {
869     dstend = 1; dmsk = 0;
870     } else {
871     dmsk = 7 << table68k[opcode].dpos;
872     dstend = 8;
873     }
874     for (srcreg=0; srcreg < sbitdst; srcreg++) {
875     for (dstreg=0; dstreg < dstend; dstreg++) {
876     uae_u16 code = opcode;
877    
878     code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
879     code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
880    
881     /* Check whether this is in fact the same instruction.
882     * The instructions should never differ, except for the
883     * Bcc.(BW) case. */
884     if (table68k[code].mnemo != table68k[opcode].mnemo
885     || table68k[code].size != table68k[opcode].size
886     || table68k[code].suse != table68k[opcode].suse
887     || table68k[code].duse != table68k[opcode].duse)
888     {
889     mismatch++; continue;
890     }
891     if (table68k[opcode].suse
892     && (table68k[opcode].spos != table68k[code].spos
893     || table68k[opcode].smode != table68k[code].smode
894     || table68k[opcode].stype != table68k[code].stype))
895     {
896     mismatch++; continue;
897     }
898     if (table68k[opcode].duse
899     && (table68k[opcode].dpos != table68k[code].dpos
900     || table68k[opcode].dmode != table68k[code].dmode))
901     {
902     mismatch++; continue;
903     }
904    
905     if (code != opcode)
906     table68k[code].handler = opcode;
907     }
908     }
909     }
910    
911     void do_merges (void)
912     {
913     long int opcode;
914     int nr = 0;
915     mismatch = 0;
916     for (opcode = 0; opcode < 65536; opcode++) {
917     if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
918     continue;
919     nr++;
920     handle_merges (opcode);
921     }
922     nr_cpuop_funcs = nr;
923     }
924    
925     int get_no_mismatches (void)
926     {
927     return mismatch;
928     }