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