ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/readcpu.cpp
Revision: 1.6
Committed: 2002-10-02T15:55:09Z (21 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.5: +0 -14 lines
Log Message:
- Remove dead code in readcpu.cpp concerning CONST_JUMP control flow.
- Replace unused fl_compiled with fl_const_jump
- Implement block inlining enabled with USE_INLINING && USE_CHECKSUM_INFO.
  However, this is currently disabled as it doesn't give much and exhibits
  even more a cache/code generation problem with FPU JIT compiled code.
- Actual checksum values are now integral part of a blockinfo regardless
  of USE_CHECKSUM_INFO is set or not. Reduce number of elements in that
  structure and speeds up a little calculation of checksum of chained blocks.
- Don't care about show_checksum() for now.

File Contents

# Content
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
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 { i_EMULOP_RETURN, "EMULOP_RETURN" },
143 { i_EMULOP, "EMULOP" },
144
145 { 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 int i, n;
202
203 int flaglive = 0, flagdead = 0;
204 int cflow = 0;
205
206 id = defs68k[insn];
207
208 // 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 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 if (bitcnt[bitE] && (bitval[bitE] == 0x00))
296 continue;
297
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 case 'L':
373 srcmode = absl;
374 break;
375 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 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 case 'p': srcmode = immi; srcreg = bitval[bitp];
429 if (CPU_EMU_SIZE < 5) {
430 /* 0..3 */
431 srcgather = 1;
432 srctype = 7;
433 srcpos = bitpos[bitp];
434 }
435 break;
436 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 if (dstpos < 0 || dstpos >= 32)
561 abort();
562 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 case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
569 default: abort();
570 }
571 if (dstpos < 0 || dstpos >= 32)
572 abort();
573 switch (opcstr[pos]) {
574 case 'p': destmode = Apdi; pos++; break;
575 case 'P': destmode = Aipi; pos++; break;
576 }
577 break;
578 case 'L':
579 destmode = absl;
580 break;
581 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
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 table68k[opc].flagdead = flagdead;
758 table68k[opc].flaglive = flaglive;
759 #endif
760 table68k[opc].cflow = cflow;
761 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
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 // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
790 int flags_used = table68k[i].flaglive;
791 if ( (mnemo == i_Scc)
792 || (mnemo == i_Bcc)
793 || (mnemo == i_DBcc)
794 || (mnemo == i_TRAPcc)
795 ) {
796 switch (table68k[i].cc) {
797 // CC mask: XNZVC
798 // 8421
799 case 0: flags_used = 0x00; break; /* T */
800 case 1: flags_used = 0x00; break; /* F */
801 case 2: flags_used = 0x05; break; /* HI */
802 case 3: flags_used = 0x05; break; /* LS */
803 case 4: flags_used = 0x01; break; /* CC */
804 case 5: flags_used = 0x01; break; /* CS */
805 case 6: flags_used = 0x04; break; /* NE */
806 case 7: flags_used = 0x04; break; /* EQ */
807 case 8: flags_used = 0x02; break; /* VC */
808 case 9: flags_used = 0x02; break; /* VS */
809 case 10:flags_used = 0x08; break; /* PL */
810 case 11:flags_used = 0x08; break; /* MI */
811 case 12:flags_used = 0x0A; break; /* GE */
812 case 13:flags_used = 0x0A; break; /* LT */
813 case 14:flags_used = 0x0E; break; /* GT */
814 case 15:flags_used = 0x0E; break; /* LE */
815 }
816 }
817
818 /* Unconditional jumps don't evaluate condition codes, so they
819 don't actually use any flags themselves */
820 if (IS_CONST_JUMP(i))
821 flags_used = 0;
822
823 table68k[i].flaglive = flags_used;
824 }
825 }
826
827 static int mismatch;
828
829 static void handle_merges (long int opcode)
830 {
831 uae_u16 smsk;
832 uae_u16 dmsk;
833 int sbitdst, dstend;
834 int srcreg, dstreg;
835
836 if (table68k[opcode].spos == -1) {
837 sbitdst = 1; smsk = 0;
838 } else {
839 switch (table68k[opcode].stype) {
840 case 0:
841 smsk = 7; sbitdst = 8; break;
842 case 1:
843 smsk = 255; sbitdst = 256; break;
844 case 2:
845 smsk = 15; sbitdst = 16; break;
846 case 3:
847 smsk = 7; sbitdst = 8; break;
848 case 4:
849 smsk = 7; sbitdst = 8; break;
850 case 5:
851 smsk = 63; sbitdst = 64; break;
852 case 6:
853 smsk = 255; sbitdst = 256; break;
854 case 7:
855 smsk = 3; sbitdst = 4; break;
856 default:
857 smsk = 0; sbitdst = 0;
858 abort();
859 break;
860 }
861 smsk <<= table68k[opcode].spos;
862 }
863 if (table68k[opcode].dpos == -1) {
864 dstend = 1; dmsk = 0;
865 } else {
866 dmsk = 7 << table68k[opcode].dpos;
867 dstend = 8;
868 }
869 for (srcreg=0; srcreg < sbitdst; srcreg++) {
870 for (dstreg=0; dstreg < dstend; dstreg++) {
871 uae_u16 code = opcode;
872
873 code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
874 code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
875
876 /* Check whether this is in fact the same instruction.
877 * The instructions should never differ, except for the
878 * Bcc.(BW) case. */
879 if (table68k[code].mnemo != table68k[opcode].mnemo
880 || table68k[code].size != table68k[opcode].size
881 || table68k[code].suse != table68k[opcode].suse
882 || table68k[code].duse != table68k[opcode].duse)
883 {
884 mismatch++; continue;
885 }
886 if (table68k[opcode].suse
887 && (table68k[opcode].spos != table68k[code].spos
888 || table68k[opcode].smode != table68k[code].smode
889 || table68k[opcode].stype != table68k[code].stype))
890 {
891 mismatch++; continue;
892 }
893 if (table68k[opcode].duse
894 && (table68k[opcode].dpos != table68k[code].dpos
895 || table68k[opcode].dmode != table68k[code].dmode))
896 {
897 mismatch++; continue;
898 }
899
900 if (code != opcode)
901 table68k[code].handler = opcode;
902 }
903 }
904 }
905
906 void do_merges (void)
907 {
908 long int opcode;
909 int nr = 0;
910 mismatch = 0;
911 for (opcode = 0; opcode < 65536; opcode++) {
912 if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
913 continue;
914 nr++;
915 handle_merges (opcode);
916 }
917 nr_cpuop_funcs = nr;
918 }
919
920 int get_no_mismatches (void)
921 {
922 return mismatch;
923 }