plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

mach386.c (62651B)


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