github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/libmach/8db.c (about)

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