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 |
|
|
#if 0 |
790 |
|
|
// gb-- Don't follow false and true branches as we may not be |
791 |
|
|
// able to determine the whole block length in bytes in order |
792 |
|
|
// to compute the block checksum |
793 |
|
|
|
794 |
|
|
// We can follow unconditional jumps if neither Lazy Flusher |
795 |
|
|
// nor Dynamic Code Patches feature is enabled |
796 |
|
|
|
797 |
|
|
// UPDATE: this is no longer permitted since we can decide |
798 |
|
|
// at runtime whether the JIT compiler is used or not |
799 |
|
|
if (IS_CONST_JUMP(i)) |
800 |
|
|
table68k[i].cflow = fl_normal; |
801 |
|
|
#endif |
802 |
|
|
|
803 |
|
|
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions |
804 |
|
|
int flags_used = table68k[i].flaglive; |
805 |
|
|
if ( (mnemo == i_Scc) |
806 |
|
|
|| (mnemo == i_Bcc) |
807 |
|
|
|| (mnemo == i_DBcc) |
808 |
|
|
|| (mnemo == i_TRAPcc) |
809 |
|
|
) { |
810 |
|
|
switch (table68k[i].cc) { |
811 |
|
|
// CC mask: XNZVC |
812 |
|
|
// 8421 |
813 |
|
|
case 0: flags_used = 0x00; break; /* T */ |
814 |
|
|
case 1: flags_used = 0x00; break; /* F */ |
815 |
|
|
case 2: flags_used = 0x05; break; /* HI */ |
816 |
|
|
case 3: flags_used = 0x05; break; /* LS */ |
817 |
|
|
case 4: flags_used = 0x01; break; /* CC */ |
818 |
|
|
case 5: flags_used = 0x01; break; /* CS */ |
819 |
|
|
case 6: flags_used = 0x04; break; /* NE */ |
820 |
|
|
case 7: flags_used = 0x04; break; /* EQ */ |
821 |
|
|
case 8: flags_used = 0x02; break; /* VC */ |
822 |
|
|
case 9: flags_used = 0x02; break; /* VS */ |
823 |
|
|
case 10:flags_used = 0x08; break; /* PL */ |
824 |
|
|
case 11:flags_used = 0x08; break; /* MI */ |
825 |
|
|
case 12:flags_used = 0x0A; break; /* GE */ |
826 |
|
|
case 13:flags_used = 0x0A; break; /* LT */ |
827 |
|
|
case 14:flags_used = 0x0E; break; /* GT */ |
828 |
|
|
case 15:flags_used = 0x0E; break; /* LE */ |
829 |
|
|
} |
830 |
|
|
} |
831 |
|
|
|
832 |
|
|
/* Unconditional jumps don't evaluate condition codes, so they |
833 |
|
|
don't actually use any flags themselves */ |
834 |
|
|
if (IS_CONST_JUMP(i)) |
835 |
|
|
flags_used = 0; |
836 |
|
|
|
837 |
|
|
table68k[i].flaglive = flags_used; |
838 |
|
|
} |
839 |
cebix |
1.1 |
} |
840 |
|
|
|
841 |
|
|
static int mismatch; |
842 |
|
|
|
843 |
|
|
static void handle_merges (long int opcode) |
844 |
|
|
{ |
845 |
|
|
uae_u16 smsk; |
846 |
|
|
uae_u16 dmsk; |
847 |
|
|
int sbitdst, dstend; |
848 |
|
|
int srcreg, dstreg; |
849 |
|
|
|
850 |
|
|
if (table68k[opcode].spos == -1) { |
851 |
|
|
sbitdst = 1; smsk = 0; |
852 |
|
|
} else { |
853 |
|
|
switch (table68k[opcode].stype) { |
854 |
|
|
case 0: |
855 |
|
|
smsk = 7; sbitdst = 8; break; |
856 |
|
|
case 1: |
857 |
|
|
smsk = 255; sbitdst = 256; break; |
858 |
|
|
case 2: |
859 |
|
|
smsk = 15; sbitdst = 16; break; |
860 |
|
|
case 3: |
861 |
|
|
smsk = 7; sbitdst = 8; break; |
862 |
|
|
case 4: |
863 |
|
|
smsk = 7; sbitdst = 8; break; |
864 |
|
|
case 5: |
865 |
|
|
smsk = 63; sbitdst = 64; break; |
866 |
gbeauche |
1.5 |
case 6: |
867 |
|
|
smsk = 255; sbitdst = 256; break; |
868 |
gbeauche |
1.3 |
case 7: |
869 |
|
|
smsk = 3; sbitdst = 4; break; |
870 |
cebix |
1.1 |
default: |
871 |
|
|
smsk = 0; sbitdst = 0; |
872 |
|
|
abort(); |
873 |
|
|
break; |
874 |
|
|
} |
875 |
|
|
smsk <<= table68k[opcode].spos; |
876 |
|
|
} |
877 |
|
|
if (table68k[opcode].dpos == -1) { |
878 |
|
|
dstend = 1; dmsk = 0; |
879 |
|
|
} else { |
880 |
|
|
dmsk = 7 << table68k[opcode].dpos; |
881 |
|
|
dstend = 8; |
882 |
|
|
} |
883 |
|
|
for (srcreg=0; srcreg < sbitdst; srcreg++) { |
884 |
|
|
for (dstreg=0; dstreg < dstend; dstreg++) { |
885 |
|
|
uae_u16 code = opcode; |
886 |
|
|
|
887 |
|
|
code = (code & ~smsk) | (srcreg << table68k[opcode].spos); |
888 |
|
|
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos); |
889 |
|
|
|
890 |
|
|
/* Check whether this is in fact the same instruction. |
891 |
|
|
* The instructions should never differ, except for the |
892 |
|
|
* Bcc.(BW) case. */ |
893 |
|
|
if (table68k[code].mnemo != table68k[opcode].mnemo |
894 |
|
|
|| table68k[code].size != table68k[opcode].size |
895 |
|
|
|| table68k[code].suse != table68k[opcode].suse |
896 |
|
|
|| table68k[code].duse != table68k[opcode].duse) |
897 |
|
|
{ |
898 |
|
|
mismatch++; continue; |
899 |
|
|
} |
900 |
|
|
if (table68k[opcode].suse |
901 |
|
|
&& (table68k[opcode].spos != table68k[code].spos |
902 |
|
|
|| table68k[opcode].smode != table68k[code].smode |
903 |
|
|
|| table68k[opcode].stype != table68k[code].stype)) |
904 |
|
|
{ |
905 |
|
|
mismatch++; continue; |
906 |
|
|
} |
907 |
|
|
if (table68k[opcode].duse |
908 |
|
|
&& (table68k[opcode].dpos != table68k[code].dpos |
909 |
|
|
|| table68k[opcode].dmode != table68k[code].dmode)) |
910 |
|
|
{ |
911 |
|
|
mismatch++; continue; |
912 |
|
|
} |
913 |
|
|
|
914 |
|
|
if (code != opcode) |
915 |
|
|
table68k[code].handler = opcode; |
916 |
|
|
} |
917 |
|
|
} |
918 |
|
|
} |
919 |
|
|
|
920 |
|
|
void do_merges (void) |
921 |
|
|
{ |
922 |
|
|
long int opcode; |
923 |
|
|
int nr = 0; |
924 |
|
|
mismatch = 0; |
925 |
|
|
for (opcode = 0; opcode < 65536; opcode++) { |
926 |
|
|
if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG) |
927 |
|
|
continue; |
928 |
|
|
nr++; |
929 |
|
|
handle_merges (opcode); |
930 |
|
|
} |
931 |
|
|
nr_cpuop_funcs = nr; |
932 |
|
|
} |
933 |
|
|
|
934 |
|
|
int get_no_mismatches (void) |
935 |
|
|
{ |
936 |
|
|
return mismatch; |
937 |
|
|
} |