]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/8db.c
9bootfat: rename open() to fileinit and make it static as its really a internal funct...
[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 [0x7E]  RM,0,           "MOV%S %M,%e",
539 [0x7F]  RM,0,           "MOVQ %M,%m",
540 [0xAE]  RMOP,0,         optab0FAE,
541 [0xAA]  0,0,            "RSM",
542 [0xB0]  RM,0,           "CMPXCHGB       %r,%e",
543 [0xB1]  RM,0,           "CMPXCHG%S      %r,%e",
544 [0xC0]  RMB,0,          "XADDB  %r,%e",
545 [0xC1]  RM,0,           "XADD%S %r,%e",
546 [0xC2]  RM,Ib,          "CMP%s  %i,%x,%X",
547 [0xC3]  RM,0,           "MOVNTI%S       %r,%e",
548 [0xC6]  RM,Ib,          "SHUF%s %i,%x,%X",
549 [0xC8]  0,0,            "BSWAP  AX",
550 [0xC9]  0,0,            "BSWAP  CX",
551 [0xCA]  0,0,            "BSWAP  DX",
552 [0xCB]  0,0,            "BSWAP  BX",
553 [0xCC]  0,0,            "BSWAP  SP",
554 [0xCD]  0,0,            "BSWAP  BP",
555 [0xCE]  0,0,            "BSWAP  SI",
556 [0xCF]  0,0,            "BSWAP  DI",
557 [0xD1]  RM,0,           "PSRLW %m,%M",
558 [0xD2]  RM,0,           "PSRLL %m,%M",
559 [0xD3]  RM,0,           "PSRLQ %m,%M",
560 [0xD5]  RM,0,           "PMULLW %m,%M",
561 [0xD6]  RM,0,           "MOVQOZX        %m*,%X",
562 [0xD7]  RM,0,           "PMOVMSKB %m,%r",
563 [0xD8]  RM,0,           "PSUBUSB %m,%M",
564 [0xD9]  RM,0,           "PSUBUSW %m,%M",
565 [0xDA]  RM,0,           "PMINUB %m,%M",
566 [0xDB]  RM,0,           "PAND %m,%M",
567 [0xDC]  RM,0,           "PADDUSB %m,%M",
568 [0xDD]  RM,0,           "PADDUSW %m,%M",
569 [0xDE]  RM,0,           "PMAXUB %m,%M",
570 [0xDF]  RM,0,           "PANDN %m,%M",
571 [0xE0]  RM,0,           "PAVGB %m,%M",
572 [0xE1]  RM,0,           "PSRAW %m,%M",
573 [0xE2]  RM,0,           "PSRAL %m,%M",
574 [0xE3]  RM,0,           "PAVGW %m,%M",
575 [0xE4]  RM,0,           "PMULHUW %m,%M",
576 [0xE5]  RM,0,           "PMULHW %m,%M",
577 [0xE7]  RM,0,           "MOVNTQ %M,%e",
578 [0xE8]  RM,0,           "PSUBSB %m,%M",
579 [0xE9]  RM,0,           "PSUBSW %m,%M",
580 [0xEA]  RM,0,           "PMINSW %m,%M",
581 [0xEB]  RM,0,           "POR %m,%M",
582 [0xEC]  RM,0,           "PADDSB %m,%M",
583 [0xED]  RM,0,           "PADDSW %m,%M",
584 [0xEE]  RM,0,           "PMAXSW %m,%M",
585 [0xEF]  RM,0,           "PXOR %m,%M",
586 [0xF1]  RM,0,           "PSLLW %m,%M",
587 [0xF2]  RM,0,           "PSLLL %m,%M",
588 [0xF3]  RM,0,           "PSLLQ %m,%M",
589 [0xF4]  RM,0,           "PMULULQ        %m,%M",
590 [0xF5]  RM,0,           "PMADDWL %m,%M",
591 [0xF6]  RM,0,           "PSADBW %m,%M",
592 [0xF7]  RMR,0,          "MASKMOVQ       %m,%M",
593 [0xF8]  RM,0,           "PSUBB %m,%M",
594 [0xF9]  RM,0,           "PSUBW %m,%M",
595 [0xFA]  RM,0,           "PSUBL %m,%M",
596 [0xFC]  RM,0,           "PADDB %m,%M",
597 [0xFD]  RM,0,           "PADDW %m,%M",
598 [0xFE]  RM,0,           "PADDL %m,%M",
599
600 [0x80]  Iwds,0,         "JOS    %p",
601 [0x81]  Iwds,0,         "JOC    %p",
602 [0x82]  Iwds,0,         "JCS    %p",
603 [0x83]  Iwds,0,         "JCC    %p",
604 [0x84]  Iwds,0,         "JEQ    %p",
605 [0x85]  Iwds,0,         "JNE    %p",
606 [0x86]  Iwds,0,         "JLS    %p",
607 [0x87]  Iwds,0,         "JHI    %p",
608 [0x88]  Iwds,0,         "JMI    %p",
609 [0x89]  Iwds,0,         "JPL    %p",
610 [0x8a]  Iwds,0,         "JPS    %p",
611 [0x8b]  Iwds,0,         "JPC    %p",
612 [0x8c]  Iwds,0,         "JLT    %p",
613 [0x8d]  Iwds,0,         "JGE    %p",
614 [0x8e]  Iwds,0,         "JLE    %p",
615 [0x8f]  Iwds,0,         "JGT    %p",
616 [0x90]  RMB,0,          "SETOS  %e",
617 [0x91]  RMB,0,          "SETOC  %e",
618 [0x92]  RMB,0,          "SETCS  %e",
619 [0x93]  RMB,0,          "SETCC  %e",
620 [0x94]  RMB,0,          "SETEQ  %e",
621 [0x95]  RMB,0,          "SETNE  %e",
622 [0x96]  RMB,0,          "SETLS  %e",
623 [0x97]  RMB,0,          "SETHI  %e",
624 [0x98]  RMB,0,          "SETMI  %e",
625 [0x99]  RMB,0,          "SETPL  %e",
626 [0x9a]  RMB,0,          "SETPS  %e",
627 [0x9b]  RMB,0,          "SETPC  %e",
628 [0x9c]  RMB,0,          "SETLT  %e",
629 [0x9d]  RMB,0,          "SETGE  %e",
630 [0x9e]  RMB,0,          "SETLE  %e",
631 [0x9f]  RMB,0,          "SETGT  %e",
632 [0xa0]  0,0,            "PUSHL  FS",
633 [0xa1]  0,0,            "POPL   FS",
634 [0xa2]  0,0,            "CPUID",
635 [0xa3]  RM,0,           "BT%S   %r,%e",
636 [0xa4]  RM,Ib,          "SHLD%S %r,%i,%e",
637 [0xa5]  RM,0,           "SHLD%S %r,CL,%e",
638 [0xa8]  0,0,            "PUSHL  GS",
639 [0xa9]  0,0,            "POPL   GS",
640 [0xab]  RM,0,           "BTS%S  %r,%e",
641 [0xac]  RM,Ib,          "SHRD%S %r,%i,%e",
642 [0xad]  RM,0,           "SHRD%S %r,CL,%e",
643 [0xaf]  RM,0,           "IMUL%S %e,%r",
644 [0xb2]  RMM,0,          "LSS    %e,%r",
645 [0xb3]  RM,0,           "BTR%S  %r,%e",
646 [0xb4]  RMM,0,          "LFS    %e,%r",
647 [0xb5]  RMM,0,          "LGS    %e,%r",
648 [0xb6]  RMB,0,          "MOVBZX %e,%R",
649 [0xb7]  RM,0,           "MOVWZX %e,%R",
650 [0xba]  RMOP,0,         optab0FBA,
651 [0xbb]  RM,0,           "BTC%S  %e,%r",
652 [0xbc]  RM,0,           "BSF%S  %e,%r",
653 [0xbd]  RM,0,           "BSR%S  %e,%r",
654 [0xbe]  RMB,0,          "MOVBSX %e,%R",
655 [0xbf]  RM,0,           "MOVWSX %e,%R",
656 [0xc7]  RMOP,0,         optab0FC7,
657 };
658
659 static Optable optab80[8]=
660 {
661 [0x00]  Ib,0,           "ADDB   %i,%e",
662 [0x01]  Ib,0,           "ORB    %i,%e",
663 [0x02]  Ib,0,           "ADCB   %i,%e",
664 [0x03]  Ib,0,           "SBBB   %i,%e",
665 [0x04]  Ib,0,           "ANDB   %i,%e",
666 [0x05]  Ib,0,           "SUBB   %i,%e",
667 [0x06]  Ib,0,           "XORB   %i,%e",
668 [0x07]  Ib,0,           "CMPB   %e,%i",
669 };
670
671 static Optable optab81[8]=
672 {
673 [0x00]  Iwd,0,          "ADD%S  %i,%e",
674 [0x01]  Iwd,0,          "OR%S   %i,%e",
675 [0x02]  Iwd,0,          "ADC%S  %i,%e",
676 [0x03]  Iwd,0,          "SBB%S  %i,%e",
677 [0x04]  Iwd,0,          "AND%S  %i,%e",
678 [0x05]  Iwd,0,          "SUB%S  %i,%e",
679 [0x06]  Iwd,0,          "XOR%S  %i,%e",
680 [0x07]  Iwd,0,          "CMP%S  %e,%i",
681 };
682
683 static Optable optab83[8]=
684 {
685 [0x00]  Ibs,0,          "ADD%S  %i,%e",
686 [0x01]  Ibs,0,          "OR%S   %i,%e",
687 [0x02]  Ibs,0,          "ADC%S  %i,%e",
688 [0x03]  Ibs,0,          "SBB%S  %i,%e",
689 [0x04]  Ibs,0,          "AND%S  %i,%e",
690 [0x05]  Ibs,0,          "SUB%S  %i,%e",
691 [0x06]  Ibs,0,          "XOR%S  %i,%e",
692 [0x07]  Ibs,0,          "CMP%S  %e,%i",
693 };
694
695 static Optable optabC0[8] =
696 {
697 [0x00]  Ib,0,           "ROLB   %i,%e",
698 [0x01]  Ib,0,           "RORB   %i,%e",
699 [0x02]  Ib,0,           "RCLB   %i,%e",
700 [0x03]  Ib,0,           "RCRB   %i,%e",
701 [0x04]  Ib,0,           "SHLB   %i,%e",
702 [0x05]  Ib,0,           "SHRB   %i,%e",
703 [0x07]  Ib,0,           "SARB   %i,%e",
704 };
705
706 static Optable optabC1[8] =
707 {
708 [0x00]  Ib,0,           "ROL%S  %i,%e",
709 [0x01]  Ib,0,           "ROR%S  %i,%e",
710 [0x02]  Ib,0,           "RCL%S  %i,%e",
711 [0x03]  Ib,0,           "RCR%S  %i,%e",
712 [0x04]  Ib,0,           "SHL%S  %i,%e",
713 [0x05]  Ib,0,           "SHR%S  %i,%e",
714 [0x07]  Ib,0,           "SAR%S  %i,%e",
715 };
716
717 static Optable optabD0[8] =
718 {
719 [0x00]  0,0,            "ROLB   %e",
720 [0x01]  0,0,            "RORB   %e",
721 [0x02]  0,0,            "RCLB   %e",
722 [0x03]  0,0,            "RCRB   %e",
723 [0x04]  0,0,            "SHLB   %e",
724 [0x05]  0,0,            "SHRB   %e",
725 [0x07]  0,0,            "SARB   %e",
726 };
727
728 static Optable optabD1[8] =
729 {
730 [0x00]  0,0,            "ROL%S  %e",
731 [0x01]  0,0,            "ROR%S  %e",
732 [0x02]  0,0,            "RCL%S  %e",
733 [0x03]  0,0,            "RCR%S  %e",
734 [0x04]  0,0,            "SHL%S  %e",
735 [0x05]  0,0,            "SHR%S  %e",
736 [0x07]  0,0,            "SAR%S  %e",
737 };
738
739 static Optable optabD2[8] =
740 {
741 [0x00]  0,0,            "ROLB   CL,%e",
742 [0x01]  0,0,            "RORB   CL,%e",
743 [0x02]  0,0,            "RCLB   CL,%e",
744 [0x03]  0,0,            "RCRB   CL,%e",
745 [0x04]  0,0,            "SHLB   CL,%e",
746 [0x05]  0,0,            "SHRB   CL,%e",
747 [0x07]  0,0,            "SARB   CL,%e",
748 };
749
750 static Optable optabD3[8] =
751 {
752 [0x00]  0,0,            "ROL%S  CL,%e",
753 [0x01]  0,0,            "ROR%S  CL,%e",
754 [0x02]  0,0,            "RCL%S  CL,%e",
755 [0x03]  0,0,            "RCR%S  CL,%e",
756 [0x04]  0,0,            "SHL%S  CL,%e",
757 [0x05]  0,0,            "SHR%S  CL,%e",
758 [0x07]  0,0,            "SAR%S  CL,%e",
759 };
760
761 static Optable optabD8[8+8] =
762 {
763 [0x00]  0,0,            "FADDF  %e,F0",
764 [0x01]  0,0,            "FMULF  %e,F0",
765 [0x02]  0,0,            "FCOMF  %e,F0",
766 [0x03]  0,0,            "FCOMFP %e,F0",
767 [0x04]  0,0,            "FSUBF  %e,F0",
768 [0x05]  0,0,            "FSUBRF %e,F0",
769 [0x06]  0,0,            "FDIVF  %e,F0",
770 [0x07]  0,0,            "FDIVRF %e,F0",
771 [0x08]  0,0,            "FADDD  %f,F0",
772 [0x09]  0,0,            "FMULD  %f,F0",
773 [0x0a]  0,0,            "FCOMD  %f,F0",
774 [0x0b]  0,0,            "FCOMPD %f,F0",
775 [0x0c]  0,0,            "FSUBD  %f,F0",
776 [0x0d]  0,0,            "FSUBRD %f,F0",
777 [0x0e]  0,0,            "FDIVD  %f,F0",
778 [0x0f]  0,0,            "FDIVRD %f,F0",
779 };
780 /*
781  *      optabD9 and optabDB use the following encoding: 
782  *      if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
783  *      else instruction = optabDx[(modrm&0x3f)+8];
784  *
785  *      the instructions for MOD == 3, follow the 8 instructions
786  *      for the other MOD values stored at the front of the table.
787  */
788 static Optable optabD9[64+8] =
789 {
790 [0x00]  0,0,            "FMOVF  %e,F0",
791 [0x02]  0,0,            "FMOVF  F0,%e",
792 [0x03]  0,0,            "FMOVFP F0,%e",
793 [0x04]  0,0,            "FLDENV%S %e",
794 [0x05]  0,0,            "FLDCW  %e",
795 [0x06]  0,0,            "FSTENV%S %e",
796 [0x07]  0,0,            "FSTCW  %e",
797 [0x08]  0,0,            "FMOVD  F0,F0",         /* Mod R/M = 11xx xxxx*/
798 [0x09]  0,0,            "FMOVD  F1,F0",
799 [0x0a]  0,0,            "FMOVD  F2,F0",
800 [0x0b]  0,0,            "FMOVD  F3,F0",
801 [0x0c]  0,0,            "FMOVD  F4,F0",
802 [0x0d]  0,0,            "FMOVD  F5,F0",
803 [0x0e]  0,0,            "FMOVD  F6,F0",
804 [0x0f]  0,0,            "FMOVD  F7,F0",
805 [0x10]  0,0,            "FXCHD  F0,F0",
806 [0x11]  0,0,            "FXCHD  F1,F0",
807 [0x12]  0,0,            "FXCHD  F2,F0",
808 [0x13]  0,0,            "FXCHD  F3,F0",
809 [0x14]  0,0,            "FXCHD  F4,F0",
810 [0x15]  0,0,            "FXCHD  F5,F0",
811 [0x16]  0,0,            "FXCHD  F6,F0",
812 [0x17]  0,0,            "FXCHD  F7,F0",
813 [0x18]  0,0,            "FNOP",
814 [0x28]  0,0,            "FCHS",
815 [0x29]  0,0,            "FABS",
816 [0x2c]  0,0,            "FTST",
817 [0x2d]  0,0,            "FXAM",
818 [0x30]  0,0,            "FLD1",
819 [0x31]  0,0,            "FLDL2T",
820 [0x32]  0,0,            "FLDL2E",
821 [0x33]  0,0,            "FLDPI",
822 [0x34]  0,0,            "FLDLG2",
823 [0x35]  0,0,            "FLDLN2",
824 [0x36]  0,0,            "FLDZ",
825 [0x38]  0,0,            "F2XM1",
826 [0x39]  0,0,            "FYL2X",
827 [0x3a]  0,0,            "FPTAN",
828 [0x3b]  0,0,            "FPATAN",
829 [0x3c]  0,0,            "FXTRACT",
830 [0x3d]  0,0,            "FPREM1",
831 [0x3e]  0,0,            "FDECSTP",
832 [0x3f]  0,0,            "FNCSTP",
833 [0x40]  0,0,            "FPREM",
834 [0x41]  0,0,            "FYL2XP1",
835 [0x42]  0,0,            "FSQRT",
836 [0x43]  0,0,            "FSINCOS",
837 [0x44]  0,0,            "FRNDINT",
838 [0x45]  0,0,            "FSCALE",
839 [0x46]  0,0,            "FSIN",
840 [0x47]  0,0,            "FCOS",
841 };
842
843 static Optable optabDA[8+8] =
844 {
845 [0x00]  0,0,            "FADDL  %e,F0",
846 [0x01]  0,0,            "FMULL  %e,F0",
847 [0x02]  0,0,            "FCOML  %e,F0",
848 [0x03]  0,0,            "FCOMLP %e,F0",
849 [0x04]  0,0,            "FSUBL  %e,F0",
850 [0x05]  0,0,            "FSUBRL %e,F0",
851 [0x06]  0,0,            "FDIVL  %e,F0",
852 [0x07]  0,0,            "FDIVRL %e,F0",
853 [0x0d]  R1,0,           "FUCOMPP",
854 };
855
856 static Optable optabDB[8+64] =
857 {
858 [0x00]  0,0,            "FMOVL  %e,F0",
859 [0x02]  0,0,            "FMOVL  F0,%e",
860 [0x03]  0,0,            "FMOVLP F0,%e",
861 [0x05]  0,0,            "FMOVX  %e,F0",
862 [0x07]  0,0,            "FMOVXP F0,%e",
863 [0x2a]  0,0,            "FCLEX",
864 [0x2b]  0,0,            "FINIT",
865 };
866
867 static Optable optabDC[8+8] =
868 {
869 [0x00]  0,0,            "FADDD  %e,F0",
870 [0x01]  0,0,            "FMULD  %e,F0",
871 [0x02]  0,0,            "FCOMD  %e,F0",
872 [0x03]  0,0,            "FCOMDP %e,F0",
873 [0x04]  0,0,            "FSUBD  %e,F0",
874 [0x05]  0,0,            "FSUBRD %e,F0",
875 [0x06]  0,0,            "FDIVD  %e,F0",
876 [0x07]  0,0,            "FDIVRD %e,F0",
877 [0x08]  0,0,            "FADDD  F0,%f",
878 [0x09]  0,0,            "FMULD  F0,%f",
879 [0x0c]  0,0,            "FSUBRD F0,%f",
880 [0x0d]  0,0,            "FSUBD  F0,%f",
881 [0x0e]  0,0,            "FDIVRD F0,%f",
882 [0x0f]  0,0,            "FDIVD  F0,%f",
883 };
884
885 static Optable optabDD[8+8] =
886 {
887 [0x00]  0,0,            "FMOVD  %e,F0",
888 [0x02]  0,0,            "FMOVD  F0,%e",
889 [0x03]  0,0,            "FMOVDP F0,%e",
890 [0x04]  0,0,            "FRSTOR%S %e",
891 [0x06]  0,0,            "FSAVE%S %e",
892 [0x07]  0,0,            "FSTSW  %e",
893 [0x08]  0,0,            "FFREED %f",
894 [0x0a]  0,0,            "FMOVD  %f,F0",
895 [0x0b]  0,0,            "FMOVDP %f,F0",
896 [0x0c]  0,0,            "FUCOMD %f,F0",
897 [0x0d]  0,0,            "FUCOMDP %f,F0",
898 };
899
900 static Optable optabDE[8+8] =
901 {
902 [0x00]  0,0,            "FADDW  %e,F0",
903 [0x01]  0,0,            "FMULW  %e,F0",
904 [0x02]  0,0,            "FCOMW  %e,F0",
905 [0x03]  0,0,            "FCOMWP %e,F0",
906 [0x04]  0,0,            "FSUBW  %e,F0",
907 [0x05]  0,0,            "FSUBRW %e,F0",
908 [0x06]  0,0,            "FDIVW  %e,F0",
909 [0x07]  0,0,            "FDIVRW %e,F0",
910 [0x08]  0,0,            "FADDDP F0,%f",
911 [0x09]  0,0,            "FMULDP F0,%f",
912 [0x0b]  R1,0,           "FCOMPDP",
913 [0x0c]  0,0,            "FSUBRDP F0,%f",
914 [0x0d]  0,0,            "FSUBDP F0,%f",
915 [0x0e]  0,0,            "FDIVRDP F0,%f",
916 [0x0f]  0,0,            "FDIVDP F0,%f",
917 };
918
919 static Optable optabDF[8+8] =
920 {
921 [0x00]  0,0,            "FMOVW  %e,F0",
922 [0x02]  0,0,            "FMOVW  F0,%e",
923 [0x03]  0,0,            "FMOVWP F0,%e",
924 [0x04]  0,0,            "FBLD   %e",
925 [0x05]  0,0,            "FMOVL  %e,F0",
926 [0x06]  0,0,            "FBSTP  %e",
927 [0x07]  0,0,            "FMOVLP F0,%e",
928 [0x0c]  R0,0,           "FSTSW  %OAX",
929 };
930
931 static Optable optabF6[8] =
932 {
933 [0x00]  Ib,0,           "TESTB  %i,%e",
934 [0x02]  0,0,            "NOTB   %e",
935 [0x03]  0,0,            "NEGB   %e",
936 [0x04]  0,0,            "MULB   AL,%e",
937 [0x05]  0,0,            "IMULB  AL,%e",
938 [0x06]  0,0,            "DIVB   AL,%e",
939 [0x07]  0,0,            "IDIVB  AL,%e",
940 };
941
942 static Optable optabF7[8] =
943 {
944 [0x00]  Iwd,0,          "TEST%S %i,%e",
945 [0x02]  0,0,            "NOT%S  %e",
946 [0x03]  0,0,            "NEG%S  %e",
947 [0x04]  0,0,            "MUL%S  %OAX,%e",
948 [0x05]  0,0,            "IMUL%S %OAX,%e",
949 [0x06]  0,0,            "DIV%S  %OAX,%e",
950 [0x07]  0,0,            "IDIV%S %OAX,%e",
951 };
952
953 static Optable optabFE[8] =
954 {
955 [0x00]  0,0,            "INCB   %e",
956 [0x01]  0,0,            "DECB   %e",
957 };
958
959 static Optable optabFF[8] =
960 {
961 [0x00]  0,0,            "INC%S  %e",
962 [0x01]  0,0,            "DEC%S  %e",
963 [0x02]  JUMP,0,         "CALL*  %e",
964 [0x03]  JUMP,0,         "CALLF* %e",
965 [0x04]  JUMP,0,         "JMP*   %e",
966 [0x05]  JUMP,0,         "JMPF*  %e",
967 [0x06]  0,0,            "PUSHL  %e",
968 };
969
970 static Optable optable[256+1] =
971 {
972 [0x00]  RMB,0,          "ADDB   %r,%e",
973 [0x01]  RM,0,           "ADD%S  %r,%e",
974 [0x02]  RMB,0,          "ADDB   %e,%r",
975 [0x03]  RM,0,           "ADD%S  %e,%r",
976 [0x04]  Ib,0,           "ADDB   %i,AL",
977 [0x05]  Iwd,0,          "ADD%S  %i,%OAX",
978 [0x06]  0,0,            "PUSHL  ES",
979 [0x07]  0,0,            "POPL   ES",
980 [0x08]  RMB,0,          "ORB    %r,%e",
981 [0x09]  RM,0,           "OR%S   %r,%e",
982 [0x0a]  RMB,0,          "ORB    %e,%r",
983 [0x0b]  RM,0,           "OR%S   %e,%r",
984 [0x0c]  Ib,0,           "ORB    %i,AL",
985 [0x0d]  Iwd,0,          "OR%S   %i,%OAX",
986 [0x0e]  0,0,            "PUSHL  CS",
987 [0x0f]  AUXMM,0,        optab0F,
988 [0x10]  RMB,0,          "ADCB   %r,%e",
989 [0x11]  RM,0,           "ADC%S  %r,%e",
990 [0x12]  RMB,0,          "ADCB   %e,%r",
991 [0x13]  RM,0,           "ADC%S  %e,%r",
992 [0x14]  Ib,0,           "ADCB   %i,AL",
993 [0x15]  Iwd,0,          "ADC%S  %i,%OAX",
994 [0x16]  0,0,            "PUSHL  SS",
995 [0x17]  0,0,            "POPL   SS",
996 [0x18]  RMB,0,          "SBBB   %r,%e",
997 [0x19]  RM,0,           "SBB%S  %r,%e",
998 [0x1a]  RMB,0,          "SBBB   %e,%r",
999 [0x1b]  RM,0,           "SBB%S  %e,%r",
1000 [0x1c]  Ib,0,           "SBBB   %i,AL",
1001 [0x1d]  Iwd,0,          "SBB%S  %i,%OAX",
1002 [0x1e]  0,0,            "PUSHL  DS",
1003 [0x1f]  0,0,            "POPL   DS",
1004 [0x20]  RMB,0,          "ANDB   %r,%e",
1005 [0x21]  RM,0,           "AND%S  %r,%e",
1006 [0x22]  RMB,0,          "ANDB   %e,%r",
1007 [0x23]  RM,0,           "AND%S  %e,%r",
1008 [0x24]  Ib,0,           "ANDB   %i,AL",
1009 [0x25]  Iwd,0,          "AND%S  %i,%OAX",
1010 [0x26]  SEG,0,          "ES:",
1011 [0x27]  0,0,            "DAA",
1012 [0x28]  RMB,0,          "SUBB   %r,%e",
1013 [0x29]  RM,0,           "SUB%S  %r,%e",
1014 [0x2a]  RMB,0,          "SUBB   %e,%r",
1015 [0x2b]  RM,0,           "SUB%S  %e,%r",
1016 [0x2c]  Ib,0,           "SUBB   %i,AL",
1017 [0x2d]  Iwd,0,          "SUB%S  %i,%OAX",
1018 [0x2e]  SEG,0,          "CS:",
1019 [0x2f]  0,0,            "DAS",
1020 [0x30]  RMB,0,          "XORB   %r,%e",
1021 [0x31]  RM,0,           "XOR%S  %r,%e",
1022 [0x32]  RMB,0,          "XORB   %e,%r",
1023 [0x33]  RM,0,           "XOR%S  %e,%r",
1024 [0x34]  Ib,0,           "XORB   %i,AL",
1025 [0x35]  Iwd,0,          "XOR%S  %i,%OAX",
1026 [0x36]  SEG,0,          "SS:",
1027 [0x37]  0,0,            "AAA",
1028 [0x38]  RMB,0,          "CMPB   %r,%e",
1029 [0x39]  RM,0,           "CMP%S  %r,%e",
1030 [0x3a]  RMB,0,          "CMPB   %e,%r",
1031 [0x3b]  RM,0,           "CMP%S  %e,%r",
1032 [0x3c]  Ib,0,           "CMPB   %i,AL",
1033 [0x3d]  Iwd,0,          "CMP%S  %i,%OAX",
1034 [0x3e]  SEG,0,          "DS:",
1035 [0x3f]  0,0,            "AAS",
1036 [0x40]  0,0,            "INC%S  %OAX",
1037 [0x41]  0,0,            "INC%S  %OCX",
1038 [0x42]  0,0,            "INC%S  %ODX",
1039 [0x43]  0,0,            "INC%S  %OBX",
1040 [0x44]  0,0,            "INC%S  %OSP",
1041 [0x45]  0,0,            "INC%S  %OBP",
1042 [0x46]  0,0,            "INC%S  %OSI",
1043 [0x47]  0,0,            "INC%S  %ODI",
1044 [0x48]  0,0,            "DEC%S  %OAX",
1045 [0x49]  0,0,            "DEC%S  %OCX",
1046 [0x4a]  0,0,            "DEC%S  %ODX",
1047 [0x4b]  0,0,            "DEC%S  %OBX",
1048 [0x4c]  0,0,            "DEC%S  %OSP",
1049 [0x4d]  0,0,            "DEC%S  %OBP",
1050 [0x4e]  0,0,            "DEC%S  %OSI",
1051 [0x4f]  0,0,            "DEC%S  %ODI",
1052 [0x50]  0,0,            "PUSH%S %OAX",
1053 [0x51]  0,0,            "PUSH%S %OCX",
1054 [0x52]  0,0,            "PUSH%S %ODX",
1055 [0x53]  0,0,            "PUSH%S %OBX",
1056 [0x54]  0,0,            "PUSH%S %OSP",
1057 [0x55]  0,0,            "PUSH%S %OBP",
1058 [0x56]  0,0,            "PUSH%S %OSI",
1059 [0x57]  0,0,            "PUSH%S %ODI",
1060 [0x58]  0,0,            "POP%S  %OAX",
1061 [0x59]  0,0,            "POP%S  %OCX",
1062 [0x5a]  0,0,            "POP%S  %ODX",
1063 [0x5b]  0,0,            "POP%S  %OBX",
1064 [0x5c]  0,0,            "POP%S  %OSP",
1065 [0x5d]  0,0,            "POP%S  %OBP",
1066 [0x5e]  0,0,            "POP%S  %OSI",
1067 [0x5f]  0,0,            "POP%S  %ODI",
1068 [0x60]  0,0,            "PUSHA%S",
1069 [0x61]  0,0,            "POPA%S",
1070 [0x62]  RMM,0,          "BOUND  %e,%r",
1071 [0x63]  RM,0,           "ARPL   %r,%e",
1072 [0x64]  SEG,0,          "FS:",
1073 [0x65]  SEG,0,          "GS:",
1074 [0x66]  OPOVER,0,       "",
1075 [0x67]  ADDOVER,0,      "",
1076 [0x68]  Iwd,0,          "PUSH%S %i",
1077 [0x69]  RM,Iwd,         "IMUL%S %e,%i,%r",
1078 [0x6a]  Ib,0,           "PUSH%S %i",
1079 [0x6b]  RM,Ibs,         "IMUL%S %e,%i,%r",
1080 [0x6c]  0,0,            "INSB   DX,(%ODI)",
1081 [0x6d]  0,0,            "INS%S  DX,(%ODI)",
1082 [0x6e]  0,0,            "OUTSB  (%ASI),DX",
1083 [0x6f]  0,0,            "OUTS%S (%ASI),DX",
1084 [0x70]  Jbs,0,          "JOS    %p",
1085 [0x71]  Jbs,0,          "JOC    %p",
1086 [0x72]  Jbs,0,          "JCS    %p",
1087 [0x73]  Jbs,0,          "JCC    %p",
1088 [0x74]  Jbs,0,          "JEQ    %p",
1089 [0x75]  Jbs,0,          "JNE    %p",
1090 [0x76]  Jbs,0,          "JLS    %p",
1091 [0x77]  Jbs,0,          "JHI    %p",
1092 [0x78]  Jbs,0,          "JMI    %p",
1093 [0x79]  Jbs,0,          "JPL    %p",
1094 [0x7a]  Jbs,0,          "JPS    %p",
1095 [0x7b]  Jbs,0,          "JPC    %p",
1096 [0x7c]  Jbs,0,          "JLT    %p",
1097 [0x7d]  Jbs,0,          "JGE    %p",
1098 [0x7e]  Jbs,0,          "JLE    %p",
1099 [0x7f]  Jbs,0,          "JGT    %p",
1100 [0x80]  RMOPB,0,        optab80,
1101 [0x81]  RMOP,0,         optab81,
1102 [0x83]  RMOP,0,         optab83,
1103 [0x84]  RMB,0,          "TESTB  %r,%e",
1104 [0x85]  RM,0,           "TEST%S %r,%e",
1105 [0x86]  RMB,0,          "XCHGB  %r,%e",
1106 [0x87]  RM,0,           "XCHG%S %r,%e",
1107 [0x88]  RMB,0,          "MOVB   %r,%e",
1108 [0x89]  RM,0,           "MOV%S  %r,%e",
1109 [0x8a]  RMB,0,          "MOVB   %e,%r",
1110 [0x8b]  RM,0,           "MOV%S  %e,%r",
1111 [0x8c]  RM,0,           "MOVW   %g,%e",
1112 [0x8d]  RM,0,           "LEA%S  %e,%r",
1113 [0x8e]  RM,0,           "MOVW   %e,%g",
1114 [0x8f]  RM,0,           "POP%S  %e",
1115 [0x90]  0,0,            "NOP",
1116 [0x91]  0,0,            "XCHG   %OCX,%OAX",
1117 [0x92]  0,0,            "XCHG   %ODX,%OAX",
1118 [0x93]  0,0,            "XCHG   %OBX,%OAX",
1119 [0x94]  0,0,            "XCHG   %OSP,%OAX",
1120 [0x95]  0,0,            "XCHG   %OBP,%OAX",
1121 [0x96]  0,0,            "XCHG   %OSI,%OAX",
1122 [0x97]  0,0,            "XCHG   %ODI,%OAX",
1123 [0x98]  0,0,            "%W",                   /* miserable CBW or CWDE */
1124 [0x99]  0,0,            "%w",                   /* idiotic CWD or CDQ */
1125 [0x9a]  PTR,0,          "CALL%S %d",
1126 [0x9b]  0,0,            "WAIT",
1127 [0x9c]  0,0,            "PUSHF",
1128 [0x9d]  0,0,            "POPF",
1129 [0x9e]  0,0,            "SAHF",
1130 [0x9f]  0,0,            "LAHF",
1131 [0xa0]  Awd,0,          "MOVB   %i,AL",
1132 [0xa1]  Awd,0,          "MOV%S  %i,%OAX",
1133 [0xa2]  Awd,0,          "MOVB   AL,%i",
1134 [0xa3]  Awd,0,          "MOV%S  %OAX,%i",
1135 [0xa4]  0,0,            "MOVSB  (%ASI),(%ADI)",
1136 [0xa5]  0,0,            "MOVS%S (%ASI),(%ADI)",
1137 [0xa6]  0,0,            "CMPSB  (%ASI),(%ADI)",
1138 [0xa7]  0,0,            "CMPS%S (%ASI),(%ADI)",
1139 [0xa8]  Ib,0,           "TESTB  %i,AL",
1140 [0xa9]  Iwd,0,          "TEST%S %i,%OAX",
1141 [0xaa]  0,0,            "STOSB  AL,(%ADI)",
1142 [0xab]  0,0,            "STOS%S %OAX,(%ADI)",
1143 [0xac]  0,0,            "LODSB  (%ASI),AL",
1144 [0xad]  0,0,            "LODS%S (%ASI),%OAX",
1145 [0xae]  0,0,            "SCASB  (%ADI),AL",
1146 [0xaf]  0,0,            "SCAS%S (%ADI),%OAX",
1147 [0xb0]  Ib,0,           "MOVB   %i,AL",
1148 [0xb1]  Ib,0,           "MOVB   %i,CL",
1149 [0xb2]  Ib,0,           "MOVB   %i,DL",
1150 [0xb3]  Ib,0,           "MOVB   %i,BL",
1151 [0xb4]  Ib,0,           "MOVB   %i,AH",
1152 [0xb5]  Ib,0,           "MOVB   %i,CH",
1153 [0xb6]  Ib,0,           "MOVB   %i,DH",
1154 [0xb7]  Ib,0,           "MOVB   %i,BH",
1155 [0xb8]  Iwdq,0,         "MOV%S  %i,%OAX",
1156 [0xb9]  Iwdq,0,         "MOV%S  %i,%OCX",
1157 [0xba]  Iwdq,0,         "MOV%S  %i,%ODX",
1158 [0xbb]  Iwdq,0,         "MOV%S  %i,%OBX",
1159 [0xbc]  Iwdq,0,         "MOV%S  %i,%OSP",
1160 [0xbd]  Iwdq,0,         "MOV%S  %i,%OBP",
1161 [0xbe]  Iwdq,0,         "MOV%S  %i,%OSI",
1162 [0xbf]  Iwdq,0,         "MOV%S  %i,%ODI",
1163 [0xc0]  RMOPB,0,        optabC0,
1164 [0xc1]  RMOP,0,         optabC1,
1165 [0xc2]  Iw,0,           "RET    %i",
1166 [0xc3]  RET,0,          "RET",
1167 [0xc4]  RM,0,           "LES    %e,%r",
1168 [0xc5]  RM,0,           "LDS    %e,%r",
1169 [0xc6]  RMB,Ib,         "MOVB   %i,%e",
1170 [0xc7]  RM,Iwd,         "MOV%S  %i,%e",
1171 [0xc8]  Iw2,Ib,         "ENTER  %i,%I",         /* loony ENTER */
1172 [0xc9]  RET,0,          "LEAVE",                /* bizarre LEAVE */
1173 [0xca]  Iw,0,           "RETF   %i",
1174 [0xcb]  RET,0,          "RETF",
1175 [0xcc]  0,0,            "INT    3",
1176 [0xcd]  Ib,0,           "INTB   %i",
1177 [0xce]  0,0,            "INTO",
1178 [0xcf]  0,0,            "IRET",
1179 [0xd0]  RMOPB,0,        optabD0,
1180 [0xd1]  RMOP,0,         optabD1,
1181 [0xd2]  RMOPB,0,        optabD2,
1182 [0xd3]  RMOP,0,         optabD3,
1183 [0xd4]  OA,0,           "AAM",
1184 [0xd5]  OA,0,           "AAD",
1185 [0xd7]  0,0,            "XLAT",
1186 [0xd8]  FRMOP,0,        optabD8,
1187 [0xd9]  FRMEX,0,        optabD9,
1188 [0xda]  FRMOP,0,        optabDA,
1189 [0xdb]  FRMEX,0,        optabDB,
1190 [0xdc]  FRMOP,0,        optabDC,
1191 [0xdd]  FRMOP,0,        optabDD,
1192 [0xde]  FRMOP,0,        optabDE,
1193 [0xdf]  FRMOP,0,        optabDF,
1194 [0xe0]  Jbs,0,          "LOOPNE %p",
1195 [0xe1]  Jbs,0,          "LOOPE  %p",
1196 [0xe2]  Jbs,0,          "LOOP   %p",
1197 [0xe3]  Jbs,0,          "JCXZ   %p",
1198 [0xe4]  Ib,0,           "INB    %i,AL",
1199 [0xe5]  Ib,0,           "IN%S   %i,%OAX",
1200 [0xe6]  Ib,0,           "OUTB   AL,%i",
1201 [0xe7]  Ib,0,           "OUT%S  %OAX,%i",
1202 [0xe8]  Iwds,0,         "CALL   %p",
1203 [0xe9]  Iwds,0,         "JMP    %p",
1204 [0xea]  PTR,0,          "JMP    %d",
1205 [0xeb]  Jbs,0,          "JMP    %p",
1206 [0xec]  0,0,            "INB    DX,AL",
1207 [0xed]  0,0,            "IN%S   DX,%OAX",
1208 [0xee]  0,0,            "OUTB   AL,DX",
1209 [0xef]  0,0,            "OUT%S  %OAX,DX",
1210 [0xf0]  PRE,0,          "LOCK",
1211 [0xf2]  OPRE,0,         "REPNE",
1212 [0xf3]  OPRE,0,         "REP",
1213 [0xf4]  0,0,            "HLT",
1214 [0xf5]  0,0,            "CMC",
1215 [0xf6]  RMOPB,0,        optabF6,
1216 [0xf7]  RMOP,0,         optabF7,
1217 [0xf8]  0,0,            "CLC",
1218 [0xf9]  0,0,            "STC",
1219 [0xfa]  0,0,            "CLI",
1220 [0xfb]  0,0,            "STI",
1221 [0xfc]  0,0,            "CLD",
1222 [0xfd]  0,0,            "STD",
1223 [0xfe]  RMOPB,0,        optabFE,
1224 [0xff]  RMOP,0,         optabFF,
1225 [0x100] RM,0,           "MOVLQSX        %r,%e",
1226 };
1227
1228 /*
1229  *  get a byte of the instruction
1230  */
1231 static int
1232 igetc(Map *map, Instr *ip, uchar *c)
1233 {
1234         if(ip->n+1 > sizeof(ip->mem)){
1235                 werrstr("instruction too long");
1236                 return -1;
1237         }
1238         if (get1(map, ip->addr+ip->n, c, 1) < 0) {
1239                 werrstr("can't read instruction: %r");
1240                 return -1;
1241         }
1242         ip->mem[ip->n++] = *c;
1243         return 1;
1244 }
1245
1246 /*
1247  *  get two bytes of the instruction
1248  */
1249 static int
1250 igets(Map *map, Instr *ip, ushort *sp)
1251 {
1252         uchar c;
1253         ushort s;
1254
1255         if (igetc(map, ip, &c) < 0)
1256                 return -1;
1257         s = c;
1258         if (igetc(map, ip, &c) < 0)
1259                 return -1;
1260         s |= (c<<8);
1261         *sp = s;
1262         return 1;
1263 }
1264
1265 /*
1266  *  get 4 bytes of the instruction
1267  */
1268 static int
1269 igetl(Map *map, Instr *ip, ulong *lp)
1270 {
1271         ushort s;
1272         long    l;
1273
1274         if (igets(map, ip, &s) < 0)
1275                 return -1;
1276         l = s;
1277         if (igets(map, ip, &s) < 0)
1278                 return -1;
1279         l |= (s<<16);
1280         *lp = l;
1281         return 1;
1282 }
1283
1284 /*
1285  *  get 8 bytes of the instruction
1286  */
1287 static int
1288 igetq(Map *map, Instr *ip, vlong *qp)
1289 {
1290         ulong   l;
1291         uvlong q;
1292
1293         if (igetl(map, ip, &l) < 0)
1294                 return -1;
1295         q = l;
1296         if (igetl(map, ip, &l) < 0)
1297                 return -1;
1298         q |= ((uvlong)l<<32);
1299         *qp = q;
1300         return 1;
1301 }
1302
1303 static int
1304 getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
1305 {
1306         uchar c;
1307         ushort s;
1308
1309         if (mod > 2)
1310                 return 1;
1311         if (mod == 1) {
1312                 if (igetc(map, ip, &c) < 0)
1313                         return -1;
1314                 if (c&0x80)
1315                         ip->disp = c|0xffffff00;
1316                 else
1317                         ip->disp = c&0xff;
1318         } else if (mod == 2 || rm == code) {
1319                 if (ip->asize == 'E') {
1320                         if (igetl(map, ip, &ip->disp) < 0)
1321                                 return -1;
1322                         if (mod == 0)
1323                                 ip->rip = pcrel;
1324                 } else {
1325                         if (igets(map, ip, &s) < 0)
1326                                 return -1;
1327                         if (s&0x8000)
1328                                 ip->disp = s|0xffff0000;
1329                         else
1330                                 ip->disp = s;
1331                 }
1332                 if (mod == 0)
1333                         ip->base = -1;
1334         }
1335         return 1;
1336 }
1337
1338 static int
1339 modrm(Map *map, Instr *ip, uchar c)
1340 {
1341         uchar rm, mod;
1342
1343         mod = (c>>6)&3;
1344         rm = c&7;
1345         ip->mod = mod;
1346         ip->base = rm;
1347         ip->reg = (c>>3)&7;
1348         ip->rip = 0;
1349         if (mod == 3)                   /* register */
1350                 return 1;
1351         if (ip->asize == 0) {           /* 16-bit mode */
1352                 switch(rm) {
1353                 case 0:
1354                         ip->base = BX; ip->index = SI;
1355                         break;
1356                 case 1:
1357                         ip->base = BX; ip->index = DI;
1358                         break;
1359                 case 2:
1360                         ip->base = BP; ip->index = SI;
1361                         break;
1362                 case 3:
1363                         ip->base = BP; ip->index = DI;
1364                         break;
1365                 case 4:
1366                         ip->base = SI;
1367                         break;
1368                 case 5:
1369                         ip->base = DI;
1370                         break;
1371                 case 6:
1372                         ip->base = BP;
1373                         break;
1374                 case 7:
1375                         ip->base = BX;
1376                         break;
1377                 default:
1378                         break;
1379                 }
1380                 return getdisp(map, ip, mod, rm, 6, 0);
1381         }
1382         if (rm == 4) {  /* scummy sib byte */
1383                 if (igetc(map, ip, &c) < 0)
1384                         return -1;
1385                 ip->ss = (c>>6)&0x03;
1386                 ip->index = (c>>3)&0x07;
1387                 if (ip->index == 4)
1388                         ip->index = -1;
1389                 ip->base = c&0x07;
1390                 return getdisp(map, ip, mod, ip->base, 5, 0);
1391         }
1392         return getdisp(map, ip, mod, rm, 5, ip->amd64);
1393 }
1394
1395 static Optable *
1396 mkinstr(Map *map, Instr *ip, uvlong pc)
1397 {
1398         int i, n, norex;
1399         uchar c;
1400         ushort s;
1401         Optable *op, *obase;
1402         char buf[128];
1403
1404         memset(ip, 0, sizeof(*ip));
1405         norex = 1;
1406         ip->base = -1;
1407         ip->index = -1;
1408         if(asstype == AI8086)
1409                 ip->osize = 'W';
1410         else {
1411                 ip->osize = 'L';
1412                 ip->asize = 'E';
1413                 ip->amd64 = asstype != AI386;
1414                 norex = 0;
1415         }
1416         ip->addr = pc;
1417         if (igetc(map, ip, &c) < 0)
1418                 return 0;
1419         obase = optable;
1420 newop:
1421         if(ip->amd64 && !norex){
1422                 if(c >= 0x40 && c <= 0x4f) {
1423                         ip->rex = c;
1424                         if(igetc(map, ip, &c) < 0)
1425                                 return 0;
1426                 }
1427                 if(c == 0x63){
1428                         op = &obase[0x100];     /* MOVLQSX */
1429                         goto hack;
1430                 }
1431         }
1432         op = &obase[c];
1433 hack:
1434         if (op->proto == 0) {
1435 badop:
1436                 n = snprint(buf, sizeof(buf), "opcode: ??");
1437                 for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
1438                         _hexify(buf+n, ip->mem[i], 1);
1439                 strcpy(buf+n, "??");
1440                 werrstr(buf);
1441                 return 0;
1442         }
1443         for(i = 0; i < 2 && op->operand[i]; i++) {
1444                 switch(op->operand[i]) {
1445                 case Ib:        /* 8-bit immediate - (no sign extension)*/
1446                         if (igetc(map, ip, &c) < 0)
1447                                 return 0;
1448                         ip->imm = c&0xff;
1449                         ip->imm64 = ip->imm;
1450                         break;
1451                 case Jbs:       /* 8-bit jump immediate (sign extended) */
1452                         if (igetc(map, ip, &c) < 0)
1453                                 return 0;
1454                         if (c&0x80)
1455                                 ip->imm = c|0xffffff00;
1456                         else
1457                                 ip->imm = c&0xff;
1458                         ip->imm64 = (long)ip->imm;
1459                         ip->jumptype = Jbs;
1460                         break;
1461                 case Ibs:       /* 8-bit immediate (sign extended) */
1462                         if (igetc(map, ip, &c) < 0)
1463                                 return 0;
1464                         if (c&0x80)
1465                                 if (ip->osize == 'L')
1466                                         ip->imm = c|0xffffff00;
1467                                 else
1468                                         ip->imm = c|0xff00;
1469                         else
1470                                 ip->imm = c&0xff;
1471                         ip->imm64 = (long)ip->imm;
1472                         break;
1473                 case Iw:        /* 16-bit immediate -> imm */
1474                         if (igets(map, ip, &s) < 0)
1475                                 return 0;
1476                         ip->imm = s&0xffff;
1477                         ip->imm64 = ip->imm;
1478                         ip->jumptype = Iw;
1479                         break;
1480                 case Iw2:       /* 16-bit immediate -> in imm2*/
1481                         if (igets(map, ip, &s) < 0)
1482                                 return 0;
1483                         ip->imm2 = s&0xffff;
1484                         break;
1485                 case Iwd:       /* Operand-sized immediate (no sign extension unless 64 bits)*/
1486                         if (ip->osize == 'L') {
1487                                 if (igetl(map, ip, &ip->imm) < 0)
1488                                         return 0;
1489                                 ip->imm64 = ip->imm;
1490                                 if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
1491                                         ip->imm64 |= (vlong)~0 << 32;
1492                         } else {
1493                                 if (igets(map, ip, &s)< 0)
1494                                         return 0;
1495                                 ip->imm = s&0xffff;
1496                                 ip->imm64 = ip->imm;
1497                         }
1498                         break;
1499                 case Iwdq:      /* Operand-sized immediate, possibly big */
1500                         if (ip->osize == 'L') {
1501                                 if (igetl(map, ip, &ip->imm) < 0)
1502                                         return 0;
1503                                 ip->imm64 = ip->imm;
1504                                 if (ip->rex & REXW) {
1505                                         ulong l;
1506                                         if (igetl(map, ip, &l) < 0)
1507                                                 return 0;
1508                                         ip->imm64 |= (uvlong)l << 32;
1509                                 }
1510                         } else {
1511                                 if (igets(map, ip, &s)< 0)
1512                                         return 0;
1513                                 ip->imm = s&0xffff;
1514                         }
1515                         break;
1516                 case Awd:       /* Address-sized immediate (no sign extension)*/
1517                         if (ip->asize == 'E') {
1518                                 if (igetl(map, ip, &ip->imm) < 0)
1519                                         return 0;
1520                                 /* TO DO: REX */
1521                         } else {
1522                                 if (igets(map, ip, &s)< 0)
1523                                         return 0;
1524                                 ip->imm = s&0xffff;
1525                         }
1526                         break;
1527                 case Iwds:      /* Operand-sized immediate (sign extended) */
1528                         if (ip->osize == 'L') {
1529                                 if (igetl(map, ip, &ip->imm) < 0)
1530                                         return 0;
1531                         } else {
1532                                 if (igets(map, ip, &s)< 0)
1533                                         return 0;
1534                                 if (s&0x8000)
1535                                         ip->imm = s|0xffff0000;
1536                                 else
1537                                         ip->imm = s&0xffff;
1538                         }
1539                         ip->jumptype = Iwds;
1540                         break;
1541                 case OA:        /* literal 0x0a byte */
1542                         if (igetc(map, ip, &c) < 0)
1543                                 return 0;
1544                         if (c != 0x0a)
1545                                 goto badop;
1546                         break;
1547                 case R0:        /* base register must be R0 */
1548                         if (ip->base != 0)
1549                                 goto badop;
1550                         break;
1551                 case R1:        /* base register must be R1 */
1552                         if (ip->base != 1)
1553                                 goto badop;
1554                         break;
1555                 case RMB:       /* R/M field with byte register (/r)*/
1556                         if (igetc(map, ip, &c) < 0)
1557                                 return 0;
1558                         if (modrm(map, ip, c) < 0)
1559                                 return 0;
1560                         ip->osize = 'B';
1561                         break;
1562                 case RM:        /* R/M field with register (/r) */
1563                         if (igetc(map, ip, &c) < 0)
1564                                 return 0;
1565                         if (modrm(map, ip, c) < 0)
1566                                 return 0;
1567                         break;
1568                 case RMOPB:     /* R/M field with op code (/digit) */
1569                         if (igetc(map, ip, &c) < 0)
1570                                 return 0;
1571                         if (modrm(map, ip, c) < 0)
1572                                 return 0;
1573                         c = ip->reg;            /* secondary op code */
1574                         obase = (Optable*)op->proto;
1575                         ip->osize = 'B';
1576                         goto newop;
1577                 case RMOP:      /* R/M field with op code (/digit) */
1578                         if (igetc(map, ip, &c) < 0)
1579                                 return 0;
1580                         if (modrm(map, ip, c) < 0)
1581                                 return 0;
1582                         obase = (Optable*)op->proto;
1583                         if(ip->amd64 && obase == optab0F01 && c == 0xF8)
1584                                 return optab0F01F8;
1585                         c = ip->reg;
1586                         goto newop;
1587                 case FRMOP:     /* FP R/M field with op code (/digit) */
1588                         if (igetc(map, ip, &c) < 0)
1589                                 return 0;
1590                         if (modrm(map, ip, c) < 0)
1591                                 return 0;
1592                         if ((c&0xc0) == 0xc0)
1593                                 c = ip->reg+8;          /* 16 entry table */
1594                         else
1595                                 c = ip->reg;
1596                         obase = (Optable*)op->proto;
1597                         goto newop;
1598                 case FRMEX:     /* Extended FP R/M field with op code (/digit) */
1599                         if (igetc(map, ip, &c) < 0)
1600                                 return 0;
1601                         if (modrm(map, ip, c) < 0)
1602                                 return 0;
1603                         if ((c&0xc0) == 0xc0)
1604                                 c = (c&0x3f)+8;         /* 64-entry table */
1605                         else
1606                                 c = ip->reg;
1607                         obase = (Optable*)op->proto;
1608                         goto newop;
1609                 case RMR:       /* R/M register only (mod = 11) */
1610                         if (igetc(map, ip, &c) < 0)
1611                                 return 0;
1612                         if ((c&0xc0) != 0xc0) {
1613                                 werrstr("invalid R/M register: %x", c);
1614                                 return 0;
1615                         }
1616                         if (modrm(map, ip, c) < 0)
1617                                 return 0;
1618                         break;
1619                 case RMM:       /* R/M register only (mod = 11) */
1620                         if (igetc(map, ip, &c) < 0)
1621                                 return 0;
1622                         if ((c&0xc0) == 0xc0) {
1623                                 werrstr("invalid R/M memory mode: %x", c);
1624                                 return 0;
1625                         }
1626                         if (modrm(map, ip, c) < 0)
1627                                 return 0;
1628                         break;
1629                 case PTR:       /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
1630                         if (ip->osize == 'L') {
1631                                 if (igetl(map, ip, &ip->disp) < 0)
1632                                         return 0;
1633                         } else {
1634                                 if (igets(map, ip, &s)< 0)
1635                                         return 0;
1636                                 ip->disp = s&0xffff;
1637                         }
1638                         if (igets(map, ip, (ushort*)&ip->seg) < 0)
1639                                 return 0;
1640                         ip->jumptype = PTR;
1641                         break;
1642                 case AUXMM:     /* Multi-byte op code; prefix determines table selection */
1643                         if (igetc(map, ip, &c) < 0)
1644                                 return 0;
1645                         obase = (Optable*)op->proto;
1646                         switch (ip->opre) {
1647                         case 0x66:      op = optab660F; break;
1648                         case 0xF2:      op = optabF20F; break;
1649                         case 0xF3:      op = optabF30F; break;
1650                         default:        op = nil; break;
1651                         }
1652                         if(op != nil && op[c].proto != nil)
1653                                 obase = op;
1654                         norex = 1;      /* no more rex prefixes */
1655                         /* otherwise the optab entry captures it */
1656                         goto newop;
1657                 case AUX:       /* Multi-byte op code - Auxiliary table */
1658                         obase = (Optable*)op->proto;
1659                         if (igetc(map, ip, &c) < 0)
1660                                 return 0;
1661                         goto newop;
1662                 case OPRE:      /* Instr Prefix or media op */
1663                         ip->opre = c;
1664                         /* fall through */
1665                 case PRE:       /* Instr Prefix */
1666                         ip->prefix = (char*)op->proto;
1667                         if (igetc(map, ip, &c) < 0)
1668                                 return 0;
1669                         if (ip->opre && c == 0x0F)
1670                                 ip->prefix = 0;
1671                         goto newop;
1672                 case SEG:       /* Segment Prefix */
1673                         ip->segment = (char*)op->proto;
1674                         if (igetc(map, ip, &c) < 0)
1675                                 return 0;
1676                         goto newop;
1677                 case OPOVER:    /* Operand size override */
1678                         ip->opre = c;
1679                         ip->osize = 'W';
1680                         if (igetc(map, ip, &c) < 0)
1681                                 return 0;
1682                         if (c == 0x0F)
1683                                 ip->osize = 'L';
1684                         else if (ip->amd64 && (c&0xF0) == 0x40)
1685                                 ip->osize = 'Q';
1686                         goto newop;
1687                 case ADDOVER:   /* Address size override */
1688                         ip->asize = 0;
1689                         if (igetc(map, ip, &c) < 0)
1690                                 return 0;
1691                         goto newop;
1692                 case JUMP:      /* mark instruction as JUMP or RET */
1693                 case RET:
1694                         ip->jumptype = op->operand[i];
1695                         break;
1696                 default:
1697                         werrstr("bad operand type %d", op->operand[i]);
1698                         return 0;
1699                 }
1700         }
1701         return op;
1702 }
1703
1704 #pragma varargck        argpos  bprint          2
1705
1706 static void
1707 bprint(Instr *ip, char *fmt, ...)
1708 {
1709         va_list arg;
1710
1711         va_start(arg, fmt);
1712         ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
1713         va_end(arg);
1714 }
1715
1716 /*
1717  *  if we want to call 16 bit regs AX,BX,CX,...
1718  *  and 32 bit regs EAX,EBX,ECX,... then
1719  *  change the defs of ANAME and ONAME to:
1720  *  #define     ANAME(ip)       ((ip->asize == 'E' ? "E" : "")
1721  *  #define     ONAME(ip)       ((ip)->osize == 'L' ? "E" : "")
1722  */
1723 #define ANAME(ip)       ""
1724 #define ONAME(ip)       ""
1725
1726 static char *reg[] =  {
1727 [AX]    "AX",
1728 [CX]    "CX",
1729 [DX]    "DX",
1730 [BX]    "BX",
1731 [SP]    "SP",
1732 [BP]    "BP",
1733 [SI]    "SI",
1734 [DI]    "DI",
1735
1736         /* amd64 */
1737 [R8]    "R8",
1738 [R9]    "R9",
1739 [R10]   "R10",
1740 [R11]   "R11",
1741 [R12]   "R12",
1742 [R13]   "R13",
1743 [R14]   "R14",
1744 [R15]   "R15",
1745 };
1746
1747 static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
1748 static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
1749         "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
1750 static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
1751
1752 static void
1753 plocal(Instr *ip)
1754 {
1755         int ret;
1756         long offset;
1757         Symbol s;
1758         char *reg;
1759
1760         offset = ip->disp;
1761         if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
1762                 bprint(ip, "%lux(SP)", offset);
1763                 return;
1764         }
1765
1766         if (s.value > ip->disp) {
1767                 ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
1768                 reg = "(SP)";
1769         } else {
1770                 offset -= s.value;
1771                 ret = getauto(&s, offset, CPARAM, &s);
1772                 reg = "(FP)";
1773         }
1774         if (ret)
1775                 bprint(ip, "%s+", s.name);
1776         else
1777                 offset = ip->disp;
1778         bprint(ip, "%lux%s", offset, reg);
1779 }
1780
1781 static int
1782 isjmp(Instr *ip)
1783 {
1784         switch(ip->jumptype){
1785         case Iwds:
1786         case Jbs:
1787         case JUMP:
1788                 return 1;
1789         default:
1790                 return 0;
1791         }
1792 }
1793
1794 /*
1795  * This is too smart for its own good, but it really is nice
1796  * to have accurate translations when debugging, and it
1797  * helps us identify which code is different in binaries that
1798  * are changed on sources.
1799  */
1800 static int
1801 issymref(Instr *ip, Symbol *s, long w, long val)
1802 {
1803         Symbol next, tmp;
1804         long isstring, size;
1805
1806         if (isjmp(ip))
1807                 return 1;
1808         if (s->class==CTEXT && w==0)
1809                 return 1;
1810         if (s->class==CDATA) {
1811                 /* use first bss symbol (or "end") rather than edata */
1812                 if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
1813                         if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value)
1814                         || (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value))
1815                                 *s = tmp;
1816                 }
1817                 if (w == 0)
1818                         return 1;
1819                 for (next=*s; next.value==s->value; next=tmp)
1820                         if (!globalsym(&tmp, next.index+1))
1821                                 break;
1822                 size = next.value - s->value;
1823                 if (w >= size)
1824                         return 0;
1825                 if (w > size-w)
1826                         w = size-w;
1827                 /* huge distances are usually wrong except in .string */
1828                 isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
1829                 if (w > 8192 && !isstring)
1830                         return 0;
1831                 /* medium distances are tricky - look for constants */
1832                 /* near powers of two */
1833                 if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
1834                         return 0;
1835                 return 1;
1836         }
1837         return 0;
1838 }
1839
1840 static void
1841 immediate(Instr *ip, vlong val)
1842 {
1843         Symbol s;
1844         long w;
1845
1846         if (findsym(val, CANY, &s)) {           /* TO DO */
1847                 w = val - s.value;
1848                 if (w < 0)
1849                         w = -w;
1850                 if (issymref(ip, &s, w, val)) {
1851                         if (w)
1852                                 bprint(ip, "%s+%lux(SB)", s.name, w);
1853                         else
1854                                 bprint(ip, "%s(SB)", s.name);
1855                         return;
1856                 }
1857 /*
1858                 if (s.class==CDATA && globalsym(&s, s.index+1)) {
1859                         w = s.value - val;
1860                         if (w < 0)
1861                                 w = -w;
1862                         if (w < 4096) {
1863                                 bprint(ip, "%s-%lux(SB)", s.name, w);
1864                                 return;
1865                         }
1866                 }
1867 */
1868         }
1869         if((ip->rex & REXW) == 0)
1870                 bprint(ip, "%lux", (long)val);
1871         else
1872                 bprint(ip, "%llux", val);
1873 }
1874
1875 static void
1876 pea(Instr *ip)
1877 {
1878         if (ip->mod == 3) {
1879                 if (ip->osize == 'B')
1880                         bprint(ip, (ip->rex & REXB? breg64: breg)[ip->base]);
1881                 else if(ip->rex & REXB)
1882                         bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]);
1883                 else
1884                         bprint(ip, "%s%s", ANAME(ip), reg[ip->base]);
1885                 return;
1886         }
1887         if (ip->segment)
1888                 bprint(ip, ip->segment);
1889         if (ip->asize == 'E' && ip->base == SP)
1890                 plocal(ip);
1891         else {
1892                 if (ip->base < 0)
1893                         immediate(ip, ip->disp);
1894                 else {
1895                         bprint(ip, "%lux", ip->disp);
1896                         if(ip->rip)
1897                                 bprint(ip, "(RIP)");
1898                         bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
1899                 }
1900         }
1901         if (ip->index >= 0)
1902                 bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
1903 }
1904
1905 static void
1906 prinstr(Instr *ip, char *fmt)
1907 {
1908         vlong v;
1909
1910         if (ip->prefix)
1911                 bprint(ip, "%s ", ip->prefix);
1912         for (; *fmt && ip->curr < ip->end; fmt++) {
1913                 if (*fmt != '%'){
1914                         *ip->curr++ = *fmt;
1915                         continue;
1916                 }
1917                 switch(*++fmt){
1918                 case '%':
1919                         *ip->curr++ = '%';
1920                         break;
1921                 case 'A':
1922                         bprint(ip, "%s", ANAME(ip));
1923                         break;
1924                 case 'C':
1925                         bprint(ip, "CR%d", ip->reg);
1926                         break;
1927                 case 'D':
1928                         if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
1929                                 bprint(ip, "DR%d",ip->reg);
1930                         else
1931                                 bprint(ip, "???");
1932                         break;
1933                 case 'I':
1934                         bprint(ip, "$");
1935                         immediate(ip, ip->imm2);
1936                         break;
1937                 case 'O':
1938                         bprint(ip,"%s", ONAME(ip));
1939                         break;
1940                 case 'i':
1941                         bprint(ip, "$");
1942                         v = ip->imm;
1943                         if(ip->rex & REXW)
1944                                 v = ip->imm64;
1945                         immediate(ip, v);
1946                         break;
1947                 case 'R':
1948                         bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
1949                         break;
1950                 case 'S':
1951                         if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1952                                 bprint(ip, "Q");
1953                         else
1954                                 bprint(ip, "%c", ip->osize);
1955                         break;
1956                 case 's':
1957                         if(ip->opre == 0 || ip->opre == 0x66)
1958                                 bprint(ip, "P");
1959                         else
1960                                 bprint(ip, "S");
1961                         if(ip->opre == 0xf2 || ip->opre == 0x66)
1962                                 bprint(ip, "D");
1963                         else
1964                                 bprint(ip, "S");
1965                         break;
1966                 case 'T':
1967                         if (ip->reg == 6 || ip->reg == 7)
1968                                 bprint(ip, "TR%d",ip->reg);
1969                         else
1970                                 bprint(ip, "???");
1971                         break;
1972                 case 'W':
1973                         if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
1974                                 bprint(ip, "CDQE");
1975                         else if (ip->osize == 'L')
1976                                 bprint(ip,"CWDE");
1977                         else
1978                                 bprint(ip, "CBW");
1979                         break;
1980                 case 'd':
1981                         bprint(ip,"%ux:%lux",ip->seg,ip->disp);
1982                         break;
1983                 case 'm':
1984                         if (ip->mod == 3 && ip->osize != 'B') {
1985                                 if(fmt[1] != '*'){
1986                                         if(ip->opre != 0) {
1987                                                 bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
1988                                                 break;
1989                                         }
1990                                 } else
1991                                         fmt++;
1992                                 bprint(ip, "M%d", ip->base);
1993                                 break;
1994                         }
1995                         pea(ip);
1996                         break;
1997                 case 'e':
1998                         pea(ip);
1999                         break;
2000                 case 'f':
2001                         bprint(ip, "F%d", ip->base);
2002                         break;
2003                 case 'g':
2004                         if (ip->reg < 6)
2005                                 bprint(ip,"%s",sreg[ip->reg]);
2006                         else
2007                                 bprint(ip,"???");
2008                         break;
2009                 case 'p':
2010                         /*
2011                          * signed immediate in the ulong ip->imm.
2012                          */
2013                         v = (long)ip->imm;
2014                         immediate(ip, v+ip->addr+ip->n);
2015                         break;
2016                 case 'r':
2017                         if (ip->osize == 'B')
2018                                 bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
2019                         else
2020                                 bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
2021                         break;
2022                 case 'w':
2023                         if (ip->osize == 'Q' || ip->rex & REXW)
2024                                 bprint(ip, "CQO");
2025                         else if (ip->osize == 'L')
2026                                 bprint(ip,"CDQ");
2027                         else
2028                                 bprint(ip, "CWD");
2029                         break;
2030                 case 'M':
2031                         if(ip->opre != 0)
2032                                 bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2033                         else
2034                                 bprint(ip, "M%d", ip->reg);
2035                         break;
2036                 case 'x':
2037                         if (ip->mod == 3 && ip->osize != 'B') {
2038                                 bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
2039                                 break;
2040                         }
2041                         pea(ip);
2042                         break;
2043                 case 'X':
2044                         bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
2045                         break;
2046                 default:
2047                         bprint(ip, "%%%c", *fmt);
2048                         break;
2049                 }
2050         }
2051         *ip->curr = 0;          /* there's always room for 1 byte */
2052 }
2053
2054 static int
2055 i386inst(Map *map, uvlong pc, char modifier, char *buf, int n)
2056 {
2057         Instr instr;
2058         Optable *op;
2059
2060         USED(modifier);
2061         op = mkinstr(map, &instr, pc);
2062         if (op == 0) {
2063                 errstr(buf, n);
2064                 return -1;
2065         }
2066         instr.curr = buf;
2067         instr.end = buf+n-1;
2068         prinstr(&instr, op->proto);
2069         return instr.n;
2070 }
2071
2072 static int
2073 i386das(Map *map, uvlong pc, char *buf, int n)
2074 {
2075         Instr instr;
2076         int i;
2077
2078         if (mkinstr(map, &instr, pc) == 0) {
2079                 errstr(buf, n);
2080                 return -1;
2081         }
2082         for(i = 0; i < instr.n && n > 2; i++) {
2083                 _hexify(buf, instr.mem[i], 1);
2084                 buf += 2;
2085                 n -= 2;
2086         }
2087         *buf = 0;
2088         return instr.n;
2089 }
2090
2091 static int
2092 i386instlen(Map *map, uvlong pc)
2093 {
2094         Instr i;
2095
2096         if (mkinstr(map, &i, pc))
2097                 return i.n;
2098         return -1;
2099 }
2100
2101 static int
2102 i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
2103 {
2104         Instr i;
2105         Optable *op;
2106         ushort s;
2107         uvlong l, addr;
2108         vlong v;
2109         int n;
2110
2111         op = mkinstr(map, &i, pc);
2112         if (!op)
2113                 return -1;
2114
2115         n = 0;
2116
2117         switch(i.jumptype) {
2118         case RET:               /* RETURN or LEAVE */
2119         case Iw:                /* RETURN */
2120                 if (strcmp(op->proto, "LEAVE") == 0) {
2121                         if (geta(map, (*rget)(map, "BP"), &l) < 0)
2122                                 return -1;
2123                 } else if (geta(map, (*rget)(map, mach->sp), &l) < 0)
2124                         return -1;
2125                 foll[0] = l;
2126                 return 1;
2127         case Iwds:              /* pc relative JUMP or CALL*/
2128         case Jbs:               /* pc relative JUMP or CALL */
2129                 v = (long)i.imm;
2130                 foll[0] = pc+v+i.n;
2131                 n = 1;
2132                 break;
2133         case PTR:               /* seg:displacement JUMP or CALL */
2134                 foll[0] = (i.seg<<4)+i.disp;
2135                 return 1;
2136         case JUMP:              /* JUMP or CALL EA */
2137
2138                 if(i.mod == 3) {
2139                         foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]);
2140                         return 1;
2141                 }
2142                         /* calculate the effective address */
2143                 addr = i.disp;
2144                 if (i.base >= 0) {
2145                         if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0)
2146                                 return -1;
2147                         addr += l;
2148                 }
2149                 if (i.index >= 0) {
2150                         if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0)
2151                                 return -1;
2152                         addr += l*(1<<i.ss);
2153                 }
2154                         /* now retrieve a seg:disp value at that address */
2155                 if (get2(map, addr, &s) < 0)                    /* seg */
2156                         return -1;
2157                 foll[0] = s<<4;
2158                 addr += 2;
2159                 if (i.asize == 'L') {
2160                         if (geta(map, addr, &l) < 0)            /* disp32 */
2161                                 return -1;
2162                         foll[0] += l;
2163                 } else {                                        /* disp16 */
2164                         if (get2(map, addr, &s) < 0)
2165                                 return -1;
2166                         foll[0] += s;
2167                 }
2168                 return 1;
2169         default:
2170                 break;
2171         }               
2172         if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
2173                 return 1;
2174         foll[n++] = pc+i.n;
2175         return n;
2176 }