...

Text file src/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c

Documentation: golang.org/x/arch/x86/x86asm/testdata

     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
    37typedef struct Map Map;
    38struct Map
    39{
    40	int (*get1)(Map*, uvlong, uchar*, int);
    41	uchar *p;
    42	uchar *ep;
    43	uchar *startp;
    44	uvlong startpc;
    45};
    46
    47static int
    48get1(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
    58static	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 */
    67typedef struct Instr Instr;
    68struct	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 */
    99enum{
   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 */
   122enum{
   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
   150typedef struct Optable Optable;
   151struct Optable
   152{
   153	char	operand[2];
   154	void	*proto;		/* actually either (char*) or (Optable*) */
   155};
   156	/* Operand decoding codes */
   157enum {
   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
   190static 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
   200static 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
   211static Optable optab0F01F8[1]=
   212{
   213[0x00] =	{ 0,0,		"SWAPGS" },
   214};
   215
   216/* 0F71 */
   217/* 0F72 */
   218/* 0F73 */
   219
   220static 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
   234static 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
   242static 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
   269static Optable optab0FC7[8]=
   270{
   271[0x01] =	{ 0,0,		"CMPXCHG8B	%e" },
   272};
   273
   274static 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
   281static 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
   288static 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
   296static 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
   325static 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
   340static 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
   357static 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
   567static 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
   579static 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
   591static 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
   603static 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
   614static 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
   625static 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
   636static 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
   647static 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
   658static 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
   669static 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 */
   696static 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
   751static 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
   768static 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
   827static 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
   845static 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
   860static 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
   879static 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
   893static 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
   904static 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
   915static Optable optabFE[8] =
   916{
   917[0x00] =	{ 0,0,		"INCB	%e" },
   918[0x01] =	{ 0,0,		"DECB	%e" },
   919};
   920
   921static 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
   932static 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 */
  1194static int
  1195igetc(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 */
  1212static int
  1213igets(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 */
  1231static int
  1232igetl(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 *
  1250static int
  1251igetq(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
  1267static int
  1268getdisp(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
  1302static int
  1303modrm(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
  1359static 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
  1374static Optable *
  1375mkinstr(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;
  1395newop:
  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];
  1413hack:
  1414	if (op->proto == 0) {
  1415badop:
  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
  1684static void
  1685bprint(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
  1704static 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
  1725static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
  1726static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
  1727	"R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
  1728static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
  1729
  1730static void
  1731immediate(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
  1740static void
  1741pea(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
  1773static void
  1774prinstr(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
  1935static int
  1936i386inst(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/*
  1952static int
  1953i386das(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
  1971static int
  1972i386instlen(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
  1982static int
  1983getmem(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
  1996int
  1997x86disasm(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
  2009void
  2010usage(void)
  2011{
  2012	fprint(2, "usage: libmach8db file\n");
  2013	exits("usage");
  2014}
  2015
  2016void
  2017main(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}

View as plain text