xref: /illumos-gate/usr/src/common/dis/i386/dis_tables.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include	"dis_tables.h"
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate  * Disassembly begins in dis_distable, which is equivalent to the One-byte
39*7c478bd9Sstevel@tonic-gate  * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy).  The
40*7c478bd9Sstevel@tonic-gate  * decoding loops then traverse out through the other tables as necessary to
41*7c478bd9Sstevel@tonic-gate  * decode a given instruction.
42*7c478bd9Sstevel@tonic-gate  *
43*7c478bd9Sstevel@tonic-gate  * The behavior of this file can be controlled by one of the following flags:
44*7c478bd9Sstevel@tonic-gate  *
45*7c478bd9Sstevel@tonic-gate  * 	DIS_TEXT	Include text for disassembly
46*7c478bd9Sstevel@tonic-gate  * 	DIS_MEM		Include memory-size calculations
47*7c478bd9Sstevel@tonic-gate  *
48*7c478bd9Sstevel@tonic-gate  * Either or both of these can be defined.
49*7c478bd9Sstevel@tonic-gate  *
50*7c478bd9Sstevel@tonic-gate  * This file is not, and will never be, cstyled.  If anything, the tables should
51*7c478bd9Sstevel@tonic-gate  * be taken out another tab stop or two so nothing overlaps.
52*7c478bd9Sstevel@tonic-gate  */
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * These functions must be provided for the consumer to do disassembly.
56*7c478bd9Sstevel@tonic-gate  */
57*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
58*7c478bd9Sstevel@tonic-gate extern char *strncpy(char *, const char *, size_t);
59*7c478bd9Sstevel@tonic-gate extern size_t strlen(const char *);
60*7c478bd9Sstevel@tonic-gate extern int strcmp(const char *, const char *);
61*7c478bd9Sstevel@tonic-gate extern int strncmp(const char *, const char *, size_t);
62*7c478bd9Sstevel@tonic-gate extern size_t strlcat(char *, const char *, size_t);
63*7c478bd9Sstevel@tonic-gate #endif
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #define		TERM 	0	/* used to indicate that the 'indirect' */
67*7c478bd9Sstevel@tonic-gate 				/* field terminates - no pointer.	*/
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /* Used to decode instructions. */
70*7c478bd9Sstevel@tonic-gate typedef struct	instable {
71*7c478bd9Sstevel@tonic-gate 	struct instable	*it_indirect;	/* for decode op codes */
72*7c478bd9Sstevel@tonic-gate 	uchar_t		it_adrmode;
73*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
74*7c478bd9Sstevel@tonic-gate 	char		it_name[NCPS];
75*7c478bd9Sstevel@tonic-gate 	uint_t		it_suffix:1;		/* mneu + "w", "l", or "d" */
76*7c478bd9Sstevel@tonic-gate #endif
77*7c478bd9Sstevel@tonic-gate #ifdef DIS_MEM
78*7c478bd9Sstevel@tonic-gate 	uint_t		it_size:16;
79*7c478bd9Sstevel@tonic-gate #endif
80*7c478bd9Sstevel@tonic-gate 	uint_t		it_invalid64:1;		/* opcode invalid in amd64 */
81*7c478bd9Sstevel@tonic-gate 	uint_t		it_always64:1;		/* 64 bit when in 64 bit mode */
82*7c478bd9Sstevel@tonic-gate 	uint_t		it_invalid32:1;		/* invalid in IA32 */
83*7c478bd9Sstevel@tonic-gate 	uint_t		it_stackop:1;		/* push/pop stack operation */
84*7c478bd9Sstevel@tonic-gate } instable_t;
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate  * Instruction formats.
88*7c478bd9Sstevel@tonic-gate  */
89*7c478bd9Sstevel@tonic-gate enum {
90*7c478bd9Sstevel@tonic-gate 	UNKNOWN,
91*7c478bd9Sstevel@tonic-gate 	MRw,
92*7c478bd9Sstevel@tonic-gate 	IMlw,
93*7c478bd9Sstevel@tonic-gate 	IMw,
94*7c478bd9Sstevel@tonic-gate 	IR,
95*7c478bd9Sstevel@tonic-gate 	OA,
96*7c478bd9Sstevel@tonic-gate 	AO,
97*7c478bd9Sstevel@tonic-gate 	MS,
98*7c478bd9Sstevel@tonic-gate 	SM,
99*7c478bd9Sstevel@tonic-gate 	Mv,
100*7c478bd9Sstevel@tonic-gate 	Mw,
101*7c478bd9Sstevel@tonic-gate 	M,		/* register or memory */
102*7c478bd9Sstevel@tonic-gate 	Mb,		/* register or memory, always byte sized */
103*7c478bd9Sstevel@tonic-gate 	MO,		/* memory only (no registers) */
104*7c478bd9Sstevel@tonic-gate 	PREF,
105*7c478bd9Sstevel@tonic-gate 	SWAPGS,
106*7c478bd9Sstevel@tonic-gate 	R,
107*7c478bd9Sstevel@tonic-gate 	RA,
108*7c478bd9Sstevel@tonic-gate 	SEG,
109*7c478bd9Sstevel@tonic-gate 	MR,
110*7c478bd9Sstevel@tonic-gate 	RM,
111*7c478bd9Sstevel@tonic-gate 	IA,
112*7c478bd9Sstevel@tonic-gate 	MA,
113*7c478bd9Sstevel@tonic-gate 	SD,
114*7c478bd9Sstevel@tonic-gate 	AD,
115*7c478bd9Sstevel@tonic-gate 	SA,
116*7c478bd9Sstevel@tonic-gate 	D,
117*7c478bd9Sstevel@tonic-gate 	INM,
118*7c478bd9Sstevel@tonic-gate 	SO,
119*7c478bd9Sstevel@tonic-gate 	BD,
120*7c478bd9Sstevel@tonic-gate 	I,
121*7c478bd9Sstevel@tonic-gate 	P,
122*7c478bd9Sstevel@tonic-gate 	V,
123*7c478bd9Sstevel@tonic-gate 	DSHIFT,		/* for double shift that has an 8-bit immediate */
124*7c478bd9Sstevel@tonic-gate 	U,
125*7c478bd9Sstevel@tonic-gate 	OVERRIDE,
126*7c478bd9Sstevel@tonic-gate 	NORM,		/* instructions w/o ModR/M byte, no memory access */
127*7c478bd9Sstevel@tonic-gate 	IMPLMEM,	/* instructions w/o ModR/M byte, implicit mem access */
128*7c478bd9Sstevel@tonic-gate 	O,		/* for call	*/
129*7c478bd9Sstevel@tonic-gate 	JTAB,		/* jump table 	*/
130*7c478bd9Sstevel@tonic-gate 	IMUL,		/* for 186 iimul instr  */
131*7c478bd9Sstevel@tonic-gate 	CBW,		/* so data16 can be evaluated for cbw and variants */
132*7c478bd9Sstevel@tonic-gate 	MvI,		/* for 186 logicals */
133*7c478bd9Sstevel@tonic-gate 	ENTER,		/* for 186 enter instr  */
134*7c478bd9Sstevel@tonic-gate 	RMw,		/* for 286 arpl instr */
135*7c478bd9Sstevel@tonic-gate 	Ib,		/* for push immediate byte */
136*7c478bd9Sstevel@tonic-gate 	F,		/* for 287 instructions */
137*7c478bd9Sstevel@tonic-gate 	FF,		/* for 287 instructions */
138*7c478bd9Sstevel@tonic-gate 	FFC,		/* for 287 instructions */
139*7c478bd9Sstevel@tonic-gate 	DM,		/* 16-bit data */
140*7c478bd9Sstevel@tonic-gate 	AM,		/* 16-bit addr */
141*7c478bd9Sstevel@tonic-gate 	LSEG,		/* for 3-bit seg reg encoding */
142*7c478bd9Sstevel@tonic-gate 	MIb,		/* for 386 logicals */
143*7c478bd9Sstevel@tonic-gate 	SREG,		/* for 386 special registers */
144*7c478bd9Sstevel@tonic-gate 	PREFIX,		/* a REP instruction prefix */
145*7c478bd9Sstevel@tonic-gate 	LOCK,		/* a LOCK instruction prefix */
146*7c478bd9Sstevel@tonic-gate 	INT3,		/* The int 3 instruction, which has a fake operand */
147*7c478bd9Sstevel@tonic-gate 	INTx,		/* The normal int instruction, with explicit int num */
148*7c478bd9Sstevel@tonic-gate 	DSHIFTcl,	/* for double shift that implicitly uses %cl */
149*7c478bd9Sstevel@tonic-gate 	CWD,		/* so data16 can be evaluated for cwd and variants */
150*7c478bd9Sstevel@tonic-gate 	RET,		/* single immediate 16-bit operand */
151*7c478bd9Sstevel@tonic-gate 	MOVZ,		/* for movs and movz, with different size operands */
152*7c478bd9Sstevel@tonic-gate 	XADDB,		/* for xaddb */
153*7c478bd9Sstevel@tonic-gate 	MOVSXZ,		/* AMD64 mov sign extend 32 to 64 bit instruction */
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate /*
156*7c478bd9Sstevel@tonic-gate  * MMX/SIMD addressing modes.
157*7c478bd9Sstevel@tonic-gate  */
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	MMO,		/* Prefixable MMX/SIMD-Int	mm/mem	-> mm */
160*7c478bd9Sstevel@tonic-gate 	MMOIMPL,	/* Prefixable MMX/SIMD-Int	mm	-> mm (mem) */
161*7c478bd9Sstevel@tonic-gate 	MMO3P,		/* Prefixable MMX/SIMD-Int	mm	-> r32,imm8 */
162*7c478bd9Sstevel@tonic-gate 	MMOM3,		/* Prefixable MMX/SIMD-Int	mm	-> r32 	*/
163*7c478bd9Sstevel@tonic-gate 	MMOS,		/* Prefixable MMX/SIMD-Int	mm	-> mm/mem */
164*7c478bd9Sstevel@tonic-gate 	MMOMS,		/* Prefixable MMX/SIMD-Int	mm	-> mem */
165*7c478bd9Sstevel@tonic-gate 	MMOPM,		/* MMX/SIMD-Int			mm/mem	-> mm,imm8 */
166*7c478bd9Sstevel@tonic-gate 	MMOPRM,		/* Prefixable MMX/SIMD-Int	r32/mem	-> mm,imm8 */
167*7c478bd9Sstevel@tonic-gate 	MMOSH,		/* Prefixable MMX		mm,imm8	*/
168*7c478bd9Sstevel@tonic-gate 	MM,		/* MMX/SIMD-Int			mm/mem	-> mm	*/
169*7c478bd9Sstevel@tonic-gate 	MMS,		/* MMX/SIMD-Int			mm	-> mm/mem */
170*7c478bd9Sstevel@tonic-gate 	MMSH,		/* MMX				mm,imm8 */
171*7c478bd9Sstevel@tonic-gate 	XMMO,		/* Prefixable SIMD		xmm/mem	-> xmm */
172*7c478bd9Sstevel@tonic-gate 	XMMOS,		/* Prefixable SIMD		xmm	-> xmm/mem */
173*7c478bd9Sstevel@tonic-gate 	XMMOPM,		/* Prefixable SIMD		xmm/mem	w/to xmm,imm8 */
174*7c478bd9Sstevel@tonic-gate 	XMMOMX,		/* Prefixable SIMD		mm/mem	-> xmm */
175*7c478bd9Sstevel@tonic-gate 	XMMOX3,		/* Prefixable SIMD		xmm	-> r32 */
176*7c478bd9Sstevel@tonic-gate 	XMMOXMM,	/* Prefixable SIMD		xmm/mem	-> mm	*/
177*7c478bd9Sstevel@tonic-gate 	XMMOM,		/* Prefixable SIMD		xmm	-> mem */
178*7c478bd9Sstevel@tonic-gate 	XMMOMS,		/* Prefixable SIMD		mem	-> xmm */
179*7c478bd9Sstevel@tonic-gate 	XMM,		/* SIMD 			xmm/mem	-> xmm */
180*7c478bd9Sstevel@tonic-gate 	XMMXIMPL,	/* SIMD				xmm	-> xmm (mem) */
181*7c478bd9Sstevel@tonic-gate 	XMM3P,		/* SIMD				xmm	-> r32,imm8 */
182*7c478bd9Sstevel@tonic-gate 	XMMP,		/* SIMD 			xmm/mem w/to xmm,imm8 */
183*7c478bd9Sstevel@tonic-gate 	XMMPRM,		/* SIMD 			r32/mem -> xmm,imm8 */
184*7c478bd9Sstevel@tonic-gate 	XMMS,		/* SIMD				xmm	-> xmm/mem */
185*7c478bd9Sstevel@tonic-gate 	XMMM,		/* SIMD 			mem	-> xmm */
186*7c478bd9Sstevel@tonic-gate 	XMMMS,		/* SIMD				xmm	-> mem */
187*7c478bd9Sstevel@tonic-gate 	XMM3MX,		/* SIMD 			r32/mem -> xmm */
188*7c478bd9Sstevel@tonic-gate 	XMM3MXS,	/* SIMD 			xmm	-> r32/mem */
189*7c478bd9Sstevel@tonic-gate 	XMMSH,		/* SIMD 			xmm,imm8 */
190*7c478bd9Sstevel@tonic-gate 	XMMXM3,		/* SIMD 			xmm/mem -> r32 */
191*7c478bd9Sstevel@tonic-gate 	XMMX3,		/* SIMD 			xmm	-> r32 */
192*7c478bd9Sstevel@tonic-gate 	XMMXMM,		/* SIMD 			xmm/mem	-> mm */
193*7c478bd9Sstevel@tonic-gate 	XMMMX,		/* SIMD 			mm	-> xmm */
194*7c478bd9Sstevel@tonic-gate 	XMMXM,		/* SIMD 			xmm	-> mm */
195*7c478bd9Sstevel@tonic-gate 	XMMFENCE,	/* SIMD lfence or mfence */
196*7c478bd9Sstevel@tonic-gate 	XMMSFNC		/* SIMD sfence (none or mem) */
197*7c478bd9Sstevel@tonic-gate };
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate #define	FILL	0x90	/* Fill byte used for alignment (nop)	*/
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate /*
202*7c478bd9Sstevel@tonic-gate ** Register numbers for the i386
203*7c478bd9Sstevel@tonic-gate */
204*7c478bd9Sstevel@tonic-gate #define	EAX_REGNO 0
205*7c478bd9Sstevel@tonic-gate #define	ECX_REGNO 1
206*7c478bd9Sstevel@tonic-gate #define	EDX_REGNO 2
207*7c478bd9Sstevel@tonic-gate #define	EBX_REGNO 3
208*7c478bd9Sstevel@tonic-gate #define	ESP_REGNO 4
209*7c478bd9Sstevel@tonic-gate #define	EBP_REGNO 5
210*7c478bd9Sstevel@tonic-gate #define	ESI_REGNO 6
211*7c478bd9Sstevel@tonic-gate #define	EDI_REGNO 7
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate /*
214*7c478bd9Sstevel@tonic-gate  * modes for immediate values
215*7c478bd9Sstevel@tonic-gate  */
216*7c478bd9Sstevel@tonic-gate #define	MODE_NONE	0
217*7c478bd9Sstevel@tonic-gate #define	MODE_IPREL	1	/* signed IP relative value */
218*7c478bd9Sstevel@tonic-gate #define	MODE_SIGNED	2	/* sign extended immediate */
219*7c478bd9Sstevel@tonic-gate #define	MODE_IMPLIED	3	/* constant value implied from opcode */
220*7c478bd9Sstevel@tonic-gate #define	MODE_OFFSET	4	/* offset part of an address */
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate /*
223*7c478bd9Sstevel@tonic-gate  * The letters used in these macros are:
224*7c478bd9Sstevel@tonic-gate  *   IND - indirect to another to another table
225*7c478bd9Sstevel@tonic-gate  *   "T" - means to Terminate indirections (this is the final opcode)
226*7c478bd9Sstevel@tonic-gate  *   "S" - means "operand length suffix required"
227*7c478bd9Sstevel@tonic-gate  *   "NS" - means "no suffix" which is the operand length suffix of the opcode
228*7c478bd9Sstevel@tonic-gate  *   "Z" - means instruction size arg required
229*7c478bd9Sstevel@tonic-gate  *   "u" - means the opcode is invalid in IA32 but valid in amd64
230*7c478bd9Sstevel@tonic-gate  *   "x" - means the opcode is invalid in amd64, but not IA32
231*7c478bd9Sstevel@tonic-gate  *   "y" - means the operand size is always 64 bits in 64 bit mode
232*7c478bd9Sstevel@tonic-gate  *   "p" - means push/pop stack operation
233*7c478bd9Sstevel@tonic-gate  */
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate #if defined(DIS_TEXT) && defined(DIS_MEM)
236*7c478bd9Sstevel@tonic-gate #define	IND(table)		{(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0}
237*7c478bd9Sstevel@tonic-gate #define	INDx(table)		{(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0}
238*7c478bd9Sstevel@tonic-gate #define	TNS(name, amode)	{TERM, amode, name, 0, 0, 0, 0, 0, 0}
239*7c478bd9Sstevel@tonic-gate #define	TNSu(name, amode)	{TERM, amode, name, 0, 0, 0, 0, 1, 0}
240*7c478bd9Sstevel@tonic-gate #define	TNSx(name, amode)	{TERM, amode, name, 0, 0, 1, 0, 0, 0}
241*7c478bd9Sstevel@tonic-gate #define	TNSy(name, amode)	{TERM, amode, name, 0, 0, 0, 1, 0, 0}
242*7c478bd9Sstevel@tonic-gate #define	TNSyp(name, amode)	{TERM, amode, name, 0, 0, 0, 1, 0, 1}
243*7c478bd9Sstevel@tonic-gate #define	TNSZ(name, amode, sz)	{TERM, amode, name, 0, sz, 0, 0, 0, 0}
244*7c478bd9Sstevel@tonic-gate #define	TNSZy(name, amode, sz)	{TERM, amode, name, 0, sz, 0, 1, 0, 0}
245*7c478bd9Sstevel@tonic-gate #define	TS(name, amode)		{TERM, amode, name, 1, 0, 0, 0, 0, 0}
246*7c478bd9Sstevel@tonic-gate #define	TSx(name, amode)	{TERM, amode, name, 1, 0, 1, 0, 0, 0}
247*7c478bd9Sstevel@tonic-gate #define	TSy(name, amode)	{TERM, amode, name, 1, 0, 0, 1, 0, 0}
248*7c478bd9Sstevel@tonic-gate #define	TSp(name, amode)	{TERM, amode, name, 1, 0, 0, 0, 0, 1}
249*7c478bd9Sstevel@tonic-gate #define	TSZ(name, amode, sz)	{TERM, amode, name, 1, sz, 0, 0, 0, 0}
250*7c478bd9Sstevel@tonic-gate #define	TSZx(name, amode, sz)	{TERM, amode, name, 1, sz, 1, 0, 0, 0}
251*7c478bd9Sstevel@tonic-gate #define	TSZy(name, amode, sz)	{TERM, amode, name, 1, sz, 0, 1, 0, 0}
252*7c478bd9Sstevel@tonic-gate #define	INVALID			{TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
253*7c478bd9Sstevel@tonic-gate #elif defined(DIS_TEXT)
254*7c478bd9Sstevel@tonic-gate #define	IND(table)		{(instable_t *)table, 0, "", 0, 0, 0, 0, 0}
255*7c478bd9Sstevel@tonic-gate #define	INDx(table)		{(instable_t *)table, 0, "", 0, 1, 0, 0, 0}
256*7c478bd9Sstevel@tonic-gate #define	TNS(name, amode)	{TERM, amode, name, 0, 0, 0, 0, 0}
257*7c478bd9Sstevel@tonic-gate #define	TNSu(name, amode)	{TERM, amode, name, 0, 0, 0, 1, 0}
258*7c478bd9Sstevel@tonic-gate #define	TNSx(name, amode)	{TERM, amode, name, 0, 1, 0, 0, 0}
259*7c478bd9Sstevel@tonic-gate #define	TNSy(name, amode)	{TERM, amode, name, 0, 0, 1, 0, 0}
260*7c478bd9Sstevel@tonic-gate #define	TNSyp(name, amode)	{TERM, amode, name, 0, 0, 1, 0, 1}
261*7c478bd9Sstevel@tonic-gate #define	TNSZ(name, amode, sz)	{TERM, amode, name, 0, 0, 0, 0, 0}
262*7c478bd9Sstevel@tonic-gate #define	TNSZy(name, amode, sz)	{TERM, amode, name, 0, 0, 1, 0, 0}
263*7c478bd9Sstevel@tonic-gate #define	TS(name, amode)		{TERM, amode, name, 1, 0, 0, 0, 0}
264*7c478bd9Sstevel@tonic-gate #define	TSx(name, amode)	{TERM, amode, name, 1, 1, 0, 0, 0}
265*7c478bd9Sstevel@tonic-gate #define	TSy(name, amode)	{TERM, amode, name, 1, 0, 1, 0, 0}
266*7c478bd9Sstevel@tonic-gate #define	TSp(name, amode)	{TERM, amode, name, 1, 0, 0, 0, 1}
267*7c478bd9Sstevel@tonic-gate #define	TSZ(name, amode, sz)	{TERM, amode, name, 1, 0, 0, 0, 0}
268*7c478bd9Sstevel@tonic-gate #define	TSZx(name, amode, sz)	{TERM, amode, name, 1, 1, 0, 0, 0}
269*7c478bd9Sstevel@tonic-gate #define	TSZy(name, amode, sz)	{TERM, amode, name, 1, 0, 1, 0, 0}
270*7c478bd9Sstevel@tonic-gate #define	INVALID			{TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
271*7c478bd9Sstevel@tonic-gate #elif defined(DIS_MEM)
272*7c478bd9Sstevel@tonic-gate #define	IND(table)		{(instable_t *)table, 0, 0, 0, 0, 0, 0}
273*7c478bd9Sstevel@tonic-gate #define	INDx(table)		{(instable_t *)table, 0, 0, 1, 0, 0, 0}
274*7c478bd9Sstevel@tonic-gate #define	TNS(name, amode)	{TERM, amode,  0, 0, 0, 0, 0}
275*7c478bd9Sstevel@tonic-gate #define	TNSu(name, amode)	{TERM, amode,  0, 0, 0, 1, 0}
276*7c478bd9Sstevel@tonic-gate #define	TNSy(name, amode)	{TERM, amode,  0, 0, 1, 0, 0}
277*7c478bd9Sstevel@tonic-gate #define	TNSyp(name, amode)	{TERM, amode,  0, 0, 1, 0, 1}
278*7c478bd9Sstevel@tonic-gate #define	TNSx(name, amode)	{TERM, amode,  0, 1, 0, 0, 0}
279*7c478bd9Sstevel@tonic-gate #define	TNSZ(name, amode, sz)	{TERM, amode, sz, 0, 0, 0, 0}
280*7c478bd9Sstevel@tonic-gate #define	TNSZy(name, amode, sz)	{TERM, amode, sz, 0, 1, 0, 0}
281*7c478bd9Sstevel@tonic-gate #define	TS(name, amode)		{TERM, amode,  0, 0, 0, 0, 0}
282*7c478bd9Sstevel@tonic-gate #define	TSx(name, amode)	{TERM, amode,  0, 1, 0, 0, 0}
283*7c478bd9Sstevel@tonic-gate #define	TSy(name, amode)	{TERM, amode,  0, 0, 1, 0, 0}
284*7c478bd9Sstevel@tonic-gate #define	TSp(name, amode)	{TERM, amode,  0, 0, 0, 0, 1}
285*7c478bd9Sstevel@tonic-gate #define	TSZ(name, amode, sz)	{TERM, amode, sz, 0, 0, 0, 0}
286*7c478bd9Sstevel@tonic-gate #define	TSZx(name, amode, sz)	{TERM, amode, sz, 1, 0, 0, 0}
287*7c478bd9Sstevel@tonic-gate #define	TSZy(name, amode, sz)	{TERM, amode, sz, 0, 1, 0, 0}
288*7c478bd9Sstevel@tonic-gate #define	INVALID			{TERM, UNKNOWN, 0, 0, 0, 0, 0}
289*7c478bd9Sstevel@tonic-gate #else
290*7c478bd9Sstevel@tonic-gate #define	IND(table)		{(instable_t *)table, 0, 0, 0, 0, 0}
291*7c478bd9Sstevel@tonic-gate #define	INDx(table)		{(instable_t *)table, 0, 1, 0, 0, 0}
292*7c478bd9Sstevel@tonic-gate #define	TNS(name, amode)	{TERM, amode,  0, 0, 0, 0}
293*7c478bd9Sstevel@tonic-gate #define	TNSu(name, amode)	{TERM, amode,  0, 0, 1, 0}
294*7c478bd9Sstevel@tonic-gate #define	TNSy(name, amode)	{TERM, amode,  0, 1, 0, 0}
295*7c478bd9Sstevel@tonic-gate #define	TNSyp(name, amode)	{TERM, amode,  0, 1, 0, 1}
296*7c478bd9Sstevel@tonic-gate #define	TNSx(name, amode)	{TERM, amode,  1, 0, 0, 0}
297*7c478bd9Sstevel@tonic-gate #define	TNSZ(name, amode, sz)	{TERM, amode,  0, 0, 0, 0}
298*7c478bd9Sstevel@tonic-gate #define	TNSZy(name, amode, sz)	{TERM, amode,  0, 1, 0, 0}
299*7c478bd9Sstevel@tonic-gate #define	TS(name, amode)		{TERM, amode,  0, 0, 0, 0}
300*7c478bd9Sstevel@tonic-gate #define	TSx(name, amode)	{TERM, amode,  1, 0, 0, 0}
301*7c478bd9Sstevel@tonic-gate #define	TSy(name, amode)	{TERM, amode,  0, 1, 0, 0}
302*7c478bd9Sstevel@tonic-gate #define	TSp(name, amode)	{TERM, amode,  0, 0, 0, 1}
303*7c478bd9Sstevel@tonic-gate #define	TSZ(name, amode, sz)	{TERM, amode,  0, 0, 0, 0}
304*7c478bd9Sstevel@tonic-gate #define	TSZx(name, amode, sz)	{TERM, amode,  1, 0, 0, 0}
305*7c478bd9Sstevel@tonic-gate #define	TSZy(name, amode, sz)	{TERM, amode,  0, 1, 0, 0}
306*7c478bd9Sstevel@tonic-gate #define	INVALID			{TERM, UNKNOWN, 0, 0, 0, 0}
307*7c478bd9Sstevel@tonic-gate #endif
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
310*7c478bd9Sstevel@tonic-gate /*
311*7c478bd9Sstevel@tonic-gate  * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode
312*7c478bd9Sstevel@tonic-gate  */
313*7c478bd9Sstevel@tonic-gate const char *const dis_addr16[3][8] = {
314*7c478bd9Sstevel@tonic-gate "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "",
315*7c478bd9Sstevel@tonic-gate 									"(%bx)",
316*7c478bd9Sstevel@tonic-gate "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)",
317*7c478bd9Sstevel@tonic-gate 									"(%bx)",
318*7c478bd9Sstevel@tonic-gate "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)",
319*7c478bd9Sstevel@tonic-gate 									"(%bx)",
320*7c478bd9Sstevel@tonic-gate };
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate /*
324*7c478bd9Sstevel@tonic-gate  * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2
325*7c478bd9Sstevel@tonic-gate  */
326*7c478bd9Sstevel@tonic-gate const char *const dis_addr32_mode0[16] = {
327*7c478bd9Sstevel@tonic-gate   "(%eax)", "(%ecx)", "(%edx)",  "(%ebx)",  "", "",        "(%esi)",  "(%edi)",
328*7c478bd9Sstevel@tonic-gate   "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "",        "(%r14d)", "(%r15d)"
329*7c478bd9Sstevel@tonic-gate };
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate const char *const dis_addr32_mode12[16] = {
332*7c478bd9Sstevel@tonic-gate   "(%eax)", "(%ecx)", "(%edx)",  "(%ebx)",  "", "(%ebp)",  "(%esi)",  "(%edi)",
333*7c478bd9Sstevel@tonic-gate   "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)"
334*7c478bd9Sstevel@tonic-gate };
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate  * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2
338*7c478bd9Sstevel@tonic-gate  */
339*7c478bd9Sstevel@tonic-gate const char *const dis_addr64_mode0[16] = {
340*7c478bd9Sstevel@tonic-gate  "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "",       "(%rip)", "(%rsi)", "(%rdi)",
341*7c478bd9Sstevel@tonic-gate  "(%r8)",  "(%r9)",  "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)"
342*7c478bd9Sstevel@tonic-gate };
343*7c478bd9Sstevel@tonic-gate const char *const dis_addr64_mode12[16] = {
344*7c478bd9Sstevel@tonic-gate  "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "",       "(%rbp)", "(%rsi)", "(%rdi)",
345*7c478bd9Sstevel@tonic-gate  "(%r8)",  "(%r9)",  "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)"
346*7c478bd9Sstevel@tonic-gate };
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate /*
349*7c478bd9Sstevel@tonic-gate  * decode for scale from SIB byte
350*7c478bd9Sstevel@tonic-gate  */
351*7c478bd9Sstevel@tonic-gate const char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" };
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate /*
354*7c478bd9Sstevel@tonic-gate  * register decoding for normal references to registers (ie. not addressing)
355*7c478bd9Sstevel@tonic-gate  */
356*7c478bd9Sstevel@tonic-gate const char *const dis_REG8[16] = {
357*7c478bd9Sstevel@tonic-gate 	"%al",  "%cl",  "%dl",   "%bl",   "%ah",   "%ch",   "%dh",   "%bh",
358*7c478bd9Sstevel@tonic-gate 	"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
359*7c478bd9Sstevel@tonic-gate };
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate const char *const dis_REG8_REX[16] = {
362*7c478bd9Sstevel@tonic-gate 	"%al",  "%cl",  "%dl",   "%bl",   "%spl",  "%bpl",  "%sil",  "%dil",
363*7c478bd9Sstevel@tonic-gate 	"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
364*7c478bd9Sstevel@tonic-gate };
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate const char *const dis_REG16[16] = {
367*7c478bd9Sstevel@tonic-gate 	"%ax",  "%cx",  "%dx",   "%bx",   "%sp",   "%bp",   "%si",   "%di",
368*7c478bd9Sstevel@tonic-gate 	"%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
369*7c478bd9Sstevel@tonic-gate };
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate const char *const dis_REG32[16] = {
372*7c478bd9Sstevel@tonic-gate 	"%eax", "%ecx", "%edx",  "%ebx",  "%esp",  "%ebp",  "%esi",  "%edi",
373*7c478bd9Sstevel@tonic-gate 	"%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
374*7c478bd9Sstevel@tonic-gate };
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate const char *const dis_REG64[16] = {
377*7c478bd9Sstevel@tonic-gate 	"%rax", "%rcx", "%rdx",  "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
378*7c478bd9Sstevel@tonic-gate 	"%r8",  "%r9",  "%r10",  "%r11", "%r12", "%r13", "%r14", "%r15"
379*7c478bd9Sstevel@tonic-gate };
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate const char *const dis_DEBUGREG[16] = {
382*7c478bd9Sstevel@tonic-gate 	"%db0", "%db1", "%db2",  "%db3",  "%db4",  "%db5",  "%db6",  "%db7",
383*7c478bd9Sstevel@tonic-gate 	"%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15"
384*7c478bd9Sstevel@tonic-gate };
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate const char *const dis_CONTROLREG[16] = {
387*7c478bd9Sstevel@tonic-gate     "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?",
388*7c478bd9Sstevel@tonic-gate     "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?"
389*7c478bd9Sstevel@tonic-gate };
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate const char *const dis_TESTREG[16] = {
392*7c478bd9Sstevel@tonic-gate 	"%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
393*7c478bd9Sstevel@tonic-gate 	"%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7"
394*7c478bd9Sstevel@tonic-gate };
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate const char *const dis_MMREG[16] = {
397*7c478bd9Sstevel@tonic-gate 	"%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
398*7c478bd9Sstevel@tonic-gate 	"%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
399*7c478bd9Sstevel@tonic-gate };
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate const char *const dis_XMMREG[16] = {
402*7c478bd9Sstevel@tonic-gate     "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
403*7c478bd9Sstevel@tonic-gate     "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15"
404*7c478bd9Sstevel@tonic-gate };
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate const char *const dis_SEGREG[16] = {
407*7c478bd9Sstevel@tonic-gate 	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>",
408*7c478bd9Sstevel@tonic-gate 	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>"
409*7c478bd9Sstevel@tonic-gate };
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate /*
412*7c478bd9Sstevel@tonic-gate  * SIMD predicate suffixes
413*7c478bd9Sstevel@tonic-gate  */
414*7c478bd9Sstevel@tonic-gate const char *const dis_PREDSUFFIX[8] = {
415*7c478bd9Sstevel@tonic-gate 	"eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord"
416*7c478bd9Sstevel@tonic-gate };
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate #endif	/* DIS_TEXT */
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate /*
426*7c478bd9Sstevel@tonic-gate  *	"decode table" for 64 bit mode MOVSXD instruction (opcode 0x63)
427*7c478bd9Sstevel@tonic-gate  */
428*7c478bd9Sstevel@tonic-gate const instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ);
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate /*
431*7c478bd9Sstevel@tonic-gate  *	"decode table" for pause and clflush instructions
432*7c478bd9Sstevel@tonic-gate  */
433*7c478bd9Sstevel@tonic-gate const instable_t dis_opPause = TNS("pause", NORM);
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate /*
436*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0F00 opcodes
437*7c478bd9Sstevel@tonic-gate  */
438*7c478bd9Sstevel@tonic-gate const instable_t dis_op0F00[8] = {
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("sldt",M),		TNS("str",M),		TNSy("lldt",M), 	TNSy("ltr",M),
441*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNSZ("verr",M,2),	TNSZ("verw",M,2),	INVALID,		INVALID,
442*7c478bd9Sstevel@tonic-gate };
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate /*
446*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0F01 opcodes
447*7c478bd9Sstevel@tonic-gate  */
448*7c478bd9Sstevel@tonic-gate const instable_t dis_op0F01[8] = {
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNSZ("sgdt",MO,6),	TNSZ("sidt",MO,6), 	TNSZ("lgdt",MO,6),	TNSZ("lidt",MO,6),
451*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNSZ("smsw",M,2),	INVALID, 		TNSZ("lmsw",M,2),	TNS("invlpg",SWAPGS),
452*7c478bd9Sstevel@tonic-gate };
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate /*
455*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0F18 opcodes -- SIMD prefetch
456*7c478bd9Sstevel@tonic-gate  */
457*7c478bd9Sstevel@tonic-gate const instable_t dis_op0F18[8] = {
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("prefetchnta",PREF),TNS("prefetcht0",PREF),	TNS("prefetcht1",PREF),	TNS("prefetcht2",PREF),
460*7c478bd9Sstevel@tonic-gate /*  [4]  */	INVALID,		INVALID,		INVALID,		INVALID,
461*7c478bd9Sstevel@tonic-gate };
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate /*
464*7c478bd9Sstevel@tonic-gate  * 	Decode table for 0x0FAE opcodes -- SIMD state save/restore
465*7c478bd9Sstevel@tonic-gate  */
466*7c478bd9Sstevel@tonic-gate const instable_t dis_op0FAE[8] = {
467*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNSZ("fxsave",M,512),	TNSZ("fxrstor",M,512),	TNS("ldmxcsr",M),	TNS("stmxcsr",M),
468*7c478bd9Sstevel@tonic-gate /*  [4]  */	INVALID,		TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE),	TNS("sfence",XMMSFNC),
469*7c478bd9Sstevel@tonic-gate };
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate /*
472*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0FBA opcodes
473*7c478bd9Sstevel@tonic-gate  */
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate const instable_t dis_op0FBA[8] = {
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate /*  [0]  */	INVALID,		INVALID,		INVALID,		INVALID,
478*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("bt",MIb),		TS("bts",MIb),		TS("btr",MIb),		TS("btc",MIb),
479*7c478bd9Sstevel@tonic-gate };
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate /*
482*7c478bd9Sstevel@tonic-gate  * 	Decode table for 0x0FC7 opcode
483*7c478bd9Sstevel@tonic-gate  */
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate const instable_t dis_op0FC7[8] = {
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate /*  [0]  */	INVALID,		TNS("cmpxchg8b",M),	INVALID,		INVALID,
488*7c478bd9Sstevel@tonic-gate /*  [4]  */	INVALID,		INVALID,	INVALID,		 INVALID,
489*7c478bd9Sstevel@tonic-gate };
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate /*
493*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0FC8 opcode -- 486 bswap instruction
494*7c478bd9Sstevel@tonic-gate  *
495*7c478bd9Sstevel@tonic-gate  *bit pattern: 0000 1111 1100 1reg
496*7c478bd9Sstevel@tonic-gate  */
497*7c478bd9Sstevel@tonic-gate const instable_t dis_op0FC8[4] = {
498*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("bswap",R),		INVALID,		INVALID,		INVALID,
499*7c478bd9Sstevel@tonic-gate };
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate /*
502*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions
503*7c478bd9Sstevel@tonic-gate  */
504*7c478bd9Sstevel@tonic-gate const instable_t dis_op0F7123[4][8] = {
505*7c478bd9Sstevel@tonic-gate {
506*7c478bd9Sstevel@tonic-gate /*  [70].0 */	INVALID,		INVALID,		INVALID,		INVALID,
507*7c478bd9Sstevel@tonic-gate /*      .4 */	INVALID,		INVALID,		INVALID,		INVALID,
508*7c478bd9Sstevel@tonic-gate }, {
509*7c478bd9Sstevel@tonic-gate /*  [71].0 */	INVALID,		INVALID,		TNS("psrlw",MMOSH),	INVALID,
510*7c478bd9Sstevel@tonic-gate /*      .4 */	TNS("psraw",MMOSH),	INVALID,		TNS("psllw",MMOSH),	INVALID,
511*7c478bd9Sstevel@tonic-gate }, {
512*7c478bd9Sstevel@tonic-gate /*  [72].0 */	INVALID,		INVALID,		TNS("psrld",MMOSH),	INVALID,
513*7c478bd9Sstevel@tonic-gate /*      .4 */	TNS("psrad",MMOSH),	INVALID,		TNS("pslld",MMOSH),	INVALID,
514*7c478bd9Sstevel@tonic-gate }, {
515*7c478bd9Sstevel@tonic-gate /*  [73].0 */	INVALID,		INVALID,		TNS("psrlq",MMOSH),	TNS("INVALID",MMOSH),
516*7c478bd9Sstevel@tonic-gate /*      .4 */	INVALID,		INVALID, 		TNS("psllq",MMOSH),	TNS("INVALID",MMOSH),
517*7c478bd9Sstevel@tonic-gate } };
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate /*
520*7c478bd9Sstevel@tonic-gate  *	Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes.
521*7c478bd9Sstevel@tonic-gate  */
522*7c478bd9Sstevel@tonic-gate const instable_t dis_opSIMD7123[32] = {
523*7c478bd9Sstevel@tonic-gate /* [70].0 */	INVALID,		INVALID,		INVALID,		INVALID,
524*7c478bd9Sstevel@tonic-gate /*     .4 */	INVALID,		INVALID,		INVALID,		INVALID,
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate /* [71].0 */	INVALID,		INVALID,		TNS("psrlw",XMMSH),	INVALID,
527*7c478bd9Sstevel@tonic-gate /*     .4 */	TNS("psraw",XMMSH),	INVALID,		TNS("psllw",XMMSH),	INVALID,
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate /* [72].0 */	INVALID,		INVALID,		TNS("psrld",XMMSH),	INVALID,
530*7c478bd9Sstevel@tonic-gate /*     .4 */	TNS("psrad",XMMSH),	INVALID,		TNS("pslld",XMMSH),	INVALID,
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate /* [73].0 */	INVALID,		INVALID,		TNS("psrlq",XMMSH),	TNS("psrldq",XMMSH),
533*7c478bd9Sstevel@tonic-gate /*     .4 */	INVALID,		INVALID,		TNS("psllq",XMMSH),	TNS("pslldq",XMMSH),
534*7c478bd9Sstevel@tonic-gate };
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate /*
537*7c478bd9Sstevel@tonic-gate  *	SIMD instructions have been wedged into the existing IA32 instruction
538*7c478bd9Sstevel@tonic-gate  *	set through the use of prefixes.  That is, while 0xf0 0x58 may be
539*7c478bd9Sstevel@tonic-gate  *	addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different
540*7c478bd9Sstevel@tonic-gate  *	instruction - addss.  At present, three prefixes have been coopted in
541*7c478bd9Sstevel@tonic-gate  *	this manner - address size (0x66), repnz (0xf2) and repz (0xf3).  The
542*7c478bd9Sstevel@tonic-gate  *	following tables are used to provide the prefixed instruction names.
543*7c478bd9Sstevel@tonic-gate  *	The arrays are sparse, but they're fast.
544*7c478bd9Sstevel@tonic-gate  */
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate /*
547*7c478bd9Sstevel@tonic-gate  *	Decode table for SIMD instructions with the address size (0x66) prefix.
548*7c478bd9Sstevel@tonic-gate  */
549*7c478bd9Sstevel@tonic-gate const instable_t dis_opSIMDdata16[256] = {
550*7c478bd9Sstevel@tonic-gate /*  [00]  */	INVALID,		INVALID,		INVALID,		INVALID,
551*7c478bd9Sstevel@tonic-gate /*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
552*7c478bd9Sstevel@tonic-gate /*  [08]  */	INVALID,		INVALID,		INVALID,		INVALID,
553*7c478bd9Sstevel@tonic-gate /*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate /*  [10]  */	TNSZ("movupd",XMM,16),	TNSZ("movupd",XMMS,16),	TNSZ("movlpd",XMMM,8),	TNSZ("movlpd",XMMMS,8),
556*7c478bd9Sstevel@tonic-gate /*  [14]  */	TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8),	TNSZ("movhpd",XMMMS,8),
557*7c478bd9Sstevel@tonic-gate /*  [18]  */	INVALID,		INVALID,		INVALID,		INVALID,
558*7c478bd9Sstevel@tonic-gate /*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate /*  [20]  */	INVALID,		INVALID,		INVALID,		INVALID,
561*7c478bd9Sstevel@tonic-gate /*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
562*7c478bd9Sstevel@tonic-gate /*  [28]  */	TNSZ("movapd",XMM,16),	TNSZ("movapd",XMMS,16),	TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16),
563*7c478bd9Sstevel@tonic-gate /*  [2C]  */	TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8),
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate /*  [30]  */	INVALID,		INVALID,		INVALID,		INVALID,
566*7c478bd9Sstevel@tonic-gate /*  [34]  */	INVALID,		INVALID,		INVALID,		INVALID,
567*7c478bd9Sstevel@tonic-gate /*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
568*7c478bd9Sstevel@tonic-gate /*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate /*  [40]  */	INVALID,		INVALID,		INVALID,		INVALID,
571*7c478bd9Sstevel@tonic-gate /*  [44]  */	INVALID,		INVALID,		INVALID,		INVALID,
572*7c478bd9Sstevel@tonic-gate /*  [48]  */	INVALID,		INVALID,		INVALID,		INVALID,
573*7c478bd9Sstevel@tonic-gate /*  [4C]  */	INVALID,		INVALID,		INVALID,		INVALID,
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate /*  [50]  */	TNS("movmskpd",XMMOX3),	TNSZ("sqrtpd",XMM,16),	INVALID,		INVALID,
576*7c478bd9Sstevel@tonic-gate /*  [54]  */	TNSZ("andpd",XMM,16),	TNSZ("andnpd",XMM,16),	TNSZ("orpd",XMM,16),	TNSZ("xorpd",XMM,16),
577*7c478bd9Sstevel@tonic-gate /*  [58]  */	TNSZ("addpd",XMM,16),	TNSZ("mulpd",XMM,16),	TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16),
578*7c478bd9Sstevel@tonic-gate /*  [5C]  */	TNSZ("subpd",XMM,16),	TNSZ("minpd",XMM,16),	TNSZ("divpd",XMM,16),	TNSZ("maxpd",XMM,16),
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate /*  [60]  */	TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16),
581*7c478bd9Sstevel@tonic-gate /*  [64]  */	TNSZ("pcmpgtb",XMM,16),	TNSZ("pcmpgtw",XMM,16),	TNSZ("pcmpgtd",XMM,16),	TNSZ("packuswb",XMM,16),
582*7c478bd9Sstevel@tonic-gate /*  [68]  */	TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16),
583*7c478bd9Sstevel@tonic-gate /*  [6C]  */	TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16),
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate /*  [70]  */	TNSZ("pshufd",XMMP,16),	INVALID,		INVALID,		INVALID,
586*7c478bd9Sstevel@tonic-gate /*  [74]  */	TNSZ("pcmpeqb",XMM,16),	TNSZ("pcmpeqw",XMM,16),	TNSZ("pcmpeqd",XMM,16),	INVALID,
587*7c478bd9Sstevel@tonic-gate /*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
588*7c478bd9Sstevel@tonic-gate /*  [7C]  */	INVALID,		INVALID,		TNSZ("movd",XMM3MXS,4),	TNSZ("movdqa",XMMS,16),
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate /*  [80]  */	INVALID,		INVALID,		INVALID,		INVALID,
591*7c478bd9Sstevel@tonic-gate /*  [84]  */	INVALID,		INVALID,		INVALID,		INVALID,
592*7c478bd9Sstevel@tonic-gate /*  [88]  */	INVALID,		INVALID,		INVALID,		INVALID,
593*7c478bd9Sstevel@tonic-gate /*  [8C]  */	INVALID,		INVALID,		INVALID,		INVALID,
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate /*  [90]  */	INVALID,		INVALID,		INVALID,		INVALID,
596*7c478bd9Sstevel@tonic-gate /*  [94]  */	INVALID,		INVALID,		INVALID,		INVALID,
597*7c478bd9Sstevel@tonic-gate /*  [98]  */	INVALID,		INVALID,		INVALID,		INVALID,
598*7c478bd9Sstevel@tonic-gate /*  [9C]  */	INVALID,		INVALID,		INVALID,		INVALID,
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate /*  [A0]  */	INVALID,		INVALID,		INVALID,		INVALID,
601*7c478bd9Sstevel@tonic-gate /*  [A4]  */	INVALID,		INVALID,		INVALID,		INVALID,
602*7c478bd9Sstevel@tonic-gate /*  [A8]  */	INVALID,		INVALID,		INVALID,		INVALID,
603*7c478bd9Sstevel@tonic-gate /*  [AC]  */	INVALID,		INVALID,		INVALID,		INVALID,
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate /*  [B0]  */	INVALID,		INVALID,		INVALID,		INVALID,
606*7c478bd9Sstevel@tonic-gate /*  [B4]  */	INVALID,		INVALID,		INVALID,		INVALID,
607*7c478bd9Sstevel@tonic-gate /*  [B8]  */	INVALID,		INVALID,		INVALID,		INVALID,
608*7c478bd9Sstevel@tonic-gate /*  [BC]  */	INVALID,		INVALID,		INVALID,		INVALID,
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate /*  [C0]  */	INVALID,		INVALID,		TNSZ("cmppd",XMMP,16),	INVALID,
611*7c478bd9Sstevel@tonic-gate /*  [C4]  */	TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P),	TNSZ("shufpd",XMMP,16),	INVALID,
612*7c478bd9Sstevel@tonic-gate /*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
613*7c478bd9Sstevel@tonic-gate /*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate /*  [D0]  */	INVALID,		TNSZ("psrlw",XMM,16),	TNSZ("psrld",XMM,16),	TNSZ("psrlq",XMM,16),
616*7c478bd9Sstevel@tonic-gate /*  [D4]  */	TNSZ("paddq",XMM,16),	TNSZ("pmullw",XMM,16),	TNSZ("movq",XMMS,8),	TNS("pmovmskb",XMMX3),
617*7c478bd9Sstevel@tonic-gate /*  [D8]  */	TNSZ("psubusb",XMM,16),	TNSZ("psubusw",XMM,16),	TNSZ("pminub",XMM,16),	TNSZ("pand",XMM,16),
618*7c478bd9Sstevel@tonic-gate /*  [DC]  */	TNSZ("paddusb",XMM,16),	TNSZ("paddusw",XMM,16),	TNSZ("pmaxub",XMM,16),	TNSZ("pandn",XMM,16),
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate /*  [E0]  */	TNSZ("pavgb",XMM,16),	TNSZ("psraw",XMM,16),	TNSZ("psrad",XMM,16),	TNSZ("pavgw",XMM,16),
621*7c478bd9Sstevel@tonic-gate /*  [E4]  */	TNSZ("pmulhuw",XMM,16),	TNSZ("pmulhw",XMM,16),	TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16),
622*7c478bd9Sstevel@tonic-gate /*  [E8]  */	TNSZ("psubsb",XMM,16),	TNSZ("psubsw",XMM,16),	TNSZ("pminsw",XMM,16),	TNSZ("por",XMM,16),
623*7c478bd9Sstevel@tonic-gate /*  [EC]  */	TNSZ("paddsb",XMM,16),	TNSZ("paddsw",XMM,16),	TNSZ("pmaxsw",XMM,16),	TNSZ("pxor",XMM,16),
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate /*  [F0]  */	INVALID,		TNSZ("psllw",XMM,16),	TNSZ("pslld",XMM,16),	TNSZ("psllq",XMM,16),
626*7c478bd9Sstevel@tonic-gate /*  [F4]  */	TNSZ("pmuludq",XMM,16),	TNSZ("pmaddwd",XMM,16),	TNSZ("psadbw",XMM,16),	TNSZ("maskmovdqu", XMMXIMPL,16),
627*7c478bd9Sstevel@tonic-gate /*  [F8]  */	TNSZ("psubb",XMM,16),	TNSZ("psubw",XMM,16),	TNSZ("psubd",XMM,16),	TNSZ("psubq",XMM,16),
628*7c478bd9Sstevel@tonic-gate /*  [FC]  */	TNSZ("paddb",XMM,16),	TNSZ("paddw",XMM,16),	TNSZ("paddd",XMM,16),	INVALID,
629*7c478bd9Sstevel@tonic-gate };
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate /*
632*7c478bd9Sstevel@tonic-gate  *	Decode table for SIMD instructions with the repnz (0xf2) prefix.
633*7c478bd9Sstevel@tonic-gate  */
634*7c478bd9Sstevel@tonic-gate const instable_t dis_opSIMDrepnz[256] = {
635*7c478bd9Sstevel@tonic-gate /*  [00]  */	INVALID,		INVALID,		INVALID,		INVALID,
636*7c478bd9Sstevel@tonic-gate /*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
637*7c478bd9Sstevel@tonic-gate /*  [08]  */	INVALID,		INVALID,		INVALID,		INVALID,
638*7c478bd9Sstevel@tonic-gate /*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate /*  [10]  */	TNSZ("movsd",XMM,8),	TNSZ("movsd",XMMS,8),	INVALID,		INVALID,
641*7c478bd9Sstevel@tonic-gate /*  [14]  */	INVALID,		INVALID,		INVALID,		INVALID,
642*7c478bd9Sstevel@tonic-gate /*  [18]  */	INVALID,		INVALID,		INVALID,		INVALID,
643*7c478bd9Sstevel@tonic-gate /*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate /*  [20]  */	INVALID,		INVALID,		INVALID,		INVALID,
646*7c478bd9Sstevel@tonic-gate /*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
647*7c478bd9Sstevel@tonic-gate /*  [28]  */	INVALID,		INVALID,		TNSZ("cvtsi2sd",XMM3MX,4),INVALID,
648*7c478bd9Sstevel@tonic-gate /*  [2C]  */	TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID,		INVALID,
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate /*  [30]  */	INVALID,		INVALID,		INVALID,		INVALID,
651*7c478bd9Sstevel@tonic-gate /*  [34]  */	INVALID,		INVALID,		INVALID,		INVALID,
652*7c478bd9Sstevel@tonic-gate /*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
653*7c478bd9Sstevel@tonic-gate /*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate /*  [40]  */	INVALID,		INVALID,		INVALID,		INVALID,
656*7c478bd9Sstevel@tonic-gate /*  [44]  */	INVALID,		INVALID,		INVALID,		INVALID,
657*7c478bd9Sstevel@tonic-gate /*  [48]  */	INVALID,		INVALID,		INVALID,		INVALID,
658*7c478bd9Sstevel@tonic-gate /*  [4C]  */	INVALID,		INVALID,		INVALID,		INVALID,
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate /*  [50]  */	INVALID,		TNSZ("sqrtsd",XMM,8),	INVALID,		INVALID,
661*7c478bd9Sstevel@tonic-gate /*  [54]  */	INVALID,		INVALID,		INVALID,		INVALID,
662*7c478bd9Sstevel@tonic-gate /*  [58]  */	TNSZ("addsd",XMM,8),	TNSZ("mulsd",XMM,8),	TNSZ("cvtsd2ss",XMM,8),	INVALID,
663*7c478bd9Sstevel@tonic-gate /*  [5C]  */	TNSZ("subsd",XMM,8),	TNSZ("minsd",XMM,8),	TNSZ("divsd",XMM,8),	TNSZ("maxsd",XMM,8),
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate /*  [60]  */	INVALID,		INVALID,		INVALID,		INVALID,
666*7c478bd9Sstevel@tonic-gate /*  [64]  */	INVALID,		INVALID,		INVALID,		INVALID,
667*7c478bd9Sstevel@tonic-gate /*  [68]  */	INVALID,		INVALID,		INVALID,		INVALID,
668*7c478bd9Sstevel@tonic-gate /*  [6C]  */	INVALID,		INVALID,		INVALID,		INVALID,
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate /*  [70]  */	TNSZ("pshuflw",XMMP,16),INVALID,		INVALID,		INVALID,
671*7c478bd9Sstevel@tonic-gate /*  [74]  */	INVALID,		INVALID,		INVALID,		INVALID,
672*7c478bd9Sstevel@tonic-gate /*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
673*7c478bd9Sstevel@tonic-gate /*  [7C]  */	INVALID,		INVALID,		INVALID,		INVALID,
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate /*  [80]  */	INVALID,		INVALID,		INVALID,		INVALID,
676*7c478bd9Sstevel@tonic-gate /*  [84]  */	INVALID,		INVALID,		INVALID,		INVALID,
677*7c478bd9Sstevel@tonic-gate /*  [88]  */	INVALID,		INVALID,		INVALID,		INVALID,
678*7c478bd9Sstevel@tonic-gate /*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate /*  [90]  */	INVALID,		INVALID,		INVALID,		INVALID,
681*7c478bd9Sstevel@tonic-gate /*  [94]  */	INVALID,		INVALID,		INVALID,		INVALID,
682*7c478bd9Sstevel@tonic-gate /*  [98]  */	INVALID,		INVALID,		INVALID,		INVALID,
683*7c478bd9Sstevel@tonic-gate /*  [9C]  */	INVALID,		INVALID,		INVALID,		INVALID,
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate /*  [A0]  */	INVALID,		INVALID,		INVALID,		INVALID,
686*7c478bd9Sstevel@tonic-gate /*  [A4]  */	INVALID,		INVALID,		INVALID,		INVALID,
687*7c478bd9Sstevel@tonic-gate /*  [A8]  */	INVALID,		INVALID,		INVALID,		INVALID,
688*7c478bd9Sstevel@tonic-gate /*  [AC]  */	INVALID,		INVALID,		INVALID,		INVALID,
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate /*  [B0]  */	INVALID,		INVALID,		INVALID,		INVALID,
691*7c478bd9Sstevel@tonic-gate /*  [B4]  */	INVALID,		INVALID,		INVALID,		INVALID,
692*7c478bd9Sstevel@tonic-gate /*  [B8]  */	INVALID,		INVALID,		INVALID,		INVALID,
693*7c478bd9Sstevel@tonic-gate /*  [BC]  */	INVALID,		INVALID,		INVALID,		INVALID,
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate /*  [C0]  */	INVALID,		INVALID,		TNSZ("cmpsd",XMMP,8),	INVALID,
696*7c478bd9Sstevel@tonic-gate /*  [C4]  */	INVALID,		INVALID,		INVALID,		INVALID,
697*7c478bd9Sstevel@tonic-gate /*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
698*7c478bd9Sstevel@tonic-gate /*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate /*  [D0]  */	INVALID,		INVALID,		INVALID,		INVALID,
701*7c478bd9Sstevel@tonic-gate /*  [D4]  */	INVALID,		INVALID,		TNS("movdq2q",XMMXM),	INVALID,
702*7c478bd9Sstevel@tonic-gate /*  [D8]  */	INVALID,		INVALID,		INVALID,		INVALID,
703*7c478bd9Sstevel@tonic-gate /*  [DC]  */	INVALID,		INVALID,		INVALID,		INVALID,
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate /*  [E0]  */	INVALID,		INVALID,		INVALID,		INVALID,
706*7c478bd9Sstevel@tonic-gate /*  [E4]  */	INVALID,		INVALID,		TNSZ("cvtpd2dq",XMM,16),INVALID,
707*7c478bd9Sstevel@tonic-gate /*  [E8]  */	INVALID,		INVALID,		INVALID,		INVALID,
708*7c478bd9Sstevel@tonic-gate /*  [EC]  */	INVALID,		INVALID,		INVALID,		INVALID,
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate /*  [F0]  */	INVALID,		INVALID,		INVALID,		INVALID,
711*7c478bd9Sstevel@tonic-gate /*  [F4]  */	INVALID,		INVALID,		INVALID,		INVALID,
712*7c478bd9Sstevel@tonic-gate /*  [F8]  */	INVALID,		INVALID,		INVALID,		INVALID,
713*7c478bd9Sstevel@tonic-gate /*  [FC]  */	INVALID,		INVALID,		INVALID,		INVALID,
714*7c478bd9Sstevel@tonic-gate };
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate /*
717*7c478bd9Sstevel@tonic-gate  *	Decode table for SIMD instructions with the repz (0xf3) prefix.
718*7c478bd9Sstevel@tonic-gate  */
719*7c478bd9Sstevel@tonic-gate const instable_t dis_opSIMDrepz[256] = {
720*7c478bd9Sstevel@tonic-gate /*  [00]  */	INVALID,		INVALID,		INVALID,		INVALID,
721*7c478bd9Sstevel@tonic-gate /*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
722*7c478bd9Sstevel@tonic-gate /*  [08]  */	INVALID,		INVALID,		INVALID,		INVALID,
723*7c478bd9Sstevel@tonic-gate /*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate /*  [10]  */	TNSZ("movss",XMM,4),	TNSZ("movss",XMMS,4),	INVALID,		INVALID,
726*7c478bd9Sstevel@tonic-gate /*  [14]  */	INVALID,		INVALID,		INVALID,		INVALID,
727*7c478bd9Sstevel@tonic-gate /*  [18]  */	INVALID,		INVALID,		INVALID,		INVALID,
728*7c478bd9Sstevel@tonic-gate /*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate /*  [20]  */	INVALID,		INVALID,		INVALID,		INVALID,
731*7c478bd9Sstevel@tonic-gate /*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
732*7c478bd9Sstevel@tonic-gate /*  [28]  */	INVALID,		INVALID,		TNSZ("cvtsi2ss",XMM3MX,4),INVALID,
733*7c478bd9Sstevel@tonic-gate /*  [2C]  */	TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID,		INVALID,
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate /*  [30]  */	INVALID,		INVALID,		INVALID,		INVALID,
736*7c478bd9Sstevel@tonic-gate /*  [34]  */	INVALID,		INVALID,		INVALID,		INVALID,
737*7c478bd9Sstevel@tonic-gate /*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
738*7c478bd9Sstevel@tonic-gate /*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate /*  [40]  */	INVALID,		INVALID,		INVALID,		INVALID,
741*7c478bd9Sstevel@tonic-gate /*  [44]  */	INVALID,		INVALID,		INVALID,		INVALID,
742*7c478bd9Sstevel@tonic-gate /*  [48]  */	INVALID,		INVALID,		INVALID,		INVALID,
743*7c478bd9Sstevel@tonic-gate /*  [4C]  */	INVALID,		INVALID,		INVALID,		INVALID,
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate /*  [50]  */	INVALID,		TNSZ("sqrtss",XMM,4),	TNSZ("rsqrtss",XMM,4),	TNSZ("rcpss",XMM,4),
746*7c478bd9Sstevel@tonic-gate /*  [54]  */	INVALID,		INVALID,		INVALID,		INVALID,
747*7c478bd9Sstevel@tonic-gate /*  [58]  */	TNSZ("addss",XMM,4),	TNSZ("mulss",XMM,4),	TNSZ("cvtss2sd",XMM,4),	TNSZ("cvttps2dq",XMM,16),
748*7c478bd9Sstevel@tonic-gate /*  [5C]  */	TNSZ("subss",XMM,4),	TNSZ("minss",XMM,4),	TNSZ("divss",XMM,4),	TNSZ("maxss",XMM,4),
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate /*  [60]  */	INVALID,		INVALID,		INVALID,		INVALID,
751*7c478bd9Sstevel@tonic-gate /*  [64]  */	INVALID,		INVALID,		INVALID,		INVALID,
752*7c478bd9Sstevel@tonic-gate /*  [68]  */	INVALID,		INVALID,		INVALID,		INVALID,
753*7c478bd9Sstevel@tonic-gate /*  [6C]  */	INVALID,		INVALID,		INVALID,		TNSZ("movdqu",XMM,16),
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate /*  [70]  */	TNSZ("pshufhw",XMMP,16),INVALID,		INVALID,		INVALID,
756*7c478bd9Sstevel@tonic-gate /*  [74]  */	INVALID,		INVALID,		INVALID,		INVALID,
757*7c478bd9Sstevel@tonic-gate /*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
758*7c478bd9Sstevel@tonic-gate /*  [7C]  */	INVALID,		INVALID,		TNSZ("movq",XMM,8),	TNSZ("movdqu",XMMS,16),
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate /*  [80]  */	INVALID,		INVALID,		INVALID,		INVALID,
761*7c478bd9Sstevel@tonic-gate /*  [84]  */	INVALID,		INVALID,		INVALID,		INVALID,
762*7c478bd9Sstevel@tonic-gate /*  [88]  */	INVALID,		INVALID,		INVALID,		INVALID,
763*7c478bd9Sstevel@tonic-gate /*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate /*  [90]  */	INVALID,		INVALID,		INVALID,		INVALID,
766*7c478bd9Sstevel@tonic-gate /*  [94]  */	INVALID,		INVALID,		INVALID,		INVALID,
767*7c478bd9Sstevel@tonic-gate /*  [98]  */	INVALID,		INVALID,		INVALID,		INVALID,
768*7c478bd9Sstevel@tonic-gate /*  [9C]  */	INVALID,		INVALID,		INVALID,		INVALID,
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate /*  [A0]  */	INVALID,		INVALID,		INVALID,		INVALID,
771*7c478bd9Sstevel@tonic-gate /*  [A4]  */	INVALID,		INVALID,		INVALID,		INVALID,
772*7c478bd9Sstevel@tonic-gate /*  [A8]  */	INVALID,		INVALID,		INVALID,		INVALID,
773*7c478bd9Sstevel@tonic-gate /*  [AC]  */	INVALID,		INVALID,		INVALID,		INVALID,
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate /*  [B0]  */	INVALID,		INVALID,		INVALID,		INVALID,
776*7c478bd9Sstevel@tonic-gate /*  [B4]  */	INVALID,		INVALID,		INVALID,		INVALID,
777*7c478bd9Sstevel@tonic-gate /*  [B8]  */	INVALID,		INVALID,		INVALID,		INVALID,
778*7c478bd9Sstevel@tonic-gate /*  [BC]  */	INVALID,		INVALID,		INVALID,		INVALID,
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate /*  [C0]  */	INVALID,		INVALID,		TNSZ("cmpss",XMMP,4),	INVALID,
781*7c478bd9Sstevel@tonic-gate /*  [C4]  */	INVALID,		INVALID,		INVALID,		INVALID,
782*7c478bd9Sstevel@tonic-gate /*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
783*7c478bd9Sstevel@tonic-gate /*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate /*  [D0]  */	INVALID,		INVALID,		INVALID,		INVALID,
786*7c478bd9Sstevel@tonic-gate /*  [D4]  */	INVALID,		INVALID,		TNS("movq2dq",XMMMX),	INVALID,
787*7c478bd9Sstevel@tonic-gate /*  [D8]  */	INVALID,		INVALID,		INVALID,		INVALID,
788*7c478bd9Sstevel@tonic-gate /*  [DC]  */	INVALID,		INVALID,		INVALID,		INVALID,
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate /*  [E0]  */	INVALID,		INVALID,		INVALID,		INVALID,
791*7c478bd9Sstevel@tonic-gate /*  [E4]  */	INVALID,		INVALID,		TNSZ("cvtdq2pd",XMM,8),	INVALID,
792*7c478bd9Sstevel@tonic-gate /*  [E8]  */	INVALID,		INVALID,		INVALID,		INVALID,
793*7c478bd9Sstevel@tonic-gate /*  [EC]  */	INVALID,		INVALID,		INVALID,		INVALID,
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate /*  [F0]  */	INVALID,		INVALID,		INVALID,		INVALID,
796*7c478bd9Sstevel@tonic-gate /*  [F4]  */	INVALID,		INVALID,		INVALID,		INVALID,
797*7c478bd9Sstevel@tonic-gate /*  [F8]  */	INVALID,		INVALID,		INVALID,		INVALID,
798*7c478bd9Sstevel@tonic-gate /*  [FC]  */	INVALID,		INVALID,		INVALID,		INVALID,
799*7c478bd9Sstevel@tonic-gate };
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate /*
802*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x0F opcodes
803*7c478bd9Sstevel@tonic-gate  */
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate const instable_t dis_op0F[16][16] = {
806*7c478bd9Sstevel@tonic-gate {
807*7c478bd9Sstevel@tonic-gate /*  [00]  */	IND(dis_op0F00),	IND(dis_op0F01),	TNS("lar",MR),		TNS("lsl",MR),
808*7c478bd9Sstevel@tonic-gate /*  [04]  */	INVALID,		TNS("syscall",NORM),	TNS("clts",NORM),	TNS("sysret",NORM),
809*7c478bd9Sstevel@tonic-gate /*  [08]  */	TNS("invd",NORM),	TNS("wbinvd",NORM),	INVALID,		TNS("ud2",NORM),
810*7c478bd9Sstevel@tonic-gate /*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
811*7c478bd9Sstevel@tonic-gate }, {
812*7c478bd9Sstevel@tonic-gate /*  [10]  */	TNSZ("movups",XMMO,16),	TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8),	TNSZ("movlps",XMMOS,8),
813*7c478bd9Sstevel@tonic-gate /*  [14]  */	TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8),
814*7c478bd9Sstevel@tonic-gate /*  [18]  */	IND(dis_op0F18),	INVALID,		INVALID,		INVALID,
815*7c478bd9Sstevel@tonic-gate /*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
816*7c478bd9Sstevel@tonic-gate }, {
817*7c478bd9Sstevel@tonic-gate /*  [20]  */	TSy("mov",SREG),	TSy("mov",SREG),	TSy("mov",SREG),	TSy("mov",SREG),
818*7c478bd9Sstevel@tonic-gate /*  [24]  */	TSx("mov",SREG),	INVALID,		TSx("mov",SREG),	INVALID,
819*7c478bd9Sstevel@tonic-gate /*  [28]  */	TNSZ("movaps",XMMO,16),	TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16),
820*7c478bd9Sstevel@tonic-gate /*  [2C]  */	TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4),
821*7c478bd9Sstevel@tonic-gate }, {
822*7c478bd9Sstevel@tonic-gate /*  [30]  */	TNS("wrmsr",NORM),	TNS("rdtsc",NORM),	TNS("rdmsr",NORM),	TNS("rdpmc",NORM),
823*7c478bd9Sstevel@tonic-gate /*  [34]  */	TNSx("sysenter",NORM),	TNSx("sysexit",NORM),	INVALID,		INVALID,
824*7c478bd9Sstevel@tonic-gate /*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
825*7c478bd9Sstevel@tonic-gate /*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
826*7c478bd9Sstevel@tonic-gate }, {
827*7c478bd9Sstevel@tonic-gate /*  [40]  */	TS("cmovx.o",MR),	TS("cmovx.no",MR),	TS("cmovx.b",MR),	TS("cmovx.ae",MR),
828*7c478bd9Sstevel@tonic-gate /*  [44]  */	TS("cmovx.e",MR),	TS("cmovx.ne",MR),	TS("cmovx.be",MR),	TS("cmovx.a",MR),
829*7c478bd9Sstevel@tonic-gate /*  [48]  */	TS("cmovx.s",MR),	TS("cmovx.ns",MR),	TS("cmovx.pe",MR),	TS("cmovx.po",MR),
830*7c478bd9Sstevel@tonic-gate /*  [4C]  */	TS("cmovx.l",MR),	TS("cmovx.ge",MR),	TS("cmovx.le",MR),	TS("cmovx.g",MR),
831*7c478bd9Sstevel@tonic-gate }, {
832*7c478bd9Sstevel@tonic-gate /*  [50]  */	TNS("movmskps",XMMOX3),	TNSZ("sqrtps",XMMO,16),	TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16),
833*7c478bd9Sstevel@tonic-gate /*  [54]  */	TNSZ("andps",XMMO,16),	TNSZ("andnps",XMMO,16),	TNSZ("orps",XMMO,16),	TNSZ("xorps",XMMO,16),
834*7c478bd9Sstevel@tonic-gate /*  [58]  */	TNSZ("addps",XMMO,16),	TNSZ("mulps",XMMO,16),	TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16),
835*7c478bd9Sstevel@tonic-gate /*  [5C]  */	TNSZ("subps",XMMO,16),	TNSZ("minps",XMMO,16),	TNSZ("divps",XMMO,16),	TNSZ("maxps",XMMO,16),
836*7c478bd9Sstevel@tonic-gate }, {
837*7c478bd9Sstevel@tonic-gate /*  [60]  */	TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8),
838*7c478bd9Sstevel@tonic-gate /*  [64]  */	TNSZ("pcmpgtb",MMO,8),	TNSZ("pcmpgtw",MMO,8),	TNSZ("pcmpgtd",MMO,8),	TNSZ("packuswb",MMO,8),
839*7c478bd9Sstevel@tonic-gate /*  [68]  */	TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8),
840*7c478bd9Sstevel@tonic-gate /*  [6C]  */	TNSZ("INVALID",MMO,0),	TNSZ("INVALID",MMO,0),	TNSZ("movd",MMO,4),	TNSZ("movq",MMO,8),
841*7c478bd9Sstevel@tonic-gate }, {
842*7c478bd9Sstevel@tonic-gate /*  [70]  */	TNSZ("pshufw",MMOPM,8),	TNS("psrXXX",MR),	TNS("psrXXX",MR),	TNS("psrXXX",MR),
843*7c478bd9Sstevel@tonic-gate /*  [74]  */	TNSZ("pcmpeqb",MMO,8),	TNSZ("pcmpeqw",MMO,8),	TNSZ("pcmpeqd",MMO,8),	TNS("emms",NORM),
844*7c478bd9Sstevel@tonic-gate /*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
845*7c478bd9Sstevel@tonic-gate /*  [7C]  */	INVALID,		INVALID,		TNSZ("movd",MMOS,4),	TNSZ("movq",MMOS,8),
846*7c478bd9Sstevel@tonic-gate }, {
847*7c478bd9Sstevel@tonic-gate /*  [80]  */	TNS("jo",D),		TNS("jno",D),		TNS("jb",D),		TNS("jae",D),
848*7c478bd9Sstevel@tonic-gate /*  [84]  */	TNS("je",D),		TNS("jne",D),		TNS("jbe",D),		TNS("ja",D),
849*7c478bd9Sstevel@tonic-gate /*  [88]  */	TNS("js",D),		TNS("jns",D),		TNS("jp",D),		TNS("jnp",D),
850*7c478bd9Sstevel@tonic-gate /*  [8C]  */	TNS("jl",D),		TNS("jge",D),		TNS("jle",D),		TNS("jg",D),
851*7c478bd9Sstevel@tonic-gate }, {
852*7c478bd9Sstevel@tonic-gate /*  [90]  */	TNS("seto",Mb),		TNS("setno",Mb),	TNS("setb",Mb),		TNS("setae",Mb),
853*7c478bd9Sstevel@tonic-gate /*  [94]  */	TNS("sete",Mb),		TNS("setne",Mb),	TNS("setbe",Mb),	TNS("seta",Mb),
854*7c478bd9Sstevel@tonic-gate /*  [98]  */	TNS("sets",Mb),		TNS("setns",Mb),	TNS("setp",Mb),		TNS("setnp",Mb),
855*7c478bd9Sstevel@tonic-gate /*  [9C]  */	TNS("setl",Mb),		TNS("setge",Mb),	TNS("setle",Mb),	TNS("setg",Mb),
856*7c478bd9Sstevel@tonic-gate }, {
857*7c478bd9Sstevel@tonic-gate /*  [A0]  */	TSp("push",LSEG),	TSp("pop",LSEG),	TNS("cpuid",NORM),	TS("bt",RMw),
858*7c478bd9Sstevel@tonic-gate /*  [A4]  */	TS("shld",DSHIFT),	TS("shld",DSHIFTcl),	INVALID,		INVALID,
859*7c478bd9Sstevel@tonic-gate /*  [A8]  */	TSp("push",LSEG),	TSp("pop",LSEG),	TNS("rsm",NORM),	TS("bts",RMw),
860*7c478bd9Sstevel@tonic-gate /*  [AC]  */	TS("shrd",DSHIFT),	TS("shrd",DSHIFTcl),	IND(dis_op0FAE),	TS("imul",MRw),
861*7c478bd9Sstevel@tonic-gate }, {
862*7c478bd9Sstevel@tonic-gate /*  [B0]  */	TNS("cmpxchgb",RMw),	TS("cmpxchg",RMw),	TS("lss",MR),		TS("btr",RMw),
863*7c478bd9Sstevel@tonic-gate /*  [B4]  */	TS("lfs",MR),		TS("lgs",MR),		TS("movzb",MOVZ),	TNS("movzwl",MOVZ),
864*7c478bd9Sstevel@tonic-gate /*  [B8]  */	INVALID,		INVALID,		IND(dis_op0FBA),	TS("btc",RMw),
865*7c478bd9Sstevel@tonic-gate /*  [BC]  */	TS("bsf",MRw),		TS("bsr",MRw),		TS("movsb",MOVZ),	TNS("movswl",MOVZ),
866*7c478bd9Sstevel@tonic-gate }, {
867*7c478bd9Sstevel@tonic-gate /*  [C0]  */	TNS("xaddb",XADDB),	TS("xadd",RMw),		TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM),
868*7c478bd9Sstevel@tonic-gate /*  [C4]  */	TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), 	TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7),
869*7c478bd9Sstevel@tonic-gate /*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
870*7c478bd9Sstevel@tonic-gate /*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
871*7c478bd9Sstevel@tonic-gate }, {
872*7c478bd9Sstevel@tonic-gate /*  [D0]  */	INVALID,		TNSZ("psrlw",MMO,8),	TNSZ("psrld",MMO,8),	TNSZ("psrlq",MMO,8),
873*7c478bd9Sstevel@tonic-gate /*  [D4]  */	TNSZ("paddq",MMO,8),	TNSZ("pmullw",MMO,8),	TNSZ("INVALID",MMO,0),	TNS("pmovmskb",MMOM3),
874*7c478bd9Sstevel@tonic-gate /*  [D8]  */	TNSZ("psubusb",MMO,8),	TNSZ("psubusw",MMO,8),	TNSZ("pminub",MMO,8),	TNSZ("pand",MMO,8),
875*7c478bd9Sstevel@tonic-gate /*  [DC]  */	TNSZ("paddusb",MMO,8),	TNSZ("paddusw",MMO,8),	TNSZ("pmaxub",MMO,8),	TNSZ("pandn",MMO,8),
876*7c478bd9Sstevel@tonic-gate }, {
877*7c478bd9Sstevel@tonic-gate /*  [E0]  */	TNSZ("pavgb",MMO,8),	TNSZ("psraw",MMO,8),	TNSZ("psrad",MMO,8),	TNSZ("pavgw",MMO,8),
878*7c478bd9Sstevel@tonic-gate /*  [E4]  */	TNSZ("pmulhuw",MMO,8),	TNSZ("pmulhw",MMO,8),	TNS("INVALID",XMMO),	TNSZ("movntq",MMOMS,8),
879*7c478bd9Sstevel@tonic-gate /*  [E8]  */	TNSZ("psubsb",MMO,8),	TNSZ("psubsw",MMO,8),	TNSZ("pminsw",MMO,8),	TNSZ("por",MMO,8),
880*7c478bd9Sstevel@tonic-gate /*  [EC]  */	TNSZ("paddsb",MMO,8),	TNSZ("paddsw",MMO,8),	TNSZ("pmaxsw",MMO,8),	TNSZ("pxor",MMO,8),
881*7c478bd9Sstevel@tonic-gate }, {
882*7c478bd9Sstevel@tonic-gate /*  [F0]  */	INVALID,		TNSZ("psllw",MMO,8),	TNSZ("pslld",MMO,8),	TNSZ("psllq",MMO,8),
883*7c478bd9Sstevel@tonic-gate /*  [F4]  */	TNSZ("pmuludq",MMO,8),	TNSZ("pmaddwd",MMO,8),	TNSZ("psadbw",MMO,8),	TNSZ("maskmovq",MMOIMPL,8),
884*7c478bd9Sstevel@tonic-gate /*  [F8]  */	TNSZ("psubb",MMO,8),	TNSZ("psubw",MMO,8),	TNSZ("psubd",MMO,8),	TNSZ("psubq",MMO,8),
885*7c478bd9Sstevel@tonic-gate /*  [FC]  */	TNSZ("paddb",MMO,8),	TNSZ("paddw",MMO,8),	TNSZ("paddd",MMO,8),	INVALID,
886*7c478bd9Sstevel@tonic-gate } };
887*7c478bd9Sstevel@tonic-gate 
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate /*
890*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x80 opcodes
891*7c478bd9Sstevel@tonic-gate  */
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate const instable_t dis_op80[8] = {
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("addb",IMlw),	TNS("orb",IMw),		TNS("adcb",IMlw),	TNS("sbbb",IMlw),
896*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNS("andb",IMw),	TNS("subb",IMlw),	TNS("xorb",IMw),	TNS("cmpb",IMlw),
897*7c478bd9Sstevel@tonic-gate };
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate /*
901*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x81 opcodes.
902*7c478bd9Sstevel@tonic-gate  */
903*7c478bd9Sstevel@tonic-gate 
904*7c478bd9Sstevel@tonic-gate const instable_t dis_op81[8] = {
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("add",IMlw),		TS("or",IMw),		TS("adc",IMlw),		TS("sbb",IMlw),
907*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("and",IMw),		TS("sub",IMlw),		TS("xor",IMw),		TS("cmp",IMlw),
908*7c478bd9Sstevel@tonic-gate };
909*7c478bd9Sstevel@tonic-gate 
910*7c478bd9Sstevel@tonic-gate 
911*7c478bd9Sstevel@tonic-gate /*
912*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x82 opcodes.
913*7c478bd9Sstevel@tonic-gate  */
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate const instable_t dis_op82[8] = {
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNSx("addb",IMlw),	TNSx("orb",IMlw),	TNSx("adcb",IMlw),	TNSx("sbbb",IMlw),
918*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNSx("andb",IMlw),	TNSx("subb",IMlw),	TNSx("xorb",IMlw),	TNSx("cmpb",IMlw),
919*7c478bd9Sstevel@tonic-gate };
920*7c478bd9Sstevel@tonic-gate /*
921*7c478bd9Sstevel@tonic-gate  *	Decode table for 0x83 opcodes.
922*7c478bd9Sstevel@tonic-gate  */
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate const instable_t dis_op83[8] = {
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("add",IMlw),		TS("or",IMlw),		TS("adc",IMlw),		TS("sbb",IMlw),
927*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("and",IMlw),		TS("sub",IMlw),		TS("xor",IMlw),		TS("cmp",IMlw),
928*7c478bd9Sstevel@tonic-gate };
929*7c478bd9Sstevel@tonic-gate 
930*7c478bd9Sstevel@tonic-gate /*
931*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xC0 opcodes.
932*7c478bd9Sstevel@tonic-gate  */
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate const instable_t dis_opC0[8] = {
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("rolb",MvI),	TNS("rorb",MvI),	TNS("rclb",MvI),	TNS("rcrb",MvI),
937*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNS("shlb",MvI),	TNS("shrb",MvI),	INVALID,		TNS("sarb",MvI),
938*7c478bd9Sstevel@tonic-gate };
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate /*
941*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xD0 opcodes.
942*7c478bd9Sstevel@tonic-gate  */
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate const instable_t dis_opD0[8] = {
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("rolb",Mv),		TNS("rorb",Mv),		TNS("rclb",Mv),		TNS("rcrb",Mv),
947*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNS("shlb",Mv),		TNS("shrb",Mv),		TNS("salb",Mv),		TNS("sarb",Mv),
948*7c478bd9Sstevel@tonic-gate };
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate /*
951*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xC1 opcodes.
952*7c478bd9Sstevel@tonic-gate  *	186 instruction set
953*7c478bd9Sstevel@tonic-gate  */
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate const instable_t dis_opC1[8] = {
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("rol",MvI),		TS("ror",MvI),		TS("rcl",MvI),		TS("rcr",MvI),
958*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("shl",MvI),		TS("shr",MvI),		TS("sal",MvI),		TS("sar",MvI),
959*7c478bd9Sstevel@tonic-gate };
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate /*
962*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xD1 opcodes.
963*7c478bd9Sstevel@tonic-gate  */
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate const instable_t dis_opD1[8] = {
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("rol",Mv),		TS("ror",Mv),		TS("rcl",Mv),		TS("rcr",Mv),
968*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("shl",Mv),		TS("shr",Mv),		TS("sal",Mv),		TS("sar",Mv),
969*7c478bd9Sstevel@tonic-gate };
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate /*
973*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xD2 opcodes.
974*7c478bd9Sstevel@tonic-gate  */
975*7c478bd9Sstevel@tonic-gate 
976*7c478bd9Sstevel@tonic-gate const instable_t dis_opD2[8] = {
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("rolb",Mv),		TNS("rorb",Mv),		TNS("rclb",Mv),		TNS("rcrb",Mv),
979*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNS("shlb",Mv),		TNS("shrb",Mv),		TNS("salb",Mv),		TNS("sarb",Mv),
980*7c478bd9Sstevel@tonic-gate };
981*7c478bd9Sstevel@tonic-gate /*
982*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xD3 opcodes.
983*7c478bd9Sstevel@tonic-gate  */
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate const instable_t dis_opD3[8] = {
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("rol",Mv),		TS("ror",Mv),		TS("rcl",Mv),		TS("rcr",Mv),
988*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("shl",Mv),		TS("shr",Mv),		TS("salb",Mv),		TS("sar",Mv),
989*7c478bd9Sstevel@tonic-gate };
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate /*
993*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xF6 opcodes.
994*7c478bd9Sstevel@tonic-gate  */
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate const instable_t dis_opF6[8] = {
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("testb",IMw),	TNS("testb",IMw),	TNS("notb",Mw),		TNS("negb",Mw),
999*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNS("mulb",MA),		TNS("imulb",MA),	TNS("divb",MA),		TNS("idivb",MA),
1000*7c478bd9Sstevel@tonic-gate };
1001*7c478bd9Sstevel@tonic-gate 
1002*7c478bd9Sstevel@tonic-gate 
1003*7c478bd9Sstevel@tonic-gate /*
1004*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xF7 opcodes.
1005*7c478bd9Sstevel@tonic-gate  */
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate const instable_t dis_opF7[8] = {
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("test",IMw),		TS("test",IMw),		TS("not",Mw),		TS("neg",Mw),
1010*7c478bd9Sstevel@tonic-gate /*  [4]  */	TS("mul",MA),		TS("imul",MA),		TS("div",MA),		TS("idiv",MA),
1011*7c478bd9Sstevel@tonic-gate };
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate 
1014*7c478bd9Sstevel@tonic-gate /*
1015*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xFE opcodes.
1016*7c478bd9Sstevel@tonic-gate  */
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate const instable_t dis_opFE[8] = {
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("incb",Mw),		TNS("decb",Mw),		INVALID,		INVALID,
1021*7c478bd9Sstevel@tonic-gate /*  [4]  */	INVALID,		INVALID,		INVALID,		INVALID,
1022*7c478bd9Sstevel@tonic-gate };
1023*7c478bd9Sstevel@tonic-gate /*
1024*7c478bd9Sstevel@tonic-gate  *	Decode table for 0xFF opcodes.
1025*7c478bd9Sstevel@tonic-gate  */
1026*7c478bd9Sstevel@tonic-gate 
1027*7c478bd9Sstevel@tonic-gate const instable_t dis_opFF[8] = {
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate /*  [0]  */	TS("inc",Mw),		TS("dec",Mw),		TNSyp("call",INM),	TNS("lcall",INM),
1030*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNSy("jmp",INM),	TNS("ljmp",INM),	TSp("push",M),		INVALID,
1031*7c478bd9Sstevel@tonic-gate };
1032*7c478bd9Sstevel@tonic-gate 
1033*7c478bd9Sstevel@tonic-gate /* for 287 instructions, which are a mess to decode */
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate const instable_t dis_opFP1n2[8][8] = {
1036*7c478bd9Sstevel@tonic-gate {
1037*7c478bd9Sstevel@tonic-gate /* bit pattern:	1101 1xxx MODxx xR/M */
1038*7c478bd9Sstevel@tonic-gate /*  [0,0] */	TNS("fadds",M),		TNS("fmuls",M),		TNS("fcoms",M),		TNS("fcomps",M),
1039*7c478bd9Sstevel@tonic-gate /*  [0,4] */	TNS("fsubs",M),		TNS("fsubrs",M),	TNS("fdivs",M),		TNS("fdivrs",M),
1040*7c478bd9Sstevel@tonic-gate }, {
1041*7c478bd9Sstevel@tonic-gate /*  [1,0]  */	TNS("flds",M),		INVALID,		TNS("fsts",M),		TNS("fstps",M),
1042*7c478bd9Sstevel@tonic-gate /*  [1,4]  */	TNSZ("fldenv",M,28),	TNSZ("fldcw",M,2),	TNSZ("fnstenv",M,28),	TNSZ("fnstcw",M,2),
1043*7c478bd9Sstevel@tonic-gate }, {
1044*7c478bd9Sstevel@tonic-gate /*  [2,0]  */	TNS("fiaddl",M),	TNS("fimull",M),	TNS("ficoml",M),	TNS("ficompl",M),
1045*7c478bd9Sstevel@tonic-gate /*  [2,4]  */	TNS("fisubl",M),	TNS("fisubrl",M),	TNS("fidivl",M),	TNS("fidivrl",M),
1046*7c478bd9Sstevel@tonic-gate }, {
1047*7c478bd9Sstevel@tonic-gate /*  [3,0]  */	TNS("fildl",M),		INVALID,		TNS("fistl",M),		TNS("fistpl",M),
1048*7c478bd9Sstevel@tonic-gate /*  [3,4]  */	INVALID,		TNSZ("fldt",M,10),	INVALID,		TNSZ("fstpt",M,10),
1049*7c478bd9Sstevel@tonic-gate }, {
1050*7c478bd9Sstevel@tonic-gate /*  [4,0]  */	TNSZ("faddl",M,8),	TNSZ("fmull",M,8),	TNSZ("fcoml",M,8),	TNSZ("fcompl",M,8),
1051*7c478bd9Sstevel@tonic-gate /*  [4,1]  */	TNSZ("fsubl",M,8),	TNSZ("fsubrl",M,8),	TNSZ("fdivl",M,8),	TNSZ("fdivrl",M,8),
1052*7c478bd9Sstevel@tonic-gate }, {
1053*7c478bd9Sstevel@tonic-gate /*  [5,0]  */	TNSZ("fldl",M,8),	INVALID,		TNSZ("fstl",M,8),	TNSZ("fstpl",M,8),
1054*7c478bd9Sstevel@tonic-gate /*  [5,4]  */	TNSZ("frstor",M,108),	INVALID,		TNSZ("fnsave",M,108),	TNSZ("fnstsw",M,2),
1055*7c478bd9Sstevel@tonic-gate }, {
1056*7c478bd9Sstevel@tonic-gate /*  [6,0]  */	TNSZ("fiadd",M,2),	TNSZ("fimul",M,2),	TNSZ("ficom",M,2),	TNSZ("ficomp",M,2),
1057*7c478bd9Sstevel@tonic-gate /*  [6,4]  */	TNSZ("fisub",M,2),	TNSZ("fisubr",M,2),	TNSZ("fidiv",M,2),	TNSZ("fidivr",M,2),
1058*7c478bd9Sstevel@tonic-gate }, {
1059*7c478bd9Sstevel@tonic-gate /*  [7,0]  */	TNSZ("fild",M,2),	INVALID,		TNSZ("fist",M,2),	TNSZ("fistp",M,2),
1060*7c478bd9Sstevel@tonic-gate /*  [7,4]  */	TNSZ("fbld",M,10),	TNSZ("fildll",M,8),	TNSZ("fbstp",M,10),	TNSZ("fistpll",M,8),
1061*7c478bd9Sstevel@tonic-gate } };
1062*7c478bd9Sstevel@tonic-gate 
1063*7c478bd9Sstevel@tonic-gate const instable_t dis_opFP3[8][8] = {
1064*7c478bd9Sstevel@tonic-gate {
1065*7c478bd9Sstevel@tonic-gate /* bit  pattern:	1101 1xxx 11xx xREG */
1066*7c478bd9Sstevel@tonic-gate /*  [0,0]  */	TNS("fadd",FF),		TNS("fmul",FF),		TNS("fcom",F),		TNS("fcomp",F),
1067*7c478bd9Sstevel@tonic-gate /*  [0,4]  */	TNS("fsub",FF),		TNS("fsubr",FF),	TNS("fdiv",FF),		TNS("fdivr",FF),
1068*7c478bd9Sstevel@tonic-gate }, {
1069*7c478bd9Sstevel@tonic-gate /*  [1,0]  */	TNS("fld",F),		TNS("fxch",F),		TNS("fnop",NORM),	TNS("fstp",F),
1070*7c478bd9Sstevel@tonic-gate /*  [1,4]  */	INVALID,		INVALID,		INVALID,		INVALID,
1071*7c478bd9Sstevel@tonic-gate }, {
1072*7c478bd9Sstevel@tonic-gate /*  [2,0]  */	INVALID,		INVALID,		INVALID,		INVALID,
1073*7c478bd9Sstevel@tonic-gate /*  [2,4]  */	INVALID,		TNS("fucompp",NORM),	INVALID,		INVALID,
1074*7c478bd9Sstevel@tonic-gate }, {
1075*7c478bd9Sstevel@tonic-gate /*  [3,0]  */	INVALID,		INVALID,		INVALID,		INVALID,
1076*7c478bd9Sstevel@tonic-gate /*  [3,4]  */	INVALID,		INVALID,		INVALID,		INVALID,
1077*7c478bd9Sstevel@tonic-gate }, {
1078*7c478bd9Sstevel@tonic-gate /*  [4,0]  */	TNS("fadd",FF),		TNS("fmul",FF),		TNS("fcom",F),		TNS("fcomp",F),
1079*7c478bd9Sstevel@tonic-gate /*  [4,4]  */	TNS("fsub",FF),		TNS("fsubr",FF),	TNS("fdiv",FF),		TNS("fdivr",FF),
1080*7c478bd9Sstevel@tonic-gate }, {
1081*7c478bd9Sstevel@tonic-gate /*  [5,0]  */	TNS("ffree",F),		TNS("fxch",F),		TNS("fst",F),		TNS("fstp",F),
1082*7c478bd9Sstevel@tonic-gate /*  [5,4]  */	TNS("fucom",F),		TNS("fucomp",F),	INVALID,		INVALID,
1083*7c478bd9Sstevel@tonic-gate }, {
1084*7c478bd9Sstevel@tonic-gate /*  [6,0]  */	TNS("faddp",FF),	TNS("fmulp",FF),	TNS("fcomp",F),		TNS("fcompp",NORM),
1085*7c478bd9Sstevel@tonic-gate /*  [6,4]  */	TNS("fsubp",FF),	TNS("fsubrp",FF),	TNS("fdivp",FF),	TNS("fdivrp",FF),
1086*7c478bd9Sstevel@tonic-gate }, {
1087*7c478bd9Sstevel@tonic-gate /*  [7,0]  */	TNS("ffree",F),		TNS("fxch",F),		TNS("fstp",F),		TNS("fstp",F),
1088*7c478bd9Sstevel@tonic-gate /*  [7,4]  */	TNS("fnstsw",M),	TNS("fucomip",FFC),	TNS("fcomip",FFC),	INVALID,
1089*7c478bd9Sstevel@tonic-gate } };
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate const instable_t dis_opFP4[4][8] = {
1092*7c478bd9Sstevel@tonic-gate {
1093*7c478bd9Sstevel@tonic-gate /* bit pattern:	1101 1001 111x xxxx */
1094*7c478bd9Sstevel@tonic-gate /*  [0,0]  */	TNS("fchs",NORM),	TNS("fabs",NORM),	INVALID,		INVALID,
1095*7c478bd9Sstevel@tonic-gate /*  [0,4]  */	TNS("ftst",NORM),	TNS("fxam",NORM),	TNS("ftstp",NORM),	INVALID,
1096*7c478bd9Sstevel@tonic-gate }, {
1097*7c478bd9Sstevel@tonic-gate /*  [1,0]  */	TNS("fld1",NORM),	TNS("fldl2t",NORM),	TNS("fldl2e",NORM),	TNS("fldpi",NORM),
1098*7c478bd9Sstevel@tonic-gate /*  [1,4]  */	TNS("fldlg2",NORM),	TNS("fldln2",NORM),	TNS("fldz",NORM),	INVALID,
1099*7c478bd9Sstevel@tonic-gate }, {
1100*7c478bd9Sstevel@tonic-gate /*  [2,0]  */	TNS("f2xm1",NORM),	TNS("fyl2x",NORM),	TNS("fptan",NORM),	TNS("fpatan",NORM),
1101*7c478bd9Sstevel@tonic-gate /*  [2,4]  */	TNS("fxtract",NORM),	TNS("fprem1",NORM),	TNS("fdecstp",NORM),	TNS("fincstp",NORM),
1102*7c478bd9Sstevel@tonic-gate }, {
1103*7c478bd9Sstevel@tonic-gate /*  [3,0]  */	TNS("fprem",NORM),	TNS("fyl2xp1",NORM),	TNS("fsqrt",NORM),	TNS("fsincos",NORM),
1104*7c478bd9Sstevel@tonic-gate /*  [3,4]  */	TNS("frndint",NORM),	TNS("fscale",NORM),	TNS("fsin",NORM),	TNS("fcos",NORM),
1105*7c478bd9Sstevel@tonic-gate } };
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate const instable_t dis_opFP5[8] = {
1108*7c478bd9Sstevel@tonic-gate /* bit pattern:	1101 1011 111x xxxx */
1109*7c478bd9Sstevel@tonic-gate /*  [0]  */	TNS("feni",NORM),	TNS("fdisi",NORM),	TNS("fnclex",NORM),	TNS("fninit",NORM),
1110*7c478bd9Sstevel@tonic-gate /*  [4]  */	TNS("fsetpm",NORM),	TNS("frstpm",NORM),	INVALID,		INVALID,
1111*7c478bd9Sstevel@tonic-gate };
1112*7c478bd9Sstevel@tonic-gate 
1113*7c478bd9Sstevel@tonic-gate const instable_t dis_opFP6[8] = {
1114*7c478bd9Sstevel@tonic-gate /* bit pattern:	1101 1011 11yy yxxx */
1115*7c478bd9Sstevel@tonic-gate /*  [00]  */	TNS("fcmov.nb",FF),	TNS("fcmov.ne",FF),	TNS("fcmov.nbe",FF),	TNS("fcmov.nu",FF),
1116*7c478bd9Sstevel@tonic-gate /*  [04]  */	INVALID,		TNS("fucomi",F),	TNS("fcomi",F),		INVALID,
1117*7c478bd9Sstevel@tonic-gate };
1118*7c478bd9Sstevel@tonic-gate 
1119*7c478bd9Sstevel@tonic-gate const instable_t dis_opFP7[8] = {
1120*7c478bd9Sstevel@tonic-gate /* bit pattern:	1101 1010 11yy yxxx */
1121*7c478bd9Sstevel@tonic-gate /*  [00]  */	TNS("fcmov.b",FF),	TNS("fcmov.e",FF),	TNS("fcmov.be",FF),	TNS("fcmov.u",FF),
1122*7c478bd9Sstevel@tonic-gate /*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
1123*7c478bd9Sstevel@tonic-gate };
1124*7c478bd9Sstevel@tonic-gate 
1125*7c478bd9Sstevel@tonic-gate /*
1126*7c478bd9Sstevel@tonic-gate  *	Main decode table for the op codes.  The first two nibbles
1127*7c478bd9Sstevel@tonic-gate  *	will be used as an index into the table.  If there is a
1128*7c478bd9Sstevel@tonic-gate  *	a need to further decode an instruction, the array to be
1129*7c478bd9Sstevel@tonic-gate  *	referenced is indicated with the other two entries being
1130*7c478bd9Sstevel@tonic-gate  *	empty.
1131*7c478bd9Sstevel@tonic-gate  */
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate const instable_t dis_distable[16][16] = {
1134*7c478bd9Sstevel@tonic-gate {
1135*7c478bd9Sstevel@tonic-gate /* [0,0] */	TNS("addb",RMw),	TS("add",RMw),		TNS("addb",MRw),	TS("add",MRw),
1136*7c478bd9Sstevel@tonic-gate /* [0,4] */	TNS("addb",IA),		TS("add",IA),		TSx("push",SEG),	TSx("pop",SEG),
1137*7c478bd9Sstevel@tonic-gate /* [0,8] */	TNS("orb",RMw),		TS("or",RMw),		TNS("orb",MRw),		TS("or",MRw),
1138*7c478bd9Sstevel@tonic-gate /* [0,C] */	TNS("orb",IA),		TS("or",IA),		TSx("push",SEG),	IND(dis_op0F),
1139*7c478bd9Sstevel@tonic-gate }, {
1140*7c478bd9Sstevel@tonic-gate /* [1,0] */	TNS("adcb",RMw),	TS("adc",RMw),		TNS("adcb",MRw),	TS("adc",MRw),
1141*7c478bd9Sstevel@tonic-gate /* [1,4] */	TNS("adcb",IA),		TS("adc",IA),		TSx("push",SEG),	TSx("pop",SEG),
1142*7c478bd9Sstevel@tonic-gate /* [1,8] */	TNS("sbbb",RMw),	TS("sbb",RMw),		TNS("sbbb",MRw),	TS("sbb",MRw),
1143*7c478bd9Sstevel@tonic-gate /* [1,C] */	TNS("sbbb",IA),		TS("sbb",IA),		TSx("push",SEG),	TSx("pop",SEG),
1144*7c478bd9Sstevel@tonic-gate }, {
1145*7c478bd9Sstevel@tonic-gate /* [2,0] */	TNS("andb",RMw),	TS("and",RMw),		TNS("andb",MRw),	TS("and",MRw),
1146*7c478bd9Sstevel@tonic-gate /* [2,4] */	TNS("andb",IA),		TS("and",IA),		TNSx("%es:",OVERRIDE),	TNSx("daa",NORM),
1147*7c478bd9Sstevel@tonic-gate /* [2,8] */	TNS("subb",RMw),	TS("sub",RMw),		TNS("subb",MRw),	TS("sub",MRw),
1148*7c478bd9Sstevel@tonic-gate /* [2,C] */	TNS("subb",IA),		TS("sub",IA),		TNSx("%cs:",OVERRIDE),	TNSx("das",NORM),
1149*7c478bd9Sstevel@tonic-gate }, {
1150*7c478bd9Sstevel@tonic-gate /* [3,0] */	TNS("xorb",RMw),	TS("xor",RMw),		TNS("xorb",MRw),	TS("xor",MRw),
1151*7c478bd9Sstevel@tonic-gate /* [3,4] */	TNS("xorb",IA),		TS("xor",IA),		TNSx("%ss:",OVERRIDE),	TNSx("aaa",NORM),
1152*7c478bd9Sstevel@tonic-gate /* [3,8] */	TNS("cmpb",RMw),	TS("cmp",RMw),		TNS("cmpb",MRw),	TS("cmp",MRw),
1153*7c478bd9Sstevel@tonic-gate /* [3,C] */	TNS("cmpb",IA),		TS("cmp",IA),		TNSx("%ds:",OVERRIDE),	TNSx("aas",NORM),
1154*7c478bd9Sstevel@tonic-gate }, {
1155*7c478bd9Sstevel@tonic-gate /* [4,0] */	TSx("inc",R),		TSx("inc",R),		TSx("inc",R),		TSx("inc",R),
1156*7c478bd9Sstevel@tonic-gate /* [4,4] */	TSx("inc",R),		TSx("inc",R),		TSx("inc",R),		TSx("inc",R),
1157*7c478bd9Sstevel@tonic-gate /* [4,8] */	TSx("dec",R),		TSx("dec",R),		TSx("dec",R),		TSx("dec",R),
1158*7c478bd9Sstevel@tonic-gate /* [4,C] */	TSx("dec",R),		TSx("dec",R),		TSx("dec",R),		TSx("dec",R),
1159*7c478bd9Sstevel@tonic-gate }, {
1160*7c478bd9Sstevel@tonic-gate /* [5,0] */	TSp("push",R),		TSp("push",R),		TSp("push",R),		TSp("push",R),
1161*7c478bd9Sstevel@tonic-gate /* [5,4] */	TSp("push",R),		TSp("push",R),		TSp("push",R),		TSp("push",R),
1162*7c478bd9Sstevel@tonic-gate /* [5,8] */	TSp("pop",R),		TSp("pop",R),		TSp("pop",R),		TSp("pop",R),
1163*7c478bd9Sstevel@tonic-gate /* [5,C] */	TSp("pop",R),		TSp("pop",R),		TSp("pop",R),		TSp("pop",R),
1164*7c478bd9Sstevel@tonic-gate }, {
1165*7c478bd9Sstevel@tonic-gate /* [6,0] */	TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR),	TNS("arpl",RMw),
1166*7c478bd9Sstevel@tonic-gate /* [6,4] */	TNS("%fs:",OVERRIDE),	TNS("%gs:",OVERRIDE),	TNS("data16",DM),	TNS("addr16",AM),
1167*7c478bd9Sstevel@tonic-gate /* [6,8] */	TSp("push",I),		TS("imul",IMUL),	TSp("push",Ib),	TS("imul",IMUL),
1168*7c478bd9Sstevel@tonic-gate /* [6,C] */	TNSZ("insb",IMPLMEM,1),	TSZ("ins",IMPLMEM,4),	TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4),
1169*7c478bd9Sstevel@tonic-gate }, {
1170*7c478bd9Sstevel@tonic-gate /* [7,0] */	TNSy("jo",BD),		TNSy("jno",BD),		TNSy("jb",BD),		TNSy("jae",BD),
1171*7c478bd9Sstevel@tonic-gate /* [7,4] */	TNSy("je",BD),		TNSy("jne",BD),		TNSy("jbe",BD),		TNSy("ja",BD),
1172*7c478bd9Sstevel@tonic-gate /* [7,8] */	TNSy("js",BD),		TNSy("jns",BD),		TNSy("jp",BD),		TNSy("jnp",BD),
1173*7c478bd9Sstevel@tonic-gate /* [7,C] */	TNSy("jl",BD),		TNSy("jge",BD),		TNSy("jle",BD),		TNSy("jg",BD),
1174*7c478bd9Sstevel@tonic-gate }, {
1175*7c478bd9Sstevel@tonic-gate /* [8,0] */	IND(dis_op80),		IND(dis_op81),		INDx(dis_op82),		IND(dis_op83),
1176*7c478bd9Sstevel@tonic-gate /* [8,4] */	TNS("testb",RMw),	TS("test",RMw),		TNS("xchgb",RMw),	TS("xchg",RMw),
1177*7c478bd9Sstevel@tonic-gate /* [8,8] */	TNS("movb",RMw),	TS("mov",RMw),		TNS("movb",MRw),	TS("mov",MRw),
1178*7c478bd9Sstevel@tonic-gate /* [8,C] */	TNS("movw",SM),		TS("lea",MR),		TNS("movw",MS),		TSp("pop",M),
1179*7c478bd9Sstevel@tonic-gate }, {
1180*7c478bd9Sstevel@tonic-gate /* [9,0] */	TNS("nop",NORM),	TS("xchg",RA),		TS("xchg",RA),		TS("xchg",RA),
1181*7c478bd9Sstevel@tonic-gate /* [9,4] */	TS("xchg",RA),		TS("xchg",RA),		TS("xchg",RA),		TS("xchg",RA),
1182*7c478bd9Sstevel@tonic-gate /* [9,8] */	TNS("cXtX",CBW),	TNS("cXtX",CWD),	TNSx("lcall",SO),	TNS("fwait",NORM),
1183*7c478bd9Sstevel@tonic-gate /* [9,C] */	TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4),	TNSx("sahf",NORM),	TNSx("lahf",NORM),
1184*7c478bd9Sstevel@tonic-gate }, {
1185*7c478bd9Sstevel@tonic-gate /* [A,0] */	TNS("movb",OA),		TS("mov",OA),		TNS("movb",AO),		TS("mov",AO),
1186*7c478bd9Sstevel@tonic-gate /* [A,4] */	TNSZ("movsb",SD,1),	TS("movs",SD),		TNSZ("cmpsb",SD,1),	TS("cmps",SD),
1187*7c478bd9Sstevel@tonic-gate /* [A,8] */	TNS("testb",IA),	TS("test",IA),		TNS("stosb",AD),	TS("stos",AD),
1188*7c478bd9Sstevel@tonic-gate /* [A,C] */	TNS("lodsb",SA),	TS("lods",SA),		TNS("scasb",AD),	TS("scas",AD),
1189*7c478bd9Sstevel@tonic-gate }, {
1190*7c478bd9Sstevel@tonic-gate /* [B,0] */	TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),
1191*7c478bd9Sstevel@tonic-gate /* [B,4] */	TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),
1192*7c478bd9Sstevel@tonic-gate /* [B,8] */	TS("mov",IR),		TS("mov",IR),		TS("mov",IR),		TS("mov",IR),
1193*7c478bd9Sstevel@tonic-gate /* [B,C] */	TS("mov",IR),		TS("mov",IR),		TS("mov",IR),		TS("mov",IR),
1194*7c478bd9Sstevel@tonic-gate }, {
1195*7c478bd9Sstevel@tonic-gate /* [C,0] */	IND(dis_opC0),		IND(dis_opC1), 		TNSyp("ret",RET),	TNSyp("ret",NORM),
1196*7c478bd9Sstevel@tonic-gate /* [C,4] */	TNSx("les",MR),		TNSx("lds",MR),		TNS("movb",IMw),	TS("mov",IMw),
1197*7c478bd9Sstevel@tonic-gate /* [C,8] */	TNSyp("enter",ENTER),	TNSyp("leave",NORM),	TNS("lret",RET),	TNS("lret",NORM),
1198*7c478bd9Sstevel@tonic-gate /* [C,C] */	TNS("int",INT3),	TNS("int",INTx),	TNSx("into",NORM),	TNS("iret",NORM),
1199*7c478bd9Sstevel@tonic-gate }, {
1200*7c478bd9Sstevel@tonic-gate /* [D,0] */	IND(dis_opD0),		IND(dis_opD1),		IND(dis_opD2),		IND(dis_opD3),
1201*7c478bd9Sstevel@tonic-gate /* [D,4] */	TNSx("aam",U),		TNSx("aad",U),		TNSx("falc",NORM),	TNSZ("xlat",IMPLMEM,1),
1202*7c478bd9Sstevel@tonic-gate 
1203*7c478bd9Sstevel@tonic-gate /* 287 instructions.  Note that although the indirect field		*/
1204*7c478bd9Sstevel@tonic-gate /* indicates opFP1n2 for further decoding, this is not necessarily	*/
1205*7c478bd9Sstevel@tonic-gate /* the case since the opFP arrays are not partitioned according to key1	*/
1206*7c478bd9Sstevel@tonic-gate /* and key2.  opFP1n2 is given only to indicate that we haven't		*/
1207*7c478bd9Sstevel@tonic-gate /* finished decoding the instruction.					*/
1208*7c478bd9Sstevel@tonic-gate /* [D,8] */	IND(dis_opFP1n2),	IND(dis_opFP1n2),	IND(dis_opFP1n2),	IND(dis_opFP1n2),
1209*7c478bd9Sstevel@tonic-gate /* [D,C] */	IND(dis_opFP1n2),	IND(dis_opFP1n2),	IND(dis_opFP1n2),	IND(dis_opFP1n2),
1210*7c478bd9Sstevel@tonic-gate }, {
1211*7c478bd9Sstevel@tonic-gate /* [E,0] */	TNSy("loopnz",BD),	TNSy("loopz",BD),	TNSy("loop",BD),	TNSy("jcxz",BD),
1212*7c478bd9Sstevel@tonic-gate /* [E,4] */	TNS("inb",P),		TS("in",P),		TNS("outb",P),		TS("out",P),
1213*7c478bd9Sstevel@tonic-gate /* [E,8] */	TNSyp("call",D),	TNSy("jmp",D),		TNSx("ljmp",SO),		TNSy("jmp",BD),
1214*7c478bd9Sstevel@tonic-gate /* [E,C] */	TNS("inb",V),		TS("in",V),		TNS("outb",V),		TS("out",V),
1215*7c478bd9Sstevel@tonic-gate }, {
1216*7c478bd9Sstevel@tonic-gate /* [F,0] */	TNS("lock",LOCK),	TNS("icebp", NORM),	TNS("repnz",PREFIX),	TNS("repz",PREFIX),
1217*7c478bd9Sstevel@tonic-gate /* [F,4] */	TNS("hlt",NORM),	TNS("cmc",NORM),	IND(dis_opF6),		IND(dis_opF7),
1218*7c478bd9Sstevel@tonic-gate /* [F,8] */	TNS("clc",NORM),	TNS("stc",NORM),	TNS("cli",NORM),	TNS("sti",NORM),
1219*7c478bd9Sstevel@tonic-gate /* [F,C] */	TNS("cld",NORM),	TNS("std",NORM),	IND(dis_opFE),		IND(dis_opFF),
1220*7c478bd9Sstevel@tonic-gate } };
1221*7c478bd9Sstevel@tonic-gate 
1222*7c478bd9Sstevel@tonic-gate /* END CSTYLED */
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate /*
1225*7c478bd9Sstevel@tonic-gate  * common functions to decode and disassemble an x86 or amd64 instruction
1226*7c478bd9Sstevel@tonic-gate  */
1227*7c478bd9Sstevel@tonic-gate 
1228*7c478bd9Sstevel@tonic-gate /*
1229*7c478bd9Sstevel@tonic-gate  * These are the individual fields of a REX prefix. Note that a REX
1230*7c478bd9Sstevel@tonic-gate  * prefix with none of these set is still needed to:
1231*7c478bd9Sstevel@tonic-gate  *	- use the MOVSXD (sign extend 32 to 64 bits) instruction
1232*7c478bd9Sstevel@tonic-gate  *	- access the %sil, %dil, %bpl, %spl registers
1233*7c478bd9Sstevel@tonic-gate  */
1234*7c478bd9Sstevel@tonic-gate #define	REX_W 0x08	/* 64 bit operand size when set */
1235*7c478bd9Sstevel@tonic-gate #define	REX_R 0x04	/* high order bit extension of ModRM reg field */
1236*7c478bd9Sstevel@tonic-gate #define	REX_X 0x02	/* high order bit extension of SIB index field */
1237*7c478bd9Sstevel@tonic-gate #define	REX_B 0x01	/* extends ModRM r_m, SIB base, or opcode reg */
1238*7c478bd9Sstevel@tonic-gate 
1239*7c478bd9Sstevel@tonic-gate static uint_t opnd_size;	/* SIZE16, SIZE32 or SIZE64 */
1240*7c478bd9Sstevel@tonic-gate static uint_t addr_size;	/* SIZE16, SIZE32 or SIZE64 */
1241*7c478bd9Sstevel@tonic-gate 
1242*7c478bd9Sstevel@tonic-gate /*
1243*7c478bd9Sstevel@tonic-gate  * Even in 64 bit mode, usually only 4 byte immediate operands are supported.
1244*7c478bd9Sstevel@tonic-gate  */
1245*7c478bd9Sstevel@tonic-gate static int isize[] = {1, 2, 4, 4};
1246*7c478bd9Sstevel@tonic-gate static int isize64[] = {1, 2, 4, 8};
1247*7c478bd9Sstevel@tonic-gate 
1248*7c478bd9Sstevel@tonic-gate /*
1249*7c478bd9Sstevel@tonic-gate  * Just a bunch of useful macros.
1250*7c478bd9Sstevel@tonic-gate  */
1251*7c478bd9Sstevel@tonic-gate #define	WBIT(x)	(x & 0x1)		/* to get w bit	*/
1252*7c478bd9Sstevel@tonic-gate #define	REGNO(x) (x & 0x7)		/* to get 3 bit register */
1253*7c478bd9Sstevel@tonic-gate #define	VBIT(x)	((x)>>1 & 0x1)		/* to get 'v' bit */
1254*7c478bd9Sstevel@tonic-gate #define	OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1)
1255*7c478bd9Sstevel@tonic-gate #define	OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1)
1256*7c478bd9Sstevel@tonic-gate 
1257*7c478bd9Sstevel@tonic-gate #define	REG_ONLY 3	/* mode to indicate a register operand (not memory) */
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate #define	BYTE_OPND	0	/* w-bit value indicating byte register */
1260*7c478bd9Sstevel@tonic-gate #define	LONG_OPND	1	/* w-bit value indicating opnd_size register */
1261*7c478bd9Sstevel@tonic-gate #define	MM_OPND		2	/* "value" used to indicate a mmx reg */
1262*7c478bd9Sstevel@tonic-gate #define	XMM_OPND	3	/* "value" used to indicate a xmm reg */
1263*7c478bd9Sstevel@tonic-gate #define	SEG_OPND	4	/* "value" used to indicate a segment reg */
1264*7c478bd9Sstevel@tonic-gate #define	CONTROL_OPND	5	/* "value" used to indicate a control reg */
1265*7c478bd9Sstevel@tonic-gate #define	DEBUG_OPND	6	/* "value" used to indicate a debug reg */
1266*7c478bd9Sstevel@tonic-gate #define	TEST_OPND	7	/* "value" used to indicate a test reg */
1267*7c478bd9Sstevel@tonic-gate #define	WORD_OPND	8	/* w-bit value indicating word size reg */
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate /*
1270*7c478bd9Sstevel@tonic-gate  * Get the next byte and separate the op code into the high and low nibbles.
1271*7c478bd9Sstevel@tonic-gate  */
1272*7c478bd9Sstevel@tonic-gate static int
1273*7c478bd9Sstevel@tonic-gate dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low)
1274*7c478bd9Sstevel@tonic-gate {
1275*7c478bd9Sstevel@tonic-gate 	int byte;
1276*7c478bd9Sstevel@tonic-gate 
1277*7c478bd9Sstevel@tonic-gate 	/*
1278*7c478bd9Sstevel@tonic-gate 	 * x86 instructions have a maximum length of 15 bytes.  Bail out if
1279*7c478bd9Sstevel@tonic-gate 	 * we try to read more.
1280*7c478bd9Sstevel@tonic-gate 	 */
1281*7c478bd9Sstevel@tonic-gate 	if (x->d86_len >= 15)
1282*7c478bd9Sstevel@tonic-gate 		return (x->d86_error = 1);
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate 	if (x->d86_error)
1285*7c478bd9Sstevel@tonic-gate 		return (1);
1286*7c478bd9Sstevel@tonic-gate 	byte = x->d86_get_byte(x->d86_data);
1287*7c478bd9Sstevel@tonic-gate 	if (byte < 0)
1288*7c478bd9Sstevel@tonic-gate 		return (x->d86_error = 1);
1289*7c478bd9Sstevel@tonic-gate 	x->d86_bytes[x->d86_len++] = byte;
1290*7c478bd9Sstevel@tonic-gate 	*low = byte & 0xf;		/* ----xxxx low 4 bits */
1291*7c478bd9Sstevel@tonic-gate 	*high = byte >> 4 & 0xf;	/* xxxx---- bits 7 to 4 */
1292*7c478bd9Sstevel@tonic-gate 	return (0);
1293*7c478bd9Sstevel@tonic-gate }
1294*7c478bd9Sstevel@tonic-gate 
1295*7c478bd9Sstevel@tonic-gate /*
1296*7c478bd9Sstevel@tonic-gate  * Get and decode an SIB (scaled index base) byte
1297*7c478bd9Sstevel@tonic-gate  */
1298*7c478bd9Sstevel@tonic-gate static void
1299*7c478bd9Sstevel@tonic-gate dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base)
1300*7c478bd9Sstevel@tonic-gate {
1301*7c478bd9Sstevel@tonic-gate 	int byte;
1302*7c478bd9Sstevel@tonic-gate 
1303*7c478bd9Sstevel@tonic-gate 	if (x->d86_error)
1304*7c478bd9Sstevel@tonic-gate 		return;
1305*7c478bd9Sstevel@tonic-gate 
1306*7c478bd9Sstevel@tonic-gate 	byte = x->d86_get_byte(x->d86_data);
1307*7c478bd9Sstevel@tonic-gate 	if (byte < 0) {
1308*7c478bd9Sstevel@tonic-gate 		x->d86_error = 1;
1309*7c478bd9Sstevel@tonic-gate 		return;
1310*7c478bd9Sstevel@tonic-gate 	}
1311*7c478bd9Sstevel@tonic-gate 	x->d86_bytes[x->d86_len++] = byte;
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 	*base = byte & 0x7;
1314*7c478bd9Sstevel@tonic-gate 	*index = (byte >> 3) & 0x7;
1315*7c478bd9Sstevel@tonic-gate 	*ss = (byte >> 6) & 0x3;
1316*7c478bd9Sstevel@tonic-gate }
1317*7c478bd9Sstevel@tonic-gate 
1318*7c478bd9Sstevel@tonic-gate /*
1319*7c478bd9Sstevel@tonic-gate  * Get the byte following the op code and separate it into the
1320*7c478bd9Sstevel@tonic-gate  * mode, register, and r/m fields.
1321*7c478bd9Sstevel@tonic-gate  */
1322*7c478bd9Sstevel@tonic-gate static void
1323*7c478bd9Sstevel@tonic-gate dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m)
1324*7c478bd9Sstevel@tonic-gate {
1325*7c478bd9Sstevel@tonic-gate 	if (x->d86_got_modrm == 0) {
1326*7c478bd9Sstevel@tonic-gate 		if (x->d86_rmindex == -1)
1327*7c478bd9Sstevel@tonic-gate 			x->d86_rmindex = x->d86_len;
1328*7c478bd9Sstevel@tonic-gate 		dtrace_get_SIB(x, mode, reg, r_m);
1329*7c478bd9Sstevel@tonic-gate 		x->d86_got_modrm = 1;
1330*7c478bd9Sstevel@tonic-gate 	}
1331*7c478bd9Sstevel@tonic-gate }
1332*7c478bd9Sstevel@tonic-gate 
1333*7c478bd9Sstevel@tonic-gate /*
1334*7c478bd9Sstevel@tonic-gate  * Adjust register selection based on any REX prefix bits present.
1335*7c478bd9Sstevel@tonic-gate  */
1336*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1337*7c478bd9Sstevel@tonic-gate static void
1338*7c478bd9Sstevel@tonic-gate dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m)
1339*7c478bd9Sstevel@tonic-gate {
1340*7c478bd9Sstevel@tonic-gate 	if (reg != NULL && r_m == NULL) {
1341*7c478bd9Sstevel@tonic-gate 		if (rex_prefix & REX_B)
1342*7c478bd9Sstevel@tonic-gate 			*reg += 8;
1343*7c478bd9Sstevel@tonic-gate 	} else {
1344*7c478bd9Sstevel@tonic-gate 		if (reg != NULL && (REX_R & rex_prefix) != 0)
1345*7c478bd9Sstevel@tonic-gate 			*reg += 8;
1346*7c478bd9Sstevel@tonic-gate 		if (r_m != NULL && (REX_B & rex_prefix) != 0)
1347*7c478bd9Sstevel@tonic-gate 			*r_m += 8;
1348*7c478bd9Sstevel@tonic-gate 	}
1349*7c478bd9Sstevel@tonic-gate }
1350*7c478bd9Sstevel@tonic-gate 
1351*7c478bd9Sstevel@tonic-gate /*
1352*7c478bd9Sstevel@tonic-gate  * Get an immediate operand of the given size, with sign extension.
1353*7c478bd9Sstevel@tonic-gate  */
1354*7c478bd9Sstevel@tonic-gate static void
1355*7c478bd9Sstevel@tonic-gate dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex)
1356*7c478bd9Sstevel@tonic-gate {
1357*7c478bd9Sstevel@tonic-gate 	int i;
1358*7c478bd9Sstevel@tonic-gate 	int byte;
1359*7c478bd9Sstevel@tonic-gate 	int valsize;
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 	if (x->d86_numopnds < opindex + 1)
1362*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = opindex + 1;
1363*7c478bd9Sstevel@tonic-gate 
1364*7c478bd9Sstevel@tonic-gate 	switch (wbit) {
1365*7c478bd9Sstevel@tonic-gate 	case BYTE_OPND:
1366*7c478bd9Sstevel@tonic-gate 		valsize = 1;
1367*7c478bd9Sstevel@tonic-gate 		break;
1368*7c478bd9Sstevel@tonic-gate 	case LONG_OPND:
1369*7c478bd9Sstevel@tonic-gate 		if (x->d86_opnd_size == SIZE16)
1370*7c478bd9Sstevel@tonic-gate 			valsize = 2;
1371*7c478bd9Sstevel@tonic-gate 		else if (x->d86_opnd_size == SIZE32)
1372*7c478bd9Sstevel@tonic-gate 			valsize = 4;
1373*7c478bd9Sstevel@tonic-gate 		else
1374*7c478bd9Sstevel@tonic-gate 			valsize = 8;
1375*7c478bd9Sstevel@tonic-gate 		break;
1376*7c478bd9Sstevel@tonic-gate 	case MM_OPND:
1377*7c478bd9Sstevel@tonic-gate 	case XMM_OPND:
1378*7c478bd9Sstevel@tonic-gate 	case SEG_OPND:
1379*7c478bd9Sstevel@tonic-gate 	case CONTROL_OPND:
1380*7c478bd9Sstevel@tonic-gate 	case DEBUG_OPND:
1381*7c478bd9Sstevel@tonic-gate 	case TEST_OPND:
1382*7c478bd9Sstevel@tonic-gate 		valsize = size;
1383*7c478bd9Sstevel@tonic-gate 		break;
1384*7c478bd9Sstevel@tonic-gate 	case WORD_OPND:
1385*7c478bd9Sstevel@tonic-gate 		valsize = 2;
1386*7c478bd9Sstevel@tonic-gate 		break;
1387*7c478bd9Sstevel@tonic-gate 	}
1388*7c478bd9Sstevel@tonic-gate 	if (valsize < size)
1389*7c478bd9Sstevel@tonic-gate 		valsize = size;
1390*7c478bd9Sstevel@tonic-gate 
1391*7c478bd9Sstevel@tonic-gate 	if (x->d86_error)
1392*7c478bd9Sstevel@tonic-gate 		return;
1393*7c478bd9Sstevel@tonic-gate 	x->d86_opnd[opindex].d86_value = 0;
1394*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < size; ++i) {
1395*7c478bd9Sstevel@tonic-gate 		byte = x->d86_get_byte(x->d86_data);
1396*7c478bd9Sstevel@tonic-gate 		if (byte < 0) {
1397*7c478bd9Sstevel@tonic-gate 			x->d86_error = 1;
1398*7c478bd9Sstevel@tonic-gate 			return;
1399*7c478bd9Sstevel@tonic-gate 		}
1400*7c478bd9Sstevel@tonic-gate 		x->d86_bytes[x->d86_len++] = byte;
1401*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8);
1402*7c478bd9Sstevel@tonic-gate 	}
1403*7c478bd9Sstevel@tonic-gate 	/* Do sign extension */
1404*7c478bd9Sstevel@tonic-gate 	if (x->d86_bytes[x->d86_len - 1] & 0x80) {
1405*7c478bd9Sstevel@tonic-gate 		for (; i < valsize; i++)
1406*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[opindex].d86_value |=
1407*7c478bd9Sstevel@tonic-gate 			    (uint64_t)0xff << (i* 8);
1408*7c478bd9Sstevel@tonic-gate 	}
1409*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1410*7c478bd9Sstevel@tonic-gate 	x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
1411*7c478bd9Sstevel@tonic-gate 	x->d86_opnd[opindex].d86_value_size = valsize;
1412*7c478bd9Sstevel@tonic-gate 	x->d86_imm_bytes += size;
1413*7c478bd9Sstevel@tonic-gate #endif
1414*7c478bd9Sstevel@tonic-gate }
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate /*
1417*7c478bd9Sstevel@tonic-gate  * Get an ip relative operand of the given size, with sign extension.
1418*7c478bd9Sstevel@tonic-gate  */
1419*7c478bd9Sstevel@tonic-gate static void
1420*7c478bd9Sstevel@tonic-gate dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex)
1421*7c478bd9Sstevel@tonic-gate {
1422*7c478bd9Sstevel@tonic-gate 	dtrace_imm_opnd(x, wbit, size, opindex);
1423*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1424*7c478bd9Sstevel@tonic-gate 	x->d86_opnd[opindex].d86_mode = MODE_IPREL;
1425*7c478bd9Sstevel@tonic-gate #endif
1426*7c478bd9Sstevel@tonic-gate }
1427*7c478bd9Sstevel@tonic-gate 
1428*7c478bd9Sstevel@tonic-gate /*
1429*7c478bd9Sstevel@tonic-gate  * Check to see if there is a segment override prefix pending.
1430*7c478bd9Sstevel@tonic-gate  * If so, print it in the current 'operand' location and set
1431*7c478bd9Sstevel@tonic-gate  * the override flag back to false.
1432*7c478bd9Sstevel@tonic-gate  */
1433*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1434*7c478bd9Sstevel@tonic-gate static void
1435*7c478bd9Sstevel@tonic-gate dtrace_check_override(dis86_t *x, int opindex)
1436*7c478bd9Sstevel@tonic-gate {
1437*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1438*7c478bd9Sstevel@tonic-gate 	if (x->d86_seg_prefix) {
1439*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_opnd[opindex].d86_prefix,
1440*7c478bd9Sstevel@tonic-gate 		    x->d86_seg_prefix, PFIXLEN);
1441*7c478bd9Sstevel@tonic-gate 	}
1442*7c478bd9Sstevel@tonic-gate #endif
1443*7c478bd9Sstevel@tonic-gate 	x->d86_seg_prefix = NULL;
1444*7c478bd9Sstevel@tonic-gate }
1445*7c478bd9Sstevel@tonic-gate 
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate /*
1448*7c478bd9Sstevel@tonic-gate  * Process a single instruction Register or Memory operand.
1449*7c478bd9Sstevel@tonic-gate  *
1450*7c478bd9Sstevel@tonic-gate  * mode = addressing mode from ModRM byte
1451*7c478bd9Sstevel@tonic-gate  * r_m = r_m (or reg if mode == 3) field from ModRM byte
1452*7c478bd9Sstevel@tonic-gate  * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use.
1453*7c478bd9Sstevel@tonic-gate  * o = index of operand that we are processing (0, 1 or 2)
1454*7c478bd9Sstevel@tonic-gate  *
1455*7c478bd9Sstevel@tonic-gate  * the value of reg or r_m must have already been adjusted for any REX prefix.
1456*7c478bd9Sstevel@tonic-gate  */
1457*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1458*7c478bd9Sstevel@tonic-gate static void
1459*7c478bd9Sstevel@tonic-gate dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex)
1460*7c478bd9Sstevel@tonic-gate {
1461*7c478bd9Sstevel@tonic-gate 	int have_SIB = 0;	/* flag presence of scale-index-byte */
1462*7c478bd9Sstevel@tonic-gate 	uint_t ss;		/* scale-factor from opcode */
1463*7c478bd9Sstevel@tonic-gate 	uint_t index;		/* index register number */
1464*7c478bd9Sstevel@tonic-gate 	uint_t base;		/* base register number */
1465*7c478bd9Sstevel@tonic-gate 	int dispsize;   	/* size of displacement in bytes */
1466*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1467*7c478bd9Sstevel@tonic-gate 	char *opnd = x->d86_opnd[opindex].d86_opnd;
1468*7c478bd9Sstevel@tonic-gate #endif
1469*7c478bd9Sstevel@tonic-gate 
1470*7c478bd9Sstevel@tonic-gate 	if (x->d86_numopnds < opindex + 1)
1471*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = opindex + 1;
1472*7c478bd9Sstevel@tonic-gate 
1473*7c478bd9Sstevel@tonic-gate 	if (x->d86_error)
1474*7c478bd9Sstevel@tonic-gate 		return;
1475*7c478bd9Sstevel@tonic-gate 
1476*7c478bd9Sstevel@tonic-gate 	/*
1477*7c478bd9Sstevel@tonic-gate 	 * first handle a simple register
1478*7c478bd9Sstevel@tonic-gate 	 */
1479*7c478bd9Sstevel@tonic-gate 	if (mode == REG_ONLY) {
1480*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1481*7c478bd9Sstevel@tonic-gate 		switch (wbit) {
1482*7c478bd9Sstevel@tonic-gate 		case MM_OPND:
1483*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_MMREG[r_m], OPLEN);
1484*7c478bd9Sstevel@tonic-gate 			break;
1485*7c478bd9Sstevel@tonic-gate 		case XMM_OPND:
1486*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_XMMREG[r_m], OPLEN);
1487*7c478bd9Sstevel@tonic-gate 			break;
1488*7c478bd9Sstevel@tonic-gate 		case SEG_OPND:
1489*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_SEGREG[r_m], OPLEN);
1490*7c478bd9Sstevel@tonic-gate 			break;
1491*7c478bd9Sstevel@tonic-gate 		case CONTROL_OPND:
1492*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_CONTROLREG[r_m], OPLEN);
1493*7c478bd9Sstevel@tonic-gate 			break;
1494*7c478bd9Sstevel@tonic-gate 		case DEBUG_OPND:
1495*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_DEBUGREG[r_m], OPLEN);
1496*7c478bd9Sstevel@tonic-gate 			break;
1497*7c478bd9Sstevel@tonic-gate 		case TEST_OPND:
1498*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_TESTREG[r_m], OPLEN);
1499*7c478bd9Sstevel@tonic-gate 			break;
1500*7c478bd9Sstevel@tonic-gate 		case BYTE_OPND:
1501*7c478bd9Sstevel@tonic-gate 			if (x->d86_rex_prefix == 0)
1502*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_REG8[r_m], OPLEN);
1503*7c478bd9Sstevel@tonic-gate 			else
1504*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_REG8_REX[r_m], OPLEN);
1505*7c478bd9Sstevel@tonic-gate 			break;
1506*7c478bd9Sstevel@tonic-gate 		case WORD_OPND:
1507*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_REG16[r_m], OPLEN);
1508*7c478bd9Sstevel@tonic-gate 			break;
1509*7c478bd9Sstevel@tonic-gate 		case LONG_OPND:
1510*7c478bd9Sstevel@tonic-gate 			if (x->d86_opnd_size == SIZE16)
1511*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_REG16[r_m], OPLEN);
1512*7c478bd9Sstevel@tonic-gate 			else if (x->d86_opnd_size == SIZE32)
1513*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_REG32[r_m], OPLEN);
1514*7c478bd9Sstevel@tonic-gate 			else
1515*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_REG64[r_m], OPLEN);
1516*7c478bd9Sstevel@tonic-gate 			break;
1517*7c478bd9Sstevel@tonic-gate 		}
1518*7c478bd9Sstevel@tonic-gate #endif /* DIS_TEXT */
1519*7c478bd9Sstevel@tonic-gate 		return;
1520*7c478bd9Sstevel@tonic-gate 	}
1521*7c478bd9Sstevel@tonic-gate 
1522*7c478bd9Sstevel@tonic-gate 	/*
1523*7c478bd9Sstevel@tonic-gate 	 * if symbolic representation, skip override prefix, if any
1524*7c478bd9Sstevel@tonic-gate 	 */
1525*7c478bd9Sstevel@tonic-gate 	dtrace_check_override(x, opindex);
1526*7c478bd9Sstevel@tonic-gate 
1527*7c478bd9Sstevel@tonic-gate 	/*
1528*7c478bd9Sstevel@tonic-gate 	 * Handle 16 bit memory references first, since they decode
1529*7c478bd9Sstevel@tonic-gate 	 * the mode values more simply.
1530*7c478bd9Sstevel@tonic-gate 	 * mode 1 is r_m + 8 bit displacement
1531*7c478bd9Sstevel@tonic-gate 	 * mode 2 is r_m + 16 bit displacement
1532*7c478bd9Sstevel@tonic-gate 	 * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp
1533*7c478bd9Sstevel@tonic-gate 	 */
1534*7c478bd9Sstevel@tonic-gate 	if (x->d86_addr_size == SIZE16) {
1535*7c478bd9Sstevel@tonic-gate 		if ((mode == 0 && r_m == 6) || mode == 2)
1536*7c478bd9Sstevel@tonic-gate 			dtrace_imm_opnd(x, WORD_OPND, 2, opindex);
1537*7c478bd9Sstevel@tonic-gate 		else if (mode == 1)
1538*7c478bd9Sstevel@tonic-gate 			dtrace_imm_opnd(x, BYTE_OPND, 1, opindex);
1539*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1540*7c478bd9Sstevel@tonic-gate 		if (mode == 0 && r_m == 6)
1541*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
1542*7c478bd9Sstevel@tonic-gate 		else if (mode == 0)
1543*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[opindex].d86_mode = MODE_NONE;
1544*7c478bd9Sstevel@tonic-gate 		else
1545*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
1546*7c478bd9Sstevel@tonic-gate 		strlcat(opnd, dis_addr16[mode][r_m], OPLEN);
1547*7c478bd9Sstevel@tonic-gate #endif
1548*7c478bd9Sstevel@tonic-gate 		return;
1549*7c478bd9Sstevel@tonic-gate 	}
1550*7c478bd9Sstevel@tonic-gate 
1551*7c478bd9Sstevel@tonic-gate 	/*
1552*7c478bd9Sstevel@tonic-gate 	 * 32 and 64 bit addressing modes are more complex since they
1553*7c478bd9Sstevel@tonic-gate 	 * can involve an SIB (scaled index and base) byte to decode.
1554*7c478bd9Sstevel@tonic-gate 	 */
1555*7c478bd9Sstevel@tonic-gate 	if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) {
1556*7c478bd9Sstevel@tonic-gate 		have_SIB = 1;
1557*7c478bd9Sstevel@tonic-gate 		dtrace_get_SIB(x, &ss, &index, &base);
1558*7c478bd9Sstevel@tonic-gate 		if (x->d86_error)
1559*7c478bd9Sstevel@tonic-gate 			return;
1560*7c478bd9Sstevel@tonic-gate 		if (base != 5 || mode != 0)
1561*7c478bd9Sstevel@tonic-gate 			if (x->d86_rex_prefix & REX_B)
1562*7c478bd9Sstevel@tonic-gate 				base += 8;
1563*7c478bd9Sstevel@tonic-gate 		if (x->d86_rex_prefix & REX_X)
1564*7c478bd9Sstevel@tonic-gate 			index += 8;
1565*7c478bd9Sstevel@tonic-gate 	} else {
1566*7c478bd9Sstevel@tonic-gate 		base = r_m;
1567*7c478bd9Sstevel@tonic-gate 	}
1568*7c478bd9Sstevel@tonic-gate 
1569*7c478bd9Sstevel@tonic-gate 	/*
1570*7c478bd9Sstevel@tonic-gate 	 * Compute the displacement size and get its bytes
1571*7c478bd9Sstevel@tonic-gate 	 */
1572*7c478bd9Sstevel@tonic-gate 	dispsize = 0;
1573*7c478bd9Sstevel@tonic-gate 
1574*7c478bd9Sstevel@tonic-gate 	if (mode == 1)
1575*7c478bd9Sstevel@tonic-gate 		dispsize = 1;
1576*7c478bd9Sstevel@tonic-gate 	else if (mode == 2)
1577*7c478bd9Sstevel@tonic-gate 		dispsize = 4;
1578*7c478bd9Sstevel@tonic-gate 	else if ((r_m & 7) == EBP_REGNO ||
1579*7c478bd9Sstevel@tonic-gate 	    (have_SIB && (base & 7) == EBP_REGNO))
1580*7c478bd9Sstevel@tonic-gate 		dispsize = 4;
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate 	if (dispsize > 0) {
1583*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND,
1584*7c478bd9Sstevel@tonic-gate 		    dispsize, opindex);
1585*7c478bd9Sstevel@tonic-gate 		if (x->d86_error)
1586*7c478bd9Sstevel@tonic-gate 			return;
1587*7c478bd9Sstevel@tonic-gate 	}
1588*7c478bd9Sstevel@tonic-gate 
1589*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1590*7c478bd9Sstevel@tonic-gate 	if (dispsize > 0)
1591*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
1592*7c478bd9Sstevel@tonic-gate 
1593*7c478bd9Sstevel@tonic-gate 	if (have_SIB == 0) {
1594*7c478bd9Sstevel@tonic-gate 		if (x->d86_mode == SIZE32) {
1595*7c478bd9Sstevel@tonic-gate 			if (mode == 0)
1596*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_addr32_mode0[r_m],
1597*7c478bd9Sstevel@tonic-gate 				    OPLEN);
1598*7c478bd9Sstevel@tonic-gate 			else
1599*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_addr32_mode12[r_m],
1600*7c478bd9Sstevel@tonic-gate 				    OPLEN);
1601*7c478bd9Sstevel@tonic-gate 		} else {
1602*7c478bd9Sstevel@tonic-gate 			if (mode == 0)
1603*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_addr64_mode0[r_m],
1604*7c478bd9Sstevel@tonic-gate 				    OPLEN);
1605*7c478bd9Sstevel@tonic-gate 			else
1606*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, dis_addr64_mode12[r_m],
1607*7c478bd9Sstevel@tonic-gate 				    OPLEN);
1608*7c478bd9Sstevel@tonic-gate 		}
1609*7c478bd9Sstevel@tonic-gate 	} else {
1610*7c478bd9Sstevel@tonic-gate 		uint_t need_paren = 0;
1611*7c478bd9Sstevel@tonic-gate 		char **regs;
1612*7c478bd9Sstevel@tonic-gate 		if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */
1613*7c478bd9Sstevel@tonic-gate 			regs = (char **)dis_REG32;
1614*7c478bd9Sstevel@tonic-gate 		else
1615*7c478bd9Sstevel@tonic-gate 			regs = (char **)dis_REG64;
1616*7c478bd9Sstevel@tonic-gate 
1617*7c478bd9Sstevel@tonic-gate 		/*
1618*7c478bd9Sstevel@tonic-gate 		 * print the base (if any)
1619*7c478bd9Sstevel@tonic-gate 		 */
1620*7c478bd9Sstevel@tonic-gate 		if (base == EBP_REGNO && mode == 0) {
1621*7c478bd9Sstevel@tonic-gate 			if (index != ESP_REGNO) {
1622*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, "(", OPLEN);
1623*7c478bd9Sstevel@tonic-gate 				need_paren = 1;
1624*7c478bd9Sstevel@tonic-gate 			}
1625*7c478bd9Sstevel@tonic-gate 		} else {
1626*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, "(", OPLEN);
1627*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, regs[base], OPLEN);
1628*7c478bd9Sstevel@tonic-gate 			need_paren = 1;
1629*7c478bd9Sstevel@tonic-gate 		}
1630*7c478bd9Sstevel@tonic-gate 
1631*7c478bd9Sstevel@tonic-gate 		/*
1632*7c478bd9Sstevel@tonic-gate 		 * print the index (if any)
1633*7c478bd9Sstevel@tonic-gate 		 */
1634*7c478bd9Sstevel@tonic-gate 		if (index != ESP_REGNO) {
1635*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, ",", OPLEN);
1636*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, regs[index], OPLEN);
1637*7c478bd9Sstevel@tonic-gate 			strlcat(opnd, dis_scale_factor[ss], OPLEN);
1638*7c478bd9Sstevel@tonic-gate 		} else
1639*7c478bd9Sstevel@tonic-gate 			if (need_paren)
1640*7c478bd9Sstevel@tonic-gate 				strlcat(opnd, ")", OPLEN);
1641*7c478bd9Sstevel@tonic-gate 	}
1642*7c478bd9Sstevel@tonic-gate #endif
1643*7c478bd9Sstevel@tonic-gate }
1644*7c478bd9Sstevel@tonic-gate 
1645*7c478bd9Sstevel@tonic-gate /*
1646*7c478bd9Sstevel@tonic-gate  * Operand sequence for standard instruction involving one register
1647*7c478bd9Sstevel@tonic-gate  * and one register/memory operand.
1648*7c478bd9Sstevel@tonic-gate  * wbit indicates a byte(0) or opnd_size(1) operation
1649*7c478bd9Sstevel@tonic-gate  * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r")
1650*7c478bd9Sstevel@tonic-gate  */
1651*7c478bd9Sstevel@tonic-gate #define	STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit)  {	\
1652*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);			\
1653*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);	\
1654*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, vbit);		\
1655*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit);	\
1656*7c478bd9Sstevel@tonic-gate }
1657*7c478bd9Sstevel@tonic-gate 
1658*7c478bd9Sstevel@tonic-gate /*
1659*7c478bd9Sstevel@tonic-gate  * Similar to above, but allows for the two operands to be of different
1660*7c478bd9Sstevel@tonic-gate  * classes (ie. wbit).
1661*7c478bd9Sstevel@tonic-gate  *	wbit is for the r_m operand
1662*7c478bd9Sstevel@tonic-gate  *	w2 is for the reg operand
1663*7c478bd9Sstevel@tonic-gate  */
1664*7c478bd9Sstevel@tonic-gate #define	MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit)	{	\
1665*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);			\
1666*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);	\
1667*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, vbit);		\
1668*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit);	\
1669*7c478bd9Sstevel@tonic-gate }
1670*7c478bd9Sstevel@tonic-gate 
1671*7c478bd9Sstevel@tonic-gate /*
1672*7c478bd9Sstevel@tonic-gate  * Similar, but for 2 operands plus an immediate.
1673*7c478bd9Sstevel@tonic-gate  */
1674*7c478bd9Sstevel@tonic-gate #define	THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \
1675*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);			\
1676*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);	\
1677*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 1);		\
1678*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, w2, 2);		\
1679*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, immsize, 0);			\
1680*7c478bd9Sstevel@tonic-gate }
1681*7c478bd9Sstevel@tonic-gate 
1682*7c478bd9Sstevel@tonic-gate /*
1683*7c478bd9Sstevel@tonic-gate  * Dissassemble a single x86 or amd64 instruction.
1684*7c478bd9Sstevel@tonic-gate  *
1685*7c478bd9Sstevel@tonic-gate  * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64)
1686*7c478bd9Sstevel@tonic-gate  * for interpreting instructions.
1687*7c478bd9Sstevel@tonic-gate  *
1688*7c478bd9Sstevel@tonic-gate  * returns non-zero for bad opcode
1689*7c478bd9Sstevel@tonic-gate  */
1690*7c478bd9Sstevel@tonic-gate int
1691*7c478bd9Sstevel@tonic-gate dtrace_disx86(dis86_t *x, uint_t cpu_mode)
1692*7c478bd9Sstevel@tonic-gate {
1693*7c478bd9Sstevel@tonic-gate 	instable_t *dp;		/* decode table being used */
1694*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1695*7c478bd9Sstevel@tonic-gate 	uint_t i;
1696*7c478bd9Sstevel@tonic-gate #endif
1697*7c478bd9Sstevel@tonic-gate #ifdef DIS_MEM
1698*7c478bd9Sstevel@tonic-gate 	uint_t nomem = 0;
1699*7c478bd9Sstevel@tonic-gate #define	NOMEM	(nomem = 1)
1700*7c478bd9Sstevel@tonic-gate #else
1701*7c478bd9Sstevel@tonic-gate #define	NOMEM	/* nothing */
1702*7c478bd9Sstevel@tonic-gate #endif
1703*7c478bd9Sstevel@tonic-gate 	uint_t wbit;		/* opcode wbit, 0 is 8 bit, !0 for opnd_size */
1704*7c478bd9Sstevel@tonic-gate 	uint_t w2;		/* wbit value for second operand */
1705*7c478bd9Sstevel@tonic-gate 	uint_t vbit;
1706*7c478bd9Sstevel@tonic-gate 	uint_t mode = 0;	/* mode value from ModRM byte */
1707*7c478bd9Sstevel@tonic-gate 	uint_t reg;		/* reg value from ModRM byte */
1708*7c478bd9Sstevel@tonic-gate 	uint_t r_m;		/* r_m value from ModRM byte */
1709*7c478bd9Sstevel@tonic-gate 
1710*7c478bd9Sstevel@tonic-gate 	uint_t opcode1;		/* high nibble of 1st byte */
1711*7c478bd9Sstevel@tonic-gate 	uint_t opcode2;		/* low nibble of 1st byte */
1712*7c478bd9Sstevel@tonic-gate 	uint_t opcode3;		/* extra opcode bits usually from ModRM byte */
1713*7c478bd9Sstevel@tonic-gate 	uint_t opcode4;		/* high nibble of 2nd byte */
1714*7c478bd9Sstevel@tonic-gate 	uint_t opcode5;		/* low nibble of 2ne byte */
1715*7c478bd9Sstevel@tonic-gate 	uint_t opcode6;		/* high nibble of 3rd byte */
1716*7c478bd9Sstevel@tonic-gate 	uint_t opcode7;		/* low nibble of 3rd byte */
1717*7c478bd9Sstevel@tonic-gate 	uint_t opcode_bytes = 1;
1718*7c478bd9Sstevel@tonic-gate 
1719*7c478bd9Sstevel@tonic-gate 	/*
1720*7c478bd9Sstevel@tonic-gate 	 * legacy prefixes come in 5 flavors, you should have only one of each
1721*7c478bd9Sstevel@tonic-gate 	 */
1722*7c478bd9Sstevel@tonic-gate 	uint_t	opnd_size_prefix = 0;
1723*7c478bd9Sstevel@tonic-gate 	uint_t	addr_size_prefix = 0;
1724*7c478bd9Sstevel@tonic-gate 	uint_t	segment_prefix = 0;
1725*7c478bd9Sstevel@tonic-gate 	uint_t	lock_prefix = 0;
1726*7c478bd9Sstevel@tonic-gate 	uint_t	rep_prefix = 0;
1727*7c478bd9Sstevel@tonic-gate 	uint_t	rex_prefix = 0;	/* amd64 register extension prefix */
1728*7c478bd9Sstevel@tonic-gate 	size_t	off;
1729*7c478bd9Sstevel@tonic-gate 
1730*7c478bd9Sstevel@tonic-gate 	x->d86_len = 0;
1731*7c478bd9Sstevel@tonic-gate 	x->d86_rmindex = -1;
1732*7c478bd9Sstevel@tonic-gate 	x->d86_error = 0;
1733*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1734*7c478bd9Sstevel@tonic-gate 	x->d86_numopnds = 0;
1735*7c478bd9Sstevel@tonic-gate 	x->d86_seg_prefix = NULL;
1736*7c478bd9Sstevel@tonic-gate 	x->d86_mneu[0] = 0;
1737*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 3; ++i) {
1738*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[i].d86_opnd[0] = 0;
1739*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[i].d86_prefix[0] = 0;
1740*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[i].d86_value_size = 0;
1741*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[i].d86_value = 0;
1742*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[i].d86_mode = MODE_NONE;
1743*7c478bd9Sstevel@tonic-gate 	}
1744*7c478bd9Sstevel@tonic-gate #endif
1745*7c478bd9Sstevel@tonic-gate 	x->d86_error = 0;
1746*7c478bd9Sstevel@tonic-gate 	x->d86_memsize = 0;
1747*7c478bd9Sstevel@tonic-gate 
1748*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE16) {
1749*7c478bd9Sstevel@tonic-gate 		opnd_size = SIZE16;
1750*7c478bd9Sstevel@tonic-gate 		addr_size = SIZE16;
1751*7c478bd9Sstevel@tonic-gate 	} else if (cpu_mode == SIZE32) {
1752*7c478bd9Sstevel@tonic-gate 		opnd_size = SIZE32;
1753*7c478bd9Sstevel@tonic-gate 		addr_size = SIZE32;
1754*7c478bd9Sstevel@tonic-gate 	} else {
1755*7c478bd9Sstevel@tonic-gate 		opnd_size = SIZE32;
1756*7c478bd9Sstevel@tonic-gate 		addr_size = SIZE64;
1757*7c478bd9Sstevel@tonic-gate 	}
1758*7c478bd9Sstevel@tonic-gate 
1759*7c478bd9Sstevel@tonic-gate 	/*
1760*7c478bd9Sstevel@tonic-gate 	 * Get one opcode byte and check for zero padding that follows
1761*7c478bd9Sstevel@tonic-gate 	 * jump tables.
1762*7c478bd9Sstevel@tonic-gate 	 */
1763*7c478bd9Sstevel@tonic-gate 	if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
1764*7c478bd9Sstevel@tonic-gate 		goto error;
1765*7c478bd9Sstevel@tonic-gate 
1766*7c478bd9Sstevel@tonic-gate 	if (opcode1 == 0 && opcode2 == 0 &&
1767*7c478bd9Sstevel@tonic-gate 	    x->d86_check_func != NULL && x->d86_check_func()) {
1768*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1769*7c478bd9Sstevel@tonic-gate 		strncpy(x->d86_mneu, ".byte\t0", OPLEN);
1770*7c478bd9Sstevel@tonic-gate #endif
1771*7c478bd9Sstevel@tonic-gate 		goto done;
1772*7c478bd9Sstevel@tonic-gate 	}
1773*7c478bd9Sstevel@tonic-gate 
1774*7c478bd9Sstevel@tonic-gate 	/*
1775*7c478bd9Sstevel@tonic-gate 	 * Gather up legacy x86 prefix bytes.
1776*7c478bd9Sstevel@tonic-gate 	 */
1777*7c478bd9Sstevel@tonic-gate 	for (;;) {
1778*7c478bd9Sstevel@tonic-gate 		uint_t *which_prefix = NULL;
1779*7c478bd9Sstevel@tonic-gate 
1780*7c478bd9Sstevel@tonic-gate 		dp = (instable_t *)&dis_distable[opcode1][opcode2];
1781*7c478bd9Sstevel@tonic-gate 
1782*7c478bd9Sstevel@tonic-gate 		switch (dp->it_adrmode) {
1783*7c478bd9Sstevel@tonic-gate 		case PREFIX:
1784*7c478bd9Sstevel@tonic-gate 			which_prefix = &rep_prefix;
1785*7c478bd9Sstevel@tonic-gate 			break;
1786*7c478bd9Sstevel@tonic-gate 		case LOCK:
1787*7c478bd9Sstevel@tonic-gate 			which_prefix = &lock_prefix;
1788*7c478bd9Sstevel@tonic-gate 			break;
1789*7c478bd9Sstevel@tonic-gate 		case OVERRIDE:
1790*7c478bd9Sstevel@tonic-gate 			which_prefix = &segment_prefix;
1791*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
1792*7c478bd9Sstevel@tonic-gate 			x->d86_seg_prefix = (char *)dp->it_name;
1793*7c478bd9Sstevel@tonic-gate #endif
1794*7c478bd9Sstevel@tonic-gate 			if (dp->it_invalid64 && cpu_mode == SIZE64)
1795*7c478bd9Sstevel@tonic-gate 				goto error;
1796*7c478bd9Sstevel@tonic-gate 			break;
1797*7c478bd9Sstevel@tonic-gate 		case AM:
1798*7c478bd9Sstevel@tonic-gate 			which_prefix = &addr_size_prefix;
1799*7c478bd9Sstevel@tonic-gate 			break;
1800*7c478bd9Sstevel@tonic-gate 		case DM:
1801*7c478bd9Sstevel@tonic-gate 			which_prefix = &opnd_size_prefix;
1802*7c478bd9Sstevel@tonic-gate 			break;
1803*7c478bd9Sstevel@tonic-gate 		}
1804*7c478bd9Sstevel@tonic-gate 		if (which_prefix == NULL)
1805*7c478bd9Sstevel@tonic-gate 			break;
1806*7c478bd9Sstevel@tonic-gate 		*which_prefix = (opcode1 << 4) | opcode2;
1807*7c478bd9Sstevel@tonic-gate 		if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
1808*7c478bd9Sstevel@tonic-gate 			goto error;
1809*7c478bd9Sstevel@tonic-gate 	}
1810*7c478bd9Sstevel@tonic-gate 
1811*7c478bd9Sstevel@tonic-gate 	/*
1812*7c478bd9Sstevel@tonic-gate 	 * Handle amd64 mode PREFIX values.
1813*7c478bd9Sstevel@tonic-gate 	 * Some of the segment prefixes are no-ops. (only FS/GS actually work)
1814*7c478bd9Sstevel@tonic-gate 	 * We might have a REX prefix (opcodes 0x40-0x4f)
1815*7c478bd9Sstevel@tonic-gate 	 */
1816*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE64) {
1817*7c478bd9Sstevel@tonic-gate 		if (segment_prefix != 0x64 && segment_prefix != 0x65)
1818*7c478bd9Sstevel@tonic-gate 			segment_prefix = 0;
1819*7c478bd9Sstevel@tonic-gate 
1820*7c478bd9Sstevel@tonic-gate 		if (opcode1 == 0x4) {
1821*7c478bd9Sstevel@tonic-gate 			rex_prefix = (opcode1 << 4) | opcode2;
1822*7c478bd9Sstevel@tonic-gate 			if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
1823*7c478bd9Sstevel@tonic-gate 				goto error;
1824*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)&dis_distable[opcode1][opcode2];
1825*7c478bd9Sstevel@tonic-gate 		}
1826*7c478bd9Sstevel@tonic-gate 	}
1827*7c478bd9Sstevel@tonic-gate 
1828*7c478bd9Sstevel@tonic-gate 	/*
1829*7c478bd9Sstevel@tonic-gate 	 * Deal with selection of operand and address size now.
1830*7c478bd9Sstevel@tonic-gate 	 * Note that the REX.W bit being set causes opnd_size_prefix to be
1831*7c478bd9Sstevel@tonic-gate 	 * ignored.
1832*7c478bd9Sstevel@tonic-gate 	 */
1833*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE64) {
1834*7c478bd9Sstevel@tonic-gate 		if (rex_prefix & 0x08)
1835*7c478bd9Sstevel@tonic-gate 			opnd_size = SIZE64;
1836*7c478bd9Sstevel@tonic-gate 		else if (opnd_size_prefix)
1837*7c478bd9Sstevel@tonic-gate 			opnd_size = SIZE16;
1838*7c478bd9Sstevel@tonic-gate 
1839*7c478bd9Sstevel@tonic-gate 		if (addr_size_prefix)
1840*7c478bd9Sstevel@tonic-gate 			addr_size = SIZE32;
1841*7c478bd9Sstevel@tonic-gate 	} else if (cpu_mode == SIZE32) {
1842*7c478bd9Sstevel@tonic-gate 		if (opnd_size_prefix)
1843*7c478bd9Sstevel@tonic-gate 			opnd_size = SIZE16;
1844*7c478bd9Sstevel@tonic-gate 		if (addr_size_prefix)
1845*7c478bd9Sstevel@tonic-gate 			addr_size = SIZE16;
1846*7c478bd9Sstevel@tonic-gate 	} else {
1847*7c478bd9Sstevel@tonic-gate 		if (opnd_size_prefix)
1848*7c478bd9Sstevel@tonic-gate 			opnd_size = SIZE32;
1849*7c478bd9Sstevel@tonic-gate 		if (addr_size_prefix)
1850*7c478bd9Sstevel@tonic-gate 			addr_size = SIZE32;
1851*7c478bd9Sstevel@tonic-gate 	}
1852*7c478bd9Sstevel@tonic-gate 
1853*7c478bd9Sstevel@tonic-gate 	/*
1854*7c478bd9Sstevel@tonic-gate 	 * The pause instruction - a repz'd nop.  This doesn't fit
1855*7c478bd9Sstevel@tonic-gate 	 * with any of the other prefix goop added for SSE, so we'll
1856*7c478bd9Sstevel@tonic-gate 	 * special-case it here.
1857*7c478bd9Sstevel@tonic-gate 	 */
1858*7c478bd9Sstevel@tonic-gate 	if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) {
1859*7c478bd9Sstevel@tonic-gate 		rep_prefix = 0;
1860*7c478bd9Sstevel@tonic-gate 		dp = (instable_t *)&dis_opPause;
1861*7c478bd9Sstevel@tonic-gate 	}
1862*7c478bd9Sstevel@tonic-gate 
1863*7c478bd9Sstevel@tonic-gate 	/*
1864*7c478bd9Sstevel@tonic-gate 	 * Some 386 instructions have 2 bytes of opcode before the mod_r/m
1865*7c478bd9Sstevel@tonic-gate 	 * byte so we may need to perform a table indirection.
1866*7c478bd9Sstevel@tonic-gate 	 */
1867*7c478bd9Sstevel@tonic-gate 	if (dp->it_indirect == (instable_t *)dis_op0F) {
1868*7c478bd9Sstevel@tonic-gate 		if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0)
1869*7c478bd9Sstevel@tonic-gate 			goto error;
1870*7c478bd9Sstevel@tonic-gate 		opcode_bytes = 2;
1871*7c478bd9Sstevel@tonic-gate 		if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) {
1872*7c478bd9Sstevel@tonic-gate 			uint_t	subcode;
1873*7c478bd9Sstevel@tonic-gate 
1874*7c478bd9Sstevel@tonic-gate 			if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
1875*7c478bd9Sstevel@tonic-gate 				goto error;
1876*7c478bd9Sstevel@tonic-gate 			opcode_bytes = 3;
1877*7c478bd9Sstevel@tonic-gate 			subcode = ((opcode6 & 0x3) << 1) |
1878*7c478bd9Sstevel@tonic-gate 			    ((opcode7 & 0x8) >> 3);
1879*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)&dis_op0F7123[opcode5][subcode];
1880*7c478bd9Sstevel@tonic-gate 		} else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) {
1881*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)&dis_op0FC8[0];
1882*7c478bd9Sstevel@tonic-gate 		} else {
1883*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)&dis_op0F[opcode4][opcode5];
1884*7c478bd9Sstevel@tonic-gate 		}
1885*7c478bd9Sstevel@tonic-gate 	}
1886*7c478bd9Sstevel@tonic-gate 
1887*7c478bd9Sstevel@tonic-gate 	/*
1888*7c478bd9Sstevel@tonic-gate 	 * If still not at a TERM decode entry, then a ModRM byte
1889*7c478bd9Sstevel@tonic-gate 	 * exists and its fields further decode the instruction.
1890*7c478bd9Sstevel@tonic-gate 	 */
1891*7c478bd9Sstevel@tonic-gate 	x->d86_got_modrm = 0;
1892*7c478bd9Sstevel@tonic-gate 	if (dp->it_indirect != TERM) {
1893*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &opcode3, &r_m);
1894*7c478bd9Sstevel@tonic-gate 		if (x->d86_error)
1895*7c478bd9Sstevel@tonic-gate 			goto error;
1896*7c478bd9Sstevel@tonic-gate 		reg = opcode3;
1897*7c478bd9Sstevel@tonic-gate 
1898*7c478bd9Sstevel@tonic-gate 		/*
1899*7c478bd9Sstevel@tonic-gate 		 * decode 287 instructions (D8-DF) from opcodeN
1900*7c478bd9Sstevel@tonic-gate 		 */
1901*7c478bd9Sstevel@tonic-gate 		if (opcode1 == 0xD && opcode2 >= 0x8) {
1902*7c478bd9Sstevel@tonic-gate 			if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4)
1903*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)&dis_opFP5[r_m];
1904*7c478bd9Sstevel@tonic-gate 			else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4)
1905*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)&dis_opFP7[opcode3];
1906*7c478bd9Sstevel@tonic-gate 			else if (opcode2 == 0xB && mode == 0x3)
1907*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)&dis_opFP6[opcode3];
1908*7c478bd9Sstevel@tonic-gate 			else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4)
1909*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m];
1910*7c478bd9Sstevel@tonic-gate 			else if (mode == 0x3)
1911*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)
1912*7c478bd9Sstevel@tonic-gate 				    &dis_opFP3[opcode2 - 8][opcode3];
1913*7c478bd9Sstevel@tonic-gate 			else
1914*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)
1915*7c478bd9Sstevel@tonic-gate 				    &dis_opFP1n2[opcode2 - 8][opcode3];
1916*7c478bd9Sstevel@tonic-gate 		} else {
1917*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)dp->it_indirect + opcode3;
1918*7c478bd9Sstevel@tonic-gate 		}
1919*7c478bd9Sstevel@tonic-gate 	}
1920*7c478bd9Sstevel@tonic-gate 
1921*7c478bd9Sstevel@tonic-gate 	/*
1922*7c478bd9Sstevel@tonic-gate 	 * In amd64 bit mode, ARPL opcode is changed to MOVSXD
1923*7c478bd9Sstevel@tonic-gate 	 * (sign extend 32bit to 64 bit)
1924*7c478bd9Sstevel@tonic-gate 	 */
1925*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE64 && opcode1 == 0x6 && opcode2 == 0x3)
1926*7c478bd9Sstevel@tonic-gate 		dp = (instable_t *)&dis_opMOVSLD;
1927*7c478bd9Sstevel@tonic-gate 
1928*7c478bd9Sstevel@tonic-gate 	/*
1929*7c478bd9Sstevel@tonic-gate 	 * at this point we should have a correct (or invalid) opcode
1930*7c478bd9Sstevel@tonic-gate 	 */
1931*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE64 && dp->it_invalid64 ||
1932*7c478bd9Sstevel@tonic-gate 	    cpu_mode != SIZE64 && dp->it_invalid32)
1933*7c478bd9Sstevel@tonic-gate 		goto error;
1934*7c478bd9Sstevel@tonic-gate 	if (dp->it_indirect != TERM)
1935*7c478bd9Sstevel@tonic-gate 		goto error;
1936*7c478bd9Sstevel@tonic-gate 
1937*7c478bd9Sstevel@tonic-gate 	/*
1938*7c478bd9Sstevel@tonic-gate 	 * deal with MMX/SSE opcodes which are changed by prefixes
1939*7c478bd9Sstevel@tonic-gate 	 */
1940*7c478bd9Sstevel@tonic-gate 	switch (dp->it_adrmode) {
1941*7c478bd9Sstevel@tonic-gate 	case MMO:
1942*7c478bd9Sstevel@tonic-gate 	case MMOIMPL:
1943*7c478bd9Sstevel@tonic-gate 	case MMO3P:
1944*7c478bd9Sstevel@tonic-gate 	case MMOM3:
1945*7c478bd9Sstevel@tonic-gate 	case MMOMS:
1946*7c478bd9Sstevel@tonic-gate 	case MMOPM:
1947*7c478bd9Sstevel@tonic-gate 	case MMOPRM:
1948*7c478bd9Sstevel@tonic-gate 	case MMOS:
1949*7c478bd9Sstevel@tonic-gate 	case XMMO:
1950*7c478bd9Sstevel@tonic-gate 	case XMMOM:
1951*7c478bd9Sstevel@tonic-gate 	case XMMOMS:
1952*7c478bd9Sstevel@tonic-gate 	case XMMOPM:
1953*7c478bd9Sstevel@tonic-gate 	case XMMOS:
1954*7c478bd9Sstevel@tonic-gate 	case XMMOMX:
1955*7c478bd9Sstevel@tonic-gate 	case XMMOX3:
1956*7c478bd9Sstevel@tonic-gate 	case XMMOXMM:
1957*7c478bd9Sstevel@tonic-gate 		/*
1958*7c478bd9Sstevel@tonic-gate 		 * This is horrible.  Some SIMD instructions take the
1959*7c478bd9Sstevel@tonic-gate 		 * form 0x0F 0x?? ..., which is easily decoded using the
1960*7c478bd9Sstevel@tonic-gate 		 * existing tables.  Other SIMD instructions use various
1961*7c478bd9Sstevel@tonic-gate 		 * prefix bytes to overload existing instructions.  For
1962*7c478bd9Sstevel@tonic-gate 		 * Example, addps is F0, 58, whereas addss is F3 (repz),
1963*7c478bd9Sstevel@tonic-gate 		 * F0, 58.  Presumably someone got a raise for this.
1964*7c478bd9Sstevel@tonic-gate 		 *
1965*7c478bd9Sstevel@tonic-gate 		 * If we see one of the instructions which can be
1966*7c478bd9Sstevel@tonic-gate 		 * modified in this way (if we've got one of the SIMDO*
1967*7c478bd9Sstevel@tonic-gate 		 * address modes), we'll check to see if the last prefix
1968*7c478bd9Sstevel@tonic-gate 		 * was a repz.  If it was, we strip the prefix from the
1969*7c478bd9Sstevel@tonic-gate 		 * mnemonic, and we indirect using the dis_opSIMDrepz
1970*7c478bd9Sstevel@tonic-gate 		 * table.
1971*7c478bd9Sstevel@tonic-gate 		 */
1972*7c478bd9Sstevel@tonic-gate 
1973*7c478bd9Sstevel@tonic-gate 		/*
1974*7c478bd9Sstevel@tonic-gate 		 * Calculate our offset in dis_op0F
1975*7c478bd9Sstevel@tonic-gate 		 */
1976*7c478bd9Sstevel@tonic-gate 		if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F))
1977*7c478bd9Sstevel@tonic-gate 			goto error;
1978*7c478bd9Sstevel@tonic-gate 
1979*7c478bd9Sstevel@tonic-gate 		off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
1980*7c478bd9Sstevel@tonic-gate 		    sizeof (instable_t);
1981*7c478bd9Sstevel@tonic-gate 
1982*7c478bd9Sstevel@tonic-gate 		/*
1983*7c478bd9Sstevel@tonic-gate 		 * Rewrite if this instruction used one of the magic prefixes.
1984*7c478bd9Sstevel@tonic-gate 		 */
1985*7c478bd9Sstevel@tonic-gate 		if (rep_prefix) {
1986*7c478bd9Sstevel@tonic-gate 			if (rep_prefix == 0xf2)
1987*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)&dis_opSIMDrepnz[off];
1988*7c478bd9Sstevel@tonic-gate 			else
1989*7c478bd9Sstevel@tonic-gate 				dp = (instable_t *)&dis_opSIMDrepz[off];
1990*7c478bd9Sstevel@tonic-gate 			rep_prefix = 0;
1991*7c478bd9Sstevel@tonic-gate 		} else if (opnd_size_prefix) {
1992*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)&dis_opSIMDdata16[off];
1993*7c478bd9Sstevel@tonic-gate 			opnd_size_prefix = 0;
1994*7c478bd9Sstevel@tonic-gate 			if (opnd_size == SIZE16)
1995*7c478bd9Sstevel@tonic-gate 				opnd_size = SIZE32;
1996*7c478bd9Sstevel@tonic-gate 		}
1997*7c478bd9Sstevel@tonic-gate 		break;
1998*7c478bd9Sstevel@tonic-gate 
1999*7c478bd9Sstevel@tonic-gate 	case MMOSH:
2000*7c478bd9Sstevel@tonic-gate 		/*
2001*7c478bd9Sstevel@tonic-gate 		 * As with the "normal" SIMD instructions, the MMX
2002*7c478bd9Sstevel@tonic-gate 		 * shuffle instructions are overloaded.  These
2003*7c478bd9Sstevel@tonic-gate 		 * instructions, however, are special in that they use
2004*7c478bd9Sstevel@tonic-gate 		 * an extra byte, and thus an extra table.  As of this
2005*7c478bd9Sstevel@tonic-gate 		 * writing, they only use the opnd_size prefix.
2006*7c478bd9Sstevel@tonic-gate 		 */
2007*7c478bd9Sstevel@tonic-gate 
2008*7c478bd9Sstevel@tonic-gate 		/*
2009*7c478bd9Sstevel@tonic-gate 		 * Calculate our offset in dis_op0F7123
2010*7c478bd9Sstevel@tonic-gate 		 */
2011*7c478bd9Sstevel@tonic-gate 		if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 >
2012*7c478bd9Sstevel@tonic-gate 		    sizeof (dis_op0F7123))
2013*7c478bd9Sstevel@tonic-gate 			goto error;
2014*7c478bd9Sstevel@tonic-gate 
2015*7c478bd9Sstevel@tonic-gate 		if (opnd_size_prefix) {
2016*7c478bd9Sstevel@tonic-gate 			off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) /
2017*7c478bd9Sstevel@tonic-gate 			    sizeof (instable_t);
2018*7c478bd9Sstevel@tonic-gate 			dp = (instable_t *)&dis_opSIMD7123[off];
2019*7c478bd9Sstevel@tonic-gate 			opnd_size_prefix = 0;
2020*7c478bd9Sstevel@tonic-gate 			if (opnd_size == SIZE16)
2021*7c478bd9Sstevel@tonic-gate 				opnd_size = SIZE32;
2022*7c478bd9Sstevel@tonic-gate 		}
2023*7c478bd9Sstevel@tonic-gate 		break;
2024*7c478bd9Sstevel@tonic-gate 	}
2025*7c478bd9Sstevel@tonic-gate 
2026*7c478bd9Sstevel@tonic-gate 	/*
2027*7c478bd9Sstevel@tonic-gate 	 * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64.
2028*7c478bd9Sstevel@tonic-gate 	 */
2029*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE64)
2030*7c478bd9Sstevel@tonic-gate 		if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop))
2031*7c478bd9Sstevel@tonic-gate 			opnd_size = SIZE64;
2032*7c478bd9Sstevel@tonic-gate 
2033*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2034*7c478bd9Sstevel@tonic-gate 	/*
2035*7c478bd9Sstevel@tonic-gate 	 * At this point most instructions can format the opcode mnemonic
2036*7c478bd9Sstevel@tonic-gate 	 * including the prefixes.
2037*7c478bd9Sstevel@tonic-gate 	 */
2038*7c478bd9Sstevel@tonic-gate 	if (lock_prefix)
2039*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_mneu, "lock ", OPLEN);
2040*7c478bd9Sstevel@tonic-gate 
2041*7c478bd9Sstevel@tonic-gate 	if (rep_prefix == 0xf2)
2042*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_mneu, "repnz ", OPLEN);
2043*7c478bd9Sstevel@tonic-gate 	else if (rep_prefix == 0xf3)
2044*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_mneu, "repz ", OPLEN);
2045*7c478bd9Sstevel@tonic-gate 
2046*7c478bd9Sstevel@tonic-gate 	if (cpu_mode == SIZE64 && addr_size_prefix)
2047*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_mneu, "addr32 ", OPLEN);
2048*7c478bd9Sstevel@tonic-gate 
2049*7c478bd9Sstevel@tonic-gate 	if (dp->it_adrmode != CBW &&
2050*7c478bd9Sstevel@tonic-gate 	    dp->it_adrmode != CWD &&
2051*7c478bd9Sstevel@tonic-gate 	    dp->it_adrmode != XMMSFNC) {
2052*7c478bd9Sstevel@tonic-gate 		if (strcmp(dp->it_name, "INVALID") == 0)
2053*7c478bd9Sstevel@tonic-gate 			goto error;
2054*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_mneu, dp->it_name, OPLEN);
2055*7c478bd9Sstevel@tonic-gate 		if (dp->it_suffix) {
2056*7c478bd9Sstevel@tonic-gate 			char *types[] = {"", "w", "l", "q"};
2057*7c478bd9Sstevel@tonic-gate 			if (opcode_bytes == 2 && opcode4 == 4) {
2058*7c478bd9Sstevel@tonic-gate 				/* It's a cmovx.yy. Replace the suffix x */
2059*7c478bd9Sstevel@tonic-gate 				for (i = 5; i < OPLEN; i++) {
2060*7c478bd9Sstevel@tonic-gate 					if (x->d86_mneu[i] == '.')
2061*7c478bd9Sstevel@tonic-gate 						break;
2062*7c478bd9Sstevel@tonic-gate 				}
2063*7c478bd9Sstevel@tonic-gate 				x->d86_mneu[i - 1] = *types[opnd_size];
2064*7c478bd9Sstevel@tonic-gate 			} else
2065*7c478bd9Sstevel@tonic-gate 				strlcat(x->d86_mneu, types[opnd_size], OPLEN);
2066*7c478bd9Sstevel@tonic-gate 		}
2067*7c478bd9Sstevel@tonic-gate 	}
2068*7c478bd9Sstevel@tonic-gate #endif
2069*7c478bd9Sstevel@tonic-gate 
2070*7c478bd9Sstevel@tonic-gate 	/*
2071*7c478bd9Sstevel@tonic-gate 	 * Process operands based on the addressing modes.
2072*7c478bd9Sstevel@tonic-gate 	 */
2073*7c478bd9Sstevel@tonic-gate 	x->d86_mode = cpu_mode;
2074*7c478bd9Sstevel@tonic-gate 	x->d86_rex_prefix = rex_prefix;
2075*7c478bd9Sstevel@tonic-gate 	x->d86_opnd_size = opnd_size;
2076*7c478bd9Sstevel@tonic-gate 	x->d86_addr_size = addr_size;
2077*7c478bd9Sstevel@tonic-gate 	vbit = 0;		/* initialize for mem/reg -> reg */
2078*7c478bd9Sstevel@tonic-gate 	switch (dp->it_adrmode) {
2079*7c478bd9Sstevel@tonic-gate 		/*
2080*7c478bd9Sstevel@tonic-gate 		 * amd64 instruction to sign extend 32 bit reg/mem operands
2081*7c478bd9Sstevel@tonic-gate 		 * into 64 bit register values
2082*7c478bd9Sstevel@tonic-gate 		 */
2083*7c478bd9Sstevel@tonic-gate 	case MOVSXZ:
2084*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2085*7c478bd9Sstevel@tonic-gate 		if (rex_prefix == 0)
2086*7c478bd9Sstevel@tonic-gate 			strncpy(x->d86_mneu, "movzld", OPLEN);
2087*7c478bd9Sstevel@tonic-gate #endif
2088*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2089*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2090*7c478bd9Sstevel@tonic-gate 		x->d86_opnd_size = SIZE64;
2091*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2092*7c478bd9Sstevel@tonic-gate 		x->d86_opnd_size = opnd_size = SIZE32;
2093*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2094*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 0);
2095*7c478bd9Sstevel@tonic-gate 		break;
2096*7c478bd9Sstevel@tonic-gate 
2097*7c478bd9Sstevel@tonic-gate 		/*
2098*7c478bd9Sstevel@tonic-gate 		 * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF)
2099*7c478bd9Sstevel@tonic-gate 		 * movzbl movzbw movzbq (0x0FB6) or mobzwl movzwq (0x0FB7)
2100*7c478bd9Sstevel@tonic-gate 		 * wbit lives in 2nd byte, note that operands
2101*7c478bd9Sstevel@tonic-gate 		 * are different sized
2102*7c478bd9Sstevel@tonic-gate 		 */
2103*7c478bd9Sstevel@tonic-gate 	case MOVZ:
2104*7c478bd9Sstevel@tonic-gate 		if (rex_prefix & REX_W) {
2105*7c478bd9Sstevel@tonic-gate 			/* target register size = 64 bit */
2106*7c478bd9Sstevel@tonic-gate 			x->d86_mneu[5] = 'q';
2107*7c478bd9Sstevel@tonic-gate 		}
2108*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2109*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2110*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2111*7c478bd9Sstevel@tonic-gate 		x->d86_opnd_size = opnd_size = SIZE16;
2112*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode5);
2113*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 0);
2114*7c478bd9Sstevel@tonic-gate 		break;
2115*7c478bd9Sstevel@tonic-gate 
2116*7c478bd9Sstevel@tonic-gate 	/*
2117*7c478bd9Sstevel@tonic-gate 	 * imul instruction, with either 8-bit or longer immediate
2118*7c478bd9Sstevel@tonic-gate 	 * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s)
2119*7c478bd9Sstevel@tonic-gate 	 */
2120*7c478bd9Sstevel@tonic-gate 	case IMUL:
2121*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2122*7c478bd9Sstevel@tonic-gate 		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND,
2123*7c478bd9Sstevel@tonic-gate 		    OPSIZE(opnd_size, opcode2 == 0x9));
2124*7c478bd9Sstevel@tonic-gate 		break;
2125*7c478bd9Sstevel@tonic-gate 
2126*7c478bd9Sstevel@tonic-gate 	/* memory or register operand to register, with 'w' bit	*/
2127*7c478bd9Sstevel@tonic-gate 	case MRw:
2128*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2129*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
2130*7c478bd9Sstevel@tonic-gate 		break;
2131*7c478bd9Sstevel@tonic-gate 
2132*7c478bd9Sstevel@tonic-gate 	/* register to memory or register operand, with 'w' bit	*/
2133*7c478bd9Sstevel@tonic-gate 	/* arpl happens to fit here also because it is odd */
2134*7c478bd9Sstevel@tonic-gate 	case RMw:
2135*7c478bd9Sstevel@tonic-gate 		if (opcode_bytes == 2)
2136*7c478bd9Sstevel@tonic-gate 			wbit = WBIT(opcode5);
2137*7c478bd9Sstevel@tonic-gate 		else
2138*7c478bd9Sstevel@tonic-gate 			wbit = WBIT(opcode2);
2139*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2140*7c478bd9Sstevel@tonic-gate 		break;
2141*7c478bd9Sstevel@tonic-gate 
2142*7c478bd9Sstevel@tonic-gate 	/* xaddb instruction */
2143*7c478bd9Sstevel@tonic-gate 	case XADDB:
2144*7c478bd9Sstevel@tonic-gate 		wbit = 0;
2145*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2146*7c478bd9Sstevel@tonic-gate 		break;
2147*7c478bd9Sstevel@tonic-gate 
2148*7c478bd9Sstevel@tonic-gate 	/* MMX register to memory or register operand		*/
2149*7c478bd9Sstevel@tonic-gate 	case MMS:
2150*7c478bd9Sstevel@tonic-gate 	case MMOS:
2151*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2152*7c478bd9Sstevel@tonic-gate 		wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
2153*7c478bd9Sstevel@tonic-gate #else
2154*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2155*7c478bd9Sstevel@tonic-gate #endif
2156*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
2157*7c478bd9Sstevel@tonic-gate 		break;
2158*7c478bd9Sstevel@tonic-gate 
2159*7c478bd9Sstevel@tonic-gate 	/* MMX register to memory */
2160*7c478bd9Sstevel@tonic-gate 	case MMOMS:
2161*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2162*7c478bd9Sstevel@tonic-gate 		if (mode == REG_ONLY)
2163*7c478bd9Sstevel@tonic-gate 			goto error;
2164*7c478bd9Sstevel@tonic-gate 		wbit = MM_OPND;
2165*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
2166*7c478bd9Sstevel@tonic-gate 		break;
2167*7c478bd9Sstevel@tonic-gate 
2168*7c478bd9Sstevel@tonic-gate 	/* Double shift. Has immediate operand specifying the shift. */
2169*7c478bd9Sstevel@tonic-gate 	case DSHIFT:
2170*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2171*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2172*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2173*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 2);
2174*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2175*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 1, 0);
2176*7c478bd9Sstevel@tonic-gate 		break;
2177*7c478bd9Sstevel@tonic-gate 
2178*7c478bd9Sstevel@tonic-gate 	/*
2179*7c478bd9Sstevel@tonic-gate 	 * Double shift. With no immediate operand, specifies using %cl.
2180*7c478bd9Sstevel@tonic-gate 	 */
2181*7c478bd9Sstevel@tonic-gate 	case DSHIFTcl:
2182*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2183*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2184*7c478bd9Sstevel@tonic-gate 		break;
2185*7c478bd9Sstevel@tonic-gate 
2186*7c478bd9Sstevel@tonic-gate 	/* immediate to memory or register operand */
2187*7c478bd9Sstevel@tonic-gate 	case IMlw:
2188*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2189*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2190*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 1);
2191*7c478bd9Sstevel@tonic-gate 		/*
2192*7c478bd9Sstevel@tonic-gate 		 * Have long immediate for opcode 0x81, but not 0x80 nor 0x83
2193*7c478bd9Sstevel@tonic-gate 		 */
2194*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0);
2195*7c478bd9Sstevel@tonic-gate 		break;
2196*7c478bd9Sstevel@tonic-gate 
2197*7c478bd9Sstevel@tonic-gate 	/* immediate to memory or register operand with the	*/
2198*7c478bd9Sstevel@tonic-gate 	/* 'w' bit present					*/
2199*7c478bd9Sstevel@tonic-gate 	case IMw:
2200*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2201*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2202*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2203*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 1);
2204*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
2205*7c478bd9Sstevel@tonic-gate 		break;
2206*7c478bd9Sstevel@tonic-gate 
2207*7c478bd9Sstevel@tonic-gate 	/* immediate to register with register in low 3 bits	*/
2208*7c478bd9Sstevel@tonic-gate 	/* of op code						*/
2209*7c478bd9Sstevel@tonic-gate 	case IR:
2210*7c478bd9Sstevel@tonic-gate 		/* w-bit here (with regs) is bit 3 */
2211*7c478bd9Sstevel@tonic-gate 		wbit = opcode2 >>3 & 0x1;
2212*7c478bd9Sstevel@tonic-gate 		reg = REGNO(opcode2);
2213*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2214*7c478bd9Sstevel@tonic-gate 		mode = REG_ONLY;
2215*7c478bd9Sstevel@tonic-gate 		r_m = reg;
2216*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 1);
2217*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0);
2218*7c478bd9Sstevel@tonic-gate 		break;
2219*7c478bd9Sstevel@tonic-gate 
2220*7c478bd9Sstevel@tonic-gate 	/* MMX immediate shift of register */
2221*7c478bd9Sstevel@tonic-gate 	case MMSH:
2222*7c478bd9Sstevel@tonic-gate 	case MMOSH:
2223*7c478bd9Sstevel@tonic-gate 		wbit = MM_OPND;
2224*7c478bd9Sstevel@tonic-gate 		goto mm_shift;	/* in next case */
2225*7c478bd9Sstevel@tonic-gate 
2226*7c478bd9Sstevel@tonic-gate 	/* SIMD immediate shift of register */
2227*7c478bd9Sstevel@tonic-gate 	case XMMSH:
2228*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2229*7c478bd9Sstevel@tonic-gate mm_shift:
2230*7c478bd9Sstevel@tonic-gate 		reg = REGNO(opcode7);
2231*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2232*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
2233*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 1, 0);
2234*7c478bd9Sstevel@tonic-gate 		NOMEM;
2235*7c478bd9Sstevel@tonic-gate 		break;
2236*7c478bd9Sstevel@tonic-gate 
2237*7c478bd9Sstevel@tonic-gate 	/* accumulator to memory operand */
2238*7c478bd9Sstevel@tonic-gate 	case AO:
2239*7c478bd9Sstevel@tonic-gate 		vbit = 1;
2240*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2241*7c478bd9Sstevel@tonic-gate 
2242*7c478bd9Sstevel@tonic-gate 	/* memory operand to accumulator */
2243*7c478bd9Sstevel@tonic-gate 	case OA:
2244*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2245*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit);
2246*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit);
2247*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2248*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[vbit].d86_mode = MODE_OFFSET;
2249*7c478bd9Sstevel@tonic-gate #endif
2250*7c478bd9Sstevel@tonic-gate 		break;
2251*7c478bd9Sstevel@tonic-gate 
2252*7c478bd9Sstevel@tonic-gate 
2253*7c478bd9Sstevel@tonic-gate 	/* segment register to memory or register operand */
2254*7c478bd9Sstevel@tonic-gate 	case SM:
2255*7c478bd9Sstevel@tonic-gate 		vbit = 1;
2256*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2257*7c478bd9Sstevel@tonic-gate 
2258*7c478bd9Sstevel@tonic-gate 	/* memory or register operand to segment register */
2259*7c478bd9Sstevel@tonic-gate 	case MS:
2260*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2261*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2262*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit);
2263*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit);
2264*7c478bd9Sstevel@tonic-gate 		break;
2265*7c478bd9Sstevel@tonic-gate 
2266*7c478bd9Sstevel@tonic-gate 	/*
2267*7c478bd9Sstevel@tonic-gate 	 * rotate or shift instructions, which may shift by 1 or
2268*7c478bd9Sstevel@tonic-gate 	 * consult the cl register, depending on the 'v' bit
2269*7c478bd9Sstevel@tonic-gate 	 */
2270*7c478bd9Sstevel@tonic-gate 	case Mv:
2271*7c478bd9Sstevel@tonic-gate 		vbit = VBIT(opcode2);
2272*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2273*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2274*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 1);
2275*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2276*7c478bd9Sstevel@tonic-gate 		if (vbit) {
2277*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN);
2278*7c478bd9Sstevel@tonic-gate 		} else {
2279*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[0].d86_mode = MODE_SIGNED;
2280*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[0].d86_value_size = 1;
2281*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[0].d86_value = 1;
2282*7c478bd9Sstevel@tonic-gate 		}
2283*7c478bd9Sstevel@tonic-gate #endif
2284*7c478bd9Sstevel@tonic-gate 		break;
2285*7c478bd9Sstevel@tonic-gate 	/*
2286*7c478bd9Sstevel@tonic-gate 	 * immediate rotate or shift instructions
2287*7c478bd9Sstevel@tonic-gate 	 */
2288*7c478bd9Sstevel@tonic-gate 	case MvI:
2289*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2290*7c478bd9Sstevel@tonic-gate normal_imm_mem:
2291*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2292*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 1);
2293*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 1, 0);
2294*7c478bd9Sstevel@tonic-gate 		break;
2295*7c478bd9Sstevel@tonic-gate 
2296*7c478bd9Sstevel@tonic-gate 	/* bit test instructions */
2297*7c478bd9Sstevel@tonic-gate 	case MIb:
2298*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2299*7c478bd9Sstevel@tonic-gate 		goto normal_imm_mem;
2300*7c478bd9Sstevel@tonic-gate 
2301*7c478bd9Sstevel@tonic-gate 	/* single memory or register operand with 'w' bit present */
2302*7c478bd9Sstevel@tonic-gate 	case Mw:
2303*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2304*7c478bd9Sstevel@tonic-gate just_mem:
2305*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2306*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2307*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 0);
2308*7c478bd9Sstevel@tonic-gate 		break;
2309*7c478bd9Sstevel@tonic-gate 
2310*7c478bd9Sstevel@tonic-gate 	case SWAPGS:
2311*7c478bd9Sstevel@tonic-gate 		if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) {
2312*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2313*7c478bd9Sstevel@tonic-gate 			strncpy(x->d86_mneu, "swapgs", OPLEN);
2314*7c478bd9Sstevel@tonic-gate #endif
2315*7c478bd9Sstevel@tonic-gate 			NOMEM;
2316*7c478bd9Sstevel@tonic-gate 			break;
2317*7c478bd9Sstevel@tonic-gate 		}
2318*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2319*7c478bd9Sstevel@tonic-gate 
2320*7c478bd9Sstevel@tonic-gate 	/* prefetch instruction - memory operand, but no memory acess */
2321*7c478bd9Sstevel@tonic-gate 	case PREF:
2322*7c478bd9Sstevel@tonic-gate 		NOMEM;
2323*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2324*7c478bd9Sstevel@tonic-gate 
2325*7c478bd9Sstevel@tonic-gate 	/* single memory or register operand */
2326*7c478bd9Sstevel@tonic-gate 	case M:
2327*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2328*7c478bd9Sstevel@tonic-gate 		goto just_mem;
2329*7c478bd9Sstevel@tonic-gate 
2330*7c478bd9Sstevel@tonic-gate 	/* single memory or register byte operand */
2331*7c478bd9Sstevel@tonic-gate 	case Mb:
2332*7c478bd9Sstevel@tonic-gate 		wbit = BYTE_OPND;
2333*7c478bd9Sstevel@tonic-gate 		goto just_mem;
2334*7c478bd9Sstevel@tonic-gate 
2335*7c478bd9Sstevel@tonic-gate 	case MO:
2336*7c478bd9Sstevel@tonic-gate 		/* Similar to M, but only memory (no direct registers) */
2337*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2338*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2339*7c478bd9Sstevel@tonic-gate 		if (mode == 3)
2340*7c478bd9Sstevel@tonic-gate 			goto error;
2341*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2342*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 0);
2343*7c478bd9Sstevel@tonic-gate 		break;
2344*7c478bd9Sstevel@tonic-gate 
2345*7c478bd9Sstevel@tonic-gate 	/* move special register to register or reverse if vbit */
2346*7c478bd9Sstevel@tonic-gate 	case SREG:
2347*7c478bd9Sstevel@tonic-gate 		switch (opcode5) {
2348*7c478bd9Sstevel@tonic-gate 
2349*7c478bd9Sstevel@tonic-gate 		case 2:
2350*7c478bd9Sstevel@tonic-gate 			vbit = 1;
2351*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
2352*7c478bd9Sstevel@tonic-gate 		case 0:
2353*7c478bd9Sstevel@tonic-gate 			wbit = CONTROL_OPND;
2354*7c478bd9Sstevel@tonic-gate 			break;
2355*7c478bd9Sstevel@tonic-gate 
2356*7c478bd9Sstevel@tonic-gate 		case 3:
2357*7c478bd9Sstevel@tonic-gate 			vbit = 1;
2358*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
2359*7c478bd9Sstevel@tonic-gate 		case 1:
2360*7c478bd9Sstevel@tonic-gate 			wbit = DEBUG_OPND;
2361*7c478bd9Sstevel@tonic-gate 			break;
2362*7c478bd9Sstevel@tonic-gate 
2363*7c478bd9Sstevel@tonic-gate 		case 6:
2364*7c478bd9Sstevel@tonic-gate 			vbit = 1;
2365*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
2366*7c478bd9Sstevel@tonic-gate 		case 4:
2367*7c478bd9Sstevel@tonic-gate 			wbit = TEST_OPND;
2368*7c478bd9Sstevel@tonic-gate 			break;
2369*7c478bd9Sstevel@tonic-gate 
2370*7c478bd9Sstevel@tonic-gate 		}
2371*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2372*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2373*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit);
2374*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit);
2375*7c478bd9Sstevel@tonic-gate 		NOMEM;
2376*7c478bd9Sstevel@tonic-gate 		break;
2377*7c478bd9Sstevel@tonic-gate 
2378*7c478bd9Sstevel@tonic-gate 	/*
2379*7c478bd9Sstevel@tonic-gate 	 * single register operand with register in the low 3
2380*7c478bd9Sstevel@tonic-gate 	 * bits of op code
2381*7c478bd9Sstevel@tonic-gate 	 */
2382*7c478bd9Sstevel@tonic-gate 	case R:
2383*7c478bd9Sstevel@tonic-gate 		if (opcode_bytes == 2)
2384*7c478bd9Sstevel@tonic-gate 			reg = REGNO(opcode5);
2385*7c478bd9Sstevel@tonic-gate 		else
2386*7c478bd9Sstevel@tonic-gate 			reg = REGNO(opcode2);
2387*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2388*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
2389*7c478bd9Sstevel@tonic-gate 		NOMEM;
2390*7c478bd9Sstevel@tonic-gate 		break;
2391*7c478bd9Sstevel@tonic-gate 
2392*7c478bd9Sstevel@tonic-gate 	/*
2393*7c478bd9Sstevel@tonic-gate 	 * register to accumulator with register in the low 3
2394*7c478bd9Sstevel@tonic-gate 	 * bits of op code, xchg instructions
2395*7c478bd9Sstevel@tonic-gate 	 */
2396*7c478bd9Sstevel@tonic-gate 	case RA:
2397*7c478bd9Sstevel@tonic-gate 		NOMEM;
2398*7c478bd9Sstevel@tonic-gate 		reg = REGNO(opcode2);
2399*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2400*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
2401*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1);
2402*7c478bd9Sstevel@tonic-gate 		break;
2403*7c478bd9Sstevel@tonic-gate 
2404*7c478bd9Sstevel@tonic-gate 	/*
2405*7c478bd9Sstevel@tonic-gate 	 * single segment register operand, with register in
2406*7c478bd9Sstevel@tonic-gate 	 * bits 3-4 of op code byte
2407*7c478bd9Sstevel@tonic-gate 	 */
2408*7c478bd9Sstevel@tonic-gate 	case SEG:
2409*7c478bd9Sstevel@tonic-gate 		NOMEM;
2410*7c478bd9Sstevel@tonic-gate 		reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3;
2411*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
2412*7c478bd9Sstevel@tonic-gate 		break;
2413*7c478bd9Sstevel@tonic-gate 
2414*7c478bd9Sstevel@tonic-gate 	/*
2415*7c478bd9Sstevel@tonic-gate 	 * single segment register operand, with register in
2416*7c478bd9Sstevel@tonic-gate 	 * bits 3-5 of op code
2417*7c478bd9Sstevel@tonic-gate 	 */
2418*7c478bd9Sstevel@tonic-gate 	case LSEG:
2419*7c478bd9Sstevel@tonic-gate 		NOMEM;
2420*7c478bd9Sstevel@tonic-gate 		/* long seg reg from opcode */
2421*7c478bd9Sstevel@tonic-gate 		reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7;
2422*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
2423*7c478bd9Sstevel@tonic-gate 		break;
2424*7c478bd9Sstevel@tonic-gate 
2425*7c478bd9Sstevel@tonic-gate 	/* memory or register operand to register */
2426*7c478bd9Sstevel@tonic-gate 	case MR:
2427*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2428*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
2429*7c478bd9Sstevel@tonic-gate 		break;
2430*7c478bd9Sstevel@tonic-gate 
2431*7c478bd9Sstevel@tonic-gate 	case RM:
2432*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2433*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2434*7c478bd9Sstevel@tonic-gate 		break;
2435*7c478bd9Sstevel@tonic-gate 
2436*7c478bd9Sstevel@tonic-gate 	/* MMX/SIMD-Int memory or mm reg to mm reg		*/
2437*7c478bd9Sstevel@tonic-gate 	case MM:
2438*7c478bd9Sstevel@tonic-gate 	case MMO:
2439*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2440*7c478bd9Sstevel@tonic-gate 		wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
2441*7c478bd9Sstevel@tonic-gate #else
2442*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2443*7c478bd9Sstevel@tonic-gate #endif
2444*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
2445*7c478bd9Sstevel@tonic-gate 		break;
2446*7c478bd9Sstevel@tonic-gate 
2447*7c478bd9Sstevel@tonic-gate 	case MMOIMPL:
2448*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2449*7c478bd9Sstevel@tonic-gate 		wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
2450*7c478bd9Sstevel@tonic-gate #else
2451*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2452*7c478bd9Sstevel@tonic-gate #endif
2453*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2454*7c478bd9Sstevel@tonic-gate 		if (mode != REG_ONLY)
2455*7c478bd9Sstevel@tonic-gate 			goto error;
2456*7c478bd9Sstevel@tonic-gate 
2457*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2458*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 0);
2459*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1);
2460*7c478bd9Sstevel@tonic-gate 		mode = 0;	/* change for memory access size... */
2461*7c478bd9Sstevel@tonic-gate 		break;
2462*7c478bd9Sstevel@tonic-gate 
2463*7c478bd9Sstevel@tonic-gate 	/* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */
2464*7c478bd9Sstevel@tonic-gate 	case MMO3P:
2465*7c478bd9Sstevel@tonic-gate 		wbit = MM_OPND;
2466*7c478bd9Sstevel@tonic-gate 		goto xmm3p;
2467*7c478bd9Sstevel@tonic-gate 	case XMM3P:
2468*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2469*7c478bd9Sstevel@tonic-gate xmm3p:
2470*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2471*7c478bd9Sstevel@tonic-gate 		if (mode != REG_ONLY)
2472*7c478bd9Sstevel@tonic-gate 			goto error;
2473*7c478bd9Sstevel@tonic-gate 
2474*7c478bd9Sstevel@tonic-gate 		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1);
2475*7c478bd9Sstevel@tonic-gate 		NOMEM;
2476*7c478bd9Sstevel@tonic-gate 		break;
2477*7c478bd9Sstevel@tonic-gate 
2478*7c478bd9Sstevel@tonic-gate 	/* MMX/SIMD-Int predicated r32/mem to mm reg */
2479*7c478bd9Sstevel@tonic-gate 	case MMOPRM:
2480*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2481*7c478bd9Sstevel@tonic-gate 		w2 = MM_OPND;
2482*7c478bd9Sstevel@tonic-gate 		goto xmmprm;
2483*7c478bd9Sstevel@tonic-gate 	case XMMPRM:
2484*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2485*7c478bd9Sstevel@tonic-gate 		w2 = XMM_OPND;
2486*7c478bd9Sstevel@tonic-gate xmmprm:
2487*7c478bd9Sstevel@tonic-gate 		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1);
2488*7c478bd9Sstevel@tonic-gate 		break;
2489*7c478bd9Sstevel@tonic-gate 
2490*7c478bd9Sstevel@tonic-gate 	/* MMX/SIMD-Int predicated mm/mem to mm reg */
2491*7c478bd9Sstevel@tonic-gate 	case MMOPM:
2492*7c478bd9Sstevel@tonic-gate 		wbit = w2 = MM_OPND;
2493*7c478bd9Sstevel@tonic-gate 		goto xmmprm;
2494*7c478bd9Sstevel@tonic-gate 
2495*7c478bd9Sstevel@tonic-gate 	/* MMX/SIMD-Int mm reg to r32 */
2496*7c478bd9Sstevel@tonic-gate 	case MMOM3:
2497*7c478bd9Sstevel@tonic-gate 		NOMEM;
2498*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2499*7c478bd9Sstevel@tonic-gate 		if (mode != REG_ONLY)
2500*7c478bd9Sstevel@tonic-gate 			goto error;
2501*7c478bd9Sstevel@tonic-gate 		wbit = MM_OPND;
2502*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
2503*7c478bd9Sstevel@tonic-gate 		break;
2504*7c478bd9Sstevel@tonic-gate 
2505*7c478bd9Sstevel@tonic-gate 	/* SIMD memory or xmm reg operand to xmm reg		*/
2506*7c478bd9Sstevel@tonic-gate 	case XMM:
2507*7c478bd9Sstevel@tonic-gate 	case XMMO:
2508*7c478bd9Sstevel@tonic-gate 	case XMMXIMPL:
2509*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2510*7c478bd9Sstevel@tonic-gate 		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
2511*7c478bd9Sstevel@tonic-gate 
2512*7c478bd9Sstevel@tonic-gate 		if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY)
2513*7c478bd9Sstevel@tonic-gate 			goto error;
2514*7c478bd9Sstevel@tonic-gate 
2515*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2516*7c478bd9Sstevel@tonic-gate 		/*
2517*7c478bd9Sstevel@tonic-gate 		 * movlps and movhlps share opcodes.  They differ in the
2518*7c478bd9Sstevel@tonic-gate 		 * addressing modes allowed for their operands.
2519*7c478bd9Sstevel@tonic-gate 		 * movhps and movlhps behave similarly.
2520*7c478bd9Sstevel@tonic-gate 		 */
2521*7c478bd9Sstevel@tonic-gate 		if (mode == REG_ONLY) {
2522*7c478bd9Sstevel@tonic-gate 			if (strcmp(dp->it_name, "movlps") == 0)
2523*7c478bd9Sstevel@tonic-gate 				strncpy(x->d86_mneu, "movhlps", OPLEN);
2524*7c478bd9Sstevel@tonic-gate 			else if (strcmp(dp->it_name, "movhps") == 0)
2525*7c478bd9Sstevel@tonic-gate 				strncpy(x->d86_mneu, "movlhps", OPLEN);
2526*7c478bd9Sstevel@tonic-gate 		}
2527*7c478bd9Sstevel@tonic-gate #endif
2528*7c478bd9Sstevel@tonic-gate 		if (dp->it_adrmode == XMMXIMPL)
2529*7c478bd9Sstevel@tonic-gate 			mode = 0;	/* change for memory access size... */
2530*7c478bd9Sstevel@tonic-gate 		break;
2531*7c478bd9Sstevel@tonic-gate 
2532*7c478bd9Sstevel@tonic-gate 	/* SIMD xmm reg to memory or xmm reg */
2533*7c478bd9Sstevel@tonic-gate 	case XMMS:
2534*7c478bd9Sstevel@tonic-gate 	case XMMOS:
2535*7c478bd9Sstevel@tonic-gate 	case XMMMS:
2536*7c478bd9Sstevel@tonic-gate 	case XMMOMS:
2537*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2538*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2539*7c478bd9Sstevel@tonic-gate 		if ((strcmp(dp->it_name, "movlps") == 0 ||
2540*7c478bd9Sstevel@tonic-gate 		    strcmp(dp->it_name, "movhps") == 0 ||
2541*7c478bd9Sstevel@tonic-gate 		    strcmp(dp->it_name, "movntps") == 0) &&
2542*7c478bd9Sstevel@tonic-gate 		    mode == REG_ONLY)
2543*7c478bd9Sstevel@tonic-gate 			goto error;
2544*7c478bd9Sstevel@tonic-gate #endif
2545*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2546*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
2547*7c478bd9Sstevel@tonic-gate 		break;
2548*7c478bd9Sstevel@tonic-gate 
2549*7c478bd9Sstevel@tonic-gate 	/* SIMD memory to xmm reg */
2550*7c478bd9Sstevel@tonic-gate 	case XMMM:
2551*7c478bd9Sstevel@tonic-gate 	case XMMOM:
2552*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2553*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2554*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2555*7c478bd9Sstevel@tonic-gate 		if (mode == REG_ONLY) {
2556*7c478bd9Sstevel@tonic-gate 			if (strcmp(dp->it_name, "movhps") == 0)
2557*7c478bd9Sstevel@tonic-gate 				strncpy(x->d86_mneu, "movlhps", OPLEN);
2558*7c478bd9Sstevel@tonic-gate 			else
2559*7c478bd9Sstevel@tonic-gate 				goto error;
2560*7c478bd9Sstevel@tonic-gate 		}
2561*7c478bd9Sstevel@tonic-gate #endif
2562*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
2563*7c478bd9Sstevel@tonic-gate 		break;
2564*7c478bd9Sstevel@tonic-gate 
2565*7c478bd9Sstevel@tonic-gate 	/* SIMD memory or r32 to xmm reg			*/
2566*7c478bd9Sstevel@tonic-gate 	case XMM3MX:
2567*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2568*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
2569*7c478bd9Sstevel@tonic-gate 		break;
2570*7c478bd9Sstevel@tonic-gate 
2571*7c478bd9Sstevel@tonic-gate 	case XMM3MXS:
2572*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2573*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
2574*7c478bd9Sstevel@tonic-gate 		break;
2575*7c478bd9Sstevel@tonic-gate 
2576*7c478bd9Sstevel@tonic-gate 	/* SIMD memory or mm reg to xmm reg			*/
2577*7c478bd9Sstevel@tonic-gate 	case XMMOMX:
2578*7c478bd9Sstevel@tonic-gate 	/* SIMD mm to xmm */
2579*7c478bd9Sstevel@tonic-gate 	case XMMMX:
2580*7c478bd9Sstevel@tonic-gate 		wbit = MM_OPND;
2581*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
2582*7c478bd9Sstevel@tonic-gate 		break;
2583*7c478bd9Sstevel@tonic-gate 
2584*7c478bd9Sstevel@tonic-gate 	/* SIMD memory or xmm reg to mm reg			*/
2585*7c478bd9Sstevel@tonic-gate 	case XMMXMM:
2586*7c478bd9Sstevel@tonic-gate 	case XMMOXMM:
2587*7c478bd9Sstevel@tonic-gate 	case XMMXM:
2588*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2589*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
2590*7c478bd9Sstevel@tonic-gate 		break;
2591*7c478bd9Sstevel@tonic-gate 
2592*7c478bd9Sstevel@tonic-gate 
2593*7c478bd9Sstevel@tonic-gate 	/* SIMD memory or xmm reg to r32			*/
2594*7c478bd9Sstevel@tonic-gate 	case XMMXM3:
2595*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2596*7c478bd9Sstevel@tonic-gate 		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
2597*7c478bd9Sstevel@tonic-gate 		break;
2598*7c478bd9Sstevel@tonic-gate 
2599*7c478bd9Sstevel@tonic-gate 	/* SIMD xmm to r32					*/
2600*7c478bd9Sstevel@tonic-gate 	case XMMX3:
2601*7c478bd9Sstevel@tonic-gate 	case XMMOX3:
2602*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2603*7c478bd9Sstevel@tonic-gate 		if (mode != REG_ONLY)
2604*7c478bd9Sstevel@tonic-gate 			goto error;
2605*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2606*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
2607*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2608*7c478bd9Sstevel@tonic-gate 		NOMEM;
2609*7c478bd9Sstevel@tonic-gate 		break;
2610*7c478bd9Sstevel@tonic-gate 
2611*7c478bd9Sstevel@tonic-gate 	/* SIMD predicated memory or xmm reg with/to xmm reg */
2612*7c478bd9Sstevel@tonic-gate 	case XMMP:
2613*7c478bd9Sstevel@tonic-gate 	case XMMOPM:
2614*7c478bd9Sstevel@tonic-gate 		wbit = XMM_OPND;
2615*7c478bd9Sstevel@tonic-gate 		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
2616*7c478bd9Sstevel@tonic-gate 
2617*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2618*7c478bd9Sstevel@tonic-gate 		/*
2619*7c478bd9Sstevel@tonic-gate 		 * cmpps and cmpss vary their instruction name based
2620*7c478bd9Sstevel@tonic-gate 		 * on the value of imm8.  Other XMMP instructions,
2621*7c478bd9Sstevel@tonic-gate 		 * such as shufps, require explicit specification of
2622*7c478bd9Sstevel@tonic-gate 		 * the predicate.
2623*7c478bd9Sstevel@tonic-gate 		 */
2624*7c478bd9Sstevel@tonic-gate 		if (dp->it_name[0] == 'c' &&
2625*7c478bd9Sstevel@tonic-gate 		    dp->it_name[1] == 'm' &&
2626*7c478bd9Sstevel@tonic-gate 		    dp->it_name[2] == 'p' &&
2627*7c478bd9Sstevel@tonic-gate 		    strlen(dp->it_name) == 5) {
2628*7c478bd9Sstevel@tonic-gate 			uchar_t pred = x->d86_opnd[0].d86_value & 0xff;
2629*7c478bd9Sstevel@tonic-gate 
2630*7c478bd9Sstevel@tonic-gate 			if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *)))
2631*7c478bd9Sstevel@tonic-gate 				goto error;
2632*7c478bd9Sstevel@tonic-gate 
2633*7c478bd9Sstevel@tonic-gate 			strncpy(x->d86_mneu, "cmp", OPLEN);
2634*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, dis_PREDSUFFIX[pred],
2635*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2636*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu,
2637*7c478bd9Sstevel@tonic-gate 			    dp->it_name + strlen(dp->it_name) - 2,
2638*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2639*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[0] = x->d86_opnd[1];
2640*7c478bd9Sstevel@tonic-gate 			x->d86_opnd[1] = x->d86_opnd[2];
2641*7c478bd9Sstevel@tonic-gate 			x->d86_numopnds = 2;
2642*7c478bd9Sstevel@tonic-gate 		}
2643*7c478bd9Sstevel@tonic-gate #endif
2644*7c478bd9Sstevel@tonic-gate 		break;
2645*7c478bd9Sstevel@tonic-gate 
2646*7c478bd9Sstevel@tonic-gate 	/* immediate operand to accumulator */
2647*7c478bd9Sstevel@tonic-gate 	case IA:
2648*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2649*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
2650*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
2651*7c478bd9Sstevel@tonic-gate 		NOMEM;
2652*7c478bd9Sstevel@tonic-gate 		break;
2653*7c478bd9Sstevel@tonic-gate 
2654*7c478bd9Sstevel@tonic-gate 	/* memory or register operand to accumulator */
2655*7c478bd9Sstevel@tonic-gate 	case MA:
2656*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2657*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2658*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, wbit, 0);
2659*7c478bd9Sstevel@tonic-gate 		break;
2660*7c478bd9Sstevel@tonic-gate 
2661*7c478bd9Sstevel@tonic-gate 	/* si register to di register used to reference memory		*/
2662*7c478bd9Sstevel@tonic-gate 	case SD:
2663*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2664*7c478bd9Sstevel@tonic-gate 		dtrace_check_override(x, 0);
2665*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 2;
2666*7c478bd9Sstevel@tonic-gate 		if (addr_size == SIZE64) {
2667*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
2668*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2669*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
2670*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2671*7c478bd9Sstevel@tonic-gate 		} else if (addr_size == SIZE32) {
2672*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
2673*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2674*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
2675*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2676*7c478bd9Sstevel@tonic-gate 		} else {
2677*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
2678*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2679*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
2680*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2681*7c478bd9Sstevel@tonic-gate 		}
2682*7c478bd9Sstevel@tonic-gate #endif
2683*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2684*7c478bd9Sstevel@tonic-gate 		break;
2685*7c478bd9Sstevel@tonic-gate 
2686*7c478bd9Sstevel@tonic-gate 	/* accumulator to di register				*/
2687*7c478bd9Sstevel@tonic-gate 	case AD:
2688*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2689*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2690*7c478bd9Sstevel@tonic-gate 		dtrace_check_override(x, 1);
2691*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 2;
2692*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0);
2693*7c478bd9Sstevel@tonic-gate 		if (addr_size == SIZE64)
2694*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
2695*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2696*7c478bd9Sstevel@tonic-gate 		else if (addr_size == SIZE32)
2697*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
2698*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2699*7c478bd9Sstevel@tonic-gate 		else
2700*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
2701*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2702*7c478bd9Sstevel@tonic-gate #endif
2703*7c478bd9Sstevel@tonic-gate 		break;
2704*7c478bd9Sstevel@tonic-gate 
2705*7c478bd9Sstevel@tonic-gate 	/* si register to accumulator				*/
2706*7c478bd9Sstevel@tonic-gate 	case SA:
2707*7c478bd9Sstevel@tonic-gate 		wbit = WBIT(opcode2);
2708*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2709*7c478bd9Sstevel@tonic-gate 		dtrace_check_override(x, 0);
2710*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 2;
2711*7c478bd9Sstevel@tonic-gate 		if (addr_size == SIZE64)
2712*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
2713*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2714*7c478bd9Sstevel@tonic-gate 		else if (addr_size == SIZE32)
2715*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
2716*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2717*7c478bd9Sstevel@tonic-gate 		else
2718*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
2719*7c478bd9Sstevel@tonic-gate 			    OPLEN);
2720*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
2721*7c478bd9Sstevel@tonic-gate #endif
2722*7c478bd9Sstevel@tonic-gate 		break;
2723*7c478bd9Sstevel@tonic-gate 
2724*7c478bd9Sstevel@tonic-gate 	/*
2725*7c478bd9Sstevel@tonic-gate 	 * single operand, a 16/32 bit displacement
2726*7c478bd9Sstevel@tonic-gate 	 */
2727*7c478bd9Sstevel@tonic-gate 	case D:
2728*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2729*7c478bd9Sstevel@tonic-gate 		dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
2730*7c478bd9Sstevel@tonic-gate 		NOMEM;
2731*7c478bd9Sstevel@tonic-gate 		break;
2732*7c478bd9Sstevel@tonic-gate 
2733*7c478bd9Sstevel@tonic-gate 	/* jmp/call indirect to memory or register operand		*/
2734*7c478bd9Sstevel@tonic-gate 	case INM:
2735*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2736*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN);
2737*7c478bd9Sstevel@tonic-gate #endif
2738*7c478bd9Sstevel@tonic-gate 		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2739*7c478bd9Sstevel@tonic-gate 		dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
2740*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2741*7c478bd9Sstevel@tonic-gate 		break;
2742*7c478bd9Sstevel@tonic-gate 
2743*7c478bd9Sstevel@tonic-gate 	/*
2744*7c478bd9Sstevel@tonic-gate 	 * for long jumps and long calls -- a new code segment
2745*7c478bd9Sstevel@tonic-gate 	 * register and an offset in IP -- stored in object
2746*7c478bd9Sstevel@tonic-gate 	 * code in reverse order. Note - not valid in amd64
2747*7c478bd9Sstevel@tonic-gate 	 */
2748*7c478bd9Sstevel@tonic-gate 	case SO:
2749*7c478bd9Sstevel@tonic-gate 		dtrace_check_override(x, 1);
2750*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2751*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1);
2752*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2753*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[1].d86_mode = MODE_SIGNED;
2754*7c478bd9Sstevel@tonic-gate #endif
2755*7c478bd9Sstevel@tonic-gate 		/* will now get segment operand */
2756*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 2, 0);
2757*7c478bd9Sstevel@tonic-gate 		break;
2758*7c478bd9Sstevel@tonic-gate 
2759*7c478bd9Sstevel@tonic-gate 	/*
2760*7c478bd9Sstevel@tonic-gate 	 * jmp/call. single operand, 8 bit displacement.
2761*7c478bd9Sstevel@tonic-gate 	 * added to current EIP in 'compofff'
2762*7c478bd9Sstevel@tonic-gate 	 */
2763*7c478bd9Sstevel@tonic-gate 	case BD:
2764*7c478bd9Sstevel@tonic-gate 		dtrace_disp_opnd(x, BYTE_OPND, 1, 0);
2765*7c478bd9Sstevel@tonic-gate 		NOMEM;
2766*7c478bd9Sstevel@tonic-gate 		break;
2767*7c478bd9Sstevel@tonic-gate 
2768*7c478bd9Sstevel@tonic-gate 	/* single 32/16 bit immediate operand			*/
2769*7c478bd9Sstevel@tonic-gate 	case I:
2770*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2771*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
2772*7c478bd9Sstevel@tonic-gate 		break;
2773*7c478bd9Sstevel@tonic-gate 
2774*7c478bd9Sstevel@tonic-gate 	/* single 8 bit immediate operand			*/
2775*7c478bd9Sstevel@tonic-gate 	case Ib:
2776*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2777*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 1, 0);
2778*7c478bd9Sstevel@tonic-gate 		break;
2779*7c478bd9Sstevel@tonic-gate 
2780*7c478bd9Sstevel@tonic-gate 	case ENTER:
2781*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2782*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 2, 0);
2783*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 1, 1);
2784*7c478bd9Sstevel@tonic-gate 		switch (opnd_size) {
2785*7c478bd9Sstevel@tonic-gate 		case SIZE64:
2786*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8;
2787*7c478bd9Sstevel@tonic-gate 			break;
2788*7c478bd9Sstevel@tonic-gate 		case SIZE32:
2789*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4;
2790*7c478bd9Sstevel@tonic-gate 			break;
2791*7c478bd9Sstevel@tonic-gate 		case SIZE16:
2792*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2;
2793*7c478bd9Sstevel@tonic-gate 			break;
2794*7c478bd9Sstevel@tonic-gate 		}
2795*7c478bd9Sstevel@tonic-gate 
2796*7c478bd9Sstevel@tonic-gate 		break;
2797*7c478bd9Sstevel@tonic-gate 
2798*7c478bd9Sstevel@tonic-gate 	/* 16-bit immediate operand */
2799*7c478bd9Sstevel@tonic-gate 	case RET:
2800*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2801*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, wbit, 2, 0);
2802*7c478bd9Sstevel@tonic-gate 		break;
2803*7c478bd9Sstevel@tonic-gate 
2804*7c478bd9Sstevel@tonic-gate 	/* single 8 bit port operand				*/
2805*7c478bd9Sstevel@tonic-gate 	case P:
2806*7c478bd9Sstevel@tonic-gate 		dtrace_check_override(x, 0);
2807*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
2808*7c478bd9Sstevel@tonic-gate 		NOMEM;
2809*7c478bd9Sstevel@tonic-gate 		break;
2810*7c478bd9Sstevel@tonic-gate 
2811*7c478bd9Sstevel@tonic-gate 	/* single operand, dx register (variable port instruction) */
2812*7c478bd9Sstevel@tonic-gate 	case V:
2813*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 1;
2814*7c478bd9Sstevel@tonic-gate 		dtrace_check_override(x, 0);
2815*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2816*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN);
2817*7c478bd9Sstevel@tonic-gate #endif
2818*7c478bd9Sstevel@tonic-gate 		NOMEM;
2819*7c478bd9Sstevel@tonic-gate 		break;
2820*7c478bd9Sstevel@tonic-gate 
2821*7c478bd9Sstevel@tonic-gate 	/*
2822*7c478bd9Sstevel@tonic-gate 	 * The int instruction, which has two forms:
2823*7c478bd9Sstevel@tonic-gate 	 * int 3 (breakpoint) or
2824*7c478bd9Sstevel@tonic-gate 	 * int n, where n is indicated in the subsequent
2825*7c478bd9Sstevel@tonic-gate 	 * byte (format Ib).  The int 3 instruction (opcode 0xCC),
2826*7c478bd9Sstevel@tonic-gate 	 * where, although the 3 looks  like an operand,
2827*7c478bd9Sstevel@tonic-gate 	 * it is implied by the opcode. It must be converted
2828*7c478bd9Sstevel@tonic-gate 	 * to the correct base and output.
2829*7c478bd9Sstevel@tonic-gate 	 */
2830*7c478bd9Sstevel@tonic-gate 	case INT3:
2831*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2832*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 1;
2833*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[0].d86_mode = MODE_SIGNED;
2834*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[0].d86_value_size = 1;
2835*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[0].d86_value = 3;
2836*7c478bd9Sstevel@tonic-gate #endif
2837*7c478bd9Sstevel@tonic-gate 		NOMEM;
2838*7c478bd9Sstevel@tonic-gate 		break;
2839*7c478bd9Sstevel@tonic-gate 
2840*7c478bd9Sstevel@tonic-gate 	/* single 8 bit immediate operand			*/
2841*7c478bd9Sstevel@tonic-gate 	case INTx:
2842*7c478bd9Sstevel@tonic-gate 		dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
2843*7c478bd9Sstevel@tonic-gate 		NOMEM;
2844*7c478bd9Sstevel@tonic-gate 		break;
2845*7c478bd9Sstevel@tonic-gate 
2846*7c478bd9Sstevel@tonic-gate 	/* an unused byte must be discarded */
2847*7c478bd9Sstevel@tonic-gate 	case U:
2848*7c478bd9Sstevel@tonic-gate 		if (x->d86_get_byte(x->d86_data) < 0)
2849*7c478bd9Sstevel@tonic-gate 			goto error;
2850*7c478bd9Sstevel@tonic-gate 		x->d86_len++;
2851*7c478bd9Sstevel@tonic-gate 		NOMEM;
2852*7c478bd9Sstevel@tonic-gate 		break;
2853*7c478bd9Sstevel@tonic-gate 
2854*7c478bd9Sstevel@tonic-gate 	case CBW:
2855*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2856*7c478bd9Sstevel@tonic-gate 		if (opnd_size == SIZE16)
2857*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "cbtw", OPLEN);
2858*7c478bd9Sstevel@tonic-gate 		else if (opnd_size == SIZE32)
2859*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "cwtl", OPLEN);
2860*7c478bd9Sstevel@tonic-gate 		else
2861*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "cltq", OPLEN);
2862*7c478bd9Sstevel@tonic-gate #endif
2863*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2864*7c478bd9Sstevel@tonic-gate 		NOMEM;
2865*7c478bd9Sstevel@tonic-gate 		break;
2866*7c478bd9Sstevel@tonic-gate 
2867*7c478bd9Sstevel@tonic-gate 	case CWD:
2868*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2869*7c478bd9Sstevel@tonic-gate 		if (opnd_size == SIZE16)
2870*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "cwtd", OPLEN);
2871*7c478bd9Sstevel@tonic-gate 		else if (opnd_size == SIZE32)
2872*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "cltd", OPLEN);
2873*7c478bd9Sstevel@tonic-gate 		else
2874*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "cqtd", OPLEN);
2875*7c478bd9Sstevel@tonic-gate #endif
2876*7c478bd9Sstevel@tonic-gate 		wbit = LONG_OPND;
2877*7c478bd9Sstevel@tonic-gate 		NOMEM;
2878*7c478bd9Sstevel@tonic-gate 		break;
2879*7c478bd9Sstevel@tonic-gate 
2880*7c478bd9Sstevel@tonic-gate 	case XMMSFNC:
2881*7c478bd9Sstevel@tonic-gate 		/*
2882*7c478bd9Sstevel@tonic-gate 		 * sfence is sfence if mode is REG_ONLY.  If mode isn't
2883*7c478bd9Sstevel@tonic-gate 		 * REG_ONLY, mnemonic should be 'clflush'.
2884*7c478bd9Sstevel@tonic-gate 		 */
2885*7c478bd9Sstevel@tonic-gate 		dtrace_get_modrm(x, &mode, &reg, &r_m);
2886*7c478bd9Sstevel@tonic-gate 
2887*7c478bd9Sstevel@tonic-gate 		/* sfence doesn't take operands */
2888*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2889*7c478bd9Sstevel@tonic-gate 		if (mode == REG_ONLY) {
2890*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "sfence", OPLEN);
2891*7c478bd9Sstevel@tonic-gate 		} else {
2892*7c478bd9Sstevel@tonic-gate 			strlcat(x->d86_mneu, "clflush", OPLEN);
2893*7c478bd9Sstevel@tonic-gate 			dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2894*7c478bd9Sstevel@tonic-gate 			dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
2895*7c478bd9Sstevel@tonic-gate 			NOMEM;
2896*7c478bd9Sstevel@tonic-gate 		}
2897*7c478bd9Sstevel@tonic-gate #else
2898*7c478bd9Sstevel@tonic-gate 		if (mode != REG_ONLY) {
2899*7c478bd9Sstevel@tonic-gate 			dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2900*7c478bd9Sstevel@tonic-gate 			dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
2901*7c478bd9Sstevel@tonic-gate 			NOMEM;
2902*7c478bd9Sstevel@tonic-gate 		}
2903*7c478bd9Sstevel@tonic-gate #endif
2904*7c478bd9Sstevel@tonic-gate 		break;
2905*7c478bd9Sstevel@tonic-gate 
2906*7c478bd9Sstevel@tonic-gate 	/*
2907*7c478bd9Sstevel@tonic-gate 	 * no disassembly, the mnemonic was all there was so go on
2908*7c478bd9Sstevel@tonic-gate 	 */
2909*7c478bd9Sstevel@tonic-gate 	case NORM:
2910*7c478bd9Sstevel@tonic-gate 		if (dp->it_invalid32 && cpu_mode != SIZE64)
2911*7c478bd9Sstevel@tonic-gate 			goto error;
2912*7c478bd9Sstevel@tonic-gate 		NOMEM;
2913*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2914*7c478bd9Sstevel@tonic-gate 	case IMPLMEM:
2915*7c478bd9Sstevel@tonic-gate 		break;
2916*7c478bd9Sstevel@tonic-gate 
2917*7c478bd9Sstevel@tonic-gate 	case XMMFENCE:
2918*7c478bd9Sstevel@tonic-gate 		/*
2919*7c478bd9Sstevel@tonic-gate 		 * Only the following exact byte sequences are allowed:
2920*7c478bd9Sstevel@tonic-gate 		 *
2921*7c478bd9Sstevel@tonic-gate 		 * 	0f ae e8	lfence
2922*7c478bd9Sstevel@tonic-gate 		 * 	0f ae f0	mfence
2923*7c478bd9Sstevel@tonic-gate 		 */
2924*7c478bd9Sstevel@tonic-gate 		if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 &&
2925*7c478bd9Sstevel@tonic-gate 		    (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0)
2926*7c478bd9Sstevel@tonic-gate 			goto error;
2927*7c478bd9Sstevel@tonic-gate 
2928*7c478bd9Sstevel@tonic-gate 		break;
2929*7c478bd9Sstevel@tonic-gate 
2930*7c478bd9Sstevel@tonic-gate 
2931*7c478bd9Sstevel@tonic-gate 	/* float reg */
2932*7c478bd9Sstevel@tonic-gate 	case F:
2933*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2934*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 1;
2935*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN);
2936*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[0].d86_opnd[4] = r_m + '0';
2937*7c478bd9Sstevel@tonic-gate #endif
2938*7c478bd9Sstevel@tonic-gate 		NOMEM;
2939*7c478bd9Sstevel@tonic-gate 		break;
2940*7c478bd9Sstevel@tonic-gate 
2941*7c478bd9Sstevel@tonic-gate 	/* float reg to float reg, with ret bit present */
2942*7c478bd9Sstevel@tonic-gate 	case FF:
2943*7c478bd9Sstevel@tonic-gate 		vbit = opcode2 >> 2 & 0x1;	/* vbit = 1: st -> st(i) */
2944*7c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2945*7c478bd9Sstevel@tonic-gate 	case FFC:				/* case for vbit always = 0 */
2946*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
2947*7c478bd9Sstevel@tonic-gate 		x->d86_numopnds = 2;
2948*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN);
2949*7c478bd9Sstevel@tonic-gate 		strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN);
2950*7c478bd9Sstevel@tonic-gate 		x->d86_opnd[vbit].d86_opnd[4] = r_m + '0';
2951*7c478bd9Sstevel@tonic-gate #endif
2952*7c478bd9Sstevel@tonic-gate 		NOMEM;
2953*7c478bd9Sstevel@tonic-gate 		break;
2954*7c478bd9Sstevel@tonic-gate 
2955*7c478bd9Sstevel@tonic-gate 	/* an invalid op code */
2956*7c478bd9Sstevel@tonic-gate 	case AM:
2957*7c478bd9Sstevel@tonic-gate 	case DM:
2958*7c478bd9Sstevel@tonic-gate 	case OVERRIDE:
2959*7c478bd9Sstevel@tonic-gate 	case PREFIX:
2960*7c478bd9Sstevel@tonic-gate 	case UNKNOWN:
2961*7c478bd9Sstevel@tonic-gate 		NOMEM;
2962*7c478bd9Sstevel@tonic-gate 	default:
2963*7c478bd9Sstevel@tonic-gate 		goto error;
2964*7c478bd9Sstevel@tonic-gate 	} /* end switch */
2965*7c478bd9Sstevel@tonic-gate 	if (x->d86_error)
2966*7c478bd9Sstevel@tonic-gate 		goto error;
2967*7c478bd9Sstevel@tonic-gate 
2968*7c478bd9Sstevel@tonic-gate done:
2969*7c478bd9Sstevel@tonic-gate #ifdef DIS_MEM
2970*7c478bd9Sstevel@tonic-gate 	/*
2971*7c478bd9Sstevel@tonic-gate 	 * compute the size of any memory accessed by the instruction
2972*7c478bd9Sstevel@tonic-gate 	 */
2973*7c478bd9Sstevel@tonic-gate 	if (x->d86_memsize != 0) {
2974*7c478bd9Sstevel@tonic-gate 		return (0);
2975*7c478bd9Sstevel@tonic-gate 	} else if (dp->it_stackop) {
2976*7c478bd9Sstevel@tonic-gate 		switch (opnd_size) {
2977*7c478bd9Sstevel@tonic-gate 		case SIZE16:
2978*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 2;
2979*7c478bd9Sstevel@tonic-gate 			break;
2980*7c478bd9Sstevel@tonic-gate 		case SIZE32:
2981*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 4;
2982*7c478bd9Sstevel@tonic-gate 			break;
2983*7c478bd9Sstevel@tonic-gate 		case SIZE64:
2984*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 8;
2985*7c478bd9Sstevel@tonic-gate 			break;
2986*7c478bd9Sstevel@tonic-gate 		}
2987*7c478bd9Sstevel@tonic-gate 	} else if (nomem || mode == REG_ONLY) {
2988*7c478bd9Sstevel@tonic-gate 		x->d86_memsize = 0;
2989*7c478bd9Sstevel@tonic-gate 
2990*7c478bd9Sstevel@tonic-gate 	} else if (dp->it_size != 0) {
2991*7c478bd9Sstevel@tonic-gate 		/*
2992*7c478bd9Sstevel@tonic-gate 		 * In 64 bit mode descriptor table entries
2993*7c478bd9Sstevel@tonic-gate 		 * go up to 10 bytes and popf/pushf are always 8 bytes
2994*7c478bd9Sstevel@tonic-gate 		 */
2995*7c478bd9Sstevel@tonic-gate 		if (x->d86_mode == SIZE64 && dp->it_size == 6)
2996*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 10;
2997*7c478bd9Sstevel@tonic-gate 		else if (x->d86_mode == SIZE64 && opcode1 == 0x9 &&
2998*7c478bd9Sstevel@tonic-gate 		    (opcode2 == 0xc || opcode2 == 0xd))
2999*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 8;
3000*7c478bd9Sstevel@tonic-gate 		else
3001*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = dp->it_size;
3002*7c478bd9Sstevel@tonic-gate 
3003*7c478bd9Sstevel@tonic-gate 	} else if (wbit == 0) {
3004*7c478bd9Sstevel@tonic-gate 		x->d86_memsize = 1;
3005*7c478bd9Sstevel@tonic-gate 
3006*7c478bd9Sstevel@tonic-gate 	} else if (wbit == LONG_OPND) {
3007*7c478bd9Sstevel@tonic-gate 		if (opnd_size == SIZE64)
3008*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 8;
3009*7c478bd9Sstevel@tonic-gate 		else if (opnd_size == SIZE32)
3010*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 4;
3011*7c478bd9Sstevel@tonic-gate 		else
3012*7c478bd9Sstevel@tonic-gate 			x->d86_memsize = 2;
3013*7c478bd9Sstevel@tonic-gate 
3014*7c478bd9Sstevel@tonic-gate 	} else if (wbit == SEG_OPND) {
3015*7c478bd9Sstevel@tonic-gate 		x->d86_memsize = 4;
3016*7c478bd9Sstevel@tonic-gate 
3017*7c478bd9Sstevel@tonic-gate 	} else {
3018*7c478bd9Sstevel@tonic-gate 		x->d86_memsize = 8;
3019*7c478bd9Sstevel@tonic-gate 	}
3020*7c478bd9Sstevel@tonic-gate #endif
3021*7c478bd9Sstevel@tonic-gate 	return (0);
3022*7c478bd9Sstevel@tonic-gate 
3023*7c478bd9Sstevel@tonic-gate error:
3024*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
3025*7c478bd9Sstevel@tonic-gate 	strlcat(x->d86_mneu, "undef", OPLEN);
3026*7c478bd9Sstevel@tonic-gate #endif
3027*7c478bd9Sstevel@tonic-gate 	return (1);
3028*7c478bd9Sstevel@tonic-gate }
3029*7c478bd9Sstevel@tonic-gate 
3030*7c478bd9Sstevel@tonic-gate #ifdef DIS_TEXT
3031*7c478bd9Sstevel@tonic-gate 
3032*7c478bd9Sstevel@tonic-gate /*
3033*7c478bd9Sstevel@tonic-gate  * Some instructions should have immediate operands printed
3034*7c478bd9Sstevel@tonic-gate  * as unsigned integers. We compare against this table.
3035*7c478bd9Sstevel@tonic-gate  */
3036*7c478bd9Sstevel@tonic-gate static char *unsigned_ops[] = {
3037*7c478bd9Sstevel@tonic-gate 	"or", "and", "xor", "test", "in", "out", "lcall", "ljmp",
3038*7c478bd9Sstevel@tonic-gate 	"rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl",
3039*7c478bd9Sstevel@tonic-gate 	0
3040*7c478bd9Sstevel@tonic-gate };
3041*7c478bd9Sstevel@tonic-gate 
3042*7c478bd9Sstevel@tonic-gate static int
3043*7c478bd9Sstevel@tonic-gate isunsigned_op(char *opcode)
3044*7c478bd9Sstevel@tonic-gate {
3045*7c478bd9Sstevel@tonic-gate 	char *where;
3046*7c478bd9Sstevel@tonic-gate 	int i;
3047*7c478bd9Sstevel@tonic-gate 	int is_unsigned = 0;
3048*7c478bd9Sstevel@tonic-gate 
3049*7c478bd9Sstevel@tonic-gate 	/*
3050*7c478bd9Sstevel@tonic-gate 	 * Work back to start of last mnemonic, since we may have
3051*7c478bd9Sstevel@tonic-gate 	 * prefixes on some opcodes.
3052*7c478bd9Sstevel@tonic-gate 	 */
3053*7c478bd9Sstevel@tonic-gate 	where = opcode + strlen(opcode) - 1;
3054*7c478bd9Sstevel@tonic-gate 	while (where > opcode && *where != ' ')
3055*7c478bd9Sstevel@tonic-gate 		--where;
3056*7c478bd9Sstevel@tonic-gate 	if (*where == ' ')
3057*7c478bd9Sstevel@tonic-gate 		++where;
3058*7c478bd9Sstevel@tonic-gate 
3059*7c478bd9Sstevel@tonic-gate 	for (i = 0; unsigned_ops[i]; ++i) {
3060*7c478bd9Sstevel@tonic-gate 		if (strncmp(where, unsigned_ops[i],
3061*7c478bd9Sstevel@tonic-gate 		    strlen(unsigned_ops[i])))
3062*7c478bd9Sstevel@tonic-gate 			continue;
3063*7c478bd9Sstevel@tonic-gate 		is_unsigned = 1;
3064*7c478bd9Sstevel@tonic-gate 		break;
3065*7c478bd9Sstevel@tonic-gate 	}
3066*7c478bd9Sstevel@tonic-gate 	return (is_unsigned);
3067*7c478bd9Sstevel@tonic-gate }
3068*7c478bd9Sstevel@tonic-gate 
3069*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
3070*7c478bd9Sstevel@tonic-gate void
3071*7c478bd9Sstevel@tonic-gate dtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf,
3072*7c478bd9Sstevel@tonic-gate     size_t buflen)
3073*7c478bd9Sstevel@tonic-gate {
3074*7c478bd9Sstevel@tonic-gate 	int i;
3075*7c478bd9Sstevel@tonic-gate 
3076*7c478bd9Sstevel@tonic-gate 	dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mneu);
3077*7c478bd9Sstevel@tonic-gate 
3078*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < dis->d86_numopnds; i++) {
3079*7c478bd9Sstevel@tonic-gate 		d86opnd_t *op = &dis->d86_opnd[i];
3080*7c478bd9Sstevel@tonic-gate 		int64_t sv;
3081*7c478bd9Sstevel@tonic-gate 		uint64_t mask;
3082*7c478bd9Sstevel@tonic-gate 
3083*7c478bd9Sstevel@tonic-gate 		if (i != 0)
3084*7c478bd9Sstevel@tonic-gate 			(void) strlcat(buf, ",", buflen);
3085*7c478bd9Sstevel@tonic-gate 
3086*7c478bd9Sstevel@tonic-gate 		(void) strlcat(buf, op->d86_prefix, buflen);
3087*7c478bd9Sstevel@tonic-gate 
3088*7c478bd9Sstevel@tonic-gate 		sv = op->d86_value;
3089*7c478bd9Sstevel@tonic-gate 
3090*7c478bd9Sstevel@tonic-gate 		switch (op->d86_mode) {
3091*7c478bd9Sstevel@tonic-gate 
3092*7c478bd9Sstevel@tonic-gate 		case MODE_NONE:
3093*7c478bd9Sstevel@tonic-gate 
3094*7c478bd9Sstevel@tonic-gate 			(void) strlcat(buf, op->d86_opnd, buflen);
3095*7c478bd9Sstevel@tonic-gate 			break;
3096*7c478bd9Sstevel@tonic-gate 
3097*7c478bd9Sstevel@tonic-gate 		case MODE_SIGNED:
3098*7c478bd9Sstevel@tonic-gate 		case MODE_IMPLIED:
3099*7c478bd9Sstevel@tonic-gate 		case MODE_OFFSET:
3100*7c478bd9Sstevel@tonic-gate 
3101*7c478bd9Sstevel@tonic-gate 			if (dis->d86_seg_prefix)
3102*7c478bd9Sstevel@tonic-gate 				strlcat(buf, dis->d86_seg_prefix, buflen);
3103*7c478bd9Sstevel@tonic-gate 
3104*7c478bd9Sstevel@tonic-gate 			switch (op->d86_value_size) {
3105*7c478bd9Sstevel@tonic-gate 			case 1:
3106*7c478bd9Sstevel@tonic-gate 				sv = (int8_t)sv;
3107*7c478bd9Sstevel@tonic-gate 				mask = 0xff;
3108*7c478bd9Sstevel@tonic-gate 				break;
3109*7c478bd9Sstevel@tonic-gate 			case 2:
3110*7c478bd9Sstevel@tonic-gate 				sv = (int16_t)sv;
3111*7c478bd9Sstevel@tonic-gate 				mask = 0xffff;
3112*7c478bd9Sstevel@tonic-gate 				break;
3113*7c478bd9Sstevel@tonic-gate 			case 4:
3114*7c478bd9Sstevel@tonic-gate 				sv = (int32_t)sv;
3115*7c478bd9Sstevel@tonic-gate 				mask = 0xffffffff;
3116*7c478bd9Sstevel@tonic-gate 				break;
3117*7c478bd9Sstevel@tonic-gate 			case 8:
3118*7c478bd9Sstevel@tonic-gate 				mask = 0xffffffffffffffff;
3119*7c478bd9Sstevel@tonic-gate 				break;
3120*7c478bd9Sstevel@tonic-gate 			}
3121*7c478bd9Sstevel@tonic-gate 
3122*7c478bd9Sstevel@tonic-gate 			if (op->d86_mode == MODE_SIGNED ||
3123*7c478bd9Sstevel@tonic-gate 			    op->d86_mode == MODE_IMPLIED)
3124*7c478bd9Sstevel@tonic-gate 				strlcat(buf, "$", buflen);
3125*7c478bd9Sstevel@tonic-gate 
3126*7c478bd9Sstevel@tonic-gate 			if (sv < 0 && sv > -0xffff &&
3127*7c478bd9Sstevel@tonic-gate 			    !isunsigned_op(dis->d86_mneu)) {
3128*7c478bd9Sstevel@tonic-gate 				dis->d86_sprintf_func(buf + strlen(buf),
3129*7c478bd9Sstevel@tonic-gate 				    buflen - strlen(buf),
3130*7c478bd9Sstevel@tonic-gate 				    (dis->d86_flags & DIS_OP_OCTAL) ?
3131*7c478bd9Sstevel@tonic-gate 				    "-0%llo" : "-0x%llx", -sv & mask);
3132*7c478bd9Sstevel@tonic-gate 			} else {
3133*7c478bd9Sstevel@tonic-gate 				dis->d86_sprintf_func(buf + strlen(buf),
3134*7c478bd9Sstevel@tonic-gate 				    buflen - strlen(buf),
3135*7c478bd9Sstevel@tonic-gate 				    (dis->d86_flags & DIS_OP_OCTAL) ?
3136*7c478bd9Sstevel@tonic-gate 				    "0%llo" : "0x%llx", sv & mask);
3137*7c478bd9Sstevel@tonic-gate 			}
3138*7c478bd9Sstevel@tonic-gate 			strlcat(buf, op->d86_opnd, buflen);
3139*7c478bd9Sstevel@tonic-gate 			break;
3140*7c478bd9Sstevel@tonic-gate 
3141*7c478bd9Sstevel@tonic-gate 		case MODE_IPREL:
3142*7c478bd9Sstevel@tonic-gate 
3143*7c478bd9Sstevel@tonic-gate 			switch (op->d86_value_size) {
3144*7c478bd9Sstevel@tonic-gate 			case 1:
3145*7c478bd9Sstevel@tonic-gate 				sv = (int8_t)sv;
3146*7c478bd9Sstevel@tonic-gate 				break;
3147*7c478bd9Sstevel@tonic-gate 			case 2:
3148*7c478bd9Sstevel@tonic-gate 				sv = (int16_t)sv;
3149*7c478bd9Sstevel@tonic-gate 				break;
3150*7c478bd9Sstevel@tonic-gate 			case 4:
3151*7c478bd9Sstevel@tonic-gate 				sv = (int32_t)sv;
3152*7c478bd9Sstevel@tonic-gate 				break;
3153*7c478bd9Sstevel@tonic-gate 			}
3154*7c478bd9Sstevel@tonic-gate 
3155*7c478bd9Sstevel@tonic-gate 			if (sv < 0)
3156*7c478bd9Sstevel@tonic-gate 				dis->d86_sprintf_func(buf + strlen(buf),
3157*7c478bd9Sstevel@tonic-gate 				    buflen - strlen(buf),
3158*7c478bd9Sstevel@tonic-gate 				    (dis->d86_flags & DIS_OP_OCTAL) ?
3159*7c478bd9Sstevel@tonic-gate 				    "-0%llo" : "-0x%llx", -sv - dis->d86_len);
3160*7c478bd9Sstevel@tonic-gate 			else
3161*7c478bd9Sstevel@tonic-gate 				dis->d86_sprintf_func(buf + strlen(buf),
3162*7c478bd9Sstevel@tonic-gate 				    buflen - strlen(buf),
3163*7c478bd9Sstevel@tonic-gate 				    (dis->d86_flags & DIS_OP_OCTAL) ?
3164*7c478bd9Sstevel@tonic-gate 				    "+0%llo" : "+0x%llx", sv + dis->d86_len);
3165*7c478bd9Sstevel@tonic-gate 
3166*7c478bd9Sstevel@tonic-gate 			strlcat(buf, "\t<", buflen);
3167*7c478bd9Sstevel@tonic-gate 
3168*7c478bd9Sstevel@tonic-gate 			if (dis->d86_sym_lookup == NULL ||
3169*7c478bd9Sstevel@tonic-gate 			    dis->d86_sym_lookup(pc + sv, buf + strlen(buf),
3170*7c478bd9Sstevel@tonic-gate 			    buflen - strlen(buf)) != 0)
3171*7c478bd9Sstevel@tonic-gate 				dis->d86_sprintf_func(buf + strlen(buf),
3172*7c478bd9Sstevel@tonic-gate 				    buflen - strlen(buf),
3173*7c478bd9Sstevel@tonic-gate 				    (dis->d86_flags & DIS_OP_OCTAL) ?
3174*7c478bd9Sstevel@tonic-gate 				    "0%llo" : "0x%llx", pc + sv);
3175*7c478bd9Sstevel@tonic-gate 
3176*7c478bd9Sstevel@tonic-gate 			strlcat(buf, ">", buflen);
3177*7c478bd9Sstevel@tonic-gate 
3178*7c478bd9Sstevel@tonic-gate 			break;
3179*7c478bd9Sstevel@tonic-gate 		}
3180*7c478bd9Sstevel@tonic-gate 	}
3181*7c478bd9Sstevel@tonic-gate }
3182*7c478bd9Sstevel@tonic-gate 
3183*7c478bd9Sstevel@tonic-gate #endif /* DIS_TEXT */
3184