]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/2db.c
merge
[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, size, vec;
98         ulong efl[2];
99         uchar *ef=(uchar*)efl;
100         ulong l;
101         uvlong stktop;
102         short fvo;
103
104                 /* The kernel proc pointer on a 68020 is always
105                  * at #8xxxxxxx; on the 68040 NeXT, the address
106                  * is always #04xxxxxx.  the sun3 port at sydney
107                  * uses 0xf8xxxxxx to 0xffxxxxxx.
108                  */
109         m68020vec = 0;
110
111         if (get4(map, mach->kbase, (&l)) < 0)
112                 return -1;
113         if ((l&0xfc000000) == 0x04000000)       /* if NeXT */
114                 size = 30*2;
115         else
116                 size = 46*2;                    /* 68020 */
117         USED(size);
118
119         stktop = mach->kbase+mach->pgsize;
120         for(i=3; i<100; i++){
121                 if (get1(map, stktop-i*4, (uchar*)&l, 4)< 0)
122                         return -1;
123
124                 if(machdata->swal(l) == 0xBADC0C0A){
125                         if (get1(map, stktop-(i-1)*4, (uchar *)&efl[0], 4) < 0)
126                                 return -1;
127                         if (get1(map, stktop-(i-2)*4, (uchar *)&efl[1], 4) < 0)
128                                 return -1;
129                         fvo = (ef[6]<<8)|ef[7];
130                         vec = fvo & 0xfff;
131                         vec >>= 2;
132                         if(vec >= 256)
133                                 continue;
134
135                         for(ft=ftype; ft->name; ft++) {
136                                 if(ft->fmt == ((fvo>>12) & 0xF)){
137                                         m68020vec = vec;
138                                         return 1;
139                                 }
140                         }
141                         break;
142                 }
143         }
144         return -1;
145 }
146
147 static char *
148 m68020excep(Map *map, Rgetter rget)
149 {
150         uvlong pc;
151         uchar buf[4];
152
153         if (m68020ufix(map) < 0)
154                 return "bad exception frame";
155
156         if(excep[m68020vec] == 0)
157                 return "bad exeception type";
158
159         if(m68020vec == BPTTRAP) {
160                 pc = (*rget)(map, "PC");
161                 if (get1(map, pc, buf, machdata->bpsize) > 0)
162                 if(memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
163                         return "breakpoint";
164         }
165         return excep[m68020vec];
166 }
167         /* 68020 Disassembler and related functions */
168 /*
169 not supported: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, cpSAVE 
170
171 opcode:                                 1 1 1 1 1 1
172                                         5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
173 %y - register number                                              x x x
174 %f - trap vector                                                  x x x
175 %e - destination eff addr                                   x x x x x x
176 %p - conditional predicate                                  x x x x x x
177 %s - size code                                          x x
178 %C - cache code                                         x x
179 %E - source eff addr.                           x x x x x x
180 %d - direction bit                                    x
181 %c - condition code                             x x x x
182 %x - register number                            x x x
183 %b - shift count                                x x x
184 %q - daffy 3-bit quick operand or shift count   x x x
185 %i - immediate operand <varies>
186 %t - offset(PC) <varies>
187
188 word 1:                                 1 1 1 1 1 1
189                                         5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
190 %a - register number                                              x x x
191 %w - bit field width                                          x x x x x
192 %L - MMU function code (SFC/DFC/D%a/#[0-3])                   x x x x x
193 %P - conditional predicate                                  x x x x x x
194 %k - k factor                                             x x x x x x x
195 %m - register mask                                      x x x x x x x x
196 %N - control register id                        x x x x x x x x x x x x
197 %j - (Dq != Dr) ? Dq:Dr : Dr              x x x                   x x x
198 %K - dynamic k register                                   x x x
199 %h - register number                                    x x x
200 %I - MMU function code mask                           x x x x
201 %o - bit field offset                             x x x x x
202 %u - register number                                  x x x
203 %D - float dest reg                                 x x x
204 %F - (fdr==fsr) ? "F%D" :"F%B,F%D"         x x x x x x
205 %S - float source type                        x x x
206 %B - float source register                    x x x
207 %Z - ATC level number                         x x x
208 %H - MMU register                           x x x x
209 %r - register type/number               x x x x
210
211 word 2:                                 1 1 1 1 1 1
212                                         5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
213 %A - register number                                              x x x
214 %U - register number                                  x x x
215 %R - register type,number               x x x x
216
217 -----------------------------------------------------------------------------
218
219 %a      -       register [word 1: 0-2]
220 %c      -       condition code [opcode: 8-11]
221 %d      -       direction [opcode: 8]
222 %e      -       destination effective address [opcode: 0-5]
223 %f      -       trap vector [opcode: 0-3]
224 %h      -       register [word 1: 5-7]
225 %i      -       immediate operand (1, 2, or 4 bytes)
226 %j      -       Dq:Dr if Dq != Dr; else Dr => Dr [word 1: 0-2] Dq [word 1: 12-14]
227 %k      -       k factor [word 1: 0-6]
228 %m      -       register mask [word 1: 0-7]
229 %o      -       bit field offset [word 1: 6-10]
230 %p      -       conditional predicate [opcode: 0-5]
231 %q      -       daffy 3-bit quick operand [opcode: 9-11]
232 %r      -       register type, [word 1: 15], register [word 1: 12-14]
233 %s      -       size [opcode: 6-7]
234 %t      -       offset beyond pc (text address) (2 or 4 bytes)
235 %u      -       register [word 1: 6-8]
236 %w      -       bit field width [word 1: 0-4]
237 %x      -       register [opcode: 9-11]
238 %y      -       register [opcode: 0-2]
239 %A      -       register [word 2: 0-2]
240 %B      -       float source register [word 1: 10-12]
241 %C      -       cache identifier [opcode: 6-7] (IC, DC, or BC)
242 %D      -       float dest reg [word 1: 7-9]
243 %E      -       dest effective address [opcode: 6-11]
244 %F      -       float dest reg == float src reg => "F%D"; else "F%B,F%D"
245 %H      -       MMU reg [word 1: 10-13] (see above & p 4-53/54)
246 %I      -       MMU function code mask [word 1: 5-8]
247 %K      -       dynamic k factor register [word 1: 4-6]
248 %L      -       MMU function code [word 1: 0-4] (SFC, DFC, D%a, or #[0-3])
249 %N      -       control register [word 1: 0-11]
250 %P      -       conditional predicate [word 1: 0-5]
251 %R      -       register type, [word 2: 15], register [word 2: 12-14]
252 %S      -       float source type code [word 1: 10-12]
253 %U      -       register [word 2: 6-8]
254 %Z      -       ATC level number [word 1: 10-12]
255 %1      -       Special case: EA as second operand
256 */
257         /* Operand classes */
258 enum {
259         EAPI = 1,       /* extended address: pre decrement only */
260         EACA,           /* extended address: control alterable */
261         EACAD,          /* extended address: control alterable or Dreg */
262         EACAPI,         /* extended address: control alterable or post-incr */
263         EACAPD,         /* extended address: control alterable or pre-decr */
264         EAMA,           /* extended address: memory alterable */
265         EADA,           /* extended address: data alterable */
266         EAA,            /* extended address: alterable */
267         EAC,            /* extended address: control addressing */
268         EACPI,          /* extended address: control addressing or post-incr */
269         EACD,           /* extended address: control addressing or Dreg */
270         EAD,            /* extended address: data addressing */
271         EAM,            /* extended address: memory addressing */
272         EAM_B,          /* EAM with byte immediate data */
273         EADI,           /* extended address: data addressing or immediate */
274         EADI_L,         /* EADI with long immediate data */
275         EADI_W,         /* EADI with word immediate data */
276         EAALL,          /* extended address: all modes */
277         EAALL_L,        /* EAALL with long immediate data */
278         EAALL_W,        /* EAALL with word immediate data */
279         EAALL_B,        /* EAALL with byte immediate date */
280                 /* special codes not directly used for validation */
281         EAFLT,          /* extended address: EADI for B, W, L, or S; else EAM */
282         EADDA,          /* destination extended address: EADA */
283         BREAC,          /* EAC operand for JMP or CALL */
284         OP8,            /* low 8 bits of op word */
285         I8,             /* low 8-bits of first extension word */
286         I16,            /* 16 bits in first extension word */
287         I32,            /* 32 bits in first and second extension words */
288         IV,             /* 8, 16 or 32 bit data in first & 2nd extension words */
289         C16,            /* CAS2 16 bit immediate with bits 9-11 & 3-5 zero */
290         BR8,            /* 8 bits in op word or 16 or 32 bits in extension words
291                                 branch instruction format (p. 2-25) */
292         BR16,           /* 16-bit branch displacement */
293         BR32,           /* 32-bit branch displacement */
294         STACK,          /* return PC on stack - follow set only */
295 };
296                 /* validation bit masks for various EA classes */
297 enum {
298         Dn      = 0x0001,       /* Data register */
299         An      = 0x0002,       /* Address register */
300         Ind     = 0x0004,       /* Address register indirect */
301         Pinc    = 0x0008,       /* Address register indirect post-increment */
302         Pdec    = 0x0010,       /* Address register indirect pre-decrement */
303         Bdisp   = 0x0020,       /* Base/Displacement in all its forms */
304         PCrel   = 0x0040,       /* PC relative addressing in all its forms */
305         Imm     = 0x0080,       /* Immediate data */
306         Abs     = 0x0100,       /* Absolute */
307 };
308         /* EA validation table indexed by operand class number */
309
310 static  short   validea[] =
311 {
312         0,                                              /* none */
313         Pdec,                                           /* EAPI */
314         Abs|Bdisp|Ind,                                  /* EACA */
315         Abs|Bdisp|Ind|Dn,                               /* EACAD */
316         Abs|Bdisp|Pinc|Ind,                             /* EACAPI */
317         Abs|Bdisp|Pdec|Ind,                             /* EACAPD */
318         Abs|Bdisp|Pdec|Pinc|Ind,                        /* EAMA */
319         Abs|Bdisp|Pdec|Pinc|Ind|Dn,                     /* EADA */
320         Abs|Bdisp|Pdec|Pinc|Ind|An|Dn,                  /* EAA */
321         Abs|PCrel|Bdisp|Ind,                            /* EAC */
322         Abs|PCrel|Bdisp|Pinc|Ind,                       /* EACPI */
323         Abs|PCrel|Bdisp|Ind|Dn,                         /* EACD */
324         Abs|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,               /* EAD */
325         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind,              /* EAM */
326         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind,              /* EAM_B */
327         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,           /* EADI */
328         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,           /* EADI_L */
329         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn,           /* EADI_W */
330         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,        /* EAALL */
331         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,        /* EAALL_L */
332         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,        /* EAALL_W */
333         Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn,        /* EAALL_B */
334 };
335         /* EA types */
336 enum
337 {
338         Dreg,           /* Dn */
339         Areg,           /* An */
340         AInd,           /* (An) */
341         APdec,          /* -(An) */
342         APinc,          /* (An)+ */
343         ADisp,          /* Displacement beyond (An) */
344         BXD,            /* Base, Index, Displacement */
345         PDisp,          /* Displacement beyond PC */
346         PXD,            /* PC, Index, Displacement */
347         ABS,            /* absolute */
348         IMM,            /* immediate */
349         IREAL,          /* single precision real immediate */
350         IEXT,           /* extended precision real immediate */
351         IPACK,          /* packed real immediate */
352         IDBL,           /* double precision real immediate */
353 };
354         
355 typedef struct optable  Optable;
356 typedef struct operand  Operand;
357 typedef struct inst     Inst;
358
359 struct optable
360 {
361         ushort  opcode;
362         ushort  mask0;
363         ushort  op2;
364         ushort  mask1;
365         char    opdata[2];
366         char    *format;
367 };
368
369 struct  operand
370 {
371         int     eatype;
372         short   ext;
373         union {
374                 long    immediate;      /* sign-extended integer byte/word/long */
375                 struct  {               /* index mode displacements */
376                         long    disp;
377                         long    outer;
378                 };
379                 char    floater[24];    /* floating point immediates */
380         };
381 };
382
383 struct  inst
384 {
385         int     n;              /* # bytes in instruction */
386         uvlong  addr;           /* addr of start of instruction */
387         ushort  raw[4+12];      /* longest instruction: 24 byte packed immediate */
388         Operand and[2];
389         char    *end;           /* end of print buffer */
390         char    *curr;          /* current fill point in buffer */
391         char    *errmsg;
392 };
393         /* class 0: bit field, MOVEP & immediate instructions */
394 static Optable t0[] = {
395 { 0x003c, 0xffff, 0x0000, 0xff00, {I8},         "ORB    %i,CCR" },
396 { 0x007c, 0xffff, 0x0000, 0x0000, {I16},        "ORW    %i,SR" },
397 { 0x023c, 0xffff, 0x0000, 0xff00, {I8},         "ANDB   %i,CCR" },
398 { 0x027c, 0xffff, 0x0000, 0x0000, {I16},        "ANDW   %i,SR" },
399 { 0x0a3c, 0xffff, 0x0000, 0xff00, {I8},         "EORB   %i,CCR" },
400 { 0x0a7c, 0xffff, 0x0000, 0x0000, {I16},        "EORW   %i,SR" },
401 { 0x0cfc, 0xffff, 0x0000, 0x0000, {C16,C16},    "CAS2W  R%a:R%A,R%u:R%U,(%r):(%R)"} ,
402 { 0x0efc, 0xffff, 0x0000, 0x0000, {C16,C16},    "CAS2L  R%a:R%A,R%u:R%U,(%r):(%R)"} ,
403
404 { 0x06c0, 0xfff8, 0x0000, 0x0000, {0},          "RTM    R%y" },
405 { 0x06c8, 0xfff8, 0x0000, 0x0000, {0},          "RTM    A%y" },
406 { 0x0800, 0xfff8, 0x0000, 0x0000, {I16},        "BTSTL  %i,R%y" },
407 { 0x0840, 0xfff8, 0x0000, 0x0000, {I16},        "BCHGL  %i,R%y" },
408 { 0x0880, 0xfff8, 0x0000, 0x0000, {I16},        "BCLRL  %i,R%y" },
409
410 { 0x00c0, 0xffc0, 0x0000, 0x0fff, {EAC},        "CMP2B  %e,%r" },
411 { 0x00c0, 0xffc0, 0x0800, 0x0fff, {EAC},        "CHK2B  %e,%r" },
412 { 0x02c0, 0xffc0, 0x0000, 0x0fff, {EAC},        "CMP2W  %e,%r" },
413 { 0x02c0, 0xffc0, 0x0800, 0x0fff, {EAC},        "CHK2W  %e,%r" },
414 { 0x04c0, 0xffc0, 0x0000, 0x0fff, {EAC},        "CMP2L  %e,%r" },
415 { 0x04c0, 0xffc0, 0x0800, 0x0fff, {EAC},        "CHK2L  %e,%r" },
416 { 0x06c0, 0xffc0, 0x0000, 0x0000, {I16, BREAC}, "CALLM  %i,%e" },
417 { 0x0800, 0xffc0, 0x0000, 0x0000, {I16, EAD},   "BTSTB  %i,%e" },
418 { 0x0840, 0xffc0, 0x0000, 0x0000, {I16, EADA},  "BCHG   %i,%e" },
419 { 0x0880, 0xffc0, 0x0000, 0x0000, {I16, EADA},  "BCLR   %i,%e" },
420 { 0x08c0, 0xffc0, 0x0000, 0x0000, {I16, EADA},  "BSET   %i,%e" },
421 { 0x0ac0, 0xffc0, 0x0000, 0xfe38, {EAMA},       "CASB   R%a,R%u,%e" },
422 { 0x0cc0, 0xffc0, 0x0000, 0xfe38, {EAMA},       "CASW   R%a,R%u,%e" },
423 { 0x0ec0, 0xffc0, 0x0000, 0xfe38, {EAMA},       "CASL   R%a,R%u,%e" },
424
425 { 0x0000, 0xff00, 0x0000, 0x0000, {IV, EADA},   "OR%s   %i,%e" },
426 { 0x0200, 0xff00, 0x0000, 0x0000, {IV, EADA},   "AND%s  %i,%e" },
427 { 0x0400, 0xff00, 0x0000, 0x0000, {IV, EADA},   "SUB%s  %i,%e" },
428 { 0x0600, 0xff00, 0x0000, 0x0000, {IV, EADA},   "ADD%s  %i,%e" },
429 { 0x0a00, 0xff00, 0x0000, 0x0000, {IV, EADA},   "EOR%s  %i,%e" },
430 { 0x0c00, 0xff00, 0x0000, 0x0000, {IV, EAD},    "CMP%s  %i,%e" },
431 { 0x0e00, 0xff00, 0x0000, 0x0800, {EAMA},       "MOVES%s        %e,%r" },
432 { 0x0e00, 0xff00, 0x0800, 0x0800, {EAMA},       "MOVES%s        %r,%e" },
433
434 { 0x0108, 0xf1f8, 0x0000, 0x0000, {I16},        "MOVEPW (%i,A%y),R%x" },
435 { 0x0148, 0xf1f8, 0x0000, 0x0000, {I16},        "MOVEPL (%i,A%y),R%x" },
436 { 0x0188, 0xf1f8, 0x0000, 0x0000, {I16},        "MOVEPW R%x,(%i,A%y)" },
437 { 0x01c8, 0xf1f8, 0x0000, 0x0000, {I16},        "MOVEPL R%x,(%i,A%y)" },
438 { 0x0100, 0xf1f8, 0x0000, 0x0000, {0},          "BTSTL  R%x,R%y" },
439 { 0x0140, 0xf1f8, 0x0000, 0x0000, {0},          "BCHGL  R%x,R%y" },
440 { 0x0180, 0xf1f8, 0x0000, 0x0000, {0},          "BCLRL  R%x,R%y" },
441 { 0x01c0, 0xf1f8, 0x0000, 0x0000, {0},          "BSET   R%x,R%y" },
442
443 { 0x0100, 0xf1c0, 0x0000, 0x0000, {EAM_B},      "BTSTB  R%x,%e" },
444 { 0x0140, 0xf1c0, 0x0000, 0x0000, {EAMA},       "BCHG   R%x,%e" },
445 { 0x0180, 0xf1c0, 0x0000, 0x0000, {EAMA},       "BCLR   R%x,%e" },
446 { 0x01c0, 0xf1c0, 0x0000, 0x0000, {EAMA},       "BSET   R%x,%e" },
447 { 0,0,0,0,{0},0 },
448 };
449         /* class 1: move byte */
450 static Optable t1[] = {
451 { 0x1000, 0xf000, 0x0000, 0x0000, {EAALL_B,EADDA},"MOVB %e,%E" },
452 { 0,0,0,0,{0},0 },
453 };
454         /* class 2: move long */
455 static Optable t2[] = {
456 { 0x2040, 0xf1c0, 0x0000, 0x0000, {EAALL_L},      "MOVL %e,A%x" },
457
458 { 0x2000, 0xf000, 0x0000, 0x0000, {EAALL_L,EADDA},"MOVL %e,%E" },
459 { 0,0,0,0,{0},0 },
460 };
461         /* class 3: move word */
462 static Optable t3[] = {
463 { 0x3040, 0xf1c0, 0x0000, 0x0000, {EAALL_W},      "MOVW %e,A%x" },
464
465 { 0x3000, 0xf000, 0x0000, 0x0000, {EAALL_W,EADDA},"MOVW %e,%E" },
466 { 0,0,0,0,{0},0 },
467 };
468         /* class 4: miscellaneous */
469 static Optable t4[] = {
470 { 0x4e75, 0xffff, 0x0000, 0x0000, {STACK},      "RTS" },
471 { 0x4e77, 0xffff, 0x0000, 0x0000, {STACK},      "RTR" },
472 { 0x4afc, 0xffff, 0x0000, 0x0000, {0},          "ILLEGAL" },
473 { 0x4e71, 0xffff, 0x0000, 0x0000, {0},          "NOP" },
474 { 0x4e74, 0xffff, 0x0000, 0x0000, {I16, STACK}, "RTD    %i" },
475 { 0x4e76, 0xffff, 0x0000, 0x0000, {0},          "TRAPV" },
476 { 0x4e70, 0xffff, 0x0000, 0x0000, {0},          "RESET" },
477 { 0x4e72, 0xffff, 0x0000, 0x0000, {I16},        "STOP   %i" },
478 { 0x4e73, 0xffff, 0x0000, 0x0000, {0},          "RTE" },
479 { 0x4e7a, 0xffff, 0x0000, 0x0000, {I16},        "MOVEL  %N,%r" },
480 { 0x4e7b, 0xffff, 0x0000, 0x0000, {I16},        "MOVEL  %r,%N" },
481
482 { 0x4808, 0xfff8, 0x0000, 0x0000, {I32},        "LINKL  A%y,%i" },
483 { 0x4840, 0xfff8, 0x0000, 0x0000, {0},          "SWAPW  R%y" },
484 { 0x4848, 0xfff8, 0x0000, 0x0000, {0},          "BKPT   #%y" },
485 { 0x4880, 0xfff8, 0x0000, 0x0000, {0},          "EXTW   R%y" },
486 { 0x48C0, 0xfff8, 0x0000, 0x0000, {0},          "EXTL   R%y" },
487 { 0x49C0, 0xfff8, 0x0000, 0x0000, {0},          "EXTBL  R%y" },
488 { 0x4e50, 0xfff8, 0x0000, 0x0000, {I16},        "LINKW  A%y,%i" },
489 { 0x4e58, 0xfff8, 0x0000, 0x0000, {0},          "UNLK   A%y" },
490 { 0x4e60, 0xfff8, 0x0000, 0x0000, {0},          "MOVEL  (A%y),USP" },
491 { 0x4e68, 0xfff8, 0x0000, 0x0000, {0},          "MOVEL  USP,(A%y)" },
492
493 { 0x4e40, 0xfff0, 0x0000, 0x0000, {0},          "SYS    %f" },
494
495 { 0x40c0, 0xffc0, 0x0000, 0x0000, {EADA},       "MOVW   SR,%e" },
496 { 0x42c0, 0xffc0, 0x0000, 0x0000, {EADA},       "MOVW   CCR,%e" },
497 { 0x44c0, 0xffc0, 0x0000, 0x0000, {EADI_W},     "MOVW   %e,CCR" },
498 { 0x46c0, 0xffc0, 0x0000, 0x0000, {EADI_W},     "MOVW   %e,SR" },
499 { 0x4800, 0xffc0, 0x0000, 0x0000, {EADA},       "NBCDB  %e" },
500 { 0x4840, 0xffc0, 0x0000, 0x0000, {EAC},        "PEA    %e" },
501 { 0x4880, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEMW %i,%e" },
502 { 0x48c0, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEML %i,%e" },
503 { 0x4ac0, 0xffc0, 0x0000, 0x0000, {EADA},       "TAS    %e" },
504 { 0x4a00, 0xffc0, 0x0000, 0x0000, {EAD},        "TSTB   %e" },
505 { 0x4c00, 0xffc0, 0x0000, 0x8ff8, {EADI_L},     "MULUL  %e,%r" },
506 { 0x4c00, 0xffc0, 0x0400, 0x8ff8, {EADI_L},     "MULUL  %e,R%a:%r" },
507 { 0x4c00, 0xffc0, 0x0800, 0x8ff8, {EADI_L},     "MULSL  %e,%r" },
508 { 0x4c00, 0xffc0, 0x0c00, 0x8ff8, {EADI_L},     "MULSL  %e,R%a:%r" },
509 { 0x4c40, 0xffc0, 0x0000, 0x8ff8, {EADI_L},     "DIVUL  %e,%j" },
510 { 0x4c40, 0xffc0, 0x0400, 0x8ff8, {EADI_L},     "DIVUD  %e,%r:R%a" },
511 { 0x4c40, 0xffc0, 0x0800, 0x8ff8, {EADI_L},     "DIVSL  %e,%j" },
512 { 0x4c40, 0xffc0, 0x0c00, 0x8ff8, {EADI_L},     "DIVSD  %e,%r:R%a" },
513 { 0x4c80, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEMW %1,%i" },
514 { 0x4cc0, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEML %1,%i" },
515 { 0x4e80, 0xffc0, 0x0000, 0x0000, {BREAC},      "JSR    %e" },
516 { 0x4ec0, 0xffc0, 0x0000, 0x0000, {BREAC},      "JMP    %e" },
517
518 { 0x4000, 0xff00, 0x0000, 0x0000, {EADA},       "NEGX%s %e" },
519 { 0x4200, 0xff00, 0x0000, 0x0000, {EADA},       "CLR%s  %e" },
520 { 0x4400, 0xff00, 0x0000, 0x0000, {EADA},       "NEG%s  %e" },
521 { 0x4600, 0xff00, 0x0000, 0x0000, {EADA},       "NOT%s  %e" },
522 { 0x4a00, 0xff00, 0x0000, 0x0000, {EAALL},      "TST%s  %e" },
523
524 { 0x4180, 0xf1c0, 0x0000, 0x0000, {EADI_W},     "CHKW   %e,R%x" },
525 { 0x41c0, 0xf1c0, 0x0000, 0x0000, {EAC},        "LEA    %e,A%x" },
526 { 0x4100, 0xf1c0, 0x0000, 0x0000, {EADI_L},     "CHKL   %e,R%x" },
527 { 0,0,0,0,{0},0 },
528 };
529         /* class 5:  miscellaneous quick, branch & trap instructions */
530 static Optable t5[] = {
531 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EADA},       "ADDB   $Q#%q,%e" },
532 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EADA},       "SUBB   $Q#%q,%e" },
533
534 { 0x50c8, 0xf1f8, 0x0000, 0x0000, {BR16},       "DB%c   R%y,%t" },
535 { 0x51c8, 0xf1f8, 0x0000, 0x0000, {BR16},       "DB%c   R%y,%t" },
536
537 { 0x5000, 0xf1c0, 0x0000, 0x0000, {EAA},        "ADDB   $Q#%q,%e" },
538 { 0x5040, 0xf1c0, 0x0000, 0x0000, {EAA},        "ADDW   $Q#%q,%e" },
539 { 0x5080, 0xf1c0, 0x0000, 0x0000, {EAA},        "ADDL   $Q#%q,%e" },
540 { 0x5100, 0xf1c0, 0x0000, 0x0000, {EAA},        "SUBB   $Q#%q,%e" },
541 { 0x5140, 0xf1c0, 0x0000, 0x0000, {EAA},        "SUBW   $Q#%q,%e" },
542 { 0x5180, 0xf1c0, 0x0000, 0x0000, {EAA},        "SUBL   $Q#%q,%e" },
543
544 { 0x50fa, 0xf0ff, 0x0000, 0x0000, {I16},        "TRAP%cW        %i" },
545 { 0x50fb, 0xf0ff, 0x0000, 0x0000, {I32},        "TRAP%cL        %i" },
546 { 0x50fc, 0xf0ff, 0x0000, 0x0000, {0},          "TRAP%c" },
547
548 { 0x50c0, 0xf0c0, 0x0000, 0x0000, {EADA},       "S%c    %e" },
549 { 0,0,0,0,{0},0 },
550 };
551         /* class 6: branch instructions */
552 static Optable t6[] = {
553 { 0x6000, 0xff00, 0x0000, 0x0000, {BR8},        "BRA    %t" },
554 { 0x6100, 0xff00, 0x0000, 0x0000, {BR8},        "BSR    %t" },
555 { 0x6000, 0xf000, 0x0000, 0x0000, {BR8},        "B%c    %t" },
556 { 0,0,0,0,{0},0 },
557 };
558         /* class 7: move quick */
559 static Optable t7[] = {
560 { 0x7000, 0xf100, 0x0000, 0x0000, {OP8},        "MOVL   $Q%i,R%x" },
561 { 0,0,0,0,{0},0 },
562 };
563         /* class 8: BCD operations, DIV, and OR instructions */
564 static Optable t8[] = {
565 { 0x8100, 0xf1f8, 0x0000, 0x0000, {0},          "SBCDB  R%y,R%x" },
566 { 0x8108, 0xf1f8, 0x0000, 0x0000, {0},          "SBCDB  -(A%y),-(A%x)" },
567 { 0x8140, 0xf1f8, 0x0000, 0x0000, {I16},        "PACK   R%y,R%x,%i" },
568 { 0x8148, 0xf1f8, 0x0000, 0x0000, {I16},        "PACK   -(A%y),-(A%x),%i" },
569 { 0x8180, 0xf1f8, 0x0000, 0x0000, {I16},        "UNPK   R%y,R%x,%i" },
570 { 0x8188, 0xf1f8, 0x0000, 0x0000, {I16},        "UNPK   -(A%y),-(A%x),%i" },
571
572 { 0x80c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},     "DIVUW  %e,R%x" },
573 { 0x81c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},     "DIVSW  %e,R%x" },
574
575 { 0x8000, 0xf100, 0x0000, 0x0000, {EADI},       "OR%s   %e,R%x" },
576 { 0x8100, 0xf100, 0x0000, 0x0000, {EAMA},       "OR%s   R%x,%e" },
577 { 0,0,0,0,{0},0 },
578 };
579         /* class 9: subtract instruction */
580 static Optable t9[] = {
581 { 0x90c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W},    "SUBW   %e,A%x" },
582 { 0x91c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L},    "SUBL   %e,A%x" },
583
584 { 0x9100, 0xf138, 0x0000, 0x0000, {0},          "SUBX%s R%y,R%x" },
585 { 0x9108, 0xf138, 0x0000, 0x0000, {0},          "SUBX%s -(A%y),-(A%x)" },
586
587 { 0x9000, 0xf100, 0x0000, 0x0000, {EAALL},      "SUB%s  %e,R%x" },
588 { 0x9100, 0xf100, 0x0000, 0x0000, {EAMA},       "SUB%s  R%x,%e" },
589 { 0,0,0,0,{0},0 },
590 };
591         /* class b: CMP & EOR */
592 static Optable tb[] = {
593 { 0xb000, 0xf1c0, 0x0000, 0x0000, {EADI},       "CMPB   R%x,%e" },
594 { 0xb040, 0xf1c0, 0x0000, 0x0000, {EAALL_W},    "CMPW   R%x,%e" },
595 { 0xb080, 0xf1c0, 0x0000, 0x0000, {EAALL_L},    "CMPL   R%x,%e" },
596 { 0xb0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W},    "CMPW   A%x,%e" },
597 { 0xb1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L},    "CMPL   A%x,%e" },
598
599 { 0xb108, 0xf138, 0x0000, 0x0000, {0},          "CMP%s  (A%y)+,(A%x)+" },
600
601 { 0xb100, 0xf100, 0x0000, 0x0000, {EADA},       "EOR%s  %e,R%x" },
602 { 0,0,0,0,{0},0 },
603 };
604         /* class c: AND, MUL, BCD & Exchange */
605 static Optable tc[] = {
606 { 0xc100, 0xf1f8, 0x0000, 0x0000, {0},          "ABCDB  R%y,R%x" },
607 { 0xc108, 0xf1f8, 0x0000, 0x0000, {0},          "ABCDB  -(A%y),-(A%x)" },
608 { 0xc140, 0xf1f8, 0x0000, 0x0000, {0},          "EXG    R%x,R%y" },
609 { 0xc148, 0xf1f8, 0x0000, 0x0000, {0},          "EXG    A%x,A%y" },
610 { 0xc188, 0xf1f8, 0x0000, 0x0000, {0},          "EXG    R%x,A%y" },
611
612 { 0xc0c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},     "MULUW  %e,R%x" },
613 { 0xc1c0, 0xf1c0, 0x0000, 0x0000, {EADI_W},     "MULSW  %e,R%x" },
614
615 { 0xc000, 0xf100, 0x0000, 0x0000, {EADI},       "AND%s  %e,R%x" },
616 { 0xc100, 0xf100, 0x0000, 0x0000, {EAMA},       "AND%s  R%x,%e" },
617 { 0,0,0,0,{0},0 },
618 };
619         /* class d: addition  */
620 static Optable td[] = {
621 { 0xd000, 0xf1c0, 0x0000, 0x0000, {EADI},       "ADDB   %e,R%x" },
622 { 0xd0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W},    "ADDW   %e,A%x" },
623 { 0xd1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L},    "ADDL   %e,A%x" },
624
625 { 0xd100, 0xf138, 0x0000, 0x0000, {0},          "ADDX%s R%y,R%x" },
626 { 0xd108, 0xf138, 0x0000, 0x0000, {0},          "ADDX%s -(A%y),-(A%x)" },
627
628 { 0xd000, 0xf100, 0x0000, 0x0000, {EAALL},      "ADD%s  %e,R%x" },
629 { 0xd100, 0xf100, 0x0000, 0x0000, {EAMA},       "ADD%s  R%x,%e" },
630 { 0,0,0,0,{0},0 },
631 };
632         /* class e: shift, rotate, bit field operations */
633 static Optable te[] = {
634 { 0xe8c0, 0xffc0, 0x0820, 0xfe38, {EACD},       "BFTST  %e{R%u:R%a}" },
635 { 0xe8c0, 0xffc0, 0x0800, 0xfe20, {EACD},       "BFTST  %e{R%u:%w}" },
636 { 0xe8c0, 0xffc0, 0x0020, 0xf838, {EACD},       "BFTST  %e{%o:R%a}" },
637 { 0xe8c0, 0xffc0, 0x0000, 0xf820, {EACD},       "BFTST  %e{%o:%w}" },
638
639 { 0xe9c0, 0xffc0, 0x0820, 0x8e38, {EACD},       "BFEXTU %e{R%u:R%a},%r" },
640 { 0xe9c0, 0xffc0, 0x0800, 0x8e20, {EACD},       "BFEXTU %e{R%u:%w},%r" },
641 { 0xe9c0, 0xffc0, 0x0020, 0x8838, {EACD},       "BFEXTU %e{%o:R%a},%r" },
642 { 0xe9c0, 0xffc0, 0x0000, 0x8820, {EACD},       "BFEXTU %e{%o:%w},%r" },
643
644 { 0xeac0, 0xffc0, 0x0820, 0xfe38, {EACAD},      "BFCHG  %e{R%u:R%a}" },
645 { 0xeac0, 0xffc0, 0x0800, 0xfe20, {EACAD},      "BFCHG  %e{R%u:%w}" },
646 { 0xeac0, 0xffc0, 0x0020, 0xf838, {EACAD},      "BFCHG  %e{%o:R%a}" },
647 { 0xeac0, 0xffc0, 0x0000, 0xf820, {EACAD},      "BFCHG  %e{%o:%w}" },
648
649 { 0xebc0, 0xffc0, 0x0820, 0x8e38, {EACD},       "BFEXTS %e{R%u:R%a},%r" },
650 { 0xebc0, 0xffc0, 0x0800, 0x8e20, {EACD},       "BFEXTS %e{R%u:%w},%r" },
651 { 0xebc0, 0xffc0, 0x0020, 0x8838, {EACD},       "BFEXTS %e{%o:R%a},%r" },
652 { 0xebc0, 0xffc0, 0x0000, 0x8820, {EACD},       "BFEXTS %e{%o:%w},%r" },
653
654 { 0xecc0, 0xffc0, 0x0820, 0xfe38, {EACAD},      "BFCLR  %e{R%u:R%a}" },
655 { 0xecc0, 0xffc0, 0x0800, 0xfe20, {EACAD},      "BFCLR  %e{R%u:%w}" },
656 { 0xecc0, 0xffc0, 0x0020, 0xf838, {EACAD},      "BFCLR  %e{%o:R%a}" },
657 { 0xecc0, 0xffc0, 0x0000, 0xf820, {EACAD},      "BFCLR  %e{%o:%w}" },
658
659 { 0xedc0, 0xffc0, 0x0820, 0x8e38, {EACAD},      "BFFFO  %e{R%u:R%a},%r" },
660 { 0xedc0, 0xffc0, 0x0800, 0x8e20, {EACAD},      "BFFFO  %e{R%u:%w},%r" },
661 { 0xedc0, 0xffc0, 0x0020, 0x8838, {EACAD},      "BFFFO  %e{%o:R%a},%r" },
662 { 0xedc0, 0xffc0, 0x0000, 0x8820, {EACAD},      "BFFFO  %e{%o:%w},%r" },
663
664 { 0xeec0, 0xffc0, 0x0820, 0xfe38, {EACAD},      "BFSET  %e{R%u:R%a}" },
665 { 0xeec0, 0xffc0, 0x0800, 0xfe20, {EACAD},      "BFSET  %e{R%u:%w}" },
666 { 0xeec0, 0xffc0, 0x0020, 0xf838, {EACAD},      "BFSET  %e{%o:R%a}" },
667 { 0xeec0, 0xffc0, 0x0000, 0xf820, {EACAD},      "BFSET  %e{%o:%w}" },
668
669 { 0xefc0, 0xffc0, 0x0820, 0x8e38, {EACAD},      "BFINS  %r,%e{R%u:R%a}" },
670 { 0xefc0, 0xffc0, 0x0800, 0x8e20, {EACAD},      "BFINS  %r,%e{R%u:%w}" },
671 { 0xefc0, 0xffc0, 0x0020, 0x8838, {EACAD},      "BFINS  %r,%e{%o:R%a}" },
672 { 0xefc0, 0xffc0, 0x0000, 0x8820, {EACAD},      "BFINS  %r,%e{%o:%w}" },
673
674 { 0xe0c0, 0xfec0, 0x0000, 0x0000, {EAMA},       "AS%dW  %e" },
675 { 0xe2c0, 0xfec0, 0x0000, 0x0000, {EAMA},       "LS%dW  %e" },
676 { 0xe4c0, 0xfec0, 0x0000, 0x0000, {EAMA},       "ROX%dW %e" },
677 { 0xe6c0, 0xfec0, 0x0000, 0x0000, {EAMA},       "RO%dW  %e" },
678
679 { 0xe000, 0xf038, 0x0000, 0x0000, {0},          "AS%d%s #%q,R%y" },
680 { 0xe008, 0xf038, 0x0000, 0x0000, {0},          "LS%d%s #%q,R%y" },
681 { 0xe010, 0xf038, 0x0000, 0x0000, {0},          "ROX%d%s        #%q,R%y" },
682 { 0xe018, 0xf038, 0x0000, 0x0000, {0},          "RO%d%s #%q,R%y" },
683 { 0xe020, 0xf038, 0x0000, 0x0000, {0},          "AS%d%s R%x,R%y" },
684 { 0xe028, 0xf038, 0x0000, 0x0000, {0},          "LS%d%s R%x,R%y" },
685 { 0xe030, 0xf038, 0x0000, 0x0000, {0},          "ROX%d%s        R%x,R%y" },
686 { 0xe038, 0xf038, 0x0000, 0x0000, {0},          "RO%d%s R%x,R%y" },
687 { 0,0,0,0,{0},0 },
688 };
689         /* class f: coprocessor and mmu instructions */
690 static Optable tf[] = {
691 { 0xf280, 0xffff, 0x0000, 0xffff, {0},          "FNOP" },
692 { 0xf200, 0xffff, 0x5c00, 0xfc00, {0},          "FMOVECRX       %k,F%D" },
693 { 0xf27a, 0xffff, 0x0000, 0xffc0, {I16},        "FTRAP%P        %i" },
694 { 0xf27b, 0xffff, 0x0000, 0xffc0, {I32},        "FTRAP%P        %i" },
695 { 0xf27c, 0xffff, 0x0000, 0xffc0, {0},          "FTRAP%P" },
696
697 { 0xf248, 0xfff8, 0x0000, 0xffc0, {BR16},       "FDB%P  R%y,%t" },
698 { 0xf620, 0xfff8, 0x8000, 0x8fff, {0},          "MOVE16 (A%y)+,(%r)+" },
699 { 0xf500, 0xfff8, 0x0000, 0x0000, {0},          "PFLUSHN        (A%y)" },
700 { 0xf508, 0xfff8, 0x0000, 0x0000, {0},          "PFLUSH (A%y)" },
701 { 0xf510, 0xfff8, 0x0000, 0x0000, {0},          "PFLUSHAN" },
702 { 0xf518, 0xfff8, 0x0000, 0x0000, {0},          "PFLUSHA" },
703 { 0xf548, 0xfff8, 0x0000, 0x0000, {0},          "PTESTW (A%y)" },
704 { 0xf568, 0xfff8, 0x0000, 0x0000, {0},          "PTESTR (A%y)" },
705 { 0xf600, 0xfff8, 0x0000, 0x0000, {I32},        "MOVE16 (A%y)+,$%i" },
706 { 0xf608, 0xfff8, 0x0000, 0x0000, {I32},        "MOVE16 $%i,(A%y)-" },
707 { 0xf610, 0xfff8, 0x0000, 0x0000, {I32},        "MOVE16 (A%y),$%i" },
708 { 0xf618, 0xfff8, 0x0000, 0x0000, {I32},        "MOVE16 $%i,(A%y)" },
709
710 { 0xf000, 0xffc0, 0x0800, 0xffff, {EACA},       "PMOVE  %e,TT0" },
711 { 0xf000, 0xffc0, 0x0900, 0xffff, {EACA},       "PMOVEFD        %e,TT0" },
712 { 0xf000, 0xffc0, 0x0a00, 0xffff, {EACA},       "PMOVE  TT0,%e" },
713 { 0xf000, 0xffc0, 0x0b00, 0xffff, {EACA},       "PMOVEFD        TT0,%e" },
714 { 0xf000, 0xffc0, 0x0c00, 0xffff, {EACA},       "PMOVE  %e,TT1" },
715 { 0xf000, 0xffc0, 0x0d00, 0xffff, {EACA},       "PMOVEFD        %e,TT1" },
716 { 0xf000, 0xffc0, 0x0e00, 0xffff, {EACA},       "PMOVE  TT1,%e" },
717 { 0xf000, 0xffc0, 0x0f00, 0xffff, {EACA},       "PMOVEFD        TT1,%e" },
718 { 0xf000, 0xffc0, 0x2400, 0xffff, {0},          "PFLUSHA" },
719 { 0xf000, 0xffc0, 0x2800, 0xffff, {EACA},       "PVALID VAL,%e" },
720 { 0xf000, 0xffc0, 0x6000, 0xffff, {EACA},       "PMOVE  %e,MMUSR" },
721 { 0xf000, 0xffc0, 0x6200, 0xffff, {EACA},       "PMOVE  MMUSR,%e" },
722 { 0xf000, 0xffc0, 0x2800, 0xfff8, {EACA},       "PVALID A%a,%e" },
723 { 0xf000, 0xffc0, 0x2000, 0xffe0, {EACA},       "PLOADW %L,%e" },
724 { 0xf000, 0xffc0, 0x2200, 0xffe0, {EACA},       "PLOADR %L,%e" },
725 { 0xf000, 0xffc0, 0x8000, 0xffe0, {EACA},       "PTESTW %L,%e,#0" },
726 { 0xf000, 0xffc0, 0x8200, 0xffe0, {EACA},       "PTESTR %L,%e,#0" },
727 { 0xf000, 0xffc0, 0x3000, 0xfe00, {0},          "PFLUSH %L,#%I" },
728 { 0xf000, 0xffc0, 0x3800, 0xfe00, {EACA},       "PFLUSH %L,#%I,%e" },
729 { 0xf000, 0xffc0, 0x8000, 0xe300, {EACA},       "PTESTW %L,%e,#%Z" },
730 { 0xf000, 0xffc0, 0x8100, 0xe300, {EACA},       "PTESTW %L,%e,#%Z,A%h" },
731 { 0xf000, 0xffc0, 0x8200, 0xe300, {EACA},       "PTESTR %L,%e,#%Z" },
732 { 0xf000, 0xffc0, 0x8300, 0xe300, {EACA},       "PTESTR %L,%e,#%Z,A%h" },
733 { 0xf000, 0xffc0, 0x4000, 0xc3ff, {EACA},       "PMOVE  %e,%H" },
734 { 0xf000, 0xffc0, 0x4100, 0xc3ff, {EACA},       "PMOVEFD        %e,%H" },
735 { 0xf000, 0xffc0, 0x4200, 0xc3ff, {EACA},       "PMOVE  %H,%e" },
736
737         /* floating point (coprocessor 1)*/
738
739 { 0xf200, 0xffc0, 0x8400, 0xffff, {EAALL_L},    "FMOVEL %e,FPIAR" },
740 { 0xf200, 0xffc0, 0x8800, 0xffff, {EADI_L},     "FMOVEL %e,FPSR" },
741 { 0xf200, 0xffc0, 0x9000, 0xffff, {EADI_L},     "FMOVEL %e,FPCR" },
742 { 0xf200, 0xffc0, 0xa400, 0xffff, {EAA},        "FMOVEL FPIAR,%e" },
743 { 0xf200, 0xffc0, 0xa800, 0xffff, {EADA},       "FMOVEL FPSR,%e" },
744 { 0xf200, 0xffc0, 0xb000, 0xffff, {EADA},       "FMOVEL FPCR,%e" },
745
746 { 0xf240, 0xffc0, 0x0000, 0xffc0, {EADA},       "FS%P   %e" },
747
748 { 0xf200, 0xffc0, 0xd000, 0xff00, {EACPI},      "FMOVEMX        %e,%m" },
749 { 0xf200, 0xffc0, 0xd800, 0xff00, {EACPI},      "FMOVEMX        %e,R%K" },
750 { 0xf200, 0xffc0, 0xe000, 0xff00, {EAPI},       "FMOVEMX        %m,-(A%y)" },
751 { 0xf200, 0xffc0, 0xe800, 0xff00, {EAPI},       "FMOVEMX        R%K,-(A%y)" },
752 { 0xf200, 0xffc0, 0xf000, 0xff00, {EACAPD},     "FMOVEMX        %m,%e" },
753 { 0xf200, 0xffc0, 0xf800, 0xff00, {EACAPD},     "FMOVEMX        R%K,%e" },
754
755 { 0xf200, 0xffc0, 0x6800, 0xfc00, {EAMA},       "FMOVEX F%D,%e" },
756 { 0xf200, 0xffc0, 0x6c00, 0xfc00, {EAMA},       "FMOVEP F%D,%e,{%k}" },
757 { 0xf200, 0xffc0, 0x7400, 0xfc00, {EAMA},       "FMOVED F%D,%e" },
758 { 0xf200, 0xffc0, 0x7c00, 0xfc00, {EAMA},       "FMOVEP F%D,%e,{R%K}" },
759
760 { 0xf200, 0xffc0, 0x8000, 0xe3ff, {EAM},        "FMOVEML        #%B,%e" },
761 { 0xf200, 0xffc0, 0xa000, 0xe3ff, {EAMA},       "FMOVEML        %e,#%B" },
762
763 { 0xf200, 0xffc0, 0x0000, 0xe07f, {0},          "FMOVE  F%B,F%D" },
764 { 0xf200, 0xffc0, 0x0001, 0xe07f, {0},          "FINTX  %F" },
765 { 0xf200, 0xffc0, 0x0002, 0xe07f, {0},          "FSINHX %F" },
766 { 0xf200, 0xffc0, 0x0003, 0xe07f, {0},          "FINTRZ %F" },
767 { 0xf200, 0xffc0, 0x0004, 0xe07f, {0},          "FSQRTX %F" },
768 { 0xf200, 0xffc0, 0x0006, 0xe07f, {0},          "FLOGNP1X       %F" },
769 { 0xf200, 0xffc0, 0x0009, 0xe07f, {0},          "FTANHX %F" },
770 { 0xf200, 0xffc0, 0x000a, 0xe07f, {0},          "FATANX %F" },
771 { 0xf200, 0xffc0, 0x000c, 0xe07f, {0},          "FASINX %F" },
772 { 0xf200, 0xffc0, 0x000d, 0xe07f, {0},          "FATANHX        %F" },
773 { 0xf200, 0xffc0, 0x000e, 0xe07f, {0},          "FSINX  %F" },
774 { 0xf200, 0xffc0, 0x000f, 0xe07f, {0},          "FTANX  %F" },
775 { 0xf200, 0xffc0, 0x0010, 0xe07f, {0},          "FETOXX %F" },
776 { 0xf200, 0xffc0, 0x0011, 0xe07f, {0},          "FTWOTOXX       %F" },
777 { 0xf200, 0xffc0, 0x0012, 0xe07f, {0},          "FTENTOXX       %F" },
778 { 0xf200, 0xffc0, 0x0014, 0xe07f, {0},          "FLOGNX %F" },
779 { 0xf200, 0xffc0, 0x0015, 0xe07f, {0},          "FLOG10X        %F" },
780 { 0xf200, 0xffc0, 0x0016, 0xe07f, {0},          "FLOG2X %F" },
781 { 0xf200, 0xffc0, 0x0018, 0xe07f, {0},          "FABSX  %F" },
782 { 0xf200, 0xffc0, 0x0019, 0xe07f, {0},          "FCOSHX %F" },
783 { 0xf200, 0xffc0, 0x001a, 0xe07f, {0},          "FNEGX  %F" },
784 { 0xf200, 0xffc0, 0x001c, 0xe07f, {0},          "FACOSX %F" },
785 { 0xf200, 0xffc0, 0x001d, 0xe07f, {0},          "FCOSX  %F" },
786 { 0xf200, 0xffc0, 0x001e, 0xe07f, {0},          "FGETEXPX       %F" },
787 { 0xf200, 0xffc0, 0x001f, 0xe07f, {0},          "FGETMANX       %F" },
788 { 0xf200, 0xffc0, 0x0020, 0xe07f, {0},          "FDIVX  F%B,F%D" },
789 { 0xf200, 0xffc0, 0x0021, 0xe07f, {0},          "FMODX  F%B,F%D" },
790 { 0xf200, 0xffc0, 0x0022, 0xe07f, {0},          "FADDX  F%B,F%D" },
791 { 0xf200, 0xffc0, 0x0023, 0xe07f, {0},          "FMULX  F%B,F%D" },
792 { 0xf200, 0xffc0, 0x0024, 0xe07f, {0},          "FSGLDIVX       F%B,F%D" },
793 { 0xf200, 0xffc0, 0x0025, 0xe07f, {0},          "FREMX  F%B,F%D" },
794 { 0xf200, 0xffc0, 0x0026, 0xe07f, {0},          "FSCALEX        F%B,F%D" },
795 { 0xf200, 0xffc0, 0x0027, 0xe07f, {0},          "FSGLMULX       F%B,F%D" },
796 { 0xf200, 0xffc0, 0x0028, 0xe07f, {0},          "FSUBX  F%B,F%D" },
797 { 0xf200, 0xffc0, 0x0038, 0xe07f, {0},          "FCMPX  F%B,F%D" },
798 { 0xf200, 0xffc0, 0x003a, 0xe07f, {0},          "FTSTX  F%B" },
799 { 0xf200, 0xffc0, 0x0040, 0xe07f, {0},          "FSMOVE F%B,F%D" },
800 { 0xf200, 0xffc0, 0x0041, 0xe07f, {0},          "FSSQRTX        %F"},
801 { 0xf200, 0xffc0, 0x0044, 0xe07f, {0},          "FDMOVE F%B,F%D" },
802 { 0xf200, 0xffc0, 0x0045, 0xe07f, {0},          "FDSQRTX        %F" },
803 { 0xf200, 0xffc0, 0x0058, 0xe07f, {0},          "FSABSX %F" },
804 { 0xf200, 0xffc0, 0x005a, 0xe07f, {0},          "FSNEGX %F" },
805 { 0xf200, 0xffc0, 0x005c, 0xe07f, {0},          "FDABSX %F" },
806 { 0xf200, 0xffc0, 0x005e, 0xe07f, {0},          "FDNEGX %F" },
807 { 0xf200, 0xffc0, 0x0060, 0xe07f, {0},          "FSDIVX F%B,F%D" },
808 { 0xf200, 0xffc0, 0x0062, 0xe07f, {0},          "FSADDX F%B,F%D" },
809 { 0xf200, 0xffc0, 0x0063, 0xe07f, {0},          "FSMULX F%B,F%D" },
810 { 0xf200, 0xffc0, 0x0064, 0xe07f, {0},          "FDDIVX F%B,F%D" },
811 { 0xf200, 0xffc0, 0x0066, 0xe07f, {0},          "FDADDX F%B,F%D" },
812 { 0xf200, 0xffc0, 0x0067, 0xe07f, {0},          "FDMULX F%B,F%D" },
813 { 0xf200, 0xffc0, 0x0068, 0xe07f, {0},          "FSSUBX F%B,F%D" },
814 { 0xf200, 0xffc0, 0x006c, 0xe07f, {0},          "FDSUBX F%B,F%D" },
815 { 0xf200, 0xffc0, 0x4000, 0xe07f, {EAFLT},      "FMOVE%S        %e,F%D" },
816 { 0xf200, 0xffc0, 0x4001, 0xe07f, {EAFLT},      "FINT%S %e,F%D" },
817 { 0xf200, 0xffc0, 0x4002, 0xe07f, {EAFLT},      "FSINH%S        %e,F%D" },
818 { 0xf200, 0xffc0, 0x4003, 0xe07f, {EAFLT},      "FINTRZ%S       %e,F%D" },
819 { 0xf200, 0xffc0, 0x4004, 0xe07f, {EAFLT},      "FSQRT%S        %e,F%D" },
820 { 0xf200, 0xffc0, 0x4006, 0xe07f, {EAFLT},      "FLOGNP1%S      %e,F%D" },
821 { 0xf200, 0xffc0, 0x4009, 0xe07f, {EAFLT},      "FTANH%S        %e,F%D" },
822 { 0xf200, 0xffc0, 0x400a, 0xe07f, {EAFLT},      "FATAN%S        %e,F%D" },
823 { 0xf200, 0xffc0, 0x400c, 0xe07f, {EAFLT},      "FASIN%S        %e,F%D" },
824 { 0xf200, 0xffc0, 0x400d, 0xe07f, {EAFLT},      "FATANH%S       %e,F%D" },
825 { 0xf200, 0xffc0, 0x400e, 0xe07f, {EAFLT},      "FSIN%S %e,F%D" },
826 { 0xf200, 0xffc0, 0x400f, 0xe07f, {EAFLT},      "FTAN%S %e,F%D" },
827 { 0xf200, 0xffc0, 0x4010, 0xe07f, {EAFLT},      "FETOX%S        %e,F%D" },
828 { 0xf200, 0xffc0, 0x4011, 0xe07f, {EAFLT},      "FTWOTOX%S      %e,F%D" },
829 { 0xf200, 0xffc0, 0x4012, 0xe07f, {EAFLT},      "FTENTOX%S      %e,F%D" },
830 { 0xf200, 0xffc0, 0x4014, 0xe07f, {EAFLT},      "FLOGN%S        %e,F%D" },
831 { 0xf200, 0xffc0, 0x4015, 0xe07f, {EAFLT},      "FLOG10%S       %e,F%D" },
832 { 0xf200, 0xffc0, 0x4016, 0xe07f, {EAFLT},      "FLOG2%S        %e,F%D" },
833 { 0xf200, 0xffc0, 0x4018, 0xe07f, {EAFLT},      "FABS%S %e,F%D" },
834 { 0xf200, 0xffc0, 0x4019, 0xe07f, {EAFLT},      "FCOSH%S        %e,F%D" },
835 { 0xf200, 0xffc0, 0x401a, 0xe07f, {EAFLT},      "FNEG%S %e,F%D" },
836 { 0xf200, 0xffc0, 0x401c, 0xe07f, {EAFLT},      "FACOS%S        %e,F%D" },
837 { 0xf200, 0xffc0, 0x401d, 0xe07f, {EAFLT},      "FCOS%S %e,F%D" },
838 { 0xf200, 0xffc0, 0x401e, 0xe07f, {EAFLT},      "FGETEXP%S      %e,F%D" },
839 { 0xf200, 0xffc0, 0x401f, 0xe07f, {EAFLT},      "FGETMAN%S      %e,F%D" },
840 { 0xf200, 0xffc0, 0x4020, 0xe07f, {EAFLT},      "FDIV%S %e,F%D" },
841 { 0xf200, 0xffc0, 0x4021, 0xe07f, {EAFLT},      "FMOD%S %e,F%D" },
842 { 0xf200, 0xffc0, 0x4022, 0xe07f, {EAFLT},      "FADD%S %e,F%D" },
843 { 0xf200, 0xffc0, 0x4023, 0xe07f, {EAFLT},      "FMUL%S %e,F%D" },
844 { 0xf200, 0xffc0, 0x4024, 0xe07f, {EAFLT},      "FSGLDIV%S      %e,F%D" },
845 { 0xf200, 0xffc0, 0x4025, 0xe07f, {EAFLT},      "FREM%S %e,F%D" },
846 { 0xf200, 0xffc0, 0x4026, 0xe07f, {EAFLT},      "FSCALE%S       %e,F%D" },
847 { 0xf200, 0xffc0, 0x4027, 0xe07f, {EAFLT},      "FSGLMUL%S      %e,F%D" },
848 { 0xf200, 0xffc0, 0x4028, 0xe07f, {EAFLT},      "FSUB%S %e,F%D" },
849 { 0xf200, 0xffc0, 0x4038, 0xe07f, {EAFLT},      "FCMP%S %e,F%D" },
850 { 0xf200, 0xffc0, 0x403a, 0xe07f, {EAFLT},      "FTST%S %e" },
851 { 0xf200, 0xffc0, 0x4040, 0xe07f, {EAFLT},      "FSMOVE%S       %e,F%D" },
852 { 0xf200, 0xffc0, 0x4041, 0xe07f, {EAFLT},      "FSSQRT%S       %e,F%D" },
853 { 0xf200, 0xffc0, 0x4044, 0xe07f, {EAFLT},      "FDMOVE%S       %e,F%D" },
854 { 0xf200, 0xffc0, 0x4045, 0xe07f, {EAFLT},      "FDSQRT%S       %e,F%D" },
855 { 0xf200, 0xffc0, 0x4058, 0xe07f, {EAFLT},      "FSABS%S        %e,F%D" },
856 { 0xf200, 0xffc0, 0x405a, 0xe07f, {EAFLT},      "FSNEG%S        %e,F%D" },
857 { 0xf200, 0xffc0, 0x405c, 0xe07f, {EAFLT},      "FDABS%S        %e,F%D" },
858 { 0xf200, 0xffc0, 0x405e, 0xe07f, {EAFLT},      "FDNEG%S        %e,F%D" },
859 { 0xf200, 0xffc0, 0x4060, 0xe07f, {EAFLT},      "FSDIV%S        %e,F%D" },
860 { 0xf200, 0xffc0, 0x4062, 0xe07f, {EAFLT},      "FSADD%S        %e,F%D" },
861 { 0xf200, 0xffc0, 0x4063, 0xe07f, {EAFLT},      "FSMUL%S        %e,F%D" },
862 { 0xf200, 0xffc0, 0x4064, 0xe07f, {EAFLT},      "FDDIV%S        %e,F%D" },
863 { 0xf200, 0xffc0, 0x4066, 0xe07f, {EAFLT},      "FDADD%S        %e,F%D" },
864 { 0xf200, 0xffc0, 0x4067, 0xe07f, {EAFLT},      "FDMUL%S        %e,F%D" },
865 { 0xf200, 0xffc0, 0x4068, 0xe07f, {EAFLT},      "FSSUB%S        %e,F%D" },
866 { 0xf200, 0xffc0, 0x406c, 0xe07f, {EAFLT},      "FDSUB%S        %e,F%D" },
867
868 { 0xf200, 0xffc0, 0x0030, 0xe078, {0},          "FSINCOSX       F%B,F%a:F%D" },
869 { 0xf200, 0xffc0, 0x4030, 0xe078, {EAFLT},      "FSINCOS%S      %e,F%a:F%D" },
870
871 { 0xf200, 0xffc0, 0x6000, 0xe000, {EADA},       "FMOVE%S        F%D,%e" },
872
873 { 0xf300, 0xffc0, 0x0000, 0x0000, {EACAPD},     "FSAVE  %e" },
874 { 0xf340, 0xffc0, 0x0000, 0x0000, {EACAPI},     "FRESTORE       %e" },
875
876 { 0xf280, 0xffc0, 0x0000, 0x0000, {BR16},       "FB%p   %t" },
877 { 0xf2c0, 0xffc0, 0x0000, 0x0000, {BR32},       "FB%p   %t" },
878
879 { 0xf408, 0xff38, 0x0000, 0x0000, {0},          "CINVL  %C,(A%y)" },
880 { 0xf410, 0xff38, 0x0000, 0x0000, {0},          "CINVP  %C,(A%y)" },
881 { 0xf418, 0xff38, 0x0000, 0x0000, {0},          "CINVA  %C" },
882 { 0xf428, 0xff38, 0x0000, 0x0000, {0},          "CPUSHL %C,(A%y)" },
883 { 0xf430, 0xff38, 0x0000, 0x0000, {0},          "CPUSHP %C,(A%y)" },
884 { 0xf438, 0xff38, 0x0000, 0x0000, {0},          "CPUSHA %C" },
885 { 0,0,0,0,{0},0 },
886 };
887
888 static Optable  *optables[] =
889 {
890         t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, 0, tb, tc, td, te, tf,
891 };
892
893 static  Map     *mymap;
894
895 static int
896 dumpinst(Inst *ip, char *buf, int n)
897 {
898         int i;
899
900         if (n <= 0)
901                 return 0;
902
903         *buf++ = '#';
904         for (i = 0; i < ip->n && i*4+1 < n-4; i++, buf += 4)
905                 _hexify(buf, ip->raw[i], 3);
906         *buf = 0;
907         return i*4+1;
908 }
909
910 static int
911 getword(Inst *ip, uvlong offset)
912 {
913         if (ip->n < nelem(ip->raw)) {
914                 if (get2(mymap, offset, &ip->raw[ip->n++]) > 0)
915                         return 1;
916                 werrstr("can't read instruction: %r");
917         } else
918                 werrstr("instruction too big: %r");
919         return -1;
920 }
921
922 static int
923 getshorts(Inst *ip, void *where, int n)
924 {
925         if (ip->n+n < nelem(ip->raw)) {
926                 if (get1(mymap, ip->addr+ip->n*2, (uchar*)&ip->raw[ip->n], n*2) < 0) {
927                         werrstr("can't read instruction: %r");
928                         return 0;
929                 }
930                 memmove(where, &ip->raw[ip->n], n*2);
931                 ip->n += n;
932                 return 1;
933         }
934         werrstr("instruction too big: %r");
935         return 0;
936 }
937
938 static int
939 i8(Inst *ip, long *l)
940 {
941         if (getword(ip, ip->addr+ip->n*2) < 0)
942                 return -1;
943         *l = ip->raw[ip->n-1]&0xff;
944         if (*l&0x80)
945                 *l |= ~0xff;
946         return 1;
947 }
948
949 static int
950 i16(Inst *ip, long *l)
951 {
952         if (getword(ip, ip->addr+ip->n*2) < 0)
953                 return -1;
954         *l = ip->raw[ip->n-1];
955         if (*l&0x8000)
956                 *l |= ~0xffff;
957         return 1;
958 }
959 static int
960 i32(Inst *ip, long *l)
961 {
962         if (getword(ip, ip->addr+ip->n*2) < 0)
963                 return -1;
964         if (getword(ip, ip->addr+ip->n*2) < 0)
965                 return -1;
966         *l = (ip->raw[ip->n-2]<<16)|ip->raw[ip->n-1];
967         return 1;
968 }
969
970 static int
971 getimm(Inst *ip, Operand *ap, int mode)
972 {
973         ap->eatype = IMM;
974         switch(mode)
975         {
976         case EAM_B:     /* byte */
977         case EAALL_B:
978                 return i8(ip, &ap->immediate);
979         case EADI_W:    /* word */
980         case EAALL_W:
981                 return i16(ip, &ap->immediate);
982         case EADI_L:    /* long */
983         case EAALL_L:
984                 return i32(ip, &ap->immediate);
985         case EAFLT:     /* floating point - size in bits 10-12 or word 1 */
986                 switch((ip->raw[1]>>10)&0x07)
987                 {
988                 case 0: /* long integer */
989                         return i32(ip, &ap->immediate);
990                 case 1: /* single precision real */
991                         ap->eatype = IREAL;
992                         return getshorts(ip, ap->floater, 2);
993                 case 2: /* extended precision real - not supported */
994                         ap->eatype = IEXT;
995                         return getshorts(ip, ap->floater, 6);
996                 case 3: /* packed decimal real - not supported */
997                         ap->eatype = IPACK;
998                         return getshorts(ip, ap->floater, 12);
999                 case 4: /* integer word */
1000                         return i16(ip, &ap->immediate);
1001                 case 5: /* double precision real */
1002                         ap->eatype = IDBL;
1003                         return getshorts(ip, ap->floater, 4);
1004                 case 6: /* integer byte */
1005                         return i8(ip, &ap->immediate);
1006                 default:
1007                         ip->errmsg = "bad immediate float data";
1008                         return -1;
1009                 }
1010                 /* not reached */
1011         case IV:        /* size encoded in bits 6&7 of opcode word */
1012         default:
1013                 switch((ip->raw[0]>>6)&0x03)
1014                 {
1015                 case 0x00:      /* integer byte */
1016                         return i8(ip, &ap->immediate);
1017                 case 0x01:      /* integer word */
1018                         return i16(ip, &ap->immediate);
1019                 case 0x02:      /* integer long */
1020                         return i32(ip, &ap->immediate);
1021                 default:
1022                         ip->errmsg = "bad immediate size";
1023                         return -1;
1024                 }
1025                 /* not reached */
1026         }
1027 }
1028
1029 static int
1030 getdisp(Inst *ip, Operand *ap)
1031 {
1032         short ext;
1033
1034         if (getword(ip, ip->addr+ip->n*2) < 0)
1035                 return -1;
1036         ext = ip->raw[ip->n-1];
1037         ap->ext = ext;
1038         if ((ext&0x100) == 0) {         /* indexed with 7-bit displacement */
1039                 ap->disp = ext&0x7f;
1040                 if (ap->disp&0x40)
1041                         ap->disp |= ~0x7f;
1042                 return 1;
1043         }
1044         switch(ext&0x30)        /* first (inner) displacement  */
1045         {
1046         case 0x10:
1047                 break;
1048         case 0x20:
1049                 if (i16(ip, &ap->disp) < 0)
1050                         return -1;
1051                 break;
1052         case 0x30:
1053                 if (i32(ip, &ap->disp) < 0)
1054                         return -1;
1055                 break;
1056         default:
1057                 ip->errmsg = "bad EA displacement";
1058                 return -1;
1059         }
1060         switch (ext&0x03)       /* outer displacement */
1061         {
1062         case 0x02:              /* 16 bit displacement */
1063                 return i16(ip, &ap->outer);
1064         case 0x03:              /* 32 bit displacement */
1065                 return i32(ip, &ap->outer);
1066         default:
1067                 break;
1068         }
1069         return 1;
1070 }
1071
1072 static int
1073 ea(Inst *ip, int ea, Operand *ap, int mode)
1074 {
1075         int type, size;
1076
1077         type = 0;
1078         ap->ext = 0;
1079         switch((ea>>3)&0x07)
1080         {
1081         case 0x00:
1082                 ap->eatype = Dreg;
1083                 type = Dn;
1084                 break;
1085         case 0x01:
1086                 ap->eatype = Areg;
1087                 type = An;
1088                 break;
1089         case 0x02:
1090                 ap->eatype = AInd;
1091                 type = Ind;
1092                 break;
1093         case 0x03:
1094                 ap->eatype = APinc;
1095                 type = Pinc;
1096                 break;
1097         case 0x04:
1098                 ap->eatype = APdec;
1099                 type = Pdec;
1100                 break;
1101         case 0x05:
1102                 ap->eatype = ADisp;
1103                 type = Bdisp;
1104                 if (i16(ip, &ap->disp) < 0)
1105                         return -1;
1106                 break;
1107         case 0x06:
1108                 ap->eatype = BXD;
1109                 type = Bdisp;
1110                 if (getdisp(ip, ap) < 0)
1111                         return -1;
1112                 break;
1113         case 0x07:
1114                 switch(ea&0x07)
1115                 {
1116                 case 0x00:
1117                         type = Abs;
1118                         ap->eatype = ABS;
1119                         if (i16(ip, &ap->immediate) < 0)
1120                                 return -1;
1121                         break;
1122                 case 0x01:
1123                         type = Abs;
1124                         ap->eatype = ABS;
1125                         if (i32(ip, &ap->immediate) < 0)
1126                                 return -1;
1127                         break;
1128                 case 0x02:
1129                         type = PCrel;
1130                         ap->eatype = PDisp;
1131                         if (i16(ip, &ap->disp) < 0)
1132                                 return -1;
1133                         break;
1134                 case 0x03:
1135                         type = PCrel;
1136                         ap->eatype = PXD;
1137                         if (getdisp(ip, ap) < 0)
1138                                 return -1;
1139                         break;
1140                 case 0x04:
1141                         type = Imm;
1142                         if (getimm(ip, ap, mode) < 0)
1143                                 return -1;
1144                         break;
1145                 default:
1146                         ip->errmsg = "bad EA mode";
1147                         return -1;
1148                 }
1149         }
1150                 /* Allowable floating point EAs are restricted for packed,
1151                  * extended, and double precision operands
1152                  */
1153         if (mode == EAFLT) {
1154                 size = (ip->raw[1]>>10)&0x07;
1155                 if (size == 2 || size == 3 || size == 5)
1156                         mode = EAM;
1157                 else
1158                         mode = EADI;
1159         }
1160         if (!(validea[mode]&type)) {
1161                 ip->errmsg = "invalid EA";
1162                 return -1;
1163         }
1164         return 1;
1165 }
1166
1167 static int
1168 decode(Inst *ip, Optable *op)
1169 {
1170         int i, t, mode;
1171         Operand *ap;
1172         short opcode;
1173
1174         opcode = ip->raw[0];
1175         for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1176                 ap = &ip->and[i];
1177                 mode = op->opdata[i];
1178                 switch(mode)
1179                 {
1180                 case EAPI:              /* normal EA modes */
1181                 case EACA:
1182                 case EACAD:
1183                 case EACAPI:
1184                 case EACAPD:
1185                 case EAMA:
1186                 case EADA:
1187                 case EAA:
1188                 case EAC:
1189                 case EACPI:
1190                 case EACD:
1191                 case EAD:
1192                 case EAM:
1193                 case EAM_B:
1194                 case EADI:
1195                 case EADI_L:
1196                 case EADI_W:
1197                 case EAALL:
1198                 case EAALL_L:
1199                 case EAALL_W:
1200                 case EAALL_B:
1201                 case EAFLT:
1202                         if (ea(ip, opcode&0x3f, ap, mode) < 0)
1203                                 return -1;
1204                         break;
1205                 case EADDA:     /* stupid bit flop required */
1206                         t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1207                         if (ea(ip, t, ap, EADA)< 0)
1208                                         return -1;
1209                         break;
1210                 case BREAC:     /* EAC JMP or CALL operand */
1211                         if (ea(ip, opcode&0x3f, ap, EAC) < 0)
1212                                 return -1;
1213                         break;
1214                 case OP8:       /* weird movq instruction */
1215                         ap->eatype = IMM;
1216                         ap->immediate = opcode&0xff;
1217                         if (opcode&0x80)
1218                                 ap->immediate |= ~0xff;
1219                         break;
1220                 case I8:        /* must be two-word opcode */
1221                         ap->eatype = IMM;
1222                         ap->immediate = ip->raw[1]&0xff;
1223                         if (ap->immediate&0x80)
1224                                 ap->immediate |= ~0xff;
1225                         break;
1226                 case I16:       /* 16 bit immediate */
1227                 case BR16:
1228                         ap->eatype = IMM;
1229                         if (i16(ip, &ap->immediate) < 0)
1230                                 return -1;
1231                         break;
1232                 case C16:       /* CAS2 16 bit immediate */
1233                         ap->eatype = IMM;
1234                         if (i16(ip, &ap->immediate) < 0)
1235                                 return -1;
1236                         if (ap->immediate & 0x0e38) {
1237                                 ip->errmsg = "bad CAS2W operand";
1238                                 return 0;
1239                         }
1240                         break;
1241                 case I32:       /* 32 bit immediate */
1242                 case BR32:
1243                         ap->eatype = IMM;
1244                         if (i32(ip, &ap->immediate) < 0)
1245                                 return -1;
1246                         break;
1247                 case IV:        /* immediate data depends on size field */
1248                         if (getimm(ip, ap, IV) < 0)
1249                                 return -1;
1250                         break;
1251                 case BR8:       /* branch displacement format */
1252                         ap->eatype = IMM;
1253                         ap->immediate = opcode&0xff;
1254                         if (ap->immediate == 0) {
1255                                 if (i16(ip, &ap->immediate) < 0)
1256                                         return -1;
1257                         } else if (ap->immediate == 0xff) {
1258                                 if (i32(ip, &ap->immediate) < 0)
1259                                         return -1;
1260                         } else if (ap->immediate & 0x80)
1261                                 ap->immediate |= ~0xff;
1262                         break;
1263                 case STACK:     /* Dummy operand type for Return instructions */
1264                 default:
1265                         break;
1266                 }
1267         }
1268         return 1;
1269 }
1270
1271 static Optable *
1272 instruction(Inst *ip)
1273 {
1274         ushort opcode, op2;
1275         Optable *op;
1276         int class;
1277
1278         ip->n = 0;
1279         if (getword(ip, ip->addr) < 0)
1280                 return 0;
1281         opcode = ip->raw[0];
1282         if (get2(mymap, ip->addr+2, &op2) < 0)
1283                 op2 = 0;
1284         class = (opcode>>12)&0x0f;
1285         for (op = optables[class]; op && op->format; op++) {
1286                 if (op->opcode != (opcode&op->mask0))
1287                         continue;
1288                 if (op->op2 != (op2&op->mask1))
1289                         continue;
1290                 if (op->mask1)
1291                         ip->raw[ip->n++] = op2;
1292                 return op;
1293         }
1294         ip->errmsg = "Invalid opcode";
1295         return 0;
1296 }
1297
1298 #pragma varargck        argpos  bprint          2
1299
1300 static void
1301 bprint(Inst *i, char *fmt, ...)
1302 {
1303         va_list arg;
1304
1305         va_start(arg, fmt);
1306         i->curr = vseprint(i->curr, i->end, fmt, arg);
1307         va_end(arg);
1308 }
1309
1310 static  char    *regname[] =
1311 {
1312         "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0",
1313         "A1", "A2", "A3", "A4", "A5", "A6", "A7", "PC", "SB"
1314 };
1315
1316 static void
1317 plocal(Inst *ip, Operand *ap)
1318 {
1319         int ret;
1320         long offset;
1321         uvlong moved;
1322         Symbol s;
1323
1324         offset = ap->disp;
1325         if (!findsym(ip->addr, CTEXT, &s))
1326                 goto none;
1327
1328         moved = pc2sp(ip->addr);
1329         if (moved == -1)
1330                 goto none;
1331
1332         if (offset > moved) {           /* above frame - must be argument */
1333                 offset -= moved;
1334                 ret = getauto(&s, offset-mach->szaddr, CPARAM, &s);
1335         } else                          /* below frame - must be automatic */
1336                 ret = getauto(&s, moved-offset, CPARAM, &s);
1337         if (ret)
1338                 bprint(ip, "%s+%lux", s.name, offset);
1339         else
1340 none:           bprint(ip, "%lux", ap->disp);
1341 }
1342
1343 /*
1344  *      this guy does all the work of printing the base and index component
1345  *      of an EA.
1346  */
1347 static int
1348 pidx(Inst *ip, int ext, int reg, char *bfmt, char *ifmt, char *nobase)
1349 {
1350         char *s;
1351         int printed;
1352         char buf[512];
1353
1354         printed = 1;
1355         if (ext&0x80) {                         /* Base suppressed */
1356                 if (reg == 16)
1357                         bprint(ip, bfmt, "(ZPC)");
1358                 else if (nobase)
1359                         bprint(ip, nobase);
1360                 else
1361                         printed = 0;
1362         } else                                  /* format base reg */
1363                 bprint(ip, bfmt, regname[reg]);
1364         if (ext & 0x40)                         /* index suppressed */
1365                 return printed;
1366         switch ((ext>>9)&0x03)
1367         {
1368         case 0x01:
1369                 s = "*2";
1370                 break;
1371         case 0x02:
1372                 s = "*4";
1373                 break;
1374         case 0x03:
1375                 s = "*8";
1376                 break;
1377         default:
1378                 if (ext&0x80)
1379                         s = "*1";
1380                 else
1381                         s = "";
1382                 break;
1383         }
1384         sprint(buf, "%s.%c%s", regname[(ext>>12)&0x0f], (ext&0x800) ? 'L' : 'W', s);
1385         if (!printed)
1386                 bprint(ip, ifmt, buf);
1387         else
1388                 bprint(ip, "(%s)", buf);
1389         return 1;
1390 }
1391
1392 static void
1393 prindex(Inst *ip, int reg, Operand *ap)
1394 {
1395         short ext;
1396         int left;
1397         int disp;
1398
1399         left = ip->end-ip->curr;
1400         if (left <= 0)
1401                 return;
1402         ext = ap->ext;
1403         disp = ap->disp;
1404                 /* look for static base register references */
1405         if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) {
1406                 reg = 17;               /* "A6" -> "SB" */
1407                 disp += mach->sb;
1408         }
1409         if ((ext&0x100) == 0) {         /* brief form */
1410                 if (reg == 15)
1411                         plocal(ip, ap);
1412                 else if (disp)
1413                         ip->curr += symoff(ip->curr, left, disp, CANY);
1414                 pidx(ip, ext&0xff00, reg, "(%s)", "(%s)", 0);
1415                 return;
1416         }
1417         switch(ext&0x3f)        /* bd size, && i/is */
1418         {
1419         case 0x10:
1420                 if (!pidx(ip, ext, reg, "(%s)", "(%s)", 0))
1421                         bprint(ip, "#0");
1422                 break;
1423         case 0x11:
1424                 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1425                         bprint(ip, ")");
1426                 else
1427                         bprint(ip, "#0");
1428                 break;
1429         case 0x12:
1430         case 0x13:
1431                 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1432                 if (pidx(ip, ext, reg, "((%s)", "((%s)", 0))
1433                         bprint(ip, ")");
1434                 break;
1435         case 0x15:
1436                 if (!pidx(ip, ext, reg, "((%s))", "(%s)", 0))
1437                         bprint(ip, "#0");
1438                 break;
1439         case 0x16:
1440         case 0x17:
1441                 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1442                 pidx(ip, ext, reg, "((%s))", "(%s)", 0);
1443                 break;
1444         case 0x20:
1445         case 0x30:
1446                 if (reg == 15)
1447                         plocal(ip, ap);
1448                 else
1449                         ip->curr += symoff(ip->curr, left, disp, CANY);
1450                 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1451                 break;
1452         case 0x21:
1453         case 0x31:
1454                 *ip->curr++ = '(';
1455                 if (reg == 15)
1456                         plocal(ip, ap);
1457                 else
1458                         ip->curr += symoff(ip->curr, left-1, disp, CANY);
1459                 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1460                 bprint(ip, ")");
1461                 break;
1462         case 0x22:
1463         case 0x23:
1464         case 0x32:
1465         case 0x33:
1466                 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1467                 bprint(ip, "(");
1468                 if (reg == 15)
1469                         plocal(ip, ap);
1470                 else
1471                         ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1472                 pidx(ip, ext, reg, "(%s)", "(%s)", 0);
1473                 bprint(ip, ")");
1474                 break;
1475         case 0x25:
1476         case 0x35:
1477                 *ip->curr++ = '(';
1478                 if (reg == 15)
1479                         plocal(ip, ap);
1480                 else
1481                         ip->curr += symoff(ip->curr, left-1, disp, CANY);
1482                 if (!pidx(ip, ext, reg, "(%s))", "(%s)", "())"))
1483                         bprint(ip, ")");
1484                 break;
1485         case 0x26:
1486         case 0x27:
1487         case 0x36:
1488         case 0x37:
1489                 ip->curr += symoff(ip->curr, left, ap->outer, CANY);
1490                 bprint(ip, "(");
1491                 if (reg == 15)
1492                         plocal(ip, ap);
1493                 else
1494                         ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY);
1495                 pidx(ip, ext, reg, "(%s))", "(%s)", "())");
1496                 break;
1497         default:
1498                 bprint(ip, "??%x??", ext);
1499                 ip->errmsg = "bad EA";
1500                 break;
1501         }
1502 }
1503
1504 static  void
1505 pea(int reg, Inst *ip, Operand *ap)
1506 {
1507         int i, left;
1508
1509         left = ip->end-ip->curr;
1510         if (left < 0)
1511                 return;
1512         switch(ap->eatype)
1513         {
1514         case Dreg:
1515                 bprint(ip, "R%d", reg);
1516                 break;
1517         case Areg:
1518                 bprint(ip, "A%d", reg);
1519                 break;
1520         case AInd:
1521                 bprint(ip, "(A%d)", reg);
1522                 break;
1523         case APinc:
1524                 bprint(ip, "(A%d)+", reg);
1525                 break;
1526         case APdec:
1527                 bprint(ip, "-(A%d)", reg);
1528                 break;
1529         case PDisp:
1530                 ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY);
1531                 break;
1532         case PXD:
1533                 prindex(ip, 16, ap);
1534                 break;
1535         case ADisp:     /* references off the static base */
1536                 if (reg == 6 && mach->sb && ap->disp) {
1537                         ip->curr += symoff(ip->curr, left, ap->disp+mach->sb, CANY);
1538                         bprint(ip, "(SB)");
1539                         break;
1540                 }
1541                         /* reference autos and parameters off the stack */
1542                 if (reg == 7)
1543                         plocal(ip, ap);
1544                 else
1545                         ip->curr += symoff(ip->curr, left, ap->disp, CANY);
1546                 bprint(ip, "(A%d)", reg);
1547                 break;
1548         case BXD:
1549                 prindex(ip, reg+8, ap);
1550                 break;
1551         case ABS:
1552                 ip->curr += symoff(ip->curr, left, ap->immediate, CANY);
1553                 bprint(ip, "($0)");
1554                 break;
1555         case IMM:
1556                 *ip->curr++ = '$';
1557                 ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY);
1558                 break;
1559         case IREAL:
1560                 *ip->curr++ = '$';
1561                 ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater);
1562                 break;
1563         case IDBL:
1564                 *ip->curr++ = '$';
1565                 ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater);
1566                 break;
1567         case IPACK:
1568                 bprint(ip, "$#");
1569                 for (i = 0; i < 24 && ip->curr < ip->end-1; i++) {
1570                         _hexify(ip->curr, ap->floater[i], 1);
1571                         ip->curr += 2;
1572                 }
1573                 break;
1574         case IEXT:
1575                 bprint(ip, "$#");
1576                 ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater);
1577                 break;
1578         default:
1579                 bprint(ip, "??%x??", ap->eatype);
1580                 ip->errmsg = "bad EA type";
1581                 break;
1582         }
1583 }
1584
1585 static char *cctab[]  = { "F", "T", "HI", "LS", "CC", "CS", "NE", "EQ",
1586                           "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" };
1587 static  char *fcond[] =
1588 {
1589         "F",    "EQ",   "OGT",  "OGE",  "OLT",  "OLE",  "OGL", "OR",
1590         "UN",   "UEQ",  "UGT",  "UGE",  "ULT",  "ULE",  "NE",   "T",
1591         "SF",   "SEQ",  "GT",   "GE",   "LT",   "LE",   "GL",   "GLE",
1592         "NGLE", "NGL",  "NLE",  "NLT",  "NGE",  "NGT",  "SNE",  "ST"
1593 };
1594 static  char *cachetab[] =      { "NC", "DC", "IC", "BC" };
1595 static  char *mmutab[] =        { "TC", "??", "SRP", "CRP" };
1596 static  char *crtab0[] =
1597 {
1598         "SFC", "DFC", "CACR", "TC", "ITT0", "ITT1", "DTT0", "DTT1",
1599 };
1600 static  char *crtab1[] =
1601 {
1602         "USP", "VBR", "CAAR", "MSP", "ISP", "MMUSR", "URP", "SRP",
1603 };
1604 static  char typetab[] =        { 'L', 'S', 'X', 'P', 'W', 'D', 'B', '?', };
1605 static  char sztab[] =          {'?', 'B', 'W', 'L', '?' };
1606
1607 static  void
1608 formatins(char *fmt, Inst *ip)
1609 {
1610         short op, w1;
1611         int r1, r2;
1612         int currand;
1613
1614         op = ip->raw[0];
1615         w1 = ip->raw[1];
1616         currand = 0;
1617         for (; *fmt && ip->curr < ip->end; fmt++) {
1618                 if (*fmt != '%')
1619                         *ip->curr++ = *fmt;
1620                 else switch(*++fmt)
1621                 {
1622                 case '%':
1623                         *ip->curr++ = '%';
1624                         break;
1625                 case 'a':       /* register number; word 1:[0-2] */
1626                         *ip->curr++ = (w1&0x07)+'0';
1627                         break;
1628                 case 'c':       /* condition code; opcode: [8-11] */
1629                         bprint(ip, cctab[(op>>8)&0x0f]);
1630                         break;
1631                 case 'd':       /* shift direction; opcode: [8] */
1632                         if (op&0x100)
1633                                 *ip->curr++ = 'L';
1634                         else
1635                                 *ip->curr++ = 'R';
1636                         break;
1637                 case 'e':       /* source effective address */
1638                         pea(op&0x07, ip, &ip->and[currand++]);
1639                         break;
1640                 case 'f':       /* trap vector; op code: [0-3] */
1641                         bprint(ip, "%x", op&0x0f);
1642                         break;
1643                 case 'h':       /* register number; word 1: [5-7] */
1644                         *ip->curr++ = (w1>>5)&0x07+'0';
1645                         break;
1646                 case 'i':       /* immediate operand */
1647                         ip->curr += symoff(ip->curr, ip->end-ip->curr,
1648                                         ip->and[currand++].immediate, CANY);
1649                         break;
1650                 case 'j':       /* data registers; word 1: [0-2] & [12-14] */
1651                         r1 = w1&0x07;
1652                         r2 = (w1>>12)&0x07;
1653                         if (r1 == r2)
1654                                 bprint(ip, "R%d", r1);
1655                         else
1656                                 bprint(ip, "R%d:R%d", r2, r1);
1657                         break;
1658                 case 'k':       /* k factor; word 1 [0-6] */
1659                         bprint(ip, "%x", w1&0x7f);
1660                         break;
1661                 case 'm':       /* register mask; word 1 [0-7] */
1662                         bprint(ip, "%x", w1&0xff);
1663                         break;
1664                 case 'o':       /* bit field offset; word1: [6-10] */
1665                         bprint(ip, "%d", (w1>>6)&0x3f);
1666                         break;
1667                 case 'p':       /* conditional predicate; opcode: [0-5]
1668                                    only bits 0-4 are defined  */
1669                         bprint(ip, fcond[op&0x1f]);
1670                         break;
1671                 case 'q':       /* 3-bit immediate value; opcode[9-11] */
1672                         r1 = (op>>9)&0x07;
1673                         if (r1 == 0)
1674                                 *ip->curr++ = '8';
1675                         else
1676                                 *ip->curr++ = r1+'0';
1677                         break;
1678                 case 'r':       /* register type & number; word 1: [12-15] */
1679                         bprint(ip, regname[(w1>>12)&0x0f]);
1680                         break;
1681                 case 's':       /* size; opcode [6-7] */
1682                         *ip->curr = sztab[((op>>6)&0x03)+1];
1683                         if (*ip->curr++ == '?')
1684                                 ip->errmsg = "bad size code";
1685                         break;
1686                 case 't':       /* text offset */
1687                         ip->curr += symoff(ip->curr, ip->end-ip->curr,
1688                                 ip->and[currand++].immediate+ip->addr+2, CTEXT);
1689                         break;
1690                 case 'u':       /* register number; word 1: [6-8] */
1691                         *ip->curr++ = ((w1>>6)&0x07)+'0';
1692                         break;
1693                 case 'w':       /* bit field width; word 1: [0-4] */
1694                         bprint(ip, "%d", w1&0x0f);
1695                         break;
1696                 case 'x':       /* register number; opcode: [9-11] */
1697                         *ip->curr++ = ((op>>9)&0x07)+'0';
1698                         break;
1699                 case 'y':       /* register number; opcode: [0-2] */
1700                         *ip->curr++ = (op&0x07)+'0';
1701                         break;
1702                 case 'z':       /* shift count; opcode: [9-11] */       
1703                         *ip->curr++ = ((op>>9)&0x07)+'0';
1704                         break;
1705                 case 'A':       /* register number; word 2: [0-2] */
1706                         *ip->curr++ = (ip->raw[2]&0x07)+'0';
1707                         break;
1708                 case 'B':       /* float source reg; word 1: [10-12] */
1709                         *ip->curr++ = ((w1>>10)&0x07)+'0';
1710                         break;
1711                 case 'C':       /* cache identifier; opcode: [6-7] */
1712                         bprint(ip, cachetab[(op>>6)&0x03]);
1713                         break;
1714                 case 'D':       /* float dest reg; word 1: [7-9] */
1715                         *ip->curr++ = ((w1>>7)&0x07)+'0';
1716                         break;
1717                 case 'E':       /* destination EA; opcode: [6-11] */
1718                         pea((op>>9)&0x07, ip, &ip->and[currand++]);
1719                         break;
1720                 case 'F':       /* float dest register(s); word 1: [7-9] & [10-12] */
1721                         r1 = (w1>>7)&0x07;
1722                         r2 = (w1>>10)&0x07;
1723                         if (r1 == r2)
1724                                 bprint(ip, "F%d", r1);
1725                         else
1726                                 bprint(ip, "F%d,F%d", r2, r1);
1727                         break;
1728                 case 'H':       /* MMU register; word 1 [10-13] */
1729                         bprint(ip, mmutab[(w1>>10)&0x03]);
1730                         if (ip->curr[-1] == '?')
1731                                 ip->errmsg = "bad mmu register";
1732                         break;
1733                 case 'I':       /* MMU function code mask; word 1: [5-8] */
1734                         bprint(ip, "%x", (w1>>4)&0x0f);
1735                         break;
1736                 case 'K':       /* dynamic k-factor register; word 1: [5-8] */
1737                         bprint(ip, "%d",  (w1>>4)&0x0f);
1738                         break;
1739                 case 'L':       /* MMU function code; word 1: [0-6] */
1740                         if (w1&0x10)
1741                                 bprint(ip, "%x", w1&0x0f);
1742                         else if (w1&0x08)
1743                                 bprint(ip, "R%d",w1&0x07);
1744                         else if (w1&0x01)
1745                                 bprint(ip, "DFC");
1746                         else
1747                                 bprint(ip, "SFC");
1748                         break;
1749                 case 'N':       /* control register; word 1: [0-11] */
1750                         r1 = w1&0xfff;
1751                         if (r1&0x800)
1752                                 bprint(ip, crtab1[r1&0x07]);
1753                         else
1754                                 bprint(ip, crtab0[r1&0x07]);
1755                         break;
1756                 case 'P':       /* conditional predicate; word 1: [0-5] */
1757                         bprint(ip, fcond[w1&0x1f]);
1758                         break;
1759                 case 'R':       /* register type & number; word 2 [12-15] */
1760                         bprint(ip, regname[(ip->raw[2]>>12)&0x0f]);
1761                         break;
1762                 case 'S':       /* float source type code; word 1: [10-12] */
1763                         *ip->curr = typetab[(w1>>10)&0x07];
1764                         if (*ip->curr++ == '?')
1765                                 ip->errmsg = "bad float type";
1766                         break;
1767                 case 'U':       /* register number; word 2: [6-8] */
1768                         *ip->curr++ = ((ip->raw[2]>>6)&0x07)+'0';
1769                         break;
1770                 case 'Z':       /* ATC level number; word 1: [10-12] */
1771                         bprint(ip, "%x", (w1>>10)&0x07);
1772                         break;
1773                 case '1':       /* effective address in second operand*/
1774                         pea(op&0x07, ip, &ip->and[1]);
1775                         break;
1776                 default:
1777                         bprint(ip, "%%%c", *fmt);
1778                         break;
1779                 }
1780         }
1781         *ip->curr = 0;          /* there's always room for 1 byte */
1782 }
1783
1784 static int
1785 dispsize(Inst *ip)
1786 {
1787         ushort ext;
1788         static int dsize[] = {0, 0, 1, 2};      /* in words */
1789
1790         if (get2(mymap, ip->addr+ip->n*2, &ext) < 0)
1791                 return -1;
1792         if ((ext&0x100) == 0)
1793                 return 1;
1794         return dsize[(ext>>4)&0x03]+dsize[ext&0x03]+1;
1795 }
1796
1797 static int
1798 immsize(Inst *ip, int mode)
1799 {
1800         static int fsize[] = { 2, 2, 6, 12, 1, 4, 1, -1 };
1801         static int isize[] = { 1, 1, 2, -1 };
1802
1803         switch(mode)
1804         {
1805         case EAM_B:                     /* byte */
1806         case EAALL_B:
1807         case EADI_W:                    /* word */
1808         case EAALL_W:
1809                 return 1;
1810         case EADI_L:                    /* long */
1811         case EAALL_L:
1812                 return 2;
1813         case EAFLT:     /* floating point - size in bits 10-12 or word 1 */
1814                 return fsize[(ip->raw[1]>>10)&0x07];
1815         case IV:        /* size encoded in bits 6&7 of opcode word */
1816         default:
1817                 return isize[(ip->raw[0]>>6)&0x03];
1818         }
1819 }
1820
1821 static int
1822 easize(Inst *ip, int ea, int mode)
1823 {
1824         switch((ea>>3)&0x07)
1825         {
1826         case 0x00:
1827         case 0x01:
1828         case 0x02:
1829         case 0x03:
1830         case 0x04:
1831                 return 0;
1832         case 0x05:
1833                 return 1;
1834         case 0x06:
1835                 return dispsize(ip);
1836         case 0x07:
1837                 switch(ea&0x07)
1838                 {
1839                 case 0x00:
1840                 case 0x02:
1841                         return 1;
1842                 case 0x01:
1843                         return 2;
1844                 case 0x03:
1845                         return dispsize(ip);
1846                 case 0x04:
1847                         return immsize(ip, mode);
1848                 default:
1849                         return -1;
1850                 }
1851         }
1852         return -1;
1853 }
1854
1855 static int
1856 instrsize(Inst *ip, Optable *op)
1857 {
1858         int i, t, mode;
1859         short opcode;
1860
1861         opcode = ip->raw[0];
1862         for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) {
1863                 mode = op->opdata[i];
1864                 switch(mode)
1865                 {
1866                 case EAPI:              /* normal EA modes */
1867                 case EACA:
1868                 case EACAD:
1869                 case EACAPI:
1870                 case EACAPD:
1871                 case EAMA:
1872                 case EADA:
1873                 case EAA:
1874                 case EAC:
1875                 case EACPI:
1876                 case EACD:
1877                 case EAD:
1878                 case EAM:
1879                 case EAM_B:
1880                 case EADI:
1881                 case EADI_L:
1882                 case EADI_W:
1883                 case EAALL:
1884                 case EAALL_L:
1885                 case EAALL_W:
1886                 case EAALL_B:
1887                 case EAFLT:
1888                         t = easize(ip, opcode&0x3f, mode);
1889                         if (t < 0)
1890                                 return -1;
1891                         ip->n += t;
1892                         break;
1893                 case EADDA:     /* stupid bit flop required */
1894                         t = ((opcode>>9)&0x07)|((opcode>>3)&0x38);
1895                         t = easize(ip, t, mode);
1896                         if (t < 0)
1897                                 return -1;
1898                         ip->n += t;
1899                         break;
1900                 case BREAC:     /* EAC JMP or CALL operand */
1901                                 /* easy displacements for follow set */
1902                         if ((opcode&0x038) == 0x28 || (opcode&0x3f) == 0x3a) {
1903                                 if (i16(ip, &ip->and[i].immediate) < 0)
1904                                         return -1;
1905                         } else {
1906                                 t = easize(ip, opcode&0x3f, mode);
1907                                 if (t < 0)
1908                                         return -1;
1909                                 ip->n += t;
1910                         }
1911                         break;
1912                 case I16:       /* 16 bit immediate */
1913                 case C16:       /* CAS2 16 bit immediate */
1914                         ip->n++;
1915                         break;
1916                 case BR16:      /* 16 bit branch displacement */
1917                         if (i16(ip, &ip->and[i].immediate) < 0)
1918                                 return -1;
1919                         break;
1920                 case BR32:      /* 32 bit branch displacement */
1921                         if (i32(ip, &ip->and[i].immediate) < 0)
1922                                 return -1;
1923                         break;
1924                 case I32:       /* 32 bit immediate */
1925                         ip->n += 2;
1926                         break;
1927                 case IV:        /* immediate data depends on size field */
1928                         t = (ip->raw[0]>>6)&0x03;
1929                         if (t < 2)
1930                                 ip->n++;
1931                         else if (t == 2)
1932                                 ip->n += 2;
1933                         else 
1934                                 return -1;
1935                         break;
1936                 case BR8:       /* loony branch displacement format */
1937                         t = opcode&0xff;
1938                         if (t == 0) {
1939                                 if (i16(ip, &ip->and[i].immediate) < 0)
1940                                         return -1;
1941                         } else if (t == 0xff) {
1942                                 if (i32(ip, &ip->and[i].immediate) < 0)
1943                                         return -1;
1944                         } else {
1945                                 ip->and[i].immediate = t;
1946                                 if (t & 0x80)
1947                                         ip->and[i].immediate |= ~0xff;
1948                         }
1949                         break;
1950                 case STACK:     /* Dummy operand for Return instructions */
1951                 case OP8:       /* weird movq instruction */
1952                 case I8:        /* must be two-word opcode */
1953                 default:
1954                         break;
1955                 }
1956         }
1957         return 1;
1958 }
1959
1960 static int
1961 eaval(Inst *ip, Operand *ap, Rgetter rget)
1962 {
1963         int reg;
1964         char buf[8];
1965
1966         reg = ip->raw[0]&0x07;
1967         switch(ap->eatype)
1968         {
1969         case AInd:
1970                 sprint(buf, "A%d", reg);
1971                 return (*rget)(mymap, buf);
1972         case PDisp:
1973                 return ip->addr+2+ap->disp;
1974         case ADisp:
1975                 sprint(buf, "A%d", reg);
1976                 return ap->disp+(*rget)(mymap, buf);
1977         case ABS:
1978                 return ap->immediate;
1979         default:
1980                 return 0;
1981         }
1982 }
1983
1984 static int
1985 m68020instlen(Map *map, uvlong pc)
1986 {
1987         Inst i;
1988         Optable *op;
1989
1990         mymap = map;
1991         i.addr = pc;
1992         i.errmsg = 0;
1993         op = instruction(&i);
1994         if (op && instrsize(&i, op) > 0)
1995                         return i.n*2;
1996         return -1;
1997 }
1998
1999 static int
2000 m68020foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2001 {
2002         int j;
2003         Inst i;
2004         ulong l;
2005         Optable *op;
2006
2007         mymap = map;
2008         i.addr = pc;
2009         i.errmsg = 0;
2010         op = instruction(&i);
2011         if (op == 0  || instrsize(&i, op) < 0)
2012                 return -1;
2013         for (j = 0; j < nelem(op->opdata) && op->opdata[j]; j++) {
2014                 switch(op->opdata[j])
2015                 {
2016                 case BREAC:     /* CALL, JMP, JSR */
2017                         foll[0] = pc+2+eaval(&i, &i.and[j], rget);
2018                         return 1;
2019                 case BR8:       /* Bcc, BSR, & BRA */
2020                 case BR16:      /* FBcc, FDBcc, DBcc */
2021                 case BR32:      /* FBcc */
2022                         foll[0] = pc+i.n*2;
2023                         foll[1] = pc+2+i.and[j].immediate;
2024                         return 2;
2025                 case STACK:     /* RTR, RTS, RTD */
2026                         if (get4(map, (*rget)(map, mach->sp), &l) < 0)
2027                                 return -1;
2028                         *foll = l;
2029                         return 1;
2030                 default:
2031                         break;
2032                 }
2033         }
2034         foll[0] = pc+i.n*2;                     
2035         return 1;
2036 }
2037
2038 static int
2039 m68020inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2040 {
2041         Inst i;
2042         Optable *op;
2043
2044         USED(modifier);
2045         mymap = map;
2046         i.addr = pc;
2047         i.curr = buf;
2048         i.end = buf+n-1;
2049         i.errmsg = 0;
2050         op = instruction(&i);
2051         if (!op)
2052                 return -1;
2053         if (decode(&i, op) > 0)
2054                 formatins(op->format, &i);
2055         if (i.errmsg) {
2056                 if (i.curr != buf)
2057                         bprint(&i, "\t\t;");
2058                 bprint(&i, "%s: ", i.errmsg);
2059                 dumpinst(&i, i.curr, i.end-i.curr);
2060         }
2061         return i.n*2;
2062 }
2063
2064 static int
2065 m68020das(Map *map, uvlong pc, char *buf, int n)
2066 {
2067         Inst i;
2068         Optable *op;
2069
2070         mymap = map;
2071         i.addr = pc;
2072         i.curr = buf;
2073         i.end = buf+n-1;
2074         i.errmsg = 0;
2075         
2076         op = instruction(&i);
2077         if (!op)
2078                 return -1;
2079         decode(&i, op);
2080         if (i.errmsg)
2081                 bprint(&i, "%s: ", i.errmsg);
2082         dumpinst(&i, i.curr, i.end-i.curr);
2083         return i.n*2;
2084 }