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