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)
114 stktop = mach->kbase+mach->pgsize;
115 for(i=3; i<100; i++){
116 if (get1(map, stktop-i*4, (uchar*)&l, 4)< 0)
119 if(machdata->swal(l) == 0xBADC0C0A){
120 if (get1(map, stktop-(i-1)*4, (uchar *)&efl[0], 4) < 0)
122 if (get1(map, stktop-(i-2)*4, (uchar *)&efl[1], 4) < 0)
124 fvo = (ef[6]<<8)|ef[7];
130 for(ft=ftype; ft->name; ft++) {
131 if(ft->fmt == ((fvo>>12) & 0xF)){
143 m68020excep(Map *map, Rgetter rget)
148 if (m68020ufix(map) < 0)
149 return "bad exception frame";
151 if(excep[m68020vec] == 0)
152 return "bad exeception type";
154 if(m68020vec == BPTTRAP) {
155 pc = (*rget)(map, "PC");
156 if (get1(map, pc, buf, machdata->bpsize) > 0)
157 if(memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
160 return excep[m68020vec];
162 /* 68020 Disassembler and related functions */
164 not supported: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, cpSAVE
167 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
168 %y - register number x x x
169 %f - trap vector x x x
170 %e - destination eff addr x x x x x x
171 %p - conditional predicate x x x x x x
174 %E - source eff addr. x x x x x x
176 %c - condition code x x x x
177 %x - register number x x x
178 %b - shift count x x x
179 %q - daffy 3-bit quick operand or shift count x x x
180 %i - immediate operand <varies>
181 %t - offset(PC) <varies>
184 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
185 %a - register number x x x
186 %w - bit field width x x x x x
187 %L - MMU function code (SFC/DFC/D%a/#[0-3]) x x x x x
188 %P - conditional predicate x x x x x x
189 %k - k factor x x x x x x x
190 %m - register mask x x x x x x x x
191 %N - control register id x x x x x x x x x x x x
192 %j - (Dq != Dr) ? Dq:Dr : Dr x x x x x x
193 %K - dynamic k register x x x
194 %h - register number x x x
195 %I - MMU function code mask x x x x
196 %o - bit field offset x x x x x
197 %u - register number x x x
198 %D - float dest reg x x x
199 %F - (fdr==fsr) ? "F%D" :"F%B,F%D" x x x x x x
200 %S - float source type x x x
201 %B - float source register x x x
202 %Z - ATC level number x x x
203 %H - MMU register x x x x
204 %r - register type/number x x x x
207 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
208 %A - register number x x x
209 %U - register number x x x
210 %R - register type,number x x x x
212 -----------------------------------------------------------------------------
214 %a - register [word 1: 0-2]
215 %c - condition code [opcode: 8-11]
216 %d - direction [opcode: 8]
217 %e - destination effective address [opcode: 0-5]
218 %f - trap vector [opcode: 0-3]
219 %h - register [word 1: 5-7]
220 %i - immediate operand (1, 2, or 4 bytes)
221 %j - Dq:Dr if Dq != Dr; else Dr => Dr [word 1: 0-2] Dq [word 1: 12-14]
222 %k - k factor [word 1: 0-6]
223 %m - register mask [word 1: 0-7]
224 %o - bit field offset [word 1: 6-10]
225 %p - conditional predicate [opcode: 0-5]
226 %q - daffy 3-bit quick operand [opcode: 9-11]
227 %r - register type, [word 1: 15], register [word 1: 12-14]
228 %s - size [opcode: 6-7]
229 %t - offset beyond pc (text address) (2 or 4 bytes)
230 %u - register [word 1: 6-8]
231 %w - bit field width [word 1: 0-4]
232 %x - register [opcode: 9-11]
233 %y - register [opcode: 0-2]
234 %A - register [word 2: 0-2]
235 %B - float source register [word 1: 10-12]
236 %C - cache identifier [opcode: 6-7] (IC, DC, or BC)
237 %D - float dest reg [word 1: 7-9]
238 %E - dest effective address [opcode: 6-11]
239 %F - float dest reg == float src reg => "F%D"; else "F%B,F%D"
240 %H - MMU reg [word 1: 10-13] (see above & p 4-53/54)
241 %I - MMU function code mask [word 1: 5-8]
242 %K - dynamic k factor register [word 1: 4-6]
243 %L - MMU function code [word 1: 0-4] (SFC, DFC, D%a, or #[0-3])
244 %N - control register [word 1: 0-11]
245 %P - conditional predicate [word 1: 0-5]
246 %R - register type, [word 2: 15], register [word 2: 12-14]
247 %S - float source type code [word 1: 10-12]
248 %U - register [word 2: 6-8]
249 %Z - ATC level number [word 1: 10-12]
250 %1 - Special case: EA as second operand
252 /* Operand classes */
254 EAPI = 1, /* extended address: pre decrement only */
255 EACA, /* extended address: control alterable */
256 EACAD, /* extended address: control alterable or Dreg */
257 EACAPI, /* extended address: control alterable or post-incr */
258 EACAPD, /* extended address: control alterable or pre-decr */
259 EAMA, /* extended address: memory alterable */
260 EADA, /* extended address: data alterable */
261 EAA, /* extended address: alterable */
262 EAC, /* extended address: control addressing */
263 EACPI, /* extended address: control addressing or post-incr */
264 EACD, /* extended address: control addressing or Dreg */
265 EAD, /* extended address: data addressing */
266 EAM, /* extended address: memory addressing */
267 EAM_B, /* EAM with byte immediate data */
268 EADI, /* extended address: data addressing or immediate */
269 EADI_L, /* EADI with long immediate data */
270 EADI_W, /* EADI with word immediate data */
271 EAALL, /* extended address: all modes */
272 EAALL_L, /* EAALL with long immediate data */
273 EAALL_W, /* EAALL with word immediate data */
274 EAALL_B, /* EAALL with byte immediate date */
275 /* special codes not directly used for validation */
276 EAFLT, /* extended address: EADI for B, W, L, or S; else EAM */
277 EADDA, /* destination extended address: EADA */
278 BREAC, /* EAC operand for JMP or CALL */
279 OP8, /* low 8 bits of op word */
280 I8, /* low 8-bits of first extension word */
281 I16, /* 16 bits in first extension word */
282 I32, /* 32 bits in first and second extension words */
283 IV, /* 8, 16 or 32 bit data in first & 2nd extension words */
284 C16, /* CAS2 16 bit immediate with bits 9-11 & 3-5 zero */
285 BR8, /* 8 bits in op word or 16 or 32 bits in extension words
286 branch instruction format (p. 2-25) */
287 BR16, /* 16-bit branch displacement */
288 BR32, /* 32-bit branch displacement */
289 STACK, /* return PC on stack - follow set only */
291 /* validation bit masks for various EA classes */
293 Dn = 0x0001, /* Data register */
294 An = 0x0002, /* Address register */
295 Ind = 0x0004, /* Address register indirect */
296 Pinc = 0x0008, /* Address register indirect post-increment */
297 Pdec = 0x0010, /* Address register indirect pre-decrement */
298 Bdisp = 0x0020, /* Base/Displacement in all its forms */
299 PCrel = 0x0040, /* PC relative addressing in all its forms */
300 Imm = 0x0080, /* Immediate data */
301 Abs = 0x0100, /* Absolute */
303 /* EA validation table indexed by operand class number */
305 static short validea[] =
309 Abs|Bdisp|Ind, /* EACA */
310 Abs|Bdisp|Ind|Dn, /* EACAD */
311 Abs|Bdisp|Pinc|Ind, /* EACAPI */
312 Abs|Bdisp|Pdec|Ind, /* EACAPD */
313 Abs|Bdisp|Pdec|Pinc|Ind, /* EAMA */
314 Abs|Bdisp|Pdec|Pinc|Ind|Dn, /* EADA */
315 Abs|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAA */
316 Abs|PCrel|Bdisp|Ind, /* EAC */
317 Abs|PCrel|Bdisp|Pinc|Ind, /* EACPI */
318 Abs|PCrel|Bdisp|Ind|Dn, /* EACD */
319 Abs|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EAD */
320 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind, /* EAM */
321 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind, /* EAM_B */
322 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI */
323 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI_L */
324 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI_W */
325 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL */
326 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_L */
327 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_W */
328 Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_B */
338 ADisp, /* Displacement beyond (An) */
339 BXD, /* Base, Index, Displacement */
340 PDisp, /* Displacement beyond PC */
341 PXD, /* PC, Index, Displacement */
344 IREAL, /* single precision real immediate */
345 IEXT, /* extended precision real immediate */
346 IPACK, /* packed real immediate */
347 IDBL, /* double precision real immediate */
350 typedef struct optable Optable;
351 typedef struct operand Operand;
352 typedef struct inst Inst;
369 long immediate; /* sign-extended integer byte/word/long */
370 struct { /* index mode displacements */
374 char floater[24]; /* floating point immediates */
380 int n; /* # bytes in instruction */
381 uvlong addr; /* addr of start of instruction */
382 ushort raw[4+12]; /* longest instruction: 24 byte packed immediate */
384 char *end; /* end of print buffer */
385 char *curr; /* current fill point in buffer */
388 /* class 0: bit field, MOVEP & immediate instructions */
389 static Optable t0[] = {
390 { 0x003c, 0xffff, 0x0000, 0xff00, {I8}, "ORB %i,CCR" },
391 { 0x007c, 0xffff, 0x0000, 0x0000, {I16}, "ORW %i,SR" },
392 { 0x023c, 0xffff, 0x0000, 0xff00, {I8}, "ANDB %i,CCR" },
393 { 0x027c, 0xffff, 0x0000, 0x0000, {I16}, "ANDW %i,SR" },
394 { 0x0a3c, 0xffff, 0x0000, 0xff00, {I8}, "EORB %i,CCR" },
395 { 0x0a7c, 0xffff, 0x0000, 0x0000, {I16}, "EORW %i,SR" },
396 { 0x0cfc, 0xffff, 0x0000, 0x0000, {C16,C16}, "CAS2W R%a:R%A,R%u:R%U,(%r):(%R)"} ,
397 { 0x0efc, 0xffff, 0x0000, 0x0000, {C16,C16}, "CAS2L R%a:R%A,R%u:R%U,(%r):(%R)"} ,
399 { 0x06c0, 0xfff8, 0x0000, 0x0000, {0}, "RTM R%y" },
400 { 0x06c8, 0xfff8, 0x0000, 0x0000, {0}, "RTM A%y" },
401 { 0x0800, 0xfff8, 0x0000, 0x0000, {I16}, "BTSTL %i,R%y" },
402 { 0x0840, 0xfff8, 0x0000, 0x0000, {I16}, "BCHGL %i,R%y" },
403 { 0x0880, 0xfff8, 0x0000, 0x0000, {I16}, "BCLRL %i,R%y" },
405 { 0x00c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2B %e,%r" },
406 { 0x00c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2B %e,%r" },
407 { 0x02c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2W %e,%r" },
408 { 0x02c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2W %e,%r" },
409 { 0x04c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2L %e,%r" },
410 { 0x04c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2L %e,%r" },
411 { 0x06c0, 0xffc0, 0x0000, 0x0000, {I16, BREAC}, "CALLM %i,%e" },
412 { 0x0800, 0xffc0, 0x0000, 0x0000, {I16, EAD}, "BTSTB %i,%e" },
413 { 0x0840, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BCHG %i,%e" },
414 { 0x0880, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BCLR %i,%e" },
415 { 0x08c0, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BSET %i,%e" },
416 { 0x0ac0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASB R%a,R%u,%e" },
417 { 0x0cc0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASW R%a,R%u,%e" },
418 { 0x0ec0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASL R%a,R%u,%e" },
420 { 0x0000, 0xff00, 0x0000, 0x0000, {IV, EADA}, "OR%s %i,%e" },
421 { 0x0200, 0xff00, 0x0000, 0x0000, {IV, EADA}, "AND%s %i,%e" },
422 { 0x0400, 0xff00, 0x0000, 0x0000, {IV, EADA}, "SUB%s %i,%e" },
423 { 0x0600, 0xff00, 0x0000, 0x0000, {IV, EADA}, "ADD%s %i,%e" },
424 { 0x0a00, 0xff00, 0x0000, 0x0000, {IV, EADA}, "EOR%s %i,%e" },
425 { 0x0c00, 0xff00, 0x0000, 0x0000, {IV, EAD}, "CMP%s %i,%e" },
426 { 0x0e00, 0xff00, 0x0000, 0x0800, {EAMA}, "MOVES%s %e,%r" },
427 { 0x0e00, 0xff00, 0x0800, 0x0800, {EAMA}, "MOVES%s %r,%e" },
429 { 0x0108, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPW (%i,A%y),R%x" },
430 { 0x0148, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPL (%i,A%y),R%x" },
431 { 0x0188, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPW R%x,(%i,A%y)" },
432 { 0x01c8, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPL R%x,(%i,A%y)" },
433 { 0x0100, 0xf1f8, 0x0000, 0x0000, {0}, "BTSTL R%x,R%y" },
434 { 0x0140, 0xf1f8, 0x0000, 0x0000, {0}, "BCHGL R%x,R%y" },
435 { 0x0180, 0xf1f8, 0x0000, 0x0000, {0}, "BCLRL R%x,R%y" },
436 { 0x01c0, 0xf1f8, 0x0000, 0x0000, {0}, "BSET R%x,R%y" },
438 { 0x0100, 0xf1c0, 0x0000, 0x0000, {EAM_B}, "BTSTB R%x,%e" },
439 { 0x0140, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BCHG R%x,%e" },
440 { 0x0180, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BCLR R%x,%e" },
441 { 0x01c0, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BSET R%x,%e" },
444 /* class 1: move byte */
445 static Optable t1[] = {
446 { 0x1000, 0xf000, 0x0000, 0x0000, {EAALL_B,EADDA},"MOVB %e,%E" },
449 /* class 2: move long */
450 static Optable t2[] = {
451 { 0x2040, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "MOVL %e,A%x" },
453 { 0x2000, 0xf000, 0x0000, 0x0000, {EAALL_L,EADDA},"MOVL %e,%E" },
456 /* class 3: move word */
457 static Optable t3[] = {
458 { 0x3040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "MOVW %e,A%x" },
460 { 0x3000, 0xf000, 0x0000, 0x0000, {EAALL_W,EADDA},"MOVW %e,%E" },
463 /* class 4: miscellaneous */
464 static Optable t4[] = {
465 { 0x4e75, 0xffff, 0x0000, 0x0000, {STACK}, "RTS" },
466 { 0x4e77, 0xffff, 0x0000, 0x0000, {STACK}, "RTR" },
467 { 0x4afc, 0xffff, 0x0000, 0x0000, {0}, "ILLEGAL" },
468 { 0x4e71, 0xffff, 0x0000, 0x0000, {0}, "NOP" },
469 { 0x4e74, 0xffff, 0x0000, 0x0000, {I16, STACK}, "RTD %i" },
470 { 0x4e76, 0xffff, 0x0000, 0x0000, {0}, "TRAPV" },
471 { 0x4e70, 0xffff, 0x0000, 0x0000, {0}, "RESET" },
472 { 0x4e72, 0xffff, 0x0000, 0x0000, {I16}, "STOP %i" },
473 { 0x4e73, 0xffff, 0x0000, 0x0000, {0}, "RTE" },
474 { 0x4e7a, 0xffff, 0x0000, 0x0000, {I16}, "MOVEL %N,%r" },
475 { 0x4e7b, 0xffff, 0x0000, 0x0000, {I16}, "MOVEL %r,%N" },
477 { 0x4808, 0xfff8, 0x0000, 0x0000, {I32}, "LINKL A%y,%i" },
478 { 0x4840, 0xfff8, 0x0000, 0x0000, {0}, "SWAPW R%y" },
479 { 0x4848, 0xfff8, 0x0000, 0x0000, {0}, "BKPT #%y" },
480 { 0x4880, 0xfff8, 0x0000, 0x0000, {0}, "EXTW R%y" },
481 { 0x48C0, 0xfff8, 0x0000, 0x0000, {0}, "EXTL R%y" },
482 { 0x49C0, 0xfff8, 0x0000, 0x0000, {0}, "EXTBL R%y" },
483 { 0x4e50, 0xfff8, 0x0000, 0x0000, {I16}, "LINKW A%y,%i" },
484 { 0x4e58, 0xfff8, 0x0000, 0x0000, {0}, "UNLK A%y" },
485 { 0x4e60, 0xfff8, 0x0000, 0x0000, {0}, "MOVEL (A%y),USP" },
486 { 0x4e68, 0xfff8, 0x0000, 0x0000, {0}, "MOVEL USP,(A%y)" },
488 { 0x4e40, 0xfff0, 0x0000, 0x0000, {0}, "SYS %f" },
490 { 0x40c0, 0xffc0, 0x0000, 0x0000, {EADA}, "MOVW SR,%e" },
491 { 0x42c0, 0xffc0, 0x0000, 0x0000, {EADA}, "MOVW CCR,%e" },
492 { 0x44c0, 0xffc0, 0x0000, 0x0000, {EADI_W}, "MOVW %e,CCR" },
493 { 0x46c0, 0xffc0, 0x0000, 0x0000, {EADI_W}, "MOVW %e,SR" },
494 { 0x4800, 0xffc0, 0x0000, 0x0000, {EADA}, "NBCDB %e" },
495 { 0x4840, 0xffc0, 0x0000, 0x0000, {EAC}, "PEA %e" },
496 { 0x4880, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEMW %i,%e" },
497 { 0x48c0, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEML %i,%e" },
498 { 0x4ac0, 0xffc0, 0x0000, 0x0000, {EADA}, "TAS %e" },
499 { 0x4a00, 0xffc0, 0x0000, 0x0000, {EAD}, "TSTB %e" },
500 { 0x4c00, 0xffc0, 0x0000, 0x8ff8, {EADI_L}, "MULUL %e,%r" },
501 { 0x4c00, 0xffc0, 0x0400, 0x8ff8, {EADI_L}, "MULUL %e,R%a:%r" },
502 { 0x4c00, 0xffc0, 0x0800, 0x8ff8, {EADI_L}, "MULSL %e,%r" },
503 { 0x4c00, 0xffc0, 0x0c00, 0x8ff8, {EADI_L}, "MULSL %e,R%a:%r" },
504 { 0x4c40, 0xffc0, 0x0000, 0x8ff8, {EADI_L}, "DIVUL %e,%j" },
505 { 0x4c40, 0xffc0, 0x0400, 0x8ff8, {EADI_L}, "DIVUD %e,%r:R%a" },
506 { 0x4c40, 0xffc0, 0x0800, 0x8ff8, {EADI_L}, "DIVSL %e,%j" },
507 { 0x4c40, 0xffc0, 0x0c00, 0x8ff8, {EADI_L}, "DIVSD %e,%r:R%a" },
508 { 0x4c80, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEMW %1,%i" },
509 { 0x4cc0, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEML %1,%i" },
510 { 0x4e80, 0xffc0, 0x0000, 0x0000, {BREAC}, "JSR %e" },
511 { 0x4ec0, 0xffc0, 0x0000, 0x0000, {BREAC}, "JMP %e" },
513 { 0x4000, 0xff00, 0x0000, 0x0000, {EADA}, "NEGX%s %e" },
514 { 0x4200, 0xff00, 0x0000, 0x0000, {EADA}, "CLR%s %e" },
515 { 0x4400, 0xff00, 0x0000, 0x0000, {EADA}, "NEG%s %e" },
516 { 0x4600, 0xff00, 0x0000, 0x0000, {EADA}, "NOT%s %e" },
517 { 0x4a00, 0xff00, 0x0000, 0x0000, {EAALL}, "TST%s %e" },
519 { 0x4180, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "CHKW %e,R%x" },
520 { 0x41c0, 0xf1c0, 0x0000, 0x0000, {EAC}, "LEA %e,A%x" },
521 { 0x4100, 0xf1c0, 0x0000, 0x0000, {EADI_L}, "CHKL %e,R%x" },
524 /* class 5: miscellaneous quick, branch & trap instructions */
525 static Optable t5[] = {
526 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EADA}, "ADDB $Q#%q,%e" },
527 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EADA}, "SUBB $Q#%q,%e" },
529 { 0x50c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" },
530 { 0x51c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" },
532 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDB $Q#%q,%e" },
533 { 0x5040, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDW $Q#%q,%e" },
534 { 0x5080, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDL $Q#%q,%e" },
535 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBB $Q#%q,%e" },
536 { 0x5140, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBW $Q#%q,%e" },
537 { 0x5180, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBL $Q#%q,%e" },
539 { 0x50fa, 0xf0ff, 0x0000, 0x0000, {I16}, "TRAP%cW %i" },
540 { 0x50fb, 0xf0ff, 0x0000, 0x0000, {I32}, "TRAP%cL %i" },
541 { 0x50fc, 0xf0ff, 0x0000, 0x0000, {0}, "TRAP%c" },
543 { 0x50c0, 0xf0c0, 0x0000, 0x0000, {EADA}, "S%c %e" },
546 /* class 6: branch instructions */
547 static Optable t6[] = {
548 { 0x6000, 0xff00, 0x0000, 0x0000, {BR8}, "BRA %t" },
549 { 0x6100, 0xff00, 0x0000, 0x0000, {BR8}, "BSR %t" },
550 { 0x6000, 0xf000, 0x0000, 0x0000, {BR8}, "B%c %t" },
553 /* class 7: move quick */
554 static Optable t7[] = {
555 { 0x7000, 0xf100, 0x0000, 0x0000, {OP8}, "MOVL $Q%i,R%x" },
558 /* class 8: BCD operations, DIV, and OR instructions */
559 static Optable t8[] = {
560 { 0x8100, 0xf1f8, 0x0000, 0x0000, {0}, "SBCDB R%y,R%x" },
561 { 0x8108, 0xf1f8, 0x0000, 0x0000, {0}, "SBCDB -(A%y),-(A%x)" },
562 { 0x8140, 0xf1f8, 0x0000, 0x0000, {I16}, "PACK R%y,R%x,%i" },
563 { 0x8148, 0xf1f8, 0x0000, 0x0000, {I16}, "PACK -(A%y),-(A%x),%i" },
564 { 0x8180, 0xf1f8, 0x0000, 0x0000, {I16}, "UNPK R%y,R%x,%i" },
565 { 0x8188, 0xf1f8, 0x0000, 0x0000, {I16}, "UNPK -(A%y),-(A%x),%i" },
567 { 0x80c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVUW %e,R%x" },
568 { 0x81c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVSW %e,R%x" },
570 { 0x8000, 0xf100, 0x0000, 0x0000, {EADI}, "OR%s %e,R%x" },
571 { 0x8100, 0xf100, 0x0000, 0x0000, {EAMA}, "OR%s R%x,%e" },
574 /* class 9: subtract instruction */
575 static Optable t9[] = {
576 { 0x90c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "SUBW %e,A%x" },
577 { 0x91c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "SUBL %e,A%x" },
579 { 0x9100, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s R%y,R%x" },
580 { 0x9108, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s -(A%y),-(A%x)" },
582 { 0x9000, 0xf100, 0x0000, 0x0000, {EAALL}, "SUB%s %e,R%x" },
583 { 0x9100, 0xf100, 0x0000, 0x0000, {EAMA}, "SUB%s R%x,%e" },
586 /* class b: CMP & EOR */
587 static Optable tb[] = {
588 { 0xb000, 0xf1c0, 0x0000, 0x0000, {EADI}, "CMPB R%x,%e" },
589 { 0xb040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "CMPW R%x,%e" },
590 { 0xb080, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "CMPL R%x,%e" },
591 { 0xb0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "CMPW A%x,%e" },
592 { 0xb1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "CMPL A%x,%e" },
594 { 0xb108, 0xf138, 0x0000, 0x0000, {0}, "CMP%s (A%y)+,(A%x)+" },
596 { 0xb100, 0xf100, 0x0000, 0x0000, {EADA}, "EOR%s %e,R%x" },
599 /* class c: AND, MUL, BCD & Exchange */
600 static Optable tc[] = {
601 { 0xc100, 0xf1f8, 0x0000, 0x0000, {0}, "ABCDB R%y,R%x" },
602 { 0xc108, 0xf1f8, 0x0000, 0x0000, {0}, "ABCDB -(A%y),-(A%x)" },
603 { 0xc140, 0xf1f8, 0x0000, 0x0000, {0}, "EXG R%x,R%y" },
604 { 0xc148, 0xf1f8, 0x0000, 0x0000, {0}, "EXG A%x,A%y" },
605 { 0xc188, 0xf1f8, 0x0000, 0x0000, {0}, "EXG R%x,A%y" },
607 { 0xc0c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULUW %e,R%x" },
608 { 0xc1c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULSW %e,R%x" },
610 { 0xc000, 0xf100, 0x0000, 0x0000, {EADI}, "AND%s %e,R%x" },
611 { 0xc100, 0xf100, 0x0000, 0x0000, {EAMA}, "AND%s R%x,%e" },
614 /* class d: addition */
615 static Optable td[] = {
616 { 0xd000, 0xf1c0, 0x0000, 0x0000, {EADI}, "ADDB %e,R%x" },
617 { 0xd0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "ADDW %e,A%x" },
618 { 0xd1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "ADDL %e,A%x" },
620 { 0xd100, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s R%y,R%x" },
621 { 0xd108, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s -(A%y),-(A%x)" },
623 { 0xd000, 0xf100, 0x0000, 0x0000, {EAALL}, "ADD%s %e,R%x" },
624 { 0xd100, 0xf100, 0x0000, 0x0000, {EAMA}, "ADD%s R%x,%e" },
627 /* class e: shift, rotate, bit field operations */
628 static Optable te[] = {
629 { 0xe8c0, 0xffc0, 0x0820, 0xfe38, {EACD}, "BFTST %e{R%u:R%a}" },
630 { 0xe8c0, 0xffc0, 0x0800, 0xfe20, {EACD}, "BFTST %e{R%u:%w}" },
631 { 0xe8c0, 0xffc0, 0x0020, 0xf838, {EACD}, "BFTST %e{%o:R%a}" },
632 { 0xe8c0, 0xffc0, 0x0000, 0xf820, {EACD}, "BFTST %e{%o:%w}" },
634 { 0xe9c0, 0xffc0, 0x0820, 0x8e38, {EACD}, "BFEXTU %e{R%u:R%a},%r" },
635 { 0xe9c0, 0xffc0, 0x0800, 0x8e20, {EACD}, "BFEXTU %e{R%u:%w},%r" },
636 { 0xe9c0, 0xffc0, 0x0020, 0x8838, {EACD}, "BFEXTU %e{%o:R%a},%r" },
637 { 0xe9c0, 0xffc0, 0x0000, 0x8820, {EACD}, "BFEXTU %e{%o:%w},%r" },
639 { 0xeac0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFCHG %e{R%u:R%a}" },
640 { 0xeac0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFCHG %e{R%u:%w}" },
641 { 0xeac0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFCHG %e{%o:R%a}" },
642 { 0xeac0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFCHG %e{%o:%w}" },
644 { 0xebc0, 0xffc0, 0x0820, 0x8e38, {EACD}, "BFEXTS %e{R%u:R%a},%r" },
645 { 0xebc0, 0xffc0, 0x0800, 0x8e20, {EACD}, "BFEXTS %e{R%u:%w},%r" },
646 { 0xebc0, 0xffc0, 0x0020, 0x8838, {EACD}, "BFEXTS %e{%o:R%a},%r" },
647 { 0xebc0, 0xffc0, 0x0000, 0x8820, {EACD}, "BFEXTS %e{%o:%w},%r" },
649 { 0xecc0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFCLR %e{R%u:R%a}" },
650 { 0xecc0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFCLR %e{R%u:%w}" },
651 { 0xecc0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFCLR %e{%o:R%a}" },
652 { 0xecc0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFCLR %e{%o:%w}" },
654 { 0xedc0, 0xffc0, 0x0820, 0x8e38, {EACAD}, "BFFFO %e{R%u:R%a},%r" },
655 { 0xedc0, 0xffc0, 0x0800, 0x8e20, {EACAD}, "BFFFO %e{R%u:%w},%r" },
656 { 0xedc0, 0xffc0, 0x0020, 0x8838, {EACAD}, "BFFFO %e{%o:R%a},%r" },
657 { 0xedc0, 0xffc0, 0x0000, 0x8820, {EACAD}, "BFFFO %e{%o:%w},%r" },
659 { 0xeec0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFSET %e{R%u:R%a}" },
660 { 0xeec0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFSET %e{R%u:%w}" },
661 { 0xeec0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFSET %e{%o:R%a}" },
662 { 0xeec0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFSET %e{%o:%w}" },
664 { 0xefc0, 0xffc0, 0x0820, 0x8e38, {EACAD}, "BFINS %r,%e{R%u:R%a}" },
665 { 0xefc0, 0xffc0, 0x0800, 0x8e20, {EACAD}, "BFINS %r,%e{R%u:%w}" },
666 { 0xefc0, 0xffc0, 0x0020, 0x8838, {EACAD}, "BFINS %r,%e{%o:R%a}" },
667 { 0xefc0, 0xffc0, 0x0000, 0x8820, {EACAD}, "BFINS %r,%e{%o:%w}" },
669 { 0xe0c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "AS%dW %e" },
670 { 0xe2c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "LS%dW %e" },
671 { 0xe4c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "ROX%dW %e" },
672 { 0xe6c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "RO%dW %e" },
674 { 0xe000, 0xf038, 0x0000, 0x0000, {0}, "AS%d%s #%q,R%y" },
675 { 0xe008, 0xf038, 0x0000, 0x0000, {0}, "LS%d%s #%q,R%y" },
676 { 0xe010, 0xf038, 0x0000, 0x0000, {0}, "ROX%d%s #%q,R%y" },
677 { 0xe018, 0xf038, 0x0000, 0x0000, {0}, "RO%d%s #%q,R%y" },
678 { 0xe020, 0xf038, 0x0000, 0x0000, {0}, "AS%d%s R%x,R%y" },
679 { 0xe028, 0xf038, 0x0000, 0x0000, {0}, "LS%d%s R%x,R%y" },
680 { 0xe030, 0xf038, 0x0000, 0x0000, {0}, "ROX%d%s R%x,R%y" },
681 { 0xe038, 0xf038, 0x0000, 0x0000, {0}, "RO%d%s R%x,R%y" },
684 /* class f: coprocessor and mmu instructions */
685 static Optable tf[] = {
686 { 0xf280, 0xffff, 0x0000, 0xffff, {0}, "FNOP" },
687 { 0xf200, 0xffff, 0x5c00, 0xfc00, {0}, "FMOVECRX %k,F%D" },
688 { 0xf27a, 0xffff, 0x0000, 0xffc0, {I16}, "FTRAP%P %i" },
689 { 0xf27b, 0xffff, 0x0000, 0xffc0, {I32}, "FTRAP%P %i" },
690 { 0xf27c, 0xffff, 0x0000, 0xffc0, {0}, "FTRAP%P" },
692 { 0xf248, 0xfff8, 0x0000, 0xffc0, {BR16}, "FDB%P R%y,%t" },
693 { 0xf620, 0xfff8, 0x8000, 0x8fff, {0}, "MOVE16 (A%y)+,(%r)+" },
694 { 0xf500, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHN (A%y)" },
695 { 0xf508, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSH (A%y)" },
696 { 0xf510, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHAN" },
697 { 0xf518, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHA" },
698 { 0xf548, 0xfff8, 0x0000, 0x0000, {0}, "PTESTW (A%y)" },
699 { 0xf568, 0xfff8, 0x0000, 0x0000, {0}, "PTESTR (A%y)" },
700 { 0xf600, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 (A%y)+,$%i" },
701 { 0xf608, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 $%i,(A%y)-" },
702 { 0xf610, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 (A%y),$%i" },
703 { 0xf618, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 $%i,(A%y)" },
705 { 0xf000, 0xffc0, 0x0800, 0xffff, {EACA}, "PMOVE %e,TT0" },
706 { 0xf000, 0xffc0, 0x0900, 0xffff, {EACA}, "PMOVEFD %e,TT0" },
707 { 0xf000, 0xffc0, 0x0a00, 0xffff, {EACA}, "PMOVE TT0,%e" },
708 { 0xf000, 0xffc0, 0x0b00, 0xffff, {EACA}, "PMOVEFD TT0,%e" },
709 { 0xf000, 0xffc0, 0x0c00, 0xffff, {EACA}, "PMOVE %e,TT1" },
710 { 0xf000, 0xffc0, 0x0d00, 0xffff, {EACA}, "PMOVEFD %e,TT1" },
711 { 0xf000, 0xffc0, 0x0e00, 0xffff, {EACA}, "PMOVE TT1,%e" },
712 { 0xf000, 0xffc0, 0x0f00, 0xffff, {EACA}, "PMOVEFD TT1,%e" },
713 { 0xf000, 0xffc0, 0x2400, 0xffff, {0}, "PFLUSHA" },
714 { 0xf000, 0xffc0, 0x2800, 0xffff, {EACA}, "PVALID VAL,%e" },
715 { 0xf000, 0xffc0, 0x6000, 0xffff, {EACA}, "PMOVE %e,MMUSR" },
716 { 0xf000, 0xffc0, 0x6200, 0xffff, {EACA}, "PMOVE MMUSR,%e" },
717 { 0xf000, 0xffc0, 0x2800, 0xfff8, {EACA}, "PVALID A%a,%e" },
718 { 0xf000, 0xffc0, 0x2000, 0xffe0, {EACA}, "PLOADW %L,%e" },
719 { 0xf000, 0xffc0, 0x2200, 0xffe0, {EACA}, "PLOADR %L,%e" },
720 { 0xf000, 0xffc0, 0x8000, 0xffe0, {EACA}, "PTESTW %L,%e,#0" },
721 { 0xf000, 0xffc0, 0x8200, 0xffe0, {EACA}, "PTESTR %L,%e,#0" },
722 { 0xf000, 0xffc0, 0x3000, 0xfe00, {0}, "PFLUSH %L,#%I" },
723 { 0xf000, 0xffc0, 0x3800, 0xfe00, {EACA}, "PFLUSH %L,#%I,%e" },
724 { 0xf000, 0xffc0, 0x8000, 0xe300, {EACA}, "PTESTW %L,%e,#%Z" },
725 { 0xf000, 0xffc0, 0x8100, 0xe300, {EACA}, "PTESTW %L,%e,#%Z,A%h" },
726 { 0xf000, 0xffc0, 0x8200, 0xe300, {EACA}, "PTESTR %L,%e,#%Z" },
727 { 0xf000, 0xffc0, 0x8300, 0xe300, {EACA}, "PTESTR %L,%e,#%Z,A%h" },
728 { 0xf000, 0xffc0, 0x4000, 0xc3ff, {EACA}, "PMOVE %e,%H" },
729 { 0xf000, 0xffc0, 0x4100, 0xc3ff, {EACA}, "PMOVEFD %e,%H" },
730 { 0xf000, 0xffc0, 0x4200, 0xc3ff, {EACA}, "PMOVE %H,%e" },
732 /* floating point (coprocessor 1)*/
734 { 0xf200, 0xffc0, 0x8400, 0xffff, {EAALL_L}, "FMOVEL %e,FPIAR" },
735 { 0xf200, 0xffc0, 0x8800, 0xffff, {EADI_L}, "FMOVEL %e,FPSR" },
736 { 0xf200, 0xffc0, 0x9000, 0xffff, {EADI_L}, "FMOVEL %e,FPCR" },
737 { 0xf200, 0xffc0, 0xa400, 0xffff, {EAA}, "FMOVEL FPIAR,%e" },
738 { 0xf200, 0xffc0, 0xa800, 0xffff, {EADA}, "FMOVEL FPSR,%e" },
739 { 0xf200, 0xffc0, 0xb000, 0xffff, {EADA}, "FMOVEL FPCR,%e" },
741 { 0xf240, 0xffc0, 0x0000, 0xffc0, {EADA}, "FS%P %e" },
743 { 0xf200, 0xffc0, 0xd000, 0xff00, {EACPI}, "FMOVEMX %e,%m" },
744 { 0xf200, 0xffc0, 0xd800, 0xff00, {EACPI}, "FMOVEMX %e,R%K" },
745 { 0xf200, 0xffc0, 0xe000, 0xff00, {EAPI}, "FMOVEMX %m,-(A%y)" },
746 { 0xf200, 0xffc0, 0xe800, 0xff00, {EAPI}, "FMOVEMX R%K,-(A%y)" },
747 { 0xf200, 0xffc0, 0xf000, 0xff00, {EACAPD}, "FMOVEMX %m,%e" },
748 { 0xf200, 0xffc0, 0xf800, 0xff00, {EACAPD}, "FMOVEMX R%K,%e" },
750 { 0xf200, 0xffc0, 0x6800, 0xfc00, {EAMA}, "FMOVEX F%D,%e" },
751 { 0xf200, 0xffc0, 0x6c00, 0xfc00, {EAMA}, "FMOVEP F%D,%e,{%k}" },
752 { 0xf200, 0xffc0, 0x7400, 0xfc00, {EAMA}, "FMOVED F%D,%e" },
753 { 0xf200, 0xffc0, 0x7c00, 0xfc00, {EAMA}, "FMOVEP F%D,%e,{R%K}" },
755 { 0xf200, 0xffc0, 0x8000, 0xe3ff, {EAM}, "FMOVEML #%B,%e" },
756 { 0xf200, 0xffc0, 0xa000, 0xe3ff, {EAMA}, "FMOVEML %e,#%B" },
758 { 0xf200, 0xffc0, 0x0000, 0xe07f, {0}, "FMOVE F%B,F%D" },
759 { 0xf200, 0xffc0, 0x0001, 0xe07f, {0}, "FINTX %F" },
760 { 0xf200, 0xffc0, 0x0002, 0xe07f, {0}, "FSINHX %F" },
761 { 0xf200, 0xffc0, 0x0003, 0xe07f, {0}, "FINTRZ %F" },
762 { 0xf200, 0xffc0, 0x0004, 0xe07f, {0}, "FSQRTX %F" },
763 { 0xf200, 0xffc0, 0x0006, 0xe07f, {0}, "FLOGNP1X %F" },
764 { 0xf200, 0xffc0, 0x0009, 0xe07f, {0}, "FTANHX %F" },
765 { 0xf200, 0xffc0, 0x000a, 0xe07f, {0}, "FATANX %F" },
766 { 0xf200, 0xffc0, 0x000c, 0xe07f, {0}, "FASINX %F" },
767 { 0xf200, 0xffc0, 0x000d, 0xe07f, {0}, "FATANHX %F" },
768 { 0xf200, 0xffc0, 0x000e, 0xe07f, {0}, "FSINX %F" },
769 { 0xf200, 0xffc0, 0x000f, 0xe07f, {0}, "FTANX %F" },
770 { 0xf200, 0xffc0, 0x0010, 0xe07f, {0}, "FETOXX %F" },
771 { 0xf200, 0xffc0, 0x0011, 0xe07f, {0}, "FTWOTOXX %F" },
772 { 0xf200, 0xffc0, 0x0012, 0xe07f, {0}, "FTENTOXX %F" },
773 { 0xf200, 0xffc0, 0x0014, 0xe07f, {0}, "FLOGNX %F" },
774 { 0xf200, 0xffc0, 0x0015, 0xe07f, {0}, "FLOG10X %F" },
775 { 0xf200, 0xffc0, 0x0016, 0xe07f, {0}, "FLOG2X %F" },
776 { 0xf200, 0xffc0, 0x0018, 0xe07f, {0}, "FABSX %F" },
777 { 0xf200, 0xffc0, 0x0019, 0xe07f, {0}, "FCOSHX %F" },
778 { 0xf200, 0xffc0, 0x001a, 0xe07f, {0}, "FNEGX %F" },
779 { 0xf200, 0xffc0, 0x001c, 0xe07f, {0}, "FACOSX %F" },
780 { 0xf200, 0xffc0, 0x001d, 0xe07f, {0}, "FCOSX %F" },
781 { 0xf200, 0xffc0, 0x001e, 0xe07f, {0}, "FGETEXPX %F" },
782 { 0xf200, 0xffc0, 0x001f, 0xe07f, {0}, "FGETMANX %F" },
783 { 0xf200, 0xffc0, 0x0020, 0xe07f, {0}, "FDIVX F%B,F%D" },
784 { 0xf200, 0xffc0, 0x0021, 0xe07f, {0}, "FMODX F%B,F%D" },
785 { 0xf200, 0xffc0, 0x0022, 0xe07f, {0}, "FADDX F%B,F%D" },
786 { 0xf200, 0xffc0, 0x0023, 0xe07f, {0}, "FMULX F%B,F%D" },
787 { 0xf200, 0xffc0, 0x0024, 0xe07f, {0}, "FSGLDIVX F%B,F%D" },
788 { 0xf200, 0xffc0, 0x0025, 0xe07f, {0}, "FREMX F%B,F%D" },
789 { 0xf200, 0xffc0, 0x0026, 0xe07f, {0}, "FSCALEX F%B,F%D" },
790 { 0xf200, 0xffc0, 0x0027, 0xe07f, {0}, "FSGLMULX F%B,F%D" },
791 { 0xf200, 0xffc0, 0x0028, 0xe07f, {0}, "FSUBX F%B,F%D" },
792 { 0xf200, 0xffc0, 0x0038, 0xe07f, {0}, "FCMPX F%B,F%D" },
793 { 0xf200, 0xffc0, 0x003a, 0xe07f, {0}, "FTSTX F%B" },
794 { 0xf200, 0xffc0, 0x0040, 0xe07f, {0}, "FSMOVE F%B,F%D" },
795 { 0xf200, 0xffc0, 0x0041, 0xe07f, {0}, "FSSQRTX %F"},
796 { 0xf200, 0xffc0, 0x0044, 0xe07f, {0}, "FDMOVE F%B,F%D" },
797 { 0xf200, 0xffc0, 0x0045, 0xe07f, {0}, "FDSQRTX %F" },
798 { 0xf200, 0xffc0, 0x0058, 0xe07f, {0}, "FSABSX %F" },
799 { 0xf200, 0xffc0, 0x005a, 0xe07f, {0}, "FSNEGX %F" },
800 { 0xf200, 0xffc0, 0x005c, 0xe07f, {0}, "FDABSX %F" },
801 { 0xf200, 0xffc0, 0x005e, 0xe07f, {0}, "FDNEGX %F" },
802 { 0xf200, 0xffc0, 0x0060, 0xe07f, {0}, "FSDIVX F%B,F%D" },
803 { 0xf200, 0xffc0, 0x0062, 0xe07f, {0}, "FSADDX F%B,F%D" },
804 { 0xf200, 0xffc0, 0x0063, 0xe07f, {0}, "FSMULX F%B,F%D" },
805 { 0xf200, 0xffc0, 0x0064, 0xe07f, {0}, "FDDIVX F%B,F%D" },
806 { 0xf200, 0xffc0, 0x0066, 0xe07f, {0}, "FDADDX F%B,F%D" },
807 { 0xf200, 0xffc0, 0x0067, 0xe07f, {0}, "FDMULX F%B,F%D" },
808 { 0xf200, 0xffc0, 0x0068, 0xe07f, {0}, "FSSUBX F%B,F%D" },
809 { 0xf200, 0xffc0, 0x006c, 0xe07f, {0}, "FDSUBX F%B,F%D" },
810 { 0xf200, 0xffc0, 0x4000, 0xe07f, {EAFLT}, "FMOVE%S %e,F%D" },
811 { 0xf200, 0xffc0, 0x4001, 0xe07f, {EAFLT}, "FINT%S %e,F%D" },
812 { 0xf200, 0xffc0, 0x4002, 0xe07f, {EAFLT}, "FSINH%S %e,F%D" },
813 { 0xf200, 0xffc0, 0x4003, 0xe07f, {EAFLT}, "FINTRZ%S %e,F%D" },
814 { 0xf200, 0xffc0, 0x4004, 0xe07f, {EAFLT}, "FSQRT%S %e,F%D" },
815 { 0xf200, 0xffc0, 0x4006, 0xe07f, {EAFLT}, "FLOGNP1%S %e,F%D" },
816 { 0xf200, 0xffc0, 0x4009, 0xe07f, {EAFLT}, "FTANH%S %e,F%D" },
817 { 0xf200, 0xffc0, 0x400a, 0xe07f, {EAFLT}, "FATAN%S %e,F%D" },
818 { 0xf200, 0xffc0, 0x400c, 0xe07f, {EAFLT}, "FASIN%S %e,F%D" },
819 { 0xf200, 0xffc0, 0x400d, 0xe07f, {EAFLT}, "FATANH%S %e,F%D" },
820 { 0xf200, 0xffc0, 0x400e, 0xe07f, {EAFLT}, "FSIN%S %e,F%D" },
821 { 0xf200, 0xffc0, 0x400f, 0xe07f, {EAFLT}, "FTAN%S %e,F%D" },
822 { 0xf200, 0xffc0, 0x4010, 0xe07f, {EAFLT}, "FETOX%S %e,F%D" },
823 { 0xf200, 0xffc0, 0x4011, 0xe07f, {EAFLT}, "FTWOTOX%S %e,F%D" },
824 { 0xf200, 0xffc0, 0x4012, 0xe07f, {EAFLT}, "FTENTOX%S %e,F%D" },
825 { 0xf200, 0xffc0, 0x4014, 0xe07f, {EAFLT}, "FLOGN%S %e,F%D" },
826 { 0xf200, 0xffc0, 0x4015, 0xe07f, {EAFLT}, "FLOG10%S %e,F%D" },
827 { 0xf200, 0xffc0, 0x4016, 0xe07f, {EAFLT}, "FLOG2%S %e,F%D" },
828 { 0xf200, 0xffc0, 0x4018, 0xe07f, {EAFLT}, "FABS%S %e,F%D" },
829 { 0xf200, 0xffc0, 0x4019, 0xe07f, {EAFLT}, "FCOSH%S %e,F%D" },
830 { 0xf200, 0xffc0, 0x401a, 0xe07f, {EAFLT}, "FNEG%S %e,F%D" },
831 { 0xf200, 0xffc0, 0x401c, 0xe07f, {EAFLT}, "FACOS%S %e,F%D" },
832 { 0xf200, 0xffc0, 0x401d, 0xe07f, {EAFLT}, "FCOS%S %e,F%D" },
833 { 0xf200, 0xffc0, 0x401e, 0xe07f, {EAFLT}, "FGETEXP%S %e,F%D" },
834 { 0xf200, 0xffc0, 0x401f, 0xe07f, {EAFLT}, "FGETMAN%S %e,F%D" },
835 { 0xf200, 0xffc0, 0x4020, 0xe07f, {EAFLT}, "FDIV%S %e,F%D" },
836 { 0xf200, 0xffc0, 0x4021, 0xe07f, {EAFLT}, "FMOD%S %e,F%D" },
837 { 0xf200, 0xffc0, 0x4022, 0xe07f, {EAFLT}, "FADD%S %e,F%D" },
838 { 0xf200, 0xffc0, 0x4023, 0xe07f, {EAFLT}, "FMUL%S %e,F%D" },
839 { 0xf200, 0xffc0, 0x4024, 0xe07f, {EAFLT}, "FSGLDIV%S %e,F%D" },
840 { 0xf200, 0xffc0, 0x4025, 0xe07f, {EAFLT}, "FREM%S %e,F%D" },
841 { 0xf200, 0xffc0, 0x4026, 0xe07f, {EAFLT}, "FSCALE%S %e,F%D" },
842 { 0xf200, 0xffc0, 0x4027, 0xe07f, {EAFLT}, "FSGLMUL%S %e,F%D" },
843 { 0xf200, 0xffc0, 0x4028, 0xe07f, {EAFLT}, "FSUB%S %e,F%D" },
844 { 0xf200, 0xffc0, 0x4038, 0xe07f, {EAFLT}, "FCMP%S %e,F%D" },
845 { 0xf200, 0xffc0, 0x403a, 0xe07f, {EAFLT}, "FTST%S %e" },
846 { 0xf200, 0xffc0, 0x4040, 0xe07f, {EAFLT}, "FSMOVE%S %e,F%D" },
847 { 0xf200, 0xffc0, 0x4041, 0xe07f, {EAFLT}, "FSSQRT%S %e,F%D" },
848 { 0xf200, 0xffc0, 0x4044, 0xe07f, {EAFLT}, "FDMOVE%S %e,F%D" },
849 { 0xf200, 0xffc0, 0x4045, 0xe07f, {EAFLT}, "FDSQRT%S %e,F%D" },
850 { 0xf200, 0xffc0, 0x4058, 0xe07f, {EAFLT}, "FSABS%S %e,F%D" },
851 { 0xf200, 0xffc0, 0x405a, 0xe07f, {EAFLT}, "FSNEG%S %e,F%D" },
852 { 0xf200, 0xffc0, 0x405c, 0xe07f, {EAFLT}, "FDABS%S %e,F%D" },
853 { 0xf200, 0xffc0, 0x405e, 0xe07f, {EAFLT}, "FDNEG%S %e,F%D" },
854 { 0xf200, 0xffc0, 0x4060, 0xe07f, {EAFLT}, "FSDIV%S %e,F%D" },
855 { 0xf200, 0xffc0, 0x4062, 0xe07f, {EAFLT}, "FSADD%S %e,F%D" },
856 { 0xf200, 0xffc0, 0x4063, 0xe07f, {EAFLT}, "FSMUL%S %e,F%D" },
857 { 0xf200, 0xffc0, 0x4064, 0xe07f, {EAFLT}, "FDDIV%S %e,F%D" },
858 { 0xf200, 0xffc0, 0x4066, 0xe07f, {EAFLT}, "FDADD%S %e,F%D" },
859 { 0xf200, 0xffc0, 0x4067, 0xe07f, {EAFLT}, "FDMUL%S %e,F%D" },
860 { 0xf200, 0xffc0, 0x4068, 0xe07f, {EAFLT}, "FSSUB%S %e,F%D" },
861 { 0xf200, 0xffc0, 0x406c, 0xe07f, {EAFLT}, "FDSUB%S %e,F%D" },
863 { 0xf200, 0xffc0, 0x0030, 0xe078, {0}, "FSINCOSX F%B,F%a:F%D" },
864 { 0xf200, 0xffc0, 0x4030, 0xe078, {EAFLT}, "FSINCOS%S %e,F%a:F%D" },
866 { 0xf200, 0xffc0, 0x6000, 0xe000, {EADA}, "FMOVE%S F%D,%e" },
868 { 0xf300, 0xffc0, 0x0000, 0x0000, {EACAPD}, "FSAVE %e" },
869 { 0xf340, 0xffc0, 0x0000, 0x0000, {EACAPI}, "FRESTORE %e" },
871 { 0xf280, 0xffc0, 0x0000, 0x0000, {BR16}, "FB%p %t" },
872 { 0xf2c0, 0xffc0, 0x0000, 0x0000, {BR32}, "FB%p %t" },
874 { 0xf408, 0xff38, 0x0000, 0x0000, {0}, "CINVL %C,(A%y)" },
875 { 0xf410, 0xff38, 0x0000, 0x0000, {0}, "CINVP %C,(A%y)" },
876 { 0xf418, 0xff38, 0x0000, 0x0000, {0}, "CINVA %C" },
877 { 0xf428, 0xff38, 0x0000, 0x0000, {0}, "CPUSHL %C,(A%y)" },
878 { 0xf430, 0xff38, 0x0000, 0x0000, {0}, "CPUSHP %C,(A%y)" },
879 { 0xf438, 0xff38, 0x0000, 0x0000, {0}, "CPUSHA %C" },
883 static Optable *optables[] =
885 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, 0, tb, tc, td, te, tf,
891 dumpinst(Inst *ip, char *buf, int n)
899 for (i = 0; i < ip->n && i*4+1 < n-4; i++, buf += 4)
900 _hexify(buf, ip->raw[i], 3);
906 getword(Inst *ip, uvlong offset)
908 if (ip->n < nelem(ip->raw)) {
909 if (get2(mymap, offset, &ip->raw[ip->n++]) > 0)
911 werrstr("can't read instruction: %r");
913 werrstr("instruction too big: %r");
918 getshorts(Inst *ip, void *where, int n)
920 if (ip->n+n < nelem(ip->raw)) {
921 if (get1(mymap, ip->addr+ip->n*2, (uchar*)&ip->raw[ip->n], n*2) < 0) {
922 werrstr("can't read instruction: %r");
925 memmove(where, &ip->raw[ip->n], n*2);
929 werrstr("instruction too big: %r");
934 i8(Inst *ip, long *l)
936 if (getword(ip, ip->addr+ip->n*2) < 0)
938 *l = ip->raw[ip->n-1]&0xff;
945 i16(Inst *ip, long *l)
947 if (getword(ip, ip->addr+ip->n*2) < 0)
949 *l = ip->raw[ip->n-1];
955 i32(Inst *ip, long *l)
957 if (getword(ip, ip->addr+ip->n*2) < 0)
959 if (getword(ip, ip->addr+ip->n*2) < 0)
961 *l = (ip->raw[ip->n-2]<<16)|ip->raw[ip->n-1];
966 getimm(Inst *ip, Operand *ap, int mode)
971 case EAM_B: /* byte */
973 return i8(ip, &ap->immediate);
974 case EADI_W: /* word */
976 return i16(ip, &ap->immediate);
977 case EADI_L: /* long */
979 return i32(ip, &ap->immediate);
980 case EAFLT: /* floating point - size in bits 10-12 or word 1 */
981 switch((ip->raw[1]>>10)&0x07)
983 case 0: /* long integer */
984 return i32(ip, &ap->immediate);
985 case 1: /* single precision real */
987 return getshorts(ip, ap->floater, 2);
988 case 2: /* extended precision real - not supported */
990 return getshorts(ip, ap->floater, 6);
991 case 3: /* packed decimal real - not supported */
993 return getshorts(ip, ap->floater, 12);
994 case 4: /* integer word */
995 return i16(ip, &ap->immediate);
996 case 5: /* double precision real */
998 return getshorts(ip, ap->floater, 4);
999 case 6: /* integer byte */
1000 return i8(ip, &ap->immediate);
1002 ip->errmsg = "bad immediate float data";
1006 case IV: /* size encoded in bits 6&7 of opcode word */
1008 switch((ip->raw[0]>>6)&0x03)
1010 case 0x00: /* integer byte */
1011 return i8(ip, &ap->immediate);
1012 case 0x01: /* integer word */
1013 return i16(ip, &ap->immediate);
1014 case 0x02: /* integer long */
1015 return i32(ip, &ap->immediate);
1017 ip->errmsg = "bad immediate size";
1025 getdisp(Inst *ip, Operand *ap)
1029 if (getword(ip, ip->addr+ip->n*2) < 0)
1031 ext = ip->raw[ip->n-1];
1033 if ((ext&0x100) == 0) { /* indexed with 7-bit displacement */
1034 ap->disp = ext&0x7f;
1039 switch(ext&0x30) /* first (inner) displacement */
1044 if (i16(ip, &ap->disp) < 0)
1048 if (i32(ip, &ap->disp) < 0)
1052 ip->errmsg = "bad EA displacement";
1055 switch (ext&0x03) /* outer displacement */
1057 case 0x02: /* 16 bit displacement */
1058 return i16(ip, &ap->outer);
1059 case 0x03: /* 32 bit displacement */
1060 return i32(ip, &ap->outer);
1068 ea(Inst *ip, int ea, Operand *ap, int mode)
1074 switch((ea>>3)&0x07)
1099 if (i16(ip, &ap->disp) < 0)
1105 if (getdisp(ip, ap) < 0)
1114 if (i16(ip, &ap->immediate) < 0)
1120 if (i32(ip, &ap->immediate) < 0)
1126 if (i16(ip, &ap->disp) < 0)
1132 if (getdisp(ip, ap) < 0)
1137 if (getimm(ip, ap, mode) < 0)
1141 ip->errmsg = "bad EA mode";
1145 /* Allowable floating point EAs are restricted for packed,
1146 * extended, and double precision operands
1148 if (mode == EAFLT) {
1149 size = (ip->raw[1]>>10)&0x07;
1150 if (size == 2 || size == 3 || size == 5)
1155 if (!(validea[mode]&type)) {
1156 ip->errmsg = "invalid EA";
1163 decode(Inst *ip, Optable *op)
1169 opcode = ip->raw[0];
1170 for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1172 mode = op->opdata[i];
1175 case EAPI: /* normal EA modes */
1197 if (ea(ip, opcode&0x3f, ap, mode) < 0)
1200 case EADDA: /* stupid bit flop required */
1201 t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1202 if (ea(ip, t, ap, EADA)< 0)
1205 case BREAC: /* EAC JMP or CALL operand */
1206 if (ea(ip, opcode&0x3f, ap, EAC) < 0)
1209 case OP8: /* weird movq instruction */
1211 ap->immediate = opcode&0xff;
1213 ap->immediate |= ~0xff;
1215 case I8: /* must be two-word opcode */
1217 ap->immediate = ip->raw[1]&0xff;
1218 if (ap->immediate&0x80)
1219 ap->immediate |= ~0xff;
1221 case I16: /* 16 bit immediate */
1224 if (i16(ip, &ap->immediate) < 0)
1227 case C16: /* CAS2 16 bit immediate */
1229 if (i16(ip, &ap->immediate) < 0)
1231 if (ap->immediate & 0x0e38) {
1232 ip->errmsg = "bad CAS2W operand";
1236 case I32: /* 32 bit immediate */
1239 if (i32(ip, &ap->immediate) < 0)
1242 case IV: /* immediate data depends on size field */
1243 if (getimm(ip, ap, IV) < 0)
1246 case BR8: /* branch displacement format */
1248 ap->immediate = opcode&0xff;
1249 if (ap->immediate == 0) {
1250 if (i16(ip, &ap->immediate) < 0)
1252 } else if (ap->immediate == 0xff) {
1253 if (i32(ip, &ap->immediate) < 0)
1255 } else if (ap->immediate & 0x80)
1256 ap->immediate |= ~0xff;
1258 case STACK: /* Dummy operand type for Return instructions */
1267 instruction(Inst *ip)
1274 if (getword(ip, ip->addr) < 0)
1276 opcode = ip->raw[0];
1277 if (get2(mymap, ip->addr+2, &op2) < 0)
1279 class = (opcode>>12)&0x0f;
1280 for (op = optables[class]; op && op->format; op++) {
1281 if (op->opcode != (opcode&op->mask0))
1283 if (op->op2 != (op2&op->mask1))
1286 ip->raw[ip->n++] = op2;
1289 ip->errmsg = "Invalid opcode";
1293 #pragma varargck argpos bprint 2
1296 bprint(Inst *i, char *fmt, ...)
1301 i->curr = vseprint(i->curr, i->end, fmt, arg);
1305 static char *regname[] =
1307 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0",
1308 "A1", "A2", "A3", "A4", "A5", "A6", "A7", "PC", "SB"
1312 plocal(Inst *ip, Operand *ap)
1320 if (!findsym(ip->addr, CTEXT, &s))
1323 moved = pc2sp(ip->addr);
1327 if (offset > moved) { /* above frame - must be argument */
1329 ret = getauto(&s, offset-mach->szaddr, CPARAM, &s);
1330 } else /* below frame - must be automatic */
1331 ret = getauto(&s, moved-offset, CPARAM, &s);
1333 bprint(ip, "%s+%lux", s.name, offset);
1335 none: bprint(ip, "%lux", ap->disp);
1339 * this guy does all the work of printing the base and index component
1343 pidx(Inst *ip, int ext, int reg, char *bfmt, char *ifmt, char *nobase)
1350 if (ext&0x80) { /* Base suppressed */
1352 bprint(ip, bfmt, "(ZPC)");
1357 } else /* format base reg */
1358 bprint(ip, bfmt, regname[reg]);
1359 if (ext & 0x40) /* index suppressed */
1361 switch ((ext>>9)&0x03)
1379 sprint(buf, "%s.%c%s", regname[(ext>>12)&0x0f], (ext&0x800) ? 'L' : 'W', s);
1381 bprint(ip, ifmt, buf);
1383 bprint(ip, "(%s)", buf);
1388 prindex(Inst *ip, int reg, Operand *ap)
1394 left = ip->end-ip->curr;
1399 /* look for static base register references */
1400 if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) {
1401 reg = 17; /* "A6" -> "SB" */
1404 if ((ext&0x100) == 0) { /* brief form */
1408 ip->curr += symoff(ip->curr, left, disp, CANY);
1409 pidx(ip, ext&0xff00, reg, "(%s)", "(%s)", 0);
1412 switch(ext&0x3f) /* bd size, && i/is */
1415 if (!pidx(ip, ext, reg, "(%s)", "(%s)", 0))
1419 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1426 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1427 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1431 if (!pidx(ip, ext, reg, "((%s))", "(%s)", 0))
1436 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1437 pidx(ip, ext, reg, "((%s))", "(%s)", 0);
1444 ip->curr += symoff(ip->curr, left, disp, CANY);
1445 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1453 ip->curr += symoff(ip->curr, left-1, disp, CANY);
1454 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1461 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1466 ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1467 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1476 ip->curr += symoff(ip->curr, left-1, disp, CANY);
1477 if (!pidx(ip, ext, reg, "(%s))", "(%s)", "())"))
1484 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1489 ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1490 pidx(ip, ext, reg, "(%s))", "(%s)", "())");
1493 bprint(ip, "??%x??", ext);
1494 ip->errmsg = "bad EA";
1500 pea(int reg, Inst *ip, Operand *ap)
1504 left = ip->end-ip->curr;
1510 bprint(ip, "R%d", reg);
1513 bprint(ip, "A%d", reg);
1516 bprint(ip, "(A%d)", reg);
1519 bprint(ip, "(A%d)+", reg);
1522 bprint(ip, "-(A%d)", reg);
1525 ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY);
1528 prindex(ip, 16, ap);
1530 case ADisp: /* references off the static base */
1531 if (reg == 6 && mach->sb && ap->disp) {
1532 ip->curr += symoff(ip->curr, left, ap->disp+mach->sb, CANY);
1536 /* reference autos and parameters off the stack */
1540 ip->curr += symoff(ip->curr, left, ap->disp, CANY);
1541 bprint(ip, "(A%d)", reg);
1544 prindex(ip, reg+8, ap);
1547 ip->curr += symoff(ip->curr, left, ap->immediate, CANY);
1552 ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY);
1556 ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater);
1560 ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater);
1564 for (i = 0; i < 24 && ip->curr < ip->end-1; i++) {
1565 _hexify(ip->curr, ap->floater[i], 1);
1571 ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater);
1574 bprint(ip, "??%x??", ap->eatype);
1575 ip->errmsg = "bad EA type";
1580 static char *cctab[] = { "F", "T", "HI", "LS", "CC", "CS", "NE", "EQ",
1581 "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" };
1582 static char *fcond[] =
1584 "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR",
1585 "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T",
1586 "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE",
1587 "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST"
1589 static char *cachetab[] = { "NC", "DC", "IC", "BC" };
1590 static char *mmutab[] = { "TC", "??", "SRP", "CRP" };
1591 static char *crtab0[] =
1593 "SFC", "DFC", "CACR", "TC", "ITT0", "ITT1", "DTT0", "DTT1",
1595 static char *crtab1[] =
1597 "USP", "VBR", "CAAR", "MSP", "ISP", "MMUSR", "URP", "SRP",
1599 static char typetab[] = { 'L', 'S', 'X', 'P', 'W', 'D', 'B', '?', };
1600 static char sztab[] = {'?', 'B', 'W', 'L', '?' };
1603 formatins(char *fmt, Inst *ip)
1612 for (; *fmt && ip->curr < ip->end; fmt++) {
1620 case 'a': /* register number; word 1:[0-2] */
1621 *ip->curr++ = (w1&0x07)+'0';
1623 case 'c': /* condition code; opcode: [8-11] */
1624 bprint(ip, cctab[(op>>8)&0x0f]);
1626 case 'd': /* shift direction; opcode: [8] */
1632 case 'e': /* source effective address */
1633 pea(op&0x07, ip, &ip->and[currand++]);
1635 case 'f': /* trap vector; op code: [0-3] */
1636 bprint(ip, "%x", op&0x0f);
1638 case 'h': /* register number; word 1: [5-7] */
1639 *ip->curr++ = (w1>>5)&0x07+'0';
1641 case 'i': /* immediate operand */
1642 ip->curr += symoff(ip->curr, ip->end-ip->curr,
1643 ip->and[currand++].immediate, CANY);
1645 case 'j': /* data registers; word 1: [0-2] & [12-14] */
1649 bprint(ip, "R%d", r1);
1651 bprint(ip, "R%d:R%d", r2, r1);
1653 case 'k': /* k factor; word 1 [0-6] */
1654 bprint(ip, "%x", w1&0x7f);
1656 case 'm': /* register mask; word 1 [0-7] */
1657 bprint(ip, "%x", w1&0xff);
1659 case 'o': /* bit field offset; word1: [6-10] */
1660 bprint(ip, "%d", (w1>>6)&0x3f);
1662 case 'p': /* conditional predicate; opcode: [0-5]
1663 only bits 0-4 are defined */
1664 bprint(ip, fcond[op&0x1f]);
1666 case 'q': /* 3-bit immediate value; opcode[9-11] */
1671 *ip->curr++ = r1+'0';
1673 case 'r': /* register type & number; word 1: [12-15] */
1674 bprint(ip, regname[(w1>>12)&0x0f]);
1676 case 's': /* size; opcode [6-7] */
1677 *ip->curr = sztab[((op>>6)&0x03)+1];
1678 if (*ip->curr++ == '?')
1679 ip->errmsg = "bad size code";
1681 case 't': /* text offset */
1682 ip->curr += symoff(ip->curr, ip->end-ip->curr,
1683 ip->and[currand++].immediate+ip->addr+2, CTEXT);
1685 case 'u': /* register number; word 1: [6-8] */
1686 *ip->curr++ = ((w1>>6)&0x07)+'0';
1688 case 'w': /* bit field width; word 1: [0-4] */
1689 bprint(ip, "%d", w1&0x0f);
1691 case 'x': /* register number; opcode: [9-11] */
1692 *ip->curr++ = ((op>>9)&0x07)+'0';
1694 case 'y': /* register number; opcode: [0-2] */
1695 *ip->curr++ = (op&0x07)+'0';
1697 case 'z': /* shift count; opcode: [9-11] */
1698 *ip->curr++ = ((op>>9)&0x07)+'0';
1700 case 'A': /* register number; word 2: [0-2] */
1701 *ip->curr++ = (ip->raw[2]&0x07)+'0';
1703 case 'B': /* float source reg; word 1: [10-12] */
1704 *ip->curr++ = ((w1>>10)&0x07)+'0';
1706 case 'C': /* cache identifier; opcode: [6-7] */
1707 bprint(ip, cachetab[(op>>6)&0x03]);
1709 case 'D': /* float dest reg; word 1: [7-9] */
1710 *ip->curr++ = ((w1>>7)&0x07)+'0';
1712 case 'E': /* destination EA; opcode: [6-11] */
1713 pea((op>>9)&0x07, ip, &ip->and[currand++]);
1715 case 'F': /* float dest register(s); word 1: [7-9] & [10-12] */
1719 bprint(ip, "F%d", r1);
1721 bprint(ip, "F%d,F%d", r2, r1);
1723 case 'H': /* MMU register; word 1 [10-13] */
1724 bprint(ip, mmutab[(w1>>10)&0x03]);
1725 if (ip->curr[-1] == '?')
1726 ip->errmsg = "bad mmu register";
1728 case 'I': /* MMU function code mask; word 1: [5-8] */
1729 bprint(ip, "%x", (w1>>4)&0x0f);
1731 case 'K': /* dynamic k-factor register; word 1: [5-8] */
1732 bprint(ip, "%d", (w1>>4)&0x0f);
1734 case 'L': /* MMU function code; word 1: [0-6] */
1736 bprint(ip, "%x", w1&0x0f);
1738 bprint(ip, "R%d",w1&0x07);
1744 case 'N': /* control register; word 1: [0-11] */
1747 bprint(ip, crtab1[r1&0x07]);
1749 bprint(ip, crtab0[r1&0x07]);
1751 case 'P': /* conditional predicate; word 1: [0-5] */
1752 bprint(ip, fcond[w1&0x1f]);
1754 case 'R': /* register type & number; word 2 [12-15] */
1755 bprint(ip, regname[(ip->raw[2]>>12)&0x0f]);
1757 case 'S': /* float source type code; word 1: [10-12] */
1758 *ip->curr = typetab[(w1>>10)&0x07];
1759 if (*ip->curr++ == '?')
1760 ip->errmsg = "bad float type";
1762 case 'U': /* register number; word 2: [6-8] */
1763 *ip->curr++ = ((ip->raw[2]>>6)&0x07)+'0';
1765 case 'Z': /* ATC level number; word 1: [10-12] */
1766 bprint(ip, "%x", (w1>>10)&0x07);
1768 case '1': /* effective address in second operand*/
1769 pea(op&0x07, ip, &ip->and[1]);
1772 bprint(ip, "%%%c", *fmt);
1776 *ip->curr = 0; /* there's always room for 1 byte */
1783 static int dsize[] = {0, 0, 1, 2}; /* in words */
1785 if (get2(mymap, ip->addr+ip->n*2, &ext) < 0)
1787 if ((ext&0x100) == 0)
1789 return dsize[(ext>>4)&0x03]+dsize[ext&0x03]+1;
1793 immsize(Inst *ip, int mode)
1795 static int fsize[] = { 2, 2, 6, 12, 1, 4, 1, -1 };
1796 static int isize[] = { 1, 1, 2, -1 };
1800 case EAM_B: /* byte */
1802 case EADI_W: /* word */
1805 case EADI_L: /* long */
1808 case EAFLT: /* floating point - size in bits 10-12 or word 1 */
1809 return fsize[(ip->raw[1]>>10)&0x07];
1810 case IV: /* size encoded in bits 6&7 of opcode word */
1812 return isize[(ip->raw[0]>>6)&0x03];
1817 easize(Inst *ip, int ea, int mode)
1819 switch((ea>>3)&0x07)
1830 return dispsize(ip);
1840 return dispsize(ip);
1842 return immsize(ip, mode);
1851 instrsize(Inst *ip, Optable *op)
1856 opcode = ip->raw[0];
1857 for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1858 mode = op->opdata[i];
1861 case EAPI: /* normal EA modes */
1883 t = easize(ip, opcode&0x3f, mode);
1888 case EADDA: /* stupid bit flop required */
1889 t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1890 t = easize(ip, t, mode);
1895 case BREAC: /* EAC JMP or CALL operand */
1896 /* easy displacements for follow set */
1897 if ((opcode&0x038) == 0x28 || (opcode&0x3f) == 0x3a) {
1898 if (i16(ip, &ip->and[i].immediate) < 0)
1901 t = easize(ip, opcode&0x3f, mode);
1907 case I16: /* 16 bit immediate */
1908 case C16: /* CAS2 16 bit immediate */
1911 case BR16: /* 16 bit branch displacement */
1912 if (i16(ip, &ip->and[i].immediate) < 0)
1915 case BR32: /* 32 bit branch displacement */
1916 if (i32(ip, &ip->and[i].immediate) < 0)
1919 case I32: /* 32 bit immediate */
1922 case IV: /* immediate data depends on size field */
1923 t = (ip->raw[0]>>6)&0x03;
1931 case BR8: /* loony branch displacement format */
1934 if (i16(ip, &ip->and[i].immediate) < 0)
1936 } else if (t == 0xff) {
1937 if (i32(ip, &ip->and[i].immediate) < 0)
1940 ip->and[i].immediate = t;
1942 ip->and[i].immediate |= ~0xff;
1945 case STACK: /* Dummy operand for Return instructions */
1946 case OP8: /* weird movq instruction */
1947 case I8: /* must be two-word opcode */
1956 eaval(Inst *ip, Operand *ap, Rgetter rget)
1961 reg = ip->raw[0]&0x07;
1965 sprint(buf, "A%d", reg);
1966 return (*rget)(mymap, buf);
1968 return ip->addr+2+ap->disp;
1970 sprint(buf, "A%d", reg);
1971 return ap->disp+(*rget)(mymap, buf);
1973 return ap->immediate;
1980 m68020instlen(Map *map, uvlong pc)
1988 op = instruction(&i);
1989 if (op && instrsize(&i, op) > 0)
1995 m68020foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2005 op = instruction(&i);
2006 if (op == 0 || instrsize(&i, op) < 0)
2008 for (j = 0; j < nelem(op->opdata) && op->opdata[j]; j++) {
2009 switch(op->opdata[j])
2011 case BREAC: /* CALL, JMP, JSR */
2012 foll[0] = pc+2+eaval(&i, &i.and[j], rget);
2014 case BR8: /* Bcc, BSR, & BRA */
2015 case BR16: /* FBcc, FDBcc, DBcc */
2016 case BR32: /* FBcc */
2018 foll[1] = pc+2+i.and[j].immediate;
2020 case STACK: /* RTR, RTS, RTD */
2021 if (get4(map, (*rget)(map, mach->sp), &l) < 0)
2034 m68020inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2045 op = instruction(&i);
2048 if (decode(&i, op) > 0)
2049 formatins(op->format, &i);
2052 bprint(&i, "\t\t;");
2053 bprint(&i, "%s: ", i.errmsg);
2054 dumpinst(&i, i.curr, i.end-i.curr);
2060 m68020das(Map *map, uvlong pc, char *buf, int n)
2071 op = instruction(&i);
2076 bprint(&i, "%s: ", i.errmsg);
2077 dumpinst(&i, i.curr, i.end-i.curr);