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

# 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 // 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 // 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 }
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 case 6:
858 smsk = 255; sbitdst = 256; break;
859 case 7:
860 smsk = 3; sbitdst = 4; break;
861 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 }