The Go Programming Language

Text file src/libmach/8db.c

     1	// Inferno libmach/8db.c
     2	// http://code.google.com/p/inferno-os/source/browse/utils/libmach/8db.c
     3	//
     4	// 	Copyright © 1994-1999 Lucent Technologies Inc.
     5	// 	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
     6	// 	Portions Copyright © 1997-1999 Vita Nuova Limited.
     7	// 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
     8	// 	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
     9	//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    10	//
    11	// Permission is hereby granted, free of charge, to any person obtaining a copy
    12	// of this software and associated documentation files (the "Software"), to deal
    13	// in the Software without restriction, including without limitation the rights
    14	// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    15	// copies of the Software, and to permit persons to whom the Software is
    16	// furnished to do so, subject to the following conditions:
    17	//
    18	// The above copyright notice and this permission notice shall be included in
    19	// all copies or substantial portions of the Software.
    20	//
    21	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    22	// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    23	// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    24	// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    25	// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    26	// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    27	// THE SOFTWARE.
    28	
    29	#include <u.h>
    30	#include <libc.h>
    31	#include <bio.h>
    32	#include <mach.h>
    33	#define Ureg UregAmd64
    34	#include <ureg_amd64.h>
    35	#undef Ureg
    36	#define Ureg Ureg386
    37	#include <ureg_x86.h>
    38	#undef Ureg
    39	
    40	typedef struct UregAmd64 UregAmd64;
    41	typedef struct Ureg386 Ureg386;
    42	
    43	/*
    44	 * i386-specific debugger interface
    45	 * also amd64 extensions
    46	 */
    47	
    48	static	char	*i386excep(Map*, Rgetter);
    49	
    50	static	int	i386trace(Map*, uvlong, uvlong, uvlong, Tracer);
    51	static	uvlong	i386frame(Map*, uvlong, uvlong, uvlong, uvlong);
    52	static	int	i386foll(Map*, uvlong, Rgetter, uvlong*);
    53	static	int	i386inst(Map*, uvlong, char, char*, int);
    54	static	int	i386das(Map*, uvlong, char*, int);
    55	static	int	i386instlen(Map*, uvlong);
    56	
    57	static	char	STARTSYM[] =	"_main";
    58	static	char	GOSTARTSYM[] =	"sys·goexit";
    59	static	char	PROFSYM[] =	"_mainp";
    60	static	char	FRAMENAME[] =	".frame";
    61	static	char	LESSSTACK[] = "sys·lessstack";
    62	static	char	MORESTACK[] = "sys·morestack";
    63	static char *excname[] =
    64	{
    65	[0] =	"divide error",
    66	[1] =	"debug exception",
    67	[4] =	"overflow",
    68	[5] =	"bounds check",
    69	[6] =	"invalid opcode",
    70	[7] =	"math coprocessor emulation",
    71	[8] =	"double fault",
    72	[9] =	"math coprocessor overrun",
    73	[10] =	"invalid TSS",
    74	[11] =	"segment not present",
    75	[12] =	"stack exception",
    76	[13] =	"general protection violation",
    77	[14] =	"page fault",
    78	[16] =	"math coprocessor error",
    79	[17] =	"alignment check",
    80	[18] =	"machine check",
    81	[19] =	"floating-point exception",
    82	[24] =	"clock",
    83	[25] =	"keyboard",
    84	[27] =	"modem status",
    85	[28] =	"serial line status",
    86	[30] =	"floppy disk",
    87	[36] =	"mouse",
    88	[37] =	"math coprocessor",
    89	[38] =	"hard disk",
    90	[64] =	"system call",
    91	};
    92	
    93	Machdata i386mach =
    94	{
    95		{0xCC, 0, 0, 0},	/* break point: INT 3 */
    96		1,			/* break point size */
    97	
    98		leswab,			/* convert short to local byte order */
    99		leswal,			/* convert int32 to local byte order */
   100		leswav,			/* convert vlong to local byte order */
   101		i386trace,		/* C traceback */
   102		i386frame,		/* frame finder */
   103		i386excep,		/* print exception */
   104		0,			/* breakpoint fixup */
   105		leieeesftos,		/* single precision float printer */
   106		leieeedftos,		/* double precision float printer */
   107		i386foll,		/* following addresses */
   108		i386inst,		/* print instruction */
   109		i386das,		/* dissembler */
   110		i386instlen,		/* instruction size calculation */
   111	};
   112	
   113	static char*
   114	i386excep(Map *map, Rgetter rget)
   115	{
   116		uint32 c;
   117		uvlong pc;
   118		static char buf[16];
   119	
   120		c = (*rget)(map, "TRAP");
   121		if(c > 64 || excname[c] == 0) {
   122			if (c == 3) {
   123				pc = (*rget)(map, "PC");
   124				if (get1(map, pc, (uchar*)buf, machdata->bpsize) > 0)
   125				if (memcmp(buf, machdata->bpinst, machdata->bpsize) == 0)
   126					return "breakpoint";
   127			}
   128			snprint(buf, sizeof(buf), "exception %ld", c);
   129			return buf;
   130		} else
   131			return excname[c];
   132	}
   133	
   134	static int
   135	i386trace(Map *map, uvlong pc, uvlong sp, uvlong link, Tracer trace)
   136	{
   137		int i;
   138		uvlong osp, pc1;
   139		Symbol s, f, s1;
   140		extern Mach mamd64;
   141		int isamd64;
   142		uvlong g, m, lessstack, morestack, stktop;
   143	
   144		isamd64 = (mach == &mamd64);
   145	
   146		// ../pkg/runtime/runtime.h
   147		// G is
   148		//	byte* stackguard
   149		//	byte* stackbase (= Stktop*)
   150		// TODO(rsc): Need some way to get at the g for other threads.
   151		// Probably need to pass it into the trace function.
   152		g = 0;
   153		if(isamd64)
   154			geta(map, offsetof(struct UregAmd64, r15), &g);
   155		else {
   156			// TODO(rsc): How to fetch g on 386?
   157		}
   158		stktop = 0;
   159		if(g != 0)
   160			geta(map, g+1*mach->szaddr, &stktop);
   161	
   162		lessstack = 0;
   163		if(lookup(0, LESSSTACK, &s))
   164			lessstack = s.value;
   165		morestack = 0;
   166		if(lookup(0, MORESTACK, &s))
   167			morestack = s.value;
   168	
   169		USED(link);
   170		osp = 0;
   171		i = 0;
   172	
   173		for(;;) {
   174			if(!findsym(pc, CTEXT, &s)) {
   175				// check for closure return sequence
   176				uchar buf[8], *p;
   177				if(get1(map, pc, buf, 8) < 0)
   178					break;
   179				// ADDQ $xxx, SP; RET
   180				p = buf;
   181				if(mach == &mamd64) {
   182					if(p[0] != 0x48)
   183						break;
   184					p++;
   185				}
   186				if(p[0] != 0x81 || p[1] != 0xc4 || p[6] != 0xc3)
   187					break;
   188				sp += p[2] | (p[3]<<8) | (p[4]<<16) | (p[5]<<24);
   189				if(geta(map, sp, &pc) < 0)
   190					break;
   191				sp += mach->szaddr;
   192				continue;
   193			}
   194	
   195			if (osp == sp)
   196				break;
   197			osp = sp;
   198	
   199			if(strcmp(STARTSYM, s.name) == 0 ||
   200			   strcmp(GOSTARTSYM, s.name) == 0 ||
   201			   strcmp(PROFSYM, s.name) == 0)
   202				break;
   203	
   204			if(s.value == morestack) {
   205				// In the middle of morestack.
   206				// Caller is m->morepc.
   207				// Caller's caller is in m->morearg.
   208				// TODO(rsc): 386
   209				geta(map, offsetof(struct UregAmd64, r14), &m);
   210	
   211				pc = 0;
   212				sp = 0;
   213				pc1 = 0;
   214				s1 = s;
   215				memset(&s, 0, sizeof s);
   216				geta(map, m+1*mach->szaddr, &pc1);	// m->morepc
   217				geta(map, m+2*mach->szaddr, &sp);	// m->morebuf.sp
   218				geta(map, m+3*mach->szaddr, &pc);	// m->morebuf.pc
   219				findsym(pc1, CTEXT, &s);
   220				(*trace)(map, pc1, sp-mach->szaddr, &s1);	// morestack symbol; caller's PC/SP
   221	
   222				// caller's caller
   223				s1 = s;
   224				findsym(pc, CTEXT, &s);
   225				(*trace)(map, pc, sp, &s1);		// morestack's caller; caller's caller's PC/SP
   226				continue;
   227			}
   228	
   229			if(pc == lessstack) {
   230				// ../pkg/runtime/runtime.h
   231				// Stktop is
   232				//	byte* stackguard
   233				//	byte* stackbase
   234				//	Gobuf gobuf
   235				//		byte* sp;
   236				//		byte* pc;
   237				//		G*	g;
   238				if(!isamd64)
   239					fprint(2, "warning: cannot unwind stack split on 386\n");
   240				if(stktop == 0)
   241					break;
   242				pc = 0;
   243				sp = 0;
   244				geta(map, stktop+2*mach->szaddr, &sp);
   245				geta(map, stktop+3*mach->szaddr, &pc);
   246				geta(map, stktop+1*mach->szaddr, &stktop);
   247				(*trace)(map, pc, sp, &s1);
   248				continue;
   249			}
   250	
   251			s1 = s;
   252			pc1 = 0;
   253			if(pc != s.value) {	/* not at first instruction */
   254				if(findlocal(&s, FRAMENAME, &f) == 0)
   255					break;
   256				geta(map, sp, &pc1);
   257				sp += f.value-mach->szaddr;
   258			}
   259			if(geta(map, sp, &pc) < 0)
   260				break;
   261	
   262			// If PC is not valid, assume we caught the function
   263			// before it moved the stack pointer down or perhaps
   264			// after it moved the stack pointer back up.
   265			// Try the PC we'd have gotten without the stack
   266			// pointer adjustment above (pc != s.value).
   267			// This only matters for the first frame, and it is only
   268			// a heuristic, but it does help.
   269			if(!findsym(pc, CTEXT, &s) || strcmp(s.name, "etext") == 0)
   270				pc = pc1;
   271	
   272			if(pc == 0)
   273				break;
   274	
   275			if(pc != lessstack)
   276				(*trace)(map, pc, sp, &s1);
   277			sp += mach->szaddr;
   278	
   279			if(++i > 1000)
   280				break;
   281		}
   282		return i;
   283	}
   284	
   285	static uvlong
   286	i386frame(Map *map, uvlong addr, uvlong pc, uvlong sp, uvlong link)
   287	{
   288		Symbol s, f;
   289	
   290		USED(link);
   291		while (findsym(pc, CTEXT, &s)) {
   292			if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
   293				break;
   294	
   295			if(pc != s.value) {	/* not first instruction */
   296				if(findlocal(&s, FRAMENAME, &f) == 0)
   297					break;
   298				sp += f.value-mach->szaddr;
   299			}
   300	
   301			if (s.value == addr)
   302				return sp;
   303	
   304			if (geta(map, sp, &pc) < 0)
   305				break;
   306			sp += mach->szaddr;
   307		}
   308		return 0;
   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	[0x7E] =	{ RM,0,		"MOV%S %M,%e" },
   692	[0x7F] =	{ RM,0,		"MOVQ %M,%m" },
   693	[0xAE] =	{ RMOP,0,		optab0FAE },
   694	[0xAA] =	{ 0,0,		"RSM" },
   695	[0xB0] =	{ RM,0,		"CMPXCHGB	%r,%e" },
   696	[0xB1] =	{ RM,0,		"CMPXCHG%S	%r,%e" },
   697	[0xC0] =	{ RMB,0,		"XADDB	%r,%e" },
   698	[0xC1] =	{ RM,0,		"XADD%S	%r,%e" },
   699	[0xC2] =	{ RM,Ib,		"CMP%s	%x,%X,%#i" },
   700	[0xC3] =	{ RM,0,		"MOVNTI%S	%r,%e" },
   701	[0xC6] =	{ RM,Ib,		"SHUF%s	%i,%x,%X" },
   702	[0xC8] =	{ 0,0,		"BSWAP	AX" },
   703	[0xC9] =	{ 0,0,		"BSWAP	CX" },
   704	[0xCA] =	{ 0,0,		"BSWAP	DX" },
   705	[0xCB] =	{ 0,0,		"BSWAP	BX" },
   706	[0xCC] =	{ 0,0,		"BSWAP	SP" },
   707	[0xCD] =	{ 0,0,		"BSWAP	BP" },
   708	[0xCE] =	{ 0,0,		"BSWAP	SI" },
   709	[0xCF] =	{ 0,0,		"BSWAP	DI" },
   710	[0xD1] =	{ RM,0,		"PSRLW %m,%M" },
   711	[0xD2] =	{ RM,0,		"PSRLL %m,%M" },
   712	[0xD3] =	{ RM,0,		"PSRLQ %m,%M" },
   713	[0xD5] =	{ RM,0,		"PMULLW %m,%M" },
   714	[0xD6] =	{ RM,0,		"MOVQOZX	%m*,%X" },
   715	[0xD7] =	{ RM,0,		"PMOVMSKB %m,%r" },
   716	[0xD8] =	{ RM,0,		"PSUBUSB %m,%M" },
   717	[0xD9] =	{ RM,0,		"PSUBUSW %m,%M" },
   718	[0xDA] =	{ RM,0,		"PMINUB %m,%M" },
   719	[0xDB] =	{ RM,0,		"PAND %m,%M" },
   720	[0xDC] =	{ RM,0,		"PADDUSB %m,%M" },
   721	[0xDD] =	{ RM,0,		"PADDUSW %m,%M" },
   722	[0xDE] =	{ RM,0,		"PMAXUB %m,%M" },
   723	[0xDF] =	{ RM,0,		"PANDN %m,%M" },
   724	[0xE0] =	{ RM,0,		"PAVGB %m,%M" },
   725	[0xE1] =	{ RM,0,		"PSRAW %m,%M" },
   726	[0xE2] =	{ RM,0,		"PSRAL %m,%M" },
   727	[0xE3] =	{ RM,0,		"PAVGW %m,%M" },
   728	[0xE4] =	{ RM,0,		"PMULHUW %m,%M" },
   729	[0xE5] =	{ RM,0,		"PMULHW %m,%M" },
   730	[0xE7] =	{ RM,0,		"MOVNTQ	%M,%e" },
   731	[0xE8] =	{ RM,0,		"PSUBSB %m,%M" },
   732	[0xE9] =	{ RM,0,		"PSUBSW %m,%M" },
   733	[0xEA] =	{ RM,0,		"PMINSW %m,%M" },
   734	[0xEB] =	{ RM,0,		"POR %m,%M" },
   735	[0xEC] =	{ RM,0,		"PADDSB %m,%M" },
   736	[0xED] =	{ RM,0,		"PADDSW %m,%M" },
   737	[0xEE] =	{ RM,0,		"PMAXSW %m,%M" },
   738	[0xEF] =	{ RM,0,		"PXOR %m,%M" },
   739	[0xF1] =	{ RM,0,		"PSLLW %m,%M" },
   740	[0xF2] =	{ RM,0,		"PSLLL %m,%M" },
   741	[0xF3] =	{ RM,0,		"PSLLQ %m,%M" },
   742	[0xF4] =	{ RM,0,		"PMULULQ	%m,%M" },
   743	[0xF5] =	{ RM,0,		"PMADDWL %m,%M" },
   744	[0xF6] =	{ RM,0,		"PSADBW %m,%M" },
   745	[0xF7] =	{ RMR,0,		"MASKMOVQ	%m,%M" },
   746	[0xF8] =	{ RM,0,		"PSUBB %m,%M" },
   747	[0xF9] =	{ RM,0,		"PSUBW %m,%M" },
   748	[0xFA] =	{ RM,0,		"PSUBL %m,%M" },
   749	[0xFC] =	{ RM,0,		"PADDB %m,%M" },
   750	[0xFD] =	{ RM,0,		"PADDW %m,%M" },
   751	[0xFE] =	{ RM,0,		"PADDL %m,%M" },
   752	
   753	[0x80] =	{ Iwds,0,		"JOS	%p" },
   754	[0x81] =	{ Iwds,0,		"JOC	%p" },
   755	[0x82] =	{ Iwds,0,		"JCS	%p" },
   756	[0x83] =	{ Iwds,0,		"JCC	%p" },
   757	[0x84] =	{ Iwds,0,		"JEQ	%p" },
   758	[0x85] =	{ Iwds,0,		"JNE	%p" },
   759	[0x86] =	{ Iwds,0,		"JLS	%p" },
   760	[0x87] =	{ Iwds,0,		"JHI	%p" },
   761	[0x88] =	{ Iwds,0,		"JMI	%p" },
   762	[0x89] =	{ Iwds,0,		"JPL	%p" },
   763	[0x8a] =	{ Iwds,0,		"JPS	%p" },
   764	[0x8b] =	{ Iwds,0,		"JPC	%p" },
   765	[0x8c] =	{ Iwds,0,		"JLT	%p" },
   766	[0x8d] =	{ Iwds,0,		"JGE	%p" },
   767	[0x8e] =	{ Iwds,0,		"JLE	%p" },
   768	[0x8f] =	{ Iwds,0,		"JGT	%p" },
   769	[0x90] =	{ RMB,0,		"SETOS	%e" },
   770	[0x91] =	{ RMB,0,		"SETOC	%e" },
   771	[0x92] =	{ RMB,0,		"SETCS	%e" },
   772	[0x93] =	{ RMB,0,		"SETCC	%e" },
   773	[0x94] =	{ RMB,0,		"SETEQ	%e" },
   774	[0x95] =	{ RMB,0,		"SETNE	%e" },
   775	[0x96] =	{ RMB,0,		"SETLS	%e" },
   776	[0x97] =	{ RMB,0,		"SETHI	%e" },
   777	[0x98] =	{ RMB,0,		"SETMI	%e" },
   778	[0x99] =	{ RMB,0,		"SETPL	%e" },
   779	[0x9a] =	{ RMB,0,		"SETPS	%e" },
   780	[0x9b] =	{ RMB,0,		"SETPC	%e" },
   781	[0x9c] =	{ RMB,0,		"SETLT	%e" },
   782	[0x9d] =	{ RMB,0,		"SETGE	%e" },
   783	[0x9e] =	{ RMB,0,		"SETLE	%e" },
   784	[0x9f] =	{ RMB,0,		"SETGT	%e" },
   785	[0xa0] =	{ 0,0,		"PUSHL	FS" },
   786	[0xa1] =	{ 0,0,		"POPL	FS" },
   787	[0xa2] =	{ 0,0,		"CPUID" },
   788	[0xa3] =	{ RM,0,		"BT%S	%r,%e" },
   789	[0xa4] =	{ RM,Ib,		"SHLD%S	%r,%i,%e" },
   790	[0xa5] =	{ RM,0,		"SHLD%S	%r,CL,%e" },
   791	[0xa8] =	{ 0,0,		"PUSHL	GS" },
   792	[0xa9] =	{ 0,0,		"POPL	GS" },
   793	[0xab] =	{ RM,0,		"BTS%S	%r,%e" },
   794	[0xac] =	{ RM,Ib,		"SHRD%S	%r,%i,%e" },
   795	[0xad] =	{ RM,0,		"SHRD%S	%r,CL,%e" },
   796	[0xaf] =	{ RM,0,		"IMUL%S	%e,%r" },
   797	[0xb2] =	{ RMM,0,		"LSS	%e,%r" },
   798	[0xb3] =	{ RM,0,		"BTR%S	%r,%e" },
   799	[0xb4] =	{ RMM,0,		"LFS	%e,%r" },
   800	[0xb5] =	{ RMM,0,		"LGS	%e,%r" },
   801	[0xb6] =	{ RMB,0,		"MOVBZX	%e,%R" },
   802	[0xb7] =	{ RM,0,		"MOVWZX	%e,%R" },
   803	[0xba] =	{ RMOP,0,		optab0FBA },
   804	[0xbb] =	{ RM,0,		"BTC%S	%e,%r" },
   805	[0xbc] =	{ RM,0,		"BSF%S	%e,%r" },
   806	[0xbd] =	{ RM,0,		"BSR%S	%e,%r" },
   807	[0xbe] =	{ RMB,0,		"MOVBSX	%e,%R" },
   808	[0xbf] =	{ RM,0,		"MOVWSX	%e,%R" },
   809	[0xc7] =	{ RMOP,0,		optab0FC7 },
   810	};
   811	
   812	static Optable optab80[8]=
   813	{
   814	[0x00] =	{ Ib,0,		"ADDB	%i,%e" },
   815	[0x01] =	{ Ib,0,		"ORB	%i,%e" },
   816	[0x02] =	{ Ib,0,		"ADCB	%i,%e" },
   817	[0x03] =	{ Ib,0,		"SBBB	%i,%e" },
   818	[0x04] =	{ Ib,0,		"ANDB	%i,%e" },
   819	[0x05] =	{ Ib,0,		"SUBB	%i,%e" },
   820	[0x06] =	{ Ib,0,		"XORB	%i,%e" },
   821	[0x07] =	{ Ib,0,		"CMPB	%e,%i" },
   822	};
   823	
   824	static Optable optab81[8]=
   825	{
   826	[0x00] =	{ Iwd,0,		"ADD%S	%i,%e" },
   827	[0x01] =	{ Iwd,0,		"OR%S	%i,%e" },
   828	[0x02] =	{ Iwd,0,		"ADC%S	%i,%e" },
   829	[0x03] =	{ Iwd,0,		"SBB%S	%i,%e" },
   830	[0x04] =	{ Iwd,0,		"AND%S	%i,%e" },
   831	[0x05] =	{ Iwd,0,		"SUB%S	%i,%e" },
   832	[0x06] =	{ Iwd,0,		"XOR%S	%i,%e" },
   833	[0x07] =	{ Iwd,0,		"CMP%S	%e,%i" },
   834	};
   835	
   836	static Optable optab83[8]=
   837	{
   838	[0x00] =	{ Ibs,0,		"ADD%S	%i,%e" },
   839	[0x01] =	{ Ibs,0,		"OR%S	%i,%e" },
   840	[0x02] =	{ Ibs,0,		"ADC%S	%i,%e" },
   841	[0x03] =	{ Ibs,0,		"SBB%S	%i,%e" },
   842	[0x04] =	{ Ibs,0,		"AND%S	%i,%e" },
   843	[0x05] =	{ Ibs,0,		"SUB%S	%i,%e" },
   844	[0x06] =	{ Ibs,0,		"XOR%S	%i,%e" },
   845	[0x07] =	{ Ibs,0,		"CMP%S	%e,%i" },
   846	};
   847	
   848	static Optable optabC0[8] =
   849	{
   850	[0x00] =	{ Ib,0,		"ROLB	%i,%e" },
   851	[0x01] =	{ Ib,0,		"RORB	%i,%e" },
   852	[0x02] =	{ Ib,0,		"RCLB	%i,%e" },
   853	[0x03] =	{ Ib,0,		"RCRB	%i,%e" },
   854	[0x04] =	{ Ib,0,		"SHLB	%i,%e" },
   855	[0x05] =	{ Ib,0,		"SHRB	%i,%e" },
   856	[0x07] =	{ Ib,0,		"SARB	%i,%e" },
   857	};
   858	
   859	static Optable optabC1[8] =
   860	{
   861	[0x00] =	{ Ib,0,		"ROL%S	%i,%e" },
   862	[0x01] =	{ Ib,0,		"ROR%S	%i,%e" },
   863	[0x02] =	{ Ib,0,		"RCL%S	%i,%e" },
   864	[0x03] =	{ Ib,0,		"RCR%S	%i,%e" },
   865	[0x04] =	{ Ib,0,		"SHL%S	%i,%e" },
   866	[0x05] =	{ Ib,0,		"SHR%S	%i,%e" },
   867	[0x07] =	{ Ib,0,		"SAR%S	%i,%e" },
   868	};
   869	
   870	static Optable optabD0[8] =
   871	{
   872	[0x00] =	{ 0,0,		"ROLB	%e" },
   873	[0x01] =	{ 0,0,		"RORB	%e" },
   874	[0x02] =	{ 0,0,		"RCLB	%e" },
   875	[0x03] =	{ 0,0,		"RCRB	%e" },
   876	[0x04] =	{ 0,0,		"SHLB	%e" },
   877	[0x05] =	{ 0,0,		"SHRB	%e" },
   878	[0x07] =	{ 0,0,		"SARB	%e" },
   879	};
   880	
   881	static Optable optabD1[8] =
   882	{
   883	[0x00] =	{ 0,0,		"ROL%S	%e" },
   884	[0x01] =	{ 0,0,		"ROR%S	%e" },
   885	[0x02] =	{ 0,0,		"RCL%S	%e" },
   886	[0x03] =	{ 0,0,		"RCR%S	%e" },
   887	[0x04] =	{ 0,0,		"SHL%S	%e" },
   888	[0x05] =	{ 0,0,		"SHR%S	%e" },
   889	[0x07] =	{ 0,0,		"SAR%S	%e" },
   890	};
   891	
   892	static Optable optabD2[8] =
   893	{
   894	[0x00] =	{ 0,0,		"ROLB	CL,%e" },
   895	[0x01] =	{ 0,0,		"RORB	CL,%e" },
   896	[0x02] =	{ 0,0,		"RCLB	CL,%e" },
   897	[0x03] =	{ 0,0,		"RCRB	CL,%e" },
   898	[0x04] =	{ 0,0,		"SHLB	CL,%e" },
   899	[0x05] =	{ 0,0,		"SHRB	CL,%e" },
   900	[0x07] =	{ 0,0,		"SARB	CL,%e" },
   901	};
   902	
   903	static Optable optabD3[8] =
   904	{
   905	[0x00] =	{ 0,0,		"ROL%S	CL,%e" },
   906	[0x01] =	{ 0,0,		"ROR%S	CL,%e" },
   907	[0x02] =	{ 0,0,		"RCL%S	CL,%e" },
   908	[0x03] =	{ 0,0,		"RCR%S	CL,%e" },
   909	[0x04] =	{ 0,0,		"SHL%S	CL,%e" },
   910	[0x05] =	{ 0,0,		"SHR%S	CL,%e" },
   911	[0x07] =	{ 0,0,		"SAR%S	CL,%e" },
   912	};
   913	
   914	static Optable optabD8[8+8] =
   915	{
   916	[0x00] =	{ 0,0,		"FADDF	%e,F0" },
   917	[0x01] =	{ 0,0,		"FMULF	%e,F0" },
   918	[0x02] =	{ 0,0,		"FCOMF	%e,F0" },
   919	[0x03] =	{ 0,0,		"FCOMFP	%e,F0" },
   920	[0x04] =	{ 0,0,		"FSUBF	%e,F0" },
   921	[0x05] =	{ 0,0,		"FSUBRF	%e,F0" },
   922	[0x06] =	{ 0,0,		"FDIVF	%e,F0" },
   923	[0x07] =	{ 0,0,		"FDIVRF	%e,F0" },
   924	[0x08] =	{ 0,0,		"FADDD	%f,F0" },
   925	[0x09] =	{ 0,0,		"FMULD	%f,F0" },
   926	[0x0a] =	{ 0,0,		"FCOMD	%f,F0" },
   927	[0x0b] =	{ 0,0,		"FCOMPD	%f,F0" },
   928	[0x0c] =	{ 0,0,		"FSUBD	%f,F0" },
   929	[0x0d] =	{ 0,0,		"FSUBRD	%f,F0" },
   930	[0x0e] =	{ 0,0,		"FDIVD	%f,F0" },
   931	[0x0f] =	{ 0,0,		"FDIVRD	%f,F0" },
   932	};
   933	/*
   934	 *	optabD9 and optabDB use the following encoding:
   935	 *	if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
   936	 *	else instruction = optabDx[(modrm&0x3f)+8];
   937	 *
   938	 *	the instructions for MOD == 3, follow the 8 instructions
   939	 *	for the other MOD values stored at the front of the table.
   940	 */
   941	static Optable optabD9[64+8] =
   942	{
   943	[0x00] =	{ 0,0,		"FMOVF	%e,F0" },
   944	[0x02] =	{ 0,0,		"FMOVF	F0,%e" },
   945	[0x03] =	{ 0,0,		"FMOVFP	F0,%e" },
   946	[0x04] =	{ 0,0,		"FLDENV%S %e" },
   947	[0x05] =	{ 0,0,		"FLDCW	%e" },
   948	[0x06] =	{ 0,0,		"FSTENV%S %e" },
   949	[0x07] =	{ 0,0,		"FSTCW	%e" },
   950	[0x08] =	{ 0,0,		"FMOVD	F0,F0" },		/* Mod R/M = 11xx xxxx*/
   951	[0x09] =	{ 0,0,		"FMOVD	F1,F0" },
   952	[0x0a] =	{ 0,0,		"FMOVD	F2,F0" },
   953	[0x0b] =	{ 0,0,		"FMOVD	F3,F0" },
   954	[0x0c] =	{ 0,0,		"FMOVD	F4,F0" },
   955	[0x0d] =	{ 0,0,		"FMOVD	F5,F0" },
   956	[0x0e] =	{ 0,0,		"FMOVD	F6,F0" },
   957	[0x0f] =	{ 0,0,		"FMOVD	F7,F0" },
   958	[0x10] =	{ 0,0,		"FXCHD	F0,F0" },
   959	[0x11] =	{ 0,0,		"FXCHD	F1,F0" },
   960	[0x12] =	{ 0,0,		"FXCHD	F2,F0" },
   961	[0x13] =	{ 0,0,		"FXCHD	F3,F0" },
   962	[0x14] =	{ 0,0,		"FXCHD	F4,F0" },
   963	[0x15] =	{ 0,0,		"FXCHD	F5,F0" },
   964	[0x16] =	{ 0,0,		"FXCHD	F6,F0" },
   965	[0x17] =	{ 0,0,		"FXCHD	F7,F0" },
   966	[0x18] =	{ 0,0,		"FNOP" },
   967	[0x28] =	{ 0,0,		"FCHS" },
   968	[0x29] =	{ 0,0,		"FABS" },
   969	[0x2c] =	{ 0,0,		"FTST" },
   970	[0x2d] =	{ 0,0,		"FXAM" },
   971	[0x30] =	{ 0,0,		"FLD1" },
   972	[0x31] =	{ 0,0,		"FLDL2T" },
   973	[0x32] =	{ 0,0,		"FLDL2E" },
   974	[0x33] =	{ 0,0,		"FLDPI" },
   975	[0x34] =	{ 0,0,		"FLDLG2" },
   976	[0x35] =	{ 0,0,		"FLDLN2" },
   977	[0x36] =	{ 0,0,		"FLDZ" },
   978	[0x38] =	{ 0,0,		"F2XM1" },
   979	[0x39] =	{ 0,0,		"FYL2X" },
   980	[0x3a] =	{ 0,0,		"FPTAN" },
   981	[0x3b] =	{ 0,0,		"FPATAN" },
   982	[0x3c] =	{ 0,0,		"FXTRACT" },
   983	[0x3d] =	{ 0,0,		"FPREM1" },
   984	[0x3e] =	{ 0,0,		"FDECSTP" },
   985	[0x3f] =	{ 0,0,		"FNCSTP" },
   986	[0x40] =	{ 0,0,		"FPREM" },
   987	[0x41] =	{ 0,0,		"FYL2XP1" },
   988	[0x42] =	{ 0,0,		"FSQRT" },
   989	[0x43] =	{ 0,0,		"FSINCOS" },
   990	[0x44] =	{ 0,0,		"FRNDINT" },
   991	[0x45] =	{ 0,0,		"FSCALE" },
   992	[0x46] =	{ 0,0,		"FSIN" },
   993	[0x47] =	{ 0,0,		"FCOS" },
   994	};
   995	
   996	static Optable optabDA[8+8] =
   997	{
   998	[0x00] =	{ 0,0,		"FADDL	%e,F0" },
   999	[0x01] =	{ 0,0,		"FMULL	%e,F0" },
  1000	[0x02] =	{ 0,0,		"FCOML	%e,F0" },
  1001	[0x03] =	{ 0,0,		"FCOMLP	%e,F0" },
  1002	[0x04] =	{ 0,0,		"FSUBL	%e,F0" },
  1003	[0x05] =	{ 0,0,		"FSUBRL	%e,F0" },
  1004	[0x06] =	{ 0,0,		"FDIVL	%e,F0" },
  1005	[0x07] =	{ 0,0,		"FDIVRL	%e,F0" },
  1006	[0x08] =	{ 0,0,		"FCMOVCS	%f,F0" },
  1007	[0x09] =	{ 0,0,		"FCMOVEQ	%f,F0" },
  1008	[0x0a] =	{ 0,0,		"FCMOVLS	%f,F0" },
  1009	[0x0b] =	{ 0,0,		"FCMOVUN	%f,F0" },
  1010	[0x0d] =	{ Op_R1,0,		"FUCOMPP" },
  1011	};
  1012	
  1013	static Optable optabDB[8+64] =
  1014	{
  1015	[0x00] =	{ 0,0,		"FMOVL	%e,F0" },
  1016	[0x02] =	{ 0,0,		"FMOVL	F0,%e" },
  1017	[0x03] =	{ 0,0,		"FMOVLP	F0,%e" },
  1018	[0x05] =	{ 0,0,		"FMOVX	%e,F0" },
  1019	[0x07] =	{ 0,0,		"FMOVXP	F0,%e" },
  1020	[0x08] =	{ 0,0,		"FCMOVCC	F0,F0" },	/* Mod R/M = 11xx xxxx*/
  1021	[0x09] =	{ 0,0,		"FCMOVCC	F1,F0" },
  1022	[0x0a] =	{ 0,0,		"FCMOVCC	F2,F0" },
  1023	[0x0b] =	{ 0,0,		"FCMOVCC	F3,F0" },
  1024	[0x0c] =	{ 0,0,		"FCMOVCC	F4,F0" },
  1025	[0x0d] =	{ 0,0,		"FCMOVCC	F5,F0" },
  1026	[0x0e] =	{ 0,0,		"FCMOVCC	F6,F0" },
  1027	[0x0f] =	{ 0,0,		"FCMOVCC	F7,F0" },
  1028	[0x10] =	{ 0,0,		"FCMOVNE	F0,F0" },
  1029	[0x11] =	{ 0,0,		"FCMOVNE	F1,F0" },
  1030	[0x12] =	{ 0,0,		"FCMOVNE	F2,F0" },
  1031	[0x13] =	{ 0,0,		"FCMOVNE	F3,F0" },
  1032	[0x14] =	{ 0,0,		"FCMOVNE	F4,F0" },
  1033	[0x15] =	{ 0,0,		"FCMOVNE	F5,F0" },
  1034	[0x16] =	{ 0,0,		"FCMOVNE	F6,F0" },
  1035	[0x17] =	{ 0,0,		"FCMOVNE	F7,F0" },
  1036	[0x18] =	{ 0,0,		"FCMOVHI	F0,F0" },
  1037	[0x19] =	{ 0,0,		"FCMOVHI	F1,F0" },
  1038	[0x1a] =	{ 0,0,		"FCMOVHI	F2,F0" },
  1039	[0x1b] =	{ 0,0,		"FCMOVHI	F3,F0" },
  1040	[0x1c] =	{ 0,0,		"FCMOVHI	F4,F0" },
  1041	[0x1d] =	{ 0,0,		"FCMOVHI	F5,F0" },
  1042	[0x1e] =	{ 0,0,		"FCMOVHI	F6,F0" },
  1043	[0x1f] =	{ 0,0,		"FCMOVHI	F7,F0" },
  1044	[0x20] =	{ 0,0,		"FCMOVNU	F0,F0" },
  1045	[0x21] =	{ 0,0,		"FCMOVNU	F1,F0" },
  1046	[0x22] =	{ 0,0,		"FCMOVNU	F2,F0" },
  1047	[0x23] =	{ 0,0,		"FCMOVNU	F3,F0" },
  1048	[0x24] =	{ 0,0,		"FCMOVNU	F4,F0" },
  1049	[0x25] =	{ 0,0,		"FCMOVNU	F5,F0" },
  1050	[0x26] =	{ 0,0,		"FCMOVNU	F6,F0" },
  1051	[0x27] =	{ 0,0,		"FCMOVNU	F7,F0" },
  1052	[0x2a] =	{ 0,0,		"FCLEX" },
  1053	[0x2b] =	{ 0,0,		"FINIT" },
  1054	[0x30] =	{ 0,0,		"FUCOMI	F0,F0" },
  1055	[0x31] =	{ 0,0,		"FUCOMI	F1,F0" },
  1056	[0x32] =	{ 0,0,		"FUCOMI	F2,F0" },
  1057	[0x33] =	{ 0,0,		"FUCOMI	F3,F0" },
  1058	[0x34] =	{ 0,0,		"FUCOMI	F4,F0" },
  1059	[0x35] =	{ 0,0,		"FUCOMI	F5,F0" },
  1060	[0x36] =	{ 0,0,		"FUCOMI	F6,F0" },
  1061	[0x37] =	{ 0,0,		"FUCOMI	F7,F0" },
  1062	[0x38] =	{ 0,0,		"FCOMI	F0,F0" },
  1063	[0x39] =	{ 0,0,		"FCOMI	F1,F0" },
  1064	[0x3a] =	{ 0,0,		"FCOMI	F2,F0" },
  1065	[0x3b] =	{ 0,0,		"FCOMI	F3,F0" },
  1066	[0x3c] =	{ 0,0,		"FCOMI	F4,F0" },
  1067	[0x3d] =	{ 0,0,		"FCOMI	F5,F0" },
  1068	[0x3e] =	{ 0,0,		"FCOMI	F6,F0" },
  1069	[0x3f] =	{ 0,0,		"FCOMI	F7,F0" },
  1070	};
  1071	
  1072	static Optable optabDC[8+8] =
  1073	{
  1074	[0x00] =	{ 0,0,		"FADDD	%e,F0" },
  1075	[0x01] =	{ 0,0,		"FMULD	%e,F0" },
  1076	[0x02] =	{ 0,0,		"FCOMD	%e,F0" },
  1077	[0x03] =	{ 0,0,		"FCOMDP	%e,F0" },
  1078	[0x04] =	{ 0,0,		"FSUBD	%e,F0" },
  1079	[0x05] =	{ 0,0,		"FSUBRD	%e,F0" },
  1080	[0x06] =	{ 0,0,		"FDIVD	%e,F0" },
  1081	[0x07] =	{ 0,0,		"FDIVRD	%e,F0" },
  1082	[0x08] =	{ 0,0,		"FADDD	F0,%f" },
  1083	[0x09] =	{ 0,0,		"FMULD	F0,%f" },
  1084	[0x0c] =	{ 0,0,		"FSUBRD	F0,%f" },
  1085	[0x0d] =	{ 0,0,		"FSUBD	F0,%f" },
  1086	[0x0e] =	{ 0,0,		"FDIVRD	F0,%f" },
  1087	[0x0f] =	{ 0,0,		"FDIVD	F0,%f" },
  1088	};
  1089	
  1090	static Optable optabDD[8+8] =
  1091	{
  1092	[0x00] =	{ 0,0,		"FMOVD	%e,F0" },
  1093	[0x02] =	{ 0,0,		"FMOVD	F0,%e" },
  1094	[0x03] =	{ 0,0,		"FMOVDP	F0,%e" },
  1095	[0x04] =	{ 0,0,		"FRSTOR%S %e" },
  1096	[0x06] =	{ 0,0,		"FSAVE%S %e" },
  1097	[0x07] =	{ 0,0,		"FSTSW	%e" },
  1098	[0x08] =	{ 0,0,		"FFREED	%f" },
  1099	[0x0a] =	{ 0,0,		"FMOVD	%f,F0" },
  1100	[0x0b] =	{ 0,0,		"FMOVDP	%f,F0" },
  1101	[0x0c] =	{ 0,0,		"FUCOMD	%f,F0" },
  1102	[0x0d] =	{ 0,0,		"FUCOMDP %f,F0" },
  1103	};
  1104	
  1105	static Optable optabDE[8+8] =
  1106	{
  1107	[0x00] =	{ 0,0,		"FADDW	%e,F0" },
  1108	[0x01] =	{ 0,0,		"FMULW	%e,F0" },
  1109	[0x02] =	{ 0,0,		"FCOMW	%e,F0" },
  1110	[0x03] =	{ 0,0,		"FCOMWP	%e,F0" },
  1111	[0x04] =	{ 0,0,		"FSUBW	%e,F0" },
  1112	[0x05] =	{ 0,0,		"FSUBRW	%e,F0" },
  1113	[0x06] =	{ 0,0,		"FDIVW	%e,F0" },
  1114	[0x07] =	{ 0,0,		"FDIVRW	%e,F0" },
  1115	[0x08] =	{ 0,0,		"FADDDP	F0,%f" },
  1116	[0x09] =	{ 0,0,		"FMULDP	F0,%f" },
  1117	[0x0b] =	{ Op_R1,0,		"FCOMPDP" },
  1118	[0x0c] =	{ 0,0,		"FSUBRDP F0,%f" },
  1119	[0x0d] =	{ 0,0,		"FSUBDP	F0,%f" },
  1120	[0x0e] =	{ 0,0,		"FDIVRDP F0,%f" },
  1121	[0x0f] =	{ 0,0,		"FDIVDP	F0,%f" },
  1122	};
  1123	
  1124	static Optable optabDF[8+8] =
  1125	{
  1126	[0x00] =	{ 0,0,		"FMOVW	%e,F0" },
  1127	[0x02] =	{ 0,0,		"FMOVW	F0,%e" },
  1128	[0x03] =	{ 0,0,		"FMOVWP	F0,%e" },
  1129	[0x04] =	{ 0,0,		"FBLD	%e" },
  1130	[0x05] =	{ 0,0,		"FMOVL	%e,F0" },
  1131	[0x06] =	{ 0,0,		"FBSTP	%e" },
  1132	[0x07] =	{ 0,0,		"FMOVLP	F0,%e" },
  1133	[0x0c] =	{ Op_R0,0,		"FSTSW	%OAX" },
  1134	[0x0d] =	{ 0,0,		"FUCOMIP	F0,%f" },
  1135	[0x0e] =	{ 0,0,		"FCOMIP	F0,%f" },
  1136	};
  1137	
  1138	static Optable optabF6[8] =
  1139	{
  1140	[0x00] =	{ Ib,0,		"TESTB	%i,%e" },
  1141	[0x02] =	{ 0,0,		"NOTB	%e" },
  1142	[0x03] =	{ 0,0,		"NEGB	%e" },
  1143	[0x04] =	{ 0,0,		"MULB	AL,%e" },
  1144	[0x05] =	{ 0,0,		"IMULB	AL,%e" },
  1145	[0x06] =	{ 0,0,		"DIVB	AL,%e" },
  1146	[0x07] =	{ 0,0,		"IDIVB	AL,%e" },
  1147	};
  1148	
  1149	static Optable optabF7[8] =
  1150	{
  1151	[0x00] =	{ Iwd,0,		"TEST%S	%i,%e" },
  1152	[0x02] =	{ 0,0,		"NOT%S	%e" },
  1153	[0x03] =	{ 0,0,		"NEG%S	%e" },
  1154	[0x04] =	{ 0,0,		"MUL%S	%OAX,%e" },
  1155	[0x05] =	{ 0,0,		"IMUL%S	%OAX,%e" },
  1156	[0x06] =	{ 0,0,		"DIV%S	%OAX,%e" },
  1157	[0x07] =	{ 0,0,		"IDIV%S	%OAX,%e" },
  1158	};
  1159	
  1160	static Optable optabFE[8] =
  1161	{
  1162	[0x00] =	{ 0,0,		"INCB	%e" },
  1163	[0x01] =	{ 0,0,		"DECB	%e" },
  1164	};
  1165	
  1166	static Optable optabFF[8] =
  1167	{
  1168	[0x00] =	{ 0,0,		"INC%S	%e" },
  1169	[0x01] =	{ 0,0,		"DEC%S	%e" },
  1170	[0x02] =	{ JUMP,0,		"CALL*	%e" },
  1171	[0x03] =	{ JUMP,0,		"CALLF*	%e" },
  1172	[0x04] =	{ JUMP,0,		"JMP*	%e" },
  1173	[0x05] =	{ JUMP,0,		"JMPF*	%e" },
  1174	[0x06] =	{ 0,0,		"PUSHL	%e" },
  1175	};
  1176	
  1177	static Optable optable[256+2] =
  1178	{
  1179	[0x00] =	{ RMB,0,		"ADDB	%r,%e" },
  1180	[0x01] =	{ RM,0,		"ADD%S	%r,%e" },
  1181	[0x02] =	{ RMB,0,		"ADDB	%e,%r" },
  1182	[0x03] =	{ RM,0,		"ADD%S	%e,%r" },
  1183	[0x04] =	{ Ib,0,		"ADDB	%i,AL" },
  1184	[0x05] =	{ Iwd,0,		"ADD%S	%i,%OAX" },
  1185	[0x06] =	{ 0,0,		"PUSHL	ES" },
  1186	[0x07] =	{ 0,0,		"POPL	ES" },
  1187	[0x08] =	{ RMB,0,		"ORB	%r,%e" },
  1188	[0x09] =	{ RM,0,		"OR%S	%r,%e" },
  1189	[0x0a] =	{ RMB,0,		"ORB	%e,%r" },
  1190	[0x0b] =	{ RM,0,		"OR%S	%e,%r" },
  1191	[0x0c] =	{ Ib,0,		"ORB	%i,AL" },
  1192	[0x0d] =	{ Iwd,0,		"OR%S	%i,%OAX" },
  1193	[0x0e] =	{ 0,0,		"PUSHL	CS" },
  1194	[0x0f] =	{ AUXMM,0,	optab0F },
  1195	[0x10] =	{ RMB,0,		"ADCB	%r,%e" },
  1196	[0x11] =	{ RM,0,		"ADC%S	%r,%e" },
  1197	[0x12] =	{ RMB,0,		"ADCB	%e,%r" },
  1198	[0x13] =	{ RM,0,		"ADC%S	%e,%r" },
  1199	[0x14] =	{ Ib,0,		"ADCB	%i,AL" },
  1200	[0x15] =	{ Iwd,0,		"ADC%S	%i,%OAX" },
  1201	[0x16] =	{ 0,0,		"PUSHL	SS" },
  1202	[0x17] =	{ 0,0,		"POPL	SS" },
  1203	[0x18] =	{ RMB,0,		"SBBB	%r,%e" },
  1204	[0x19] =	{ RM,0,		"SBB%S	%r,%e" },
  1205	[0x1a] =	{ RMB,0,		"SBBB	%e,%r" },
  1206	[0x1b] =	{ RM,0,		"SBB%S	%e,%r" },
  1207	[0x1c] =	{ Ib,0,		"SBBB	%i,AL" },
  1208	[0x1d] =	{ Iwd,0,		"SBB%S	%i,%OAX" },
  1209	[0x1e] =	{ 0,0,		"PUSHL	DS" },
  1210	[0x1f] =	{ 0,0,		"POPL	DS" },
  1211	[0x20] =	{ RMB,0,		"ANDB	%r,%e" },
  1212	[0x21] =	{ RM,0,		"AND%S	%r,%e" },
  1213	[0x22] =	{ RMB,0,		"ANDB	%e,%r" },
  1214	[0x23] =	{ RM,0,		"AND%S	%e,%r" },
  1215	[0x24] =	{ Ib,0,		"ANDB	%i,AL" },
  1216	[0x25] =	{ Iwd,0,		"AND%S	%i,%OAX" },
  1217	[0x26] =	{ SEG,0,		"ES:" },
  1218	[0x27] =	{ 0,0,		"DAA" },
  1219	[0x28] =	{ RMB,0,		"SUBB	%r,%e" },
  1220	[0x29] =	{ RM,0,		"SUB%S	%r,%e" },
  1221	[0x2a] =	{ RMB,0,		"SUBB	%e,%r" },
  1222	[0x2b] =	{ RM,0,		"SUB%S	%e,%r" },
  1223	[0x2c] =	{ Ib,0,		"SUBB	%i,AL" },
  1224	[0x2d] =	{ Iwd,0,		"SUB%S	%i,%OAX" },
  1225	[0x2e] =	{ SEG,0,		"CS:" },
  1226	[0x2f] =	{ 0,0,		"DAS" },
  1227	[0x30] =	{ RMB,0,		"XORB	%r,%e" },
  1228	[0x31] =	{ RM,0,		"XOR%S	%r,%e" },
  1229	[0x32] =	{ RMB,0,		"XORB	%e,%r" },
  1230	[0x33] =	{ RM,0,		"XOR%S	%e,%r" },
  1231	[0x34] =	{ Ib,0,		"XORB	%i,AL" },
  1232	[0x35] =	{ Iwd,0,		"XOR%S	%i,%OAX" },
  1233	[0x36] =	{ SEG,0,		"SS:" },
  1234	[0x37] =	{ 0,0,		"AAA" },
  1235	[0x38] =	{ RMB,0,		"CMPB	%r,%e" },
  1236	[0x39] =	{ RM,0,		"CMP%S	%r,%e" },
  1237	[0x3a] =	{ RMB,0,		"CMPB	%e,%r" },
  1238	[0x3b] =	{ RM,0,		"CMP%S	%e,%r" },
  1239	[0x3c] =	{ Ib,0,		"CMPB	%i,AL" },
  1240	[0x3d] =	{ Iwd,0,		"CMP%S	%i,%OAX" },
  1241	[0x3e] =	{ SEG,0,		"DS:" },
  1242	[0x3f] =	{ 0,0,		"AAS" },
  1243	[0x40] =	{ 0,0,		"INC%S	%OAX" },
  1244	[0x41] =	{ 0,0,		"INC%S	%OCX" },
  1245	[0x42] =	{ 0,0,		"INC%S	%ODX" },
  1246	[0x43] =	{ 0,0,		"INC%S	%OBX" },
  1247	[0x44] =	{ 0,0,		"INC%S	%OSP" },
  1248	[0x45] =	{ 0,0,		"INC%S	%OBP" },
  1249	[0x46] =	{ 0,0,		"INC%S	%OSI" },
  1250	[0x47] =	{ 0,0,		"INC%S	%ODI" },
  1251	[0x48] =	{ 0,0,		"DEC%S	%OAX" },
  1252	[0x49] =	{ 0,0,		"DEC%S	%OCX" },
  1253	[0x4a] =	{ 0,0,		"DEC%S	%ODX" },
  1254	[0x4b] =	{ 0,0,		"DEC%S	%OBX" },
  1255	[0x4c] =	{ 0,0,		"DEC%S	%OSP" },
  1256	[0x4d] =	{ 0,0,		"DEC%S	%OBP" },
  1257	[0x4e] =	{ 0,0,		"DEC%S	%OSI" },
  1258	[0x4f] =	{ 0,0,		"DEC%S	%ODI" },
  1259	[0x50] =	{ 0,0,		"PUSH%S	%OAX" },
  1260	[0x51] =	{ 0,0,		"PUSH%S	%OCX" },
  1261	[0x52] =	{ 0,0,		"PUSH%S	%ODX" },
  1262	[0x53] =	{ 0,0,		"PUSH%S	%OBX" },
  1263	[0x54] =	{ 0,0,		"PUSH%S	%OSP" },
  1264	[0x55] =	{ 0,0,		"PUSH%S	%OBP" },
  1265	[0x56] =	{ 0,0,		"PUSH%S	%OSI" },
  1266	[0x57] =	{ 0,0,		"PUSH%S	%ODI" },
  1267	[0x58] =	{ 0,0,		"POP%S	%OAX" },
  1268	[0x59] =	{ 0,0,		"POP%S	%OCX" },
  1269	[0x5a] =	{ 0,0,		"POP%S	%ODX" },
  1270	[0x5b] =	{ 0,0,		"POP%S	%OBX" },
  1271	[0x5c] =	{ 0,0,		"POP%S	%OSP" },
  1272	[0x5d] =	{ 0,0,		"POP%S	%OBP" },
  1273	[0x5e] =	{ 0,0,		"POP%S	%OSI" },
  1274	[0x5f] =	{ 0,0,		"POP%S	%ODI" },
  1275	[0x60] =	{ 0,0,		"PUSHA%S" },
  1276	[0x61] =	{ 0,0,		"POPA%S" },
  1277	[0x62] =	{ RMM,0,		"BOUND	%e,%r" },
  1278	[0x63] =	{ RM,0,		"ARPL	%r,%e" },
  1279	[0x64] =	{ SEG,0,		"FS:" },
  1280	[0x65] =	{ SEG,0,		"GS:" },
  1281	[0x66] =	{ OPOVER,0,	"" },
  1282	[0x67] =	{ ADDOVER,0,	"" },
  1283	[0x68] =	{ Iwd,0,		"PUSH%S	%i" },
  1284	[0x69] =	{ RM,Iwd,		"IMUL%S	%e,%i,%r" },
  1285	[0x6a] =	{ Ib,0,		"PUSH%S	%i" },
  1286	[0x6b] =	{ RM,Ibs,		"IMUL%S	%e,%i,%r" },
  1287	[0x6c] =	{ 0,0,		"INSB	DX,(%ODI)" },
  1288	[0x6d] =	{ 0,0,		"INS%S	DX,(%ODI)" },
  1289	[0x6e] =	{ 0,0,		"OUTSB	(%ASI),DX" },
  1290	[0x6f] =	{ 0,0,		"OUTS%S	(%ASI),DX" },
  1291	[0x70] =	{ Jbs,0,		"JOS	%p" },
  1292	[0x71] =	{ Jbs,0,		"JOC	%p" },
  1293	[0x72] =	{ Jbs,0,		"JCS	%p" },
  1294	[0x73] =	{ Jbs,0,		"JCC	%p" },
  1295	[0x74] =	{ Jbs,0,		"JEQ	%p" },
  1296	[0x75] =	{ Jbs,0,		"JNE	%p" },
  1297	[0x76] =	{ Jbs,0,		"JLS	%p" },
  1298	[0x77] =	{ Jbs,0,		"JHI	%p" },
  1299	[0x78] =	{ Jbs,0,		"JMI	%p" },
  1300	[0x79] =	{ Jbs,0,		"JPL	%p" },
  1301	[0x7a] =	{ Jbs,0,		"JPS	%p" },
  1302	[0x7b] =	{ Jbs,0,		"JPC	%p" },
  1303	[0x7c] =	{ Jbs,0,		"JLT	%p" },
  1304	[0x7d] =	{ Jbs,0,		"JGE	%p" },
  1305	[0x7e] =	{ Jbs,0,		"JLE	%p" },
  1306	[0x7f] =	{ Jbs,0,		"JGT	%p" },
  1307	[0x80] =	{ RMOPB,0,	optab80 },
  1308	[0x81] =	{ RMOP,0,		optab81 },
  1309	[0x83] =	{ RMOP,0,		optab83 },
  1310	[0x84] =	{ RMB,0,		"TESTB	%r,%e" },
  1311	[0x85] =	{ RM,0,		"TEST%S	%r,%e" },
  1312	[0x86] =	{ RMB,0,		"XCHGB	%r,%e" },
  1313	[0x87] =	{ RM,0,		"XCHG%S	%r,%e" },
  1314	[0x88] =	{ RMB,0,		"MOVB	%r,%e" },
  1315	[0x89] =	{ RM,0,		"MOV%S	%r,%e" },
  1316	[0x8a] =	{ RMB,0,		"MOVB	%e,%r" },
  1317	[0x8b] =	{ RM,0,		"MOV%S	%e,%r" },
  1318	[0x8c] =	{ RM,0,		"MOVW	%g,%e" },
  1319	[0x8d] =	{ RM,0,		"LEA%S	%e,%r" },
  1320	[0x8e] =	{ RM,0,		"MOVW	%e,%g" },
  1321	[0x8f] =	{ RM,0,		"POP%S	%e" },
  1322	[0x90] =	{ 0,0,		"NOP" },
  1323	[0x91] =	{ 0,0,		"XCHG	%OCX,%OAX" },
  1324	[0x92] =	{ 0,0,		"XCHG	%ODX,%OAX" },
  1325	[0x93] =	{ 0,0,		"XCHG	%OBX,%OAX" },
  1326	[0x94] =	{ 0,0,		"XCHG	%OSP,%OAX" },
  1327	[0x95] =	{ 0,0,		"XCHG	%OBP,%OAX" },
  1328	[0x96] =	{ 0,0,		"XCHG	%OSI,%OAX" },
  1329	[0x97] =	{ 0,0,		"XCHG	%ODI,%OAX" },
  1330	[0x98] =	{ 0,0,		"%W" },			/* miserable CBW or CWDE */
  1331	[0x99] =	{ 0,0,		"%w" },			/* idiotic CWD or CDQ */
  1332	[0x9a] =	{ PTR,0,		"CALL%S	%d" },
  1333	[0x9b] =	{ 0,0,		"WAIT" },
  1334	[0x9c] =	{ 0,0,		"PUSHF" },
  1335	[0x9d] =	{ 0,0,		"POPF" },
  1336	[0x9e] =	{ 0,0,		"SAHF" },
  1337	[0x9f] =	{ 0,0,		"LAHF" },
  1338	[0xa0] =	{ Awd,0,		"MOVB	%i,AL" },
  1339	[0xa1] =	{ Awd,0,		"MOV%S	%i,%OAX" },
  1340	[0xa2] =	{ Awd,0,		"MOVB	AL,%i" },
  1341	[0xa3] =	{ Awd,0,		"MOV%S	%OAX,%i" },
  1342	[0xa4] =	{ 0,0,		"MOVSB	(%ASI),(%ADI)" },
  1343	[0xa5] =	{ 0,0,		"MOVS%S	(%ASI),(%ADI)" },
  1344	[0xa6] =	{ 0,0,		"CMPSB	(%ASI),(%ADI)" },
  1345	[0xa7] =	{ 0,0,		"CMPS%S	(%ASI),(%ADI)" },
  1346	[0xa8] =	{ Ib,0,		"TESTB	%i,AL" },
  1347	[0xa9] =	{ Iwd,0,		"TEST%S	%i,%OAX" },
  1348	[0xaa] =	{ 0,0,		"STOSB	AL,(%ADI)" },
  1349	[0xab] =	{ 0,0,		"STOS%S	%OAX,(%ADI)" },
  1350	[0xac] =	{ 0,0,		"LODSB	(%ASI),AL" },
  1351	[0xad] =	{ 0,0,		"LODS%S	(%ASI),%OAX" },
  1352	[0xae] =	{ 0,0,		"SCASB	(%ADI),AL" },
  1353	[0xaf] =	{ 0,0,		"SCAS%S	(%ADI),%OAX" },
  1354	[0xb0] =	{ Ib,0,		"MOVB	%i,AL" },
  1355	[0xb1] =	{ Ib,0,		"MOVB	%i,CL" },
  1356	[0xb2] =	{ Ib,0,		"MOVB	%i,DL" },
  1357	[0xb3] =	{ Ib,0,		"MOVB	%i,BL" },
  1358	[0xb4] =	{ Ib,0,		"MOVB	%i,AH" },
  1359	[0xb5] =	{ Ib,0,		"MOVB	%i,CH" },
  1360	[0xb6] =	{ Ib,0,		"MOVB	%i,DH" },
  1361	[0xb7] =	{ Ib,0,		"MOVB	%i,BH" },
  1362	[0xb8] =	{ Iwdq,0,		"MOV%S	%i,%OAX" },
  1363	[0xb9] =	{ Iwdq,0,		"MOV%S	%i,%OCX" },
  1364	[0xba] =	{ Iwdq,0,		"MOV%S	%i,%ODX" },
  1365	[0xbb] =	{ Iwdq,0,		"MOV%S	%i,%OBX" },
  1366	[0xbc] =	{ Iwdq,0,		"MOV%S	%i,%OSP" },
  1367	[0xbd] =	{ Iwdq,0,		"MOV%S	%i,%OBP" },
  1368	[0xbe] =	{ Iwdq,0,		"MOV%S	%i,%OSI" },
  1369	[0xbf] =	{ Iwdq,0,		"MOV%S	%i,%ODI" },
  1370	[0xc0] =	{ RMOPB,0,	optabC0 },
  1371	[0xc1] =	{ RMOP,0,		optabC1 },
  1372	[0xc2] =	{ Iw,0,		"RET	%i" },
  1373	[0xc3] =	{ RET,0,		"RET" },
  1374	[0xc4] =	{ RM,0,		"LES	%e,%r" },
  1375	[0xc5] =	{ RM,0,		"LDS	%e,%r" },
  1376	[0xc6] =	{ RMB,Ib,		"MOVB	%i,%e" },
  1377	[0xc7] =	{ RM,Iwd,		"MOV%S	%i,%e" },
  1378	[0xc8] =	{ Iw2,Ib,		"ENTER	%i,%I" },		/* loony ENTER */
  1379	[0xc9] =	{ RET,0,		"LEAVE" },		/* bizarre LEAVE */
  1380	[0xca] =	{ Iw,0,		"RETF	%i" },
  1381	[0xcb] =	{ RET,0,		"RETF" },
  1382	[0xcc] =	{ 0,0,		"INT	3" },
  1383	[0xcd] =	{ Ib,0,		"INTB	%i" },
  1384	[0xce] =	{ 0,0,		"INTO" },
  1385	[0xcf] =	{ 0,0,		"IRET" },
  1386	[0xd0] =	{ RMOPB,0,	optabD0 },
  1387	[0xd1] =	{ RMOP,0,		optabD1 },
  1388	[0xd2] =	{ RMOPB,0,	optabD2 },
  1389	[0xd3] =	{ RMOP,0,		optabD3 },
  1390	[0xd4] =	{ OA,0,		"AAM" },
  1391	[0xd5] =	{ OA,0,		"AAD" },
  1392	[0xd7] =	{ 0,0,		"XLAT" },
  1393	[0xd8] =	{ FRMOP,0,	optabD8 },
  1394	[0xd9] =	{ FRMEX,0,	optabD9 },
  1395	[0xda] =	{ FRMOP,0,	optabDA },
  1396	[0xdb] =	{ FRMEX,0,	optabDB },
  1397	[0xdc] =	{ FRMOP,0,	optabDC },
  1398	[0xdd] =	{ FRMOP,0,	optabDD },
  1399	[0xde] =	{ FRMOP,0,	optabDE },
  1400	[0xdf] =	{ FRMOP,0,	optabDF },
  1401	[0xe0] =	{ Jbs,0,		"LOOPNE	%p" },
  1402	[0xe1] =	{ Jbs,0,		"LOOPE	%p" },
  1403	[0xe2] =	{ Jbs,0,		"LOOP	%p" },
  1404	[0xe3] =	{ Jbs,0,		"JCXZ	%p" },
  1405	[0xe4] =	{ Ib,0,		"INB	%i,AL" },
  1406	[0xe5] =	{ Ib,0,		"IN%S	%i,%OAX" },
  1407	[0xe6] =	{ Ib,0,		"OUTB	AL,%i" },
  1408	[0xe7] =	{ Ib,0,		"OUT%S	%OAX,%i" },
  1409	[0xe8] =	{ Iwds,0,		"CALL	%p" },
  1410	[0xe9] =	{ Iwds,0,		"JMP	%p" },
  1411	[0xea] =	{ PTR,0,		"JMP	%d" },
  1412	[0xeb] =	{ Jbs,0,		"JMP	%p" },
  1413	[0xec] =	{ 0,0,		"INB	DX,AL" },
  1414	[0xed] =	{ 0,0,		"IN%S	DX,%OAX" },
  1415	[0xee] =	{ 0,0,		"OUTB	AL,DX" },
  1416	[0xef] =	{ 0,0,		"OUT%S	%OAX,DX" },
  1417	[0xf0] =	{ PRE,0,		"LOCK" },
  1418	[0xf2] =	{ OPRE,0,		"REPNE" },
  1419	[0xf3] =	{ OPRE,0,		"REP" },
  1420	[0xf4] =	{ 0,0,		"HLT" },
  1421	[0xf5] =	{ 0,0,		"CMC" },
  1422	[0xf6] =	{ RMOPB,0,	optabF6 },
  1423	[0xf7] =	{ RMOP,0,		optabF7 },
  1424	[0xf8] =	{ 0,0,		"CLC" },
  1425	[0xf9] =	{ 0,0,		"STC" },
  1426	[0xfa] =	{ 0,0,		"CLI" },
  1427	[0xfb] =	{ 0,0,		"STI" },
  1428	[0xfc] =	{ 0,0,		"CLD" },
  1429	[0xfd] =	{ 0,0,		"STD" },
  1430	[0xfe] =	{ RMOPB,0,	optabFE },
  1431	[0xff] =	{ RMOP,0,		optabFF },
  1432	[0x100] =	{ RM,0,		"MOVLQSX	%e,%r" },
  1433	[0x101] =	{ RM,0,		"MOVLQZX	%e,%r" },
  1434	};
  1435	
  1436	/*
  1437	 *  get a byte of the instruction
  1438	 */
  1439	static int
  1440	igetc(Map *map, Instr *ip, uchar *c)
  1441	{
  1442		if(ip->n+1 > sizeof(ip->mem)){
  1443			werrstr("instruction too long");
  1444			return -1;
  1445		}
  1446		if (get1(map, ip->addr+ip->n, c, 1) < 0) {
  1447			werrstr("can't read instruction: %r");
  1448			return -1;
  1449		}
  1450		ip->mem[ip->n++] = *c;
  1451		return 1;
  1452	}
  1453	
  1454	/*
  1455	 *  get two bytes of the instruction
  1456	 */
  1457	static int
  1458	igets(Map *map, Instr *ip, ushort *sp)
  1459	{
  1460		uchar c;
  1461		ushort s;
  1462	
  1463		if (igetc(map, ip, &c) < 0)
  1464			return -1;
  1465		s = c;
  1466		if (igetc(map, ip, &c) < 0)
  1467			return -1;
  1468		s |= (c<<8);
  1469		*sp = s;
  1470		return 1;
  1471	}
  1472	
  1473	/*
  1474	 *  get 4 bytes of the instruction
  1475	 */
  1476	static int
  1477	igetl(Map *map, Instr *ip, uint32 *lp)
  1478	{
  1479		ushort s;
  1480		int32	l;
  1481	
  1482		if (igets(map, ip, &s) < 0)
  1483			return -1;
  1484		l = s;
  1485		if (igets(map, ip, &s) < 0)
  1486			return -1;
  1487		l |= (s<<16);
  1488		*lp = l;
  1489		return 1;
  1490	}
  1491	
  1492	/*
  1493	 *  get 8 bytes of the instruction
  1494	 *
  1495	static int
  1496	igetq(Map *map, Instr *ip, vlong *qp)
  1497	{
  1498		uint32	l;
  1499		uvlong q;
  1500	
  1501		if (igetl(map, ip, &l) < 0)
  1502			return -1;
  1503		q = l;
  1504		if (igetl(map, ip, &l) < 0)
  1505			return -1;
  1506		q |= ((uvlong)l<<32);
  1507		*qp = q;
  1508		return 1;
  1509	}
  1510	 */
  1511	
  1512	static int
  1513	getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
  1514	{
  1515		uchar c;
  1516		ushort s;
  1517	
  1518		if (mod > 2)
  1519			return 1;
  1520		if (mod == 1) {
  1521			if (igetc(map, ip, &c) < 0)
  1522				return -1;
  1523			if (c&0x80)
  1524				ip->disp = c|0xffffff00;
  1525			else
  1526				ip->disp = c&0xff;
  1527		} else if (mod == 2 || rm == code) {
  1528			if (ip->asize == 'E') {
  1529				if (igetl(map, ip, &ip->disp) < 0)
  1530					return -1;
  1531				if (mod == 0)
  1532					ip->rip = pcrel;
  1533			} else {
  1534				if (igets(map, ip, &s) < 0)
  1535					return -1;
  1536				if (s&0x8000)
  1537					ip->disp = s|0xffff0000;
  1538				else
  1539					ip->disp = s;
  1540			}
  1541			if (mod == 0)
  1542				ip->base = -1;
  1543		}
  1544		return 1;
  1545	}
  1546	
  1547	static int
  1548	modrm(Map *map, Instr *ip, uchar c)
  1549	{
  1550		uchar rm, mod;
  1551	
  1552		mod = (c>>6)&3;
  1553		rm = c&7;
  1554		ip->mod = mod;
  1555		ip->base = rm;
  1556		ip->reg = (c>>3)&7;
  1557		ip->rip = 0;
  1558		if (mod == 3)			/* register */
  1559			return 1;
  1560		if (ip->asize == 0) {		/* 16-bit mode */
  1561			switch(rm) {
  1562			case 0:
  1563				ip->base = BX; ip->index = SI;
  1564				break;
  1565			case 1:
  1566				ip->base = BX; ip->index = DI;
  1567				break;
  1568			case 2:
  1569				ip->base = BP; ip->index = SI;
  1570				break;
  1571			case 3:
  1572				ip->base = BP; ip->index = DI;
  1573				break;
  1574			case 4:
  1575				ip->base = SI;
  1576				break;
  1577			case 5:
  1578				ip->base = DI;
  1579				break;
  1580			case 6:
  1581				ip->base = BP;
  1582				break;
  1583			case 7:
  1584				ip->base = BX;
  1585				break;
  1586			default:
  1587				break;
  1588			}
  1589			return getdisp(map, ip, mod, rm, 6, 0);
  1590		}
  1591		if (rm == 4) {	/* scummy sib byte */
  1592			if (igetc(map, ip, &c) < 0)
  1593				return -1;
  1594			ip->ss = (c>>6)&0x03;
  1595			ip->index = (c>>3)&0x07;
  1596			if (ip->index == 4)
  1597				ip->index = -1;
  1598			ip->base = c&0x07;
  1599			return getdisp(map, ip, mod, ip->base, 5, 0);
  1600		}
  1601		return getdisp(map, ip, mod, rm, 5, ip->amd64);
  1602	}
  1603	
  1604	static Optable *
  1605	mkinstr(Map *map, Instr *ip, uvlong pc)
  1606	{
  1607		int i, n, norex;
  1608		uchar c;
  1609		ushort s;
  1610		Optable *op, *obase;
  1611		char buf[128];
  1612	
  1613		memset(ip, 0, sizeof(*ip));
  1614		norex = 1;
  1615		ip->base = -1;
  1616		ip->index = -1;
  1617		if(asstype == AI8086)
  1618			ip->osize = 'W';
  1619		else {
  1620			ip->osize = 'L';
  1621			ip->asize = 'E';
  1622			ip->amd64 = asstype != AI386;
  1623			norex = 0;
  1624		}
  1625		ip->addr = pc;
  1626		if (igetc(map, ip, &c) < 0)
  1627			return 0;
  1628		obase = optable;
  1629	newop:
  1630		if(ip->amd64 && !norex){
  1631			if(c >= 0x40 && c <= 0x4f) {
  1632				ip->rex = c;
  1633				if(igetc(map, ip, &c) < 0)
  1634					return 0;
  1635			}
  1636			if(c == 0x63){
  1637				if(ip->rex&REXW)
  1638					op = &obase[0x100];	/* MOVLQSX */
  1639				else
  1640					op = &obase[0x101];	/* MOVLQZX */
  1641				goto hack;
  1642			}
  1643		}
  1644		op = &obase[c];
  1645	hack:
  1646		if (op->proto == 0) {
  1647	badop:
  1648			n = snprint(buf, sizeof(buf), "opcode: ??");
  1649			for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
  1650				_hexify(buf+n, ip->mem[i], 1);
  1651			strcpy(buf+n, "??");
  1652			werrstr(buf);
  1653			return 0;
  1654		}
  1655		for(i = 0; i < 2 && op->operand[i]; i++) {
  1656			switch(op->operand[i]) {
  1657			case Ib:	/* 8-bit immediate - (no sign extension)*/
  1658				if (igetc(map, ip, &c) < 0)
  1659					return 0;
  1660				ip->imm = c&0xff;
  1661				ip->imm64 = ip->imm;
  1662				break;
  1663			case Jbs:	/* 8-bit jump immediate (sign extended) */
  1664				if (igetc(map, ip, &c) < 0)
  1665					return 0;
  1666				if (c&0x80)
  1667					ip->imm = c|0xffffff00;
  1668				else
  1669					ip->imm = c&0xff;
  1670				ip->imm64 = (int32)ip->imm;
  1671				ip->jumptype = Jbs;
  1672				break;
  1673			case Ibs:	/* 8-bit immediate (sign extended) */
  1674				if (igetc(map, ip, &c) < 0)
  1675					return 0;
  1676				if (c&0x80)
  1677					if (ip->osize == 'L')
  1678						ip->imm = c|0xffffff00;
  1679					else
  1680						ip->imm = c|0xff00;
  1681				else
  1682					ip->imm = c&0xff;
  1683				ip->imm64 = (int32)ip->imm;
  1684				break;
  1685			case Iw:	/* 16-bit immediate -> imm */
  1686				if (igets(map, ip, &s) < 0)
  1687					return 0;
  1688				ip->imm = s&0xffff;
  1689				ip->imm64 = ip->imm;
  1690				ip->jumptype = Iw;
  1691				break;
  1692			case Iw2:	/* 16-bit immediate -> in imm2*/
  1693				if (igets(map, ip, &s) < 0)
  1694					return 0;
  1695				ip->imm2 = s&0xffff;
  1696				break;
  1697			case Iwd:	/* Operand-sized immediate (no sign extension unless 64 bits)*/
  1698				if (ip->osize == 'L') {
  1699					if (igetl(map, ip, &ip->imm) < 0)
  1700						return 0;
  1701					ip->imm64 = ip->imm;
  1702					if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
  1703						ip->imm64 |= (vlong)~0 << 32;
  1704				} else {
  1705					if (igets(map, ip, &s)< 0)
  1706						return 0;
  1707					ip->imm = s&0xffff;
  1708					ip->imm64 = ip->imm;
  1709				}
  1710				break;
  1711			case Iwdq:	/* Operand-sized immediate, possibly big */
  1712				if (ip->osize == 'L') {
  1713					if (igetl(map, ip, &ip->imm) < 0)
  1714						return 0;
  1715					ip->imm64 = ip->imm;
  1716					if (ip->rex & REXW) {
  1717						uint32 l;
  1718						if (igetl(map, ip, &l) < 0)
  1719							return 0;
  1720						ip->imm64 |= (uvlong)l << 32;
  1721					}
  1722				} else {
  1723					if (igets(map, ip, &s)< 0)
  1724						return 0;
  1725					ip->imm = s&0xffff;
  1726				}
  1727				break;
  1728			case Awd:	/* Address-sized immediate (no sign extension)*/
  1729				if (ip->asize == 'E') {
  1730					if (igetl(map, ip, &ip->imm) < 0)
  1731						return 0;
  1732					/* TO DO: REX */
  1733				} else {
  1734					if (igets(map, ip, &s)< 0)
  1735						return 0;
  1736					ip->imm = s&0xffff;
  1737				}
  1738				break;
  1739			case Iwds:	/* Operand-sized immediate (sign extended) */
  1740				if (ip->osize == 'L') {
  1741					if (igetl(map, ip, &ip->imm) < 0)
  1742						return 0;
  1743				} else {
  1744					if (igets(map, ip, &s)< 0)
  1745						return 0;
  1746					if (s&0x8000)
  1747						ip->imm = s|0xffff0000;
  1748					else
  1749						ip->imm = s&0xffff;
  1750				}
  1751				ip->jumptype = Iwds;
  1752				break;
  1753			case OA:	/* literal 0x0a byte */
  1754				if (igetc(map, ip, &c) < 0)
  1755					return 0;
  1756				if (c != 0x0a)
  1757					goto badop;
  1758				break;
  1759			case Op_R0:	/* base register must be R0 */
  1760				if (ip->base != 0)
  1761					goto badop;
  1762				break;
  1763			case Op_R1:	/* base register must be R1 */
  1764				if (ip->base != 1)
  1765					goto badop;
  1766				break;
  1767			case RMB:	/* R/M field with byte register (/r)*/
  1768				if (igetc(map, ip, &c) < 0)
  1769					return 0;
  1770				if (modrm(map, ip, c) < 0)
  1771					return 0;
  1772				ip->osize = 'B';
  1773				break;
  1774			case RM:	/* R/M field with register (/r) */
  1775				if (igetc(map, ip, &c) < 0)
  1776					return 0;
  1777				if (modrm(map, ip, c) < 0)
  1778					return 0;
  1779				break;
  1780			case RMOPB:	/* R/M field with op code (/digit) */
  1781				if (igetc(map, ip, &c) < 0)
  1782					return 0;
  1783				if (modrm(map, ip, c) < 0)
  1784					return 0;
  1785				c = ip->reg;		/* secondary op code */
  1786				obase = (Optable*)op->proto;
  1787				ip->osize = 'B';
  1788				goto newop;
  1789			case RMOP:	/* R/M field with op code (/digit) */
  1790				if (igetc(map, ip, &c) < 0)
  1791					return 0;
  1792				if (modrm(map, ip, c) < 0)
  1793					return 0;
  1794				obase = (Optable*)op->proto;
  1795				if(ip->amd64 && obase == optab0F01 && c == 0xF8)
  1796					return optab0F01F8;
  1797				c = ip->reg;
  1798				goto newop;
  1799			case FRMOP:	/* FP R/M field with op code (/digit) */
  1800				if (igetc(map, ip, &c) < 0)
  1801					return 0;
  1802				if (modrm(map, ip, c) < 0)
  1803					return 0;
  1804				if ((c&0xc0) == 0xc0)
  1805					c = ip->reg+8;		/* 16 entry table */
  1806				else
  1807					c = ip->reg;
  1808				obase = (Optable*)op->proto;
  1809				goto newop;
  1810			case FRMEX:	/* Extended FP R/M field with op code (/digit) */
  1811				if (igetc(map, ip, &c) < 0)
  1812					return 0;
  1813				if (modrm(map, ip, c) < 0)
  1814					return 0;
  1815				if ((c&0xc0) == 0xc0)
  1816					c = (c&0x3f)+8;		/* 64-entry table */
  1817				else
  1818					c = ip->reg;
  1819				obase = (Optable*)op->proto;
  1820				goto newop;
  1821			case RMR:	/* R/M register only (mod = 11) */
  1822				if (igetc(map, ip, &c) < 0)
  1823					return 0;
  1824				if ((c&0xc0) != 0xc0) {
  1825					werrstr("invalid R/M register: %x", c);
  1826					return 0;
  1827				}
  1828				if (modrm(map, ip, c) < 0)
  1829					return 0;
  1830				break;
  1831			case RMM:	/* R/M register only (mod = 11) */
  1832				if (igetc(map, ip, &c) < 0)
  1833					return 0;
  1834				if ((c&0xc0) == 0xc0) {
  1835					werrstr("invalid R/M memory mode: %x", c);
  1836					return 0;
  1837				}
  1838				if (modrm(map, ip, c) < 0)
  1839					return 0;
  1840				break;
  1841			case PTR:	/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
  1842				if (ip->osize == 'L') {
  1843					if (igetl(map, ip, &ip->disp) < 0)
  1844						return 0;
  1845				} else {
  1846					if (igets(map, ip, &s)< 0)
  1847						return 0;
  1848					ip->disp = s&0xffff;
  1849				}
  1850				if (igets(map, ip, (ushort*)&ip->seg) < 0)
  1851					return 0;
  1852				ip->jumptype = PTR;
  1853				break;
  1854			case AUXMM:	/* Multi-byte op code; prefix determines table selection */
  1855				if (igetc(map, ip, &c) < 0)
  1856					return 0;
  1857				obase = (Optable*)op->proto;
  1858				switch (ip->opre) {
  1859				case 0x66:	op = optab660F; break;
  1860				case 0xF2:	op = optabF20F; break;
  1861				case 0xF3:	op = optabF30F; break;
  1862				default:	op = nil; break;
  1863				}
  1864				if(op != nil && op[c].proto != nil)
  1865					obase = op;
  1866				norex = 1;	/* no more rex prefixes */
  1867				/* otherwise the optab entry captures it */
  1868				goto newop;
  1869			case AUX:	/* Multi-byte op code - Auxiliary table */
  1870				obase = (Optable*)op->proto;
  1871				if (igetc(map, ip, &c) < 0)
  1872					return 0;
  1873				goto newop;
  1874			case OPRE:	/* Instr Prefix or media op */
  1875				ip->opre = c;
  1876				/* fall through */
  1877			case PRE:	/* Instr Prefix */
  1878				ip->prefix = (char*)op->proto;
  1879				if (igetc(map, ip, &c) < 0)
  1880					return 0;
  1881				if (ip->opre && c == 0x0F)
  1882					ip->prefix = 0;
  1883				goto newop;
  1884			case SEG:	/* Segment Prefix */
  1885				ip->segment = (char*)op->proto;
  1886				if (igetc(map, ip, &c) < 0)
  1887					return 0;
  1888				goto newop;
  1889			case OPOVER:	/* Operand size override */
  1890				ip->opre = c;
  1891				ip->osize = 'W';
  1892				if (igetc(map, ip, &c) < 0)
  1893					return 0;
  1894				if (c == 0x0F)
  1895					ip->osize = 'L';
  1896				else if (ip->amd64 && (c&0xF0) == 0x40)
  1897					ip->osize = 'Q';
  1898				goto newop;
  1899			case ADDOVER:	/* Address size override */
  1900				ip->asize = 0;
  1901				if (igetc(map, ip, &c) < 0)
  1902					return 0;
  1903				goto newop;
  1904			case JUMP:	/* mark instruction as JUMP or RET */
  1905			case RET:
  1906				ip->jumptype = op->operand[i];
  1907				break;
  1908			default:
  1909				werrstr("bad operand type %d", op->operand[i]);
  1910				return 0;
  1911			}
  1912		}
  1913		return op;
  1914	}
  1915	
  1916	#pragma	varargck	argpos	bprint		2
  1917	
  1918	static void
  1919	bprint(Instr *ip, char *fmt, ...)
  1920	{
  1921		va_list arg;
  1922	
  1923		va_start(arg, fmt);
  1924		ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
  1925		va_end(arg);
  1926	}
  1927	
  1928	/*
  1929	 *  if we want to call 16 bit regs AX,BX,CX,...
  1930	 *  and 32 bit regs EAX,EBX,ECX,... then
  1931	 *  change the defs of ANAME and ONAME to:
  1932	 *  #define	ANAME(ip)	((ip->asize == 'E' ? "E" : "")
  1933	 *  #define	ONAME(ip)	((ip)->osize == 'L' ? "E" : "")
  1934	 */
  1935	#define	ANAME(ip)	""
  1936	#define	ONAME(ip)	""
  1937	
  1938	static char *reg[] =  {
  1939	[AX] =	"AX",
  1940	[CX] =	"CX",
  1941	[DX] =	"DX",
  1942	[BX] =	"BX",
  1943	[SP] =	"SP",
  1944	[BP] =	"BP",
  1945	[SI] =	"SI",
  1946	[DI] =	"DI",
  1947	
  1948		/* amd64 */
  1949	[AMD64_R8] =	"R8",
  1950	[AMD64_R9] =	"R9",
  1951	[AMD64_R10] =	"R10",
  1952	[AMD64_R11] =	"R11",
  1953	[AMD64_R12] =	"R12",
  1954	[AMD64_R13] =	"R13",
  1955	[AMD64_R14] =	"R14",
  1956	[AMD64_R15] =	"R15",
  1957	};
  1958	
  1959	static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
  1960	static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
  1961		"R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
  1962	static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
  1963	
  1964	static void
  1965	plocal(Instr *ip)
  1966	{
  1967		int ret;
  1968		int32 offset;
  1969		Symbol s;
  1970		char *reg;
  1971	
  1972		offset = ip->disp;
  1973		if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) {
  1974			bprint(ip, "%lux(SP)", offset);
  1975			return;
  1976		}
  1977	
  1978		if (s.value > ip->disp) {
  1979			ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s);
  1980			reg = "(SP)";
  1981		} else {
  1982			offset -= s.value;
  1983			ret = getauto(&s, offset, CPARAM, &s);
  1984			reg = "(FP)";
  1985		}
  1986		if (ret)
  1987			bprint(ip, "%s+", s.name);
  1988		else
  1989			offset = ip->disp;
  1990		bprint(ip, "%lux%s", offset, reg);
  1991	}
  1992	
  1993	static int
  1994	isjmp(Instr *ip)
  1995	{
  1996		switch(ip->jumptype){
  1997		case Iwds:
  1998		case Jbs:
  1999		case JUMP:
  2000			return 1;
  2001		default:
  2002			return 0;
  2003		}
  2004	}
  2005	
  2006	/*
  2007	 * This is too smart for its own good, but it really is nice
  2008	 * to have accurate translations when debugging, and it
  2009	 * helps us identify which code is different in binaries that
  2010	 * are changed on sources.
  2011	 */
  2012	static int
  2013	issymref(Instr *ip, Symbol *s, int32 w, int32 val)
  2014	{
  2015		Symbol next, tmp;
  2016		int32 isstring, size;
  2017	
  2018		if (isjmp(ip))
  2019			return 1;
  2020		if (s->class==CTEXT && w==0)
  2021			return 1;
  2022		if (s->class==CDATA) {
  2023			/* use first bss symbol (or "end") rather than edata */
  2024			if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){
  2025				if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value)
  2026				|| (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value))
  2027					*s = tmp;
  2028			}
  2029			if (w == 0)
  2030				return 1;
  2031			for (next=*s; next.value==s->value; next=tmp)
  2032				if (!globalsym(&tmp, next.index+1))
  2033					break;
  2034			size = next.value - s->value;
  2035			if (w >= size)
  2036				return 0;
  2037			if (w > size-w)
  2038				w = size-w;
  2039			/* huge distances are usually wrong except in .string */
  2040			isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0);
  2041			if (w > 8192 && !isstring)
  2042				return 0;
  2043			/* medium distances are tricky - look for constants */
  2044			/* near powers of two */
  2045			if ((val&(val-1)) == 0 || (val&(val+1)) == 0)
  2046				return 0;
  2047			return 1;
  2048		}
  2049		return 0;
  2050	}
  2051	
  2052	static void
  2053	immediate(Instr *ip, vlong val)
  2054	{
  2055		Symbol s;
  2056		int32 w;
  2057	
  2058		if (findsym(val, CANY, &s)) {		/* TO DO */
  2059			w = val - s.value;
  2060			if (w < 0)
  2061				w = -w;
  2062			if (issymref(ip, &s, w, val)) {
  2063				if (w)
  2064					bprint(ip, "%s+%#lux(SB)", s.name, w);
  2065				else
  2066					bprint(ip, "%s(SB)", s.name);
  2067				return;
  2068			}
  2069	/*
  2070			if (s.class==CDATA && globalsym(&s, s.index+1)) {
  2071				w = s.value - val;
  2072				if (w < 0)
  2073					w = -w;
  2074				if (w < 4096) {
  2075					bprint(ip, "%s-%#lux(SB)", s.name, w);
  2076					return;
  2077				}
  2078			}
  2079	*/
  2080		}
  2081		if((ip->rex & REXW) == 0)
  2082			bprint(ip, "%lux", (long)val);
  2083		else
  2084			bprint(ip, "%llux", val);
  2085	}
  2086	
  2087	static void
  2088	pea(Instr *ip)
  2089	{
  2090		if (ip->mod == 3) {
  2091			if (ip->osize == 'B')
  2092				bprint(ip, (ip->rex & REXB? breg64: breg)[(uchar)ip->base]);
  2093			else if(ip->rex & REXB)
  2094				bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]);
  2095			else
  2096				bprint(ip, "%s%s", ANAME(ip), reg[(uchar)ip->base]);
  2097			return;
  2098		}
  2099		if (ip->segment)
  2100			bprint(ip, ip->segment);
  2101		if (ip->asize == 'E' && ip->base == SP)
  2102			plocal(ip);
  2103		else {
  2104			if (ip->base < 0)
  2105				immediate(ip, ip->disp);
  2106			else {
  2107				bprint(ip, "%lux", ip->disp);
  2108				if(ip->rip)
  2109					bprint(ip, "(RIP)");
  2110				bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
  2111			}
  2112		}
  2113		if (ip->index >= 0)
  2114			bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
  2115	}
  2116	
  2117	static void
  2118	prinstr(Instr *ip, char *fmt)
  2119	{
  2120		int sharp;
  2121		vlong v;
  2122	
  2123		if (ip->prefix)
  2124			bprint(ip, "%s ", ip->prefix);
  2125		for (; *fmt && ip->curr < ip->end; fmt++) {
  2126			if (*fmt != '%'){
  2127				*ip->curr++ = *fmt;
  2128				continue;
  2129			}
  2130			sharp = 0;
  2131			if(*++fmt == '#') {
  2132				sharp = 1;
  2133				++fmt;
  2134			}
  2135			switch(*fmt){
  2136			case '%':
  2137				*ip->curr++ = '%';
  2138				break;
  2139			case 'A':
  2140				bprint(ip, "%s", ANAME(ip));
  2141				break;
  2142			case 'C':
  2143				bprint(ip, "CR%d", ip->reg);
  2144				break;
  2145			case 'D':
  2146				if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
  2147					bprint(ip, "DR%d",ip->reg);
  2148				else
  2149					bprint(ip, "???");
  2150				break;
  2151			case 'I':
  2152				bprint(ip, "$");
  2153				immediate(ip, ip->imm2);
  2154				break;
  2155			case 'O':
  2156				bprint(ip,"%s", ONAME(ip));
  2157				break;
  2158			case 'i':
  2159				if(!sharp)
  2160					bprint(ip, "$");
  2161				v = ip->imm;
  2162				if(ip->rex & REXW)
  2163					v = ip->imm64;
  2164				immediate(ip, v);
  2165				break;
  2166			case 'R':
  2167				bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
  2168				break;
  2169			case 'S':
  2170				if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
  2171					bprint(ip, "Q");
  2172				else
  2173					bprint(ip, "%c", ip->osize);
  2174				break;
  2175			case 's':
  2176				if(ip->opre == 0 || ip->opre == 0x66)
  2177					bprint(ip, "P");
  2178				else
  2179					bprint(ip, "S");
  2180				if(ip->opre == 0xf2 || ip->opre == 0x66)
  2181					bprint(ip, "D");
  2182				else
  2183					bprint(ip, "S");
  2184				break;
  2185			case 'T':
  2186				if (ip->reg == 6 || ip->reg == 7)
  2187					bprint(ip, "TR%d",ip->reg);
  2188				else
  2189					bprint(ip, "???");
  2190				break;
  2191			case 'W':
  2192				if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW)
  2193					bprint(ip, "CDQE");
  2194				else if (ip->osize == 'L')
  2195					bprint(ip,"CWDE");
  2196				else
  2197					bprint(ip, "CBW");
  2198				break;
  2199			case 'd':
  2200				bprint(ip,"%ux:%lux",ip->seg,ip->disp);
  2201				break;
  2202			case 'm':
  2203				if (ip->mod == 3 && ip->osize != 'B') {
  2204					if(fmt[1] != '*'){
  2205						if(ip->opre != 0) {
  2206							bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
  2207							break;
  2208						}
  2209					} else
  2210						fmt++;
  2211					bprint(ip, "M%d", ip->base);
  2212					break;
  2213				}
  2214				pea(ip);
  2215				break;
  2216			case 'e':
  2217				pea(ip);
  2218				break;
  2219			case 'f':
  2220				bprint(ip, "F%d", ip->base);
  2221				break;
  2222			case 'g':
  2223				if (ip->reg < 6)
  2224					bprint(ip,"%s",sreg[ip->reg]);
  2225				else
  2226					bprint(ip,"???");
  2227				break;
  2228			case 'p':
  2229				/*
  2230				 * signed immediate in the uint32 ip->imm.
  2231				 */
  2232				v = (int32)ip->imm;
  2233				immediate(ip, v+ip->addr+ip->n);
  2234				break;
  2235			case 'r':
  2236				if (ip->osize == 'B')
  2237					bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
  2238				else
  2239					bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
  2240				break;
  2241			case 'w':
  2242				if (ip->osize == 'Q' || ip->rex & REXW)
  2243					bprint(ip, "CQO");
  2244				else if (ip->osize == 'L')
  2245					bprint(ip,"CDQ");
  2246				else
  2247					bprint(ip, "CWD");
  2248				break;
  2249			case 'M':
  2250				if(ip->opre != 0)
  2251					bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
  2252				else
  2253					bprint(ip, "M%d", ip->reg);
  2254				break;
  2255			case 'x':
  2256				if (ip->mod == 3 && ip->osize != 'B') {
  2257					bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
  2258					break;
  2259				}
  2260				pea(ip);
  2261				break;
  2262			case 'X':
  2263				bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
  2264				break;
  2265			default:
  2266				bprint(ip, "%%%c", *fmt);
  2267				break;
  2268			}
  2269		}
  2270		*ip->curr = 0;		/* there's always room for 1 byte */
  2271	}
  2272	
  2273	static int
  2274	i386inst(Map *map, uvlong pc, char modifier, char *buf, int n)
  2275	{
  2276		Instr instr;
  2277		Optable *op;
  2278	
  2279		USED(modifier);
  2280		op = mkinstr(map, &instr, pc);
  2281		if (op == 0) {
  2282			errstr(buf, n);
  2283			return -1;
  2284		}
  2285		instr.curr = buf;
  2286		instr.end = buf+n-1;
  2287		prinstr(&instr, op->proto);
  2288		return instr.n;
  2289	}
  2290	
  2291	static int
  2292	i386das(Map *map, uvlong pc, char *buf, int n)
  2293	{
  2294		Instr instr;
  2295		int i;
  2296	
  2297		if (mkinstr(map, &instr, pc) == 0) {
  2298			errstr(buf, n);
  2299			return -1;
  2300		}
  2301		for(i = 0; i < instr.n && n > 2; i++) {
  2302			_hexify(buf, instr.mem[i], 1);
  2303			buf += 2;
  2304			n -= 2;
  2305		}
  2306		*buf = 0;
  2307		return instr.n;
  2308	}
  2309	
  2310	static int
  2311	i386instlen(Map *map, uvlong pc)
  2312	{
  2313		Instr i;
  2314	
  2315		if (mkinstr(map, &i, pc))
  2316			return i.n;
  2317		return -1;
  2318	}
  2319	
  2320	static int
  2321	i386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
  2322	{
  2323		Instr i;
  2324		Optable *op;
  2325		ushort s;
  2326		uvlong l, addr;
  2327		vlong v;
  2328		int n;
  2329	
  2330		op = mkinstr(map, &i, pc);
  2331		if (!op)
  2332			return -1;
  2333	
  2334		n = 0;
  2335	
  2336		switch(i.jumptype) {
  2337		case RET:		/* RETURN or LEAVE */
  2338		case Iw:		/* RETURN */
  2339			if (strcmp(op->proto, "LEAVE") == 0) {
  2340				if (geta(map, (*rget)(map, "BP"), &l) < 0)
  2341					return -1;
  2342			} else if (geta(map, (*rget)(map, mach->sp), &l) < 0)
  2343				return -1;
  2344			foll[0] = l;
  2345			return 1;
  2346		case Iwds:		/* pc relative JUMP or CALL*/
  2347		case Jbs:		/* pc relative JUMP or CALL */
  2348			v = (int32)i.imm;
  2349			foll[0] = pc+v+i.n;
  2350			n = 1;
  2351			break;
  2352		case PTR:		/* seg:displacement JUMP or CALL */
  2353			foll[0] = (i.seg<<4)+i.disp;
  2354			return 1;
  2355		case JUMP:		/* JUMP or CALL EA */
  2356	
  2357			if(i.mod == 3) {
  2358				foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]);
  2359				return 1;
  2360			}
  2361				/* calculate the effective address */
  2362			addr = i.disp;
  2363			if (i.base >= 0) {
  2364				if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0)
  2365					return -1;
  2366				addr += l;
  2367			}
  2368			if (i.index >= 0) {
  2369				if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0)
  2370					return -1;
  2371				addr += l*(1<<i.ss);
  2372			}
  2373				/* now retrieve a seg:disp value at that address */
  2374			if (get2(map, addr, &s) < 0)			/* seg */
  2375				return -1;
  2376			foll[0] = s<<4;
  2377			addr += 2;
  2378			if (i.asize == 'L') {
  2379				if (geta(map, addr, &l) < 0)		/* disp32 */
  2380					return -1;
  2381				foll[0] += l;
  2382			} else {					/* disp16 */
  2383				if (get2(map, addr, &s) < 0)
  2384					return -1;
  2385				foll[0] += s;
  2386			}
  2387			return 1;
  2388		default:
  2389			break;
  2390		}
  2391		if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0)
  2392			return 1;
  2393		foll[n++] = pc+i.n;
  2394		return n;
  2395	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.