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