golang.org/x/arch@v0.17.0/x86/x86asm/testdata/libmach8db.c (about)

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