1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5
6 /*
7 * 68020-specific debugger interface
8 */
9
10 static char *m68020excep(Map*, Rgetter);
11
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);
16
17 Machdata m68020mach =
18 {
19 {0x48,0x48,0,0}, /* break point #0 instr. */
20 2, /* size of break point instr. */
21
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 */
29 beieeesftos,
30 beieeedftos,
31 m68020foll, /* follow-set calculation */
32 m68020inst, /* print instruction */
33 m68020das, /* dissembler */
34 m68020instlen, /* instruction size */
35 };
36
37 /*
38 * 68020 exception frames
39 */
40
41 #define BPTTRAP 4 /* breakpoint gives illegal inst */
42
43 static char * excep[] = {
44 [2] "bus error",
45 [3] "address error",
46 [4] "illegal instruction",
47 [5] "zero divide",
48 [6] "CHK",
49 [7] "TRAP",
50 [8] "privilege violation",
51 [9] "Trace",
52 [10] "line 1010",
53 [11] "line 1011",
54 [13] "coprocessor protocol violation",
55 [24] "spurious",
56 [25] "incon",
57 [26] "tac",
58 [27] "auto 3",
59 [28] "clock",
60 [29] "auto 5",
61 [30] "parity",
62 [31] "mouse",
63 [32] "system call",
64 [33] "system call 1",
65 [48] "FPCP branch",
66 [49] "FPCP inexact",
67 [50] "FPCP zero div",
68 [51] "FPCP underflow",
69 [52] "FPCP operand err",
70 [53] "FPCP overflow",
71 [54] "FPCP signal NAN",
72 };
73
74 static int m68020vec;
75 static
76 struct ftype{
77 short fmt;
78 short len;
79 char *name;
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" },
90 { 0, 0, 0 }
91 };
92
93 static int
m68020ufix(Map * map)94 m68020ufix(Map *map)
95 {
96 struct ftype *ft;
97 int i, size, vec;
98 ulong efl[2];
99 uchar *ef=(uchar*)efl;
100 ulong l;
101 uvlong stktop;
102 short fvo;
103
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.
108 */
109 m68020vec = 0;
110
111 if (get4(map, mach->kbase, (&l)) < 0)
112 return -1;
113 if ((l&0xfc000000) == 0x04000000) /* if NeXT */
114 size = 30*2;
115 else
116 size = 46*2; /* 68020 */
117 USED(size);
118
119 stktop = mach->kbase+mach->pgsize;
120 for(i=3; i<100; i++){
121 if (get1(map, stktop-i*4, (uchar*)&l, 4)< 0)
122 return -1;
123
124 if(machdata->swal(l) == 0xBADC0C0A){
125 if (get1(map, stktop-(i-1)*4, (uchar *)&efl[0], 4) < 0)
126 return -1;
127 if (get1(map, stktop-(i-2)*4, (uchar *)&efl[1], 4) < 0)
128 return -1;
129 fvo = (ef[6]<<8)|ef[7];
130 vec = fvo & 0xfff;
131 vec >>= 2;
132 if(vec >= 256)
133 continue;
134
135 for(ft=ftype; ft->name; ft++) {
136 if(ft->fmt == ((fvo>>12) & 0xF)){
137 m68020vec = vec;
138 return 1;
139 }
140 }
141 break;
142 }
143 }
144 return -1;
145 }
146
147 static char *
m68020excep(Map * map,Rgetter rget)148 m68020excep(Map *map, Rgetter rget)
149 {
150 uvlong pc;
151 uchar buf[4];
152
153 if (m68020ufix(map) < 0)
154 return "bad exception frame";
155
156 if(excep[m68020vec] == 0)
157 return "bad exeception type";
158
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)
163 return "breakpoint";
164 }
165 return excep[m68020vec];
166 }
167 /* 68020 Disassembler and related functions */
168 /*
169 not supported: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, cpSAVE
170
171 opcode: 1 1 1 1 1 1
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
177 %s - size code x x
178 %C - cache code x x
179 %E - source eff addr. x x x x x x
180 %d - direction bit 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>
187
188 word 1: 1 1 1 1 1 1
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
210
211 word 2: 1 1 1 1 1 1
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
216
217 -----------------------------------------------------------------------------
218
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
256 */
257 /* Operand classes */
258 enum {
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 */
295 };
296 /* validation bit masks for various EA classes */
297 enum {
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 */
307 };
308 /* EA validation table indexed by operand class number */
309
310 static short validea[] =
311 {
312 0, /* none */
313 Pdec, /* EAPI */
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 */
334 };
335 /* EA types */
336 enum
337 {
338 Dreg, /* Dn */
339 Areg, /* An */
340 AInd, /* (An) */
341 APdec, /* -(An) */
342 APinc, /* (An)+ */
343 ADisp, /* Displacement beyond (An) */
344 BXD, /* Base, Index, Displacement */
345 PDisp, /* Displacement beyond PC */
346 PXD, /* PC, Index, Displacement */
347 ABS, /* absolute */
348 IMM, /* immediate */
349 IREAL, /* single precision real immediate */
350 IEXT, /* extended precision real immediate */
351 IPACK, /* packed real immediate */
352 IDBL, /* double precision real immediate */
353 };
354
355 typedef struct optable Optable;
356 typedef struct operand Operand;
357 typedef struct inst Inst;
358
359 struct optable
360 {
361 ushort opcode;
362 ushort mask0;
363 ushort op2;
364 ushort mask1;
365 char opdata[2];
366 char *format;
367 };
368
369 struct operand
370 {
371 int eatype;
372 short ext;
373 union {
374 long immediate; /* sign-extended integer byte/word/long */
375 struct { /* index mode displacements */
376 long disp;
377 long outer;
378 };
379 char floater[24]; /* floating point immediates */
380 };
381 };
382
383 struct inst
384 {
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 */
388 Operand and[2];
389 char *end; /* end of print buffer */
390 char *curr; /* current fill point in buffer */
391 char *errmsg;
392 };
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)"} ,
403
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" },
409
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" },
424
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" },
433
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" },
442
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" },
447 { 0,0,0,0,{0},0 },
448 };
449 /* class 1: move byte */
450 static Optable t1[] = {
451 { 0x1000, 0xf000, 0x0000, 0x0000, {EAALL_B,EADDA},"MOVB %e,%E" },
452 { 0,0,0,0,{0},0 },
453 };
454 /* class 2: move long */
455 static Optable t2[] = {
456 { 0x2040, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "MOVL %e,A%x" },
457
458 { 0x2000, 0xf000, 0x0000, 0x0000, {EAALL_L,EADDA},"MOVL %e,%E" },
459 { 0,0,0,0,{0},0 },
460 };
461 /* class 3: move word */
462 static Optable t3[] = {
463 { 0x3040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "MOVW %e,A%x" },
464
465 { 0x3000, 0xf000, 0x0000, 0x0000, {EAALL_W,EADDA},"MOVW %e,%E" },
466 { 0,0,0,0,{0},0 },
467 };
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" },
481
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)" },
492
493 { 0x4e40, 0xfff0, 0x0000, 0x0000, {0}, "SYS %f" },
494
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" },
517
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" },
523
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" },
527 { 0,0,0,0,{0},0 },
528 };
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" },
533
534 { 0x50c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" },
535 { 0x51c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" },
536
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" },
543
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" },
547
548 { 0x50c0, 0xf0c0, 0x0000, 0x0000, {EADA}, "S%c %e" },
549 { 0,0,0,0,{0},0 },
550 };
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" },
556 { 0,0,0,0,{0},0 },
557 };
558 /* class 7: move quick */
559 static Optable t7[] = {
560 { 0x7000, 0xf100, 0x0000, 0x0000, {OP8}, "MOVL $Q%i,R%x" },
561 { 0,0,0,0,{0},0 },
562 };
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" },
571
572 { 0x80c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVUW %e,R%x" },
573 { 0x81c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVSW %e,R%x" },
574
575 { 0x8000, 0xf100, 0x0000, 0x0000, {EADI}, "OR%s %e,R%x" },
576 { 0x8100, 0xf100, 0x0000, 0x0000, {EAMA}, "OR%s R%x,%e" },
577 { 0,0,0,0,{0},0 },
578 };
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" },
583
584 { 0x9100, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s R%y,R%x" },
585 { 0x9108, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s -(A%y),-(A%x)" },
586
587 { 0x9000, 0xf100, 0x0000, 0x0000, {EAALL}, "SUB%s %e,R%x" },
588 { 0x9100, 0xf100, 0x0000, 0x0000, {EAMA}, "SUB%s R%x,%e" },
589 { 0,0,0,0,{0},0 },
590 };
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" },
598
599 { 0xb108, 0xf138, 0x0000, 0x0000, {0}, "CMP%s (A%y)+,(A%x)+" },
600
601 { 0xb100, 0xf100, 0x0000, 0x0000, {EADA}, "EOR%s %e,R%x" },
602 { 0,0,0,0,{0},0 },
603 };
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" },
611
612 { 0xc0c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULUW %e,R%x" },
613 { 0xc1c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULSW %e,R%x" },
614
615 { 0xc000, 0xf100, 0x0000, 0x0000, {EADI}, "AND%s %e,R%x" },
616 { 0xc100, 0xf100, 0x0000, 0x0000, {EAMA}, "AND%s R%x,%e" },
617 { 0,0,0,0,{0},0 },
618 };
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" },
624
625 { 0xd100, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s R%y,R%x" },
626 { 0xd108, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s -(A%y),-(A%x)" },
627
628 { 0xd000, 0xf100, 0x0000, 0x0000, {EAALL}, "ADD%s %e,R%x" },
629 { 0xd100, 0xf100, 0x0000, 0x0000, {EAMA}, "ADD%s R%x,%e" },
630 { 0,0,0,0,{0},0 },
631 };
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}" },
638
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" },
643
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}" },
648
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" },
653
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}" },
658
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" },
663
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}" },
668
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}" },
673
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" },
678
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" },
687 { 0,0,0,0,{0},0 },
688 };
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" },
696
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)" },
709
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" },
736
737 /* floating point (coprocessor 1)*/
738
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" },
745
746 { 0xf240, 0xffc0, 0x0000, 0xffc0, {EADA}, "FS%P %e" },
747
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" },
754
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}" },
759
760 { 0xf200, 0xffc0, 0x8000, 0xe3ff, {EAM}, "FMOVEML #%B,%e" },
761 { 0xf200, 0xffc0, 0xa000, 0xe3ff, {EAMA}, "FMOVEML %e,#%B" },
762
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" },
867
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" },
870
871 { 0xf200, 0xffc0, 0x6000, 0xe000, {EADA}, "FMOVE%S F%D,%e" },
872
873 { 0xf300, 0xffc0, 0x0000, 0x0000, {EACAPD}, "FSAVE %e" },
874 { 0xf340, 0xffc0, 0x0000, 0x0000, {EACAPI}, "FRESTORE %e" },
875
876 { 0xf280, 0xffc0, 0x0000, 0x0000, {BR16}, "FB%p %t" },
877 { 0xf2c0, 0xffc0, 0x0000, 0x0000, {BR32}, "FB%p %t" },
878
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" },
885 { 0,0,0,0,{0},0 },
886 };
887
888 static Optable *optables[] =
889 {
890 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, 0, tb, tc, td, te, tf,
891 };
892
893 static Map *mymap;
894
895 static int
dumpinst(Inst * ip,char * buf,int n)896 dumpinst(Inst *ip, char *buf, int n)
897 {
898 int i;
899
900 if (n <= 0)
901 return 0;
902
903 *buf++ = '#';
904 for (i = 0; i < ip->n && i*4+1 < n-4; i++, buf += 4)
905 _hexify(buf, ip->raw[i], 3);
906 *buf = 0;
907 return i*4+1;
908 }
909
910 static int
getword(Inst * ip,uvlong offset)911 getword(Inst *ip, uvlong offset)
912 {
913 if (ip->n < nelem(ip->raw)) {
914 if (get2(mymap, offset, &ip->raw[ip->n++]) > 0)
915 return 1;
916 werrstr("can't read instruction: %r");
917 } else
918 werrstr("instruction too big: %r");
919 return -1;
920 }
921
922 static int
getshorts(Inst * ip,void * where,int n)923 getshorts(Inst *ip, void *where, int n)
924 {
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");
928 return 0;
929 }
930 memmove(where, &ip->raw[ip->n], n*2);
931 ip->n += n;
932 return 1;
933 }
934 werrstr("instruction too big: %r");
935 return 0;
936 }
937
938 static int
i8(Inst * ip,long * l)939 i8(Inst *ip, long *l)
940 {
941 if (getword(ip, ip->addr+ip->n*2) < 0)
942 return -1;
943 *l = ip->raw[ip->n-1]&0xff;
944 if (*l&0x80)
945 *l |= ~0xff;
946 return 1;
947 }
948
949 static int
i16(Inst * ip,long * l)950 i16(Inst *ip, long *l)
951 {
952 if (getword(ip, ip->addr+ip->n*2) < 0)
953 return -1;
954 *l = ip->raw[ip->n-1];
955 if (*l&0x8000)
956 *l |= ~0xffff;
957 return 1;
958 }
959 static int
i32(Inst * ip,long * l)960 i32(Inst *ip, long *l)
961 {
962 if (getword(ip, ip->addr+ip->n*2) < 0)
963 return -1;
964 if (getword(ip, ip->addr+ip->n*2) < 0)
965 return -1;
966 *l = (ip->raw[ip->n-2]<<16)|ip->raw[ip->n-1];
967 return 1;
968 }
969
970 static int
getimm(Inst * ip,Operand * ap,int mode)971 getimm(Inst *ip, Operand *ap, int mode)
972 {
973 ap->eatype = IMM;
974 switch(mode)
975 {
976 case EAM_B: /* byte */
977 case EAALL_B:
978 return i8(ip, &ap->immediate);
979 case EADI_W: /* word */
980 case EAALL_W:
981 return i16(ip, &ap->immediate);
982 case EADI_L: /* long */
983 case EAALL_L:
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)
987 {
988 case 0: /* long integer */
989 return i32(ip, &ap->immediate);
990 case 1: /* single precision real */
991 ap->eatype = IREAL;
992 return getshorts(ip, ap->floater, 2);
993 case 2: /* extended precision real - not supported */
994 ap->eatype = IEXT;
995 return getshorts(ip, ap->floater, 6);
996 case 3: /* packed decimal real - not supported */
997 ap->eatype = IPACK;
998 return getshorts(ip, ap->floater, 12);
999 case 4: /* integer word */
1000 return i16(ip, &ap->immediate);
1001 case 5: /* double precision real */
1002 ap->eatype = IDBL;
1003 return getshorts(ip, ap->floater, 4);
1004 case 6: /* integer byte */
1005 return i8(ip, &ap->immediate);
1006 default:
1007 ip->errmsg = "bad immediate float data";
1008 return -1;
1009 }
1010 /* not reached */
1011 case IV: /* size encoded in bits 6&7 of opcode word */
1012 default:
1013 switch((ip->raw[0]>>6)&0x03)
1014 {
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);
1021 default:
1022 ip->errmsg = "bad immediate size";
1023 return -1;
1024 }
1025 /* not reached */
1026 }
1027 }
1028
1029 static int
getdisp(Inst * ip,Operand * ap)1030 getdisp(Inst *ip, Operand *ap)
1031 {
1032 short ext;
1033
1034 if (getword(ip, ip->addr+ip->n*2) < 0)
1035 return -1;
1036 ext = ip->raw[ip->n-1];
1037 ap->ext = ext;
1038 if ((ext&0x100) == 0) { /* indexed with 7-bit displacement */
1039 ap->disp = ext&0x7f;
1040 if (ap->disp&0x40)
1041 ap->disp |= ~0x7f;
1042 return 1;
1043 }
1044 switch(ext&0x30) /* first (inner) displacement */
1045 {
1046 case 0x10:
1047 break;
1048 case 0x20:
1049 if (i16(ip, &ap->disp) < 0)
1050 return -1;
1051 break;
1052 case 0x30:
1053 if (i32(ip, &ap->disp) < 0)
1054 return -1;
1055 break;
1056 default:
1057 ip->errmsg = "bad EA displacement";
1058 return -1;
1059 }
1060 switch (ext&0x03) /* outer displacement */
1061 {
1062 case 0x02: /* 16 bit displacement */
1063 return i16(ip, &ap->outer);
1064 case 0x03: /* 32 bit displacement */
1065 return i32(ip, &ap->outer);
1066 default:
1067 break;
1068 }
1069 return 1;
1070 }
1071
1072 static int
ea(Inst * ip,int ea,Operand * ap,int mode)1073 ea(Inst *ip, int ea, Operand *ap, int mode)
1074 {
1075 int type, size;
1076
1077 type = 0;
1078 ap->ext = 0;
1079 switch((ea>>3)&0x07)
1080 {
1081 case 0x00:
1082 ap->eatype = Dreg;
1083 type = Dn;
1084 break;
1085 case 0x01:
1086 ap->eatype = Areg;
1087 type = An;
1088 break;
1089 case 0x02:
1090 ap->eatype = AInd;
1091 type = Ind;
1092 break;
1093 case 0x03:
1094 ap->eatype = APinc;
1095 type = Pinc;
1096 break;
1097 case 0x04:
1098 ap->eatype = APdec;
1099 type = Pdec;
1100 break;
1101 case 0x05:
1102 ap->eatype = ADisp;
1103 type = Bdisp;
1104 if (i16(ip, &ap->disp) < 0)
1105 return -1;
1106 break;
1107 case 0x06:
1108 ap->eatype = BXD;
1109 type = Bdisp;
1110 if (getdisp(ip, ap) < 0)
1111 return -1;
1112 break;
1113 case 0x07:
1114 switch(ea&0x07)
1115 {
1116 case 0x00:
1117 type = Abs;
1118 ap->eatype = ABS;
1119 if (i16(ip, &ap->immediate) < 0)
1120 return -1;
1121 break;
1122 case 0x01:
1123 type = Abs;
1124 ap->eatype = ABS;
1125 if (i32(ip, &ap->immediate) < 0)
1126 return -1;
1127 break;
1128 case 0x02:
1129 type = PCrel;
1130 ap->eatype = PDisp;
1131 if (i16(ip, &ap->disp) < 0)
1132 return -1;
1133 break;
1134 case 0x03:
1135 type = PCrel;
1136 ap->eatype = PXD;
1137 if (getdisp(ip, ap) < 0)
1138 return -1;
1139 break;
1140 case 0x04:
1141 type = Imm;
1142 if (getimm(ip, ap, mode) < 0)
1143 return -1;
1144 break;
1145 default:
1146 ip->errmsg = "bad EA mode";
1147 return -1;
1148 }
1149 }
1150 /* Allowable floating point EAs are restricted for packed,
1151 * extended, and double precision operands
1152 */
1153 if (mode == EAFLT) {
1154 size = (ip->raw[1]>>10)&0x07;
1155 if (size == 2 || size == 3 || size == 5)
1156 mode = EAM;
1157 else
1158 mode = EADI;
1159 }
1160 if (!(validea[mode]&type)) {
1161 ip->errmsg = "invalid EA";
1162 return -1;
1163 }
1164 return 1;
1165 }
1166
1167 static int
decode(Inst * ip,Optable * op)1168 decode(Inst *ip, Optable *op)
1169 {
1170 int i, t, mode;
1171 Operand *ap;
1172 short opcode;
1173
1174 opcode = ip->raw[0];
1175 for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1176 ap = &ip->and[i];
1177 mode = op->opdata[i];
1178 switch(mode)
1179 {
1180 case EAPI: /* normal EA modes */
1181 case EACA:
1182 case EACAD:
1183 case EACAPI:
1184 case EACAPD:
1185 case EAMA:
1186 case EADA:
1187 case EAA:
1188 case EAC:
1189 case EACPI:
1190 case EACD:
1191 case EAD:
1192 case EAM:
1193 case EAM_B:
1194 case EADI:
1195 case EADI_L:
1196 case EADI_W:
1197 case EAALL:
1198 case EAALL_L:
1199 case EAALL_W:
1200 case EAALL_B:
1201 case EAFLT:
1202 if (ea(ip, opcode&0x3f, ap, mode) < 0)
1203 return -1;
1204 break;
1205 case EADDA: /* stupid bit flop required */
1206 t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1207 if (ea(ip, t, ap, EADA)< 0)
1208 return -1;
1209 break;
1210 case BREAC: /* EAC JMP or CALL operand */
1211 if (ea(ip, opcode&0x3f, ap, EAC) < 0)
1212 return -1;
1213 break;
1214 case OP8: /* weird movq instruction */
1215 ap->eatype = IMM;
1216 ap->immediate = opcode&0xff;
1217 if (opcode&0x80)
1218 ap->immediate |= ~0xff;
1219 break;
1220 case I8: /* must be two-word opcode */
1221 ap->eatype = IMM;
1222 ap->immediate = ip->raw[1]&0xff;
1223 if (ap->immediate&0x80)
1224 ap->immediate |= ~0xff;
1225 break;
1226 case I16: /* 16 bit immediate */
1227 case BR16:
1228 ap->eatype = IMM;
1229 if (i16(ip, &ap->immediate) < 0)
1230 return -1;
1231 break;
1232 case C16: /* CAS2 16 bit immediate */
1233 ap->eatype = IMM;
1234 if (i16(ip, &ap->immediate) < 0)
1235 return -1;
1236 if (ap->immediate & 0x0e38) {
1237 ip->errmsg = "bad CAS2W operand";
1238 return 0;
1239 }
1240 break;
1241 case I32: /* 32 bit immediate */
1242 case BR32:
1243 ap->eatype = IMM;
1244 if (i32(ip, &ap->immediate) < 0)
1245 return -1;
1246 break;
1247 case IV: /* immediate data depends on size field */
1248 if (getimm(ip, ap, IV) < 0)
1249 return -1;
1250 break;
1251 case BR8: /* branch displacement format */
1252 ap->eatype = IMM;
1253 ap->immediate = opcode&0xff;
1254 if (ap->immediate == 0) {
1255 if (i16(ip, &ap->immediate) < 0)
1256 return -1;
1257 } else if (ap->immediate == 0xff) {
1258 if (i32(ip, &ap->immediate) < 0)
1259 return -1;
1260 } else if (ap->immediate & 0x80)
1261 ap->immediate |= ~0xff;
1262 break;
1263 case STACK: /* Dummy operand type for Return instructions */
1264 default:
1265 break;
1266 }
1267 }
1268 return 1;
1269 }
1270
1271 static Optable *
instruction(Inst * ip)1272 instruction(Inst *ip)
1273 {
1274 ushort opcode, op2;
1275 Optable *op;
1276 int class;
1277
1278 ip->n = 0;
1279 if (getword(ip, ip->addr) < 0)
1280 return 0;
1281 opcode = ip->raw[0];
1282 if (get2(mymap, ip->addr+2, &op2) < 0)
1283 op2 = 0;
1284 class = (opcode>>12)&0x0f;
1285 for (op = optables[class]; op && op->format; op++) {
1286 if (op->opcode != (opcode&op->mask0))
1287 continue;
1288 if (op->op2 != (op2&op->mask1))
1289 continue;
1290 if (op->mask1)
1291 ip->raw[ip->n++] = op2;
1292 return op;
1293 }
1294 ip->errmsg = "Invalid opcode";
1295 return 0;
1296 }
1297
1298 #pragma varargck argpos bprint 2
1299
1300 static void
bprint(Inst * i,char * fmt,...)1301 bprint(Inst *i, char *fmt, ...)
1302 {
1303 va_list arg;
1304
1305 va_start(arg, fmt);
1306 i->curr = vseprint(i->curr, i->end, fmt, arg);
1307 va_end(arg);
1308 }
1309
1310 static char *regname[] =
1311 {
1312 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0",
1313 "A1", "A2", "A3", "A4", "A5", "A6", "A7", "PC", "SB"
1314 };
1315
1316 static void
plocal(Inst * ip,Operand * ap)1317 plocal(Inst *ip, Operand *ap)
1318 {
1319 int ret;
1320 long offset;
1321 uvlong moved;
1322 Symbol s;
1323
1324 offset = ap->disp;
1325 if (!findsym(ip->addr, CTEXT, &s))
1326 goto none;
1327
1328 moved = pc2sp(ip->addr);
1329 if (moved == -1)
1330 goto none;
1331
1332 if (offset > moved) { /* above frame - must be argument */
1333 offset -= moved;
1334 ret = getauto(&s, offset-mach->szaddr, CPARAM, &s);
1335 } else /* below frame - must be automatic */
1336 ret = getauto(&s, moved-offset, CPARAM, &s);
1337 if (ret)
1338 bprint(ip, "%s+%lux", s.name, offset);
1339 else
1340 none: bprint(ip, "%lux", ap->disp);
1341 }
1342
1343 /*
1344 * this guy does all the work of printing the base and index component
1345 * of an EA.
1346 */
1347 static int
pidx(Inst * ip,int ext,int reg,char * bfmt,char * ifmt,char * nobase)1348 pidx(Inst *ip, int ext, int reg, char *bfmt, char *ifmt, char *nobase)
1349 {
1350 char *s;
1351 int printed;
1352 char buf[512];
1353
1354 printed = 1;
1355 if (ext&0x80) { /* Base suppressed */
1356 if (reg == 16)
1357 bprint(ip, bfmt, "(ZPC)");
1358 else if (nobase)
1359 bprint(ip, nobase);
1360 else
1361 printed = 0;
1362 } else /* format base reg */
1363 bprint(ip, bfmt, regname[reg]);
1364 if (ext & 0x40) /* index suppressed */
1365 return printed;
1366 switch ((ext>>9)&0x03)
1367 {
1368 case 0x01:
1369 s = "*2";
1370 break;
1371 case 0x02:
1372 s = "*4";
1373 break;
1374 case 0x03:
1375 s = "*8";
1376 break;
1377 default:
1378 if (ext&0x80)
1379 s = "*1";
1380 else
1381 s = "";
1382 break;
1383 }
1384 sprint(buf, "%s.%c%s", regname[(ext>>12)&0x0f], (ext&0x800) ? 'L' : 'W', s);
1385 if (!printed)
1386 bprint(ip, ifmt, buf);
1387 else
1388 bprint(ip, "(%s)", buf);
1389 return 1;
1390 }
1391
1392 static void
prindex(Inst * ip,int reg,Operand * ap)1393 prindex(Inst *ip, int reg, Operand *ap)
1394 {
1395 short ext;
1396 int left;
1397 int disp;
1398
1399 left = ip->end-ip->curr;
1400 if (left <= 0)
1401 return;
1402 ext = ap->ext;
1403 disp = ap->disp;
1404 /* look for static base register references */
1405 if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) {
1406 reg = 17; /* "A6" -> "SB" */
1407 disp += mach->sb;
1408 }
1409 if ((ext&0x100) == 0) { /* brief form */
1410 if (reg == 15)
1411 plocal(ip, ap);
1412 else if (disp)
1413 ip->curr += symoff(ip->curr, left, disp, CANY);
1414 pidx(ip, ext&0xff00, reg, "(%s)", "(%s)", 0);
1415 return;
1416 }
1417 switch(ext&0x3f) /* bd size, && i/is */
1418 {
1419 case 0x10:
1420 if (!pidx(ip, ext, reg, "(%s)", "(%s)", 0))
1421 bprint(ip, "#0");
1422 break;
1423 case 0x11:
1424 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1425 bprint(ip, ")");
1426 else
1427 bprint(ip, "#0");
1428 break;
1429 case 0x12:
1430 case 0x13:
1431 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1432 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1433 bprint(ip, ")");
1434 break;
1435 case 0x15:
1436 if (!pidx(ip, ext, reg, "((%s))", "(%s)", 0))
1437 bprint(ip, "#0");
1438 break;
1439 case 0x16:
1440 case 0x17:
1441 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1442 pidx(ip, ext, reg, "((%s))", "(%s)", 0);
1443 break;
1444 case 0x20:
1445 case 0x30:
1446 if (reg == 15)
1447 plocal(ip, ap);
1448 else
1449 ip->curr += symoff(ip->curr, left, disp, CANY);
1450 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1451 break;
1452 case 0x21:
1453 case 0x31:
1454 *ip->curr++ = '(';
1455 if (reg == 15)
1456 plocal(ip, ap);
1457 else
1458 ip->curr += symoff(ip->curr, left-1, disp, CANY);
1459 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1460 bprint(ip, ")");
1461 break;
1462 case 0x22:
1463 case 0x23:
1464 case 0x32:
1465 case 0x33:
1466 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1467 bprint(ip, "(");
1468 if (reg == 15)
1469 plocal(ip, ap);
1470 else
1471 ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1472 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1473 bprint(ip, ")");
1474 break;
1475 case 0x25:
1476 case 0x35:
1477 *ip->curr++ = '(';
1478 if (reg == 15)
1479 plocal(ip, ap);
1480 else
1481 ip->curr += symoff(ip->curr, left-1, disp, CANY);
1482 if (!pidx(ip, ext, reg, "(%s))", "(%s)", "())"))
1483 bprint(ip, ")");
1484 break;
1485 case 0x26:
1486 case 0x27:
1487 case 0x36:
1488 case 0x37:
1489 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1490 bprint(ip, "(");
1491 if (reg == 15)
1492 plocal(ip, ap);
1493 else
1494 ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1495 pidx(ip, ext, reg, "(%s))", "(%s)", "())");
1496 break;
1497 default:
1498 bprint(ip, "??%x??", ext);
1499 ip->errmsg = "bad EA";
1500 break;
1501 }
1502 }
1503
1504 static void
pea(int reg,Inst * ip,Operand * ap)1505 pea(int reg, Inst *ip, Operand *ap)
1506 {
1507 int i, left;
1508
1509 left = ip->end-ip->curr;
1510 if (left < 0)
1511 return;
1512 switch(ap->eatype)
1513 {
1514 case Dreg:
1515 bprint(ip, "R%d", reg);
1516 break;
1517 case Areg:
1518 bprint(ip, "A%d", reg);
1519 break;
1520 case AInd:
1521 bprint(ip, "(A%d)", reg);
1522 break;
1523 case APinc:
1524 bprint(ip, "(A%d)+", reg);
1525 break;
1526 case APdec:
1527 bprint(ip, "-(A%d)", reg);
1528 break;
1529 case PDisp:
1530 ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY);
1531 break;
1532 case PXD:
1533 prindex(ip, 16, ap);
1534 break;
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);
1538 bprint(ip, "(SB)");
1539 break;
1540 }
1541 /* reference autos and parameters off the stack */
1542 if (reg == 7)
1543 plocal(ip, ap);
1544 else
1545 ip->curr += symoff(ip->curr, left, ap->disp, CANY);
1546 bprint(ip, "(A%d)", reg);
1547 break;
1548 case BXD:
1549 prindex(ip, reg+8, ap);
1550 break;
1551 case ABS:
1552 ip->curr += symoff(ip->curr, left, ap->immediate, CANY);
1553 bprint(ip, "($0)");
1554 break;
1555 case IMM:
1556 *ip->curr++ = '$';
1557 ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY);
1558 break;
1559 case IREAL:
1560 *ip->curr++ = '$';
1561 ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater);
1562 break;
1563 case IDBL:
1564 *ip->curr++ = '$';
1565 ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater);
1566 break;
1567 case IPACK:
1568 bprint(ip, "$#");
1569 for (i = 0; i < 24 && ip->curr < ip->end-1; i++) {
1570 _hexify(ip->curr, ap->floater[i], 1);
1571 ip->curr += 2;
1572 }
1573 break;
1574 case IEXT:
1575 bprint(ip, "$#");
1576 ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater);
1577 break;
1578 default:
1579 bprint(ip, "??%x??", ap->eatype);
1580 ip->errmsg = "bad EA type";
1581 break;
1582 }
1583 }
1584
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[] =
1588 {
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"
1593 };
1594 static char *cachetab[] = { "NC", "DC", "IC", "BC" };
1595 static char *mmutab[] = { "TC", "??", "SRP", "CRP" };
1596 static char *crtab0[] =
1597 {
1598 "SFC", "DFC", "CACR", "TC", "ITT0", "ITT1", "DTT0", "DTT1",
1599 };
1600 static char *crtab1[] =
1601 {
1602 "USP", "VBR", "CAAR", "MSP", "ISP", "MMUSR", "URP", "SRP",
1603 };
1604 static char typetab[] = { 'L', 'S', 'X', 'P', 'W', 'D', 'B', '?', };
1605 static char sztab[] = {'?', 'B', 'W', 'L', '?' };
1606
1607 static void
formatins(char * fmt,Inst * ip)1608 formatins(char *fmt, Inst *ip)
1609 {
1610 short op, w1;
1611 int r1, r2;
1612 int currand;
1613
1614 op = ip->raw[0];
1615 w1 = ip->raw[1];
1616 currand = 0;
1617 for (; *fmt && ip->curr < ip->end; fmt++) {
1618 if (*fmt != '%')
1619 *ip->curr++ = *fmt;
1620 else switch(*++fmt)
1621 {
1622 case '%':
1623 *ip->curr++ = '%';
1624 break;
1625 case 'a': /* register number; word 1:[0-2] */
1626 *ip->curr++ = (w1&0x07)+'0';
1627 break;
1628 case 'c': /* condition code; opcode: [8-11] */
1629 bprint(ip, cctab[(op>>8)&0x0f]);
1630 break;
1631 case 'd': /* shift direction; opcode: [8] */
1632 if (op&0x100)
1633 *ip->curr++ = 'L';
1634 else
1635 *ip->curr++ = 'R';
1636 break;
1637 case 'e': /* source effective address */
1638 pea(op&0x07, ip, &ip->and[currand++]);
1639 break;
1640 case 'f': /* trap vector; op code: [0-3] */
1641 bprint(ip, "%x", op&0x0f);
1642 break;
1643 case 'h': /* register number; word 1: [5-7] */
1644 *ip->curr++ = (w1>>5)&0x07+'0';
1645 break;
1646 case 'i': /* immediate operand */
1647 ip->curr += symoff(ip->curr, ip->end-ip->curr,
1648 ip->and[currand++].immediate, CANY);
1649 break;
1650 case 'j': /* data registers; word 1: [0-2] & [12-14] */
1651 r1 = w1&0x07;
1652 r2 = (w1>>12)&0x07;
1653 if (r1 == r2)
1654 bprint(ip, "R%d", r1);
1655 else
1656 bprint(ip, "R%d:R%d", r2, r1);
1657 break;
1658 case 'k': /* k factor; word 1 [0-6] */
1659 bprint(ip, "%x", w1&0x7f);
1660 break;
1661 case 'm': /* register mask; word 1 [0-7] */
1662 bprint(ip, "%x", w1&0xff);
1663 break;
1664 case 'o': /* bit field offset; word1: [6-10] */
1665 bprint(ip, "%d", (w1>>6)&0x3f);
1666 break;
1667 case 'p': /* conditional predicate; opcode: [0-5]
1668 only bits 0-4 are defined */
1669 bprint(ip, fcond[op&0x1f]);
1670 break;
1671 case 'q': /* 3-bit immediate value; opcode[9-11] */
1672 r1 = (op>>9)&0x07;
1673 if (r1 == 0)
1674 *ip->curr++ = '8';
1675 else
1676 *ip->curr++ = r1+'0';
1677 break;
1678 case 'r': /* register type & number; word 1: [12-15] */
1679 bprint(ip, regname[(w1>>12)&0x0f]);
1680 break;
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";
1685 break;
1686 case 't': /* text offset */
1687 ip->curr += symoff(ip->curr, ip->end-ip->curr,
1688 ip->and[currand++].immediate+ip->addr+2, CTEXT);
1689 break;
1690 case 'u': /* register number; word 1: [6-8] */
1691 *ip->curr++ = ((w1>>6)&0x07)+'0';
1692 break;
1693 case 'w': /* bit field width; word 1: [0-4] */
1694 bprint(ip, "%d", w1&0x0f);
1695 break;
1696 case 'x': /* register number; opcode: [9-11] */
1697 *ip->curr++ = ((op>>9)&0x07)+'0';
1698 break;
1699 case 'y': /* register number; opcode: [0-2] */
1700 *ip->curr++ = (op&0x07)+'0';
1701 break;
1702 case 'z': /* shift count; opcode: [9-11] */
1703 *ip->curr++ = ((op>>9)&0x07)+'0';
1704 break;
1705 case 'A': /* register number; word 2: [0-2] */
1706 *ip->curr++ = (ip->raw[2]&0x07)+'0';
1707 break;
1708 case 'B': /* float source reg; word 1: [10-12] */
1709 *ip->curr++ = ((w1>>10)&0x07)+'0';
1710 break;
1711 case 'C': /* cache identifier; opcode: [6-7] */
1712 bprint(ip, cachetab[(op>>6)&0x03]);
1713 break;
1714 case 'D': /* float dest reg; word 1: [7-9] */
1715 *ip->curr++ = ((w1>>7)&0x07)+'0';
1716 break;
1717 case 'E': /* destination EA; opcode: [6-11] */
1718 pea((op>>9)&0x07, ip, &ip->and[currand++]);
1719 break;
1720 case 'F': /* float dest register(s); word 1: [7-9] & [10-12] */
1721 r1 = (w1>>7)&0x07;
1722 r2 = (w1>>10)&0x07;
1723 if (r1 == r2)
1724 bprint(ip, "F%d", r1);
1725 else
1726 bprint(ip, "F%d,F%d", r2, r1);
1727 break;
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";
1732 break;
1733 case 'I': /* MMU function code mask; word 1: [5-8] */
1734 bprint(ip, "%x", (w1>>4)&0x0f);
1735 break;
1736 case 'K': /* dynamic k-factor register; word 1: [5-8] */
1737 bprint(ip, "%d", (w1>>4)&0x0f);
1738 break;
1739 case 'L': /* MMU function code; word 1: [0-6] */
1740 if (w1&0x10)
1741 bprint(ip, "%x", w1&0x0f);
1742 else if (w1&0x08)
1743 bprint(ip, "R%d",w1&0x07);
1744 else if (w1&0x01)
1745 bprint(ip, "DFC");
1746 else
1747 bprint(ip, "SFC");
1748 break;
1749 case 'N': /* control register; word 1: [0-11] */
1750 r1 = w1&0xfff;
1751 if (r1&0x800)
1752 bprint(ip, crtab1[r1&0x07]);
1753 else
1754 bprint(ip, crtab0[r1&0x07]);
1755 break;
1756 case 'P': /* conditional predicate; word 1: [0-5] */
1757 bprint(ip, fcond[w1&0x1f]);
1758 break;
1759 case 'R': /* register type & number; word 2 [12-15] */
1760 bprint(ip, regname[(ip->raw[2]>>12)&0x0f]);
1761 break;
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";
1766 break;
1767 case 'U': /* register number; word 2: [6-8] */
1768 *ip->curr++ = ((ip->raw[2]>>6)&0x07)+'0';
1769 break;
1770 case 'Z': /* ATC level number; word 1: [10-12] */
1771 bprint(ip, "%x", (w1>>10)&0x07);
1772 break;
1773 case '1': /* effective address in second operand*/
1774 pea(op&0x07, ip, &ip->and[1]);
1775 break;
1776 default:
1777 bprint(ip, "%%%c", *fmt);
1778 break;
1779 }
1780 }
1781 *ip->curr = 0; /* there's always room for 1 byte */
1782 }
1783
1784 static int
dispsize(Inst * ip)1785 dispsize(Inst *ip)
1786 {
1787 ushort ext;
1788 static int dsize[] = {0, 0, 1, 2}; /* in words */
1789
1790 if (get2(mymap, ip->addr+ip->n*2, &ext) < 0)
1791 return -1;
1792 if ((ext&0x100) == 0)
1793 return 1;
1794 return dsize[(ext>>4)&0x03]+dsize[ext&0x03]+1;
1795 }
1796
1797 static int
immsize(Inst * ip,int mode)1798 immsize(Inst *ip, int mode)
1799 {
1800 static int fsize[] = { 2, 2, 6, 12, 1, 4, 1, -1 };
1801 static int isize[] = { 1, 1, 2, -1 };
1802
1803 switch(mode)
1804 {
1805 case EAM_B: /* byte */
1806 case EAALL_B:
1807 case EADI_W: /* word */
1808 case EAALL_W:
1809 return 1;
1810 case EADI_L: /* long */
1811 case EAALL_L:
1812 return 2;
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 */
1816 default:
1817 return isize[(ip->raw[0]>>6)&0x03];
1818 }
1819 }
1820
1821 static int
easize(Inst * ip,int ea,int mode)1822 easize(Inst *ip, int ea, int mode)
1823 {
1824 switch((ea>>3)&0x07)
1825 {
1826 case 0x00:
1827 case 0x01:
1828 case 0x02:
1829 case 0x03:
1830 case 0x04:
1831 return 0;
1832 case 0x05:
1833 return 1;
1834 case 0x06:
1835 return dispsize(ip);
1836 case 0x07:
1837 switch(ea&0x07)
1838 {
1839 case 0x00:
1840 case 0x02:
1841 return 1;
1842 case 0x01:
1843 return 2;
1844 case 0x03:
1845 return dispsize(ip);
1846 case 0x04:
1847 return immsize(ip, mode);
1848 default:
1849 return -1;
1850 }
1851 }
1852 return -1;
1853 }
1854
1855 static int
instrsize(Inst * ip,Optable * op)1856 instrsize(Inst *ip, Optable *op)
1857 {
1858 int i, t, mode;
1859 short opcode;
1860
1861 opcode = ip->raw[0];
1862 for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1863 mode = op->opdata[i];
1864 switch(mode)
1865 {
1866 case EAPI: /* normal EA modes */
1867 case EACA:
1868 case EACAD:
1869 case EACAPI:
1870 case EACAPD:
1871 case EAMA:
1872 case EADA:
1873 case EAA:
1874 case EAC:
1875 case EACPI:
1876 case EACD:
1877 case EAD:
1878 case EAM:
1879 case EAM_B:
1880 case EADI:
1881 case EADI_L:
1882 case EADI_W:
1883 case EAALL:
1884 case EAALL_L:
1885 case EAALL_W:
1886 case EAALL_B:
1887 case EAFLT:
1888 t = easize(ip, opcode&0x3f, mode);
1889 if (t < 0)
1890 return -1;
1891 ip->n += t;
1892 break;
1893 case EADDA: /* stupid bit flop required */
1894 t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1895 t = easize(ip, t, mode);
1896 if (t < 0)
1897 return -1;
1898 ip->n += t;
1899 break;
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)
1904 return -1;
1905 } else {
1906 t = easize(ip, opcode&0x3f, mode);
1907 if (t < 0)
1908 return -1;
1909 ip->n += t;
1910 }
1911 break;
1912 case I16: /* 16 bit immediate */
1913 case C16: /* CAS2 16 bit immediate */
1914 ip->n++;
1915 break;
1916 case BR16: /* 16 bit branch displacement */
1917 if (i16(ip, &ip->and[i].immediate) < 0)
1918 return -1;
1919 break;
1920 case BR32: /* 32 bit branch displacement */
1921 if (i32(ip, &ip->and[i].immediate) < 0)
1922 return -1;
1923 break;
1924 case I32: /* 32 bit immediate */
1925 ip->n += 2;
1926 break;
1927 case IV: /* immediate data depends on size field */
1928 t = (ip->raw[0]>>6)&0x03;
1929 if (t < 2)
1930 ip->n++;
1931 else if (t == 2)
1932 ip->n += 2;
1933 else
1934 return -1;
1935 break;
1936 case BR8: /* loony branch displacement format */
1937 t = opcode&0xff;
1938 if (t == 0) {
1939 if (i16(ip, &ip->and[i].immediate) < 0)
1940 return -1;
1941 } else if (t == 0xff) {
1942 if (i32(ip, &ip->and[i].immediate) < 0)
1943 return -1;
1944 } else {
1945 ip->and[i].immediate = t;
1946 if (t & 0x80)
1947 ip->and[i].immediate |= ~0xff;
1948 }
1949 break;
1950 case STACK: /* Dummy operand for Return instructions */
1951 case OP8: /* weird movq instruction */
1952 case I8: /* must be two-word opcode */
1953 default:
1954 break;
1955 }
1956 }
1957 return 1;
1958 }
1959
1960 static int
eaval(Inst * ip,Operand * ap,Rgetter rget)1961 eaval(Inst *ip, Operand *ap, Rgetter rget)
1962 {
1963 int reg;
1964 char buf[8];
1965
1966 reg = ip->raw[0]&0x07;
1967 switch(ap->eatype)
1968 {
1969 case AInd:
1970 sprint(buf, "A%d", reg);
1971 return (*rget)(mymap, buf);
1972 case PDisp:
1973 return ip->addr+2+ap->disp;
1974 case ADisp:
1975 sprint(buf, "A%d", reg);
1976 return ap->disp+(*rget)(mymap, buf);
1977 case ABS:
1978 return ap->immediate;
1979 default:
1980 return 0;
1981 }
1982 }
1983
1984 static int
m68020instlen(Map * map,uvlong pc)1985 m68020instlen(Map *map, uvlong pc)
1986 {
1987 Inst i;
1988 Optable *op;
1989
1990 mymap = map;
1991 i.addr = pc;
1992 i.errmsg = 0;
1993 op = instruction(&i);
1994 if (op && instrsize(&i, op) > 0)
1995 return i.n*2;
1996 return -1;
1997 }
1998
1999 static int
m68020foll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)2000 m68020foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2001 {
2002 int j;
2003 Inst i;
2004 ulong l;
2005 Optable *op;
2006
2007 mymap = map;
2008 i.addr = pc;
2009 i.errmsg = 0;
2010 op = instruction(&i);
2011 if (op == 0 || instrsize(&i, op) < 0)
2012 return -1;
2013 for (j = 0; j < nelem(op->opdata) && op->opdata[j]; j++) {
2014 switch(op->opdata[j])
2015 {
2016 case BREAC: /* CALL, JMP, JSR */
2017 foll[0] = pc+2+eaval(&i, &i.and[j], rget);
2018 return 1;
2019 case BR8: /* Bcc, BSR, & BRA */
2020 case BR16: /* FBcc, FDBcc, DBcc */
2021 case BR32: /* FBcc */
2022 foll[0] = pc+i.n*2;
2023 foll[1] = pc+2+i.and[j].immediate;
2024 return 2;
2025 case STACK: /* RTR, RTS, RTD */
2026 if (get4(map, (*rget)(map, mach->sp), &l) < 0)
2027 return -1;
2028 *foll = l;
2029 return 1;
2030 default:
2031 break;
2032 }
2033 }
2034 foll[0] = pc+i.n*2;
2035 return 1;
2036 }
2037
2038 static int
m68020inst(Map * map,uvlong pc,char modifier,char * buf,int n)2039 m68020inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2040 {
2041 Inst i;
2042 Optable *op;
2043
2044 USED(modifier);
2045 mymap = map;
2046 i.addr = pc;
2047 i.curr = buf;
2048 i.end = buf+n-1;
2049 i.errmsg = 0;
2050 op = instruction(&i);
2051 if (!op)
2052 return -1;
2053 if (decode(&i, op) > 0)
2054 formatins(op->format, &i);
2055 if (i.errmsg) {
2056 if (i.curr != buf)
2057 bprint(&i, "\t\t;");
2058 bprint(&i, "%s: ", i.errmsg);
2059 dumpinst(&i, i.curr, i.end-i.curr);
2060 }
2061 return i.n*2;
2062 }
2063
2064 static int
m68020das(Map * map,uvlong pc,char * buf,int n)2065 m68020das(Map *map, uvlong pc, char *buf, int n)
2066 {
2067 Inst i;
2068 Optable *op;
2069
2070 mymap = map;
2071 i.addr = pc;
2072 i.curr = buf;
2073 i.end = buf+n-1;
2074 i.errmsg = 0;
2075
2076 op = instruction(&i);
2077 if (!op)
2078 return -1;
2079 decode(&i, op);
2080 if (i.errmsg)
2081 bprint(&i, "%s: ", i.errmsg);
2082 dumpinst(&i, i.curr, i.end-i.curr);
2083 return i.n*2;
2084 }
2085