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