]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/8db.c
ssh: document thumbfile options
[plan9front.git] / sys / src / libmach / 8db.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5
6 /*
7  * i386-specific debugger interface
8  * also amd64 extensions
9  */
10
11 static  char    *i386excep(Map*, Rgetter);
12
13 static  int     i386trace(Map*, uvlong, uvlong, uvlong, Tracer);
14 static  uvlong  i386frame(Map*, uvlong, uvlong, uvlong, uvlong);
15 static  int     i386foll(Map*, uvlong, Rgetter, uvlong*);
16 static  int     i386inst(Map*, uvlong, char, char*, int);
17 static  int     i386das(Map*, uvlong, char*, int);
18 static  int     i386instlen(Map*, uvlong);
19
20 static  char    STARTSYM[] =    "_main";
21 static  char    PROFSYM[] =     "_mainp";
22 static  char    FRAMENAME[] =   ".frame";
23 static char *excname[] =
24 {
25 [0]     "divide error",
26 [1]     "debug exception",
27 [4]     "overflow",
28 [5]     "bounds check",
29 [6]     "invalid opcode",
30 [7]     "math coprocessor emulation",
31 [8]     "double fault",
32 [9]     "math coprocessor overrun",
33 [10]    "invalid TSS",
34 [11]    "segment not present",
35 [12]    "stack exception",
36 [13]    "general protection violation",
37 [14]    "page fault",
38 [16]    "math coprocessor error",
39 [17]    "alignment check",
40 [18]    "machine check",
41 [19]    "floating-point exception",
42 [24]    "clock",
43 [25]    "keyboard",
44 [27]    "modem status",
45 [28]    "serial line status",
46 [30]    "floppy disk",
47 [36]    "mouse",
48 [37]    "math coprocessor",
49 [38]    "hard disk",
50 [64]    "system call",
51 };
52
53 Machdata i386mach =
54 {
55         {0xCC, 0, 0, 0},        /* break point: INT 3 */
56         1,                      /* break point size */
57
58         leswab,                 /* convert short to local byte order */
59         leswal,                 /* convert long to local byte order */
60         leswav,                 /* convert vlong to local byte order */
61         i386trace,              /* C traceback */
62         i386frame,              /* frame finder */
63         i386excep,              /* print exception */
64         0,                      /* breakpoint fixup */
65         leieeesftos,            /* single precision float printer */
66         leieeedftos,            /* double precision float printer */
67         i386foll,               /* following addresses */
68         i386inst,               /* print instruction */
69         i386das,                /* dissembler */
70         i386instlen,            /* instruction size calculation */
71 };
72
73 static char*
74 i386excep(Map *map, Rgetter rget)
75 {
76         ulong c;
77         uvlong pc;
78         static char buf[16];
79
80         c = (*rget)(map, "TRAP");
81         if(c > 64 || excname[c] == 0) {
82                 if (c == 3) {
83                         pc = (*rget)(map, "PC");
84                         if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0)
85                         if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
86                                 return "breakpoint";
87                 }
88                 snprint(buf, sizeof(buf), "exception %ld", c);
89                 return buf;
90         } else
91                 return excname[c];
92 }
93
94 static int
95 i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
96 {
97         int i;
98         uvlong osp;
99         Symbol s, f;
100
101         USED(link);
102         i = 0;
103         osp = 0;
104         while(findsym(pc, CTEXT, &s)) {
105                 if (osp == sp)
106                         break;
107                 osp = sp;
108
109                 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
110                         break;
111
112                 if(pc != s.value) {     /* not at first instruction */
113                         if(findlocal(&s, FRAMENAME, &f) == 0)
114                                 break;
115                         sp += f.value-mach->szaddr;
116                 }
117
118                 if (geta(map, sp, &pc) < 0)
119                         break;
120
121                 if(pc == 0)
122                         break;
123
124                 (*trace)(map, pc, sp, &s);
125                 sp += mach->szaddr;
126
127                 if(++i > 1000)
128                         break;
129         }
130         return i;
131 }
132
133 static uvlong
134 i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
135 {
136         Symbol s, f;
137
138         USED(link);
139         while (findsym(pc, CTEXT, &s)) {
140                 if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
141                         break;
142
143                 if(pc != s.value) {     /* not first instruction */
144                         if(findlocal(&s, FRAMENAME, &f) == 0)
145                                 break;
146                         sp += f.value-mach->szaddr;
147                 }
148
149                 if (s.value == addr)
150                         return sp;
151
152                 if (geta(map, sp, &pc) < 0)
153                         break;
154                 sp += mach->szaddr;
155         }
156         return 0;
157 }
158
159         /* I386/486 - Disassembler and related functions */
160
161 /*
162  *  an instruction
163  */
164 typedef struct Instr Instr;
165 struct  Instr
166 {
167         uchar   mem[1+1+1+1+2+1+1+4+4];         /* raw instruction */
168         uvlong  addr;           /* address of start of instruction */
169         int     n;              /* number of bytes in instruction */
170         char    *prefix;        /* instr prefix */
171         char    *segment;       /* segment override */
172         uchar   jumptype;       /* set to the operand type for jump/ret/call */
173         uchar   amd64;
174         uchar   rex;            /* REX prefix (or zero) */
175         char    osize;          /* 'W' or 'L' (or 'Q' on amd64) */
176         char    asize;          /* address size 'W' or 'L' (or 'Q' or amd64) */
177         uchar   mod;            /* bits 6-7 of mod r/m field */
178         uchar   reg;            /* bits 3-5 of mod r/m field */
179         char    ss;             /* bits 6-7 of SIB */
180         char    index;          /* bits 3-5 of SIB */
181         char    base;           /* bits 0-2 of SIB */
182         char    rip;            /* RIP-relative in amd64 mode */
183         uchar   opre;           /* f2/f3 could introduce media */
184         short   seg;            /* segment of far address */
185         ulong   disp;           /* displacement */
186         ulong   imm;            /* immediate */
187         ulong   imm2;           /* second immediate operand */
188         uvlong  imm64;          /* big immediate */
189         char    *curr;          /* fill level in output buffer */
190         char    *end;           /* end of output buffer */
191         char    *err;           /* error message */
192 };
193
194         /* 386 register (ha!) set */
195 enum{
196         AX=0,
197         CX,
198         DX,
199         BX,
200         SP,
201         BP,
202         SI,
203         DI,
204
205         /* amd64 */
206         R8,
207         R9,
208         R10,
209         R11,
210         R12,
211         R13,
212         R14,
213         R15
214 };
215
216         /* amd64 rex extension byte */
217 enum{
218         REXW            = 1<<3, /* =1, 64-bit operand size */
219         REXR            = 1<<2, /* extend modrm reg */
220         REXX            = 1<<1, /* extend sib index */
221         REXB            = 1<<0  /* extend modrm r/m, sib base, or opcode reg */
222 };
223         
224         /* Operand Format codes */
225 /*
226 %A      -       address size register modifier (!asize -> 'E')
227 %C      -       Control register CR0/CR1/CR2
228 %D      -       Debug register DR0/DR1/DR2/DR3/DR6/DR7
229 %I      -       second immediate operand
230 %O      -       Operand size register modifier (!osize -> 'E')
231 %T      -       Test register TR6/TR7
232 %S      -       size code ('W' or 'L')
233 %W      -       Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
234 %d      -       displacement 16-32 bits
235 %e      -       effective address - Mod R/M value
236 %f      -       floating point register F0-F7 - from Mod R/M register
237 %g      -       segment register
238 %i      -       immediate operand 8-32 bits
239 %p      -       PC-relative - signed displacement in immediate field
240 %r      -       Reg from Mod R/M
241 %w      -       Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
242 */
243
244 typedef struct Optable Optable;
245 struct Optable
246 {
247         char    operand[2];
248         void    *proto;         /* actually either (char*) or (Optable*) */
249 };
250         /* Operand decoding codes */
251 enum {
252         Ib = 1,                 /* 8-bit immediate - (no sign extension)*/
253         Ibs,                    /* 8-bit immediate (sign extended) */
254         Jbs,                    /* 8-bit sign-extended immediate in jump or call */
255         Iw,                     /* 16-bit immediate -> imm */
256         Iw2,                    /* 16-bit immediate -> imm2 */
257         Iwd,                    /* Operand-sized immediate (no sign extension)*/
258         Iwdq,                   /* Operand-sized immediate, possibly 64 bits */
259         Awd,                    /* Address offset */
260         Iwds,                   /* Operand-sized immediate (sign extended) */
261         RM,                     /* Word or long R/M field with register (/r) */
262         RMB,                    /* Byte R/M field with register (/r) */
263         RMOP,                   /* Word or long R/M field with op code (/digit) */
264         RMOPB,                  /* Byte R/M field with op code (/digit) */
265         RMR,                    /* R/M register only (mod = 11) */
266         RMM,                    /* R/M memory only (mod = 0/1/2) */
267         R0,                     /* Base reg of Mod R/M is literal 0x00 */
268         R1,                     /* Base reg of Mod R/M is literal 0x01 */
269         FRMOP,                  /* Floating point R/M field with opcode */
270         FRMEX,                  /* Extended floating point R/M field with opcode */
271         JUMP,                   /* Jump or Call flag - no operand */
272         RET,                    /* Return flag - no operand */
273         OA,                     /* literal 0x0a byte */
274         PTR,                    /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
275         AUX,                    /* Multi-byte op code - Auxiliary table */
276         AUXMM,                  /* multi-byte op code - auxiliary table chosen by prefix */
277         PRE,                    /* Instr Prefix */
278         OPRE,                   /* Instr Prefix or media op extension */
279         SEG,                    /* Segment Prefix */
280         OPOVER,                 /* Operand size override */
281         ADDOVER,                /* Address size override */
282 };
283         
284 static Optable optab0F00[8]=
285 {
286 [0x00]  0,0,            "MOVW   LDT,%e",
287 [0x01]  0,0,            "MOVW   TR,%e",
288 [0x02]  0,0,            "MOVW   %e,LDT",
289 [0x03]  0,0,            "MOVW   %e,TR",
290 [0x04]  0,0,            "VERR   %e",
291 [0x05]  0,0,            "VERW   %e",
292 };
293
294 static Optable optab0F01[8]=
295 {
296 [0x00]  0,0,            "MOVL   GDTR,%e",
297 [0x01]  0,0,            "MOVL   IDTR,%e",
298 [0x02]  0,0,            "MOVL   %e,GDTR",
299 [0x03]  0,0,            "MOVL   %e,IDTR",
300 [0x04]  0,0,            "MOVW   MSW,%e",        /* word */
301 [0x06]  0,0,            "MOVW   %e,MSW",        /* word */
302 [0x07]  0,0,            "INVLPG %e",            /* or SWAPGS */
303 };
304
305 static Optable optab0F01F8[1]=
306 {
307 [0x00]  0,0,            "SWAPGS",
308 };
309
310 /* 0F71 */
311 /* 0F72 */
312 /* 0F73 */
313
314 static Optable optab0FAE[8]=
315 {
316 [0x00]  0,0,            "FXSAVE %e",
317 [0x01]  0,0,            "FXRSTOR        %e",
318 [0x02]  0,0,            "LDMXCSR        %e",
319 [0x03]  0,0,            "STMXCSR        %e",
320 [0x05]  0,0,            "LFENCE",
321 [0x06]  0,0,            "MFENCE",
322 [0x07]  0,0,            "SFENCE",
323 };
324
325 /* 0F18 */
326 /* 0F0D */
327
328 static Optable optab0FBA[8]=
329 {
330 [0x04]  Ib,0,           "BT%S   %i,%e",
331 [0x05]  Ib,0,           "BTS%S  %i,%e",
332 [0x06]  Ib,0,           "BTR%S  %i,%e",
333 [0x07]  Ib,0,           "BTC%S  %i,%e",
334 };
335
336 static Optable optab0F0F[256]=
337 {
338 [0x0c]  0,0,            "PI2FW  %m,%M",
339 [0x0d]  0,0,            "PI2L   %m,%M",
340 [0x1c]  0,0,            "PF2IW  %m,%M",
341 [0x1d]  0,0,            "PF2IL  %m,%M",
342 [0x8a]  0,0,            "PFNACC %m,%M",
343 [0x8e]  0,0,            "PFPNACC        %m,%M",
344 [0x90]  0,0,            "PFCMPGE        %m,%M",
345 [0x94]  0,0,            "PFMIN  %m,%M",
346 [0x96]  0,0,            "PFRCP  %m,%M",
347 [0x97]  0,0,            "PFRSQRT        %m,%M",
348 [0x9a]  0,0,            "PFSUB  %m,%M",
349 [0x9e]  0,0,            "PFADD  %m,%M",
350 [0xa0]  0,0,            "PFCMPGT        %m,%M",
351 [0xa4]  0,0,            "PFMAX  %m,%M",
352 [0xa6]  0,0,            "PFRCPIT1       %m,%M",
353 [0xa7]  0,0,            "PFRSQIT1       %m,%M",
354 [0xaa]  0,0,            "PFSUBR %m,%M",
355 [0xae]  0,0,            "PFACC  %m,%M",
356 [0xb0]  0,0,            "PFCMPEQ        %m,%M",
357 [0xb4]  0,0,            "PFMUL  %m,%M",
358 [0xb6]  0,0,            "PFRCPI2T       %m,%M",
359 [0xb7]  0,0,            "PMULHRW        %m,%M",
360 [0xbb]  0,0,            "PSWAPL %m,%M",
361 };
362
363 static Optable optab0FC7[8]=
364 {
365 [0x01]  0,0,            "CMPXCHG8B      %e",
366 };
367
368 static Optable optab660F71[8]=
369 {
370 [0x02]  Ib,0,           "PSRLW  %i,%X",
371 [0x04]  Ib,0,           "PSRAW  %i,%X",
372 [0x06]  Ib,0,           "PSLLW  %i,%X",
373 };
374
375 static Optable optab660F72[8]=
376 {
377 [0x02]  Ib,0,           "PSRLL  %i,%X",
378 [0x04]  Ib,0,           "PSRAL  %i,%X",
379 [0x06]  Ib,0,           "PSLLL  %i,%X",
380 };
381
382 static Optable optab660F73[8]=
383 {
384 [0x02]  Ib,0,           "PSRLQ  %i,%X",
385 [0x03]  Ib,0,           "PSRLO  %i,%X",
386 [0x06]  Ib,0,           "PSLLQ  %i,%X",
387 [0x07]  Ib,0,           "PSLLO  %i,%X",
388 };
389
390 static Optable optab660F[256]=
391 {
392 [0x2B]  RM,0,           "MOVNTPD        %x,%e",
393 [0x2E]  RM,0,           "UCOMISD        %x,%X",
394 [0x2F]  RM,0,           "COMISD %x,%X",
395 [0x5A]  RM,0,           "CVTPD2PS       %x,%X",
396 [0x5B]  RM,0,           "CVTPS2PL       %x,%X",
397 [0x6A]  RM,0,           "PUNPCKHLQ %x,%X",
398 [0x6B]  RM,0,           "PACKSSLW %x,%X",
399 [0x6C]  RM,0,           "PUNPCKLQDQ %x,%X",
400 [0x6D]  RM,0,           "PUNPCKHQDQ %x,%X",
401 [0x6E]  RM,0,           "MOV%S  %e,%X",
402 [0x6F]  RM,0,           "MOVO   %x,%X",         /* MOVDQA */
403 [0x70]  RM,Ib,          "PSHUFL %i,%x,%X",
404 [0x71]  RMOP,0,         optab660F71,
405 [0x72]  RMOP,0,         optab660F72,
406 [0x73]  RMOP,0,         optab660F73,
407 [0x7E]  RM,0,           "MOV%S  %X,%e",
408 [0x7F]  RM,0,           "MOVO   %X,%x",
409 [0xC4]  RM,Ib,          "PINSRW %i,%e,%X",
410 [0xC5]  RMR,Ib,         "PEXTRW %i,%X,%e",
411 [0xD4]  RM,0,           "PADDQ  %x,%X",
412 [0xD5]  RM,0,           "PMULLW %x,%X",
413 [0xD6]  RM,0,           "MOVQ   %X,%x",
414 [0xE6]  RM,0,           "CVTTPD2PL      %x,%X",
415 [0xE7]  RM,0,           "MOVNTO %X,%e",
416 [0xF7]  RM,0,           "MASKMOVOU      %x,%X",
417 };
418
419 static Optable optabF20F[256]=
420 {
421 [0x10]  RM,0,           "MOVSD  %x,%X",
422 [0x11]  RM,0,           "MOVSD  %X,%x",
423 [0x2A]  RM,0,           "CVTS%S2SD      %e,%X",
424 [0x2C]  RM,0,           "CVTTSD2S%S     %x,%r",
425 [0x2D]  RM,0,           "CVTSD2S%S      %x,%r",
426 [0x5A]  RM,0,           "CVTSD2SS       %x,%X",
427 [0x6F]  RM,0,           "MOVOU  %x,%X",
428 [0x70]  RM,Ib,          "PSHUFLW        %i,%x,%X",
429 [0x7F]  RM,0,           "MOVOU  %X,%x",
430 [0xD6]  RM,0,           "MOVQOZX        %M,%X",
431 [0xE6]  RM,0,           "CVTPD2PL       %x,%X",
432 };
433
434 static Optable optabF30F[256]=
435 {
436 [0x10]  RM,0,           "MOVSS  %x,%X",
437 [0x11]  RM,0,           "MOVSS  %X,%x",
438 [0x2A]  RM,0,           "CVTS%S2SS      %e,%X",
439 [0x2C]  RM,0,           "CVTTSS2S%S     %x,%r",
440 [0x2D]  RM,0,           "CVTSS2S%S      %x,%r",
441 [0x5A]  RM,0,           "CVTSS2SD       %x,%X",
442 [0x5B]  RM,0,           "CVTTPS2PL      %x,%X",
443 [0x6F]  RM,0,           "MOVOU  %x,%X",
444 [0x70]  RM,Ib,          "PSHUFHW        %i,%x,%X",
445 [0x7E]  RM,0,           "MOVQOZX        %x,%X",
446 [0x7F]  RM,0,           "MOVOU  %X,%x",
447 [0xD6]  RM,0,           "MOVQOZX        %m*,%X",
448 [0xE6]  RM,0,           "CVTPL2PD       %x,%X",
449 };
450
451 static Optable optab0F[256]=
452 {
453 [0x00]  RMOP,0,         optab0F00,
454 [0x01]  RMOP,0,         optab0F01,
455 [0x02]  RM,0,           "LAR    %e,%r",
456 [0x03]  RM,0,           "LSL    %e,%r",
457 [0x05]  0,0,            "SYSCALL",
458 [0x06]  0,0,            "CLTS",
459 [0x07]  0,0,            "SYSRET",
460 [0x08]  0,0,            "INVD",
461 [0x09]  0,0,            "WBINVD",
462 [0x0B]  0,0,            "UD2",
463 [0x0F]  RM,AUX,         optab0F0F,              /* 3DNow! */
464 [0x10]  RM,0,           "MOVU%s %x,%X",
465 [0x11]  RM,0,           "MOVU%s %X,%x",
466 [0x12]  RM,0,           "MOV[H]L%s      %x,%X", /* TO DO: H if source is XMM */
467 [0x13]  RM,0,           "MOVL%s %X,%e",
468 [0x14]  RM,0,           "UNPCKL%s       %x,%X",
469 [0x15]  RM,0,           "UNPCKH%s       %x,%X",
470 [0x16]  RM,0,           "MOV[L]H%s      %x,%X", /* TO DO: L if source is XMM */
471 [0x17]  RM,0,           "MOVH%s %X,%x",
472 [0x20]  RMR,0,          "MOVL   %C,%e",
473 [0x21]  RMR,0,          "MOVL   %D,%e",
474 [0x22]  RMR,0,          "MOVL   %e,%C",
475 [0x23]  RMR,0,          "MOVL   %e,%D",
476 [0x24]  RMR,0,          "MOVL   %T,%e",
477 [0x26]  RMR,0,          "MOVL   %e,%T",
478 [0x28]  RM,0,           "MOVA%s %x,%X",
479 [0x29]  RM,0,           "MOVA%s %X,%x",
480 [0x2A]  RM,0,           "CVTPL2%s       %m*,%X",
481 [0x2B]  RM,0,           "MOVNT%s        %X,%e",
482 [0x2C]  RM,0,           "CVTT%s2PL      %x,%M",
483 [0x2D]  RM,0,           "CVT%s2PL       %x,%M",
484 [0x2E]  RM,0,           "UCOMISS        %x,%X",
485 [0x2F]  RM,0,           "COMISS %x,%X",
486 [0x30]  0,0,            "WRMSR",
487 [0x31]  0,0,            "RDTSC",
488 [0x32]  0,0,            "RDMSR",
489 [0x33]  0,0,            "RDPMC",
490 [0x42]  RM,0,           "CMOVC  %e,%r",         /* CF */
491 [0x43]  RM,0,           "CMOVNC %e,%r",         /* Â¬ CF */
492 [0x44]  RM,0,           "CMOVZ  %e,%r",         /* ZF */
493 [0x45]  RM,0,           "CMOVNZ %e,%r",         /* Â¬ ZF */
494 [0x46]  RM,0,           "CMOVBE %e,%r",         /* CF âˆ¨ ZF */
495 [0x47]  RM,0,           "CMOVA  %e,%r",         /* Â¬CF âˆ§ Â¬ZF */
496 [0x48]  RM,0,           "CMOVS  %e,%r",         /* SF */
497 [0x49]  RM,0,           "CMOVNS %e,%r",         /* Â¬ SF */
498 [0x4A]  RM,0,           "CMOVP  %e,%r",         /* PF */
499 [0x4B]  RM,0,           "CMOVNP %e,%r",         /* Â¬ PF */
500 [0x4C]  RM,0,           "CMOVLT %e,%r",         /* LT â‰¡ OF â‰  SF */
501 [0x4D]  RM,0,           "CMOVGE %e,%r",         /* GE â‰¡ ZF âˆ¨ SF */
502 [0x4E]  RM,0,           "CMOVLE %e,%r",         /* LE â‰¡ ZF âˆ¨ LT */
503 [0x4F]  RM,0,           "CMOVGT %e,%r",         /* GT â‰¡ Â¬ZF âˆ§ GE */
504 [0x50]  RM,0,           "MOVMSK%s       %X,%r", /* TO DO: check */
505 [0x51]  RM,0,           "SQRT%s %x,%X",
506 [0x52]  RM,0,           "RSQRT%s        %x,%X",
507 [0x53]  RM,0,           "RCP%s  %x,%X",
508 [0x54]  RM,0,           "AND%s  %x,%X",
509 [0x55]  RM,0,           "ANDN%s %x,%X",
510 [0x56]  RM,0,           "OR%s   %x,%X",         /* TO DO: S/D */
511 [0x57]  RM,0,           "XOR%s  %x,%X",         /* S/D */
512 [0x58]  RM,0,           "ADD%s  %x,%X",         /* S/P S/D */
513 [0x59]  RM,0,           "MUL%s  %x,%X",
514 [0x5A]  RM,0,           "CVTPS2PD       %x,%X",
515 [0x5B]  RM,0,           "CVTPL2PS       %x,%X",
516 [0x5C]  RM,0,           "SUB%s  %x,%X",
517 [0x5D]  RM,0,           "MIN%s  %x,%X",
518 [0x5E]  RM,0,           "DIV%s  %x,%X",         /* TO DO: S/P S/D */
519 [0x5F]  RM,0,           "MAX%s  %x,%X",
520 [0x60]  RM,0,           "PUNPCKLBW %m,%M",
521 [0x61]  RM,0,           "PUNPCKLWL %m,%M",
522 [0x62]  RM,0,           "PUNPCKLLQ %m,%M",
523 [0x63]  RM,0,           "PACKSSWB %m,%M",
524 [0x64]  RM,0,           "PCMPGTB %m,%M",
525 [0x65]  RM,0,           "PCMPGTW %m,%M",
526 [0x66]  RM,0,           "PCMPGTL %m,%M",
527 [0x67]  RM,0,           "PACKUSWB %m,%M",
528 [0x68]  RM,0,           "PUNPCKHBW %m,%M",
529 [0x69]  RM,0,           "PUNPCKHWL %m,%M",
530 [0x6A]  RM,0,           "PUNPCKHLQ %m,%M",
531 [0x6B]  RM,0,           "PACKSSLW %m,%M",
532 [0x6E]  RM,0,           "MOV%S %e,%M",
533 [0x6F]  RM,0,           "MOVQ %m,%M",
534 [0x70]  RM,Ib,          "PSHUFW %i,%m,%M",
535 [0x74]  RM,0,           "PCMPEQB %m,%M",
536 [0x75]  RM,0,           "PCMPEQW %m,%M",
537 [0x76]  RM,0,           "PCMPEQL %m,%M",
538 [0x77]  0,0,            "EMMS",
539 [0x7E]  RM,0,           "MOV%S %M,%e",
540 [0x7F]  RM,0,           "MOVQ %M,%m",
541 [0xAE]  RMOP,0,         optab0FAE,
542 [0xAA]  0,0,            "RSM",
543 [0xB0]  RM,0,           "CMPXCHGB       %r,%e",
544 [0xB1]  RM,0,           "CMPXCHG%S      %r,%e",
545 [0xC0]  RMB,0,          "XADDB  %r,%e",
546 [0xC1]  RM,0,           "XADD%S %r,%e",
547 [0xC2]  RM,Ib,          "CMP%s  %i,%x,%X",
548 [0xC3]  RM,0,           "MOVNTI%S       %r,%e",
549 [0xC6]  RM,Ib,          "SHUF%s %i,%x,%X",
550 [0xC8]  0,0,            "BSWAP  AX",
551 [0xC9]  0,0,            "BSWAP  CX",
552 [0xCA]  0,0,            "BSWAP  DX",
553 [0xCB]  0,0,            "BSWAP  BX",
554 [0xCC]  0,0,            "BSWAP  SP",
555 [0xCD]  0,0,            "BSWAP  BP",
556 [0xCE]  0,0,            "BSWAP  SI",
557 [0xCF]  0,0,            "BSWAP  DI",
558 [0xD1]  RM,0,           "PSRLW %m,%M",
559 [0xD2]  RM,0,           "PSRLL %m,%M",
560 [0xD3]  RM,0,           "PSRLQ %m,%M",
561 [0xD5]  RM,0,           "PMULLW %m,%M",
562 [0xD6]  RM,0,           "MOVQOZX        %m*,%X",
563 [0xD7]  RM,0,           "PMOVMSKB %m,%r",
564 [0xD8]  RM,0,           "PSUBUSB %m,%M",
565 [0xD9]  RM,0,           "PSUBUSW %m,%M",
566 [0xDA]  RM,0,           "PMINUB %m,%M",
567 [0xDB]  RM,0,           "PAND %m,%M",
568 [0xDC]  RM,0,           "PADDUSB %m,%M",
569 [0xDD]  RM,0,           "PADDUSW %m,%M",
570 [0xDE]  RM,0,           "PMAXUB %m,%M",
571 [0xDF]  RM,0,           "PANDN %m,%M",
572 [0xE0]  RM,0,           "PAVGB %m,%M",
573 [0xE1]  RM,0,           "PSRAW %m,%M",
574 [0xE2]  RM,0,           "PSRAL %m,%M",
575 [0xE3]  RM,0,           "PAVGW %m,%M",
576 [0xE4]  RM,0,           "PMULHUW %m,%M",
577 [0xE5]  RM,0,           "PMULHW %m,%M",
578 [0xE7]  RM,0,           "MOVNTQ %M,%e",
579 [0xE8]  RM,0,           "PSUBSB %m,%M",
580 [0xE9]  RM,0,           "PSUBSW %m,%M",
581 [0xEA]  RM,0,           "PMINSW %m,%M",
582 [0xEB]  RM,0,           "POR %m,%M",
583 [0xEC]  RM,0,           "PADDSB %m,%M",
584 [0xED]  RM,0,           "PADDSW %m,%M",
585 [0xEE]  RM,0,           "PMAXSW %m,%M",
586 [0xEF]  RM,0,           "PXOR %m,%M",
587 [0xF1]  RM,0,           "PSLLW %m,%M",
588 [0xF2]  RM,0,           "PSLLL %m,%M",
589 [0xF3]  RM,0,           "PSLLQ %m,%M",
590 [0xF4]  RM,0,           "PMULULQ        %m,%M",
591 [0xF5]  RM,0,           "PMADDWL %m,%M",
592 [0xF6]  RM,0,           "PSADBW %m,%M",
593 [0xF7]  RMR,0,          "MASKMOVQ       %m,%M",
594 [0xF8]  RM,0,           "PSUBB %m,%M",
595 [0xF9]  RM,0,           "PSUBW %m,%M",
596 [0xFA]  RM,0,           "PSUBL %m,%M",
597 [0xFC]  RM,0,           "PADDB %m,%M",
598 [0xFD]  RM,0,           "PADDW %m,%M",
599 [0xFE]  RM,0,           "PADDL %m,%M",
600
601 [0x80]  Iwds,0,         "JOS    %p",
602 [0x81]  Iwds,0,         "JOC    %p",
603 [0x82]  Iwds,0,         "JCS    %p",
604 [0x83]  Iwds,0,         "JCC    %p",
605 [0x84]  Iwds,0,         "JEQ    %p",
606 [0x85]  Iwds,0,         "JNE    %p",
607 [0x86]  Iwds,0,         "JLS    %p",
608 [0x87]  Iwds,0,         "JHI    %p",
609 [0x88]  Iwds,0,         "JMI    %p",
610 [0x89]  Iwds,0,         "JPL    %p",
611 [0x8a]  Iwds,0,         "JPS    %p",
612 [0x8b]  Iwds,0,         "JPC    %p",
613 [0x8c]  Iwds,0,         "JLT    %p",
614 [0x8d]  Iwds,0,         "JGE    %p",
615 [0x8e]  Iwds,0,         "JLE    %p",
616 [0x8f]  Iwds,0,         "JGT    %p",
617 [0x90]  RMB,0,          "SETOS  %e",
618 [0x91]  RMB,0,          "SETOC  %e",
619 [0x92]  RMB,0,          "SETCS  %e",
620 [0x93]  RMB,0,          "SETCC  %e",
621 [0x94]  RMB,0,          "SETEQ  %e",
622 [0x95]  RMB,0,          "SETNE  %e",
623 [0x96]  RMB,0,          "SETLS  %e",
624 [0x97]  RMB,0,          "SETHI  %e",
625 [0x98]  RMB,0,          "SETMI  %e",
626 [0x99]  RMB,0,          "SETPL  %e",
627 [0x9a]  RMB,0,          "SETPS  %e",
628 [0x9b]  RMB,0,          "SETPC  %e",
629 [0x9c]  RMB,0,          "SETLT  %e",
630 [0x9d]  RMB,0,          "SETGE  %e",
631 [0x9e]  RMB,0,          "SETLE  %e",
632 [0x9f]  RMB,0,          "SETGT  %e",
633 [0xa0]  0,0,            "PUSHL  FS",
634 [0xa1]  0,0,            "POPL   FS",
635 [0xa2]  0,0,            "CPUID",
636 [0xa3]  RM,0,           "BT%S   %r,%e",
637 [0xa4]  RM,Ib,          "SHLD%S %r,%i,%e",
638 [0xa5]  RM,0,           "SHLD%S %r,CL,%e",
639 [0xa8]  0,0,            "PUSHL  GS",
640 [0xa9]  0,0,            "POPL   GS",
641 [0xab]  RM,0,           "BTS%S  %r,%e",
642 [0xac]  RM,Ib,          "SHRD%S %r,%i,%e",
643 [0xad]  RM,0,           "SHRD%S %r,CL,%e",
644 [0xaf]  RM,0,           "IMUL%S %e,%r",
645 [0xb2]  RMM,0,          "LSS    %e,%r",
646 [0xb3]  RM,0,           "BTR%S  %r,%e",
647 [0xb4]  RMM,0,          "LFS    %e,%r",
648 [0xb5]  RMM,0,          "LGS    %e,%r",
649 [0xb6]  RMB,0,          "MOVBZX %e,%R",
650 [0xb7]  RM,0,           "MOVWZX %e,%R",
651 [0xba]  RMOP,0,         optab0FBA,
652 [0xbb]  RM,0,           "BTC%S  %e,%r",
653 [0xbc]  RM,0,           "BSF%S  %e,%r",
654 [0xbd]  RM,0,           "BSR%S  %e,%r",
655 [0xbe]  RMB,0,          "MOVBSX %e,%R",
656 [0xbf]  RM,0,           "MOVWSX %e,%R",
657 [0xc7]  RMOP,0,         optab0FC7,
658 };
659
660 static Optable optab80[8]=
661 {
662 [0x00]  Ib,0,           "ADDB   %i,%e",
663 [0x01]  Ib,0,           "ORB    %i,%e",
664 [0x02]  Ib,0,           "ADCB   %i,%e",
665 [0x03]  Ib,0,           "SBBB   %i,%e",
666 [0x04]  Ib,0,           "ANDB   %i,%e",
667 [0x05]  Ib,0,           "SUBB   %i,%e",
668 [0x06]  Ib,0,           "XORB   %i,%e",
669 [0x07]  Ib,0,           "CMPB   %e,%i",
670 };
671
672 static Optable optab81[8]=
673 {
674 [0x00]  Iwd,0,          "ADD%S  %i,%e",
675 [0x01]  Iwd,0,          "OR%S   %i,%e",
676 [0x02]  Iwd,0,          "ADC%S  %i,%e",
677 [0x03]  Iwd,0,          "SBB%S  %i,%e",
678 [0x04]  Iwd,0,          "AND%S  %i,%e",
679 [0x05]  Iwd,0,          "SUB%S  %i,%e",
680 [0x06]  Iwd,0,          "XOR%S  %i,%e",
681 [0x07]  Iwd,0,          "CMP%S  %e,%i",
682 };
683
684 static Optable optab83[8]=
685 {
686 [0x00]  Ibs,0,          "ADD%S  %i,%e",
687 [0x01]  Ibs,0,          "OR%S   %i,%e",
688 [0x02]  Ibs,0,          "ADC%S  %i,%e",
689 [0x03]  Ibs,0,          "SBB%S  %i,%e",
690 [0x04]  Ibs,0,          "AND%S  %i,%e",
691 [0x05]  Ibs,0,          "SUB%S  %i,%e",
692 [0x06]  Ibs,0,          "XOR%S  %i,%e",
693 [0x07]  Ibs,0,          "CMP%S  %e,%i",
694 };
695
696 static Optable optabC0[8] =
697 {
698 [0x00]  Ib,0,           "ROLB   %i,%e",
699 [0x01]  Ib,0,           "RORB   %i,%e",
700 [0x02]  Ib,0,           "RCLB   %i,%e",
701 [0x03]  Ib,0,           "RCRB   %i,%e",
702 [0x04]  Ib,0,           "SHLB   %i,%e",
703 [0x05]  Ib,0,           "SHRB   %i,%e",
704 [0x07]  Ib,0,           "SARB   %i,%e",
705 };
706
707 static Optable optabC1[8] =
708 {
709 [0x00]  Ib,0,           "ROL%S  %i,%e",
710 [0x01]  Ib,0,           "ROR%S  %i,%e",
711 [0x02]  Ib,0,           "RCL%S  %i,%e",
712 [0x03]  Ib,0,           "RCR%S  %i,%e",
713 [0x04]  Ib,0,           "SHL%S  %i,%e",
714 [0x05]  Ib,0,           "SHR%S  %i,%e",
715 [0x07]  Ib,0,           "SAR%S  %i,%e",
716 };
717
718 static Optable optabD0[8] =
719 {
720 [0x00]  0,0,            "ROLB   %e",
721 [0x01]  0,0,            "RORB   %e",
722 [0x02]  0,0,            "RCLB   %e",
723 [0x03]  0,0,            "RCRB   %e",
724 [0x04]  0,0,            "SHLB   %e",
725 [0x05]  0,0,            "SHRB   %e",
726 [0x07]  0,0,            "SARB   %e",
727 };
728
729 static Optable optabD1[8] =
730 {
731 [0x00]  0,0,            "ROL%S  %e",
732 [0x01]  0,0,            "ROR%S  %e",
733 [0x02]  0,0,            "RCL%S  %e",
734 [0x03]  0,0,            "RCR%S  %e",
735 [0x04]  0,0,            "SHL%S  %e",
736 [0x05]  0,0,            "SHR%S  %e",
737 [0x07]  0,0,            "SAR%S  %e",
738 };
739
740 static Optable optabD2[8] =
741 {
742 [0x00]  0,0,            "ROLB   CL,%e",
743 [0x01]  0,0,            "RORB   CL,%e",
744 [0x02]  0,0,            "RCLB   CL,%e",
745 [0x03]  0,0,            "RCRB   CL,%e",
746 [0x04]  0,0,            "SHLB   CL,%e",
747 [0x05]  0,0,            "SHRB   CL,%e",
748 [0x07]  0,0,            "SARB   CL,%e",
749 };
750
751 static Optable optabD3[8] =
752 {
753 [0x00]  0,0,            "ROL%S  CL,%e",
754 [0x01]  0,0,            "ROR%S  CL,%e",
755 [0x02]  0,0,            "RCL%S  CL,%e",
756 [0x03]  0,0,            "RCR%S  CL,%e",
757 [0x04]  0,0,            "SHL%S  CL,%e",
758 [0x05]  0,0,            "SHR%S  CL,%e",
759 [0x07]  0,0,            "SAR%S  CL,%e",
760 };
761
762 static Optable optabD8[8+8] =
763 {
764 [0x00]  0,0,            "FADDF  %e,F0",
765 [0x01]  0,0,            "FMULF  %e,F0",
766 [0x02]  0,0,            "FCOMF  %e,F0",
767 [0x03]  0,0,            "FCOMFP %e,F0",
768 [0x04]  0,0,            "FSUBF  %e,F0",
769 [0x05]  0,0,            "FSUBRF %e,F0",
770 [0x06]  0,0,            "FDIVF  %e,F0",
771 [0x07]  0,0,            "FDIVRF %e,F0",
772 [0x08]  0,0,            "FADDD  %f,F0",
773 [0x09]  0,0,            "FMULD  %f,F0",
774 [0x0a]  0,0,            "FCOMD  %f,F0",
775 [0x0b]  0,0,            "FCOMPD %f,F0",
776 [0x0c]  0,0,            "FSUBD  %f,F0",
777 [0x0d]  0,0,            "FSUBRD %f,F0",
778 [0x0e]  0,0,            "FDIVD  %f,F0",
779 [0x0f]  0,0,            "FDIVRD %f,F0",
780 };
781 /*
782  *      optabD9 and optabDB use the following encoding: 
783  *      if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
784  *      else instruction = optabDx[(modrm&0x3f)+8];
785  *
786  *      the instructions for MOD == 3, follow the 8 instructions
787  *      for the other MOD values stored at the front of the table.
788  */
789 static Optable optabD9[64+8] =
790 {
791 [0x00]  0,0,            "FMOVF  %e,F0",
792 [0x02]  0,0,            "FMOVF  F0,%e",
793 [0x03]  0,0,            "FMOVFP F0,%e",
794 [0x04]  0,0,            "FLDENV%S %e",
795 [0x05]  0,0,            "FLDCW  %e",
796 [0x06]  0,0,            "FSTENV%S %e",
797 [0x07]  0,0,            "FSTCW  %e",
798 [0x08]  0,0,            "FMOVD  F0,F0",         /* Mod R/M = 11xx xxxx*/
799 [0x09]  0,0,            "FMOVD  F1,F0",
800 [0x0a]  0,0,            "FMOVD  F2,F0",
801 [0x0b]  0,0,            "FMOVD  F3,F0",
802 [0x0c]  0,0,            "FMOVD  F4,F0",
803 [0x0d]  0,0,            "FMOVD  F5,F0",
804 [0x0e]  0,0,            "FMOVD  F6,F0",
805 [0x0f]  0,0,            "FMOVD  F7,F0",
806 [0x10]  0,0,            "FXCHD  F0,F0",
807 [0x11]  0,0,            "FXCHD  F1,F0",
808 [0x12]  0,0,            "FXCHD  F2,F0",
809 [0x13]  0,0,            "FXCHD  F3,F0",
810 [0x14]  0,0,            "FXCHD  F4,F0",
811 [0x15]  0,0,            "FXCHD  F5,F0",
812 [0x16]  0,0,            "FXCHD  F6,F0",
813 [0x17]  0,0,            "FXCHD  F7,F0",
814 [0x18]  0,0,            "FNOP",
815 [0x28]  0,0,            "FCHS",
816 [0x29]  0,0,            "FABS",
817 [0x2c]  0,0,            "FTST",
818 [0x2d]  0,0,            "FXAM",
819 [0x30]  0,0,            "FLD1",
820 [0x31]  0,0,            "FLDL2T",
821 [0x32]  0,0,            "FLDL2E",
822 [0x33]  0,0,            "FLDPI",
823 [0x34]  0,0,            "FLDLG2",
824 [0x35]  0,0,            "FLDLN2",
825 [0x36]  0,0,            "FLDZ",
826 [0x38]  0,0,            "F2XM1",
827 [0x39]  0,0,            "FYL2X",
828 [0x3a]  0,0,            "FPTAN",
829 [0x3b]  0,0,            "FPATAN",
830 [0x3c]  0,0,            "FXTRACT",
831 [0x3d]  0,0,            "FPREM1",
832 [0x3e]  0,0,            "FDECSTP",
833 [0x3f]  0,0,            "FNCSTP",
834 [0x40]  0,0,            "FPREM",
835 [0x41]  0,0,            "FYL2XP1",
836 [0x42]  0,0,            "FSQRT",
837 [0x43]  0,0,            "FSINCOS",
838 [0x44]  0,0,            "FRNDINT",
839 [0x45]  0,0,            "FSCALE",
840 [0x46]  0,0,            "FSIN",
841 [0x47]  0,0,            "FCOS",
842 };
843
844 static Optable optabDA[8+8] =
845 {
846 [0x00]  0,0,            "FADDL  %e,F0",
847 [0x01]  0,0,            "FMULL  %e,F0",
848 [0x02]  0,0,            "FCOML  %e,F0",
849 [0x03]  0,0,            "FCOMLP %e,F0",
850 [0x04]  0,0,            "FSUBL  %e,F0",
851 [0x05]  0,0,            "FSUBRL %e,F0",
852 [0x06]  0,0,            "FDIVL  %e,F0",
853 [0x07]  0,0,            "FDIVRL %e,F0",
854 [0x0d]  R1,0,           "FUCOMPP",
855 };
856
857 static Optable optabDB[8+64] =
858 {
859 [0x00]  0,0,            "FMOVL  %e,F0",
860 [0x02]  0,0,            "FMOVL  F0,%e",
861 [0x03]  0,0,            "FMOVLP F0,%e",
862 [0x05]  0,0,            "FMOVX  %e,F0",
863 [0x07]  0,0,            "FMOVXP F0,%e",
864 [0x2a]  0,0,            "FCLEX",
865 [0x2b]  0,0,            "FINIT",
866 };
867
868 static Optable optabDC[8+8] =
869 {
870 [0x00]  0,0,            "FADDD  %e,F0",
871 [0x01]  0,0,            "FMULD  %e,F0",
872 [0x02]  0,0,            "FCOMD  %e,F0",
873 [0x03]  0,0,            "FCOMDP %e,F0",
874 [0x04]  0,0,            "FSUBD  %e,F0",
875 [0x05]  0,0,            "FSUBRD %e,F0",
876 [0x06]  0,0,            "FDIVD  %e,F0",
877 [0x07]  0,0,            "FDIVRD %e,F0",
878 [0x08]  0,0,            "FADDD  F0,%f",
879 [0x09]  0,0,            "FMULD  F0,%f",
880 [0x0c]  0,0,            "FSUBRD F0,%f",
881 [0x0d]  0,0,            "FSUBD  F0,%f",
882 [0x0e]  0,0,            "FDIVRD F0,%f",
883 [0x0f]  0,0,            "FDIVD  F0,%f",
884 };
885
886 static Optable optabDD[8+8] =
887 {
888 [0x00]  0,0,            "FMOVD  %e,F0",
889 [0x02]  0,0,            "FMOVD  F0,%e",
890 [0x03]  0,0,            "FMOVDP F0,%e",
891 [0x04]  0,0,            "FRSTOR%S %e",
892 [0x06]  0,0,            "FSAVE%S %e",
893 [0x07]  0,0,            "FSTSW  %e",
894 [0x08]  0,0,            "FFREED %f",
895 [0x0a]  0,0,            "FMOVD  %f,F0",
896 [0x0b]  0,0,            "FMOVDP %f,F0",
897 [0x0c]  0,0,            "FUCOMD %f,F0",
898 [0x0d]  0,0,            "FUCOMDP %f,F0",
899 };
900
901 static Optable optabDE[8+8] =
902 {
903 [0x00]  0,0,            "FADDW  %e,F0",
904 [0x01]  0,0,            "FMULW  %e,F0",
905 [0x02]  0,0,            "FCOMW  %e,F0",
906 [0x03]  0,0,            "FCOMWP %e,F0",
907 [0x04]  0,0,            "FSUBW  %e,F0",
908 [0x05]  0,0,            "FSUBRW %e,F0",
909 [0x06]  0,0,            "FDIVW  %e,F0",
910 [0x07]  0,0,            "FDIVRW %e,F0",
911 [0x08]  0,0,            "FADDDP F0,%f",
912 [0x09]  0,0,            "FMULDP F0,%f",
913 [0x0b]  R1,0,           "FCOMPDP",
914 [0x0c]  0,0,            "FSUBRDP F0,%f",
915 [0x0d]  0,0,            "FSUBDP F0,%f",
916 [0x0e]  0,0,            "FDIVRDP F0,%f",
917 [0x0f]  0,0,            "FDIVDP F0,%f",
918 };
919
920 static Optable optabDF[8+8] =
921 {
922 [0x00]  0,0,            "FMOVW  %e,F0",
923 [0x02]  0,0,            "FMOVW  F0,%e",
924 [0x03]  0,0,            "FMOVWP F0,%e",
925 [0x04]  0,0,            "FBLD   %e",
926 [0x05]  0,0,            "FMOVL  %e,F0",
927 [0x06]  0,0,            "FBSTP  %e",
928 [0x07]  0,0,            "FMOVLP F0,%e",
929 [0x0c]  R0,0,           "FSTSW  %OAX",
930 };
931
932 static Optable optabF6[8] =
933 {
934 [0x00]  Ib,0,           "TESTB  %i,%e",
935 [0x02]  0,0,            "NOTB   %e",
936 [0x03]  0,0,            "NEGB   %e",
937 [0x04]  0,0,            "MULB   AL,%e",
938 [0x05]  0,0,            "IMULB  AL,%e",
939 [0x06]  0,0,            "DIVB   AL,%e",
940 [0x07]  0,0,            "IDIVB  AL,%e",
941 };
942
943 static Optable optabF7[8] =
944 {
945 [0x00]  Iwd,0,          "TEST%S %i,%e",
946 [0x02]  0,0,            "NOT%S  %e",
947 [0x03]  0,0,            "NEG%S  %e",
948 [0x04]  0,0,            "MUL%S  %OAX,%e",
949 [0x05]  0,0,            "IMUL%S %OAX,%e",
950 [0x06]  0,0,            "DIV%S  %OAX,%e",
951 [0x07]  0,0,            "IDIV%S %OAX,%e",
952 };
953
954 static Optable optabFE[8] =
955 {
956 [0x00]  0,0,            "INCB   %e",
957 [0x01]  0,0,            "DECB   %e",
958 };
959
960 static Optable optabFF[8] =
961 {
962 [0x00]  0,0,            "INC%S  %e",
963 [0x01]  0,0,            "DEC%S  %e",
964 [0x02]  JUMP,0,         "CALL*  %e",
965 [0x03]  JUMP,0,         "CALLF* %e",
966 [0x04]  JUMP,0,         "JMP*   %e",
967 [0x05]  JUMP,0,         "JMPF*  %e",
968 [0x06]  0,0,            "PUSHL  %e",
969 };
970
971 static Optable optable[256+1] =
972 {
973 [0x00]  RMB,0,          "ADDB   %r,%e",
974 [0x01]  RM,0,           "ADD%S  %r,%e",
975 [0x02]  RMB,0,          "ADDB   %e,%r",
976 [0x03]  RM,0,           "ADD%S  %e,%r",
977 [0x04]  Ib,0,           "ADDB   %i,AL",
978 [0x05]  Iwd,0,          "ADD%S  %i,%OAX",
979 [0x06]  0,0,            "PUSHL  ES",
980 [0x07]  0,0,            "POPL   ES",
981 [0x08]  RMB,0,          "ORB    %r,%e",
982 [0x09]  RM,0,           "OR%S   %r,%e",
983 [0x0a]  RMB,0,          "ORB    %e,%r",
984 [0x0b]  RM,0,           "OR%S   %e,%r",
985 [0x0c]  Ib,0,           "ORB    %i,AL",
986 [0x0d]  Iwd,0,          "OR%S   %i,%OAX",
987 [0x0e]  0,0,            "PUSHL  CS",
988 [0x0f]  AUXMM,0,        optab0F,
989 [0x10]  RMB,0,          "ADCB   %r,%e",
990 [0x11]  RM,0,           "ADC%S  %r,%e",
991 [0x12]  RMB,0,          "ADCB   %e,%r",
992 [0x13]  RM,0,           "ADC%S  %e,%r",
993 [0x14]  Ib,0,           "ADCB   %i,AL",
994 [0x15]  Iwd,0,          "ADC%S  %i,%OAX",
995 [0x16]  0,0,            "PUSHL  SS",
996 [0x17]  0,0,            "POPL   SS",
997 [0x18]  RMB,0,          "SBBB   %r,%e",
998 [0x19]  RM,0,           "SBB%S  %r,%e",
999 [0x1a]  RMB,0,          "SBBB   %e,%r",
1000 [0x1b]  RM,0,           "SBB%S  %e,%r",
1001 [0x1c]  Ib,0,           "SBBB   %i,AL",
1002 [0x1d]  Iwd,0,          "SBB%S  %i,%OAX",
1003 [0x1e]  0,0,            "PUSHL  DS",
1004 [0x1f]  0,0,            "POPL   DS",
1005 [0x20]  RMB,0,          "ANDB   %r,%e",
1006 [0x21]  RM,0,           "AND%S  %r,%e",
1007 [0x22]  RMB,0,          "ANDB   %e,%r",
1008 [0x23]  RM,0,           "AND%S  %e,%r",
1009 [0x24]  Ib,0,           "ANDB   %i,AL",
1010 [0x25]  Iwd,0,          "AND%S  %i,%OAX",
1011 [0x26]  SEG,0,          "ES:",
1012 [0x27]  0,0,            "DAA",
1013 [0x28]  RMB,0,          "SUBB   %r,%e",
1014 [0x29]  RM,0,           "SUB%S  %r,%e",
1015 [0x2a]  RMB,0,          "SUBB   %e,%r",
1016 [0x2b]  RM,0,           "SUB%S  %e,%r",
1017 [0x2c]  Ib,0,           "SUBB   %i,AL",
1018 [0x2d]  Iwd,0,          "SUB%S  %i,%OAX",
1019 [0x2e]  SEG,0,          "CS:",
1020 [0x2f]  0,0,            "DAS",
1021 [0x30]  RMB,0,          "XORB   %r,%e",
1022 [0x31]  RM,0,           "XOR%S  %r,%e",
1023 [0x32]  RMB,0,          "XORB   %e,%r",
1024 [0x33]  RM,0,           "XOR%S  %e,%r",
1025 [0x34]  Ib,0,           "XORB   %i,AL",
1026 [0x35]  Iwd,0,          "XOR%S  %i,%OAX",
1027 [0x36]  SEG,0,          "SS:",
1028 [0x37]  0,0,            "AAA",
1029 [0x38]  RMB,0,          "CMPB   %r,%e",
1030 [0x39]  RM,0,           "CMP%S  %r,%e",
1031 [0x3a]  RMB,0,          "CMPB   %e,%r",
1032 [0x3b]  RM,0,           "CMP%S  %e,%r",
1033 [0x3c]  Ib,0,           "CMPB   %i,AL",
1034 [0x3d]  Iwd,0,          "CMP%S  %i,%OAX",
1035 [0x3e]  SEG,0,          "DS:",
1036 [0x3f]  0,0,            "AAS",
1037 [0x40]  0,0,            "INC%S  %OAX",
1038 [0x41]  0,0,            "INC%S  %OCX",
1039 [0x42]  0,0,            "INC%S  %ODX",
1040 [0x43]  0,0,            "INC%S  %OBX",
1041 [0x44]  0,0,            "INC%S  %OSP",
1042 [0x45]  0,0,            "INC%S  %OBP",
1043 [0x46]  0,0,            "INC%S  %OSI",
1044 [0x47]  0,0,            "INC%S  %ODI",
1045 [0x48]  0,0,            "DEC%S  %OAX",
1046 [0x49]  0,0,            "DEC%S  %OCX",
1047 [0x4a]  0,0,            "DEC%S  %ODX",
1048 [0x4b]  0,0,            "DEC%S  %OBX",
1049 [0x4c]  0,0,            "DEC%S  %OSP",
1050 [0x4d]  0,0,            "DEC%S  %OBP",
1051 [0x4e]  0,0,            "DEC%S  %OSI",
1052 [0x4f]  0,0,            "DEC%S  %ODI",
1053 [0x50]  0,0,            "PUSH%S %OAX",
1054 [0x51]  0,0,            "PUSH%S %OCX",
1055 [0x52]  0,0,            "PUSH%S %ODX",
1056 [0x53]  0,0,            "PUSH%S %OBX",
1057 [0x54]  0,0,            "PUSH%S %OSP",
1058 [0x55]  0,0,            "PUSH%S %OBP",
1059 [0x56]  0,0,            "PUSH%S %OSI",
1060 [0x57]  0,0,            "PUSH%S %ODI",
1061 [0x58]  0,0,            "POP%S  %OAX",
1062 [0x59]  0,0,            "POP%S  %OCX",
1063 [0x5a]  0,0,            "POP%S  %ODX",
1064 [0x5b]  0,0,            "POP%S  %OBX",
1065 [0x5c]  0,0,            "POP%S  %OSP",
1066 [0x5d]  0,0,            "POP%S  %OBP",
1067 [0x5e]  0,0,            "POP%S  %OSI",
1068 [0x5f]  0,0,            "POP%S  %ODI",
1069 [0x60]  0,0,            "PUSHA%S",
1070 [0x61]  0,0,            "POPA%S",
1071 [0x62]  RMM,0,          "BOUND  %e,%r",
1072 [0x63]  RM,0,           "ARPL   %r,%e",
1073 [0x64]  SEG,0,          "FS:",
1074 [0x65]  SEG,0,          "GS:",
1075 [0x66]  OPOVER,0,       "",
1076 [0x67]  ADDOVER,0,      "",
1077 [0x68]  Iwd,0,          "PUSH%S %i",
1078 [0x69]  RM,Iwd,         "IMUL%S %e,%i,%r",
1079 [0x6a]  Ib,0,           "PUSH%S %i",
1080 [0x6b]  RM,Ibs,         "IMUL%S %e,%i,%r",
1081 [0x6c]  0,0,            "INSB   DX,(%ODI)",
1082 [0x6d]  0,0,            "INS%S  DX,(%ODI)",
1083 [0x6e]  0,0,            "OUTSB  (%ASI),DX",
1084 [0x6f]  0,0,            "OUTS%S (%ASI),DX",
1085 [0x70]  Jbs,0,          "JOS    %p",
1086 [0x71]  Jbs,0,          "JOC    %p",
1087 [0x72]  Jbs,0,          "JCS    %p",
1088 [0x73]  Jbs,0,          "JCC    %p",
1089 [0x74]  Jbs,0,          "JEQ    %p",
1090 [0x75]  Jbs,0,          "JNE    %p",
1091 [0x76]  Jbs,0,          "JLS    %p",
1092 [0x77]  Jbs,0,          "JHI    %p",
1093 [0x78]  Jbs,0,          "JMI    %p",
1094 [0x79]  Jbs,0,          "JPL    %p",
1095 [0x7a]  Jbs,0,          "JPS    %p",
1096 [0x7b]  Jbs,0,          "JPC    %p",
1097 [0x7c]  Jbs,0,          "JLT    %p",
1098 [0x7d]  Jbs,0,          "JGE    %p",
1099 [0x7e]  Jbs,0,          "JLE    %p",
1100 [0x7f]  Jbs,0,          "JGT    %p",
1101 [0x80]  RMOPB,0,        optab80,
1102 [0x81]  RMOP,0,         optab81,
1103 [0x83]  RMOP,0,         optab83,
1104 [0x84]  RMB,0,          "TESTB  %r,%e",
1105 [0x85]  RM,0,           "TEST%S %r,%e",
1106 [0x86]  RMB,0,          "XCHGB  %r,%e",
1107 [0x87]  RM,0,           "XCHG%S %r,%e",
1108 [0x88]  RMB,0,          "MOVB   %r,%e",
1109 [0x89]  RM,0,           "MOV%S  %r,%e",
1110 [0x8a]  RMB,0,          "MOVB   %e,%r",
1111 [0x8b]  RM,0,           "MOV%S  %e,%r",
1112 [0x8c]  RM,0,           "MOVW   %g,%e",
1113 [0x8d]  RM,0,           "LEA%S  %e,%r",
1114 [0x8e]  RM,0,           "MOVW   %e,%g",
1115 [0x8f]  RM,0,           "POP%S  %e",
1116 [0x90]  0,0,            "NOP",
1117 [0x91]  0,0,            "XCHG   %OCX,%OAX",
1118 [0x92]  0,0,            "XCHG   %ODX,%OAX",
1119 [0x93]  0,0,            "XCHG   %OBX,%OAX",
1120 [0x94]  0,0,            "XCHG   %OSP,%OAX",
1121 [0x95]  0,0,            "XCHG   %OBP,%OAX",
1122 [0x96]  0,0,            "XCHG   %OSI,%OAX",
1123 [0x97]  0,0,            "XCHG   %ODI,%OAX",
1124 [0x98]  0,0,            "%W",                   /* miserable CBW or CWDE */
1125 [0x99]  0,0,            "%w",                   /* idiotic CWD or CDQ */
1126 [0x9a]  PTR,0,          "CALL%S %d",
1127 [0x9b]  0,0,            "WAIT",
1128 [0x9c]  0,0,            "PUSHF",
1129 [0x9d]  0,0,            "POPF",
1130 [0x9e]  0,0,            "SAHF",
1131 [0x9f]  0,0,            "LAHF",
1132 [0xa0]  Awd,0,          "MOVB   %i,AL",
1133 [0xa1]  Awd,0,          "MOV%S  %i,%OAX",
1134 [0xa2]  Awd,0,          "MOVB   AL,%i",
1135 [0xa3]  Awd,0,          "MOV%S  %OAX,%i",
1136 [0xa4]  0,0,            "MOVSB  (%ASI),(%ADI)",
1137 [0xa5]  0,0,            "MOVS%S (%ASI),(%ADI)",
1138 [0xa6]  0,0,            "CMPSB  (%ASI),(%ADI)",
1139 [0xa7]  0,0,            "CMPS%S (%ASI),(%ADI)",
1140 [0xa8]  Ib,0,           "TESTB  %i,AL",
1141 [0xa9]  Iwd,0,          "TEST%S %i,%OAX",
1142 [0xaa]  0,0,            "STOSB  AL,(%ADI)",
1143 [0xab]  0,0,            "STOS%S %OAX,(%ADI)",
1144 [0xac]  0,0,            "LODSB  (%ASI),AL",
1145 [0xad]  0,0,            "LODS%S (%ASI),%OAX",
1146 [0xae]  0,0,            "SCASB  (%ADI),AL",
1147 [0xaf]  0,0,            "SCAS%S (%ADI),%OAX",
1148 [0xb0]  Ib,0,           "MOVB   %i,AL",
1149 [0xb1]  Ib,0,           "MOVB   %i,CL",
1150 [0xb2]  Ib,0,           "MOVB   %i,DL",
1151 [0xb3]  Ib,0,           "MOVB   %i,BL",
1152 [0xb4]  Ib,0,           "MOVB   %i,AH",
1153 [0xb5]  Ib,0,           "MOVB   %i,CH",
1154 [0xb6]  Ib,0,           "MOVB   %i,DH",
1155 [0xb7]  Ib,0,           "MOVB   %i,BH",
1156 [0xb8]  Iwdq,0,         "MOV%S  %i,%OAX",
1157 [0xb9]  Iwdq,0,         "MOV%S  %i,%OCX",
1158 [0xba]  Iwdq,0,         "MOV%S  %i,%ODX",
1159 [0xbb]  Iwdq,0,         "MOV%S  %i,%OBX",
1160 [0xbc]  Iwdq,0,         "MOV%S  %i,%OSP",
1161 [0xbd]  Iwdq,0,         "MOV%S  %i,%OBP",
1162 [0xbe]  Iwdq,0,         "MOV%S  %i,%OSI",
1163 [0xbf]  Iwdq,0,         "MOV%S  %i,%ODI",
1164 [0xc0]  RMOPB,0,        optabC0,
1165 [0xc1]  RMOP,0,         optabC1,
1166 [0xc2]  Iw,0,           "RET    %i",
1167 [0xc3]  RET,0,          "RET",
1168 [0xc4]  RM,0,           "LES    %e,%r",
1169 [0xc5]  RM,0,           "LDS    %e,%r",
1170 [0xc6]  RMB,Ib,         "MOVB   %i,%e",
1171 [0xc7]  RM,Iwd,         "MOV%S  %i,%e",
1172 [0xc8]  Iw2,Ib,         "ENTER  %i,%I",         /* loony ENTER */
1173 [0xc9]  RET,0,          "LEAVE",                /* bizarre LEAVE */
1174 [0xca]  Iw,0,           "RETF   %i",
1175 [0xcb]  RET,0,          "RETF",
1176 [0xcc]  0,0,            "INT    3",
1177 [0xcd]  Ib,0,           "INTB   %i",
1178 [0xce]  0,0,            "INTO",
1179 [0xcf]  0,0,            "IRET",
1180 [0xd0]  RMOPB,0,        optabD0,
1181 [0xd1]  RMOP,0,         optabD1,
1182 [0xd2]  RMOPB,0,        optabD2,
1183 [0xd3]  RMOP,0,         optabD3,
1184 [0xd4]  OA,0,           "AAM",
1185 [0xd5]  OA,0,           "AAD",
1186 [0xd7]  0,0,            "XLAT",
1187 [0xd8]  FRMOP,0,        optabD8,
1188 [0xd9]  FRMEX,0,        optabD9,
1189 [0xda]  FRMOP,0,        optabDA,
1190 [0xdb]  FRMEX,0,        optabDB,
1191 [0xdc]  FRMOP,0,        optabDC,
1192 [0xdd]  FRMOP,0,        optabDD,
1193 [0xde]  FRMOP,0,        optabDE,
1194 [0xdf]  FRMOP,0,        optabDF,
1195 [0xe0]  Jbs,0,          "LOOPNE %p",
1196 [0xe1]  Jbs,0,          "LOOPE  %p",
1197 [0xe2]  Jbs,0,          "LOOP   %p",
1198 [0xe3]  Jbs,0,          "JCXZ   %p",
1199 [0xe4]  Ib,0,           "INB    %i,AL",
1200 [0xe5]  Ib,0,           "IN%S   %i,%OAX",
1201 [0xe6]  Ib,0,           "OUTB   AL,%i",
1202 [0xe7]  Ib,0,           "OUT%S  %OAX,%i",
1203 [0xe8]  Iwds,0,         "CALL   %p",
1204 [0xe9]  Iwds,0,         "JMP    %p",
1205 [0xea]  PTR,0,          "JMP    %d",
1206 [0xeb]  Jbs,0,          "JMP    %p",
1207 [0xec]  0,0,            "INB    DX,AL",
1208 [0xed]  0,0,            "IN%S   DX,%OAX",
1209 [0xee]  0,0,            "OUTB   AL,DX",
1210 [0xef]  0,0,            "OUT%S  %OAX,DX",
1211 [0xf0]  PRE,0,          "LOCK",
1212 [0xf2]  OPRE,0,         "REPNE",
1213 [0xf3]  OPRE,0,         "REP",
1214 [0xf4]  0,0,            "HLT",
1215 [0xf5]  0,0,            "CMC",
1216 [0xf6]  RMOPB,0,        optabF6,
1217 [0xf7]  RMOP,0,         optabF7,
1218 [0xf8]  0,0,            "CLC",
1219 [0xf9]  0,0,            "STC",
1220 [0xfa]  0,0,            "CLI",
1221 [0xfb]  0,0,            "STI",
1222 [0xfc]  0,0,            "CLD",
1223 [0xfd]  0,0,            "STD",
1224 [0xfe]  RMOPB,0,        optabFE,
1225 [0xff]  RMOP,0,         optabFF,
1226 [0x100] RM,0,           "MOVLQSX        %e,%r",
1227 };
1228
1229 /*
1230  *  get a byte of the instruction
1231  */
1232 static int
1233 igetc(Map *map, Instr *ip, uchar *c)
1234 {
1235         if(ip->n+1 > sizeof(ip->mem)){
1236                 werrstr("instruction too long");
1237                 return -1;
1238         }
1239         if (get1(map, ip->addr+ip->n, c, 1) < 0) {
1240                 werrstr("can't read instruction: %r");
1241                 return -1;
1242         }
1243         ip->mem[ip->n++] = *c;
1244         return 1;
1245 }
1246
1247 /*
1248  *  get two bytes of the instruction
1249  */
1250 static int
1251 igets(Map *map, Instr *ip, ushort *sp)
1252 {
1253         uchar c;
1254         ushort s;
1255
1256         if (igetc(map, ip, &c) < 0)
1257                 return -1;
1258         s = c;
1259         if (igetc(map, ip, &c) < 0)
1260                 return -1;
1261         s |= (c<<8);
1262         *sp = s;
1263         return 1;
1264 }
1265
1266 /*
1267  *  get 4 bytes of the instruction
1268  */
1269 static int
1270 igetl(Map *map, Instr *ip, ulong *lp)
1271 {
1272         ushort s;
1273         long    l;
1274
1275         if (igets(map, ip, &s) < 0)
1276                 return -1;
1277         l = s;
1278         if (igets(map, ip, &s) < 0)
1279                 return -1;
1280         l |= (s<<16);
1281         *lp = l;
1282         return 1;
1283 }
1284
1285 /*
1286  *  get 8 bytes of the instruction
1287  */
1288 static int
1289 igetq(Map *map, Instr *ip, vlong *qp)
1290 {
1291         ulong   l;
1292         uvlong q;
1293
1294         if (igetl(map, ip, &l) < 0)
1295                 return -1;
1296         q = l;
1297         if (igetl(map, ip, &l) < 0)
1298                 return -1;
1299         q |= ((uvlong)l<<32);
1300         *qp = q;
1301         return 1;
1302 }
1303
1304 static int
1305 getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
1306 {
1307         uchar c;
1308         ushort s;
1309
1310         if (mod > 2)
1311                 return 1;
1312         if (mod == 1) {
1313                 if (igetc(map, ip, &c) < 0)
1314                         return -1;
1315                 if (c&0x80)
1316                         ip->disp = c|0xffffff00;
1317                 else
1318                         ip->disp = c&0xff;
1319         } else if (mod == 2 || rm == code) {
1320                 if (ip->asize == 'E') {
1321                         if (igetl(map, ip, &ip->disp) < 0)
1322                                 return -1;
1323                         if (mod == 0)
1324                                 ip->rip = pcrel;
1325                 } else {
1326                         if (igets(map, ip, &s) < 0)
1327                                 return -1;
1328                         if (s&0x8000)
1329                                 ip->disp = s|0xffff0000;
1330                         else
1331                                 ip->disp = s;
1332                 }
1333                 if (mod == 0)
1334                         ip->base = -1;
1335         }
1336         return 1;
1337 }
1338
1339 static int
1340 modrm(Map *map, Instr *ip, uchar c)
1341 {
1342         uchar rm, mod;
1343
1344         mod = (c>>6)&3;
1345         rm = c&7;
1346         ip->mod = mod;
1347         ip->base = rm;
1348         ip->reg = (c>>3)&7;
1349         ip->rip = 0;
1350         if (mod == 3)                   /* register */
1351                 return 1;
1352         if (ip->asize == 0) {           /* 16-bit mode */
1353                 switch(rm) {
1354                 case 0:
1355                         ip->base = BX; ip->index = SI;
1356                         break;
1357                 case 1:
1358                         ip->base = BX; ip->index = DI;
1359                         break;
1360                 case 2:
1361                         ip->base = BP; ip->index = SI;
1362                         break;
1363                 case 3:
1364                         ip->base = BP; ip->index = DI;
1365                         break;
1366                 case 4:
1367                         ip->base = SI;
1368                         break;
1369                 case 5:
1370                         ip->base = DI;
1371                         break;
1372                 case 6:
1373                         ip->base = BP;
1374                         break;
1375                 case 7:
1376                         ip->base = BX;
1377                         break;
1378                 default:
1379                         break;
1380                 }
1381                 return getdisp(map, ip, mod, rm, 6, 0);
1382         }
1383         if (rm == 4) {  /* scummy sib byte */
1384                 if (igetc(map, ip, &c) < 0)
1385                         return -1;
1386                 ip->ss = (c>>6)&0x03;
1387                 ip->index = (c>>3)&0x07;
1388                 if (ip->index == 4)
1389                         ip->index = -1;
1390                 ip->base = c&0x07;
1391                 return getdisp(map, ip, mod, ip->base, 5, 0);
1392         }
1393         return getdisp(map, ip, mod, rm, 5, ip->amd64);
1394 }
1395
1396 static Optable *
1397 mkinstr(Map *map, Instr *ip, uvlong pc)
1398 {
1399         int i, n, norex;
1400         uchar c;
1401         ushort s;
1402         Optable *op, *obase;
1403         char buf[128];
1404
1405         memset(ip, 0, sizeof(*ip));
1406         norex = 1;
1407         ip->base = -1;
1408         ip->index = -1;
1409         if(asstype == AI8086)
1410                 ip->osize = 'W';
1411         else {
1412                 ip->osize = 'L';
1413                 ip->asize = 'E';
1414                 ip->amd64 = asstype != AI386;
1415                 norex = 0;
1416         }
1417         ip->addr = pc;
1418         if (igetc(map, ip, &c) < 0)
1419                 return 0;
1420         obase = optable;
1421 newop:
1422         if(ip->amd64 && !norex){
1423                 if(c >= 0x40 && c <= 0x4f) {
1424                         ip->rex = c;
1425                         if(igetc(map, ip, &c) < 0)
1426                                 return 0;
1427                 }
1428                 if(c == 0x63){
1429                         op = &obase[0x100];     /* MOVLQSX */
1430                         goto hack;
1431                 }
1432         }
1433         op = &obase[c];
1434 hack:
1435         if (op->proto == 0) {
1436 badop:
1437                 n = snprint(buf, sizeof(buf), "opcode: ??");
1438                 for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
1439                         _hexify(buf+n, ip->mem[i], 1);
1440                 strcpy(buf+n, "??");
1441                 werrstr(buf);
1442                 return 0;
1443         }
1444         for(i = 0; i < 2 && op->operand[i]; i++) {
1445                 switch(op->operand[i]) {
1446                 case Ib:        /* 8-bit immediate - (no sign extension)*/
1447                         if (igetc(map, ip, &c) < 0)
1448                                 return 0;
1449                         ip->imm = c&0xff;
1450                         ip->imm64 = ip->imm;
1451                         break;
1452                 case Jbs:       /* 8-bit jump immediate (sign extended) */
1453                         if (igetc(map, ip, &c) < 0)
1454                                 return 0;
1455                         if (c&0x80)
1456                                 ip->imm = c|0xffffff00;
1457                         else
1458                                 ip->imm = c&0xff;
1459                         ip->imm64 = (long)ip->imm;
1460                         ip->jumptype = Jbs;
1461                         break;
1462                 case Ibs:       /* 8-bit immediate (sign extended) */
1463                         if (igetc(map, ip, &c) < 0)
1464                                 return 0;
1465                         if (c&0x80)
1466                                 if (ip->osize == 'L')
1467                                         ip->imm = c|0xffffff00;
1468                                 else
1469                                         ip->imm = c|0xff00;
1470                         else
1471                                 ip->imm = c&0xff;
1472                         ip->imm64 = (long)ip->imm;
1473                         break;
1474                 case Iw:        /* 16-bit immediate -> imm */
1475                         if (igets(map, ip, &s) < 0)
1476                                 return 0;
1477                         ip->imm = s&0xffff;
1478                         ip->imm64 = ip->imm;
1479                         ip->jumptype = Iw;
1480                         break;
1481                 case Iw2:       /* 16-bit immediate -> in imm2*/
1482                         if (igets(map, ip, &s) < 0)
1483                                 return 0;
1484                         ip->imm2 = s&0xffff;
1485                         break;
1486                 case Iwd:       /* Operand-sized immediate (no sign extension unless 64 bits)*/
1487                         if (ip->osize == 'L') {
1488                                 if (igetl(map, ip, &ip->imm) < 0)
1489                                         return 0;
1490                                 ip->imm64 = ip->imm;
1491                                 if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
1492                                         ip->imm64 |= (vlong)~0 << 32;
1493                         } else {
1494                                 if (igets(map, ip, &s)< 0)
1495                                         return 0;
1496                                 ip->imm = s&0xffff;
1497                                 ip->imm64 = ip->imm;
1498                         }
1499                         break;
1500                 case Iwdq:      /* Operand-sized immediate, possibly big */
1501                         if (ip->osize == 'L') {
1502                                 if (igetl(map, ip, &ip->imm) < 0)
1503                                         return 0;
1504                                 ip->imm64 = ip->imm;
1505                                 if (ip->rex & REXW) {
1506                                         ulong l;
1507                                         if (igetl(map, ip, &l) < 0)
1508                                                 return 0;
1509                                         ip->imm64 |= (uvlong)l << 32;
1510                                 }
1511                         } else {
1512                                 if (igets(map, ip, &s)< 0)
1513                                         return 0;
1514                                 ip->imm = s&0xffff;
1515                         }
1516                         break;
1517                 case Awd:       /* Address-sized immediate (no sign extension)*/
1518                         if (ip->asize == 'E') {
1519                                 if (igetl(map, ip, &ip->imm) < 0)
1520                                         return 0;
1521                                 /* TO DO: REX */
1522                         } else {
1523                                 if (igets(map, ip, &s)< 0)
1524                                         return 0;
1525                                 ip->imm = s&0xffff;
1526                         }
1527                         break;
1528                 case Iwds:      /* Operand-sized immediate (sign extended) */
1529                         if (ip->osize == 'L') {
1530                                 if (igetl(map, ip, &ip->imm) < 0)
1531                                         return 0;
1532                         } else {
1533                                 if (igets(map, ip, &s)< 0)
1534                                         return 0;
1535                                 if (s&0x8000)
1536                                         ip->imm = s|0xffff0000;
1537                                 else
1538                                         ip->imm = s&0xffff;
1539                         }
1540                         ip->jumptype = Iwds;
1541                         break;
1542                 case OA:        /* literal 0x0a byte */
1543                         if (igetc(map, ip, &c) < 0)
1544                                 return 0;
1545                         if (c != 0x0a)
1546                                 goto badop;
1547                         break;
1548                 case R0:        /* base register must be R0 */
1549                         if (ip->base != 0)
1550                                 goto badop;
1551                         break;
1552                 case R1:        /* base register must be R1 */
1553                         if (ip->base != 1)
1554                                 goto badop;
1555                         break;
1556                 case RMB:       /* R/M field with byte register (/r)*/
1557                         if (igetc(map, ip, &c) < 0)
1558                                 return 0;
1559                         if (modrm(map, ip, c) < 0)
1560                                 return 0;
1561                         ip->osize = 'B';
1562                         break;
1563                 case RM:        /* R/M field with register (/r) */
1564                         if (igetc(map, ip, &c) < 0)
1565                                 return 0;
1566                         if (modrm(map, ip, c) < 0)
1567                                 return 0;
1568                         break;
1569                 case RMOPB:     /* R/M field with op code (/digit) */
1570                         if (igetc(map, ip, &c) < 0)
1571                                 return 0;
1572                         if (modrm(map, ip, c) < 0)
1573                                 return 0;
1574                         c = ip->reg;            /* secondary op code */
1575                         obase = (Optable*)op->proto;
1576                         ip->osize = 'B';
1577                         goto newop;
1578                 case RMOP:      /* R/M field with op code (/digit) */
1579                         if (igetc(map, ip, &c) < 0)
1580                                 return 0;
1581                         if (modrm(map, ip, c) < 0)
1582                                 return 0;
1583                         obase = (Optable*)op->proto;
1584                         if(ip->amd64 && obase == optab0F01 && c == 0xF8)
1585                                 return optab0F01F8;
1586                         c = ip->reg;
1587                         goto newop;
1588                 case FRMOP:     /* FP R/M field with op code (/digit) */
1589                         if (igetc(map, ip, &c) < 0)
1590                                 return 0;
1591                         if (modrm(map, ip, c) < 0)
1592                                 return 0;
1593                         if ((c&0xc0) == 0xc0)
1594                                 c = ip->reg+8;          /* 16 entry table */
1595                         else
1596                                 c = ip->reg;
1597                         obase = (Optable*)op->proto;
1598                         goto newop;
1599                 case FRMEX:     /* Extended FP R/M field with op code (/digit) */
1600                         if (igetc(map, ip, &c) < 0)
1601                                 return 0;
1602                         if (modrm(map, ip, c) < 0)
1603                                 return 0;
1604                         if ((c&0xc0) == 0xc0)
1605                                 c = (c&0x3f)+8;         /* 64-entry table */
1606                         else
1607                                 c = ip->reg;
1608                         obase = (Optable*)op->proto;
1609                         goto newop;
1610                 case RMR:       /* R/M register only (mod = 11) */
1611                         if (igetc(map, ip, &c) < 0)
1612                                 return 0;
1613                         if ((c&0xc0) != 0xc0) {
1614                                 werrstr("invalid R/M register: %x", c);
1615                                 return 0;
1616                         }
1617                         if (modrm(map, ip, c) < 0)
1618                                 return 0;
1619                         break;
1620                 case RMM:       /* R/M register only (mod = 11) */
1621                         if (igetc(map, ip, &c) < 0)
1622                                 return 0;
1623                         if ((c&0xc0) == 0xc0) {
1624                                 werrstr("invalid R/M memory mode: %x", c);
1625                                 return 0;
1626                         }
1627                         if (modrm(map, ip, c) < 0)
1628                                 return 0;
1629                         break;
1630                 case PTR:       /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
1631                         if (ip->osize == 'L') {
1632                                 if (igetl(map, ip, &ip->disp) < 0)
1633                                         return 0;
1634                         } else {
1635                                 if (igets(map, ip, &s)< 0)
1636                                         return 0;
1637                                 ip->disp = s&0xffff;
1638                         }
1639                         if (igets(map, ip, (ushort*)&ip->seg) < 0)
1640                                 return 0;
1641                         ip->jumptype = PTR;
1642                         break;
1643                 case AUXMM:     /* Multi-byte op code; prefix determines table selection */
1644                         if (igetc(map, ip, &c) < 0)
1645                                 return 0;
1646                         obase = (Optable*)op->proto;
1647                         switch (ip->opre) {
1648                         case 0x66:      op = optab660F; break;
1649                         case 0xF2:      op = optabF20F; break;
1650                         case 0xF3:      op = optabF30F; break;
1651                         default:        op = nil; break;
1652                         }
1653                         if(op != nil && op[c].proto != nil)
1654                                 obase = op;
1655                         norex = 1;      /* no more rex prefixes */
1656                         /* otherwise the optab entry captures it */
1657                         goto newop;
1658                 case AUX:       /* Multi-byte op code - Auxiliary table */
1659                         obase = (Optable*)op->proto;
1660                         if (igetc(map, ip, &c) < 0)
1661                                 return 0;
1662                         goto newop;
1663                 case OPRE:      /* Instr Prefix or media op */
1664                         ip->opre = c;
1665                         /* fall through */
1666                 case PRE:       /* Instr Prefix */
1667                         ip->prefix = (char*)op->proto;
1668                         if (igetc(map, ip, &c) < 0)
1669                                 return 0;
1670                         if (ip->opre && c == 0x0F)
1671                                 ip->prefix = 0;
1672                         goto newop;
1673                 case SEG:       /* Segment Prefix */
1674                         ip->segment = (char*)op->proto;
1675                         if (igetc(map, ip, &c) < 0)
1676                                 return 0;
1677                         goto newop;
1678                 case OPOVER:    /* Operand size override */
1679                         ip->opre = c;
1680                         ip->osize = 'W';
1681                         if (igetc(map, ip, &c) < 0)
1682                                 return 0;
1683                         if (c == 0x0F)
1684                                 ip->osize = 'L';
1685                         else if (ip->amd64 && (c&0xF0) == 0x40)
1686                                 ip->osize = 'Q';
1687                         goto newop;
1688                 case ADDOVER:   /* Address size override */
1689                         ip->asize = 0;
1690                         if (igetc(map, ip, &c) < 0)
1691                                 return 0;
1692                         goto newop;
1693                 case JUMP:      /* mark instruction as JUMP or RET */
1694                 case RET:
1695                         ip->jumptype = op->operand[i];
1696                         break;
1697                 default:
1698                         werrstr("bad operand type %d", op->operand[i]);
1699                         return 0;
1700                 }
1701         }
1702         return op;
1703 }
1704
1705 #pragma varargck        argpos  bprint          2
1706
1707 static void
1708 bprint(Instr *ip, char *fmt, ...)
1709 {
1710         va_list arg;
1711
1712         va_start(arg, fmt);
1713         ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
1714         va_end(arg);
1715 }
1716
1717 /*
1718  *  if we want to call 16 bit regs AX,BX,CX,...
1719  *  and 32 bit regs EAX,EBX,ECX,... then
1720  *  change the defs of ANAME and ONAME to:
1721  *  #define     ANAME(ip)       ((ip->asize == 'E' ? "E" : "")
1722  *  #define     ONAME(ip)       ((ip)->osize == 'L' ? "E" : "")
1723  */
1724 #define ANAME(ip)       ""
1725 #define ONAME(ip)       ""
1726
1727 static char *reg[] =  {
1728 [AX]    "AX",
1729 [CX]    "CX",
1730 [DX]    "DX",
1731 [BX]    "BX",
1732 [SP]    "SP",
1733 [BP]    "BP",
1734 [SI]    "SI",
1735 [DI]    "DI",
1736
1737         /* amd64 */
1738 [R8]    "R8",
1739 [R9]    "R9",
1740 [R10]   "R10",
1741 [R11]   "R11",
1742 [R12]   "R12",
1743 [R13]   "R13",
1744 [R14]   "R14",
1745 [R15]   "R15",
1746 };
1747
1748 static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
1749 static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
1750         "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
1751 static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
1752
1753 static void
1754 plocal(Instr *ip)
1755 {
1756         int ret;
1757         long offset;
1758         Symbol s;
1759         char *reg;
1760
1761         offset = ip->disp;
1762         if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
1763                 bprint(ip, "%lux(SP)", offset);
1764                 return;
1765         }
1766
1767         if (s.value > ip->disp) {
1768                 ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
1769                 reg = "(SP)";
1770         } else {
1771                 offset -= s.value;
1772                 ret = getauto(&s, offset, CPARAM, &s);
1773                 reg = "(FP)";
1774         }
1775         if (ret)
1776                 bprint(ip, "%s+", s.name);
1777         else
1778                 offset = ip->disp;
1779         bprint(ip, "%lux%s", offset, reg);
1780 }
1781
1782 static int
1783 isjmp(Instr *ip)
1784 {
1785         switch(ip->jumptype){
1786         case Iwds:
1787         case Jbs:
1788         case JUMP:
1789                 return 1;
1790         default:
1791                 return 0;
1792         }
1793 }
1794
1795 /*
1796  * This is too smart for its own good, but it really is nice
1797  * to have accurate translations when debugging, and it
1798  * helps us identify which code is different in binaries that
1799  * are changed on sources.
1800  */
1801 static int
1802 issymref(Instr *ip, Symbol *s, long w, long val)
1803 {
1804         Symbol next, tmp;
1805         long isstring, size;
1806
1807         if (isjmp(ip))
1808                 return 1;
1809         if (s->class==CTEXT && w==0)
1810                 return 1;
1811         if (s->class==CDATA) {
1812                 /* use first bss symbol (or "end") rather than edata */
1813                 if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
1814                         if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value)
1815                         || (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value))
1816                                 *s = tmp;
1817                 }
1818                 if (w == 0)
1819                         return 1;
1820                 for (next=*s; next.value==s->value; next=tmp)
1821                         if (!globalsym(&tmp, next.index+1))
1822                                 break;
1823                 size = next.value - s->value;
1824                 if (w >= size)
1825                         return 0;
1826                 if (w > size-w)
1827                         w = size-w;
1828                 /* huge distances are usually wrong except in .string */
1829                 isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
1830                 if (w > 8192 && !isstring)
1831                         return 0;
1832                 /* medium distances are tricky - look for constants */
1833                 /* near powers of two */
1834                 if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
1835                         return 0;
1836                 return 1;
1837         }
1838         return 0;
1839 }
1840
1841 static void
1842 immediate(Instr *ip, vlong val)
1843 {
1844         Symbol s;
1845         long w;
1846
1847         if (findsym(val, CANY, &s)) {           /* TO DO */
1848                 w = val - s.value;
1849                 if (w < 0)
1850                         w = -w;
1851                 if (issymref(ip, &s, w, val)) {
1852                         if (w)
1853                                 bprint(ip, "%s+%lux(SB)", s.name, w);
1854                         else
1855                                 bprint(ip, "%s(SB)", s.name);
1856                         return;
1857                 }
1858 /*
1859                 if (s.class==CDATA && globalsym(&s, s.index+1)) {
1860                         w = s.value - val;
1861                         if (w < 0)
1862                                 w = -w;
1863                         if (w < 4096) {
1864                                 bprint(ip, "%s-%lux(SB)", s.name, w);
1865                                 return;
1866                         }
1867                 }
1868 */
1869         }
1870         if((ip->rex & REXW) == 0)
1871                 bprint(ip, "%lux", (long)val);
1872         else
1873                 bprint(ip, "%llux", val);
1874 }
1875
1876 static void
1877 pea(Instr *ip)
1878 {
1879         if (ip->mod == 3) {
1880                 if (ip->osize == 'B')
1881                         bprint(ip, (ip->rex? breg64: breg)[ip->rex&REXB? ip->base+8: ip->base]);
1882                 else if(ip->rex & REXB)
1883                         bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]);
1884                 else
1885                         bprint(ip, "%s%s", ANAME(ip), reg[ip->base]);
1886                 return;
1887         }
1888         if (ip->segment)
1889                 bprint(ip, ip->segment);
1890         if (ip->asize == 'E' && ip->base == SP)
1891                 plocal(ip);
1892         else {
1893                 if (ip->base < 0)
1894                         immediate(ip, ip->disp);
1895                 else {
1896                         bprint(ip, "%lux", ip->disp);
1897                         if(ip->rip)
1898                                 bprint(ip, "(RIP)");
1899                         bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
1900                 }
1901         }
1902         if (ip->index >= 0)
1903                 bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
1904 }
1905
1906 static void
1907 prinstr(Instr *ip, char *fmt)
1908 {
1909         vlong v;
1910
1911         if (ip->prefix)
1912                 bprint(ip, "%s ", ip->prefix);
1913         for (; *fmt && ip->curr < ip->end; fmt++) {
1914                 if (*fmt != '%'){
1915                         *ip->curr++ = *fmt;
1916                         continue;
1917                 }
1918                 switch(*++fmt){
1919                 case '%':
1920                         *ip->curr++ = '%';
1921                         break;
1922                 case 'A':
1923                         bprint(ip, "%s", ANAME(ip));
1924                         break;
1925                 case 'C':
1926                         bprint(ip, "CR%d", ip->reg);
1927                         break;
1928                 case 'D':
1929                         if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
1930                                 bprint(ip, "DR%d",ip->reg);
1931                         else
1932                                 bprint(ip, "???");
1933                         break;
1934                 case 'I':
1935                         bprint(ip, "$");
1936                         immediate(ip, ip->imm2);
1937                         break;
1938                 case 'O':
1939                         bprint(ip,"%s", ONAME(ip));
1940                         break;
1941                 case 'i':
1942                         bprint(ip, "$");
1943                         v = ip->imm;
1944                         if(ip->rex & REXW)
1945                                 v = ip->imm64;
1946                         immediate(ip, v);
1947                         break;
1948                 case 'R':
1949                         bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
1950                         break;
1951                 case 'S':
1952                         if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1953                                 bprint(ip, "Q");
1954                         else
1955                                 bprint(ip, "%c", ip->osize);
1956                         break;
1957                 case 's':
1958                         if(ip->opre == 0 || ip->opre == 0x66)
1959                                 bprint(ip, "P");
1960                         else
1961                                 bprint(ip, "S");
1962                         if(ip->opre == 0xf2 || ip->opre == 0x66)
1963                                 bprint(ip, "D");
1964                         else
1965                                 bprint(ip, "S");
1966                         break;
1967                 case 'T':
1968                         if (ip->reg == 6 || ip->reg == 7)
1969                                 bprint(ip, "TR%d",ip->reg);
1970                         else
1971                                 bprint(ip, "???");
1972                         break;
1973                 case 'W':
1974                         if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1975                                 bprint(ip, "CDQE");
1976                         else if (ip->osize == 'L')
1977                                 bprint(ip,"CWDE");
1978                         else
1979                                 bprint(ip, "CBW");
1980                         break;
1981                 case 'd':
1982                         bprint(ip,"%ux:%lux",ip->seg,ip->disp);
1983                         break;
1984                 case 'm':
1985                         if (ip->mod == 3 && ip->osize != 'B') {
1986                                 if(fmt[1] != '*'){
1987                                         if(ip->opre != 0) {
1988                                                 bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
1989                                                 break;
1990                                         }
1991                                 } else
1992                                         fmt++;
1993                                 bprint(ip, "M%d", ip->base);
1994                                 break;
1995                         }
1996                         pea(ip);
1997                         break;
1998                 case 'e':
1999                         pea(ip);
2000                         break;
2001                 case 'f':
2002                         bprint(ip, "F%d", ip->base);
2003                         break;
2004                 case 'g':
2005                         if (ip->reg < 6)
2006                                 bprint(ip,"%s",sreg[ip->reg]);
2007                         else
2008                                 bprint(ip,"???");
2009                         break;
2010                 case 'p':
2011                         /*
2012                          * signed immediate in the ulong ip->imm.
2013                          */
2014                         v = (long)ip->imm;
2015                         immediate(ip, v+ip->addr+ip->n);
2016                         break;
2017                 case 'r':
2018                         if (ip->osize == 'B')
2019                                 bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
2020                         else
2021                                 bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
2022                         break;
2023                 case 'w':
2024                         if (ip->osize == 'Q' || ip->rex & REXW)
2025                                 bprint(ip, "CQO");
2026                         else if (ip->osize == 'L')
2027                                 bprint(ip,"CDQ");
2028                         else
2029                                 bprint(ip, "CWD");
2030                         break;
2031                 case 'M':
2032                         if(ip->opre != 0)
2033                                 bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2034                         else
2035                                 bprint(ip, "M%d", ip->reg);
2036                         break;
2037                 case 'x':
2038                         if (ip->mod == 3 && ip->osize != 'B') {
2039                                 bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
2040                                 break;
2041                         }
2042                         pea(ip);
2043                         break;
2044                 case 'X':
2045                         bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2046                         break;
2047                 default:
2048                         bprint(ip, "%%%c", *fmt);
2049                         break;
2050                 }
2051         }
2052         *ip->curr = 0;          /* there's always room for 1 byte */
2053 }
2054
2055 static int
2056 i386inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2057 {
2058         Instr instr;
2059         Optable *op;
2060
2061         USED(modifier);
2062         op = mkinstr(map, &instr, pc);
2063         if (op == 0) {
2064                 errstr(buf, n);
2065                 return -1;
2066         }
2067         instr.curr = buf;
2068         instr.end = buf+n-1;
2069         prinstr(&instr, op->proto);
2070         return instr.n;
2071 }
2072
2073 static int
2074 i386das(Map *map, uvlong pc, char *buf, int n)
2075 {
2076         Instr instr;
2077         int i;
2078
2079         if (mkinstr(map, &instr, pc) == 0) {
2080                 errstr(buf, n);
2081                 return -1;
2082         }
2083         for(i = 0; i < instr.n && n > 2; i++) {
2084                 _hexify(buf, instr.mem[i], 1);
2085                 buf += 2;
2086                 n -= 2;
2087         }
2088         *buf = 0;
2089         return instr.n;
2090 }
2091
2092 static int
2093 i386instlen(Map *map, uvlong pc)
2094 {
2095         Instr i;
2096
2097         if (mkinstr(map, &i, pc))
2098                 return i.n;
2099         return -1;
2100 }
2101
2102 static int
2103 i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2104 {
2105         Instr i;
2106         Optable *op;
2107         ushort s;
2108         uvlong l, addr;
2109         vlong v;
2110         int n;
2111
2112         op = mkinstr(map, &i, pc);
2113         if (!op)
2114                 return -1;
2115
2116         n = 0;
2117
2118         switch(i.jumptype) {
2119         case RET:               /* RETURN or LEAVE */
2120         case Iw:                /* RETURN */
2121                 if (strcmp(op->proto, "LEAVE") == 0) {
2122                         if (geta(map, (*rget)(map, "BP"), &l) < 0)
2123                                 return -1;
2124                 } else if (geta(map, (*rget)(map, mach->sp), &l) < 0)
2125                         return -1;
2126                 foll[0] = l;
2127                 return 1;
2128         case Iwds:              /* pc relative JUMP or CALL*/
2129         case Jbs:               /* pc relative JUMP or CALL */
2130                 v = (long)i.imm;
2131                 foll[0] = pc+v+i.n;
2132                 n = 1;
2133                 break;
2134         case PTR:               /* seg:displacement JUMP or CALL */
2135                 foll[0] = (i.seg<<4)+i.disp;
2136                 return 1;
2137         case JUMP:              /* JUMP or CALL EA */
2138
2139                 if(i.mod == 3) {
2140                         foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]);
2141                         return 1;
2142                 }
2143                         /* calculate the effective address */
2144                 addr = i.disp;
2145                 if (i.base >= 0) {
2146                         if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0)
2147                                 return -1;
2148                         addr += l;
2149                 }
2150                 if (i.index >= 0) {
2151                         if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0)
2152                                 return -1;
2153                         addr += l*(1<<i.ss);
2154                 }
2155                         /* now retrieve a seg:disp value at that address */
2156                 if (get2(map, addr, &s) < 0)                    /* seg */
2157                         return -1;
2158                 foll[0] = s<<4;
2159                 addr += 2;
2160                 if (i.asize == 'L') {
2161                         if (geta(map, addr, &l) < 0)            /* disp32 */
2162                                 return -1;
2163                         foll[0] += l;
2164                 } else {                                        /* disp16 */
2165                         if (get2(map, addr, &s) < 0)
2166                                 return -1;
2167                         foll[0] += s;
2168                 }
2169                 return 1;
2170         default:
2171                 break;
2172         }               
2173         if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
2174                 return 1;
2175         foll[n++] = pc+i.n;
2176         return n;
2177 }