dis_tables.c revision 238168
1179237Sjb/*
2179237Sjb * CDDL HEADER START
3179237Sjb *
4179237Sjb * The contents of this file are subject to the terms of the
5179237Sjb * Common Development and Distribution License (the "License").
6179237Sjb * You may not use this file except in compliance with the License.
7179237Sjb *
8179237Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9179237Sjb * or http://www.opensolaris.org/os/licensing.
10179237Sjb * See the License for the specific language governing permissions
11179237Sjb * and limitations under the License.
12179237Sjb *
13179237Sjb * When distributing Covered Code, include this CDDL HEADER in each
14179237Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15179237Sjb * If applicable, add the following below this CDDL HEADER, with the
16179237Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17179237Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18179237Sjb *
19179237Sjb * CDDL HEADER END
20179237Sjb *
21179237Sjb * $FreeBSD: head/sys/cddl/dev/dtrace/amd64/dis_tables.c 238168 2012-07-06 14:41:02Z avg $
22179237Sjb */
23179237Sjb/*
24179237Sjb * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25179237Sjb * Use is subject to license terms.
26179237Sjb */
27179237Sjb
28179237Sjb/*	Copyright (c) 1988 AT&T	*/
29179237Sjb/*	  All Rights Reserved  	*/
30179237Sjb
31179237Sjb
32179237Sjb#if defined(sun)
33179237Sjb#pragma ident	"@(#)dis_tables.c	1.11	06/03/02 SMI"
34179237Sjb#endif
35179237Sjb
36179237Sjb#include	"dis_tables.h"
37179237Sjb
38179237Sjb/* BEGIN CSTYLED */
39179237Sjb
40179237Sjb/*
41179237Sjb * Disassembly begins in dis_distable, which is equivalent to the One-byte
42179237Sjb * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy).  The
43179237Sjb * decoding loops then traverse out through the other tables as necessary to
44179237Sjb * decode a given instruction.
45179237Sjb *
46179237Sjb * The behavior of this file can be controlled by one of the following flags:
47179237Sjb *
48179237Sjb * 	DIS_TEXT	Include text for disassembly
49179237Sjb * 	DIS_MEM		Include memory-size calculations
50179237Sjb *
51179237Sjb * Either or both of these can be defined.
52179237Sjb *
53179237Sjb * This file is not, and will never be, cstyled.  If anything, the tables should
54179237Sjb * be taken out another tab stop or two so nothing overlaps.
55179237Sjb */
56179237Sjb
57179237Sjb/*
58179237Sjb * These functions must be provided for the consumer to do disassembly.
59179237Sjb */
60179237Sjb#ifdef DIS_TEXT
61179237Sjbextern char *strncpy(char *, const char *, size_t);
62179237Sjbextern size_t strlen(const char *);
63179237Sjbextern int strcmp(const char *, const char *);
64179237Sjbextern int strncmp(const char *, const char *, size_t);
65179237Sjbextern size_t strlcat(char *, const char *, size_t);
66179237Sjb#endif
67179237Sjb
68179237Sjb
69179237Sjb#define		TERM 	NULL	/* used to indicate that the 'indirect' */
70179237Sjb				/* field terminates - no pointer.	*/
71179237Sjb
72179237Sjb/* Used to decode instructions. */
73179237Sjbtypedef struct	instable {
74179237Sjb	const struct instable	*it_indirect;	/* for decode op codes */
75179237Sjb	uchar_t		it_adrmode;
76179237Sjb#ifdef DIS_TEXT
77179237Sjb	char		it_name[NCPS];
78179237Sjb	uint_t		it_suffix:1;		/* mneu + "w", "l", or "d" */
79179237Sjb#endif
80179237Sjb#ifdef DIS_MEM
81179237Sjb	uint_t		it_size:16;
82179237Sjb#endif
83179237Sjb	uint_t		it_invalid64:1;		/* opcode invalid in amd64 */
84179237Sjb	uint_t		it_always64:1;		/* 64 bit when in 64 bit mode */
85179237Sjb	uint_t		it_invalid32:1;		/* invalid in IA32 */
86179237Sjb	uint_t		it_stackop:1;		/* push/pop stack operation */
87179237Sjb} instable_t;
88179237Sjb
89179237Sjb/*
90179237Sjb * Instruction formats.
91179237Sjb */
92179237Sjbenum {
93179237Sjb	UNKNOWN,
94179237Sjb	MRw,
95179237Sjb	IMlw,
96179237Sjb	IMw,
97179237Sjb	IR,
98179237Sjb	OA,
99179237Sjb	AO,
100179237Sjb	MS,
101179237Sjb	SM,
102179237Sjb	Mv,
103179237Sjb	Mw,
104179237Sjb	M,		/* register or memory */
105179237Sjb	Mb,		/* register or memory, always byte sized */
106179237Sjb	MO,		/* memory only (no registers) */
107179237Sjb	PREF,
108179237Sjb	SWAPGS,
109179237Sjb	R,
110179237Sjb	RA,
111179237Sjb	SEG,
112179237Sjb	MR,
113179237Sjb	RM,
114179237Sjb	IA,
115179237Sjb	MA,
116179237Sjb	SD,
117179237Sjb	AD,
118179237Sjb	SA,
119179237Sjb	D,
120179237Sjb	INM,
121179237Sjb	SO,
122179237Sjb	BD,
123179237Sjb	I,
124179237Sjb	P,
125179237Sjb	V,
126179237Sjb	DSHIFT,		/* for double shift that has an 8-bit immediate */
127179237Sjb	U,
128179237Sjb	OVERRIDE,
129179237Sjb	NORM,		/* instructions w/o ModR/M byte, no memory access */
130179237Sjb	IMPLMEM,	/* instructions w/o ModR/M byte, implicit mem access */
131179237Sjb	O,		/* for call	*/
132179237Sjb	JTAB,		/* jump table 	*/
133179237Sjb	IMUL,		/* for 186 iimul instr  */
134179237Sjb	CBW,		/* so data16 can be evaluated for cbw and variants */
135179237Sjb	MvI,		/* for 186 logicals */
136179237Sjb	ENTER,		/* for 186 enter instr  */
137179237Sjb	RMw,		/* for 286 arpl instr */
138179237Sjb	Ib,		/* for push immediate byte */
139179237Sjb	F,		/* for 287 instructions */
140179237Sjb	FF,		/* for 287 instructions */
141179237Sjb	FFC,		/* for 287 instructions */
142179237Sjb	DM,		/* 16-bit data */
143179237Sjb	AM,		/* 16-bit addr */
144179237Sjb	LSEG,		/* for 3-bit seg reg encoding */
145179237Sjb	MIb,		/* for 386 logicals */
146179237Sjb	SREG,		/* for 386 special registers */
147179237Sjb	PREFIX,		/* a REP instruction prefix */
148179237Sjb	LOCK,		/* a LOCK instruction prefix */
149179237Sjb	INT3,		/* The int 3 instruction, which has a fake operand */
150179237Sjb	INTx,		/* The normal int instruction, with explicit int num */
151179237Sjb	DSHIFTcl,	/* for double shift that implicitly uses %cl */
152179237Sjb	CWD,		/* so data16 can be evaluated for cwd and variants */
153179237Sjb	RET,		/* single immediate 16-bit operand */
154179237Sjb	MOVZ,		/* for movs and movz, with different size operands */
155179237Sjb	XADDB,		/* for xaddb */
156179237Sjb	MOVSXZ,		/* AMD64 mov sign extend 32 to 64 bit instruction */
157179237Sjb
158179237Sjb/*
159179237Sjb * MMX/SIMD addressing modes.
160179237Sjb */
161179237Sjb
162179237Sjb	MMO,		/* Prefixable MMX/SIMD-Int	mm/mem	-> mm */
163179237Sjb	MMOIMPL,	/* Prefixable MMX/SIMD-Int	mm	-> mm (mem) */
164179237Sjb	MMO3P,		/* Prefixable MMX/SIMD-Int	mm	-> r32,imm8 */
165179237Sjb	MMOM3,		/* Prefixable MMX/SIMD-Int	mm	-> r32 	*/
166179237Sjb	MMOS,		/* Prefixable MMX/SIMD-Int	mm	-> mm/mem */
167179237Sjb	MMOMS,		/* Prefixable MMX/SIMD-Int	mm	-> mem */
168179237Sjb	MMOPM,		/* MMX/SIMD-Int			mm/mem	-> mm,imm8 */
169179237Sjb	MMOPRM,		/* Prefixable MMX/SIMD-Int	r32/mem	-> mm,imm8 */
170179237Sjb	MMOSH,		/* Prefixable MMX		mm,imm8	*/
171179237Sjb	MM,		/* MMX/SIMD-Int			mm/mem	-> mm	*/
172179237Sjb	MMS,		/* MMX/SIMD-Int			mm	-> mm/mem */
173179237Sjb	MMSH,		/* MMX				mm,imm8 */
174179237Sjb	XMMO,		/* Prefixable SIMD		xmm/mem	-> xmm */
175179237Sjb	XMMOS,		/* Prefixable SIMD		xmm	-> xmm/mem */
176179237Sjb	XMMOPM,		/* Prefixable SIMD		xmm/mem	w/to xmm,imm8 */
177179237Sjb	XMMOMX,		/* Prefixable SIMD		mm/mem	-> xmm */
178179237Sjb	XMMOX3,		/* Prefixable SIMD		xmm	-> r32 */
179179237Sjb	XMMOXMM,	/* Prefixable SIMD		xmm/mem	-> mm	*/
180179237Sjb	XMMOM,		/* Prefixable SIMD		xmm	-> mem */
181179237Sjb	XMMOMS,		/* Prefixable SIMD		mem	-> xmm */
182179237Sjb	XMM,		/* SIMD 			xmm/mem	-> xmm */
183179237Sjb	XMMXIMPL,	/* SIMD				xmm	-> xmm (mem) */
184179237Sjb	XMM3P,		/* SIMD				xmm	-> r32,imm8 */
185179237Sjb	XMMP,		/* SIMD 			xmm/mem w/to xmm,imm8 */
186179237Sjb	XMMPRM,		/* SIMD 			r32/mem -> xmm,imm8 */
187179237Sjb	XMMS,		/* SIMD				xmm	-> xmm/mem */
188179237Sjb	XMMM,		/* SIMD 			mem	-> xmm */
189179237Sjb	XMMMS,		/* SIMD				xmm	-> mem */
190179237Sjb	XMM3MX,		/* SIMD 			r32/mem -> xmm */
191179237Sjb	XMM3MXS,	/* SIMD 			xmm	-> r32/mem */
192179237Sjb	XMMSH,		/* SIMD 			xmm,imm8 */
193179237Sjb	XMMXM3,		/* SIMD 			xmm/mem -> r32 */
194179237Sjb	XMMX3,		/* SIMD 			xmm	-> r32 */
195179237Sjb	XMMXMM,		/* SIMD 			xmm/mem	-> mm */
196179237Sjb	XMMMX,		/* SIMD 			mm	-> xmm */
197179237Sjb	XMMXM,		/* SIMD 			xmm	-> mm */
198179237Sjb	XMMFENCE,	/* SIMD lfence or mfence */
199179237Sjb	XMMSFNC		/* SIMD sfence (none or mem) */
200179237Sjb};
201179237Sjb
202179237Sjb#define	FILL	0x90	/* Fill byte used for alignment (nop)	*/
203179237Sjb
204179237Sjb/*
205179237Sjb** Register numbers for the i386
206179237Sjb*/
207179237Sjb#define	EAX_REGNO 0
208179237Sjb#define	ECX_REGNO 1
209179237Sjb#define	EDX_REGNO 2
210179237Sjb#define	EBX_REGNO 3
211179237Sjb#define	ESP_REGNO 4
212179237Sjb#define	EBP_REGNO 5
213179237Sjb#define	ESI_REGNO 6
214179237Sjb#define	EDI_REGNO 7
215179237Sjb
216179237Sjb/*
217179237Sjb * modes for immediate values
218179237Sjb */
219179237Sjb#define	MODE_NONE	0
220179237Sjb#define	MODE_IPREL	1	/* signed IP relative value */
221179237Sjb#define	MODE_SIGNED	2	/* sign extended immediate */
222179237Sjb#define	MODE_IMPLIED	3	/* constant value implied from opcode */
223179237Sjb#define	MODE_OFFSET	4	/* offset part of an address */
224179237Sjb
225179237Sjb/*
226179237Sjb * The letters used in these macros are:
227179237Sjb *   IND - indirect to another to another table
228179237Sjb *   "T" - means to Terminate indirections (this is the final opcode)
229179237Sjb *   "S" - means "operand length suffix required"
230179237Sjb *   "NS" - means "no suffix" which is the operand length suffix of the opcode
231179237Sjb *   "Z" - means instruction size arg required
232179237Sjb *   "u" - means the opcode is invalid in IA32 but valid in amd64
233179237Sjb *   "x" - means the opcode is invalid in amd64, but not IA32
234179237Sjb *   "y" - means the operand size is always 64 bits in 64 bit mode
235179237Sjb *   "p" - means push/pop stack operation
236179237Sjb */
237179237Sjb
238179237Sjb#if defined(DIS_TEXT) && defined(DIS_MEM)
239179237Sjb#define	IND(table)		{table, 0, "", 0, 0, 0, 0, 0, 0}
240179237Sjb#define	INDx(table)		{table, 0, "", 0, 0, 1, 0, 0, 0}
241179237Sjb#define	TNS(name, amode)	{TERM, amode, name, 0, 0, 0, 0, 0, 0}
242179237Sjb#define	TNSu(name, amode)	{TERM, amode, name, 0, 0, 0, 0, 1, 0}
243179237Sjb#define	TNSx(name, amode)	{TERM, amode, name, 0, 0, 1, 0, 0, 0}
244179237Sjb#define	TNSy(name, amode)	{TERM, amode, name, 0, 0, 0, 1, 0, 0}
245179237Sjb#define	TNSyp(name, amode)	{TERM, amode, name, 0, 0, 0, 1, 0, 1}
246179237Sjb#define	TNSZ(name, amode, sz)	{TERM, amode, name, 0, sz, 0, 0, 0, 0}
247179237Sjb#define	TNSZy(name, amode, sz)	{TERM, amode, name, 0, sz, 0, 1, 0, 0}
248179237Sjb#define	TS(name, amode)		{TERM, amode, name, 1, 0, 0, 0, 0, 0}
249179237Sjb#define	TSx(name, amode)	{TERM, amode, name, 1, 0, 1, 0, 0, 0}
250179237Sjb#define	TSy(name, amode)	{TERM, amode, name, 1, 0, 0, 1, 0, 0}
251179237Sjb#define	TSp(name, amode)	{TERM, amode, name, 1, 0, 0, 0, 0, 1}
252179237Sjb#define	TSZ(name, amode, sz)	{TERM, amode, name, 1, sz, 0, 0, 0, 0}
253179237Sjb#define	TSZx(name, amode, sz)	{TERM, amode, name, 1, sz, 1, 0, 0, 0}
254179237Sjb#define	TSZy(name, amode, sz)	{TERM, amode, name, 1, sz, 0, 1, 0, 0}
255179237Sjb#define	INVALID			{TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
256179237Sjb#elif defined(DIS_TEXT)
257179237Sjb#define	IND(table)		{table, 0, "", 0, 0, 0, 0, 0}
258179237Sjb#define	INDx(table)		{table, 0, "", 0, 1, 0, 0, 0}
259179237Sjb#define	TNS(name, amode)	{TERM, amode, name, 0, 0, 0, 0, 0}
260179237Sjb#define	TNSu(name, amode)	{TERM, amode, name, 0, 0, 0, 1, 0}
261179237Sjb#define	TNSx(name, amode)	{TERM, amode, name, 0, 1, 0, 0, 0}
262179237Sjb#define	TNSy(name, amode)	{TERM, amode, name, 0, 0, 1, 0, 0}
263179237Sjb#define	TNSyp(name, amode)	{TERM, amode, name, 0, 0, 1, 0, 1}
264179237Sjb#define	TNSZ(name, amode, sz)	{TERM, amode, name, 0, 0, 0, 0, 0}
265179237Sjb#define	TNSZy(name, amode, sz)	{TERM, amode, name, 0, 0, 1, 0, 0}
266179237Sjb#define	TS(name, amode)		{TERM, amode, name, 1, 0, 0, 0, 0}
267179237Sjb#define	TSx(name, amode)	{TERM, amode, name, 1, 1, 0, 0, 0}
268179237Sjb#define	TSy(name, amode)	{TERM, amode, name, 1, 0, 1, 0, 0}
269179237Sjb#define	TSp(name, amode)	{TERM, amode, name, 1, 0, 0, 0, 1}
270179237Sjb#define	TSZ(name, amode, sz)	{TERM, amode, name, 1, 0, 0, 0, 0}
271179237Sjb#define	TSZx(name, amode, sz)	{TERM, amode, name, 1, 1, 0, 0, 0}
272179237Sjb#define	TSZy(name, amode, sz)	{TERM, amode, name, 1, 0, 1, 0, 0}
273179237Sjb#define	INVALID			{TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
274179237Sjb#elif defined(DIS_MEM)
275179237Sjb#define	IND(table)		{table, 0, 0, 0, 0, 0, 0}
276179237Sjb#define	INDx(table)		{table, 0, 0, 1, 0, 0, 0}
277179237Sjb#define	TNS(name, amode)	{TERM, amode,  0, 0, 0, 0, 0}
278179237Sjb#define	TNSu(name, amode)	{TERM, amode,  0, 0, 0, 1, 0}
279179237Sjb#define	TNSy(name, amode)	{TERM, amode,  0, 0, 1, 0, 0}
280179237Sjb#define	TNSyp(name, amode)	{TERM, amode,  0, 0, 1, 0, 1}
281179237Sjb#define	TNSx(name, amode)	{TERM, amode,  0, 1, 0, 0, 0}
282179237Sjb#define	TNSZ(name, amode, sz)	{TERM, amode, sz, 0, 0, 0, 0}
283179237Sjb#define	TNSZy(name, amode, sz)	{TERM, amode, sz, 0, 1, 0, 0}
284179237Sjb#define	TS(name, amode)		{TERM, amode,  0, 0, 0, 0, 0}
285179237Sjb#define	TSx(name, amode)	{TERM, amode,  0, 1, 0, 0, 0}
286179237Sjb#define	TSy(name, amode)	{TERM, amode,  0, 0, 1, 0, 0}
287179237Sjb#define	TSp(name, amode)	{TERM, amode,  0, 0, 0, 0, 1}
288179237Sjb#define	TSZ(name, amode, sz)	{TERM, amode, sz, 0, 0, 0, 0}
289179237Sjb#define	TSZx(name, amode, sz)	{TERM, amode, sz, 1, 0, 0, 0}
290179237Sjb#define	TSZy(name, amode, sz)	{TERM, amode, sz, 0, 1, 0, 0}
291179237Sjb#define	INVALID			{TERM, UNKNOWN, 0, 0, 0, 0, 0}
292179237Sjb#else
293179237Sjb#define	IND(table)		{table[0], 0, 0, 0, 0, 0}
294179237Sjb#define	INDx(table)		{table[0], 0, 1, 0, 0, 0}
295179237Sjb#define	TNS(name, amode)	{TERM, amode,  0, 0, 0, 0}
296179237Sjb#define	TNSu(name, amode)	{TERM, amode,  0, 0, 1, 0}
297179237Sjb#define	TNSy(name, amode)	{TERM, amode,  0, 1, 0, 0}
298179237Sjb#define	TNSyp(name, amode)	{TERM, amode,  0, 1, 0, 1}
299179237Sjb#define	TNSx(name, amode)	{TERM, amode,  1, 0, 0, 0}
300179237Sjb#define	TNSZ(name, amode, sz)	{TERM, amode,  0, 0, 0, 0}
301179237Sjb#define	TNSZy(name, amode, sz)	{TERM, amode,  0, 1, 0, 0}
302179237Sjb#define	TS(name, amode)		{TERM, amode,  0, 0, 0, 0}
303179237Sjb#define	TSx(name, amode)	{TERM, amode,  1, 0, 0, 0}
304179237Sjb#define	TSy(name, amode)	{TERM, amode,  0, 1, 0, 0}
305179237Sjb#define	TSp(name, amode)	{TERM, amode,  0, 0, 0, 1}
306179237Sjb#define	TSZ(name, amode, sz)	{TERM, amode,  0, 0, 0, 0}
307179237Sjb#define	TSZx(name, amode, sz)	{TERM, amode,  1, 0, 0, 0}
308179237Sjb#define	TSZy(name, amode, sz)	{TERM, amode,  0, 1, 0, 0}
309179237Sjb#define	INVALID			{TERM, UNKNOWN, 0, 0, 0, 0}
310179237Sjb#endif
311179237Sjb
312179237Sjb#ifdef DIS_TEXT
313179237Sjb/*
314179237Sjb * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode
315179237Sjb */
316179237Sjbconst char *const dis_addr16[3][8] = {
317179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "",
318179237Sjb									"(%bx)",
319179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)",
320179237Sjb									"(%bx)",
321179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)",
322179237Sjb									"(%bx)",
323179237Sjb};
324179237Sjb
325179237Sjb
326179237Sjb/*
327179237Sjb * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2
328179237Sjb */
329179237Sjbconst char *const dis_addr32_mode0[16] = {
330179237Sjb  "(%eax)", "(%ecx)", "(%edx)",  "(%ebx)",  "", "",        "(%esi)",  "(%edi)",
331179237Sjb  "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "",        "(%r14d)", "(%r15d)"
332179237Sjb};
333179237Sjb
334179237Sjbconst char *const dis_addr32_mode12[16] = {
335179237Sjb  "(%eax)", "(%ecx)", "(%edx)",  "(%ebx)",  "", "(%ebp)",  "(%esi)",  "(%edi)",
336179237Sjb  "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)"
337179237Sjb};
338179237Sjb
339179237Sjb/*
340179237Sjb * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2
341179237Sjb */
342179237Sjbconst char *const dis_addr64_mode0[16] = {
343179237Sjb "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "",       "(%rip)", "(%rsi)", "(%rdi)",
344179237Sjb "(%r8)",  "(%r9)",  "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)"
345179237Sjb};
346179237Sjbconst char *const dis_addr64_mode12[16] = {
347179237Sjb "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "",       "(%rbp)", "(%rsi)", "(%rdi)",
348179237Sjb "(%r8)",  "(%r9)",  "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)"
349179237Sjb};
350179237Sjb
351179237Sjb/*
352179237Sjb * decode for scale from SIB byte
353179237Sjb */
354179237Sjbconst char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" };
355179237Sjb
356179237Sjb/*
357179237Sjb * register decoding for normal references to registers (ie. not addressing)
358179237Sjb */
359179237Sjbconst char *const dis_REG8[16] = {
360179237Sjb	"%al",  "%cl",  "%dl",   "%bl",   "%ah",   "%ch",   "%dh",   "%bh",
361179237Sjb	"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
362179237Sjb};
363179237Sjb
364179237Sjbconst char *const dis_REG8_REX[16] = {
365179237Sjb	"%al",  "%cl",  "%dl",   "%bl",   "%spl",  "%bpl",  "%sil",  "%dil",
366179237Sjb	"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
367179237Sjb};
368179237Sjb
369179237Sjbconst char *const dis_REG16[16] = {
370179237Sjb	"%ax",  "%cx",  "%dx",   "%bx",   "%sp",   "%bp",   "%si",   "%di",
371179237Sjb	"%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
372179237Sjb};
373179237Sjb
374179237Sjbconst char *const dis_REG32[16] = {
375179237Sjb	"%eax", "%ecx", "%edx",  "%ebx",  "%esp",  "%ebp",  "%esi",  "%edi",
376179237Sjb	"%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
377179237Sjb};
378179237Sjb
379179237Sjbconst char *const dis_REG64[16] = {
380179237Sjb	"%rax", "%rcx", "%rdx",  "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
381179237Sjb	"%r8",  "%r9",  "%r10",  "%r11", "%r12", "%r13", "%r14", "%r15"
382179237Sjb};
383179237Sjb
384179237Sjbconst char *const dis_DEBUGREG[16] = {
385179237Sjb	"%db0", "%db1", "%db2",  "%db3",  "%db4",  "%db5",  "%db6",  "%db7",
386179237Sjb	"%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15"
387179237Sjb};
388179237Sjb
389179237Sjbconst char *const dis_CONTROLREG[16] = {
390179237Sjb    "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?",
391179237Sjb    "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?"
392179237Sjb};
393179237Sjb
394179237Sjbconst char *const dis_TESTREG[16] = {
395179237Sjb	"%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
396179237Sjb	"%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7"
397179237Sjb};
398179237Sjb
399179237Sjbconst char *const dis_MMREG[16] = {
400179237Sjb	"%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
401179237Sjb	"%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
402179237Sjb};
403179237Sjb
404179237Sjbconst char *const dis_XMMREG[16] = {
405179237Sjb    "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
406179237Sjb    "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15"
407179237Sjb};
408179237Sjb
409179237Sjbconst char *const dis_SEGREG[16] = {
410179237Sjb	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>",
411179237Sjb	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>"
412179237Sjb};
413179237Sjb
414179237Sjb/*
415179237Sjb * SIMD predicate suffixes
416179237Sjb */
417179237Sjbconst char *const dis_PREDSUFFIX[8] = {
418179237Sjb	"eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord"
419179237Sjb};
420179237Sjb
421179237Sjb
422179237Sjb
423179237Sjb#endif	/* DIS_TEXT */
424179237Sjb
425179237Sjb
426179237Sjb
427179237Sjb
428179237Sjb/*
429179237Sjb *	"decode table" for 64 bit mode MOVSXD instruction (opcode 0x63)
430179237Sjb */
431179237Sjbconst instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ);
432179237Sjb
433179237Sjb/*
434179237Sjb *	"decode table" for pause and clflush instructions
435179237Sjb */
436179237Sjbconst instable_t dis_opPause = TNS("pause", NORM);
437179237Sjb
438179237Sjb/*
439179237Sjb *	Decode table for 0x0F00 opcodes
440179237Sjb */
441179237Sjbconst instable_t dis_op0F00[8] = {
442179237Sjb
443179237Sjb/*  [0]  */	TNS("sldt",M),		TNS("str",M),		TNSy("lldt",M), 	TNSy("ltr",M),
444179237Sjb/*  [4]  */	TNSZ("verr",M,2),	TNSZ("verw",M,2),	INVALID,		INVALID,
445179237Sjb};
446179237Sjb
447179237Sjb
448179237Sjb/*
449179237Sjb *	Decode table for 0x0F01 opcodes
450179237Sjb */
451179237Sjbconst instable_t dis_op0F01[8] = {
452179237Sjb
453179237Sjb/*  [0]  */	TNSZ("sgdt",MO,6),	TNSZ("sidt",MO,6), 	TNSZ("lgdt",MO,6),	TNSZ("lidt",MO,6),
454179237Sjb/*  [4]  */	TNSZ("smsw",M,2),	INVALID, 		TNSZ("lmsw",M,2),	TNS("invlpg",SWAPGS),
455179237Sjb};
456179237Sjb
457179237Sjb/*
458179237Sjb *	Decode table for 0x0F18 opcodes -- SIMD prefetch
459179237Sjb */
460179237Sjbconst instable_t dis_op0F18[8] = {
461179237Sjb
462179237Sjb/*  [0]  */	TNS("prefetchnta",PREF),TNS("prefetcht0",PREF),	TNS("prefetcht1",PREF),	TNS("prefetcht2",PREF),
463179237Sjb/*  [4]  */	INVALID,		INVALID,		INVALID,		INVALID,
464179237Sjb};
465179237Sjb
466179237Sjb/*
467179237Sjb * 	Decode table for 0x0FAE opcodes -- SIMD state save/restore
468179237Sjb */
469179237Sjbconst instable_t dis_op0FAE[8] = {
470179237Sjb/*  [0]  */	TNSZ("fxsave",M,512),	TNSZ("fxrstor",M,512),	TNS("ldmxcsr",M),	TNS("stmxcsr",M),
471179237Sjb/*  [4]  */	INVALID,		TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE),	TNS("sfence",XMMSFNC),
472179237Sjb};
473179237Sjb
474179237Sjb/*
475179237Sjb *	Decode table for 0x0FBA opcodes
476179237Sjb */
477179237Sjb
478179237Sjbconst instable_t dis_op0FBA[8] = {
479179237Sjb
480179237Sjb/*  [0]  */	INVALID,		INVALID,		INVALID,		INVALID,
481179237Sjb/*  [4]  */	TS("bt",MIb),		TS("bts",MIb),		TS("btr",MIb),		TS("btc",MIb),
482179237Sjb};
483179237Sjb
484179237Sjb/*
485179237Sjb * 	Decode table for 0x0FC7 opcode
486179237Sjb */
487179237Sjb
488179237Sjbconst instable_t dis_op0FC7[8] = {
489179237Sjb
490179237Sjb/*  [0]  */	INVALID,		TNS("cmpxchg8b",M),	INVALID,		INVALID,
491179237Sjb/*  [4]  */	INVALID,		INVALID,	INVALID,		 INVALID,
492179237Sjb};
493179237Sjb
494179237Sjb
495179237Sjb/*
496179237Sjb *	Decode table for 0x0FC8 opcode -- 486 bswap instruction
497179237Sjb *
498179237Sjb *bit pattern: 0000 1111 1100 1reg
499179237Sjb */
500179237Sjbconst instable_t dis_op0FC8[4] = {
501179237Sjb/*  [0]  */	TNS("bswap",R),		INVALID,		INVALID,		INVALID,
502179237Sjb};
503179237Sjb
504179237Sjb/*
505179237Sjb *	Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions
506179237Sjb */
507179237Sjbconst instable_t dis_op0F7123[4][8] = {
508179237Sjb{
509179237Sjb/*  [70].0 */	INVALID,		INVALID,		INVALID,		INVALID,
510179237Sjb/*      .4 */	INVALID,		INVALID,		INVALID,		INVALID,
511179237Sjb}, {
512179237Sjb/*  [71].0 */	INVALID,		INVALID,		TNS("psrlw",MMOSH),	INVALID,
513179237Sjb/*      .4 */	TNS("psraw",MMOSH),	INVALID,		TNS("psllw",MMOSH),	INVALID,
514179237Sjb}, {
515179237Sjb/*  [72].0 */	INVALID,		INVALID,		TNS("psrld",MMOSH),	INVALID,
516179237Sjb/*      .4 */	TNS("psrad",MMOSH),	INVALID,		TNS("pslld",MMOSH),	INVALID,
517179237Sjb}, {
518179237Sjb/*  [73].0 */	INVALID,		INVALID,		TNS("psrlq",MMOSH),	TNS("INVALID",MMOSH),
519179237Sjb/*      .4 */	INVALID,		INVALID, 		TNS("psllq",MMOSH),	TNS("INVALID",MMOSH),
520179237Sjb} };
521179237Sjb
522179237Sjb/*
523179237Sjb *	Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes.
524179237Sjb */
525179237Sjbconst instable_t dis_opSIMD7123[32] = {
526179237Sjb/* [70].0 */	INVALID,		INVALID,		INVALID,		INVALID,
527179237Sjb/*     .4 */	INVALID,		INVALID,		INVALID,		INVALID,
528179237Sjb
529179237Sjb/* [71].0 */	INVALID,		INVALID,		TNS("psrlw",XMMSH),	INVALID,
530179237Sjb/*     .4 */	TNS("psraw",XMMSH),	INVALID,		TNS("psllw",XMMSH),	INVALID,
531179237Sjb
532179237Sjb/* [72].0 */	INVALID,		INVALID,		TNS("psrld",XMMSH),	INVALID,
533179237Sjb/*     .4 */	TNS("psrad",XMMSH),	INVALID,		TNS("pslld",XMMSH),	INVALID,
534179237Sjb
535179237Sjb/* [73].0 */	INVALID,		INVALID,		TNS("psrlq",XMMSH),	TNS("psrldq",XMMSH),
536179237Sjb/*     .4 */	INVALID,		INVALID,		TNS("psllq",XMMSH),	TNS("pslldq",XMMSH),
537179237Sjb};
538179237Sjb
539179237Sjb/*
540179237Sjb *	SIMD instructions have been wedged into the existing IA32 instruction
541179237Sjb *	set through the use of prefixes.  That is, while 0xf0 0x58 may be
542179237Sjb *	addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different
543179237Sjb *	instruction - addss.  At present, three prefixes have been coopted in
544179237Sjb *	this manner - address size (0x66), repnz (0xf2) and repz (0xf3).  The
545179237Sjb *	following tables are used to provide the prefixed instruction names.
546179237Sjb *	The arrays are sparse, but they're fast.
547179237Sjb */
548179237Sjb
549179237Sjb/*
550179237Sjb *	Decode table for SIMD instructions with the address size (0x66) prefix.
551179237Sjb */
552179237Sjbconst instable_t dis_opSIMDdata16[256] = {
553179237Sjb/*  [00]  */	INVALID,		INVALID,		INVALID,		INVALID,
554179237Sjb/*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
555179237Sjb/*  [08]  */	INVALID,		INVALID,		INVALID,		INVALID,
556179237Sjb/*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
557179237Sjb
558179237Sjb/*  [10]  */	TNSZ("movupd",XMM,16),	TNSZ("movupd",XMMS,16),	TNSZ("movlpd",XMMM,8),	TNSZ("movlpd",XMMMS,8),
559179237Sjb/*  [14]  */	TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8),	TNSZ("movhpd",XMMMS,8),
560179237Sjb/*  [18]  */	INVALID,		INVALID,		INVALID,		INVALID,
561179237Sjb/*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
562179237Sjb
563179237Sjb/*  [20]  */	INVALID,		INVALID,		INVALID,		INVALID,
564179237Sjb/*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
565179237Sjb/*  [28]  */	TNSZ("movapd",XMM,16),	TNSZ("movapd",XMMS,16),	TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16),
566179237Sjb/*  [2C]  */	TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8),
567179237Sjb
568179237Sjb/*  [30]  */	INVALID,		INVALID,		INVALID,		INVALID,
569179237Sjb/*  [34]  */	INVALID,		INVALID,		INVALID,		INVALID,
570179237Sjb/*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
571179237Sjb/*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
572179237Sjb
573179237Sjb/*  [40]  */	INVALID,		INVALID,		INVALID,		INVALID,
574179237Sjb/*  [44]  */	INVALID,		INVALID,		INVALID,		INVALID,
575179237Sjb/*  [48]  */	INVALID,		INVALID,		INVALID,		INVALID,
576179237Sjb/*  [4C]  */	INVALID,		INVALID,		INVALID,		INVALID,
577179237Sjb
578179237Sjb/*  [50]  */	TNS("movmskpd",XMMOX3),	TNSZ("sqrtpd",XMM,16),	INVALID,		INVALID,
579179237Sjb/*  [54]  */	TNSZ("andpd",XMM,16),	TNSZ("andnpd",XMM,16),	TNSZ("orpd",XMM,16),	TNSZ("xorpd",XMM,16),
580179237Sjb/*  [58]  */	TNSZ("addpd",XMM,16),	TNSZ("mulpd",XMM,16),	TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16),
581179237Sjb/*  [5C]  */	TNSZ("subpd",XMM,16),	TNSZ("minpd",XMM,16),	TNSZ("divpd",XMM,16),	TNSZ("maxpd",XMM,16),
582179237Sjb
583179237Sjb/*  [60]  */	TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16),
584179237Sjb/*  [64]  */	TNSZ("pcmpgtb",XMM,16),	TNSZ("pcmpgtw",XMM,16),	TNSZ("pcmpgtd",XMM,16),	TNSZ("packuswb",XMM,16),
585179237Sjb/*  [68]  */	TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16),
586179237Sjb/*  [6C]  */	TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16),
587179237Sjb
588179237Sjb/*  [70]  */	TNSZ("pshufd",XMMP,16),	INVALID,		INVALID,		INVALID,
589179237Sjb/*  [74]  */	TNSZ("pcmpeqb",XMM,16),	TNSZ("pcmpeqw",XMM,16),	TNSZ("pcmpeqd",XMM,16),	INVALID,
590179237Sjb/*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
591179237Sjb/*  [7C]  */	INVALID,		INVALID,		TNSZ("movd",XMM3MXS,4),	TNSZ("movdqa",XMMS,16),
592179237Sjb
593179237Sjb/*  [80]  */	INVALID,		INVALID,		INVALID,		INVALID,
594179237Sjb/*  [84]  */	INVALID,		INVALID,		INVALID,		INVALID,
595179237Sjb/*  [88]  */	INVALID,		INVALID,		INVALID,		INVALID,
596179237Sjb/*  [8C]  */	INVALID,		INVALID,		INVALID,		INVALID,
597179237Sjb
598179237Sjb/*  [90]  */	INVALID,		INVALID,		INVALID,		INVALID,
599179237Sjb/*  [94]  */	INVALID,		INVALID,		INVALID,		INVALID,
600179237Sjb/*  [98]  */	INVALID,		INVALID,		INVALID,		INVALID,
601179237Sjb/*  [9C]  */	INVALID,		INVALID,		INVALID,		INVALID,
602179237Sjb
603179237Sjb/*  [A0]  */	INVALID,		INVALID,		INVALID,		INVALID,
604179237Sjb/*  [A4]  */	INVALID,		INVALID,		INVALID,		INVALID,
605179237Sjb/*  [A8]  */	INVALID,		INVALID,		INVALID,		INVALID,
606179237Sjb/*  [AC]  */	INVALID,		INVALID,		INVALID,		INVALID,
607179237Sjb
608179237Sjb/*  [B0]  */	INVALID,		INVALID,		INVALID,		INVALID,
609179237Sjb/*  [B4]  */	INVALID,		INVALID,		INVALID,		INVALID,
610179237Sjb/*  [B8]  */	INVALID,		INVALID,		INVALID,		INVALID,
611179237Sjb/*  [BC]  */	INVALID,		INVALID,		INVALID,		INVALID,
612179237Sjb
613179237Sjb/*  [C0]  */	INVALID,		INVALID,		TNSZ("cmppd",XMMP,16),	INVALID,
614179237Sjb/*  [C4]  */	TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P),	TNSZ("shufpd",XMMP,16),	INVALID,
615179237Sjb/*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
616179237Sjb/*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
617179237Sjb
618179237Sjb/*  [D0]  */	INVALID,		TNSZ("psrlw",XMM,16),	TNSZ("psrld",XMM,16),	TNSZ("psrlq",XMM,16),
619179237Sjb/*  [D4]  */	TNSZ("paddq",XMM,16),	TNSZ("pmullw",XMM,16),	TNSZ("movq",XMMS,8),	TNS("pmovmskb",XMMX3),
620179237Sjb/*  [D8]  */	TNSZ("psubusb",XMM,16),	TNSZ("psubusw",XMM,16),	TNSZ("pminub",XMM,16),	TNSZ("pand",XMM,16),
621179237Sjb/*  [DC]  */	TNSZ("paddusb",XMM,16),	TNSZ("paddusw",XMM,16),	TNSZ("pmaxub",XMM,16),	TNSZ("pandn",XMM,16),
622179237Sjb
623179237Sjb/*  [E0]  */	TNSZ("pavgb",XMM,16),	TNSZ("psraw",XMM,16),	TNSZ("psrad",XMM,16),	TNSZ("pavgw",XMM,16),
624179237Sjb/*  [E4]  */	TNSZ("pmulhuw",XMM,16),	TNSZ("pmulhw",XMM,16),	TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16),
625179237Sjb/*  [E8]  */	TNSZ("psubsb",XMM,16),	TNSZ("psubsw",XMM,16),	TNSZ("pminsw",XMM,16),	TNSZ("por",XMM,16),
626179237Sjb/*  [EC]  */	TNSZ("paddsb",XMM,16),	TNSZ("paddsw",XMM,16),	TNSZ("pmaxsw",XMM,16),	TNSZ("pxor",XMM,16),
627179237Sjb
628179237Sjb/*  [F0]  */	INVALID,		TNSZ("psllw",XMM,16),	TNSZ("pslld",XMM,16),	TNSZ("psllq",XMM,16),
629179237Sjb/*  [F4]  */	TNSZ("pmuludq",XMM,16),	TNSZ("pmaddwd",XMM,16),	TNSZ("psadbw",XMM,16),	TNSZ("maskmovdqu", XMMXIMPL,16),
630179237Sjb/*  [F8]  */	TNSZ("psubb",XMM,16),	TNSZ("psubw",XMM,16),	TNSZ("psubd",XMM,16),	TNSZ("psubq",XMM,16),
631179237Sjb/*  [FC]  */	TNSZ("paddb",XMM,16),	TNSZ("paddw",XMM,16),	TNSZ("paddd",XMM,16),	INVALID,
632179237Sjb};
633179237Sjb
634179237Sjb/*
635179237Sjb *	Decode table for SIMD instructions with the repnz (0xf2) prefix.
636179237Sjb */
637179237Sjbconst instable_t dis_opSIMDrepnz[256] = {
638179237Sjb/*  [00]  */	INVALID,		INVALID,		INVALID,		INVALID,
639179237Sjb/*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
640179237Sjb/*  [08]  */	INVALID,		INVALID,		INVALID,		INVALID,
641179237Sjb/*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
642179237Sjb
643179237Sjb/*  [10]  */	TNSZ("movsd",XMM,8),	TNSZ("movsd",XMMS,8),	INVALID,		INVALID,
644179237Sjb/*  [14]  */	INVALID,		INVALID,		INVALID,		INVALID,
645179237Sjb/*  [18]  */	INVALID,		INVALID,		INVALID,		INVALID,
646179237Sjb/*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
647179237Sjb
648179237Sjb/*  [20]  */	INVALID,		INVALID,		INVALID,		INVALID,
649179237Sjb/*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
650179237Sjb/*  [28]  */	INVALID,		INVALID,		TNSZ("cvtsi2sd",XMM3MX,4),INVALID,
651179237Sjb/*  [2C]  */	TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID,		INVALID,
652179237Sjb
653179237Sjb/*  [30]  */	INVALID,		INVALID,		INVALID,		INVALID,
654179237Sjb/*  [34]  */	INVALID,		INVALID,		INVALID,		INVALID,
655179237Sjb/*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
656179237Sjb/*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
657179237Sjb
658179237Sjb/*  [40]  */	INVALID,		INVALID,		INVALID,		INVALID,
659179237Sjb/*  [44]  */	INVALID,		INVALID,		INVALID,		INVALID,
660179237Sjb/*  [48]  */	INVALID,		INVALID,		INVALID,		INVALID,
661179237Sjb/*  [4C]  */	INVALID,		INVALID,		INVALID,		INVALID,
662179237Sjb
663179237Sjb/*  [50]  */	INVALID,		TNSZ("sqrtsd",XMM,8),	INVALID,		INVALID,
664179237Sjb/*  [54]  */	INVALID,		INVALID,		INVALID,		INVALID,
665179237Sjb/*  [58]  */	TNSZ("addsd",XMM,8),	TNSZ("mulsd",XMM,8),	TNSZ("cvtsd2ss",XMM,8),	INVALID,
666179237Sjb/*  [5C]  */	TNSZ("subsd",XMM,8),	TNSZ("minsd",XMM,8),	TNSZ("divsd",XMM,8),	TNSZ("maxsd",XMM,8),
667179237Sjb
668179237Sjb/*  [60]  */	INVALID,		INVALID,		INVALID,		INVALID,
669179237Sjb/*  [64]  */	INVALID,		INVALID,		INVALID,		INVALID,
670179237Sjb/*  [68]  */	INVALID,		INVALID,		INVALID,		INVALID,
671179237Sjb/*  [6C]  */	INVALID,		INVALID,		INVALID,		INVALID,
672179237Sjb
673179237Sjb/*  [70]  */	TNSZ("pshuflw",XMMP,16),INVALID,		INVALID,		INVALID,
674179237Sjb/*  [74]  */	INVALID,		INVALID,		INVALID,		INVALID,
675179237Sjb/*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
676179237Sjb/*  [7C]  */	INVALID,		INVALID,		INVALID,		INVALID,
677179237Sjb
678179237Sjb/*  [80]  */	INVALID,		INVALID,		INVALID,		INVALID,
679179237Sjb/*  [84]  */	INVALID,		INVALID,		INVALID,		INVALID,
680179237Sjb/*  [88]  */	INVALID,		INVALID,		INVALID,		INVALID,
681179237Sjb/*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
682179237Sjb
683179237Sjb/*  [90]  */	INVALID,		INVALID,		INVALID,		INVALID,
684179237Sjb/*  [94]  */	INVALID,		INVALID,		INVALID,		INVALID,
685179237Sjb/*  [98]  */	INVALID,		INVALID,		INVALID,		INVALID,
686179237Sjb/*  [9C]  */	INVALID,		INVALID,		INVALID,		INVALID,
687179237Sjb
688179237Sjb/*  [A0]  */	INVALID,		INVALID,		INVALID,		INVALID,
689179237Sjb/*  [A4]  */	INVALID,		INVALID,		INVALID,		INVALID,
690179237Sjb/*  [A8]  */	INVALID,		INVALID,		INVALID,		INVALID,
691179237Sjb/*  [AC]  */	INVALID,		INVALID,		INVALID,		INVALID,
692179237Sjb
693179237Sjb/*  [B0]  */	INVALID,		INVALID,		INVALID,		INVALID,
694179237Sjb/*  [B4]  */	INVALID,		INVALID,		INVALID,		INVALID,
695179237Sjb/*  [B8]  */	INVALID,		INVALID,		INVALID,		INVALID,
696179237Sjb/*  [BC]  */	INVALID,		INVALID,		INVALID,		INVALID,
697179237Sjb
698179237Sjb/*  [C0]  */	INVALID,		INVALID,		TNSZ("cmpsd",XMMP,8),	INVALID,
699179237Sjb/*  [C4]  */	INVALID,		INVALID,		INVALID,		INVALID,
700179237Sjb/*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
701179237Sjb/*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
702179237Sjb
703179237Sjb/*  [D0]  */	INVALID,		INVALID,		INVALID,		INVALID,
704179237Sjb/*  [D4]  */	INVALID,		INVALID,		TNS("movdq2q",XMMXM),	INVALID,
705179237Sjb/*  [D8]  */	INVALID,		INVALID,		INVALID,		INVALID,
706179237Sjb/*  [DC]  */	INVALID,		INVALID,		INVALID,		INVALID,
707179237Sjb
708179237Sjb/*  [E0]  */	INVALID,		INVALID,		INVALID,		INVALID,
709179237Sjb/*  [E4]  */	INVALID,		INVALID,		TNSZ("cvtpd2dq",XMM,16),INVALID,
710179237Sjb/*  [E8]  */	INVALID,		INVALID,		INVALID,		INVALID,
711179237Sjb/*  [EC]  */	INVALID,		INVALID,		INVALID,		INVALID,
712179237Sjb
713179237Sjb/*  [F0]  */	INVALID,		INVALID,		INVALID,		INVALID,
714179237Sjb/*  [F4]  */	INVALID,		INVALID,		INVALID,		INVALID,
715179237Sjb/*  [F8]  */	INVALID,		INVALID,		INVALID,		INVALID,
716179237Sjb/*  [FC]  */	INVALID,		INVALID,		INVALID,		INVALID,
717179237Sjb};
718179237Sjb
719179237Sjb/*
720179237Sjb *	Decode table for SIMD instructions with the repz (0xf3) prefix.
721179237Sjb */
722179237Sjbconst instable_t dis_opSIMDrepz[256] = {
723179237Sjb/*  [00]  */	INVALID,		INVALID,		INVALID,		INVALID,
724179237Sjb/*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
725179237Sjb/*  [08]  */	INVALID,		INVALID,		INVALID,		INVALID,
726179237Sjb/*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
727179237Sjb
728179237Sjb/*  [10]  */	TNSZ("movss",XMM,4),	TNSZ("movss",XMMS,4),	INVALID,		INVALID,
729179237Sjb/*  [14]  */	INVALID,		INVALID,		INVALID,		INVALID,
730179237Sjb/*  [18]  */	INVALID,		INVALID,		INVALID,		INVALID,
731179237Sjb/*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
732179237Sjb
733179237Sjb/*  [20]  */	INVALID,		INVALID,		INVALID,		INVALID,
734179237Sjb/*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
735179237Sjb/*  [28]  */	INVALID,		INVALID,		TNSZ("cvtsi2ss",XMM3MX,4),INVALID,
736179237Sjb/*  [2C]  */	TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID,		INVALID,
737179237Sjb
738179237Sjb/*  [30]  */	INVALID,		INVALID,		INVALID,		INVALID,
739179237Sjb/*  [34]  */	INVALID,		INVALID,		INVALID,		INVALID,
740179237Sjb/*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
741179237Sjb/*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
742179237Sjb
743179237Sjb/*  [40]  */	INVALID,		INVALID,		INVALID,		INVALID,
744179237Sjb/*  [44]  */	INVALID,		INVALID,		INVALID,		INVALID,
745179237Sjb/*  [48]  */	INVALID,		INVALID,		INVALID,		INVALID,
746179237Sjb/*  [4C]  */	INVALID,		INVALID,		INVALID,		INVALID,
747179237Sjb
748179237Sjb/*  [50]  */	INVALID,		TNSZ("sqrtss",XMM,4),	TNSZ("rsqrtss",XMM,4),	TNSZ("rcpss",XMM,4),
749179237Sjb/*  [54]  */	INVALID,		INVALID,		INVALID,		INVALID,
750179237Sjb/*  [58]  */	TNSZ("addss",XMM,4),	TNSZ("mulss",XMM,4),	TNSZ("cvtss2sd",XMM,4),	TNSZ("cvttps2dq",XMM,16),
751179237Sjb/*  [5C]  */	TNSZ("subss",XMM,4),	TNSZ("minss",XMM,4),	TNSZ("divss",XMM,4),	TNSZ("maxss",XMM,4),
752179237Sjb
753179237Sjb/*  [60]  */	INVALID,		INVALID,		INVALID,		INVALID,
754179237Sjb/*  [64]  */	INVALID,		INVALID,		INVALID,		INVALID,
755179237Sjb/*  [68]  */	INVALID,		INVALID,		INVALID,		INVALID,
756179237Sjb/*  [6C]  */	INVALID,		INVALID,		INVALID,		TNSZ("movdqu",XMM,16),
757179237Sjb
758179237Sjb/*  [70]  */	TNSZ("pshufhw",XMMP,16),INVALID,		INVALID,		INVALID,
759179237Sjb/*  [74]  */	INVALID,		INVALID,		INVALID,		INVALID,
760179237Sjb/*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
761179237Sjb/*  [7C]  */	INVALID,		INVALID,		TNSZ("movq",XMM,8),	TNSZ("movdqu",XMMS,16),
762179237Sjb
763179237Sjb/*  [80]  */	INVALID,		INVALID,		INVALID,		INVALID,
764179237Sjb/*  [84]  */	INVALID,		INVALID,		INVALID,		INVALID,
765179237Sjb/*  [88]  */	INVALID,		INVALID,		INVALID,		INVALID,
766179237Sjb/*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
767179237Sjb
768179237Sjb/*  [90]  */	INVALID,		INVALID,		INVALID,		INVALID,
769179237Sjb/*  [94]  */	INVALID,		INVALID,		INVALID,		INVALID,
770179237Sjb/*  [98]  */	INVALID,		INVALID,		INVALID,		INVALID,
771179237Sjb/*  [9C]  */	INVALID,		INVALID,		INVALID,		INVALID,
772179237Sjb
773179237Sjb/*  [A0]  */	INVALID,		INVALID,		INVALID,		INVALID,
774179237Sjb/*  [A4]  */	INVALID,		INVALID,		INVALID,		INVALID,
775179237Sjb/*  [A8]  */	INVALID,		INVALID,		INVALID,		INVALID,
776179237Sjb/*  [AC]  */	INVALID,		INVALID,		INVALID,		INVALID,
777179237Sjb
778179237Sjb/*  [B0]  */	INVALID,		INVALID,		INVALID,		INVALID,
779179237Sjb/*  [B4]  */	INVALID,		INVALID,		INVALID,		INVALID,
780179237Sjb/*  [B8]  */	INVALID,		INVALID,		INVALID,		INVALID,
781179237Sjb/*  [BC]  */	INVALID,		INVALID,		INVALID,		INVALID,
782179237Sjb
783179237Sjb/*  [C0]  */	INVALID,		INVALID,		TNSZ("cmpss",XMMP,4),	INVALID,
784179237Sjb/*  [C4]  */	INVALID,		INVALID,		INVALID,		INVALID,
785179237Sjb/*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
786179237Sjb/*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
787179237Sjb
788179237Sjb/*  [D0]  */	INVALID,		INVALID,		INVALID,		INVALID,
789179237Sjb/*  [D4]  */	INVALID,		INVALID,		TNS("movq2dq",XMMMX),	INVALID,
790179237Sjb/*  [D8]  */	INVALID,		INVALID,		INVALID,		INVALID,
791179237Sjb/*  [DC]  */	INVALID,		INVALID,		INVALID,		INVALID,
792179237Sjb
793179237Sjb/*  [E0]  */	INVALID,		INVALID,		INVALID,		INVALID,
794179237Sjb/*  [E4]  */	INVALID,		INVALID,		TNSZ("cvtdq2pd",XMM,8),	INVALID,
795179237Sjb/*  [E8]  */	INVALID,		INVALID,		INVALID,		INVALID,
796179237Sjb/*  [EC]  */	INVALID,		INVALID,		INVALID,		INVALID,
797179237Sjb
798179237Sjb/*  [F0]  */	INVALID,		INVALID,		INVALID,		INVALID,
799179237Sjb/*  [F4]  */	INVALID,		INVALID,		INVALID,		INVALID,
800179237Sjb/*  [F8]  */	INVALID,		INVALID,		INVALID,		INVALID,
801179237Sjb/*  [FC]  */	INVALID,		INVALID,		INVALID,		INVALID,
802179237Sjb};
803179237Sjb
804179237Sjb/*
805179237Sjb *	Decode table for 0x0F opcodes
806179237Sjb */
807179237Sjb
808179237Sjbconst instable_t dis_op0F[16][16] = {
809179237Sjb{
810179237Sjb/*  [00]  */	IND(dis_op0F00),	IND(dis_op0F01),	TNS("lar",MR),		TNS("lsl",MR),
811179237Sjb/*  [04]  */	INVALID,		TNS("syscall",NORM),	TNS("clts",NORM),	TNS("sysret",NORM),
812179237Sjb/*  [08]  */	TNS("invd",NORM),	TNS("wbinvd",NORM),	INVALID,		TNS("ud2",NORM),
813179237Sjb/*  [0C]  */	INVALID,		INVALID,		INVALID,		INVALID,
814179237Sjb}, {
815179237Sjb/*  [10]  */	TNSZ("movups",XMMO,16),	TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8),	TNSZ("movlps",XMMOS,8),
816179237Sjb/*  [14]  */	TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8),
817179237Sjb/*  [18]  */	IND(dis_op0F18),	INVALID,		INVALID,		INVALID,
818237748Savg/*  [1C]  */	INVALID,		INVALID,		INVALID,		TNS("nopw", M),
819179237Sjb}, {
820179237Sjb/*  [20]  */	TSy("mov",SREG),	TSy("mov",SREG),	TSy("mov",SREG),	TSy("mov",SREG),
821179237Sjb/*  [24]  */	TSx("mov",SREG),	INVALID,		TSx("mov",SREG),	INVALID,
822179237Sjb/*  [28]  */	TNSZ("movaps",XMMO,16),	TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16),
823179237Sjb/*  [2C]  */	TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4),
824179237Sjb}, {
825179237Sjb/*  [30]  */	TNS("wrmsr",NORM),	TNS("rdtsc",NORM),	TNS("rdmsr",NORM),	TNS("rdpmc",NORM),
826179237Sjb/*  [34]  */	TNSx("sysenter",NORM),	TNSx("sysexit",NORM),	INVALID,		INVALID,
827179237Sjb/*  [38]  */	INVALID,		INVALID,		INVALID,		INVALID,
828179237Sjb/*  [3C]  */	INVALID,		INVALID,		INVALID,		INVALID,
829179237Sjb}, {
830179237Sjb/*  [40]  */	TS("cmovx.o",MR),	TS("cmovx.no",MR),	TS("cmovx.b",MR),	TS("cmovx.ae",MR),
831179237Sjb/*  [44]  */	TS("cmovx.e",MR),	TS("cmovx.ne",MR),	TS("cmovx.be",MR),	TS("cmovx.a",MR),
832179237Sjb/*  [48]  */	TS("cmovx.s",MR),	TS("cmovx.ns",MR),	TS("cmovx.pe",MR),	TS("cmovx.po",MR),
833179237Sjb/*  [4C]  */	TS("cmovx.l",MR),	TS("cmovx.ge",MR),	TS("cmovx.le",MR),	TS("cmovx.g",MR),
834179237Sjb}, {
835179237Sjb/*  [50]  */	TNS("movmskps",XMMOX3),	TNSZ("sqrtps",XMMO,16),	TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16),
836179237Sjb/*  [54]  */	TNSZ("andps",XMMO,16),	TNSZ("andnps",XMMO,16),	TNSZ("orps",XMMO,16),	TNSZ("xorps",XMMO,16),
837179237Sjb/*  [58]  */	TNSZ("addps",XMMO,16),	TNSZ("mulps",XMMO,16),	TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16),
838179237Sjb/*  [5C]  */	TNSZ("subps",XMMO,16),	TNSZ("minps",XMMO,16),	TNSZ("divps",XMMO,16),	TNSZ("maxps",XMMO,16),
839179237Sjb}, {
840179237Sjb/*  [60]  */	TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8),
841179237Sjb/*  [64]  */	TNSZ("pcmpgtb",MMO,8),	TNSZ("pcmpgtw",MMO,8),	TNSZ("pcmpgtd",MMO,8),	TNSZ("packuswb",MMO,8),
842179237Sjb/*  [68]  */	TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8),
843179237Sjb/*  [6C]  */	TNSZ("INVALID",MMO,0),	TNSZ("INVALID",MMO,0),	TNSZ("movd",MMO,4),	TNSZ("movq",MMO,8),
844179237Sjb}, {
845179237Sjb/*  [70]  */	TNSZ("pshufw",MMOPM,8),	TNS("psrXXX",MR),	TNS("psrXXX",MR),	TNS("psrXXX",MR),
846179237Sjb/*  [74]  */	TNSZ("pcmpeqb",MMO,8),	TNSZ("pcmpeqw",MMO,8),	TNSZ("pcmpeqd",MMO,8),	TNS("emms",NORM),
847179237Sjb/*  [78]  */	INVALID,		INVALID,		INVALID,		INVALID,
848179237Sjb/*  [7C]  */	INVALID,		INVALID,		TNSZ("movd",MMOS,4),	TNSZ("movq",MMOS,8),
849179237Sjb}, {
850179237Sjb/*  [80]  */	TNS("jo",D),		TNS("jno",D),		TNS("jb",D),		TNS("jae",D),
851179237Sjb/*  [84]  */	TNS("je",D),		TNS("jne",D),		TNS("jbe",D),		TNS("ja",D),
852179237Sjb/*  [88]  */	TNS("js",D),		TNS("jns",D),		TNS("jp",D),		TNS("jnp",D),
853179237Sjb/*  [8C]  */	TNS("jl",D),		TNS("jge",D),		TNS("jle",D),		TNS("jg",D),
854179237Sjb}, {
855179237Sjb/*  [90]  */	TNS("seto",Mb),		TNS("setno",Mb),	TNS("setb",Mb),		TNS("setae",Mb),
856179237Sjb/*  [94]  */	TNS("sete",Mb),		TNS("setne",Mb),	TNS("setbe",Mb),	TNS("seta",Mb),
857179237Sjb/*  [98]  */	TNS("sets",Mb),		TNS("setns",Mb),	TNS("setp",Mb),		TNS("setnp",Mb),
858179237Sjb/*  [9C]  */	TNS("setl",Mb),		TNS("setge",Mb),	TNS("setle",Mb),	TNS("setg",Mb),
859179237Sjb}, {
860179237Sjb/*  [A0]  */	TSp("push",LSEG),	TSp("pop",LSEG),	TNS("cpuid",NORM),	TS("bt",RMw),
861179237Sjb/*  [A4]  */	TS("shld",DSHIFT),	TS("shld",DSHIFTcl),	INVALID,		INVALID,
862179237Sjb/*  [A8]  */	TSp("push",LSEG),	TSp("pop",LSEG),	TNS("rsm",NORM),	TS("bts",RMw),
863179237Sjb/*  [AC]  */	TS("shrd",DSHIFT),	TS("shrd",DSHIFTcl),	IND(dis_op0FAE),	TS("imul",MRw),
864179237Sjb}, {
865179237Sjb/*  [B0]  */	TNS("cmpxchgb",RMw),	TS("cmpxchg",RMw),	TS("lss",MR),		TS("btr",RMw),
866179237Sjb/*  [B4]  */	TS("lfs",MR),		TS("lgs",MR),		TS("movzb",MOVZ),	TNS("movzwl",MOVZ),
867179237Sjb/*  [B8]  */	INVALID,		INVALID,		IND(dis_op0FBA),	TS("btc",RMw),
868179237Sjb/*  [BC]  */	TS("bsf",MRw),		TS("bsr",MRw),		TS("movsb",MOVZ),	TNS("movswl",MOVZ),
869179237Sjb}, {
870179237Sjb/*  [C0]  */	TNS("xaddb",XADDB),	TS("xadd",RMw),		TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM),
871179237Sjb/*  [C4]  */	TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), 	TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7),
872179237Sjb/*  [C8]  */	INVALID,		INVALID,		INVALID,		INVALID,
873179237Sjb/*  [CC]  */	INVALID,		INVALID,		INVALID,		INVALID,
874179237Sjb}, {
875179237Sjb/*  [D0]  */	INVALID,		TNSZ("psrlw",MMO,8),	TNSZ("psrld",MMO,8),	TNSZ("psrlq",MMO,8),
876179237Sjb/*  [D4]  */	TNSZ("paddq",MMO,8),	TNSZ("pmullw",MMO,8),	TNSZ("INVALID",MMO,0),	TNS("pmovmskb",MMOM3),
877179237Sjb/*  [D8]  */	TNSZ("psubusb",MMO,8),	TNSZ("psubusw",MMO,8),	TNSZ("pminub",MMO,8),	TNSZ("pand",MMO,8),
878179237Sjb/*  [DC]  */	TNSZ("paddusb",MMO,8),	TNSZ("paddusw",MMO,8),	TNSZ("pmaxub",MMO,8),	TNSZ("pandn",MMO,8),
879179237Sjb}, {
880179237Sjb/*  [E0]  */	TNSZ("pavgb",MMO,8),	TNSZ("psraw",MMO,8),	TNSZ("psrad",MMO,8),	TNSZ("pavgw",MMO,8),
881179237Sjb/*  [E4]  */	TNSZ("pmulhuw",MMO,8),	TNSZ("pmulhw",MMO,8),	TNS("INVALID",XMMO),	TNSZ("movntq",MMOMS,8),
882179237Sjb/*  [E8]  */	TNSZ("psubsb",MMO,8),	TNSZ("psubsw",MMO,8),	TNSZ("pminsw",MMO,8),	TNSZ("por",MMO,8),
883179237Sjb/*  [EC]  */	TNSZ("paddsb",MMO,8),	TNSZ("paddsw",MMO,8),	TNSZ("pmaxsw",MMO,8),	TNSZ("pxor",MMO,8),
884179237Sjb}, {
885179237Sjb/*  [F0]  */	INVALID,		TNSZ("psllw",MMO,8),	TNSZ("pslld",MMO,8),	TNSZ("psllq",MMO,8),
886179237Sjb/*  [F4]  */	TNSZ("pmuludq",MMO,8),	TNSZ("pmaddwd",MMO,8),	TNSZ("psadbw",MMO,8),	TNSZ("maskmovq",MMOIMPL,8),
887179237Sjb/*  [F8]  */	TNSZ("psubb",MMO,8),	TNSZ("psubw",MMO,8),	TNSZ("psubd",MMO,8),	TNSZ("psubq",MMO,8),
888179237Sjb/*  [FC]  */	TNSZ("paddb",MMO,8),	TNSZ("paddw",MMO,8),	TNSZ("paddd",MMO,8),	INVALID,
889179237Sjb} };
890179237Sjb
891179237Sjb
892179237Sjb/*
893179237Sjb *	Decode table for 0x80 opcodes
894179237Sjb */
895179237Sjb
896179237Sjbconst instable_t dis_op80[8] = {
897179237Sjb
898179237Sjb/*  [0]  */	TNS("addb",IMlw),	TNS("orb",IMw),		TNS("adcb",IMlw),	TNS("sbbb",IMlw),
899179237Sjb/*  [4]  */	TNS("andb",IMw),	TNS("subb",IMlw),	TNS("xorb",IMw),	TNS("cmpb",IMlw),
900179237Sjb};
901179237Sjb
902179237Sjb
903179237Sjb/*
904179237Sjb *	Decode table for 0x81 opcodes.
905179237Sjb */
906179237Sjb
907179237Sjbconst instable_t dis_op81[8] = {
908179237Sjb
909179237Sjb/*  [0]  */	TS("add",IMlw),		TS("or",IMw),		TS("adc",IMlw),		TS("sbb",IMlw),
910179237Sjb/*  [4]  */	TS("and",IMw),		TS("sub",IMlw),		TS("xor",IMw),		TS("cmp",IMlw),
911179237Sjb};
912179237Sjb
913179237Sjb
914179237Sjb/*
915179237Sjb *	Decode table for 0x82 opcodes.
916179237Sjb */
917179237Sjb
918179237Sjbconst instable_t dis_op82[8] = {
919179237Sjb
920179237Sjb/*  [0]  */	TNSx("addb",IMlw),	TNSx("orb",IMlw),	TNSx("adcb",IMlw),	TNSx("sbbb",IMlw),
921179237Sjb/*  [4]  */	TNSx("andb",IMlw),	TNSx("subb",IMlw),	TNSx("xorb",IMlw),	TNSx("cmpb",IMlw),
922179237Sjb};
923179237Sjb/*
924179237Sjb *	Decode table for 0x83 opcodes.
925179237Sjb */
926179237Sjb
927179237Sjbconst instable_t dis_op83[8] = {
928179237Sjb
929179237Sjb/*  [0]  */	TS("add",IMlw),		TS("or",IMlw),		TS("adc",IMlw),		TS("sbb",IMlw),
930179237Sjb/*  [4]  */	TS("and",IMlw),		TS("sub",IMlw),		TS("xor",IMlw),		TS("cmp",IMlw),
931179237Sjb};
932179237Sjb
933179237Sjb/*
934179237Sjb *	Decode table for 0xC0 opcodes.
935179237Sjb */
936179237Sjb
937179237Sjbconst instable_t dis_opC0[8] = {
938179237Sjb
939179237Sjb/*  [0]  */	TNS("rolb",MvI),	TNS("rorb",MvI),	TNS("rclb",MvI),	TNS("rcrb",MvI),
940179237Sjb/*  [4]  */	TNS("shlb",MvI),	TNS("shrb",MvI),	INVALID,		TNS("sarb",MvI),
941179237Sjb};
942179237Sjb
943179237Sjb/*
944179237Sjb *	Decode table for 0xD0 opcodes.
945179237Sjb */
946179237Sjb
947179237Sjbconst instable_t dis_opD0[8] = {
948179237Sjb
949179237Sjb/*  [0]  */	TNS("rolb",Mv),		TNS("rorb",Mv),		TNS("rclb",Mv),		TNS("rcrb",Mv),
950179237Sjb/*  [4]  */	TNS("shlb",Mv),		TNS("shrb",Mv),		TNS("salb",Mv),		TNS("sarb",Mv),
951179237Sjb};
952179237Sjb
953179237Sjb/*
954179237Sjb *	Decode table for 0xC1 opcodes.
955179237Sjb *	186 instruction set
956179237Sjb */
957179237Sjb
958179237Sjbconst instable_t dis_opC1[8] = {
959179237Sjb
960179237Sjb/*  [0]  */	TS("rol",MvI),		TS("ror",MvI),		TS("rcl",MvI),		TS("rcr",MvI),
961179237Sjb/*  [4]  */	TS("shl",MvI),		TS("shr",MvI),		TS("sal",MvI),		TS("sar",MvI),
962179237Sjb};
963179237Sjb
964179237Sjb/*
965179237Sjb *	Decode table for 0xD1 opcodes.
966179237Sjb */
967179237Sjb
968179237Sjbconst instable_t dis_opD1[8] = {
969179237Sjb
970179237Sjb/*  [0]  */	TS("rol",Mv),		TS("ror",Mv),		TS("rcl",Mv),		TS("rcr",Mv),
971179237Sjb/*  [4]  */	TS("shl",Mv),		TS("shr",Mv),		TS("sal",Mv),		TS("sar",Mv),
972179237Sjb};
973179237Sjb
974179237Sjb
975179237Sjb/*
976179237Sjb *	Decode table for 0xD2 opcodes.
977179237Sjb */
978179237Sjb
979179237Sjbconst instable_t dis_opD2[8] = {
980179237Sjb
981179237Sjb/*  [0]  */	TNS("rolb",Mv),		TNS("rorb",Mv),		TNS("rclb",Mv),		TNS("rcrb",Mv),
982179237Sjb/*  [4]  */	TNS("shlb",Mv),		TNS("shrb",Mv),		TNS("salb",Mv),		TNS("sarb",Mv),
983179237Sjb};
984179237Sjb/*
985179237Sjb *	Decode table for 0xD3 opcodes.
986179237Sjb */
987179237Sjb
988179237Sjbconst instable_t dis_opD3[8] = {
989179237Sjb
990179237Sjb/*  [0]  */	TS("rol",Mv),		TS("ror",Mv),		TS("rcl",Mv),		TS("rcr",Mv),
991179237Sjb/*  [4]  */	TS("shl",Mv),		TS("shr",Mv),		TS("salb",Mv),		TS("sar",Mv),
992179237Sjb};
993179237Sjb
994179237Sjb
995179237Sjb/*
996179237Sjb *	Decode table for 0xF6 opcodes.
997179237Sjb */
998179237Sjb
999179237Sjbconst instable_t dis_opF6[8] = {
1000179237Sjb
1001179237Sjb/*  [0]  */	TNS("testb",IMw),	TNS("testb",IMw),	TNS("notb",Mw),		TNS("negb",Mw),
1002179237Sjb/*  [4]  */	TNS("mulb",MA),		TNS("imulb",MA),	TNS("divb",MA),		TNS("idivb",MA),
1003179237Sjb};
1004179237Sjb
1005179237Sjb
1006179237Sjb/*
1007179237Sjb *	Decode table for 0xF7 opcodes.
1008179237Sjb */
1009179237Sjb
1010179237Sjbconst instable_t dis_opF7[8] = {
1011179237Sjb
1012179237Sjb/*  [0]  */	TS("test",IMw),		TS("test",IMw),		TS("not",Mw),		TS("neg",Mw),
1013179237Sjb/*  [4]  */	TS("mul",MA),		TS("imul",MA),		TS("div",MA),		TS("idiv",MA),
1014179237Sjb};
1015179237Sjb
1016179237Sjb
1017179237Sjb/*
1018179237Sjb *	Decode table for 0xFE opcodes.
1019179237Sjb */
1020179237Sjb
1021179237Sjbconst instable_t dis_opFE[8] = {
1022179237Sjb
1023179237Sjb/*  [0]  */	TNS("incb",Mw),		TNS("decb",Mw),		INVALID,		INVALID,
1024179237Sjb/*  [4]  */	INVALID,		INVALID,		INVALID,		INVALID,
1025179237Sjb};
1026179237Sjb/*
1027179237Sjb *	Decode table for 0xFF opcodes.
1028179237Sjb */
1029179237Sjb
1030179237Sjbconst instable_t dis_opFF[8] = {
1031179237Sjb
1032179237Sjb/*  [0]  */	TS("inc",Mw),		TS("dec",Mw),		TNSyp("call",INM),	TNS("lcall",INM),
1033179237Sjb/*  [4]  */	TNSy("jmp",INM),	TNS("ljmp",INM),	TSp("push",M),		INVALID,
1034179237Sjb};
1035179237Sjb
1036179237Sjb/* for 287 instructions, which are a mess to decode */
1037179237Sjb
1038179237Sjbconst instable_t dis_opFP1n2[8][8] = {
1039179237Sjb{
1040179237Sjb/* bit pattern:	1101 1xxx MODxx xR/M */
1041179237Sjb/*  [0,0] */	TNS("fadds",M),		TNS("fmuls",M),		TNS("fcoms",M),		TNS("fcomps",M),
1042179237Sjb/*  [0,4] */	TNS("fsubs",M),		TNS("fsubrs",M),	TNS("fdivs",M),		TNS("fdivrs",M),
1043179237Sjb}, {
1044179237Sjb/*  [1,0]  */	TNS("flds",M),		INVALID,		TNS("fsts",M),		TNS("fstps",M),
1045179237Sjb/*  [1,4]  */	TNSZ("fldenv",M,28),	TNSZ("fldcw",M,2),	TNSZ("fnstenv",M,28),	TNSZ("fnstcw",M,2),
1046179237Sjb}, {
1047179237Sjb/*  [2,0]  */	TNS("fiaddl",M),	TNS("fimull",M),	TNS("ficoml",M),	TNS("ficompl",M),
1048179237Sjb/*  [2,4]  */	TNS("fisubl",M),	TNS("fisubrl",M),	TNS("fidivl",M),	TNS("fidivrl",M),
1049179237Sjb}, {
1050179237Sjb/*  [3,0]  */	TNS("fildl",M),		INVALID,		TNS("fistl",M),		TNS("fistpl",M),
1051179237Sjb/*  [3,4]  */	INVALID,		TNSZ("fldt",M,10),	INVALID,		TNSZ("fstpt",M,10),
1052179237Sjb}, {
1053179237Sjb/*  [4,0]  */	TNSZ("faddl",M,8),	TNSZ("fmull",M,8),	TNSZ("fcoml",M,8),	TNSZ("fcompl",M,8),
1054179237Sjb/*  [4,1]  */	TNSZ("fsubl",M,8),	TNSZ("fsubrl",M,8),	TNSZ("fdivl",M,8),	TNSZ("fdivrl",M,8),
1055179237Sjb}, {
1056179237Sjb/*  [5,0]  */	TNSZ("fldl",M,8),	INVALID,		TNSZ("fstl",M,8),	TNSZ("fstpl",M,8),
1057179237Sjb/*  [5,4]  */	TNSZ("frstor",M,108),	INVALID,		TNSZ("fnsave",M,108),	TNSZ("fnstsw",M,2),
1058179237Sjb}, {
1059179237Sjb/*  [6,0]  */	TNSZ("fiadd",M,2),	TNSZ("fimul",M,2),	TNSZ("ficom",M,2),	TNSZ("ficomp",M,2),
1060179237Sjb/*  [6,4]  */	TNSZ("fisub",M,2),	TNSZ("fisubr",M,2),	TNSZ("fidiv",M,2),	TNSZ("fidivr",M,2),
1061179237Sjb}, {
1062179237Sjb/*  [7,0]  */	TNSZ("fild",M,2),	INVALID,		TNSZ("fist",M,2),	TNSZ("fistp",M,2),
1063179237Sjb/*  [7,4]  */	TNSZ("fbld",M,10),	TNSZ("fildll",M,8),	TNSZ("fbstp",M,10),	TNSZ("fistpll",M,8),
1064179237Sjb} };
1065179237Sjb
1066179237Sjbconst instable_t dis_opFP3[8][8] = {
1067179237Sjb{
1068179237Sjb/* bit  pattern:	1101 1xxx 11xx xREG */
1069179237Sjb/*  [0,0]  */	TNS("fadd",FF),		TNS("fmul",FF),		TNS("fcom",F),		TNS("fcomp",F),
1070179237Sjb/*  [0,4]  */	TNS("fsub",FF),		TNS("fsubr",FF),	TNS("fdiv",FF),		TNS("fdivr",FF),
1071179237Sjb}, {
1072179237Sjb/*  [1,0]  */	TNS("fld",F),		TNS("fxch",F),		TNS("fnop",NORM),	TNS("fstp",F),
1073179237Sjb/*  [1,4]  */	INVALID,		INVALID,		INVALID,		INVALID,
1074179237Sjb}, {
1075179237Sjb/*  [2,0]  */	INVALID,		INVALID,		INVALID,		INVALID,
1076179237Sjb/*  [2,4]  */	INVALID,		TNS("fucompp",NORM),	INVALID,		INVALID,
1077179237Sjb}, {
1078179237Sjb/*  [3,0]  */	INVALID,		INVALID,		INVALID,		INVALID,
1079179237Sjb/*  [3,4]  */	INVALID,		INVALID,		INVALID,		INVALID,
1080179237Sjb}, {
1081179237Sjb/*  [4,0]  */	TNS("fadd",FF),		TNS("fmul",FF),		TNS("fcom",F),		TNS("fcomp",F),
1082179237Sjb/*  [4,4]  */	TNS("fsub",FF),		TNS("fsubr",FF),	TNS("fdiv",FF),		TNS("fdivr",FF),
1083179237Sjb}, {
1084179237Sjb/*  [5,0]  */	TNS("ffree",F),		TNS("fxch",F),		TNS("fst",F),		TNS("fstp",F),
1085179237Sjb/*  [5,4]  */	TNS("fucom",F),		TNS("fucomp",F),	INVALID,		INVALID,
1086179237Sjb}, {
1087179237Sjb/*  [6,0]  */	TNS("faddp",FF),	TNS("fmulp",FF),	TNS("fcomp",F),		TNS("fcompp",NORM),
1088179237Sjb/*  [6,4]  */	TNS("fsubp",FF),	TNS("fsubrp",FF),	TNS("fdivp",FF),	TNS("fdivrp",FF),
1089179237Sjb}, {
1090179237Sjb/*  [7,0]  */	TNS("ffree",F),		TNS("fxch",F),		TNS("fstp",F),		TNS("fstp",F),
1091179237Sjb/*  [7,4]  */	TNS("fnstsw",M),	TNS("fucomip",FFC),	TNS("fcomip",FFC),	INVALID,
1092179237Sjb} };
1093179237Sjb
1094179237Sjbconst instable_t dis_opFP4[4][8] = {
1095179237Sjb{
1096179237Sjb/* bit pattern:	1101 1001 111x xxxx */
1097179237Sjb/*  [0,0]  */	TNS("fchs",NORM),	TNS("fabs",NORM),	INVALID,		INVALID,
1098179237Sjb/*  [0,4]  */	TNS("ftst",NORM),	TNS("fxam",NORM),	TNS("ftstp",NORM),	INVALID,
1099179237Sjb}, {
1100179237Sjb/*  [1,0]  */	TNS("fld1",NORM),	TNS("fldl2t",NORM),	TNS("fldl2e",NORM),	TNS("fldpi",NORM),
1101179237Sjb/*  [1,4]  */	TNS("fldlg2",NORM),	TNS("fldln2",NORM),	TNS("fldz",NORM),	INVALID,
1102179237Sjb}, {
1103179237Sjb/*  [2,0]  */	TNS("f2xm1",NORM),	TNS("fyl2x",NORM),	TNS("fptan",NORM),	TNS("fpatan",NORM),
1104179237Sjb/*  [2,4]  */	TNS("fxtract",NORM),	TNS("fprem1",NORM),	TNS("fdecstp",NORM),	TNS("fincstp",NORM),
1105179237Sjb}, {
1106179237Sjb/*  [3,0]  */	TNS("fprem",NORM),	TNS("fyl2xp1",NORM),	TNS("fsqrt",NORM),	TNS("fsincos",NORM),
1107179237Sjb/*  [3,4]  */	TNS("frndint",NORM),	TNS("fscale",NORM),	TNS("fsin",NORM),	TNS("fcos",NORM),
1108179237Sjb} };
1109179237Sjb
1110179237Sjbconst instable_t dis_opFP5[8] = {
1111179237Sjb/* bit pattern:	1101 1011 111x xxxx */
1112179237Sjb/*  [0]  */	TNS("feni",NORM),	TNS("fdisi",NORM),	TNS("fnclex",NORM),	TNS("fninit",NORM),
1113179237Sjb/*  [4]  */	TNS("fsetpm",NORM),	TNS("frstpm",NORM),	INVALID,		INVALID,
1114179237Sjb};
1115179237Sjb
1116179237Sjbconst instable_t dis_opFP6[8] = {
1117179237Sjb/* bit pattern:	1101 1011 11yy yxxx */
1118179237Sjb/*  [00]  */	TNS("fcmov.nb",FF),	TNS("fcmov.ne",FF),	TNS("fcmov.nbe",FF),	TNS("fcmov.nu",FF),
1119179237Sjb/*  [04]  */	INVALID,		TNS("fucomi",F),	TNS("fcomi",F),		INVALID,
1120179237Sjb};
1121179237Sjb
1122179237Sjbconst instable_t dis_opFP7[8] = {
1123179237Sjb/* bit pattern:	1101 1010 11yy yxxx */
1124179237Sjb/*  [00]  */	TNS("fcmov.b",FF),	TNS("fcmov.e",FF),	TNS("fcmov.be",FF),	TNS("fcmov.u",FF),
1125179237Sjb/*  [04]  */	INVALID,		INVALID,		INVALID,		INVALID,
1126179237Sjb};
1127179237Sjb
1128179237Sjb/*
1129179237Sjb *	Main decode table for the op codes.  The first two nibbles
1130179237Sjb *	will be used as an index into the table.  If there is a
1131179237Sjb *	a need to further decode an instruction, the array to be
1132179237Sjb *	referenced is indicated with the other two entries being
1133179237Sjb *	empty.
1134179237Sjb */
1135179237Sjb
1136179237Sjbconst instable_t dis_distable[16][16] = {
1137179237Sjb{
1138179237Sjb/* [0,0] */	TNS("addb",RMw),	TS("add",RMw),		TNS("addb",MRw),	TS("add",MRw),
1139179237Sjb/* [0,4] */	TNS("addb",IA),		TS("add",IA),		TSx("push",SEG),	TSx("pop",SEG),
1140179237Sjb/* [0,8] */	TNS("orb",RMw),		TS("or",RMw),		TNS("orb",MRw),		TS("or",MRw),
1141179237Sjb/* [0,C] */	TNS("orb",IA),		TS("or",IA),		TSx("push",SEG),	IND(&dis_op0F[0][0]),
1142179237Sjb}, {
1143179237Sjb/* [1,0] */	TNS("adcb",RMw),	TS("adc",RMw),		TNS("adcb",MRw),	TS("adc",MRw),
1144179237Sjb/* [1,4] */	TNS("adcb",IA),		TS("adc",IA),		TSx("push",SEG),	TSx("pop",SEG),
1145179237Sjb/* [1,8] */	TNS("sbbb",RMw),	TS("sbb",RMw),		TNS("sbbb",MRw),	TS("sbb",MRw),
1146179237Sjb/* [1,C] */	TNS("sbbb",IA),		TS("sbb",IA),		TSx("push",SEG),	TSx("pop",SEG),
1147179237Sjb}, {
1148179237Sjb/* [2,0] */	TNS("andb",RMw),	TS("and",RMw),		TNS("andb",MRw),	TS("and",MRw),
1149238168Savg/* [2,4] */	TNS("andb",IA),		TS("and",IA),		TNS("%es:",OVERRIDE),	TNSx("daa",NORM),
1150179237Sjb/* [2,8] */	TNS("subb",RMw),	TS("sub",RMw),		TNS("subb",MRw),	TS("sub",MRw),
1151238168Savg/* [2,C] */	TNS("subb",IA),		TS("sub",IA),		TNS("%cs:",OVERRIDE),	TNSx("das",NORM),
1152179237Sjb}, {
1153179237Sjb/* [3,0] */	TNS("xorb",RMw),	TS("xor",RMw),		TNS("xorb",MRw),	TS("xor",MRw),
1154238168Savg/* [3,4] */	TNS("xorb",IA),		TS("xor",IA),		TNS("%ss:",OVERRIDE),	TNSx("aaa",NORM),
1155179237Sjb/* [3,8] */	TNS("cmpb",RMw),	TS("cmp",RMw),		TNS("cmpb",MRw),	TS("cmp",MRw),
1156238168Savg/* [3,C] */	TNS("cmpb",IA),		TS("cmp",IA),		TNS("%ds:",OVERRIDE),	TNSx("aas",NORM),
1157179237Sjb}, {
1158179237Sjb/* [4,0] */	TSx("inc",R),		TSx("inc",R),		TSx("inc",R),		TSx("inc",R),
1159179237Sjb/* [4,4] */	TSx("inc",R),		TSx("inc",R),		TSx("inc",R),		TSx("inc",R),
1160179237Sjb/* [4,8] */	TSx("dec",R),		TSx("dec",R),		TSx("dec",R),		TSx("dec",R),
1161179237Sjb/* [4,C] */	TSx("dec",R),		TSx("dec",R),		TSx("dec",R),		TSx("dec",R),
1162179237Sjb}, {
1163179237Sjb/* [5,0] */	TSp("push",R),		TSp("push",R),		TSp("push",R),		TSp("push",R),
1164179237Sjb/* [5,4] */	TSp("push",R),		TSp("push",R),		TSp("push",R),		TSp("push",R),
1165179237Sjb/* [5,8] */	TSp("pop",R),		TSp("pop",R),		TSp("pop",R),		TSp("pop",R),
1166179237Sjb/* [5,C] */	TSp("pop",R),		TSp("pop",R),		TSp("pop",R),		TSp("pop",R),
1167179237Sjb}, {
1168179237Sjb/* [6,0] */	TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR),	TNS("arpl",RMw),
1169179237Sjb/* [6,4] */	TNS("%fs:",OVERRIDE),	TNS("%gs:",OVERRIDE),	TNS("data16",DM),	TNS("addr16",AM),
1170179237Sjb/* [6,8] */	TSp("push",I),		TS("imul",IMUL),	TSp("push",Ib),	TS("imul",IMUL),
1171179237Sjb/* [6,C] */	TNSZ("insb",IMPLMEM,1),	TSZ("ins",IMPLMEM,4),	TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4),
1172179237Sjb}, {
1173179237Sjb/* [7,0] */	TNSy("jo",BD),		TNSy("jno",BD),		TNSy("jb",BD),		TNSy("jae",BD),
1174179237Sjb/* [7,4] */	TNSy("je",BD),		TNSy("jne",BD),		TNSy("jbe",BD),		TNSy("ja",BD),
1175179237Sjb/* [7,8] */	TNSy("js",BD),		TNSy("jns",BD),		TNSy("jp",BD),		TNSy("jnp",BD),
1176179237Sjb/* [7,C] */	TNSy("jl",BD),		TNSy("jge",BD),		TNSy("jle",BD),		TNSy("jg",BD),
1177179237Sjb}, {
1178179237Sjb/* [8,0] */	IND(dis_op80),		IND(dis_op81),		INDx(dis_op82),		IND(dis_op83),
1179179237Sjb/* [8,4] */	TNS("testb",RMw),	TS("test",RMw),		TNS("xchgb",RMw),	TS("xchg",RMw),
1180179237Sjb/* [8,8] */	TNS("movb",RMw),	TS("mov",RMw),		TNS("movb",MRw),	TS("mov",MRw),
1181179237Sjb/* [8,C] */	TNS("movw",SM),		TS("lea",MR),		TNS("movw",MS),		TSp("pop",M),
1182179237Sjb}, {
1183179237Sjb/* [9,0] */	TNS("nop",NORM),	TS("xchg",RA),		TS("xchg",RA),		TS("xchg",RA),
1184179237Sjb/* [9,4] */	TS("xchg",RA),		TS("xchg",RA),		TS("xchg",RA),		TS("xchg",RA),
1185179237Sjb/* [9,8] */	TNS("cXtX",CBW),	TNS("cXtX",CWD),	TNSx("lcall",SO),	TNS("fwait",NORM),
1186179237Sjb/* [9,C] */	TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4),	TNSx("sahf",NORM),	TNSx("lahf",NORM),
1187179237Sjb}, {
1188179237Sjb/* [A,0] */	TNS("movb",OA),		TS("mov",OA),		TNS("movb",AO),		TS("mov",AO),
1189179237Sjb/* [A,4] */	TNSZ("movsb",SD,1),	TS("movs",SD),		TNSZ("cmpsb",SD,1),	TS("cmps",SD),
1190179237Sjb/* [A,8] */	TNS("testb",IA),	TS("test",IA),		TNS("stosb",AD),	TS("stos",AD),
1191179237Sjb/* [A,C] */	TNS("lodsb",SA),	TS("lods",SA),		TNS("scasb",AD),	TS("scas",AD),
1192179237Sjb}, {
1193179237Sjb/* [B,0] */	TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),
1194179237Sjb/* [B,4] */	TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),		TNS("movb",IR),
1195179237Sjb/* [B,8] */	TS("mov",IR),		TS("mov",IR),		TS("mov",IR),		TS("mov",IR),
1196179237Sjb/* [B,C] */	TS("mov",IR),		TS("mov",IR),		TS("mov",IR),		TS("mov",IR),
1197179237Sjb}, {
1198179237Sjb/* [C,0] */	IND(dis_opC0),		IND(dis_opC1), 		TNSyp("ret",RET),	TNSyp("ret",NORM),
1199179237Sjb/* [C,4] */	TNSx("les",MR),		TNSx("lds",MR),		TNS("movb",IMw),	TS("mov",IMw),
1200179237Sjb/* [C,8] */	TNSyp("enter",ENTER),	TNSyp("leave",NORM),	TNS("lret",RET),	TNS("lret",NORM),
1201179237Sjb/* [C,C] */	TNS("int",INT3),	TNS("int",INTx),	TNSx("into",NORM),	TNS("iret",NORM),
1202179237Sjb}, {
1203179237Sjb/* [D,0] */	IND(dis_opD0),		IND(dis_opD1),		IND(dis_opD2),		IND(dis_opD3),
1204179237Sjb/* [D,4] */	TNSx("aam",U),		TNSx("aad",U),		TNSx("falc",NORM),	TNSZ("xlat",IMPLMEM,1),
1205179237Sjb
1206179237Sjb/* 287 instructions.  Note that although the indirect field		*/
1207179237Sjb/* indicates opFP1n2 for further decoding, this is not necessarily	*/
1208179237Sjb/* the case since the opFP arrays are not partitioned according to key1	*/
1209179237Sjb/* and key2.  opFP1n2 is given only to indicate that we haven't		*/
1210179237Sjb/* finished decoding the instruction.					*/
1211179237Sjb/* [D,8] */	IND(&dis_opFP1n2[0][0]),	IND(&dis_opFP1n2[0][0]),	IND(&dis_opFP1n2[0][0]),	IND(&dis_opFP1n2[0][0]),
1212179237Sjb/* [D,C] */	IND(&dis_opFP1n2[0][0]),	IND(&dis_opFP1n2[0][0]),	IND(&dis_opFP1n2[0][0]),	IND(&dis_opFP1n2[0][0]),
1213179237Sjb}, {
1214179237Sjb/* [E,0] */	TNSy("loopnz",BD),	TNSy("loopz",BD),	TNSy("loop",BD),	TNSy("jcxz",BD),
1215179237Sjb/* [E,4] */	TNS("inb",P),		TS("in",P),		TNS("outb",P),		TS("out",P),
1216179237Sjb/* [E,8] */	TNSyp("call",D),	TNSy("jmp",D),		TNSx("ljmp",SO),		TNSy("jmp",BD),
1217179237Sjb/* [E,C] */	TNS("inb",V),		TS("in",V),		TNS("outb",V),		TS("out",V),
1218179237Sjb}, {
1219179237Sjb/* [F,0] */	TNS("lock",LOCK),	TNS("icebp", NORM),	TNS("repnz",PREFIX),	TNS("repz",PREFIX),
1220179237Sjb/* [F,4] */	TNS("hlt",NORM),	TNS("cmc",NORM),	IND(dis_opF6),		IND(dis_opF7),
1221179237Sjb/* [F,8] */	TNS("clc",NORM),	TNS("stc",NORM),	TNS("cli",NORM),	TNS("sti",NORM),
1222179237Sjb/* [F,C] */	TNS("cld",NORM),	TNS("std",NORM),	IND(dis_opFE),		IND(dis_opFF),
1223179237Sjb} };
1224179237Sjb
1225179237Sjb/* END CSTYLED */
1226179237Sjb
1227179237Sjb/*
1228179237Sjb * common functions to decode and disassemble an x86 or amd64 instruction
1229179237Sjb */
1230179237Sjb
1231179237Sjb/*
1232179237Sjb * These are the individual fields of a REX prefix. Note that a REX
1233179237Sjb * prefix with none of these set is still needed to:
1234179237Sjb *	- use the MOVSXD (sign extend 32 to 64 bits) instruction
1235179237Sjb *	- access the %sil, %dil, %bpl, %spl registers
1236179237Sjb */
1237179237Sjb#define	REX_W 0x08	/* 64 bit operand size when set */
1238179237Sjb#define	REX_R 0x04	/* high order bit extension of ModRM reg field */
1239179237Sjb#define	REX_X 0x02	/* high order bit extension of SIB index field */
1240179237Sjb#define	REX_B 0x01	/* extends ModRM r_m, SIB base, or opcode reg */
1241179237Sjb
1242179237Sjbstatic uint_t opnd_size;	/* SIZE16, SIZE32 or SIZE64 */
1243179237Sjbstatic uint_t addr_size;	/* SIZE16, SIZE32 or SIZE64 */
1244179237Sjb
1245179237Sjb/*
1246179237Sjb * Even in 64 bit mode, usually only 4 byte immediate operands are supported.
1247179237Sjb */
1248179237Sjbstatic int isize[] = {1, 2, 4, 4};
1249179237Sjbstatic int isize64[] = {1, 2, 4, 8};
1250179237Sjb
1251179237Sjb/*
1252179237Sjb * Just a bunch of useful macros.
1253179237Sjb */
1254179237Sjb#define	WBIT(x)	(x & 0x1)		/* to get w bit	*/
1255179237Sjb#define	REGNO(x) (x & 0x7)		/* to get 3 bit register */
1256179237Sjb#define	VBIT(x)	((x)>>1 & 0x1)		/* to get 'v' bit */
1257179237Sjb#define	OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1)
1258179237Sjb#define	OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1)
1259179237Sjb
1260179237Sjb#define	REG_ONLY 3	/* mode to indicate a register operand (not memory) */
1261179237Sjb
1262179237Sjb#define	BYTE_OPND	0	/* w-bit value indicating byte register */
1263179237Sjb#define	LONG_OPND	1	/* w-bit value indicating opnd_size register */
1264179237Sjb#define	MM_OPND		2	/* "value" used to indicate a mmx reg */
1265179237Sjb#define	XMM_OPND	3	/* "value" used to indicate a xmm reg */
1266179237Sjb#define	SEG_OPND	4	/* "value" used to indicate a segment reg */
1267179237Sjb#define	CONTROL_OPND	5	/* "value" used to indicate a control reg */
1268179237Sjb#define	DEBUG_OPND	6	/* "value" used to indicate a debug reg */
1269179237Sjb#define	TEST_OPND	7	/* "value" used to indicate a test reg */
1270179237Sjb#define	WORD_OPND	8	/* w-bit value indicating word size reg */
1271179237Sjb
1272179237Sjb/*
1273179237Sjb * Get the next byte and separate the op code into the high and low nibbles.
1274179237Sjb */
1275179237Sjbstatic int
1276179237Sjbdtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low)
1277179237Sjb{
1278179237Sjb	int byte;
1279179237Sjb
1280179237Sjb	/*
1281179237Sjb	 * x86 instructions have a maximum length of 15 bytes.  Bail out if
1282179237Sjb	 * we try to read more.
1283179237Sjb	 */
1284179237Sjb	if (x->d86_len >= 15)
1285179237Sjb		return (x->d86_error = 1);
1286179237Sjb
1287179237Sjb	if (x->d86_error)
1288179237Sjb		return (1);
1289179237Sjb	byte = x->d86_get_byte(x->d86_data);
1290179237Sjb	if (byte < 0)
1291179237Sjb		return (x->d86_error = 1);
1292179237Sjb	x->d86_bytes[x->d86_len++] = byte;
1293179237Sjb	*low = byte & 0xf;		/* ----xxxx low 4 bits */
1294179237Sjb	*high = byte >> 4 & 0xf;	/* xxxx---- bits 7 to 4 */
1295179237Sjb	return (0);
1296179237Sjb}
1297179237Sjb
1298179237Sjb/*
1299179237Sjb * Get and decode an SIB (scaled index base) byte
1300179237Sjb */
1301179237Sjbstatic void
1302179237Sjbdtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base)
1303179237Sjb{
1304179237Sjb	int byte;
1305179237Sjb
1306179237Sjb	if (x->d86_error)
1307179237Sjb		return;
1308179237Sjb
1309179237Sjb	byte = x->d86_get_byte(x->d86_data);
1310179237Sjb	if (byte < 0) {
1311179237Sjb		x->d86_error = 1;
1312179237Sjb		return;
1313179237Sjb	}
1314179237Sjb	x->d86_bytes[x->d86_len++] = byte;
1315179237Sjb
1316179237Sjb	*base = byte & 0x7;
1317179237Sjb	*index = (byte >> 3) & 0x7;
1318179237Sjb	*ss = (byte >> 6) & 0x3;
1319179237Sjb}
1320179237Sjb
1321179237Sjb/*
1322179237Sjb * Get the byte following the op code and separate it into the
1323179237Sjb * mode, register, and r/m fields.
1324179237Sjb */
1325179237Sjbstatic void
1326179237Sjbdtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m)
1327179237Sjb{
1328179237Sjb	if (x->d86_got_modrm == 0) {
1329179237Sjb		if (x->d86_rmindex == -1)
1330179237Sjb			x->d86_rmindex = x->d86_len;
1331179237Sjb		dtrace_get_SIB(x, mode, reg, r_m);
1332179237Sjb		x->d86_got_modrm = 1;
1333179237Sjb	}
1334179237Sjb}
1335179237Sjb
1336179237Sjb/*
1337179237Sjb * Adjust register selection based on any REX prefix bits present.
1338179237Sjb */
1339179237Sjb/*ARGSUSED*/
1340179237Sjbstatic void
1341179237Sjbdtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m)
1342179237Sjb{
1343179237Sjb	if (reg != NULL && r_m == NULL) {
1344179237Sjb		if (rex_prefix & REX_B)
1345179237Sjb			*reg += 8;
1346179237Sjb	} else {
1347179237Sjb		if (reg != NULL && (REX_R & rex_prefix) != 0)
1348179237Sjb			*reg += 8;
1349179237Sjb		if (r_m != NULL && (REX_B & rex_prefix) != 0)
1350179237Sjb			*r_m += 8;
1351179237Sjb	}
1352179237Sjb}
1353179237Sjb
1354179237Sjb/*
1355179237Sjb * Get an immediate operand of the given size, with sign extension.
1356179237Sjb */
1357179237Sjbstatic void
1358179237Sjbdtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex)
1359179237Sjb{
1360179237Sjb	int i;
1361179237Sjb	int byte;
1362179237Sjb	int valsize = 0;
1363179237Sjb
1364179237Sjb	if (x->d86_numopnds < opindex + 1)
1365179237Sjb		x->d86_numopnds = opindex + 1;
1366179237Sjb
1367179237Sjb	switch (wbit) {
1368179237Sjb	case BYTE_OPND:
1369179237Sjb		valsize = 1;
1370179237Sjb		break;
1371179237Sjb	case LONG_OPND:
1372179237Sjb		if (x->d86_opnd_size == SIZE16)
1373179237Sjb			valsize = 2;
1374179237Sjb		else if (x->d86_opnd_size == SIZE32)
1375179237Sjb			valsize = 4;
1376179237Sjb		else
1377179237Sjb			valsize = 8;
1378179237Sjb		break;
1379179237Sjb	case MM_OPND:
1380179237Sjb	case XMM_OPND:
1381179237Sjb	case SEG_OPND:
1382179237Sjb	case CONTROL_OPND:
1383179237Sjb	case DEBUG_OPND:
1384179237Sjb	case TEST_OPND:
1385179237Sjb		valsize = size;
1386179237Sjb		break;
1387179237Sjb	case WORD_OPND:
1388179237Sjb		valsize = 2;
1389179237Sjb		break;
1390179237Sjb	}
1391179237Sjb	if (valsize < size)
1392179237Sjb		valsize = size;
1393179237Sjb
1394179237Sjb	if (x->d86_error)
1395179237Sjb		return;
1396179237Sjb	x->d86_opnd[opindex].d86_value = 0;
1397179237Sjb	for (i = 0; i < size; ++i) {
1398179237Sjb		byte = x->d86_get_byte(x->d86_data);
1399179237Sjb		if (byte < 0) {
1400179237Sjb			x->d86_error = 1;
1401179237Sjb			return;
1402179237Sjb		}
1403179237Sjb		x->d86_bytes[x->d86_len++] = byte;
1404179237Sjb		x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8);
1405179237Sjb	}
1406179237Sjb	/* Do sign extension */
1407179237Sjb	if (x->d86_bytes[x->d86_len - 1] & 0x80) {
1408179237Sjb		for (; i < valsize; i++)
1409179237Sjb			x->d86_opnd[opindex].d86_value |=
1410179237Sjb			    (uint64_t)0xff << (i* 8);
1411179237Sjb	}
1412179237Sjb#ifdef DIS_TEXT
1413179237Sjb	x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
1414179237Sjb	x->d86_opnd[opindex].d86_value_size = valsize;
1415179237Sjb	x->d86_imm_bytes += size;
1416179237Sjb#endif
1417179237Sjb}
1418179237Sjb
1419179237Sjb/*
1420179237Sjb * Get an ip relative operand of the given size, with sign extension.
1421179237Sjb */
1422179237Sjbstatic void
1423179237Sjbdtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex)
1424179237Sjb{
1425179237Sjb	dtrace_imm_opnd(x, wbit, size, opindex);
1426179237Sjb#ifdef DIS_TEXT
1427179237Sjb	x->d86_opnd[opindex].d86_mode = MODE_IPREL;
1428179237Sjb#endif
1429179237Sjb}
1430179237Sjb
1431179237Sjb/*
1432179237Sjb * Check to see if there is a segment override prefix pending.
1433179237Sjb * If so, print it in the current 'operand' location and set
1434179237Sjb * the override flag back to false.
1435179237Sjb */
1436179237Sjb/*ARGSUSED*/
1437179237Sjbstatic void
1438179237Sjbdtrace_check_override(dis86_t *x, int opindex)
1439179237Sjb{
1440179237Sjb#ifdef DIS_TEXT
1441179237Sjb	if (x->d86_seg_prefix) {
1442179237Sjb		(void) strlcat(x->d86_opnd[opindex].d86_prefix,
1443179237Sjb		    x->d86_seg_prefix, PFIXLEN);
1444179237Sjb	}
1445179237Sjb#endif
1446179237Sjb	x->d86_seg_prefix = NULL;
1447179237Sjb}
1448179237Sjb
1449179237Sjb
1450179237Sjb/*
1451179237Sjb * Process a single instruction Register or Memory operand.
1452179237Sjb *
1453179237Sjb * mode = addressing mode from ModRM byte
1454179237Sjb * r_m = r_m (or reg if mode == 3) field from ModRM byte
1455179237Sjb * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use.
1456179237Sjb * o = index of operand that we are processing (0, 1 or 2)
1457179237Sjb *
1458179237Sjb * the value of reg or r_m must have already been adjusted for any REX prefix.
1459179237Sjb */
1460179237Sjb/*ARGSUSED*/
1461179237Sjbstatic void
1462179237Sjbdtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex)
1463179237Sjb{
1464179237Sjb	int have_SIB = 0;	/* flag presence of scale-index-byte */
1465179237Sjb	uint_t ss;		/* scale-factor from opcode */
1466179237Sjb	uint_t index;		/* index register number */
1467179237Sjb	uint_t base;		/* base register number */
1468179237Sjb	int dispsize;   	/* size of displacement in bytes */
1469179237Sjb#ifdef DIS_TEXT
1470179237Sjb	char *opnd = x->d86_opnd[opindex].d86_opnd;
1471179237Sjb#endif
1472179237Sjb
1473179237Sjb	if (x->d86_numopnds < opindex + 1)
1474179237Sjb		x->d86_numopnds = opindex + 1;
1475179237Sjb
1476179237Sjb	if (x->d86_error)
1477179237Sjb		return;
1478179237Sjb
1479179237Sjb	/*
1480179237Sjb	 * first handle a simple register
1481179237Sjb	 */
1482179237Sjb	if (mode == REG_ONLY) {
1483179237Sjb#ifdef DIS_TEXT
1484179237Sjb		switch (wbit) {
1485179237Sjb		case MM_OPND:
1486179237Sjb			(void) strlcat(opnd, dis_MMREG[r_m], OPLEN);
1487179237Sjb			break;
1488179237Sjb		case XMM_OPND:
1489179237Sjb			(void) strlcat(opnd, dis_XMMREG[r_m], OPLEN);
1490179237Sjb			break;
1491179237Sjb		case SEG_OPND:
1492179237Sjb			(void) strlcat(opnd, dis_SEGREG[r_m], OPLEN);
1493179237Sjb			break;
1494179237Sjb		case CONTROL_OPND:
1495179237Sjb			(void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN);
1496179237Sjb			break;
1497179237Sjb		case DEBUG_OPND:
1498179237Sjb			(void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN);
1499179237Sjb			break;
1500179237Sjb		case TEST_OPND:
1501179237Sjb			(void) strlcat(opnd, dis_TESTREG[r_m], OPLEN);
1502179237Sjb			break;
1503179237Sjb		case BYTE_OPND:
1504179237Sjb			if (x->d86_rex_prefix == 0)
1505179237Sjb				(void) strlcat(opnd, dis_REG8[r_m], OPLEN);
1506179237Sjb			else
1507179237Sjb				(void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN);
1508179237Sjb			break;
1509179237Sjb		case WORD_OPND:
1510179237Sjb			(void) strlcat(opnd, dis_REG16[r_m], OPLEN);
1511179237Sjb			break;
1512179237Sjb		case LONG_OPND:
1513179237Sjb			if (x->d86_opnd_size == SIZE16)
1514179237Sjb				(void) strlcat(opnd, dis_REG16[r_m], OPLEN);
1515179237Sjb			else if (x->d86_opnd_size == SIZE32)
1516179237Sjb				(void) strlcat(opnd, dis_REG32[r_m], OPLEN);
1517179237Sjb			else
1518179237Sjb				(void) strlcat(opnd, dis_REG64[r_m], OPLEN);
1519179237Sjb			break;
1520179237Sjb		}
1521179237Sjb#endif /* DIS_TEXT */
1522179237Sjb		return;
1523179237Sjb	}
1524179237Sjb
1525179237Sjb	/*
1526179237Sjb	 * if symbolic representation, skip override prefix, if any
1527179237Sjb	 */
1528179237Sjb	dtrace_check_override(x, opindex);
1529179237Sjb
1530179237Sjb	/*
1531179237Sjb	 * Handle 16 bit memory references first, since they decode
1532179237Sjb	 * the mode values more simply.
1533179237Sjb	 * mode 1 is r_m + 8 bit displacement
1534179237Sjb	 * mode 2 is r_m + 16 bit displacement
1535179237Sjb	 * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp
1536179237Sjb	 */
1537179237Sjb	if (x->d86_addr_size == SIZE16) {
1538179237Sjb		if ((mode == 0 && r_m == 6) || mode == 2)
1539179237Sjb			dtrace_imm_opnd(x, WORD_OPND, 2, opindex);
1540179237Sjb		else if (mode == 1)
1541179237Sjb			dtrace_imm_opnd(x, BYTE_OPND, 1, opindex);
1542179237Sjb#ifdef DIS_TEXT
1543179237Sjb		if (mode == 0 && r_m == 6)
1544179237Sjb			x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
1545179237Sjb		else if (mode == 0)
1546179237Sjb			x->d86_opnd[opindex].d86_mode = MODE_NONE;
1547179237Sjb		else
1548179237Sjb			x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
1549179237Sjb		(void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN);
1550179237Sjb#endif
1551179237Sjb		return;
1552179237Sjb	}
1553179237Sjb
1554179237Sjb	/*
1555179237Sjb	 * 32 and 64 bit addressing modes are more complex since they
1556179237Sjb	 * can involve an SIB (scaled index and base) byte to decode.
1557179237Sjb	 */
1558179237Sjb	if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) {
1559179237Sjb		have_SIB = 1;
1560179237Sjb		dtrace_get_SIB(x, &ss, &index, &base);
1561179237Sjb		if (x->d86_error)
1562179237Sjb			return;
1563179237Sjb		if (base != 5 || mode != 0)
1564179237Sjb			if (x->d86_rex_prefix & REX_B)
1565179237Sjb				base += 8;
1566179237Sjb		if (x->d86_rex_prefix & REX_X)
1567179237Sjb			index += 8;
1568179237Sjb	} else {
1569179237Sjb		base = r_m;
1570179237Sjb	}
1571179237Sjb
1572179237Sjb	/*
1573179237Sjb	 * Compute the displacement size and get its bytes
1574179237Sjb	 */
1575179237Sjb	dispsize = 0;
1576179237Sjb
1577179237Sjb	if (mode == 1)
1578179237Sjb		dispsize = 1;
1579179237Sjb	else if (mode == 2)
1580179237Sjb		dispsize = 4;
1581179237Sjb	else if ((r_m & 7) == EBP_REGNO ||
1582179237Sjb	    (have_SIB && (base & 7) == EBP_REGNO))
1583179237Sjb		dispsize = 4;
1584179237Sjb
1585179237Sjb	if (dispsize > 0) {
1586179237Sjb		dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND,
1587179237Sjb		    dispsize, opindex);
1588179237Sjb		if (x->d86_error)
1589179237Sjb			return;
1590179237Sjb	}
1591179237Sjb
1592179237Sjb#ifdef DIS_TEXT
1593179237Sjb	if (dispsize > 0)
1594179237Sjb		x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
1595179237Sjb
1596179237Sjb	if (have_SIB == 0) {
1597179237Sjb		if (x->d86_mode == SIZE32) {
1598179237Sjb			if (mode == 0)
1599179237Sjb				(void) strlcat(opnd, dis_addr32_mode0[r_m],
1600179237Sjb				    OPLEN);
1601179237Sjb			else
1602179237Sjb				(void) strlcat(opnd, dis_addr32_mode12[r_m],
1603179237Sjb				    OPLEN);
1604179237Sjb		} else {
1605179237Sjb			if (mode == 0)
1606179237Sjb				(void) strlcat(opnd, dis_addr64_mode0[r_m],
1607179237Sjb				    OPLEN);
1608179237Sjb			else
1609179237Sjb				(void) strlcat(opnd, dis_addr64_mode12[r_m],
1610179237Sjb				    OPLEN);
1611179237Sjb		}
1612179237Sjb	} else {
1613179237Sjb		uint_t need_paren = 0;
1614179237Sjb		char **regs;
1615179237Sjb		if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */
1616179237Sjb			regs = (char **)dis_REG32;
1617179237Sjb		else
1618179237Sjb			regs = (char **)dis_REG64;
1619179237Sjb
1620179237Sjb		/*
1621179237Sjb		 * print the base (if any)
1622179237Sjb		 */
1623179237Sjb		if (base == EBP_REGNO && mode == 0) {
1624179237Sjb			if (index != ESP_REGNO) {
1625179237Sjb				(void) strlcat(opnd, "(", OPLEN);
1626179237Sjb				need_paren = 1;
1627179237Sjb			}
1628179237Sjb		} else {
1629179237Sjb			(void) strlcat(opnd, "(", OPLEN);
1630179237Sjb			(void) strlcat(opnd, regs[base], OPLEN);
1631179237Sjb			need_paren = 1;
1632179237Sjb		}
1633179237Sjb
1634179237Sjb		/*
1635179237Sjb		 * print the index (if any)
1636179237Sjb		 */
1637179237Sjb		if (index != ESP_REGNO) {
1638179237Sjb			(void) strlcat(opnd, ",", OPLEN);
1639179237Sjb			(void) strlcat(opnd, regs[index], OPLEN);
1640179237Sjb			(void) strlcat(opnd, dis_scale_factor[ss], OPLEN);
1641179237Sjb		} else
1642179237Sjb			if (need_paren)
1643179237Sjb				(void) strlcat(opnd, ")", OPLEN);
1644179237Sjb	}
1645179237Sjb#endif
1646179237Sjb}
1647179237Sjb
1648179237Sjb/*
1649179237Sjb * Operand sequence for standard instruction involving one register
1650179237Sjb * and one register/memory operand.
1651179237Sjb * wbit indicates a byte(0) or opnd_size(1) operation
1652179237Sjb * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r")
1653179237Sjb */
1654179237Sjb#define	STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit)  {	\
1655179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);			\
1656179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);	\
1657179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, vbit);		\
1658179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit);	\
1659179237Sjb}
1660179237Sjb
1661179237Sjb/*
1662179237Sjb * Similar to above, but allows for the two operands to be of different
1663179237Sjb * classes (ie. wbit).
1664179237Sjb *	wbit is for the r_m operand
1665179237Sjb *	w2 is for the reg operand
1666179237Sjb */
1667179237Sjb#define	MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit)	{	\
1668179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);			\
1669179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);	\
1670179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, vbit);		\
1671179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit);	\
1672179237Sjb}
1673179237Sjb
1674179237Sjb/*
1675179237Sjb * Similar, but for 2 operands plus an immediate.
1676179237Sjb */
1677179237Sjb#define	THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \
1678179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);			\
1679179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);	\
1680179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 1);		\
1681179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, w2, 2);		\
1682179237Sjb		dtrace_imm_opnd(x, wbit, immsize, 0);			\
1683179237Sjb}
1684179237Sjb
1685179237Sjb/*
1686179237Sjb * Dissassemble a single x86 or amd64 instruction.
1687179237Sjb *
1688179237Sjb * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64)
1689179237Sjb * for interpreting instructions.
1690179237Sjb *
1691179237Sjb * returns non-zero for bad opcode
1692179237Sjb */
1693179237Sjbint
1694179237Sjbdtrace_disx86(dis86_t *x, uint_t cpu_mode)
1695179237Sjb{
1696179237Sjb	const instable_t *dp = NULL;	/* decode table being used */
1697179237Sjb#ifdef DIS_TEXT
1698179237Sjb	uint_t i;
1699179237Sjb#endif
1700179237Sjb#ifdef DIS_MEM
1701179237Sjb	uint_t nomem = 0;
1702179237Sjb#define	NOMEM	(nomem = 1)
1703179237Sjb#else
1704179237Sjb#define	NOMEM	/* nothing */
1705179237Sjb#endif
1706179237Sjb	uint_t wbit = 0;	/* opcode wbit, 0 is 8 bit, !0 for opnd_size */
1707179237Sjb	uint_t w2;		/* wbit value for second operand */
1708179237Sjb	uint_t vbit;
1709179237Sjb	uint_t mode = 0;	/* mode value from ModRM byte */
1710179237Sjb	uint_t reg;		/* reg value from ModRM byte */
1711179237Sjb	uint_t r_m;		/* r_m value from ModRM byte */
1712179237Sjb
1713179237Sjb	uint_t opcode1;		/* high nibble of 1st byte */
1714179237Sjb	uint_t opcode2;		/* low nibble of 1st byte */
1715179237Sjb	uint_t opcode3;		/* extra opcode bits usually from ModRM byte */
1716179237Sjb	uint_t opcode4;		/* high nibble of 2nd byte */
1717179237Sjb	uint_t opcode5;		/* low nibble of 2ne byte */
1718179237Sjb	uint_t opcode6;		/* high nibble of 3rd byte */
1719179237Sjb	uint_t opcode7;		/* low nibble of 3rd byte */
1720179237Sjb	uint_t opcode_bytes = 1;
1721179237Sjb
1722179237Sjb	/*
1723179237Sjb	 * legacy prefixes come in 5 flavors, you should have only one of each
1724179237Sjb	 */
1725179237Sjb	uint_t	opnd_size_prefix = 0;
1726179237Sjb	uint_t	addr_size_prefix = 0;
1727179237Sjb	uint_t	segment_prefix = 0;
1728179237Sjb	uint_t	lock_prefix = 0;
1729179237Sjb	uint_t	rep_prefix = 0;
1730179237Sjb	uint_t	rex_prefix = 0;	/* amd64 register extension prefix */
1731179237Sjb	size_t	off;
1732179237Sjb
1733179237Sjb	x->d86_len = 0;
1734179237Sjb	x->d86_rmindex = -1;
1735179237Sjb	x->d86_error = 0;
1736179237Sjb#ifdef DIS_TEXT
1737179237Sjb	x->d86_numopnds = 0;
1738179237Sjb	x->d86_seg_prefix = NULL;
1739179237Sjb	x->d86_mneu[0] = 0;
1740179237Sjb	for (i = 0; i < 3; ++i) {
1741179237Sjb		x->d86_opnd[i].d86_opnd[0] = 0;
1742179237Sjb		x->d86_opnd[i].d86_prefix[0] = 0;
1743179237Sjb		x->d86_opnd[i].d86_value_size = 0;
1744179237Sjb		x->d86_opnd[i].d86_value = 0;
1745179237Sjb		x->d86_opnd[i].d86_mode = MODE_NONE;
1746179237Sjb	}
1747179237Sjb#endif
1748179237Sjb	x->d86_error = 0;
1749179237Sjb	x->d86_memsize = 0;
1750179237Sjb
1751179237Sjb	if (cpu_mode == SIZE16) {
1752179237Sjb		opnd_size = SIZE16;
1753179237Sjb		addr_size = SIZE16;
1754179237Sjb	} else if (cpu_mode == SIZE32) {
1755179237Sjb		opnd_size = SIZE32;
1756179237Sjb		addr_size = SIZE32;
1757179237Sjb	} else {
1758179237Sjb		opnd_size = SIZE32;
1759179237Sjb		addr_size = SIZE64;
1760179237Sjb	}
1761179237Sjb
1762179237Sjb	/*
1763179237Sjb	 * Get one opcode byte and check for zero padding that follows
1764179237Sjb	 * jump tables.
1765179237Sjb	 */
1766179237Sjb	if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
1767179237Sjb		goto error;
1768179237Sjb
1769179237Sjb	if (opcode1 == 0 && opcode2 == 0 &&
1770179237Sjb	    x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) {
1771179237Sjb#ifdef DIS_TEXT
1772179237Sjb		(void) strncpy(x->d86_mneu, ".byte\t0", OPLEN);
1773179237Sjb#endif
1774179237Sjb		goto done;
1775179237Sjb	}
1776179237Sjb
1777179237Sjb	/*
1778179237Sjb	 * Gather up legacy x86 prefix bytes.
1779179237Sjb	 */
1780179237Sjb	for (;;) {
1781179237Sjb		uint_t *which_prefix = NULL;
1782179237Sjb
1783179237Sjb		dp = &dis_distable[opcode1][opcode2];
1784179237Sjb
1785179237Sjb		switch (dp->it_adrmode) {
1786179237Sjb		case PREFIX:
1787179237Sjb			which_prefix = &rep_prefix;
1788179237Sjb			break;
1789179237Sjb		case LOCK:
1790179237Sjb			which_prefix = &lock_prefix;
1791179237Sjb			break;
1792179237Sjb		case OVERRIDE:
1793179237Sjb			which_prefix = &segment_prefix;
1794179237Sjb#ifdef DIS_TEXT
1795179237Sjb			x->d86_seg_prefix = (char *)dp->it_name;
1796179237Sjb#endif
1797179237Sjb			if (dp->it_invalid64 && cpu_mode == SIZE64)
1798179237Sjb				goto error;
1799179237Sjb			break;
1800179237Sjb		case AM:
1801179237Sjb			which_prefix = &addr_size_prefix;
1802179237Sjb			break;
1803179237Sjb		case DM:
1804179237Sjb			which_prefix = &opnd_size_prefix;
1805179237Sjb			break;
1806179237Sjb		}
1807179237Sjb		if (which_prefix == NULL)
1808179237Sjb			break;
1809179237Sjb		*which_prefix = (opcode1 << 4) | opcode2;
1810179237Sjb		if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
1811179237Sjb			goto error;
1812179237Sjb	}
1813179237Sjb
1814179237Sjb	/*
1815179237Sjb	 * Handle amd64 mode PREFIX values.
1816179237Sjb	 * Some of the segment prefixes are no-ops. (only FS/GS actually work)
1817179237Sjb	 * We might have a REX prefix (opcodes 0x40-0x4f)
1818179237Sjb	 */
1819179237Sjb	if (cpu_mode == SIZE64) {
1820179237Sjb		if (segment_prefix != 0x64 && segment_prefix != 0x65)
1821179237Sjb			segment_prefix = 0;
1822179237Sjb
1823179237Sjb		if (opcode1 == 0x4) {
1824179237Sjb			rex_prefix = (opcode1 << 4) | opcode2;
1825179237Sjb			if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
1826179237Sjb				goto error;
1827179237Sjb			dp = &dis_distable[opcode1][opcode2];
1828179237Sjb		}
1829179237Sjb	}
1830179237Sjb
1831179237Sjb	/*
1832179237Sjb	 * Deal with selection of operand and address size now.
1833179237Sjb	 * Note that the REX.W bit being set causes opnd_size_prefix to be
1834179237Sjb	 * ignored.
1835179237Sjb	 */
1836179237Sjb	if (cpu_mode == SIZE64) {
1837179237Sjb		if (rex_prefix & 0x08)
1838179237Sjb			opnd_size = SIZE64;
1839179237Sjb		else if (opnd_size_prefix)
1840179237Sjb			opnd_size = SIZE16;
1841179237Sjb
1842179237Sjb		if (addr_size_prefix)
1843179237Sjb			addr_size = SIZE32;
1844179237Sjb	} else if (cpu_mode == SIZE32) {
1845179237Sjb		if (opnd_size_prefix)
1846179237Sjb			opnd_size = SIZE16;
1847179237Sjb		if (addr_size_prefix)
1848179237Sjb			addr_size = SIZE16;
1849179237Sjb	} else {
1850179237Sjb		if (opnd_size_prefix)
1851179237Sjb			opnd_size = SIZE32;
1852179237Sjb		if (addr_size_prefix)
1853179237Sjb			addr_size = SIZE32;
1854179237Sjb	}
1855179237Sjb
1856179237Sjb	/*
1857179237Sjb	 * The pause instruction - a repz'd nop.  This doesn't fit
1858179237Sjb	 * with any of the other prefix goop added for SSE, so we'll
1859179237Sjb	 * special-case it here.
1860179237Sjb	 */
1861179237Sjb	if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) {
1862179237Sjb		rep_prefix = 0;
1863179237Sjb		dp = &dis_opPause;
1864179237Sjb	}
1865179237Sjb
1866179237Sjb	/*
1867179237Sjb	 * Some 386 instructions have 2 bytes of opcode before the mod_r/m
1868179237Sjb	 * byte so we may need to perform a table indirection.
1869179237Sjb	 */
1870179237Sjb	if (dp->it_indirect == dis_op0F[0]) {
1871179237Sjb		if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0)
1872179237Sjb			goto error;
1873179237Sjb		opcode_bytes = 2;
1874179237Sjb		if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) {
1875179237Sjb			uint_t	subcode;
1876179237Sjb
1877179237Sjb			if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
1878179237Sjb				goto error;
1879179237Sjb			opcode_bytes = 3;
1880179237Sjb			subcode = ((opcode6 & 0x3) << 1) |
1881179237Sjb			    ((opcode7 & 0x8) >> 3);
1882179237Sjb			dp = &dis_op0F7123[opcode5][subcode];
1883179237Sjb		} else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) {
1884179237Sjb			dp = &dis_op0FC8[0];
1885179237Sjb		} else {
1886179237Sjb			dp = &dis_op0F[opcode4][opcode5];
1887179237Sjb		}
1888179237Sjb	}
1889179237Sjb
1890179237Sjb	/*
1891179237Sjb	 * If still not at a TERM decode entry, then a ModRM byte
1892179237Sjb	 * exists and its fields further decode the instruction.
1893179237Sjb	 */
1894179237Sjb	x->d86_got_modrm = 0;
1895179237Sjb	if (dp->it_indirect != TERM) {
1896179237Sjb		dtrace_get_modrm(x, &mode, &opcode3, &r_m);
1897179237Sjb		if (x->d86_error)
1898179237Sjb			goto error;
1899179237Sjb		reg = opcode3;
1900179237Sjb
1901179237Sjb		/*
1902179237Sjb		 * decode 287 instructions (D8-DF) from opcodeN
1903179237Sjb		 */
1904179237Sjb		if (opcode1 == 0xD && opcode2 >= 0x8) {
1905179237Sjb			if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4)
1906179237Sjb				dp = &dis_opFP5[r_m];
1907179237Sjb			else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4)
1908179237Sjb				dp = &dis_opFP7[opcode3];
1909179237Sjb			else if (opcode2 == 0xB && mode == 0x3)
1910179237Sjb				dp = &dis_opFP6[opcode3];
1911179237Sjb			else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4)
1912179237Sjb				dp = &dis_opFP4[opcode3 - 4][r_m];
1913179237Sjb			else if (mode == 0x3)
1914179237Sjb				dp = &dis_opFP3[opcode2 - 8][opcode3];
1915179237Sjb			else
1916179237Sjb				dp = &dis_opFP1n2[opcode2 - 8][opcode3];
1917179237Sjb		} else {
1918179237Sjb			dp = dp->it_indirect + opcode3;
1919179237Sjb		}
1920179237Sjb	}
1921179237Sjb
1922179237Sjb	/*
1923179237Sjb	 * In amd64 bit mode, ARPL opcode is changed to MOVSXD
1924179237Sjb	 * (sign extend 32bit to 64 bit)
1925179237Sjb	 */
1926179237Sjb	if (cpu_mode == SIZE64 && opcode1 == 0x6 && opcode2 == 0x3)
1927179237Sjb		dp = &dis_opMOVSLD;
1928179237Sjb
1929179237Sjb	/*
1930179237Sjb	 * at this point we should have a correct (or invalid) opcode
1931179237Sjb	 */
1932179237Sjb	if ((cpu_mode == SIZE64 && dp->it_invalid64) ||
1933179237Sjb	    (cpu_mode != SIZE64 && dp->it_invalid32))
1934179237Sjb		goto error;
1935179237Sjb	if (dp->it_indirect != TERM)
1936179237Sjb		goto error;
1937179237Sjb
1938179237Sjb	/*
1939179237Sjb	 * deal with MMX/SSE opcodes which are changed by prefixes
1940179237Sjb	 */
1941179237Sjb	switch (dp->it_adrmode) {
1942179237Sjb	case MMO:
1943179237Sjb	case MMOIMPL:
1944179237Sjb	case MMO3P:
1945179237Sjb	case MMOM3:
1946179237Sjb	case MMOMS:
1947179237Sjb	case MMOPM:
1948179237Sjb	case MMOPRM:
1949179237Sjb	case MMOS:
1950179237Sjb	case XMMO:
1951179237Sjb	case XMMOM:
1952179237Sjb	case XMMOMS:
1953179237Sjb	case XMMOPM:
1954179237Sjb	case XMMOS:
1955179237Sjb	case XMMOMX:
1956179237Sjb	case XMMOX3:
1957179237Sjb	case XMMOXMM:
1958179237Sjb		/*
1959179237Sjb		 * This is horrible.  Some SIMD instructions take the
1960179237Sjb		 * form 0x0F 0x?? ..., which is easily decoded using the
1961179237Sjb		 * existing tables.  Other SIMD instructions use various
1962179237Sjb		 * prefix bytes to overload existing instructions.  For
1963179237Sjb		 * Example, addps is F0, 58, whereas addss is F3 (repz),
1964179237Sjb		 * F0, 58.  Presumably someone got a raise for this.
1965179237Sjb		 *
1966179237Sjb		 * If we see one of the instructions which can be
1967179237Sjb		 * modified in this way (if we've got one of the SIMDO*
1968179237Sjb		 * address modes), we'll check to see if the last prefix
1969179237Sjb		 * was a repz.  If it was, we strip the prefix from the
1970179237Sjb		 * mnemonic, and we indirect using the dis_opSIMDrepz
1971179237Sjb		 * table.
1972179237Sjb		 */
1973179237Sjb
1974179237Sjb		/*
1975179237Sjb		 * Calculate our offset in dis_op0F
1976179237Sjb		 */
1977179237Sjb		if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F))
1978179237Sjb			goto error;
1979179237Sjb
1980179237Sjb		off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
1981179237Sjb		    sizeof (instable_t);
1982179237Sjb
1983179237Sjb		/*
1984179237Sjb		 * Rewrite if this instruction used one of the magic prefixes.
1985179237Sjb		 */
1986179237Sjb		if (rep_prefix) {
1987179237Sjb			if (rep_prefix == 0xf2)
1988179237Sjb				dp = &dis_opSIMDrepnz[off];
1989179237Sjb			else
1990179237Sjb				dp = &dis_opSIMDrepz[off];
1991179237Sjb			rep_prefix = 0;
1992179237Sjb		} else if (opnd_size_prefix) {
1993179237Sjb			dp = &dis_opSIMDdata16[off];
1994179237Sjb			opnd_size_prefix = 0;
1995179237Sjb			if (opnd_size == SIZE16)
1996179237Sjb				opnd_size = SIZE32;
1997179237Sjb		}
1998179237Sjb		break;
1999179237Sjb
2000179237Sjb	case MMOSH:
2001179237Sjb		/*
2002179237Sjb		 * As with the "normal" SIMD instructions, the MMX
2003179237Sjb		 * shuffle instructions are overloaded.  These
2004179237Sjb		 * instructions, however, are special in that they use
2005179237Sjb		 * an extra byte, and thus an extra table.  As of this
2006179237Sjb		 * writing, they only use the opnd_size prefix.
2007179237Sjb		 */
2008179237Sjb
2009179237Sjb		/*
2010179237Sjb		 * Calculate our offset in dis_op0F7123
2011179237Sjb		 */
2012179237Sjb		if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 >
2013179237Sjb		    sizeof (dis_op0F7123))
2014179237Sjb			goto error;
2015179237Sjb
2016179237Sjb		if (opnd_size_prefix) {
2017179237Sjb			off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) /
2018179237Sjb			    sizeof (instable_t);
2019179237Sjb			dp = &dis_opSIMD7123[off];
2020179237Sjb			opnd_size_prefix = 0;
2021179237Sjb			if (opnd_size == SIZE16)
2022179237Sjb				opnd_size = SIZE32;
2023179237Sjb		}
2024179237Sjb		break;
2025179237Sjb	}
2026179237Sjb
2027179237Sjb	/*
2028179237Sjb	 * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64.
2029179237Sjb	 */
2030179237Sjb	if (cpu_mode == SIZE64)
2031179237Sjb		if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop))
2032179237Sjb			opnd_size = SIZE64;
2033179237Sjb
2034179237Sjb#ifdef DIS_TEXT
2035179237Sjb	/*
2036179237Sjb	 * At this point most instructions can format the opcode mnemonic
2037179237Sjb	 * including the prefixes.
2038179237Sjb	 */
2039179237Sjb	if (lock_prefix)
2040179237Sjb		(void) strlcat(x->d86_mneu, "lock ", OPLEN);
2041179237Sjb
2042179237Sjb	if (rep_prefix == 0xf2)
2043179237Sjb		(void) strlcat(x->d86_mneu, "repnz ", OPLEN);
2044179237Sjb	else if (rep_prefix == 0xf3)
2045179237Sjb		(void) strlcat(x->d86_mneu, "repz ", OPLEN);
2046179237Sjb
2047179237Sjb	if (cpu_mode == SIZE64 && addr_size_prefix)
2048179237Sjb		(void) strlcat(x->d86_mneu, "addr32 ", OPLEN);
2049179237Sjb
2050179237Sjb	if (dp->it_adrmode != CBW &&
2051179237Sjb	    dp->it_adrmode != CWD &&
2052179237Sjb	    dp->it_adrmode != XMMSFNC) {
2053179237Sjb		if (strcmp(dp->it_name, "INVALID") == 0)
2054179237Sjb			goto error;
2055179237Sjb		(void) strlcat(x->d86_mneu, dp->it_name, OPLEN);
2056179237Sjb		if (dp->it_suffix) {
2057179237Sjb			char *types[] = {"", "w", "l", "q"};
2058179237Sjb			if (opcode_bytes == 2 && opcode4 == 4) {
2059179237Sjb				/* It's a cmovx.yy. Replace the suffix x */
2060179237Sjb				for (i = 5; i < OPLEN; i++) {
2061179237Sjb					if (x->d86_mneu[i] == '.')
2062179237Sjb						break;
2063179237Sjb				}
2064179237Sjb				x->d86_mneu[i - 1] = *types[opnd_size];
2065179237Sjb			} else {
2066179237Sjb				(void) strlcat(x->d86_mneu, types[opnd_size],
2067179237Sjb				    OPLEN);
2068179237Sjb			}
2069179237Sjb		}
2070179237Sjb	}
2071179237Sjb#endif
2072179237Sjb
2073179237Sjb	/*
2074179237Sjb	 * Process operands based on the addressing modes.
2075179237Sjb	 */
2076179237Sjb	x->d86_mode = cpu_mode;
2077179237Sjb	x->d86_rex_prefix = rex_prefix;
2078179237Sjb	x->d86_opnd_size = opnd_size;
2079179237Sjb	x->d86_addr_size = addr_size;
2080179237Sjb	vbit = 0;		/* initialize for mem/reg -> reg */
2081179237Sjb	switch (dp->it_adrmode) {
2082179237Sjb		/*
2083179237Sjb		 * amd64 instruction to sign extend 32 bit reg/mem operands
2084179237Sjb		 * into 64 bit register values
2085179237Sjb		 */
2086179237Sjb	case MOVSXZ:
2087179237Sjb#ifdef DIS_TEXT
2088179237Sjb		if (rex_prefix == 0)
2089179237Sjb			(void) strncpy(x->d86_mneu, "movzld", OPLEN);
2090179237Sjb#endif
2091179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2092179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2093179237Sjb		x->d86_opnd_size = SIZE64;
2094179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2095179237Sjb		x->d86_opnd_size = opnd_size = SIZE32;
2096179237Sjb		wbit = LONG_OPND;
2097179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 0);
2098179237Sjb		break;
2099179237Sjb
2100179237Sjb		/*
2101179237Sjb		 * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF)
2102179237Sjb		 * movzbl movzbw movzbq (0x0FB6) or mobzwl movzwq (0x0FB7)
2103179237Sjb		 * wbit lives in 2nd byte, note that operands
2104179237Sjb		 * are different sized
2105179237Sjb		 */
2106179237Sjb	case MOVZ:
2107179237Sjb		if (rex_prefix & REX_W) {
2108179237Sjb			/* target register size = 64 bit */
2109179237Sjb			x->d86_mneu[5] = 'q';
2110179237Sjb		}
2111179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2112179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2113179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2114179237Sjb		x->d86_opnd_size = opnd_size = SIZE16;
2115179237Sjb		wbit = WBIT(opcode5);
2116179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 0);
2117179237Sjb		break;
2118179237Sjb
2119179237Sjb	/*
2120179237Sjb	 * imul instruction, with either 8-bit or longer immediate
2121179237Sjb	 * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s)
2122179237Sjb	 */
2123179237Sjb	case IMUL:
2124179237Sjb		wbit = LONG_OPND;
2125179237Sjb		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND,
2126179237Sjb		    OPSIZE(opnd_size, opcode2 == 0x9));
2127179237Sjb		break;
2128179237Sjb
2129179237Sjb	/* memory or register operand to register, with 'w' bit	*/
2130179237Sjb	case MRw:
2131179237Sjb		wbit = WBIT(opcode2);
2132179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
2133179237Sjb		break;
2134179237Sjb
2135179237Sjb	/* register to memory or register operand, with 'w' bit	*/
2136179237Sjb	/* arpl happens to fit here also because it is odd */
2137179237Sjb	case RMw:
2138179237Sjb		if (opcode_bytes == 2)
2139179237Sjb			wbit = WBIT(opcode5);
2140179237Sjb		else
2141179237Sjb			wbit = WBIT(opcode2);
2142179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2143179237Sjb		break;
2144179237Sjb
2145179237Sjb	/* xaddb instruction */
2146179237Sjb	case XADDB:
2147179237Sjb		wbit = 0;
2148179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2149179237Sjb		break;
2150179237Sjb
2151179237Sjb	/* MMX register to memory or register operand		*/
2152179237Sjb	case MMS:
2153179237Sjb	case MMOS:
2154179237Sjb#ifdef DIS_TEXT
2155179237Sjb		wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
2156179237Sjb#else
2157179237Sjb		wbit = LONG_OPND;
2158179237Sjb#endif
2159179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
2160179237Sjb		break;
2161179237Sjb
2162179237Sjb	/* MMX register to memory */
2163179237Sjb	case MMOMS:
2164179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2165179237Sjb		if (mode == REG_ONLY)
2166179237Sjb			goto error;
2167179237Sjb		wbit = MM_OPND;
2168179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
2169179237Sjb		break;
2170179237Sjb
2171179237Sjb	/* Double shift. Has immediate operand specifying the shift. */
2172179237Sjb	case DSHIFT:
2173179237Sjb		wbit = LONG_OPND;
2174179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2175179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2176179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 2);
2177179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2178179237Sjb		dtrace_imm_opnd(x, wbit, 1, 0);
2179179237Sjb		break;
2180179237Sjb
2181179237Sjb	/*
2182179237Sjb	 * Double shift. With no immediate operand, specifies using %cl.
2183179237Sjb	 */
2184179237Sjb	case DSHIFTcl:
2185179237Sjb		wbit = LONG_OPND;
2186179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2187179237Sjb		break;
2188179237Sjb
2189179237Sjb	/* immediate to memory or register operand */
2190179237Sjb	case IMlw:
2191179237Sjb		wbit = WBIT(opcode2);
2192179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2193179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 1);
2194179237Sjb		/*
2195179237Sjb		 * Have long immediate for opcode 0x81, but not 0x80 nor 0x83
2196179237Sjb		 */
2197179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0);
2198179237Sjb		break;
2199179237Sjb
2200179237Sjb	/* immediate to memory or register operand with the	*/
2201179237Sjb	/* 'w' bit present					*/
2202179237Sjb	case IMw:
2203179237Sjb		wbit = WBIT(opcode2);
2204179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2205179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2206179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 1);
2207179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
2208179237Sjb		break;
2209179237Sjb
2210179237Sjb	/* immediate to register with register in low 3 bits	*/
2211179237Sjb	/* of op code						*/
2212179237Sjb	case IR:
2213179237Sjb		/* w-bit here (with regs) is bit 3 */
2214179237Sjb		wbit = opcode2 >>3 & 0x1;
2215179237Sjb		reg = REGNO(opcode2);
2216179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2217179237Sjb		mode = REG_ONLY;
2218179237Sjb		r_m = reg;
2219179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 1);
2220179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0);
2221179237Sjb		break;
2222179237Sjb
2223179237Sjb	/* MMX immediate shift of register */
2224179237Sjb	case MMSH:
2225179237Sjb	case MMOSH:
2226179237Sjb		wbit = MM_OPND;
2227179237Sjb		goto mm_shift;	/* in next case */
2228179237Sjb
2229179237Sjb	/* SIMD immediate shift of register */
2230179237Sjb	case XMMSH:
2231179237Sjb		wbit = XMM_OPND;
2232179237Sjbmm_shift:
2233179237Sjb		reg = REGNO(opcode7);
2234179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2235179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
2236179237Sjb		dtrace_imm_opnd(x, wbit, 1, 0);
2237179237Sjb		NOMEM;
2238179237Sjb		break;
2239179237Sjb
2240179237Sjb	/* accumulator to memory operand */
2241179237Sjb	case AO:
2242179237Sjb		vbit = 1;
2243179237Sjb		/*FALLTHROUGH*/
2244179237Sjb
2245179237Sjb	/* memory operand to accumulator */
2246179237Sjb	case OA:
2247179237Sjb		wbit = WBIT(opcode2);
2248179237Sjb		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit);
2249179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit);
2250179237Sjb#ifdef DIS_TEXT
2251179237Sjb		x->d86_opnd[vbit].d86_mode = MODE_OFFSET;
2252179237Sjb#endif
2253179237Sjb		break;
2254179237Sjb
2255179237Sjb
2256179237Sjb	/* segment register to memory or register operand */
2257179237Sjb	case SM:
2258179237Sjb		vbit = 1;
2259179237Sjb		/*FALLTHROUGH*/
2260179237Sjb
2261179237Sjb	/* memory or register operand to segment register */
2262179237Sjb	case MS:
2263179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2264179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2265179237Sjb		dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit);
2266179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit);
2267179237Sjb		break;
2268179237Sjb
2269179237Sjb	/*
2270179237Sjb	 * rotate or shift instructions, which may shift by 1 or
2271179237Sjb	 * consult the cl register, depending on the 'v' bit
2272179237Sjb	 */
2273179237Sjb	case Mv:
2274179237Sjb		vbit = VBIT(opcode2);
2275179237Sjb		wbit = WBIT(opcode2);
2276179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2277179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 1);
2278179237Sjb#ifdef DIS_TEXT
2279179237Sjb		if (vbit) {
2280179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN);
2281179237Sjb		} else {
2282179237Sjb			x->d86_opnd[0].d86_mode = MODE_SIGNED;
2283179237Sjb			x->d86_opnd[0].d86_value_size = 1;
2284179237Sjb			x->d86_opnd[0].d86_value = 1;
2285179237Sjb		}
2286179237Sjb#endif
2287179237Sjb		break;
2288179237Sjb	/*
2289179237Sjb	 * immediate rotate or shift instructions
2290179237Sjb	 */
2291179237Sjb	case MvI:
2292179237Sjb		wbit = WBIT(opcode2);
2293179237Sjbnormal_imm_mem:
2294179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2295179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 1);
2296179237Sjb		dtrace_imm_opnd(x, wbit, 1, 0);
2297179237Sjb		break;
2298179237Sjb
2299179237Sjb	/* bit test instructions */
2300179237Sjb	case MIb:
2301179237Sjb		wbit = LONG_OPND;
2302179237Sjb		goto normal_imm_mem;
2303179237Sjb
2304179237Sjb	/* single memory or register operand with 'w' bit present */
2305179237Sjb	case Mw:
2306179237Sjb		wbit = WBIT(opcode2);
2307179237Sjbjust_mem:
2308179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2309179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2310179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 0);
2311179237Sjb		break;
2312179237Sjb
2313179237Sjb	case SWAPGS:
2314179237Sjb		if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) {
2315179237Sjb#ifdef DIS_TEXT
2316179237Sjb			(void) strncpy(x->d86_mneu, "swapgs", OPLEN);
2317179237Sjb#endif
2318179237Sjb			NOMEM;
2319179237Sjb			break;
2320179237Sjb		}
2321179237Sjb		/*FALLTHROUGH*/
2322179237Sjb
2323179237Sjb	/* prefetch instruction - memory operand, but no memory acess */
2324179237Sjb	case PREF:
2325179237Sjb		NOMEM;
2326179237Sjb		/*FALLTHROUGH*/
2327179237Sjb
2328179237Sjb	/* single memory or register operand */
2329179237Sjb	case M:
2330179237Sjb		wbit = LONG_OPND;
2331179237Sjb		goto just_mem;
2332179237Sjb
2333179237Sjb	/* single memory or register byte operand */
2334179237Sjb	case Mb:
2335179237Sjb		wbit = BYTE_OPND;
2336179237Sjb		goto just_mem;
2337179237Sjb
2338179237Sjb	case MO:
2339179237Sjb		/* Similar to M, but only memory (no direct registers) */
2340179237Sjb		wbit = LONG_OPND;
2341179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2342179237Sjb		if (mode == 3)
2343179237Sjb			goto error;
2344179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2345179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 0);
2346179237Sjb		break;
2347179237Sjb
2348179237Sjb	/* move special register to register or reverse if vbit */
2349179237Sjb	case SREG:
2350179237Sjb		switch (opcode5) {
2351179237Sjb
2352179237Sjb		case 2:
2353179237Sjb			vbit = 1;
2354179237Sjb			/*FALLTHROUGH*/
2355179237Sjb		case 0:
2356179237Sjb			wbit = CONTROL_OPND;
2357179237Sjb			break;
2358179237Sjb
2359179237Sjb		case 3:
2360179237Sjb			vbit = 1;
2361179237Sjb			/*FALLTHROUGH*/
2362179237Sjb		case 1:
2363179237Sjb			wbit = DEBUG_OPND;
2364179237Sjb			break;
2365179237Sjb
2366179237Sjb		case 6:
2367179237Sjb			vbit = 1;
2368179237Sjb			/*FALLTHROUGH*/
2369179237Sjb		case 4:
2370179237Sjb			wbit = TEST_OPND;
2371179237Sjb			break;
2372179237Sjb
2373179237Sjb		}
2374179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2375179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2376179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit);
2377179237Sjb		dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit);
2378179237Sjb		NOMEM;
2379179237Sjb		break;
2380179237Sjb
2381179237Sjb	/*
2382179237Sjb	 * single register operand with register in the low 3
2383179237Sjb	 * bits of op code
2384179237Sjb	 */
2385179237Sjb	case R:
2386179237Sjb		if (opcode_bytes == 2)
2387179237Sjb			reg = REGNO(opcode5);
2388179237Sjb		else
2389179237Sjb			reg = REGNO(opcode2);
2390179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2391179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
2392179237Sjb		NOMEM;
2393179237Sjb		break;
2394179237Sjb
2395179237Sjb	/*
2396179237Sjb	 * register to accumulator with register in the low 3
2397179237Sjb	 * bits of op code, xchg instructions
2398179237Sjb	 */
2399179237Sjb	case RA:
2400179237Sjb		NOMEM;
2401179237Sjb		reg = REGNO(opcode2);
2402179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
2403179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
2404179237Sjb		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1);
2405179237Sjb		break;
2406179237Sjb
2407179237Sjb	/*
2408179237Sjb	 * single segment register operand, with register in
2409179237Sjb	 * bits 3-4 of op code byte
2410179237Sjb	 */
2411179237Sjb	case SEG:
2412179237Sjb		NOMEM;
2413179237Sjb		reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3;
2414179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
2415179237Sjb		break;
2416179237Sjb
2417179237Sjb	/*
2418179237Sjb	 * single segment register operand, with register in
2419179237Sjb	 * bits 3-5 of op code
2420179237Sjb	 */
2421179237Sjb	case LSEG:
2422179237Sjb		NOMEM;
2423179237Sjb		/* long seg reg from opcode */
2424179237Sjb		reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7;
2425179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
2426179237Sjb		break;
2427179237Sjb
2428179237Sjb	/* memory or register operand to register */
2429179237Sjb	case MR:
2430179237Sjb		wbit = LONG_OPND;
2431179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
2432179237Sjb		break;
2433179237Sjb
2434179237Sjb	case RM:
2435179237Sjb		wbit = LONG_OPND;
2436179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
2437179237Sjb		break;
2438179237Sjb
2439179237Sjb	/* MMX/SIMD-Int memory or mm reg to mm reg		*/
2440179237Sjb	case MM:
2441179237Sjb	case MMO:
2442179237Sjb#ifdef DIS_TEXT
2443179237Sjb		wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
2444179237Sjb#else
2445179237Sjb		wbit = LONG_OPND;
2446179237Sjb#endif
2447179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
2448179237Sjb		break;
2449179237Sjb
2450179237Sjb	case MMOIMPL:
2451179237Sjb#ifdef DIS_TEXT
2452179237Sjb		wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
2453179237Sjb#else
2454179237Sjb		wbit = LONG_OPND;
2455179237Sjb#endif
2456179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2457179237Sjb		if (mode != REG_ONLY)
2458179237Sjb			goto error;
2459179237Sjb
2460179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2461179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 0);
2462179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1);
2463179237Sjb		mode = 0;	/* change for memory access size... */
2464179237Sjb		break;
2465179237Sjb
2466179237Sjb	/* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */
2467179237Sjb	case MMO3P:
2468179237Sjb		wbit = MM_OPND;
2469179237Sjb		goto xmm3p;
2470179237Sjb	case XMM3P:
2471179237Sjb		wbit = XMM_OPND;
2472179237Sjbxmm3p:
2473179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2474179237Sjb		if (mode != REG_ONLY)
2475179237Sjb			goto error;
2476179237Sjb
2477179237Sjb		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1);
2478179237Sjb		NOMEM;
2479179237Sjb		break;
2480179237Sjb
2481179237Sjb	/* MMX/SIMD-Int predicated r32/mem to mm reg */
2482179237Sjb	case MMOPRM:
2483179237Sjb		wbit = LONG_OPND;
2484179237Sjb		w2 = MM_OPND;
2485179237Sjb		goto xmmprm;
2486179237Sjb	case XMMPRM:
2487179237Sjb		wbit = LONG_OPND;
2488179237Sjb		w2 = XMM_OPND;
2489179237Sjbxmmprm:
2490179237Sjb		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1);
2491179237Sjb		break;
2492179237Sjb
2493179237Sjb	/* MMX/SIMD-Int predicated mm/mem to mm reg */
2494179237Sjb	case MMOPM:
2495179237Sjb		wbit = w2 = MM_OPND;
2496179237Sjb		goto xmmprm;
2497179237Sjb
2498179237Sjb	/* MMX/SIMD-Int mm reg to r32 */
2499179237Sjb	case MMOM3:
2500179237Sjb		NOMEM;
2501179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2502179237Sjb		if (mode != REG_ONLY)
2503179237Sjb			goto error;
2504179237Sjb		wbit = MM_OPND;
2505179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
2506179237Sjb		break;
2507179237Sjb
2508179237Sjb	/* SIMD memory or xmm reg operand to xmm reg		*/
2509179237Sjb	case XMM:
2510179237Sjb	case XMMO:
2511179237Sjb	case XMMXIMPL:
2512179237Sjb		wbit = XMM_OPND;
2513179237Sjb		STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
2514179237Sjb
2515179237Sjb		if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY)
2516179237Sjb			goto error;
2517179237Sjb
2518179237Sjb#ifdef DIS_TEXT
2519179237Sjb		/*
2520179237Sjb		 * movlps and movhlps share opcodes.  They differ in the
2521179237Sjb		 * addressing modes allowed for their operands.
2522179237Sjb		 * movhps and movlhps behave similarly.
2523179237Sjb		 */
2524179237Sjb		if (mode == REG_ONLY) {
2525179237Sjb			if (strcmp(dp->it_name, "movlps") == 0)
2526179237Sjb				(void) strncpy(x->d86_mneu, "movhlps", OPLEN);
2527179237Sjb			else if (strcmp(dp->it_name, "movhps") == 0)
2528179237Sjb				(void) strncpy(x->d86_mneu, "movlhps", OPLEN);
2529179237Sjb		}
2530179237Sjb#endif
2531179237Sjb		if (dp->it_adrmode == XMMXIMPL)
2532179237Sjb			mode = 0;	/* change for memory access size... */
2533179237Sjb		break;
2534179237Sjb
2535179237Sjb	/* SIMD xmm reg to memory or xmm reg */
2536179237Sjb	case XMMS:
2537179237Sjb	case XMMOS:
2538179237Sjb	case XMMMS:
2539179237Sjb	case XMMOMS:
2540179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2541179237Sjb#ifdef DIS_TEXT
2542179237Sjb		if ((strcmp(dp->it_name, "movlps") == 0 ||
2543179237Sjb		    strcmp(dp->it_name, "movhps") == 0 ||
2544179237Sjb		    strcmp(dp->it_name, "movntps") == 0) &&
2545179237Sjb		    mode == REG_ONLY)
2546179237Sjb			goto error;
2547179237Sjb#endif
2548179237Sjb		wbit = XMM_OPND;
2549179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
2550179237Sjb		break;
2551179237Sjb
2552179237Sjb	/* SIMD memory to xmm reg */
2553179237Sjb	case XMMM:
2554179237Sjb	case XMMOM:
2555179237Sjb		wbit = XMM_OPND;
2556179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2557179237Sjb#ifdef DIS_TEXT
2558179237Sjb		if (mode == REG_ONLY) {
2559179237Sjb			if (strcmp(dp->it_name, "movhps") == 0)
2560179237Sjb				(void) strncpy(x->d86_mneu, "movlhps", OPLEN);
2561179237Sjb			else
2562179237Sjb				goto error;
2563179237Sjb		}
2564179237Sjb#endif
2565179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
2566179237Sjb		break;
2567179237Sjb
2568179237Sjb	/* SIMD memory or r32 to xmm reg			*/
2569179237Sjb	case XMM3MX:
2570179237Sjb		wbit = LONG_OPND;
2571179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
2572179237Sjb		break;
2573179237Sjb
2574179237Sjb	case XMM3MXS:
2575179237Sjb		wbit = LONG_OPND;
2576179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
2577179237Sjb		break;
2578179237Sjb
2579179237Sjb	/* SIMD memory or mm reg to xmm reg			*/
2580179237Sjb	case XMMOMX:
2581179237Sjb	/* SIMD mm to xmm */
2582179237Sjb	case XMMMX:
2583179237Sjb		wbit = MM_OPND;
2584179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
2585179237Sjb		break;
2586179237Sjb
2587179237Sjb	/* SIMD memory or xmm reg to mm reg			*/
2588179237Sjb	case XMMXMM:
2589179237Sjb	case XMMOXMM:
2590179237Sjb	case XMMXM:
2591179237Sjb		wbit = XMM_OPND;
2592179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
2593179237Sjb		break;
2594179237Sjb
2595179237Sjb
2596179237Sjb	/* SIMD memory or xmm reg to r32			*/
2597179237Sjb	case XMMXM3:
2598179237Sjb		wbit = XMM_OPND;
2599179237Sjb		MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
2600179237Sjb		break;
2601179237Sjb
2602179237Sjb	/* SIMD xmm to r32					*/
2603179237Sjb	case XMMX3:
2604179237Sjb	case XMMOX3:
2605179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2606179237Sjb		if (mode != REG_ONLY)
2607179237Sjb			goto error;
2608179237Sjb		dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2609179237Sjb		dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
2610179237Sjb		dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
2611179237Sjb		NOMEM;
2612179237Sjb		break;
2613179237Sjb
2614179237Sjb	/* SIMD predicated memory or xmm reg with/to xmm reg */
2615179237Sjb	case XMMP:
2616179237Sjb	case XMMOPM:
2617179237Sjb		wbit = XMM_OPND;
2618179237Sjb		THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
2619179237Sjb
2620179237Sjb#ifdef DIS_TEXT
2621179237Sjb		/*
2622179237Sjb		 * cmpps and cmpss vary their instruction name based
2623179237Sjb		 * on the value of imm8.  Other XMMP instructions,
2624179237Sjb		 * such as shufps, require explicit specification of
2625179237Sjb		 * the predicate.
2626179237Sjb		 */
2627179237Sjb		if (dp->it_name[0] == 'c' &&
2628179237Sjb		    dp->it_name[1] == 'm' &&
2629179237Sjb		    dp->it_name[2] == 'p' &&
2630179237Sjb		    strlen(dp->it_name) == 5) {
2631179237Sjb			uchar_t pred = x->d86_opnd[0].d86_value & 0xff;
2632179237Sjb
2633179237Sjb			if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *)))
2634179237Sjb				goto error;
2635179237Sjb
2636179237Sjb			(void) strncpy(x->d86_mneu, "cmp", OPLEN);
2637179237Sjb			(void) strlcat(x->d86_mneu, dis_PREDSUFFIX[pred],
2638179237Sjb			    OPLEN);
2639179237Sjb			(void) strlcat(x->d86_mneu,
2640179237Sjb			    dp->it_name + strlen(dp->it_name) - 2,
2641179237Sjb			    OPLEN);
2642179237Sjb			x->d86_opnd[0] = x->d86_opnd[1];
2643179237Sjb			x->d86_opnd[1] = x->d86_opnd[2];
2644179237Sjb			x->d86_numopnds = 2;
2645179237Sjb		}
2646179237Sjb#endif
2647179237Sjb		break;
2648179237Sjb
2649179237Sjb	/* immediate operand to accumulator */
2650179237Sjb	case IA:
2651179237Sjb		wbit = WBIT(opcode2);
2652179237Sjb		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
2653179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
2654179237Sjb		NOMEM;
2655179237Sjb		break;
2656179237Sjb
2657179237Sjb	/* memory or register operand to accumulator */
2658179237Sjb	case MA:
2659179237Sjb		wbit = WBIT(opcode2);
2660179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2661179237Sjb		dtrace_get_operand(x, mode, r_m, wbit, 0);
2662179237Sjb		break;
2663179237Sjb
2664179237Sjb	/* si register to di register used to reference memory		*/
2665179237Sjb	case SD:
2666179237Sjb#ifdef DIS_TEXT
2667179237Sjb		dtrace_check_override(x, 0);
2668179237Sjb		x->d86_numopnds = 2;
2669179237Sjb		if (addr_size == SIZE64) {
2670179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
2671179237Sjb			    OPLEN);
2672179237Sjb			(void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
2673179237Sjb			    OPLEN);
2674179237Sjb		} else if (addr_size == SIZE32) {
2675179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
2676179237Sjb			    OPLEN);
2677179237Sjb			(void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
2678179237Sjb			    OPLEN);
2679179237Sjb		} else {
2680179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
2681179237Sjb			    OPLEN);
2682179237Sjb			(void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
2683179237Sjb			    OPLEN);
2684179237Sjb		}
2685179237Sjb#endif
2686179237Sjb		wbit = LONG_OPND;
2687179237Sjb		break;
2688179237Sjb
2689179237Sjb	/* accumulator to di register				*/
2690179237Sjb	case AD:
2691179237Sjb		wbit = WBIT(opcode2);
2692179237Sjb#ifdef DIS_TEXT
2693179237Sjb		dtrace_check_override(x, 1);
2694179237Sjb		x->d86_numopnds = 2;
2695179237Sjb		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0);
2696179237Sjb		if (addr_size == SIZE64)
2697179237Sjb			(void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
2698179237Sjb			    OPLEN);
2699179237Sjb		else if (addr_size == SIZE32)
2700179237Sjb			(void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
2701179237Sjb			    OPLEN);
2702179237Sjb		else
2703179237Sjb			(void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
2704179237Sjb			    OPLEN);
2705179237Sjb#endif
2706179237Sjb		break;
2707179237Sjb
2708179237Sjb	/* si register to accumulator				*/
2709179237Sjb	case SA:
2710179237Sjb		wbit = WBIT(opcode2);
2711179237Sjb#ifdef DIS_TEXT
2712179237Sjb		dtrace_check_override(x, 0);
2713179237Sjb		x->d86_numopnds = 2;
2714179237Sjb		if (addr_size == SIZE64)
2715179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
2716179237Sjb			    OPLEN);
2717179237Sjb		else if (addr_size == SIZE32)
2718179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
2719179237Sjb			    OPLEN);
2720179237Sjb		else
2721179237Sjb			(void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
2722179237Sjb			    OPLEN);
2723179237Sjb		dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
2724179237Sjb#endif
2725179237Sjb		break;
2726179237Sjb
2727179237Sjb	/*
2728179237Sjb	 * single operand, a 16/32 bit displacement
2729179237Sjb	 */
2730179237Sjb	case D:
2731179237Sjb		wbit = LONG_OPND;
2732179237Sjb		dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
2733179237Sjb		NOMEM;
2734179237Sjb		break;
2735179237Sjb
2736179237Sjb	/* jmp/call indirect to memory or register operand		*/
2737179237Sjb	case INM:
2738179237Sjb#ifdef DIS_TEXT
2739179237Sjb		(void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN);
2740179237Sjb#endif
2741179237Sjb		dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
2742179237Sjb		dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
2743179237Sjb		wbit = LONG_OPND;
2744179237Sjb		break;
2745179237Sjb
2746179237Sjb	/*
2747179237Sjb	 * for long jumps and long calls -- a new code segment
2748179237Sjb	 * register and an offset in IP -- stored in object
2749179237Sjb	 * code in reverse order. Note - not valid in amd64
2750179237Sjb	 */
2751179237Sjb	case SO:
2752179237Sjb		dtrace_check_override(x, 1);
2753179237Sjb		wbit = LONG_OPND;
2754179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1);
2755179237Sjb#ifdef DIS_TEXT
2756179237Sjb		x->d86_opnd[1].d86_mode = MODE_SIGNED;
2757179237Sjb#endif
2758179237Sjb		/* will now get segment operand */
2759179237Sjb		dtrace_imm_opnd(x, wbit, 2, 0);
2760179237Sjb		break;
2761179237Sjb
2762179237Sjb	/*
2763179237Sjb	 * jmp/call. single operand, 8 bit displacement.
2764179237Sjb	 * added to current EIP in 'compofff'
2765179237Sjb	 */
2766179237Sjb	case BD:
2767179237Sjb		dtrace_disp_opnd(x, BYTE_OPND, 1, 0);
2768179237Sjb		NOMEM;
2769179237Sjb		break;
2770179237Sjb
2771179237Sjb	/* single 32/16 bit immediate operand			*/
2772179237Sjb	case I:
2773179237Sjb		wbit = LONG_OPND;
2774179237Sjb		dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
2775179237Sjb		break;
2776179237Sjb
2777179237Sjb	/* single 8 bit immediate operand			*/
2778179237Sjb	case Ib:
2779179237Sjb		wbit = LONG_OPND;
2780179237Sjb		dtrace_imm_opnd(x, wbit, 1, 0);
2781179237Sjb		break;
2782179237Sjb
2783179237Sjb	case ENTER:
2784179237Sjb		wbit = LONG_OPND;
2785179237Sjb		dtrace_imm_opnd(x, wbit, 2, 0);
2786179237Sjb		dtrace_imm_opnd(x, wbit, 1, 1);
2787179237Sjb		switch (opnd_size) {
2788179237Sjb		case SIZE64:
2789179237Sjb			x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8;
2790179237Sjb			break;
2791179237Sjb		case SIZE32:
2792179237Sjb			x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4;
2793179237Sjb			break;
2794179237Sjb		case SIZE16:
2795179237Sjb			x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2;
2796179237Sjb			break;
2797179237Sjb		}
2798179237Sjb
2799179237Sjb		break;
2800179237Sjb
2801179237Sjb	/* 16-bit immediate operand */
2802179237Sjb	case RET:
2803179237Sjb		wbit = LONG_OPND;
2804179237Sjb		dtrace_imm_opnd(x, wbit, 2, 0);
2805179237Sjb		break;
2806179237Sjb
2807179237Sjb	/* single 8 bit port operand				*/
2808179237Sjb	case P:
2809179237Sjb		dtrace_check_override(x, 0);
2810179237Sjb		dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
2811179237Sjb		NOMEM;
2812179237Sjb		break;
2813179237Sjb
2814179237Sjb	/* single operand, dx register (variable port instruction) */
2815179237Sjb	case V:
2816179237Sjb		x->d86_numopnds = 1;
2817179237Sjb		dtrace_check_override(x, 0);
2818179237Sjb#ifdef DIS_TEXT
2819179237Sjb		(void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN);
2820179237Sjb#endif
2821179237Sjb		NOMEM;
2822179237Sjb		break;
2823179237Sjb
2824179237Sjb	/*
2825179237Sjb	 * The int instruction, which has two forms:
2826179237Sjb	 * int 3 (breakpoint) or
2827179237Sjb	 * int n, where n is indicated in the subsequent
2828179237Sjb	 * byte (format Ib).  The int 3 instruction (opcode 0xCC),
2829179237Sjb	 * where, although the 3 looks  like an operand,
2830179237Sjb	 * it is implied by the opcode. It must be converted
2831179237Sjb	 * to the correct base and output.
2832179237Sjb	 */
2833179237Sjb	case INT3:
2834179237Sjb#ifdef DIS_TEXT
2835179237Sjb		x->d86_numopnds = 1;
2836179237Sjb		x->d86_opnd[0].d86_mode = MODE_SIGNED;
2837179237Sjb		x->d86_opnd[0].d86_value_size = 1;
2838179237Sjb		x->d86_opnd[0].d86_value = 3;
2839179237Sjb#endif
2840179237Sjb		NOMEM;
2841179237Sjb		break;
2842179237Sjb
2843179237Sjb	/* single 8 bit immediate operand			*/
2844179237Sjb	case INTx:
2845179237Sjb		dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
2846179237Sjb		NOMEM;
2847179237Sjb		break;
2848179237Sjb
2849179237Sjb	/* an unused byte must be discarded */
2850179237Sjb	case U:
2851179237Sjb		if (x->d86_get_byte(x->d86_data) < 0)
2852179237Sjb			goto error;
2853179237Sjb		x->d86_len++;
2854179237Sjb		NOMEM;
2855179237Sjb		break;
2856179237Sjb
2857179237Sjb	case CBW:
2858179237Sjb#ifdef DIS_TEXT
2859179237Sjb		if (opnd_size == SIZE16)
2860179237Sjb			(void) strlcat(x->d86_mneu, "cbtw", OPLEN);
2861179237Sjb		else if (opnd_size == SIZE32)
2862179237Sjb			(void) strlcat(x->d86_mneu, "cwtl", OPLEN);
2863179237Sjb		else
2864179237Sjb			(void) strlcat(x->d86_mneu, "cltq", OPLEN);
2865179237Sjb#endif
2866179237Sjb		wbit = LONG_OPND;
2867179237Sjb		NOMEM;
2868179237Sjb		break;
2869179237Sjb
2870179237Sjb	case CWD:
2871179237Sjb#ifdef DIS_TEXT
2872179237Sjb		if (opnd_size == SIZE16)
2873179237Sjb			(void) strlcat(x->d86_mneu, "cwtd", OPLEN);
2874179237Sjb		else if (opnd_size == SIZE32)
2875179237Sjb			(void) strlcat(x->d86_mneu, "cltd", OPLEN);
2876179237Sjb		else
2877179237Sjb			(void) strlcat(x->d86_mneu, "cqtd", OPLEN);
2878179237Sjb#endif
2879179237Sjb		wbit = LONG_OPND;
2880179237Sjb		NOMEM;
2881179237Sjb		break;
2882179237Sjb
2883179237Sjb	case XMMSFNC:
2884179237Sjb		/*
2885179237Sjb		 * sfence is sfence if mode is REG_ONLY.  If mode isn't
2886179237Sjb		 * REG_ONLY, mnemonic should be 'clflush'.
2887179237Sjb		 */
2888179237Sjb		dtrace_get_modrm(x, &mode, &reg, &r_m);
2889179237Sjb
2890179237Sjb		/* sfence doesn't take operands */
2891179237Sjb#ifdef DIS_TEXT
2892179237Sjb		if (mode == REG_ONLY) {
2893179237Sjb			(void) strlcat(x->d86_mneu, "sfence", OPLEN);
2894179237Sjb		} else {
2895179237Sjb			(void) strlcat(x->d86_mneu, "clflush", OPLEN);
2896179237Sjb			dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2897179237Sjb			dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
2898179237Sjb			NOMEM;
2899179237Sjb		}
2900179237Sjb#else
2901179237Sjb		if (mode != REG_ONLY) {
2902179237Sjb			dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
2903179237Sjb			dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
2904179237Sjb			NOMEM;
2905179237Sjb		}
2906179237Sjb#endif
2907179237Sjb		break;
2908179237Sjb
2909179237Sjb	/*
2910179237Sjb	 * no disassembly, the mnemonic was all there was so go on
2911179237Sjb	 */
2912179237Sjb	case NORM:
2913179237Sjb		if (dp->it_invalid32 && cpu_mode != SIZE64)
2914179237Sjb			goto error;
2915179237Sjb		NOMEM;
2916179237Sjb		/*FALLTHROUGH*/
2917179237Sjb	case IMPLMEM:
2918179237Sjb		break;
2919179237Sjb
2920179237Sjb	case XMMFENCE:
2921179237Sjb		/*
2922179237Sjb		 * Only the following exact byte sequences are allowed:
2923179237Sjb		 *
2924179237Sjb		 * 	0f ae e8	lfence
2925179237Sjb		 * 	0f ae f0	mfence
2926179237Sjb		 */
2927179237Sjb		if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 &&
2928179237Sjb		    (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0)
2929179237Sjb			goto error;
2930179237Sjb
2931179237Sjb		break;
2932179237Sjb
2933179237Sjb
2934179237Sjb	/* float reg */
2935179237Sjb	case F:
2936179237Sjb#ifdef DIS_TEXT
2937179237Sjb		x->d86_numopnds = 1;
2938179237Sjb		(void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN);
2939179237Sjb		x->d86_opnd[0].d86_opnd[4] = r_m + '0';
2940179237Sjb#endif
2941179237Sjb		NOMEM;
2942179237Sjb		break;
2943179237Sjb
2944179237Sjb	/* float reg to float reg, with ret bit present */
2945179237Sjb	case FF:
2946179237Sjb		vbit = opcode2 >> 2 & 0x1;	/* vbit = 1: st -> st(i) */
2947179237Sjb		/*FALLTHROUGH*/
2948179237Sjb	case FFC:				/* case for vbit always = 0 */
2949179237Sjb#ifdef DIS_TEXT
2950179237Sjb		x->d86_numopnds = 2;
2951179237Sjb		(void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN);
2952179237Sjb		(void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN);
2953179237Sjb		x->d86_opnd[vbit].d86_opnd[4] = r_m + '0';
2954179237Sjb#endif
2955179237Sjb		NOMEM;
2956179237Sjb		break;
2957179237Sjb
2958179237Sjb	/* an invalid op code */
2959179237Sjb	case AM:
2960179237Sjb	case DM:
2961179237Sjb	case OVERRIDE:
2962179237Sjb	case PREFIX:
2963179237Sjb	case UNKNOWN:
2964179237Sjb		NOMEM;
2965179237Sjb	default:
2966179237Sjb		goto error;
2967179237Sjb	} /* end switch */
2968179237Sjb	if (x->d86_error)
2969179237Sjb		goto error;
2970179237Sjb
2971179237Sjbdone:
2972179237Sjb#ifdef DIS_MEM
2973179237Sjb	/*
2974179237Sjb	 * compute the size of any memory accessed by the instruction
2975179237Sjb	 */
2976179237Sjb	if (x->d86_memsize != 0) {
2977179237Sjb		return (0);
2978179237Sjb	} else if (dp->it_stackop) {
2979179237Sjb		switch (opnd_size) {
2980179237Sjb		case SIZE16:
2981179237Sjb			x->d86_memsize = 2;
2982179237Sjb			break;
2983179237Sjb		case SIZE32:
2984179237Sjb			x->d86_memsize = 4;
2985179237Sjb			break;
2986179237Sjb		case SIZE64:
2987179237Sjb			x->d86_memsize = 8;
2988179237Sjb			break;
2989179237Sjb		}
2990179237Sjb	} else if (nomem || mode == REG_ONLY) {
2991179237Sjb		x->d86_memsize = 0;
2992179237Sjb
2993179237Sjb	} else if (dp->it_size != 0) {
2994179237Sjb		/*
2995179237Sjb		 * In 64 bit mode descriptor table entries
2996179237Sjb		 * go up to 10 bytes and popf/pushf are always 8 bytes
2997179237Sjb		 */
2998179237Sjb		if (x->d86_mode == SIZE64 && dp->it_size == 6)
2999179237Sjb			x->d86_memsize = 10;
3000179237Sjb		else if (x->d86_mode == SIZE64 && opcode1 == 0x9 &&
3001179237Sjb		    (opcode2 == 0xc || opcode2 == 0xd))
3002179237Sjb			x->d86_memsize = 8;
3003179237Sjb		else
3004179237Sjb			x->d86_memsize = dp->it_size;
3005179237Sjb
3006179237Sjb	} else if (wbit == 0) {
3007179237Sjb		x->d86_memsize = 1;
3008179237Sjb
3009179237Sjb	} else if (wbit == LONG_OPND) {
3010179237Sjb		if (opnd_size == SIZE64)
3011179237Sjb			x->d86_memsize = 8;
3012179237Sjb		else if (opnd_size == SIZE32)
3013179237Sjb			x->d86_memsize = 4;
3014179237Sjb		else
3015179237Sjb			x->d86_memsize = 2;
3016179237Sjb
3017179237Sjb	} else if (wbit == SEG_OPND) {
3018179237Sjb		x->d86_memsize = 4;
3019179237Sjb
3020179237Sjb	} else {
3021179237Sjb		x->d86_memsize = 8;
3022179237Sjb	}
3023179237Sjb#endif
3024179237Sjb	return (0);
3025179237Sjb
3026179237Sjberror:
3027179237Sjb#ifdef DIS_TEXT
3028179237Sjb	(void) strlcat(x->d86_mneu, "undef", OPLEN);
3029179237Sjb#endif
3030179237Sjb	return (1);
3031179237Sjb}
3032179237Sjb
3033179237Sjb#ifdef DIS_TEXT
3034179237Sjb
3035179237Sjb/*
3036179237Sjb * Some instructions should have immediate operands printed
3037179237Sjb * as unsigned integers. We compare against this table.
3038179237Sjb */
3039179237Sjbstatic char *unsigned_ops[] = {
3040179237Sjb	"or", "and", "xor", "test", "in", "out", "lcall", "ljmp",
3041179237Sjb	"rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl",
3042179237Sjb	0
3043179237Sjb};
3044179237Sjb
3045179237Sjbstatic int
3046179237Sjbisunsigned_op(char *opcode)
3047179237Sjb{
3048179237Sjb	char *where;
3049179237Sjb	int i;
3050179237Sjb	int is_unsigned = 0;
3051179237Sjb
3052179237Sjb	/*
3053179237Sjb	 * Work back to start of last mnemonic, since we may have
3054179237Sjb	 * prefixes on some opcodes.
3055179237Sjb	 */
3056179237Sjb	where = opcode + strlen(opcode) - 1;
3057179237Sjb	while (where > opcode && *where != ' ')
3058179237Sjb		--where;
3059179237Sjb	if (*where == ' ')
3060179237Sjb		++where;
3061179237Sjb
3062179237Sjb	for (i = 0; unsigned_ops[i]; ++i) {
3063179237Sjb		if (strncmp(where, unsigned_ops[i],
3064179237Sjb		    strlen(unsigned_ops[i])))
3065179237Sjb			continue;
3066179237Sjb		is_unsigned = 1;
3067179237Sjb		break;
3068179237Sjb	}
3069179237Sjb	return (is_unsigned);
3070179237Sjb}
3071179237Sjb
3072179237Sjb/* ARGSUSED */
3073179237Sjbvoid
3074179237Sjbdtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf,
3075179237Sjb    size_t buflen)
3076179237Sjb{
3077179237Sjb	int i;
3078179237Sjb
3079179237Sjb	dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mneu);
3080179237Sjb
3081179237Sjb	/*
3082179237Sjb	 * For PC-relative jumps, the pc is really the next pc after executing
3083179237Sjb	 * this instruction, so increment it appropriately.
3084179237Sjb	 */
3085179237Sjb	pc += dis->d86_len;
3086179237Sjb
3087179237Sjb	for (i = 0; i < dis->d86_numopnds; i++) {
3088179237Sjb		d86opnd_t *op = &dis->d86_opnd[i];
3089179237Sjb		int64_t sv;
3090179237Sjb		uint64_t mask;
3091179237Sjb
3092179237Sjb		if (i != 0)
3093179237Sjb			(void) strlcat(buf, ",", buflen);
3094179237Sjb
3095179237Sjb		(void) strlcat(buf, op->d86_prefix, buflen);
3096179237Sjb
3097179237Sjb		sv = op->d86_value;
3098179237Sjb
3099179237Sjb		switch (op->d86_mode) {
3100179237Sjb
3101179237Sjb		case MODE_NONE:
3102179237Sjb
3103179237Sjb			(void) strlcat(buf, op->d86_opnd, buflen);
3104179237Sjb			break;
3105179237Sjb
3106179237Sjb		case MODE_SIGNED:
3107179237Sjb		case MODE_IMPLIED:
3108179237Sjb		case MODE_OFFSET:
3109179237Sjb
3110179237Sjb			if (dis->d86_seg_prefix)
3111179237Sjb				(void) strlcat(buf, dis->d86_seg_prefix,
3112179237Sjb				    buflen);
3113179237Sjb
3114179237Sjb			switch (op->d86_value_size) {
3115179237Sjb			case 1:
3116179237Sjb				sv = (int8_t)sv;
3117179237Sjb				mask = 0xff;
3118179237Sjb				break;
3119179237Sjb			case 2:
3120179237Sjb				sv = (int16_t)sv;
3121179237Sjb				mask = 0xffff;
3122179237Sjb				break;
3123179237Sjb			case 4:
3124179237Sjb				sv = (int32_t)sv;
3125179237Sjb				mask = 0xffffffff;
3126179237Sjb				break;
3127179237Sjb			case 8:
3128179237Sjb				mask = 0xffffffffffffffffULL;
3129179237Sjb				break;
3130179237Sjb			}
3131179237Sjb
3132179237Sjb			if (op->d86_mode == MODE_SIGNED ||
3133179237Sjb			    op->d86_mode == MODE_IMPLIED)
3134179237Sjb				(void) strlcat(buf, "$", buflen);
3135179237Sjb
3136179237Sjb			if (sv < 0 && sv > -0xffff &&
3137179237Sjb			    !isunsigned_op(dis->d86_mneu)) {
3138179237Sjb				dis->d86_sprintf_func(buf + strlen(buf),
3139179237Sjb				    buflen - strlen(buf),
3140179237Sjb				    (dis->d86_flags & DIS_OP_OCTAL) ?
3141179237Sjb				    "-0%llo" : "-0x%llx", -sv & mask);
3142179237Sjb			} else {
3143179237Sjb				dis->d86_sprintf_func(buf + strlen(buf),
3144179237Sjb				    buflen - strlen(buf),
3145179237Sjb				    (dis->d86_flags & DIS_OP_OCTAL) ?
3146179237Sjb				    "0%llo" : "0x%llx", sv & mask);
3147179237Sjb			}
3148179237Sjb			(void) strlcat(buf, op->d86_opnd, buflen);
3149179237Sjb			break;
3150179237Sjb
3151179237Sjb		case MODE_IPREL:
3152179237Sjb
3153179237Sjb			switch (op->d86_value_size) {
3154179237Sjb			case 1:
3155179237Sjb				sv = (int8_t)sv;
3156179237Sjb				break;
3157179237Sjb			case 2:
3158179237Sjb				sv = (int16_t)sv;
3159179237Sjb				break;
3160179237Sjb			case 4:
3161179237Sjb				sv = (int32_t)sv;
3162179237Sjb				break;
3163179237Sjb			}
3164179237Sjb
3165179237Sjb			if (sv < 0)
3166179237Sjb				dis->d86_sprintf_func(buf + strlen(buf),
3167179237Sjb				    buflen - strlen(buf),
3168179237Sjb				    (dis->d86_flags & DIS_OP_OCTAL) ?
3169179237Sjb				    "-0%llo" : "-0x%llx", -sv - dis->d86_len);
3170179237Sjb			else
3171179237Sjb				dis->d86_sprintf_func(buf + strlen(buf),
3172179237Sjb				    buflen - strlen(buf),
3173179237Sjb				    (dis->d86_flags & DIS_OP_OCTAL) ?
3174179237Sjb				    "+0%llo" : "+0x%llx", sv + dis->d86_len);
3175179237Sjb
3176179237Sjb			(void) strlcat(buf, "\t<", buflen);
3177179237Sjb
3178179237Sjb			if (dis->d86_sym_lookup == NULL ||
3179179237Sjb			    dis->d86_sym_lookup(dis->d86_data, pc + sv,
3180179237Sjb			    buf + strlen(buf), buflen - strlen(buf)) != 0)
3181179237Sjb				dis->d86_sprintf_func(buf + strlen(buf),
3182179237Sjb				    buflen - strlen(buf),
3183179237Sjb				    (dis->d86_flags & DIS_OP_OCTAL) ?
3184179237Sjb				    "0%llo" : "0x%llx", pc + sv);
3185179237Sjb
3186179237Sjb			(void) strlcat(buf, ">", buflen);
3187179237Sjb
3188179237Sjb			break;
3189179237Sjb		}
3190179237Sjb	}
3191179237Sjb}
3192179237Sjb
3193179237Sjb#endif /* DIS_TEXT */
3194