7 * 68020-specific debugger interface
10 static char *m68020excep(Map*, Rgetter);
12 static int m68020foll(Map*, uvlong, Rgetter, uvlong*);
13 static int m68020inst(Map*, uvlong, char, char*, int);
14 static int m68020das(Map*, uvlong, char*, int);
15 static int m68020instlen(Map*, uvlong);
19 {0x48,0x48,0,0}, /* break point #0 instr. */
20 2, /* size of break point instr. */
22 beswab, /* convert short to local byte order */
23 beswal, /* convert long to local byte order */
24 beswav, /* convert vlong to local byte order */
25 cisctrace, /* C traceback */
26 ciscframe, /* frame finder */
27 m68020excep, /* print exception */
28 0, /* breakpoint fixup */
31 m68020foll, /* follow-set calculation */
32 m68020inst, /* print instruction */
33 m68020das, /* dissembler */
34 m68020instlen, /* instruction size */
38 * 68020 exception frames
41 #define BPTTRAP 4 /* breakpoint gives illegal inst */
43 static char * excep[] = {
46 [4] "illegal instruction",
50 [8] "privilege violation",
54 [13] "coprocessor protocol violation",
68 [51] "FPCP underflow",
69 [52] "FPCP operand err",
71 [54] "FPCP signal NAN",
80 } ftype[] = { /* section 6.5.7 page 6-24 */
81 { 0, 4*2, "Short Format" },
82 { 1, 4*2, "Throwaway" },
83 { 2, 6*2, "Instruction Exception" },
84 { 3, 6*2, "MC68040 Floating Point Exception" },
85 { 8, 29*2, "MC68010 Bus Fault" },
86 { 7, 30*2, "MC68040 Bus Fault" },
87 { 9, 10*2, "Coprocessor mid-Instruction" },
88 { 10, 16*2, "MC68020 Short Bus Fault" },
89 { 11, 46*2, "MC68020 Long Bus Fault" },
99 uchar *ef=(uchar*)efl;
104 /* The kernel proc pointer on a 68020 is always
105 * at #8xxxxxxx; on the 68040 NeXT, the address
106 * is always #04xxxxxx. the sun3 port at sydney
107 * uses 0xf8xxxxxx to 0xffxxxxxx.
111 if (get4(map, mach->kbase, (&l)) < 0)
113 if ((l&0xfc000000) == 0x04000000) /* if NeXT */
116 size = 46*2; /* 68020 */
119 stktop = mach->kbase+mach->pgsize;
120 for(i=3; i<100; i++){
121 if (get1(map, stktop-i*4, (uchar*)&l, 4)< 0)
124 if(machdata->swal(l) == 0xBADC0C0A){
125 if (get1(map, stktop-(i-1)*4, (uchar *)&efl[0], 4) < 0)
127 if (get1(map, stktop-(i-2)*4, (uchar *)&efl[1], 4) < 0)
129 fvo = (ef[6]<<8)|ef[7];
135 for(ft=ftype; ft->name; ft++) {
136 if(ft->fmt == ((fvo>>12) & 0xF)){
148 m68020excep(Map *map, Rgetter rget)
153 if (m68020ufix(map) < 0)
154 return "bad exception frame";
156 if(excep[m68020vec] == 0)
157 return "bad exeception type";
159 if(m68020vec == BPTTRAP) {
160 pc = (*rget)(map, "PC");
161 if (get1(map, pc, buf, machdata->bpsize) > 0)
162 if(memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
165 return excep[m68020vec];
167 /* 68020 Disassembler and related functions */
169 not supported: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, cpSAVE
172 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
173 %y - register number x x x
174 %f - trap vector x x x
175 %e - destination eff addr x x x x x x
176 %p - conditional predicate x x x x x x
179 %E - source eff addr. x x x x x x
181 %c - condition code x x x x
182 %x - register number x x x
183 %b - shift count x x x
184 %q - daffy 3-bit quick operand or shift count x x x
185 %i - immediate operand <varies>
186 %t - offset(PC) <varies>
189 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
190 %a - register number x x x
191 %w - bit field width x x x x x
192 %L - MMU function code (SFC/DFC/D%a/#[0-3]) x x x x x
193 %P - conditional predicate x x x x x x
194 %k - k factor x x x x x x x
195 %m - register mask x x x x x x x x
196 %N - control register id x x x x x x x x x x x x
197 %j - (Dq != Dr) ? Dq:Dr : Dr x x x x x x
198 %K - dynamic k register x x x
199 %h - register number x x x
200 %I - MMU function code mask x x x x
201 %o - bit field offset x x x x x
202 %u - register number x x x
203 %D - float dest reg x x x
204 %F - (fdr==fsr) ? "F%D" :"F%B,F%D" x x x x x x
205 %S - float source type x x x
206 %B - float source register x x x
207 %Z - ATC level number x x x
208 %H - MMU register x x x x
209 %r - register type/number x x x x
212 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
213 %A - register number x x x
214 %U - register number x x x
215 %R - register type,number x x x x
217 -----------------------------------------------------------------------------
219 %a - register [word 1: 0-2]
220 %c - condition code [opcode: 8-11]
221 %d - direction [opcode: 8]
222 %e - destination effective address [opcode: 0-5]
223 %f - trap vector [opcode: 0-3]
224 %h - register [word 1: 5-7]
225 %i - immediate operand (1, 2, or 4 bytes)
226 %j - Dq:Dr if Dq != Dr; else Dr => Dr [word 1: 0-2] Dq [word 1: 12-14]
227 %k - k factor [word 1: 0-6]
228 %m - register mask [word 1: 0-7]
229 %o - bit field offset [word 1: 6-10]
230 %p - conditional predicate [opcode: 0-5]
231 %q - daffy 3-bit quick operand [opcode: 9-11]
232 %r - register type, [word 1: 15], register [word 1: 12-14]
233 %s - size [opcode: 6-7]
234 %t - offset beyond pc (text address) (2 or 4 bytes)
235 %u - register [word 1: 6-8]
236 %w - bit field width [word 1: 0-4]
237 %x - register [opcode: 9-11]
238 %y - register [opcode: 0-2]
239 %A - register [word 2: 0-2]
240 %B - float source register [word 1: 10-12]
241 %C - cache identifier [opcode: 6-7] (IC, DC, or BC)
242 %D - float dest reg [word 1: 7-9]
243 %E - dest effective address [opcode: 6-11]
244 %F - float dest reg == float src reg => "F%D"; else "F%B,F%D"
245 %H - MMU reg [word 1: 10-13] (see above & p 4-53/54)
246 %I - MMU function code mask [word 1: 5-8]
247 %K - dynamic k factor register [word 1: 4-6]
248 %L - MMU function code [word 1: 0-4] (SFC, DFC, D%a, or #[0-3])
249 %N - control register [word 1: 0-11]
250 %P - conditional predicate [word 1: 0-5]
251 %R - register type, [word 2: 15], register [word 2: 12-14]
252 %S - float source type code [word 1: 10-12]
253 %U - register [word 2: 6-8]
254 %Z - ATC level number [word 1: 10-12]
255 %1 - Special case: EA as second operand
257 /* Operand classes */
259 EAPI = 1, /* extended address: pre decrement only */
260 EACA, /* extended address: control alterable */
261 EACAD, /* extended address: control alterable or Dreg */
262 EACAPI, /* extended address: control alterable or post-incr */
263 EACAPD, /* extended address: control alterable or pre-decr */
264 EAMA, /* extended address: memory alterable */
265 EADA, /* extended address: data alterable */
266 EAA, /* extended address: alterable */
267 EAC, /* extended address: control addressing */
268 EACPI, /* extended address: control addressing or post-incr */
269 EACD, /* extended address: control addressing or Dreg */
270 EAD, /* extended address: data addressing */
271 EAM, /* extended address: memory addressing */
272 EAM_B, /* EAM with byte immediate data */
273 EADI, /* extended address: data addressing or immediate */
274 EADI_L, /* EADI with long immediate data */
275 EADI_W, /* EADI with word immediate data */
276 EAALL, /* extended address: all modes */
277 EAALL_L, /* EAALL with long immediate data */
278 EAALL_W, /* EAALL with word immediate data */
279 EAALL_B, /* EAALL with byte immediate date */
280 /* special codes not directly used for validation */
281 EAFLT, /* extended address: EADI for B, W, L, or S; else EAM */
282 EADDA, /* destination extended address: EADA */
283 BREAC, /* EAC operand for JMP or CALL */
284 OP8, /* low 8 bits of op word */
285 I8, /* low 8-bits of first extension word */
286 I16, /* 16 bits in first extension word */
287 I32, /* 32 bits in first and second extension words */
288 IV, /* 8, 16 or 32 bit data in first & 2nd extension words */
289 C16, /* CAS2 16 bit immediate with bits 9-11 & 3-5 zero */
290 BR8, /* 8 bits in op word or 16 or 32 bits in extension words
291 branch instruction format (p. 2-25) */
292 BR16, /* 16-bit branch displacement */
293 BR32, /* 32-bit branch displacement */
294 STACK, /* return PC on stack - follow set only */
296 /* validation bit masks for various EA classes */
298 Dn = 0x0001, /* Data register */
299 An = 0x0002, /* Address register */
300 Ind = 0x0004, /* Address register indirect */
301 Pinc = 0x0008, /* Address register indirect post-increment */
302 Pdec = 0x0010, /* Address register indirect pre-decrement */
303 Bdisp = 0x0020, /* Base/Displacement in all its forms */
304 PCrel = 0x0040, /* PC relative addressing in all its forms */
305 Imm = 0x0080, /* Immediate data */
306 Abs = 0x0100, /* Absolute */
308 /* EA validation table indexed by operand class number */
310 static short validea[] =
314 Abs|Bdisp|Ind, /* EACA */
315 Abs|Bdisp|Ind|Dn, /* EACAD */
316 Abs|Bdisp|Pinc|Ind, /* EACAPI */
317 Abs|Bdisp|Pdec|Ind, /* EACAPD */
318 Abs|Bdisp|Pdec|Pinc|Ind, /* EAMA */
319 Abs|Bdisp|Pdec|Pinc|Ind|Dn, /* EADA */
320 Abs|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAA */
321 Abs|PCrel|Bdisp|Ind, /* EAC */
322 Abs|PCrel|Bdisp|Pinc|Ind, /* EACPI */
323 Abs|PCrel|Bdisp|Ind|Dn, /* EACD */
324 Abs|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EAD */
325 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind, /* EAM */
326 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind, /* EAM_B */
327 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI */
328 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI_L */
329 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI_W */
330 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL */
331 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_L */
332 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_W */
333 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_B */
343 ADisp, /* Displacement beyond (An) */
344 BXD, /* Base, Index, Displacement */
345 PDisp, /* Displacement beyond PC */
346 PXD, /* PC, Index, Displacement */
349 IREAL, /* single precision real immediate */
350 IEXT, /* extended precision real immediate */
351 IPACK, /* packed real immediate */
352 IDBL, /* double precision real immediate */
355 typedef struct optable Optable;
356 typedef struct operand Operand;
357 typedef struct inst Inst;
374 long immediate; /* sign-extended integer byte/word/long */
375 struct { /* index mode displacements */
379 char floater[24]; /* floating point immediates */
385 int n; /* # bytes in instruction */
386 uvlong addr; /* addr of start of instruction */
387 ushort raw[4+12]; /* longest instruction: 24 byte packed immediate */
389 char *end; /* end of print buffer */
390 char *curr; /* current fill point in buffer */
393 /* class 0: bit field, MOVEP & immediate instructions */
394 static Optable t0[] = {
395 { 0x003c, 0xffff, 0x0000, 0xff00, {I8}, "ORB %i,CCR" },
396 { 0x007c, 0xffff, 0x0000, 0x0000, {I16}, "ORW %i,SR" },
397 { 0x023c, 0xffff, 0x0000, 0xff00, {I8}, "ANDB %i,CCR" },
398 { 0x027c, 0xffff, 0x0000, 0x0000, {I16}, "ANDW %i,SR" },
399 { 0x0a3c, 0xffff, 0x0000, 0xff00, {I8}, "EORB %i,CCR" },
400 { 0x0a7c, 0xffff, 0x0000, 0x0000, {I16}, "EORW %i,SR" },
401 { 0x0cfc, 0xffff, 0x0000, 0x0000, {C16,C16}, "CAS2W R%a:R%A,R%u:R%U,(%r):(%R)"} ,
402 { 0x0efc, 0xffff, 0x0000, 0x0000, {C16,C16}, "CAS2L R%a:R%A,R%u:R%U,(%r):(%R)"} ,
404 { 0x06c0, 0xfff8, 0x0000, 0x0000, {0}, "RTM R%y" },
405 { 0x06c8, 0xfff8, 0x0000, 0x0000, {0}, "RTM A%y" },
406 { 0x0800, 0xfff8, 0x0000, 0x0000, {I16}, "BTSTL %i,R%y" },
407 { 0x0840, 0xfff8, 0x0000, 0x0000, {I16}, "BCHGL %i,R%y" },
408 { 0x0880, 0xfff8, 0x0000, 0x0000, {I16}, "BCLRL %i,R%y" },
410 { 0x00c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2B %e,%r" },
411 { 0x00c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2B %e,%r" },
412 { 0x02c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2W %e,%r" },
413 { 0x02c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2W %e,%r" },
414 { 0x04c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2L %e,%r" },
415 { 0x04c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2L %e,%r" },
416 { 0x06c0, 0xffc0, 0x0000, 0x0000, {I16, BREAC}, "CALLM %i,%e" },
417 { 0x0800, 0xffc0, 0x0000, 0x0000, {I16, EAD}, "BTSTB %i,%e" },
418 { 0x0840, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BCHG %i,%e" },
419 { 0x0880, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BCLR %i,%e" },
420 { 0x08c0, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BSET %i,%e" },
421 { 0x0ac0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASB R%a,R%u,%e" },
422 { 0x0cc0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASW R%a,R%u,%e" },
423 { 0x0ec0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASL R%a,R%u,%e" },
425 { 0x0000, 0xff00, 0x0000, 0x0000, {IV, EADA}, "OR%s %i,%e" },
426 { 0x0200, 0xff00, 0x0000, 0x0000, {IV, EADA}, "AND%s %i,%e" },
427 { 0x0400, 0xff00, 0x0000, 0x0000, {IV, EADA}, "SUB%s %i,%e" },
428 { 0x0600, 0xff00, 0x0000, 0x0000, {IV, EADA}, "ADD%s %i,%e" },
429 { 0x0a00, 0xff00, 0x0000, 0x0000, {IV, EADA}, "EOR%s %i,%e" },
430 { 0x0c00, 0xff00, 0x0000, 0x0000, {IV, EAD}, "CMP%s %i,%e" },
431 { 0x0e00, 0xff00, 0x0000, 0x0800, {EAMA}, "MOVES%s %e,%r" },
432 { 0x0e00, 0xff00, 0x0800, 0x0800, {EAMA}, "MOVES%s %r,%e" },
434 { 0x0108, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPW (%i,A%y),R%x" },
435 { 0x0148, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPL (%i,A%y),R%x" },
436 { 0x0188, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPW R%x,(%i,A%y)" },
437 { 0x01c8, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPL R%x,(%i,A%y)" },
438 { 0x0100, 0xf1f8, 0x0000, 0x0000, {0}, "BTSTL R%x,R%y" },
439 { 0x0140, 0xf1f8, 0x0000, 0x0000, {0}, "BCHGL R%x,R%y" },
440 { 0x0180, 0xf1f8, 0x0000, 0x0000, {0}, "BCLRL R%x,R%y" },
441 { 0x01c0, 0xf1f8, 0x0000, 0x0000, {0}, "BSET R%x,R%y" },
443 { 0x0100, 0xf1c0, 0x0000, 0x0000, {EAM_B}, "BTSTB R%x,%e" },
444 { 0x0140, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BCHG R%x,%e" },
445 { 0x0180, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BCLR R%x,%e" },
446 { 0x01c0, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BSET R%x,%e" },
449 /* class 1: move byte */
450 static Optable t1[] = {
451 { 0x1000, 0xf000, 0x0000, 0x0000, {EAALL_B,EADDA},"MOVB %e,%E" },
454 /* class 2: move long */
455 static Optable t2[] = {
456 { 0x2040, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "MOVL %e,A%x" },
458 { 0x2000, 0xf000, 0x0000, 0x0000, {EAALL_L,EADDA},"MOVL %e,%E" },
461 /* class 3: move word */
462 static Optable t3[] = {
463 { 0x3040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "MOVW %e,A%x" },
465 { 0x3000, 0xf000, 0x0000, 0x0000, {EAALL_W,EADDA},"MOVW %e,%E" },
468 /* class 4: miscellaneous */
469 static Optable t4[] = {
470 { 0x4e75, 0xffff, 0x0000, 0x0000, {STACK}, "RTS" },
471 { 0x4e77, 0xffff, 0x0000, 0x0000, {STACK}, "RTR" },
472 { 0x4afc, 0xffff, 0x0000, 0x0000, {0}, "ILLEGAL" },
473 { 0x4e71, 0xffff, 0x0000, 0x0000, {0}, "NOP" },
474 { 0x4e74, 0xffff, 0x0000, 0x0000, {I16, STACK}, "RTD %i" },
475 { 0x4e76, 0xffff, 0x0000, 0x0000, {0}, "TRAPV" },
476 { 0x4e70, 0xffff, 0x0000, 0x0000, {0}, "RESET" },
477 { 0x4e72, 0xffff, 0x0000, 0x0000, {I16}, "STOP %i" },
478 { 0x4e73, 0xffff, 0x0000, 0x0000, {0}, "RTE" },
479 { 0x4e7a, 0xffff, 0x0000, 0x0000, {I16}, "MOVEL %N,%r" },
480 { 0x4e7b, 0xffff, 0x0000, 0x0000, {I16}, "MOVEL %r,%N" },
482 { 0x4808, 0xfff8, 0x0000, 0x0000, {I32}, "LINKL A%y,%i" },
483 { 0x4840, 0xfff8, 0x0000, 0x0000, {0}, "SWAPW R%y" },
484 { 0x4848, 0xfff8, 0x0000, 0x0000, {0}, "BKPT #%y" },
485 { 0x4880, 0xfff8, 0x0000, 0x0000, {0}, "EXTW R%y" },
486 { 0x48C0, 0xfff8, 0x0000, 0x0000, {0}, "EXTL R%y" },
487 { 0x49C0, 0xfff8, 0x0000, 0x0000, {0}, "EXTBL R%y" },
488 { 0x4e50, 0xfff8, 0x0000, 0x0000, {I16}, "LINKW A%y,%i" },
489 { 0x4e58, 0xfff8, 0x0000, 0x0000, {0}, "UNLK A%y" },
490 { 0x4e60, 0xfff8, 0x0000, 0x0000, {0}, "MOVEL (A%y),USP" },
491 { 0x4e68, 0xfff8, 0x0000, 0x0000, {0}, "MOVEL USP,(A%y)" },
493 { 0x4e40, 0xfff0, 0x0000, 0x0000, {0}, "SYS %f" },
495 { 0x40c0, 0xffc0, 0x0000, 0x0000, {EADA}, "MOVW SR,%e" },
496 { 0x42c0, 0xffc0, 0x0000, 0x0000, {EADA}, "MOVW CCR,%e" },
497 { 0x44c0, 0xffc0, 0x0000, 0x0000, {EADI_W}, "MOVW %e,CCR" },
498 { 0x46c0, 0xffc0, 0x0000, 0x0000, {EADI_W}, "MOVW %e,SR" },
499 { 0x4800, 0xffc0, 0x0000, 0x0000, {EADA}, "NBCDB %e" },
500 { 0x4840, 0xffc0, 0x0000, 0x0000, {EAC}, "PEA %e" },
501 { 0x4880, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEMW %i,%e" },
502 { 0x48c0, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEML %i,%e" },
503 { 0x4ac0, 0xffc0, 0x0000, 0x0000, {EADA}, "TAS %e" },
504 { 0x4a00, 0xffc0, 0x0000, 0x0000, {EAD}, "TSTB %e" },
505 { 0x4c00, 0xffc0, 0x0000, 0x8ff8, {EADI_L}, "MULUL %e,%r" },
506 { 0x4c00, 0xffc0, 0x0400, 0x8ff8, {EADI_L}, "MULUL %e,R%a:%r" },
507 { 0x4c00, 0xffc0, 0x0800, 0x8ff8, {EADI_L}, "MULSL %e,%r" },
508 { 0x4c00, 0xffc0, 0x0c00, 0x8ff8, {EADI_L}, "MULSL %e,R%a:%r" },
509 { 0x4c40, 0xffc0, 0x0000, 0x8ff8, {EADI_L}, "DIVUL %e,%j" },
510 { 0x4c40, 0xffc0, 0x0400, 0x8ff8, {EADI_L}, "DIVUD %e,%r:R%a" },
511 { 0x4c40, 0xffc0, 0x0800, 0x8ff8, {EADI_L}, "DIVSL %e,%j" },
512 { 0x4c40, 0xffc0, 0x0c00, 0x8ff8, {EADI_L}, "DIVSD %e,%r:R%a" },
513 { 0x4c80, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEMW %1,%i" },
514 { 0x4cc0, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEML %1,%i" },
515 { 0x4e80, 0xffc0, 0x0000, 0x0000, {BREAC}, "JSR %e" },
516 { 0x4ec0, 0xffc0, 0x0000, 0x0000, {BREAC}, "JMP %e" },
518 { 0x4000, 0xff00, 0x0000, 0x0000, {EADA}, "NEGX%s %e" },
519 { 0x4200, 0xff00, 0x0000, 0x0000, {EADA}, "CLR%s %e" },
520 { 0x4400, 0xff00, 0x0000, 0x0000, {EADA}, "NEG%s %e" },
521 { 0x4600, 0xff00, 0x0000, 0x0000, {EADA}, "NOT%s %e" },
522 { 0x4a00, 0xff00, 0x0000, 0x0000, {EAALL}, "TST%s %e" },
524 { 0x4180, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "CHKW %e,R%x" },
525 { 0x41c0, 0xf1c0, 0x0000, 0x0000, {EAC}, "LEA %e,A%x" },
526 { 0x4100, 0xf1c0, 0x0000, 0x0000, {EADI_L}, "CHKL %e,R%x" },
529 /* class 5: miscellaneous quick, branch & trap instructions */
530 static Optable t5[] = {
531 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EADA}, "ADDB $Q#%q,%e" },
532 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EADA}, "SUBB $Q#%q,%e" },
534 { 0x50c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" },
535 { 0x51c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" },
537 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDB $Q#%q,%e" },
538 { 0x5040, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDW $Q#%q,%e" },
539 { 0x5080, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDL $Q#%q,%e" },
540 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBB $Q#%q,%e" },
541 { 0x5140, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBW $Q#%q,%e" },
542 { 0x5180, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBL $Q#%q,%e" },
544 { 0x50fa, 0xf0ff, 0x0000, 0x0000, {I16}, "TRAP%cW %i" },
545 { 0x50fb, 0xf0ff, 0x0000, 0x0000, {I32}, "TRAP%cL %i" },
546 { 0x50fc, 0xf0ff, 0x0000, 0x0000, {0}, "TRAP%c" },
548 { 0x50c0, 0xf0c0, 0x0000, 0x0000, {EADA}, "S%c %e" },
551 /* class 6: branch instructions */
552 static Optable t6[] = {
553 { 0x6000, 0xff00, 0x0000, 0x0000, {BR8}, "BRA %t" },
554 { 0x6100, 0xff00, 0x0000, 0x0000, {BR8}, "BSR %t" },
555 { 0x6000, 0xf000, 0x0000, 0x0000, {BR8}, "B%c %t" },
558 /* class 7: move quick */
559 static Optable t7[] = {
560 { 0x7000, 0xf100, 0x0000, 0x0000, {OP8}, "MOVL $Q%i,R%x" },
563 /* class 8: BCD operations, DIV, and OR instructions */
564 static Optable t8[] = {
565 { 0x8100, 0xf1f8, 0x0000, 0x0000, {0}, "SBCDB R%y,R%x" },
566 { 0x8108, 0xf1f8, 0x0000, 0x0000, {0}, "SBCDB -(A%y),-(A%x)" },
567 { 0x8140, 0xf1f8, 0x0000, 0x0000, {I16}, "PACK R%y,R%x,%i" },
568 { 0x8148, 0xf1f8, 0x0000, 0x0000, {I16}, "PACK -(A%y),-(A%x),%i" },
569 { 0x8180, 0xf1f8, 0x0000, 0x0000, {I16}, "UNPK R%y,R%x,%i" },
570 { 0x8188, 0xf1f8, 0x0000, 0x0000, {I16}, "UNPK -(A%y),-(A%x),%i" },
572 { 0x80c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVUW %e,R%x" },
573 { 0x81c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVSW %e,R%x" },
575 { 0x8000, 0xf100, 0x0000, 0x0000, {EADI}, "OR%s %e,R%x" },
576 { 0x8100, 0xf100, 0x0000, 0x0000, {EAMA}, "OR%s R%x,%e" },
579 /* class 9: subtract instruction */
580 static Optable t9[] = {
581 { 0x90c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "SUBW %e,A%x" },
582 { 0x91c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "SUBL %e,A%x" },
584 { 0x9100, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s R%y,R%x" },
585 { 0x9108, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s -(A%y),-(A%x)" },
587 { 0x9000, 0xf100, 0x0000, 0x0000, {EAALL}, "SUB%s %e,R%x" },
588 { 0x9100, 0xf100, 0x0000, 0x0000, {EAMA}, "SUB%s R%x,%e" },
591 /* class b: CMP & EOR */
592 static Optable tb[] = {
593 { 0xb000, 0xf1c0, 0x0000, 0x0000, {EADI}, "CMPB R%x,%e" },
594 { 0xb040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "CMPW R%x,%e" },
595 { 0xb080, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "CMPL R%x,%e" },
596 { 0xb0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "CMPW A%x,%e" },
597 { 0xb1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "CMPL A%x,%e" },
599 { 0xb108, 0xf138, 0x0000, 0x0000, {0}, "CMP%s (A%y)+,(A%x)+" },
601 { 0xb100, 0xf100, 0x0000, 0x0000, {EADA}, "EOR%s %e,R%x" },
604 /* class c: AND, MUL, BCD & Exchange */
605 static Optable tc[] = {
606 { 0xc100, 0xf1f8, 0x0000, 0x0000, {0}, "ABCDB R%y,R%x" },
607 { 0xc108, 0xf1f8, 0x0000, 0x0000, {0}, "ABCDB -(A%y),-(A%x)" },
608 { 0xc140, 0xf1f8, 0x0000, 0x0000, {0}, "EXG R%x,R%y" },
609 { 0xc148, 0xf1f8, 0x0000, 0x0000, {0}, "EXG A%x,A%y" },
610 { 0xc188, 0xf1f8, 0x0000, 0x0000, {0}, "EXG R%x,A%y" },
612 { 0xc0c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULUW %e,R%x" },
613 { 0xc1c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULSW %e,R%x" },
615 { 0xc000, 0xf100, 0x0000, 0x0000, {EADI}, "AND%s %e,R%x" },
616 { 0xc100, 0xf100, 0x0000, 0x0000, {EAMA}, "AND%s R%x,%e" },
619 /* class d: addition */
620 static Optable td[] = {
621 { 0xd000, 0xf1c0, 0x0000, 0x0000, {EADI}, "ADDB %e,R%x" },
622 { 0xd0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "ADDW %e,A%x" },
623 { 0xd1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "ADDL %e,A%x" },
625 { 0xd100, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s R%y,R%x" },
626 { 0xd108, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s -(A%y),-(A%x)" },
628 { 0xd000, 0xf100, 0x0000, 0x0000, {EAALL}, "ADD%s %e,R%x" },
629 { 0xd100, 0xf100, 0x0000, 0x0000, {EAMA}, "ADD%s R%x,%e" },
632 /* class e: shift, rotate, bit field operations */
633 static Optable te[] = {
634 { 0xe8c0, 0xffc0, 0x0820, 0xfe38, {EACD}, "BFTST %e{R%u:R%a}" },
635 { 0xe8c0, 0xffc0, 0x0800, 0xfe20, {EACD}, "BFTST %e{R%u:%w}" },
636 { 0xe8c0, 0xffc0, 0x0020, 0xf838, {EACD}, "BFTST %e{%o:R%a}" },
637 { 0xe8c0, 0xffc0, 0x0000, 0xf820, {EACD}, "BFTST %e{%o:%w}" },
639 { 0xe9c0, 0xffc0, 0x0820, 0x8e38, {EACD}, "BFEXTU %e{R%u:R%a},%r" },
640 { 0xe9c0, 0xffc0, 0x0800, 0x8e20, {EACD}, "BFEXTU %e{R%u:%w},%r" },
641 { 0xe9c0, 0xffc0, 0x0020, 0x8838, {EACD}, "BFEXTU %e{%o:R%a},%r" },
642 { 0xe9c0, 0xffc0, 0x0000, 0x8820, {EACD}, "BFEXTU %e{%o:%w},%r" },
644 { 0xeac0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFCHG %e{R%u:R%a}" },
645 { 0xeac0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFCHG %e{R%u:%w}" },
646 { 0xeac0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFCHG %e{%o:R%a}" },
647 { 0xeac0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFCHG %e{%o:%w}" },
649 { 0xebc0, 0xffc0, 0x0820, 0x8e38, {EACD}, "BFEXTS %e{R%u:R%a},%r" },
650 { 0xebc0, 0xffc0, 0x0800, 0x8e20, {EACD}, "BFEXTS %e{R%u:%w},%r" },
651 { 0xebc0, 0xffc0, 0x0020, 0x8838, {EACD}, "BFEXTS %e{%o:R%a},%r" },
652 { 0xebc0, 0xffc0, 0x0000, 0x8820, {EACD}, "BFEXTS %e{%o:%w},%r" },
654 { 0xecc0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFCLR %e{R%u:R%a}" },
655 { 0xecc0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFCLR %e{R%u:%w}" },
656 { 0xecc0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFCLR %e{%o:R%a}" },
657 { 0xecc0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFCLR %e{%o:%w}" },
659 { 0xedc0, 0xffc0, 0x0820, 0x8e38, {EACAD}, "BFFFO %e{R%u:R%a},%r" },
660 { 0xedc0, 0xffc0, 0x0800, 0x8e20, {EACAD}, "BFFFO %e{R%u:%w},%r" },
661 { 0xedc0, 0xffc0, 0x0020, 0x8838, {EACAD}, "BFFFO %e{%o:R%a},%r" },
662 { 0xedc0, 0xffc0, 0x0000, 0x8820, {EACAD}, "BFFFO %e{%o:%w},%r" },
664 { 0xeec0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFSET %e{R%u:R%a}" },
665 { 0xeec0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFSET %e{R%u:%w}" },
666 { 0xeec0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFSET %e{%o:R%a}" },
667 { 0xeec0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFSET %e{%o:%w}" },
669 { 0xefc0, 0xffc0, 0x0820, 0x8e38, {EACAD}, "BFINS %r,%e{R%u:R%a}" },
670 { 0xefc0, 0xffc0, 0x0800, 0x8e20, {EACAD}, "BFINS %r,%e{R%u:%w}" },
671 { 0xefc0, 0xffc0, 0x0020, 0x8838, {EACAD}, "BFINS %r,%e{%o:R%a}" },
672 { 0xefc0, 0xffc0, 0x0000, 0x8820, {EACAD}, "BFINS %r,%e{%o:%w}" },
674 { 0xe0c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "AS%dW %e" },
675 { 0xe2c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "LS%dW %e" },
676 { 0xe4c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "ROX%dW %e" },
677 { 0xe6c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "RO%dW %e" },
679 { 0xe000, 0xf038, 0x0000, 0x0000, {0}, "AS%d%s #%q,R%y" },
680 { 0xe008, 0xf038, 0x0000, 0x0000, {0}, "LS%d%s #%q,R%y" },
681 { 0xe010, 0xf038, 0x0000, 0x0000, {0}, "ROX%d%s #%q,R%y" },
682 { 0xe018, 0xf038, 0x0000, 0x0000, {0}, "RO%d%s #%q,R%y" },
683 { 0xe020, 0xf038, 0x0000, 0x0000, {0}, "AS%d%s R%x,R%y" },
684 { 0xe028, 0xf038, 0x0000, 0x0000, {0}, "LS%d%s R%x,R%y" },
685 { 0xe030, 0xf038, 0x0000, 0x0000, {0}, "ROX%d%s R%x,R%y" },
686 { 0xe038, 0xf038, 0x0000, 0x0000, {0}, "RO%d%s R%x,R%y" },
689 /* class f: coprocessor and mmu instructions */
690 static Optable tf[] = {
691 { 0xf280, 0xffff, 0x0000, 0xffff, {0}, "FNOP" },
692 { 0xf200, 0xffff, 0x5c00, 0xfc00, {0}, "FMOVECRX %k,F%D" },
693 { 0xf27a, 0xffff, 0x0000, 0xffc0, {I16}, "FTRAP%P %i" },
694 { 0xf27b, 0xffff, 0x0000, 0xffc0, {I32}, "FTRAP%P %i" },
695 { 0xf27c, 0xffff, 0x0000, 0xffc0, {0}, "FTRAP%P" },
697 { 0xf248, 0xfff8, 0x0000, 0xffc0, {BR16}, "FDB%P R%y,%t" },
698 { 0xf620, 0xfff8, 0x8000, 0x8fff, {0}, "MOVE16 (A%y)+,(%r)+" },
699 { 0xf500, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHN (A%y)" },
700 { 0xf508, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSH (A%y)" },
701 { 0xf510, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHAN" },
702 { 0xf518, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHA" },
703 { 0xf548, 0xfff8, 0x0000, 0x0000, {0}, "PTESTW (A%y)" },
704 { 0xf568, 0xfff8, 0x0000, 0x0000, {0}, "PTESTR (A%y)" },
705 { 0xf600, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 (A%y)+,$%i" },
706 { 0xf608, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 $%i,(A%y)-" },
707 { 0xf610, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 (A%y),$%i" },
708 { 0xf618, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 $%i,(A%y)" },
710 { 0xf000, 0xffc0, 0x0800, 0xffff, {EACA}, "PMOVE %e,TT0" },
711 { 0xf000, 0xffc0, 0x0900, 0xffff, {EACA}, "PMOVEFD %e,TT0" },
712 { 0xf000, 0xffc0, 0x0a00, 0xffff, {EACA}, "PMOVE TT0,%e" },
713 { 0xf000, 0xffc0, 0x0b00, 0xffff, {EACA}, "PMOVEFD TT0,%e" },
714 { 0xf000, 0xffc0, 0x0c00, 0xffff, {EACA}, "PMOVE %e,TT1" },
715 { 0xf000, 0xffc0, 0x0d00, 0xffff, {EACA}, "PMOVEFD %e,TT1" },
716 { 0xf000, 0xffc0, 0x0e00, 0xffff, {EACA}, "PMOVE TT1,%e" },
717 { 0xf000, 0xffc0, 0x0f00, 0xffff, {EACA}, "PMOVEFD TT1,%e" },
718 { 0xf000, 0xffc0, 0x2400, 0xffff, {0}, "PFLUSHA" },
719 { 0xf000, 0xffc0, 0x2800, 0xffff, {EACA}, "PVALID VAL,%e" },
720 { 0xf000, 0xffc0, 0x6000, 0xffff, {EACA}, "PMOVE %e,MMUSR" },
721 { 0xf000, 0xffc0, 0x6200, 0xffff, {EACA}, "PMOVE MMUSR,%e" },
722 { 0xf000, 0xffc0, 0x2800, 0xfff8, {EACA}, "PVALID A%a,%e" },
723 { 0xf000, 0xffc0, 0x2000, 0xffe0, {EACA}, "PLOADW %L,%e" },
724 { 0xf000, 0xffc0, 0x2200, 0xffe0, {EACA}, "PLOADR %L,%e" },
725 { 0xf000, 0xffc0, 0x8000, 0xffe0, {EACA}, "PTESTW %L,%e,#0" },
726 { 0xf000, 0xffc0, 0x8200, 0xffe0, {EACA}, "PTESTR %L,%e,#0" },
727 { 0xf000, 0xffc0, 0x3000, 0xfe00, {0}, "PFLUSH %L,#%I" },
728 { 0xf000, 0xffc0, 0x3800, 0xfe00, {EACA}, "PFLUSH %L,#%I,%e" },
729 { 0xf000, 0xffc0, 0x8000, 0xe300, {EACA}, "PTESTW %L,%e,#%Z" },
730 { 0xf000, 0xffc0, 0x8100, 0xe300, {EACA}, "PTESTW %L,%e,#%Z,A%h" },
731 { 0xf000, 0xffc0, 0x8200, 0xe300, {EACA}, "PTESTR %L,%e,#%Z" },
732 { 0xf000, 0xffc0, 0x8300, 0xe300, {EACA}, "PTESTR %L,%e,#%Z,A%h" },
733 { 0xf000, 0xffc0, 0x4000, 0xc3ff, {EACA}, "PMOVE %e,%H" },
734 { 0xf000, 0xffc0, 0x4100, 0xc3ff, {EACA}, "PMOVEFD %e,%H" },
735 { 0xf000, 0xffc0, 0x4200, 0xc3ff, {EACA}, "PMOVE %H,%e" },
737 /* floating point (coprocessor 1)*/
739 { 0xf200, 0xffc0, 0x8400, 0xffff, {EAALL_L}, "FMOVEL %e,FPIAR" },
740 { 0xf200, 0xffc0, 0x8800, 0xffff, {EADI_L}, "FMOVEL %e,FPSR" },
741 { 0xf200, 0xffc0, 0x9000, 0xffff, {EADI_L}, "FMOVEL %e,FPCR" },
742 { 0xf200, 0xffc0, 0xa400, 0xffff, {EAA}, "FMOVEL FPIAR,%e" },
743 { 0xf200, 0xffc0, 0xa800, 0xffff, {EADA}, "FMOVEL FPSR,%e" },
744 { 0xf200, 0xffc0, 0xb000, 0xffff, {EADA}, "FMOVEL FPCR,%e" },
746 { 0xf240, 0xffc0, 0x0000, 0xffc0, {EADA}, "FS%P %e" },
748 { 0xf200, 0xffc0, 0xd000, 0xff00, {EACPI}, "FMOVEMX %e,%m" },
749 { 0xf200, 0xffc0, 0xd800, 0xff00, {EACPI}, "FMOVEMX %e,R%K" },
750 { 0xf200, 0xffc0, 0xe000, 0xff00, {EAPI}, "FMOVEMX %m,-(A%y)" },
751 { 0xf200, 0xffc0, 0xe800, 0xff00, {EAPI}, "FMOVEMX R%K,-(A%y)" },
752 { 0xf200, 0xffc0, 0xf000, 0xff00, {EACAPD}, "FMOVEMX %m,%e" },
753 { 0xf200, 0xffc0, 0xf800, 0xff00, {EACAPD}, "FMOVEMX R%K,%e" },
755 { 0xf200, 0xffc0, 0x6800, 0xfc00, {EAMA}, "FMOVEX F%D,%e" },
756 { 0xf200, 0xffc0, 0x6c00, 0xfc00, {EAMA}, "FMOVEP F%D,%e,{%k}" },
757 { 0xf200, 0xffc0, 0x7400, 0xfc00, {EAMA}, "FMOVED F%D,%e" },
758 { 0xf200, 0xffc0, 0x7c00, 0xfc00, {EAMA}, "FMOVEP F%D,%e,{R%K}" },
760 { 0xf200, 0xffc0, 0x8000, 0xe3ff, {EAM}, "FMOVEML #%B,%e" },
761 { 0xf200, 0xffc0, 0xa000, 0xe3ff, {EAMA}, "FMOVEML %e,#%B" },
763 { 0xf200, 0xffc0, 0x0000, 0xe07f, {0}, "FMOVE F%B,F%D" },
764 { 0xf200, 0xffc0, 0x0001, 0xe07f, {0}, "FINTX %F" },
765 { 0xf200, 0xffc0, 0x0002, 0xe07f, {0}, "FSINHX %F" },
766 { 0xf200, 0xffc0, 0x0003, 0xe07f, {0}, "FINTRZ %F" },
767 { 0xf200, 0xffc0, 0x0004, 0xe07f, {0}, "FSQRTX %F" },
768 { 0xf200, 0xffc0, 0x0006, 0xe07f, {0}, "FLOGNP1X %F" },
769 { 0xf200, 0xffc0, 0x0009, 0xe07f, {0}, "FTANHX %F" },
770 { 0xf200, 0xffc0, 0x000a, 0xe07f, {0}, "FATANX %F" },
771 { 0xf200, 0xffc0, 0x000c, 0xe07f, {0}, "FASINX %F" },
772 { 0xf200, 0xffc0, 0x000d, 0xe07f, {0}, "FATANHX %F" },
773 { 0xf200, 0xffc0, 0x000e, 0xe07f, {0}, "FSINX %F" },
774 { 0xf200, 0xffc0, 0x000f, 0xe07f, {0}, "FTANX %F" },
775 { 0xf200, 0xffc0, 0x0010, 0xe07f, {0}, "FETOXX %F" },
776 { 0xf200, 0xffc0, 0x0011, 0xe07f, {0}, "FTWOTOXX %F" },
777 { 0xf200, 0xffc0, 0x0012, 0xe07f, {0}, "FTENTOXX %F" },
778 { 0xf200, 0xffc0, 0x0014, 0xe07f, {0}, "FLOGNX %F" },
779 { 0xf200, 0xffc0, 0x0015, 0xe07f, {0}, "FLOG10X %F" },
780 { 0xf200, 0xffc0, 0x0016, 0xe07f, {0}, "FLOG2X %F" },
781 { 0xf200, 0xffc0, 0x0018, 0xe07f, {0}, "FABSX %F" },
782 { 0xf200, 0xffc0, 0x0019, 0xe07f, {0}, "FCOSHX %F" },
783 { 0xf200, 0xffc0, 0x001a, 0xe07f, {0}, "FNEGX %F" },
784 { 0xf200, 0xffc0, 0x001c, 0xe07f, {0}, "FACOSX %F" },
785 { 0xf200, 0xffc0, 0x001d, 0xe07f, {0}, "FCOSX %F" },
786 { 0xf200, 0xffc0, 0x001e, 0xe07f, {0}, "FGETEXPX %F" },
787 { 0xf200, 0xffc0, 0x001f, 0xe07f, {0}, "FGETMANX %F" },
788 { 0xf200, 0xffc0, 0x0020, 0xe07f, {0}, "FDIVX F%B,F%D" },
789 { 0xf200, 0xffc0, 0x0021, 0xe07f, {0}, "FMODX F%B,F%D" },
790 { 0xf200, 0xffc0, 0x0022, 0xe07f, {0}, "FADDX F%B,F%D" },
791 { 0xf200, 0xffc0, 0x0023, 0xe07f, {0}, "FMULX F%B,F%D" },
792 { 0xf200, 0xffc0, 0x0024, 0xe07f, {0}, "FSGLDIVX F%B,F%D" },
793 { 0xf200, 0xffc0, 0x0025, 0xe07f, {0}, "FREMX F%B,F%D" },
794 { 0xf200, 0xffc0, 0x0026, 0xe07f, {0}, "FSCALEX F%B,F%D" },
795 { 0xf200, 0xffc0, 0x0027, 0xe07f, {0}, "FSGLMULX F%B,F%D" },
796 { 0xf200, 0xffc0, 0x0028, 0xe07f, {0}, "FSUBX F%B,F%D" },
797 { 0xf200, 0xffc0, 0x0038, 0xe07f, {0}, "FCMPX F%B,F%D" },
798 { 0xf200, 0xffc0, 0x003a, 0xe07f, {0}, "FTSTX F%B" },
799 { 0xf200, 0xffc0, 0x0040, 0xe07f, {0}, "FSMOVE F%B,F%D" },
800 { 0xf200, 0xffc0, 0x0041, 0xe07f, {0}, "FSSQRTX %F"},
801 { 0xf200, 0xffc0, 0x0044, 0xe07f, {0}, "FDMOVE F%B,F%D" },
802 { 0xf200, 0xffc0, 0x0045, 0xe07f, {0}, "FDSQRTX %F" },
803 { 0xf200, 0xffc0, 0x0058, 0xe07f, {0}, "FSABSX %F" },
804 { 0xf200, 0xffc0, 0x005a, 0xe07f, {0}, "FSNEGX %F" },
805 { 0xf200, 0xffc0, 0x005c, 0xe07f, {0}, "FDABSX %F" },
806 { 0xf200, 0xffc0, 0x005e, 0xe07f, {0}, "FDNEGX %F" },
807 { 0xf200, 0xffc0, 0x0060, 0xe07f, {0}, "FSDIVX F%B,F%D" },
808 { 0xf200, 0xffc0, 0x0062, 0xe07f, {0}, "FSADDX F%B,F%D" },
809 { 0xf200, 0xffc0, 0x0063, 0xe07f, {0}, "FSMULX F%B,F%D" },
810 { 0xf200, 0xffc0, 0x0064, 0xe07f, {0}, "FDDIVX F%B,F%D" },
811 { 0xf200, 0xffc0, 0x0066, 0xe07f, {0}, "FDADDX F%B,F%D" },
812 { 0xf200, 0xffc0, 0x0067, 0xe07f, {0}, "FDMULX F%B,F%D" },
813 { 0xf200, 0xffc0, 0x0068, 0xe07f, {0}, "FSSUBX F%B,F%D" },
814 { 0xf200, 0xffc0, 0x006c, 0xe07f, {0}, "FDSUBX F%B,F%D" },
815 { 0xf200, 0xffc0, 0x4000, 0xe07f, {EAFLT}, "FMOVE%S %e,F%D" },
816 { 0xf200, 0xffc0, 0x4001, 0xe07f, {EAFLT}, "FINT%S %e,F%D" },
817 { 0xf200, 0xffc0, 0x4002, 0xe07f, {EAFLT}, "FSINH%S %e,F%D" },
818 { 0xf200, 0xffc0, 0x4003, 0xe07f, {EAFLT}, "FINTRZ%S %e,F%D" },
819 { 0xf200, 0xffc0, 0x4004, 0xe07f, {EAFLT}, "FSQRT%S %e,F%D" },
820 { 0xf200, 0xffc0, 0x4006, 0xe07f, {EAFLT}, "FLOGNP1%S %e,F%D" },
821 { 0xf200, 0xffc0, 0x4009, 0xe07f, {EAFLT}, "FTANH%S %e,F%D" },
822 { 0xf200, 0xffc0, 0x400a, 0xe07f, {EAFLT}, "FATAN%S %e,F%D" },
823 { 0xf200, 0xffc0, 0x400c, 0xe07f, {EAFLT}, "FASIN%S %e,F%D" },
824 { 0xf200, 0xffc0, 0x400d, 0xe07f, {EAFLT}, "FATANH%S %e,F%D" },
825 { 0xf200, 0xffc0, 0x400e, 0xe07f, {EAFLT}, "FSIN%S %e,F%D" },
826 { 0xf200, 0xffc0, 0x400f, 0xe07f, {EAFLT}, "FTAN%S %e,F%D" },
827 { 0xf200, 0xffc0, 0x4010, 0xe07f, {EAFLT}, "FETOX%S %e,F%D" },
828 { 0xf200, 0xffc0, 0x4011, 0xe07f, {EAFLT}, "FTWOTOX%S %e,F%D" },
829 { 0xf200, 0xffc0, 0x4012, 0xe07f, {EAFLT}, "FTENTOX%S %e,F%D" },
830 { 0xf200, 0xffc0, 0x4014, 0xe07f, {EAFLT}, "FLOGN%S %e,F%D" },
831 { 0xf200, 0xffc0, 0x4015, 0xe07f, {EAFLT}, "FLOG10%S %e,F%D" },
832 { 0xf200, 0xffc0, 0x4016, 0xe07f, {EAFLT}, "FLOG2%S %e,F%D" },
833 { 0xf200, 0xffc0, 0x4018, 0xe07f, {EAFLT}, "FABS%S %e,F%D" },
834 { 0xf200, 0xffc0, 0x4019, 0xe07f, {EAFLT}, "FCOSH%S %e,F%D" },
835 { 0xf200, 0xffc0, 0x401a, 0xe07f, {EAFLT}, "FNEG%S %e,F%D" },
836 { 0xf200, 0xffc0, 0x401c, 0xe07f, {EAFLT}, "FACOS%S %e,F%D" },
837 { 0xf200, 0xffc0, 0x401d, 0xe07f, {EAFLT}, "FCOS%S %e,F%D" },
838 { 0xf200, 0xffc0, 0x401e, 0xe07f, {EAFLT}, "FGETEXP%S %e,F%D" },
839 { 0xf200, 0xffc0, 0x401f, 0xe07f, {EAFLT}, "FGETMAN%S %e,F%D" },
840 { 0xf200, 0xffc0, 0x4020, 0xe07f, {EAFLT}, "FDIV%S %e,F%D" },
841 { 0xf200, 0xffc0, 0x4021, 0xe07f, {EAFLT}, "FMOD%S %e,F%D" },
842 { 0xf200, 0xffc0, 0x4022, 0xe07f, {EAFLT}, "FADD%S %e,F%D" },
843 { 0xf200, 0xffc0, 0x4023, 0xe07f, {EAFLT}, "FMUL%S %e,F%D" },
844 { 0xf200, 0xffc0, 0x4024, 0xe07f, {EAFLT}, "FSGLDIV%S %e,F%D" },
845 { 0xf200, 0xffc0, 0x4025, 0xe07f, {EAFLT}, "FREM%S %e,F%D" },
846 { 0xf200, 0xffc0, 0x4026, 0xe07f, {EAFLT}, "FSCALE%S %e,F%D" },
847 { 0xf200, 0xffc0, 0x4027, 0xe07f, {EAFLT}, "FSGLMUL%S %e,F%D" },
848 { 0xf200, 0xffc0, 0x4028, 0xe07f, {EAFLT}, "FSUB%S %e,F%D" },
849 { 0xf200, 0xffc0, 0x4038, 0xe07f, {EAFLT}, "FCMP%S %e,F%D" },
850 { 0xf200, 0xffc0, 0x403a, 0xe07f, {EAFLT}, "FTST%S %e" },
851 { 0xf200, 0xffc0, 0x4040, 0xe07f, {EAFLT}, "FSMOVE%S %e,F%D" },
852 { 0xf200, 0xffc0, 0x4041, 0xe07f, {EAFLT}, "FSSQRT%S %e,F%D" },
853 { 0xf200, 0xffc0, 0x4044, 0xe07f, {EAFLT}, "FDMOVE%S %e,F%D" },
854 { 0xf200, 0xffc0, 0x4045, 0xe07f, {EAFLT}, "FDSQRT%S %e,F%D" },
855 { 0xf200, 0xffc0, 0x4058, 0xe07f, {EAFLT}, "FSABS%S %e,F%D" },
856 { 0xf200, 0xffc0, 0x405a, 0xe07f, {EAFLT}, "FSNEG%S %e,F%D" },
857 { 0xf200, 0xffc0, 0x405c, 0xe07f, {EAFLT}, "FDABS%S %e,F%D" },
858 { 0xf200, 0xffc0, 0x405e, 0xe07f, {EAFLT}, "FDNEG%S %e,F%D" },
859 { 0xf200, 0xffc0, 0x4060, 0xe07f, {EAFLT}, "FSDIV%S %e,F%D" },
860 { 0xf200, 0xffc0, 0x4062, 0xe07f, {EAFLT}, "FSADD%S %e,F%D" },
861 { 0xf200, 0xffc0, 0x4063, 0xe07f, {EAFLT}, "FSMUL%S %e,F%D" },
862 { 0xf200, 0xffc0, 0x4064, 0xe07f, {EAFLT}, "FDDIV%S %e,F%D" },
863 { 0xf200, 0xffc0, 0x4066, 0xe07f, {EAFLT}, "FDADD%S %e,F%D" },
864 { 0xf200, 0xffc0, 0x4067, 0xe07f, {EAFLT}, "FDMUL%S %e,F%D" },
865 { 0xf200, 0xffc0, 0x4068, 0xe07f, {EAFLT}, "FSSUB%S %e,F%D" },
866 { 0xf200, 0xffc0, 0x406c, 0xe07f, {EAFLT}, "FDSUB%S %e,F%D" },
868 { 0xf200, 0xffc0, 0x0030, 0xe078, {0}, "FSINCOSX F%B,F%a:F%D" },
869 { 0xf200, 0xffc0, 0x4030, 0xe078, {EAFLT}, "FSINCOS%S %e,F%a:F%D" },
871 { 0xf200, 0xffc0, 0x6000, 0xe000, {EADA}, "FMOVE%S F%D,%e" },
873 { 0xf300, 0xffc0, 0x0000, 0x0000, {EACAPD}, "FSAVE %e" },
874 { 0xf340, 0xffc0, 0x0000, 0x0000, {EACAPI}, "FRESTORE %e" },
876 { 0xf280, 0xffc0, 0x0000, 0x0000, {BR16}, "FB%p %t" },
877 { 0xf2c0, 0xffc0, 0x0000, 0x0000, {BR32}, "FB%p %t" },
879 { 0xf408, 0xff38, 0x0000, 0x0000, {0}, "CINVL %C,(A%y)" },
880 { 0xf410, 0xff38, 0x0000, 0x0000, {0}, "CINVP %C,(A%y)" },
881 { 0xf418, 0xff38, 0x0000, 0x0000, {0}, "CINVA %C" },
882 { 0xf428, 0xff38, 0x0000, 0x0000, {0}, "CPUSHL %C,(A%y)" },
883 { 0xf430, 0xff38, 0x0000, 0x0000, {0}, "CPUSHP %C,(A%y)" },
884 { 0xf438, 0xff38, 0x0000, 0x0000, {0}, "CPUSHA %C" },
888 static Optable *optables[] =
890 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, 0, tb, tc, td, te, tf,
896 dumpinst(Inst *ip, char *buf, int n)
904 for (i = 0; i < ip->n && i*4+1 < n-4; i++, buf += 4)
905 _hexify(buf, ip->raw[i], 3);
911 getword(Inst *ip, uvlong offset)
913 if (ip->n < nelem(ip->raw)) {
914 if (get2(mymap, offset, &ip->raw[ip->n++]) > 0)
916 werrstr("can't read instruction: %r");
918 werrstr("instruction too big: %r");
923 getshorts(Inst *ip, void *where, int n)
925 if (ip->n+n < nelem(ip->raw)) {
926 if (get1(mymap, ip->addr+ip->n*2, (uchar*)&ip->raw[ip->n], n*2) < 0) {
927 werrstr("can't read instruction: %r");
930 memmove(where, &ip->raw[ip->n], n*2);
934 werrstr("instruction too big: %r");
939 i8(Inst *ip, long *l)
941 if (getword(ip, ip->addr+ip->n*2) < 0)
943 *l = ip->raw[ip->n-1]&0xff;
950 i16(Inst *ip, long *l)
952 if (getword(ip, ip->addr+ip->n*2) < 0)
954 *l = ip->raw[ip->n-1];
960 i32(Inst *ip, long *l)
962 if (getword(ip, ip->addr+ip->n*2) < 0)
964 if (getword(ip, ip->addr+ip->n*2) < 0)
966 *l = (ip->raw[ip->n-2]<<16)|ip->raw[ip->n-1];
971 getimm(Inst *ip, Operand *ap, int mode)
976 case EAM_B: /* byte */
978 return i8(ip, &ap->immediate);
979 case EADI_W: /* word */
981 return i16(ip, &ap->immediate);
982 case EADI_L: /* long */
984 return i32(ip, &ap->immediate);
985 case EAFLT: /* floating point - size in bits 10-12 or word 1 */
986 switch((ip->raw[1]>>10)&0x07)
988 case 0: /* long integer */
989 return i32(ip, &ap->immediate);
990 case 1: /* single precision real */
992 return getshorts(ip, ap->floater, 2);
993 case 2: /* extended precision real - not supported */
995 return getshorts(ip, ap->floater, 6);
996 case 3: /* packed decimal real - not supported */
998 return getshorts(ip, ap->floater, 12);
999 case 4: /* integer word */
1000 return i16(ip, &ap->immediate);
1001 case 5: /* double precision real */
1003 return getshorts(ip, ap->floater, 4);
1004 case 6: /* integer byte */
1005 return i8(ip, &ap->immediate);
1007 ip->errmsg = "bad immediate float data";
1011 case IV: /* size encoded in bits 6&7 of opcode word */
1013 switch((ip->raw[0]>>6)&0x03)
1015 case 0x00: /* integer byte */
1016 return i8(ip, &ap->immediate);
1017 case 0x01: /* integer word */
1018 return i16(ip, &ap->immediate);
1019 case 0x02: /* integer long */
1020 return i32(ip, &ap->immediate);
1022 ip->errmsg = "bad immediate size";
1030 getdisp(Inst *ip, Operand *ap)
1034 if (getword(ip, ip->addr+ip->n*2) < 0)
1036 ext = ip->raw[ip->n-1];
1038 if ((ext&0x100) == 0) { /* indexed with 7-bit displacement */
1039 ap->disp = ext&0x7f;
1044 switch(ext&0x30) /* first (inner) displacement */
1049 if (i16(ip, &ap->disp) < 0)
1053 if (i32(ip, &ap->disp) < 0)
1057 ip->errmsg = "bad EA displacement";
1060 switch (ext&0x03) /* outer displacement */
1062 case 0x02: /* 16 bit displacement */
1063 return i16(ip, &ap->outer);
1064 case 0x03: /* 32 bit displacement */
1065 return i32(ip, &ap->outer);
1073 ea(Inst *ip, int ea, Operand *ap, int mode)
1079 switch((ea>>3)&0x07)
1104 if (i16(ip, &ap->disp) < 0)
1110 if (getdisp(ip, ap) < 0)
1119 if (i16(ip, &ap->immediate) < 0)
1125 if (i32(ip, &ap->immediate) < 0)
1131 if (i16(ip, &ap->disp) < 0)
1137 if (getdisp(ip, ap) < 0)
1142 if (getimm(ip, ap, mode) < 0)
1146 ip->errmsg = "bad EA mode";
1150 /* Allowable floating point EAs are restricted for packed,
1151 * extended, and double precision operands
1153 if (mode == EAFLT) {
1154 size = (ip->raw[1]>>10)&0x07;
1155 if (size == 2 || size == 3 || size == 5)
1160 if (!(validea[mode]&type)) {
1161 ip->errmsg = "invalid EA";
1168 decode(Inst *ip, Optable *op)
1174 opcode = ip->raw[0];
1175 for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1177 mode = op->opdata[i];
1180 case EAPI: /* normal EA modes */
1202 if (ea(ip, opcode&0x3f, ap, mode) < 0)
1205 case EADDA: /* stupid bit flop required */
1206 t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1207 if (ea(ip, t, ap, EADA)< 0)
1210 case BREAC: /* EAC JMP or CALL operand */
1211 if (ea(ip, opcode&0x3f, ap, EAC) < 0)
1214 case OP8: /* weird movq instruction */
1216 ap->immediate = opcode&0xff;
1218 ap->immediate |= ~0xff;
1220 case I8: /* must be two-word opcode */
1222 ap->immediate = ip->raw[1]&0xff;
1223 if (ap->immediate&0x80)
1224 ap->immediate |= ~0xff;
1226 case I16: /* 16 bit immediate */
1229 if (i16(ip, &ap->immediate) < 0)
1232 case C16: /* CAS2 16 bit immediate */
1234 if (i16(ip, &ap->immediate) < 0)
1236 if (ap->immediate & 0x0e38) {
1237 ip->errmsg = "bad CAS2W operand";
1241 case I32: /* 32 bit immediate */
1244 if (i32(ip, &ap->immediate) < 0)
1247 case IV: /* immediate data depends on size field */
1248 if (getimm(ip, ap, IV) < 0)
1251 case BR8: /* branch displacement format */
1253 ap->immediate = opcode&0xff;
1254 if (ap->immediate == 0) {
1255 if (i16(ip, &ap->immediate) < 0)
1257 } else if (ap->immediate == 0xff) {
1258 if (i32(ip, &ap->immediate) < 0)
1260 } else if (ap->immediate & 0x80)
1261 ap->immediate |= ~0xff;
1263 case STACK: /* Dummy operand type for Return instructions */
1272 instruction(Inst *ip)
1279 if (getword(ip, ip->addr) < 0)
1281 opcode = ip->raw[0];
1282 if (get2(mymap, ip->addr+2, &op2) < 0)
1284 class = (opcode>>12)&0x0f;
1285 for (op = optables[class]; op && op->format; op++) {
1286 if (op->opcode != (opcode&op->mask0))
1288 if (op->op2 != (op2&op->mask1))
1291 ip->raw[ip->n++] = op2;
1294 ip->errmsg = "Invalid opcode";
1298 #pragma varargck argpos bprint 2
1301 bprint(Inst *i, char *fmt, ...)
1306 i->curr = vseprint(i->curr, i->end, fmt, arg);
1310 static char *regname[] =
1312 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0",
1313 "A1", "A2", "A3", "A4", "A5", "A6", "A7", "PC", "SB"
1317 plocal(Inst *ip, Operand *ap)
1325 if (!findsym(ip->addr, CTEXT, &s))
1328 moved = pc2sp(ip->addr);
1332 if (offset > moved) { /* above frame - must be argument */
1334 ret = getauto(&s, offset-mach->szaddr, CPARAM, &s);
1335 } else /* below frame - must be automatic */
1336 ret = getauto(&s, moved-offset, CPARAM, &s);
1338 bprint(ip, "%s+%lux", s.name, offset);
1340 none: bprint(ip, "%lux", ap->disp);
1344 * this guy does all the work of printing the base and index component
1348 pidx(Inst *ip, int ext, int reg, char *bfmt, char *ifmt, char *nobase)
1355 if (ext&0x80) { /* Base suppressed */
1357 bprint(ip, bfmt, "(ZPC)");
1362 } else /* format base reg */
1363 bprint(ip, bfmt, regname[reg]);
1364 if (ext & 0x40) /* index suppressed */
1366 switch ((ext>>9)&0x03)
1384 sprint(buf, "%s.%c%s", regname[(ext>>12)&0x0f], (ext&0x800) ? 'L' : 'W', s);
1386 bprint(ip, ifmt, buf);
1388 bprint(ip, "(%s)", buf);
1393 prindex(Inst *ip, int reg, Operand *ap)
1399 left = ip->end-ip->curr;
1404 /* look for static base register references */
1405 if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) {
1406 reg = 17; /* "A6" -> "SB" */
1409 if ((ext&0x100) == 0) { /* brief form */
1413 ip->curr += symoff(ip->curr, left, disp, CANY);
1414 pidx(ip, ext&0xff00, reg, "(%s)", "(%s)", 0);
1417 switch(ext&0x3f) /* bd size, && i/is */
1420 if (!pidx(ip, ext, reg, "(%s)", "(%s)", 0))
1424 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1431 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1432 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1436 if (!pidx(ip, ext, reg, "((%s))", "(%s)", 0))
1441 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1442 pidx(ip, ext, reg, "((%s))", "(%s)", 0);
1449 ip->curr += symoff(ip->curr, left, disp, CANY);
1450 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1458 ip->curr += symoff(ip->curr, left-1, disp, CANY);
1459 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1466 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1471 ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1472 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1481 ip->curr += symoff(ip->curr, left-1, disp, CANY);
1482 if (!pidx(ip, ext, reg, "(%s))", "(%s)", "())"))
1489 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1494 ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1495 pidx(ip, ext, reg, "(%s))", "(%s)", "())");
1498 bprint(ip, "??%x??", ext);
1499 ip->errmsg = "bad EA";
1505 pea(int reg, Inst *ip, Operand *ap)
1509 left = ip->end-ip->curr;
1515 bprint(ip, "R%d", reg);
1518 bprint(ip, "A%d", reg);
1521 bprint(ip, "(A%d)", reg);
1524 bprint(ip, "(A%d)+", reg);
1527 bprint(ip, "-(A%d)", reg);
1530 ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY);
1533 prindex(ip, 16, ap);
1535 case ADisp: /* references off the static base */
1536 if (reg == 6 && mach->sb && ap->disp) {
1537 ip->curr += symoff(ip->curr, left, ap->disp+mach->sb, CANY);
1541 /* reference autos and parameters off the stack */
1545 ip->curr += symoff(ip->curr, left, ap->disp, CANY);
1546 bprint(ip, "(A%d)", reg);
1549 prindex(ip, reg+8, ap);
1552 ip->curr += symoff(ip->curr, left, ap->immediate, CANY);
1557 ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY);
1561 ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater);
1565 ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater);
1569 for (i = 0; i < 24 && ip->curr < ip->end-1; i++) {
1570 _hexify(ip->curr, ap->floater[i], 1);
1576 ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater);
1579 bprint(ip, "??%x??", ap->eatype);
1580 ip->errmsg = "bad EA type";
1585 static char *cctab[] = { "F", "T", "HI", "LS", "CC", "CS", "NE", "EQ",
1586 "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" };
1587 static char *fcond[] =
1589 "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR",
1590 "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T",
1591 "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE",
1592 "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST"
1594 static char *cachetab[] = { "NC", "DC", "IC", "BC" };
1595 static char *mmutab[] = { "TC", "??", "SRP", "CRP" };
1596 static char *crtab0[] =
1598 "SFC", "DFC", "CACR", "TC", "ITT0", "ITT1", "DTT0", "DTT1",
1600 static char *crtab1[] =
1602 "USP", "VBR", "CAAR", "MSP", "ISP", "MMUSR", "URP", "SRP",
1604 static char typetab[] = { 'L', 'S', 'X', 'P', 'W', 'D', 'B', '?', };
1605 static char sztab[] = {'?', 'B', 'W', 'L', '?' };
1608 formatins(char *fmt, Inst *ip)
1617 for (; *fmt && ip->curr < ip->end; fmt++) {
1625 case 'a': /* register number; word 1:[0-2] */
1626 *ip->curr++ = (w1&0x07)+'0';
1628 case 'c': /* condition code; opcode: [8-11] */
1629 bprint(ip, cctab[(op>>8)&0x0f]);
1631 case 'd': /* shift direction; opcode: [8] */
1637 case 'e': /* source effective address */
1638 pea(op&0x07, ip, &ip->and[currand++]);
1640 case 'f': /* trap vector; op code: [0-3] */
1641 bprint(ip, "%x", op&0x0f);
1643 case 'h': /* register number; word 1: [5-7] */
1644 *ip->curr++ = (w1>>5)&0x07+'0';
1646 case 'i': /* immediate operand */
1647 ip->curr += symoff(ip->curr, ip->end-ip->curr,
1648 ip->and[currand++].immediate, CANY);
1650 case 'j': /* data registers; word 1: [0-2] & [12-14] */
1654 bprint(ip, "R%d", r1);
1656 bprint(ip, "R%d:R%d", r2, r1);
1658 case 'k': /* k factor; word 1 [0-6] */
1659 bprint(ip, "%x", w1&0x7f);
1661 case 'm': /* register mask; word 1 [0-7] */
1662 bprint(ip, "%x", w1&0xff);
1664 case 'o': /* bit field offset; word1: [6-10] */
1665 bprint(ip, "%d", (w1>>6)&0x3f);
1667 case 'p': /* conditional predicate; opcode: [0-5]
1668 only bits 0-4 are defined */
1669 bprint(ip, fcond[op&0x1f]);
1671 case 'q': /* 3-bit immediate value; opcode[9-11] */
1676 *ip->curr++ = r1+'0';
1678 case 'r': /* register type & number; word 1: [12-15] */
1679 bprint(ip, regname[(w1>>12)&0x0f]);
1681 case 's': /* size; opcode [6-7] */
1682 *ip->curr = sztab[((op>>6)&0x03)+1];
1683 if (*ip->curr++ == '?')
1684 ip->errmsg = "bad size code";
1686 case 't': /* text offset */
1687 ip->curr += symoff(ip->curr, ip->end-ip->curr,
1688 ip->and[currand++].immediate+ip->addr+2, CTEXT);
1690 case 'u': /* register number; word 1: [6-8] */
1691 *ip->curr++ = ((w1>>6)&0x07)+'0';
1693 case 'w': /* bit field width; word 1: [0-4] */
1694 bprint(ip, "%d", w1&0x0f);
1696 case 'x': /* register number; opcode: [9-11] */
1697 *ip->curr++ = ((op>>9)&0x07)+'0';
1699 case 'y': /* register number; opcode: [0-2] */
1700 *ip->curr++ = (op&0x07)+'0';
1702 case 'z': /* shift count; opcode: [9-11] */
1703 *ip->curr++ = ((op>>9)&0x07)+'0';
1705 case 'A': /* register number; word 2: [0-2] */
1706 *ip->curr++ = (ip->raw[2]&0x07)+'0';
1708 case 'B': /* float source reg; word 1: [10-12] */
1709 *ip->curr++ = ((w1>>10)&0x07)+'0';
1711 case 'C': /* cache identifier; opcode: [6-7] */
1712 bprint(ip, cachetab[(op>>6)&0x03]);
1714 case 'D': /* float dest reg; word 1: [7-9] */
1715 *ip->curr++ = ((w1>>7)&0x07)+'0';
1717 case 'E': /* destination EA; opcode: [6-11] */
1718 pea((op>>9)&0x07, ip, &ip->and[currand++]);
1720 case 'F': /* float dest register(s); word 1: [7-9] & [10-12] */
1724 bprint(ip, "F%d", r1);
1726 bprint(ip, "F%d,F%d", r2, r1);
1728 case 'H': /* MMU register; word 1 [10-13] */
1729 bprint(ip, mmutab[(w1>>10)&0x03]);
1730 if (ip->curr[-1] == '?')
1731 ip->errmsg = "bad mmu register";
1733 case 'I': /* MMU function code mask; word 1: [5-8] */
1734 bprint(ip, "%x", (w1>>4)&0x0f);
1736 case 'K': /* dynamic k-factor register; word 1: [5-8] */
1737 bprint(ip, "%d", (w1>>4)&0x0f);
1739 case 'L': /* MMU function code; word 1: [0-6] */
1741 bprint(ip, "%x", w1&0x0f);
1743 bprint(ip, "R%d",w1&0x07);
1749 case 'N': /* control register; word 1: [0-11] */
1752 bprint(ip, crtab1[r1&0x07]);
1754 bprint(ip, crtab0[r1&0x07]);
1756 case 'P': /* conditional predicate; word 1: [0-5] */
1757 bprint(ip, fcond[w1&0x1f]);
1759 case 'R': /* register type & number; word 2 [12-15] */
1760 bprint(ip, regname[(ip->raw[2]>>12)&0x0f]);
1762 case 'S': /* float source type code; word 1: [10-12] */
1763 *ip->curr = typetab[(w1>>10)&0x07];
1764 if (*ip->curr++ == '?')
1765 ip->errmsg = "bad float type";
1767 case 'U': /* register number; word 2: [6-8] */
1768 *ip->curr++ = ((ip->raw[2]>>6)&0x07)+'0';
1770 case 'Z': /* ATC level number; word 1: [10-12] */
1771 bprint(ip, "%x", (w1>>10)&0x07);
1773 case '1': /* effective address in second operand*/
1774 pea(op&0x07, ip, &ip->and[1]);
1777 bprint(ip, "%%%c", *fmt);
1781 *ip->curr = 0; /* there's always room for 1 byte */
1788 static int dsize[] = {0, 0, 1, 2}; /* in words */
1790 if (get2(mymap, ip->addr+ip->n*2, &ext) < 0)
1792 if ((ext&0x100) == 0)
1794 return dsize[(ext>>4)&0x03]+dsize[ext&0x03]+1;
1798 immsize(Inst *ip, int mode)
1800 static int fsize[] = { 2, 2, 6, 12, 1, 4, 1, -1 };
1801 static int isize[] = { 1, 1, 2, -1 };
1805 case EAM_B: /* byte */
1807 case EADI_W: /* word */
1810 case EADI_L: /* long */
1813 case EAFLT: /* floating point - size in bits 10-12 or word 1 */
1814 return fsize[(ip->raw[1]>>10)&0x07];
1815 case IV: /* size encoded in bits 6&7 of opcode word */
1817 return isize[(ip->raw[0]>>6)&0x03];
1822 easize(Inst *ip, int ea, int mode)
1824 switch((ea>>3)&0x07)
1835 return dispsize(ip);
1845 return dispsize(ip);
1847 return immsize(ip, mode);
1856 instrsize(Inst *ip, Optable *op)
1861 opcode = ip->raw[0];
1862 for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1863 mode = op->opdata[i];
1866 case EAPI: /* normal EA modes */
1888 t = easize(ip, opcode&0x3f, mode);
1893 case EADDA: /* stupid bit flop required */
1894 t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1895 t = easize(ip, t, mode);
1900 case BREAC: /* EAC JMP or CALL operand */
1901 /* easy displacements for follow set */
1902 if ((opcode&0x038) == 0x28 || (opcode&0x3f) == 0x3a) {
1903 if (i16(ip, &ip->and[i].immediate) < 0)
1906 t = easize(ip, opcode&0x3f, mode);
1912 case I16: /* 16 bit immediate */
1913 case C16: /* CAS2 16 bit immediate */
1916 case BR16: /* 16 bit branch displacement */
1917 if (i16(ip, &ip->and[i].immediate) < 0)
1920 case BR32: /* 32 bit branch displacement */
1921 if (i32(ip, &ip->and[i].immediate) < 0)
1924 case I32: /* 32 bit immediate */
1927 case IV: /* immediate data depends on size field */
1928 t = (ip->raw[0]>>6)&0x03;
1936 case BR8: /* loony branch displacement format */
1939 if (i16(ip, &ip->and[i].immediate) < 0)
1941 } else if (t == 0xff) {
1942 if (i32(ip, &ip->and[i].immediate) < 0)
1945 ip->and[i].immediate = t;
1947 ip->and[i].immediate |= ~0xff;
1950 case STACK: /* Dummy operand for Return instructions */
1951 case OP8: /* weird movq instruction */
1952 case I8: /* must be two-word opcode */
1961 eaval(Inst *ip, Operand *ap, Rgetter rget)
1966 reg = ip->raw[0]&0x07;
1970 sprint(buf, "A%d", reg);
1971 return (*rget)(mymap, buf);
1973 return ip->addr+2+ap->disp;
1975 sprint(buf, "A%d", reg);
1976 return ap->disp+(*rget)(mymap, buf);
1978 return ap->immediate;
1985 m68020instlen(Map *map, uvlong pc)
1993 op = instruction(&i);
1994 if (op && instrsize(&i, op) > 0)
2000 m68020foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2010 op = instruction(&i);
2011 if (op == 0 || instrsize(&i, op) < 0)
2013 for (j = 0; j < nelem(op->opdata) && op->opdata[j]; j++) {
2014 switch(op->opdata[j])
2016 case BREAC: /* CALL, JMP, JSR */
2017 foll[0] = pc+2+eaval(&i, &i.and[j], rget);
2019 case BR8: /* Bcc, BSR, & BRA */
2020 case BR16: /* FBcc, FDBcc, DBcc */
2021 case BR32: /* FBcc */
2023 foll[1] = pc+2+i.and[j].immediate;
2025 case STACK: /* RTR, RTS, RTD */
2026 if (get4(map, (*rget)(map, mach->sp), &l) < 0)
2039 m68020inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2050 op = instruction(&i);
2053 if (decode(&i, op) > 0)
2054 formatins(op->format, &i);
2057 bprint(&i, "\t\t;");
2058 bprint(&i, "%s: ", i.errmsg);
2059 dumpinst(&i, i.curr, i.end-i.curr);
2065 m68020das(Map *map, uvlong pc, char *buf, int n)
2076 op = instruction(&i);
2081 bprint(&i, "%s: ", i.errmsg);
2082 dumpinst(&i, i.curr, i.end-i.curr);