]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/i386/dis_tables.c
xnu-3247.1.106.tar.gz
[apple/xnu.git] / bsd / dev / i386 / dis_tables.c
1 /*
2 *
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
23 /*
24 * Copyright (c) 2015, Joyent, Inc.
25 * Copyright (c) 2008 Sun Microsystems, Inc. All rights reserved.
26 *
27 * Use is subject to license terms.
28 */
29
30 /*
31 * Copyright (c) 2010, Intel Corporation.
32 * All rights reserved.
33 */
34
35 /* Copyright (c) 1988 AT&T */
36 /* All Rights Reserved */
37
38
39 /*
40 * #pragma ident "@(#)dis_tables.c 1.18 08/05/24 SMI"
41 */
42 #include <sys/dtrace.h>
43 #include <sys/dtrace_glue.h>
44 #include <sys/dis_tables.h>
45
46 /* BEGIN CSTYLED */
47
48 /*
49 * Disassembly begins in dis_distable, which is equivalent to the One-byte
50 * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy). The
51 * decoding loops then traverse out through the other tables as necessary to
52 * decode a given instruction.
53 *
54 * The behavior of this file can be controlled by one of the following flags:
55 *
56 * DIS_TEXT Include text for disassembly
57 * DIS_MEM Include memory-size calculations
58 *
59 * Either or both of these can be defined.
60 *
61 * This file is not, and will never be, cstyled. If anything, the tables should
62 * be taken out another tab stop or two so nothing overlaps.
63 */
64
65 /*
66 * These functions must be provided for the consumer to do disassembly.
67 */
68 #ifdef DIS_TEXT
69 extern char *strncpy(char *, const char *, size_t);
70 extern size_t strlen(const char *);
71 extern int strncmp(const char *, const char *, size_t);
72 extern size_t strlcat(char *, const char *, size_t);
73 #endif
74
75
76 #define TERM 0 /* used to indicate that the 'indirect' */
77 /* field terminates - no pointer. */
78
79 /* Used to decode instructions. */
80 typedef struct instable {
81 struct instable *it_indirect; /* for decode op codes */
82 uchar_t it_adrmode;
83 #ifdef DIS_TEXT
84 char it_name[NCPS];
85 uint_t it_suffix:1; /* mnem + "w", "l", or "d" */
86 #endif
87 #ifdef DIS_MEM
88 uint_t it_size:16;
89 #endif
90 uint_t it_invalid64:1; /* opcode invalid in amd64 */
91 uint_t it_always64:1; /* 64 bit when in 64 bit mode */
92 uint_t it_invalid32:1; /* invalid in IA32 */
93 uint_t it_stackop:1; /* push/pop stack operation */
94 } instable_t;
95
96 /*
97 * Instruction formats.
98 */
99 enum {
100 UNKNOWN,
101 MRw,
102 IMlw,
103 IMw,
104 IR,
105 OA,
106 AO,
107 MS,
108 SM,
109 Mv,
110 Mw,
111 M, /* register or memory */
112 Mb, /* register or memory, always byte sized */
113 MO, /* memory only (no registers) */
114 PREF,
115 SWAPGS,
116 MONITOR_MWAIT,
117 R,
118 RA,
119 SEG,
120 MR,
121 RM,
122 IA,
123 MA,
124 SD,
125 AD,
126 SA,
127 D,
128 INM,
129 SO,
130 BD,
131 I,
132 P,
133 V,
134 DSHIFT, /* for double shift that has an 8-bit immediate */
135 U,
136 OVERRIDE,
137 NORM, /* instructions w/o ModR/M byte, no memory access */
138 IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */
139 O, /* for call */
140 JTAB, /* jump table */
141 IMUL, /* for 186 iimul instr */
142 CBW, /* so data16 can be evaluated for cbw and variants */
143 MvI, /* for 186 logicals */
144 ENTER, /* for 186 enter instr */
145 RMw, /* for 286 arpl instr */
146 Ib, /* for push immediate byte */
147 F, /* for 287 instructions */
148 FF, /* for 287 instructions */
149 FFC, /* for 287 instructions */
150 DM, /* 16-bit data */
151 AM, /* 16-bit addr */
152 LSEG, /* for 3-bit seg reg encoding */
153 MIb, /* for 386 logicals */
154 SREG, /* for 386 special registers */
155 PREFIX, /* a REP instruction prefix */
156 LOCK, /* a LOCK instruction prefix */
157 INT3, /* The int 3 instruction, which has a fake operand */
158 INTx, /* The normal int instruction, with explicit int num */
159 DSHIFTcl, /* for double shift that implicitly uses %cl */
160 CWD, /* so data16 can be evaluated for cwd and variants */
161 RET, /* single immediate 16-bit operand */
162 MOVZ, /* for movs and movz, with different size operands */
163 CRC32, /* for crc32, with different size operands */
164 XADDB, /* for xaddb */
165 MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */
166 MOVBE, /* movbe 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 */
179 MMOPM_66o, /* MMX/SIMD-Int 0x66 optional mm/mem -> mm,imm8 */
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 */
194 XMM_66r, /* SIMD 0x66 prefix required xmm/mem -> xmm */
195 XMM_66o, /* SIMD 0x66 prefix optional xmm/mem -> xmm */
196 XMMXIMPL, /* SIMD xmm -> xmm (mem) */
197 XMM3P, /* SIMD xmm -> r32,imm8 */
198 XMM3PM_66r, /* SIMD 0x66 prefix required xmm -> r32/mem,imm8 */
199 XMMP, /* SIMD xmm/mem w/to xmm,imm8 */
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 */
202 XMMPRM, /* SIMD r32/mem -> xmm,imm8 */
203 XMMPRM_66r, /* SIMD 0x66 prefix required r32/mem -> xmm,imm8 */
204 XMMS, /* SIMD xmm -> xmm/mem */
205 XMMM, /* SIMD mem -> xmm */
206 XMMM_66r, /* SIMD 0x66 prefix required mem -> xmm */
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 */
216 XMMX2I, /* SIMD xmm -> xmm, imm, imm */
217 XMM2I, /* SIMD xmm, imm, imm */
218 XMMFENCE, /* SIMD lfence or mfence */
219 XMMSFNC, /* SIMD sfence (none or mem) */
220 XGETBV_XSETBV,
221 VEX_NONE, /* VEX no operand */
222 VEX_MO, /* VEX mod_rm -> implicit reg */
223 VEX_RMrX, /* VEX VEX.vvvv, mod_rm -> mod_reg */
224 VEX_RRX, /* VEX VEX.vvvv, mod_reg -> mod_rm */
225 VEX_RMRX, /* VEX VEX.vvvv, mod_rm, imm8[7:4] -> mod_reg */
226 VEX_MX, /* VEX mod_rm -> mod_reg */
227 VEX_MXI, /* VEX mod_rm, imm8 -> mod_reg */
228 VEX_XXI, /* VEX mod_rm, imm8 -> VEX.vvvv */
229 VEX_MR, /* VEX mod_rm -> mod_reg */
230 VEX_RRI, /* VEX mod_reg, mod_rm -> implicit(eflags/r32) */
231 VEX_RX, /* VEX mod_reg -> mod_rm */
232 VEX_RR, /* VEX mod_rm -> mod_reg */
233 VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */
234 VEX_RM, /* VEX mod_reg -> mod_rm */
235 VEX_RIM, /* VEX mod_reg, imm8 -> mod_rm */
236 VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */
237 VEX_RMX, /* VEX VEX.vvvv, mod_rm -> mod_reg */
238 };
239
240 /*
241 * VEX prefixes
242 */
243 #define VEX_2bytes 0xC5 /* the first byte of two-byte form */
244 #define VEX_3bytes 0xC4 /* the first byte of three-byte form */
245
246 #define FILL 0x90 /* Fill byte used for alignment (nop) */
247
248 /*
249 ** Register numbers for the i386
250 */
251 #define EAX_REGNO 0
252 #define ECX_REGNO 1
253 #define EDX_REGNO 2
254 #define EBX_REGNO 3
255 #define ESP_REGNO 4
256 #define EBP_REGNO 5
257 #define ESI_REGNO 6
258 #define EDI_REGNO 7
259
260 /*
261 * modes for immediate values
262 */
263 #define MODE_NONE 0
264 #define MODE_IPREL 1 /* signed IP relative value */
265 #define MODE_SIGNED 2 /* sign extended immediate */
266 #define MODE_IMPLIED 3 /* constant value implied from opcode */
267 #define MODE_OFFSET 4 /* offset part of an address */
268 #define MODE_RIPREL 5 /* like IPREL, but from %rip (amd64) */
269
270 /*
271 * The letters used in these macros are:
272 * IND - indirect to another to another table
273 * "T" - means to Terminate indirections (this is the final opcode)
274 * "S" - means "operand length suffix required"
275 * "NS" - means "no suffix" which is the operand length suffix of the opcode
276 * "Z" - means instruction size arg required
277 * "u" - means the opcode is invalid in IA32 but valid in amd64
278 * "x" - means the opcode is invalid in amd64, but not IA32
279 * "y" - means the operand size is always 64 bits in 64 bit mode
280 * "p" - means push/pop stack operation
281 */
282
283 #if defined(DIS_TEXT) && defined(DIS_MEM)
284 #define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0}
285 #define INDx(table) {(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0}
286 #define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0}
287 #define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0}
288 #define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0}
289 #define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0}
290 #define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1}
291 #define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0}
292 #define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0}
293 #define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0}
294 #define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0}
295 #define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0}
296 #define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1}
297 #define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0}
298 #define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0}
299 #define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0}
300 #define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
301 #elif defined(DIS_TEXT)
302 #define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0}
303 #define INDx(table) {(instable_t *)table, 0, "", 0, 1, 0, 0, 0}
304 #define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0}
305 #define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0}
306 #define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0}
307 #define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0}
308 #define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1}
309 #define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0}
310 #define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0}
311 #define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0}
312 #define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0}
313 #define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0}
314 #define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1}
315 #define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0}
316 #define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0}
317 #define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0}
318 #define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
319 #elif defined(DIS_MEM)
320 #define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0, 0}
321 #define INDx(table) {(instable_t *)table, 0, 0, 1, 0, 0, 0}
322 #define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0}
323 #define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0}
324 #define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0}
325 #define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1}
326 #define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0}
327 #define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0}
328 #define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0}
329 #define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0}
330 #define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0}
331 #define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0}
332 #define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1}
333 #define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0}
334 #define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0}
335 #define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0}
336 #define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0}
337 #else
338 #define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0}
339 #define INDx(table) {(instable_t *)table, 0, 1, 0, 0, 0}
340 #define TNS(name, amode) {TERM, amode, 0, 0, 0, 0}
341 #define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0}
342 #define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0}
343 #define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1}
344 #define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0}
345 #define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0}
346 #define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0}
347 #define TS(name, amode) {TERM, amode, 0, 0, 0, 0}
348 #define TSx(name, amode) {TERM, amode, 1, 0, 0, 0}
349 #define TSy(name, amode) {TERM, amode, 0, 1, 0, 0}
350 #define TSp(name, amode) {TERM, amode, 0, 0, 0, 1}
351 #define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0}
352 #define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0}
353 #define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0}
354 #define INVALID {TERM, UNKNOWN, 0, 0, 0, 0}
355 #endif
356
357 #ifdef DIS_TEXT
358 /*
359 * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode
360 */
361 const char *const dis_addr16[3][8] = {
362 "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "",
363 "(%bx)",
364 "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)",
365 "(%bx)",
366 "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)",
367 "(%bx)",
368 };
369
370
371 /*
372 * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2
373 */
374 const char *const dis_addr32_mode0[16] = {
375 "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)",
376 "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)"
377 };
378
379 const char *const dis_addr32_mode12[16] = {
380 "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)",
381 "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)"
382 };
383
384 /*
385 * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2
386 */
387 const char *const dis_addr64_mode0[16] = {
388 "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)",
389 "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)"
390 };
391 const char *const dis_addr64_mode12[16] = {
392 "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)",
393 "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)"
394 };
395
396 /*
397 * decode for scale from SIB byte
398 */
399 const char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" };
400
401 /*
402 * register decoding for normal references to registers (ie. not addressing)
403 */
404 const char *const dis_REG8[16] = {
405 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
406 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
407 };
408
409 const char *const dis_REG8_REX[16] = {
410 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
411 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
412 };
413
414 const char *const dis_REG16[16] = {
415 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
416 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
417 };
418
419 const char *const dis_REG32[16] = {
420 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
421 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
422 };
423
424 const char *const dis_REG64[16] = {
425 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
426 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
427 };
428
429 const char *const dis_DEBUGREG[16] = {
430 "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7",
431 "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15"
432 };
433
434 const char *const dis_CONTROLREG[16] = {
435 "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?",
436 "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?"
437 };
438
439 const char *const dis_TESTREG[16] = {
440 "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
441 "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7"
442 };
443
444 const char *const dis_MMREG[16] = {
445 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
446 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
447 };
448
449 const char *const dis_XMMREG[16] = {
450 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
451 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15"
452 };
453
454 const char *const dis_YMMREG[16] = {
455 "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7",
456 "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15"
457 };
458
459 const char *const dis_SEGREG[16] = {
460 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>",
461 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>"
462 };
463
464 /*
465 * SIMD predicate suffixes
466 */
467 const char *const dis_PREDSUFFIX[8] = {
468 "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord"
469 };
470
471 const char *const dis_AVXvgrp7[3][8] = {
472 /*0 1 2 3 4 5 6 7*/
473 /*71*/ {"", "", "vpsrlw", "", "vpsraw", "", "vpsllw", ""},
474 /*72*/ {"", "", "vpsrld", "", "vpsrad", "", "vpslld", ""},
475 /*73*/ {"", "", "vpsrlq", "vpsrldq", "", "", "vpsllq", "vpslldq"}
476 };
477
478 #endif /* DIS_TEXT */
479
480
481
482
483 /*
484 * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63)
485 */
486 const instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ);
487
488 /*
489 * "decode table" for pause and clflush instructions
490 */
491 const instable_t dis_opPause = TNS("pause", NORM);
492
493 /*
494 * Decode table for 0x0F00 opcodes
495 */
496 const instable_t dis_op0F00[8] = {
497
498 /* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M),
499 /* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID,
500 };
501
502
503 /*
504 * Decode table for 0x0F01 opcodes
505 */
506 const instable_t dis_op0F01[8] = {
507
508 /* [0] */ TNSZ("sgdt",MO,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",MO,6),
509 /* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS),
510 };
511
512 /*
513 * Decode table for 0x0F18 opcodes -- SIMD prefetch
514 */
515 const instable_t dis_op0F18[8] = {
516
517 /* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF),
518 /* [4] */ TNSZ("xsave",M,512), TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC),
519 };
520
521 /*
522 * Decode table for 0x0FAE opcodes -- SIMD state save/restore
523 */
524 const instable_t dis_op0FAE[8] = {
525 /* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M),
526 /* [4] */ INVALID, TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC),
527 };
528
529 /*
530 * Decode table for 0x0FBA opcodes
531 */
532
533 const instable_t dis_op0FBA[8] = {
534
535 /* [0] */ INVALID, INVALID, INVALID, INVALID,
536 /* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb),
537 };
538
539 /*
540 * Decode table for 0x0FC7 opcode
541 */
542
543 const instable_t dis_op0FC7[8] = {
544
545 /* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID,
546 /* [4] */ INVALID, INVALID, INVALID, INVALID,
547 };
548
549
550 /*
551 * Decode table for 0x0FC8 opcode -- 486 bswap instruction
552 *
553 *bit pattern: 0000 1111 1100 1reg
554 */
555 const instable_t dis_op0FC8[4] = {
556 /* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID,
557 };
558
559 /*
560 * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions
561 */
562 const instable_t dis_op0F7123[4][8] = {
563 {
564 /* [70].0 */ INVALID, INVALID, INVALID, INVALID,
565 /* .4 */ INVALID, INVALID, INVALID, INVALID,
566 }, {
567 /* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID,
568 /* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID,
569 }, {
570 /* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID,
571 /* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID,
572 }, {
573 /* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH),
574 /* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH),
575 } };
576
577 /*
578 * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes.
579 */
580 const instable_t dis_opSIMD7123[32] = {
581 /* [70].0 */ INVALID, INVALID, INVALID, INVALID,
582 /* .4 */ INVALID, INVALID, INVALID, INVALID,
583
584 /* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID,
585 /* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID,
586
587 /* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID,
588 /* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID,
589
590 /* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH),
591 /* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH),
592 };
593
594 /*
595 * SIMD instructions have been wedged into the existing IA32 instruction
596 * set through the use of prefixes. That is, while 0xf0 0x58 may be
597 * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different
598 * instruction - addss. At present, three prefixes have been coopted in
599 * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The
600 * following tables are used to provide the prefixed instruction names.
601 * The arrays are sparse, but they're fast.
602 */
603
604 /*
605 * Decode table for SIMD instructions with the address size (0x66) prefix.
606 */
607 const instable_t dis_opSIMDdata16[256] = {
608 /* [00] */ INVALID, INVALID, INVALID, INVALID,
609 /* [04] */ INVALID, INVALID, INVALID, INVALID,
610 /* [08] */ INVALID, INVALID, INVALID, INVALID,
611 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
612
613 /* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8),
614 /* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8),
615 /* [18] */ INVALID, INVALID, INVALID, INVALID,
616 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
617
618 /* [20] */ INVALID, INVALID, INVALID, INVALID,
619 /* [24] */ INVALID, INVALID, INVALID, INVALID,
620 /* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16),
621 /* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8),
622
623 /* [30] */ INVALID, INVALID, INVALID, INVALID,
624 /* [34] */ INVALID, INVALID, INVALID, INVALID,
625 /* [38] */ INVALID, INVALID, INVALID, INVALID,
626 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
627
628 /* [40] */ INVALID, INVALID, INVALID, INVALID,
629 /* [44] */ INVALID, INVALID, INVALID, INVALID,
630 /* [48] */ INVALID, INVALID, INVALID, INVALID,
631 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
632
633 /* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID,
634 /* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16),
635 /* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16),
636 /* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16),
637
638 /* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16),
639 /* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16),
640 /* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16),
641 /* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16),
642
643 /* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID,
644 /* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID,
645 /* [78] */ TNSZ("extrq",XMM2I,16), TNSZ("extrq",XMM,16), INVALID, INVALID,
646 /* [7C] */ INVALID, INVALID, TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16),
647
648 /* [80] */ INVALID, INVALID, INVALID, INVALID,
649 /* [84] */ INVALID, INVALID, INVALID, INVALID,
650 /* [88] */ INVALID, INVALID, INVALID, INVALID,
651 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
652
653 /* [90] */ INVALID, INVALID, INVALID, INVALID,
654 /* [94] */ INVALID, INVALID, INVALID, INVALID,
655 /* [98] */ INVALID, INVALID, INVALID, INVALID,
656 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
657
658 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
659 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
660 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
661 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
662
663 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
664 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
665 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
666 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
667
668 /* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID,
669 /* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID,
670 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
671 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
672
673 /* [D0] */ INVALID, TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16),
674 /* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3),
675 /* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16),
676 /* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16),
677
678 /* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16),
679 /* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16),
680 /* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16),
681 /* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16),
682
683 /* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16),
684 /* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16),
685 /* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16),
686 /* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID,
687 };
688
689 const instable_t dis_opAVX660F[256] = {
690 /* [00] */ INVALID, INVALID, INVALID, INVALID,
691 /* [04] */ INVALID, INVALID, INVALID, INVALID,
692 /* [08] */ INVALID, INVALID, INVALID, INVALID,
693 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
694
695 /* [10] */ TNSZ("vmovupd",VEX_MX,16), TNSZ("vmovupd",VEX_RX,16), TNSZ("vmovlpd",VEX_RMrX,8), TNSZ("vmovlpd",VEX_RM,8),
696 /* [14] */ TNSZ("vunpcklpd",VEX_RMrX,16),TNSZ("vunpckhpd",VEX_RMrX,16),TNSZ("vmovhpd",VEX_RMrX,8), TNSZ("vmovhpd",VEX_RM,8),
697 /* [18] */ INVALID, INVALID, INVALID, INVALID,
698 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
699
700 /* [20] */ INVALID, INVALID, INVALID, INVALID,
701 /* [24] */ INVALID, INVALID, INVALID, INVALID,
702 /* [28] */ TNSZ("vmovapd",VEX_MX,16), TNSZ("vmovapd",VEX_RX,16), INVALID, TNSZ("vmovntpd",VEX_RM,16),
703 /* [2C] */ INVALID, INVALID, TNSZ("vucomisd",VEX_MX,8),TNSZ("vcomisd",VEX_MX,8),
704
705 /* [30] */ INVALID, INVALID, INVALID, INVALID,
706 /* [34] */ INVALID, INVALID, INVALID, INVALID,
707 /* [38] */ INVALID, INVALID, INVALID, INVALID,
708 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
709
710 /* [40] */ INVALID, INVALID, INVALID, INVALID,
711 /* [44] */ INVALID, INVALID, INVALID, INVALID,
712 /* [48] */ INVALID, INVALID, INVALID, INVALID,
713 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
714
715 /* [50] */ TNS("vmovmskpd",VEX_MR), TNSZ("vsqrtpd",VEX_MX,16), INVALID, INVALID,
716 /* [54] */ TNSZ("vandpd",VEX_RMrX,16), TNSZ("vandnpd",VEX_RMrX,16), TNSZ("vorpd",VEX_RMrX,16), TNSZ("vxorpd",VEX_RMrX,16),
717 /* [58] */ TNSZ("vaddpd",VEX_RMrX,16), TNSZ("vmulpd",VEX_RMrX,16), TNSZ("vcvtpd2ps",VEX_MX,16),TNSZ("vcvtps2dq",VEX_MX,16),
718 /* [5C] */ TNSZ("vsubpd",VEX_RMrX,16), TNSZ("vminpd",VEX_RMrX,16), TNSZ("vdivpd",VEX_RMrX,16), TNSZ("vmaxpd",VEX_RMrX,16),
719
720 /* [60] */ TNSZ("vpunpcklbw",VEX_RMrX,16),TNSZ("vpunpcklwd",VEX_RMrX,16),TNSZ("vpunpckldq",VEX_RMrX,16),TNSZ("vpacksswb",VEX_RMrX,16),
721 /* [64] */ TNSZ("vpcmpgtb",VEX_RMrX,16), TNSZ("vpcmpgtw",VEX_RMrX,16), TNSZ("vpcmpgtd",VEX_RMrX,16), TNSZ("vpackuswb",VEX_RMrX,16),
722 /* [68] */ TNSZ("vpunpckhbw",VEX_RMrX,16),TNSZ("vpunpckhwd",VEX_RMrX,16),TNSZ("vpunpckhdq",VEX_RMrX,16),TNSZ("vpackssdw",VEX_RMrX,16),
723 /* [6C] */ TNSZ("vpunpcklqdq",VEX_RMrX,16),TNSZ("vpunpckhqdq",VEX_RMrX,16),TNSZ("vmovd",VEX_MX,4),TNSZ("vmovdqa",VEX_MX,16),
724
725 /* [70] */ TNSZ("vpshufd",VEX_MXI,16), TNSZ("vgrp71",VEX_XXI,16), TNSZ("vgrp72",VEX_XXI,16), TNSZ("vgrp73",VEX_XXI,16),
726 /* [74] */ TNSZ("vpcmpeqb",VEX_RMrX,16), TNSZ("vpcmpeqw",VEX_RMrX,16), TNSZ("vpcmpeqd",VEX_RMrX,16), INVALID,
727 /* [78] */ INVALID, INVALID, INVALID, INVALID,
728 /* [7C] */ TNSZ("vhaddpd",VEX_RMrX,16), TNSZ("vhsubpd",VEX_RMrX,16), TNSZ("vmovd",VEX_RR,4), TNSZ("vmovdqa",VEX_RX,16),
729
730 /* [80] */ INVALID, INVALID, INVALID, INVALID,
731 /* [84] */ INVALID, INVALID, INVALID, INVALID,
732 /* [88] */ INVALID, INVALID, INVALID, INVALID,
733 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
734
735 /* [90] */ INVALID, INVALID, INVALID, INVALID,
736 /* [94] */ INVALID, INVALID, INVALID, INVALID,
737 /* [98] */ INVALID, INVALID, INVALID, INVALID,
738 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
739
740 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
741 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
742 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
743 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
744
745 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
746 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
747 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
748 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
749
750 /* [C0] */ INVALID, INVALID, TNSZ("vcmppd",VEX_RMRX,16), INVALID,
751 /* [C4] */ TNSZ("vpinsrw",VEX_RMRX,2),TNS("vpextrw",VEX_MR), TNSZ("vshufpd",VEX_RMRX,16), INVALID,
752 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
753 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
754
755 /* [D0] */ TNSZ("vaddsubpd",VEX_RMrX,16),TNSZ("vpsrlw",VEX_RMrX,16), TNSZ("vpsrld",VEX_RMrX,16), TNSZ("vpsrlq",VEX_RMrX,16),
756 /* [D4] */ TNSZ("vpaddq",VEX_RMrX,16), TNSZ("vpmullw",VEX_RMrX,16), TNSZ("vmovq",VEX_RX,8), TNS("vpmovmskb",VEX_MR),
757 /* [D8] */ TNSZ("vpsubusb",VEX_RMrX,16), TNSZ("vpsubusw",VEX_RMrX,16), TNSZ("vpminub",VEX_RMrX,16), TNSZ("vpand",VEX_RMrX,16),
758 /* [DC] */ TNSZ("vpaddusb",VEX_RMrX,16), TNSZ("vpaddusw",VEX_RMrX,16), TNSZ("vpmaxub",VEX_RMrX,16), TNSZ("vpandn",VEX_RMrX,16),
759
760 /* [E0] */ TNSZ("vpavgb",VEX_RMrX,16), TNSZ("vpsraw",VEX_RMrX,16), TNSZ("vpsrad",VEX_RMrX,16), TNSZ("vpavgw",VEX_RMrX,16),
761 /* [E4] */ TNSZ("vpmulhuw",VEX_RMrX,16), TNSZ("vpmulhw",VEX_RMrX,16), TNSZ("vcvttpd2dq",VEX_MX,16),TNSZ("vmovntdq",VEX_RM,16),
762 /* [E8] */ TNSZ("vpsubsb",VEX_RMrX,16), TNSZ("vpsubsw",VEX_RMrX,16), TNSZ("vpminsw",VEX_RMrX,16), TNSZ("vpor",VEX_RMrX,16),
763 /* [EC] */ TNSZ("vpaddsb",VEX_RMrX,16), TNSZ("vpaddsw",VEX_RMrX,16), TNSZ("vpmaxsw",VEX_RMrX,16), TNSZ("vpxor",VEX_RMrX,16),
764
765 /* [F0] */ INVALID, TNSZ("vpsllw",VEX_RMrX,16), TNSZ("vpslld",VEX_RMrX,16), TNSZ("vpsllq",VEX_RMrX,16),
766 /* [F4] */ TNSZ("vpmuludq",VEX_RMrX,16), TNSZ("vpmaddwd",VEX_RMrX,16), TNSZ("vpsadbw",VEX_RMrX,16), TNS("vmaskmovdqu",VEX_MX),
767 /* [F8] */ TNSZ("vpsubb",VEX_RMrX,16), TNSZ("vpsubw",VEX_RMrX,16), TNSZ("vpsubd",VEX_RMrX,16), TNSZ("vpsubq",VEX_RMrX,16),
768 /* [FC] */ TNSZ("vpaddb",VEX_RMrX,16), TNSZ("vpaddw",VEX_RMrX,16), TNSZ("vpaddd",VEX_RMrX,16), INVALID,
769 };
770
771 /*
772 * Decode table for SIMD instructions with the repnz (0xf2) prefix.
773 */
774 const instable_t dis_opSIMDrepnz[256] = {
775 /* [00] */ INVALID, INVALID, INVALID, INVALID,
776 /* [04] */ INVALID, INVALID, INVALID, INVALID,
777 /* [08] */ INVALID, INVALID, INVALID, INVALID,
778 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
779
780 /* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), INVALID, INVALID,
781 /* [14] */ INVALID, INVALID, INVALID, INVALID,
782 /* [18] */ INVALID, INVALID, INVALID, INVALID,
783 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
784
785 /* [20] */ INVALID, INVALID, INVALID, INVALID,
786 /* [24] */ INVALID, INVALID, INVALID, INVALID,
787 /* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),TNSZ("movntsd",XMMMS,8),
788 /* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID,
789
790 /* [30] */ INVALID, INVALID, INVALID, INVALID,
791 /* [34] */ INVALID, INVALID, INVALID, INVALID,
792 /* [38] */ INVALID, INVALID, INVALID, INVALID,
793 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
794
795 /* [40] */ INVALID, INVALID, INVALID, INVALID,
796 /* [44] */ INVALID, INVALID, INVALID, INVALID,
797 /* [48] */ INVALID, INVALID, INVALID, INVALID,
798 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
799
800 /* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID,
801 /* [54] */ INVALID, INVALID, INVALID, INVALID,
802 /* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID,
803 /* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8),
804
805 /* [60] */ INVALID, INVALID, INVALID, INVALID,
806 /* [64] */ INVALID, INVALID, INVALID, INVALID,
807 /* [68] */ INVALID, INVALID, INVALID, INVALID,
808 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
809
810 /* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID,
811 /* [74] */ INVALID, INVALID, INVALID, INVALID,
812 /* [78] */ TNSZ("insertq",XMMX2I,16),TNSZ("insertq",XMM,8),INVALID, INVALID,
813 /* [7C] */ INVALID, INVALID, INVALID, INVALID,
814
815 /* [80] */ INVALID, INVALID, INVALID, INVALID,
816 /* [84] */ INVALID, INVALID, INVALID, INVALID,
817 /* [88] */ INVALID, INVALID, INVALID, INVALID,
818 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
819
820 /* [90] */ INVALID, INVALID, INVALID, INVALID,
821 /* [94] */ INVALID, INVALID, INVALID, INVALID,
822 /* [98] */ INVALID, INVALID, INVALID, INVALID,
823 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
824
825 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
826 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
827 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
828 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
829
830 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
831 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
832 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
833 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
834
835 /* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID,
836 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
837 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
838 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
839
840 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
841 /* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID,
842 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
843 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
844
845 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
846 /* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID,
847 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
848 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
849
850 /* [F0] */ INVALID, INVALID, INVALID, INVALID,
851 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
852 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
853 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
854 };
855
856 const instable_t dis_opAVXF20F[256] = {
857 /* [00] */ INVALID, INVALID, INVALID, INVALID,
858 /* [04] */ INVALID, INVALID, INVALID, INVALID,
859 /* [08] */ INVALID, INVALID, INVALID, INVALID,
860 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
861
862 /* [10] */ TNSZ("vmovsd",VEX_RMrX,8), TNSZ("vmovsd",VEX_RRX,8), TNSZ("vmovddup",VEX_MX,8), INVALID,
863 /* [14] */ INVALID, INVALID, INVALID, INVALID,
864 /* [18] */ INVALID, INVALID, INVALID, INVALID,
865 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
866
867 /* [20] */ INVALID, INVALID, INVALID, INVALID,
868 /* [24] */ INVALID, INVALID, INVALID, INVALID,
869 /* [28] */ INVALID, INVALID, TNSZ("vcvtsi2sd",VEX_RMrX,4),INVALID,
870 /* [2C] */ TNSZ("vcvttsd2si",VEX_MR,8),TNSZ("vcvtsd2si",VEX_MR,8),INVALID, INVALID,
871
872 /* [30] */ INVALID, INVALID, INVALID, INVALID,
873 /* [34] */ INVALID, INVALID, INVALID, INVALID,
874 /* [38] */ INVALID, INVALID, INVALID, INVALID,
875 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
876
877 /* [40] */ INVALID, INVALID, INVALID, INVALID,
878 /* [44] */ INVALID, INVALID, INVALID, INVALID,
879 /* [48] */ INVALID, INVALID, INVALID, INVALID,
880 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
881
882 /* [50] */ INVALID, TNSZ("vsqrtsd",VEX_RMrX,8), INVALID, INVALID,
883 /* [54] */ INVALID, INVALID, INVALID, INVALID,
884 /* [58] */ TNSZ("vaddsd",VEX_RMrX,8), TNSZ("vmulsd",VEX_RMrX,8), TNSZ("vcvtsd2ss",VEX_RMrX,8), INVALID,
885 /* [5C] */ TNSZ("vsubsd",VEX_RMrX,8), TNSZ("vminsd",VEX_RMrX,8), TNSZ("vdivsd",VEX_RMrX,8), TNSZ("vmaxsd",VEX_RMrX,8),
886
887 /* [60] */ INVALID, INVALID, INVALID, INVALID,
888 /* [64] */ INVALID, INVALID, INVALID, INVALID,
889 /* [68] */ INVALID, INVALID, INVALID, INVALID,
890 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
891
892 /* [70] */ TNSZ("vpshuflw",VEX_MXI,16),INVALID, INVALID, INVALID,
893 /* [74] */ INVALID, INVALID, INVALID, INVALID,
894 /* [78] */ INVALID, INVALID, INVALID, INVALID,
895 /* [7C] */ TNSZ("vhaddps",VEX_RMrX,8), TNSZ("vhsubps",VEX_RMrX,8), INVALID, INVALID,
896
897 /* [80] */ INVALID, INVALID, INVALID, INVALID,
898 /* [84] */ INVALID, INVALID, INVALID, INVALID,
899 /* [88] */ INVALID, INVALID, INVALID, INVALID,
900 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
901
902 /* [90] */ INVALID, INVALID, INVALID, INVALID,
903 /* [94] */ INVALID, INVALID, INVALID, INVALID,
904 /* [98] */ INVALID, INVALID, INVALID, INVALID,
905 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
906
907 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
908 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
909 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
910 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
911
912 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
913 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
914 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
915 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
916
917 /* [C0] */ INVALID, INVALID, TNSZ("vcmpsd",VEX_RMRX,8), INVALID,
918 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
919 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
920 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
921
922 /* [D0] */ TNSZ("vaddsubps",VEX_RMrX,8), INVALID, INVALID, INVALID,
923 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
924 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
925 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
926
927 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
928 /* [E4] */ INVALID, INVALID, TNSZ("vcvtpd2dq",VEX_MX,16),INVALID,
929 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
930 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
931
932 /* [F0] */ TNSZ("vlddqu",VEX_MX,16), INVALID, INVALID, INVALID,
933 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
934 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
935 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
936 };
937
938 /*
939 * Decode table for SIMD instructions with the repz (0xf3) prefix.
940 */
941 const instable_t dis_opSIMDrepz[256] = {
942 /* [00] */ INVALID, INVALID, INVALID, INVALID,
943 /* [04] */ INVALID, INVALID, INVALID, INVALID,
944 /* [08] */ INVALID, INVALID, INVALID, INVALID,
945 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
946
947 /* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), INVALID, INVALID,
948 /* [14] */ INVALID, INVALID, INVALID, INVALID,
949 /* [18] */ INVALID, INVALID, INVALID, INVALID,
950 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
951
952 /* [20] */ INVALID, INVALID, INVALID, INVALID,
953 /* [24] */ INVALID, INVALID, INVALID, INVALID,
954 /* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),TNSZ("movntss",XMMMS,4),
955 /* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID,
956
957 /* [30] */ INVALID, INVALID, INVALID, INVALID,
958 /* [34] */ INVALID, INVALID, INVALID, INVALID,
959 /* [38] */ INVALID, INVALID, INVALID, INVALID,
960 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
961
962 /* [40] */ INVALID, INVALID, INVALID, INVALID,
963 /* [44] */ INVALID, INVALID, INVALID, INVALID,
964 /* [48] */ INVALID, INVALID, INVALID, INVALID,
965 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
966
967 /* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4),
968 /* [54] */ INVALID, INVALID, INVALID, INVALID,
969 /* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16),
970 /* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4),
971
972 /* [60] */ INVALID, INVALID, INVALID, INVALID,
973 /* [64] */ INVALID, INVALID, INVALID, INVALID,
974 /* [68] */ INVALID, INVALID, INVALID, INVALID,
975 /* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16),
976
977 /* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID,
978 /* [74] */ INVALID, INVALID, INVALID, INVALID,
979 /* [78] */ INVALID, INVALID, INVALID, INVALID,
980 /* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16),
981
982 /* [80] */ INVALID, INVALID, INVALID, INVALID,
983 /* [84] */ INVALID, INVALID, INVALID, INVALID,
984 /* [88] */ INVALID, INVALID, INVALID, INVALID,
985 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
986
987 /* [90] */ INVALID, INVALID, INVALID, INVALID,
988 /* [94] */ INVALID, INVALID, INVALID, INVALID,
989 /* [98] */ INVALID, INVALID, INVALID, INVALID,
990 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
991
992 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
993 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
994 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
995 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
996
997 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
998 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
999 /* [B8] */ TS("popcnt",MRw), INVALID, INVALID, INVALID,
1000 /* [BC] */ INVALID, TS("lzcnt",MRw), INVALID, INVALID,
1001
1002 /* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID,
1003 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
1004 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1005 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1006
1007 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1008 /* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID,
1009 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
1010 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
1011
1012 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1013 /* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID,
1014 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1015 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1016
1017 /* [F0] */ INVALID, INVALID, INVALID, INVALID,
1018 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1019 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1020 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1021 };
1022
1023 const instable_t dis_opAVXF30F[256] = {
1024 /* [00] */ INVALID, INVALID, INVALID, INVALID,
1025 /* [04] */ INVALID, INVALID, INVALID, INVALID,
1026 /* [08] */ INVALID, INVALID, INVALID, INVALID,
1027 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
1028
1029 /* [10] */ TNSZ("vmovss",VEX_RMrX,4), TNSZ("vmovss",VEX_RRX,4), TNSZ("vmovsldup",VEX_MX,4), INVALID,
1030 /* [14] */ INVALID, INVALID, TNSZ("vmovshdup",VEX_MX,4), INVALID,
1031 /* [18] */ INVALID, INVALID, INVALID, INVALID,
1032 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
1033
1034 /* [20] */ INVALID, INVALID, INVALID, INVALID,
1035 /* [24] */ INVALID, INVALID, INVALID, INVALID,
1036 /* [28] */ INVALID, INVALID, TNSZ("vcvtsi2ss",VEX_RMrX,4),INVALID,
1037 /* [2C] */ TNSZ("vcvttss2si",VEX_MR,4),TNSZ("vcvtss2si",VEX_MR,4),INVALID, INVALID,
1038
1039 /* [30] */ INVALID, INVALID, INVALID, INVALID,
1040 /* [34] */ INVALID, INVALID, INVALID, INVALID,
1041 /* [38] */ INVALID, INVALID, INVALID, INVALID,
1042 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
1043
1044 /* [40] */ INVALID, INVALID, INVALID, INVALID,
1045 /* [44] */ INVALID, INVALID, INVALID, INVALID,
1046 /* [48] */ INVALID, INVALID, INVALID, INVALID,
1047 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
1048
1049 /* [50] */ INVALID, TNSZ("vsqrtss",VEX_RMrX,4), TNSZ("vrsqrtss",VEX_RMrX,4), TNSZ("vrcpss",VEX_RMrX,4),
1050 /* [54] */ INVALID, INVALID, INVALID, INVALID,
1051 /* [58] */ TNSZ("vaddss",VEX_RMrX,4), TNSZ("vmulss",VEX_RMrX,4), TNSZ("vcvtss2sd",VEX_RMrX,4), TNSZ("vcvttps2dq",VEX_MX,16),
1052 /* [5C] */ TNSZ("vsubss",VEX_RMrX,4), TNSZ("vminss",VEX_RMrX,4), TNSZ("vdivss",VEX_RMrX,4), TNSZ("vmaxss",VEX_RMrX,4),
1053
1054 /* [60] */ INVALID, INVALID, INVALID, INVALID,
1055 /* [64] */ INVALID, INVALID, INVALID, INVALID,
1056 /* [68] */ INVALID, INVALID, INVALID, INVALID,
1057 /* [6C] */ INVALID, INVALID, INVALID, TNSZ("vmovdqu",VEX_MX,16),
1058
1059 /* [70] */ TNSZ("vpshufhw",VEX_MXI,16),INVALID, INVALID, INVALID,
1060 /* [74] */ INVALID, INVALID, INVALID, INVALID,
1061 /* [78] */ INVALID, INVALID, INVALID, INVALID,
1062 /* [7C] */ INVALID, INVALID, TNSZ("vmovq",VEX_MX,8), TNSZ("vmovdqu",VEX_RX,16),
1063
1064 /* [80] */ INVALID, INVALID, INVALID, INVALID,
1065 /* [84] */ INVALID, INVALID, INVALID, INVALID,
1066 /* [88] */ INVALID, INVALID, INVALID, INVALID,
1067 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
1068
1069 /* [90] */ INVALID, INVALID, INVALID, INVALID,
1070 /* [94] */ INVALID, INVALID, INVALID, INVALID,
1071 /* [98] */ INVALID, INVALID, INVALID, INVALID,
1072 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
1073
1074 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
1075 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
1076 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
1077 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
1078
1079 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
1080 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
1081 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
1082 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
1083
1084 /* [C0] */ INVALID, INVALID, TNSZ("vcmpss",VEX_RMRX,4), INVALID,
1085 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
1086 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1087 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1088
1089 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1090 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
1091 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
1092 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
1093
1094 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1095 /* [E4] */ INVALID, INVALID, TNSZ("vcvtdq2pd",VEX_MX,8), INVALID,
1096 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1097 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1098
1099 /* [F0] */ INVALID, INVALID, INVALID, INVALID,
1100 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1101 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1102 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1103 };
1104
1105 /*
1106 * The following two tables are used to encode crc32 and movbe
1107 * since they share the same opcodes.
1108 */
1109 const instable_t dis_op0F38F0[2] = {
1110 /* [00] */ TNS("crc32b",CRC32),
1111 TS("movbe",MOVBE),
1112 };
1113
1114 const instable_t dis_op0F38F1[2] = {
1115 /* [00] */ TS("crc32",CRC32),
1116 TS("movbe",MOVBE),
1117 };
1118
1119
1120 const instable_t dis_op0F38[256] = {
1121 /* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16),
1122 /* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16),
1123 /* [08] */ TNSZ("psignb",XMM_66o,16),TNSZ("psignw",XMM_66o,16),TNSZ("psignd",XMM_66o,16),TNSZ("pmulhrsw",XMM_66o,16),
1124 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
1125
1126 /* [10] */ TNSZ("pblendvb",XMM_66r,16),INVALID, INVALID, INVALID,
1127 /* [14] */ TNSZ("blendvps",XMM_66r,16),TNSZ("blendvpd",XMM_66r,16),INVALID, TNSZ("ptest",XMM_66r,16),
1128 /* [18] */ INVALID, INVALID, INVALID, INVALID,
1129 /* [1C] */ TNSZ("pabsb",XMM_66o,16),TNSZ("pabsw",XMM_66o,16),TNSZ("pabsd",XMM_66o,16),INVALID,
1130
1131 /* [20] */ TNSZ("pmovsxbw",XMM_66r,16),TNSZ("pmovsxbd",XMM_66r,16),TNSZ("pmovsxbq",XMM_66r,16),TNSZ("pmovsxwd",XMM_66r,16),
1132 /* [24] */ TNSZ("pmovsxwq",XMM_66r,16),TNSZ("pmovsxdq",XMM_66r,16),INVALID, INVALID,
1133 /* [28] */ TNSZ("pmuldq",XMM_66r,16),TNSZ("pcmpeqq",XMM_66r,16),TNSZ("movntdqa",XMMM_66r,16),TNSZ("packusdw",XMM_66r,16),
1134 /* [2C] */ INVALID, INVALID, INVALID, INVALID,
1135
1136 /* [30] */ TNSZ("pmovzxbw",XMM_66r,16),TNSZ("pmovzxbd",XMM_66r,16),TNSZ("pmovzxbq",XMM_66r,16),TNSZ("pmovzxwd",XMM_66r,16),
1137 /* [34] */ TNSZ("pmovzxwq",XMM_66r,16),TNSZ("pmovzxdq",XMM_66r,16),INVALID, TNSZ("pcmpgtq",XMM_66r,16),
1138 /* [38] */ TNSZ("pminsb",XMM_66r,16),TNSZ("pminsd",XMM_66r,16),TNSZ("pminuw",XMM_66r,16),TNSZ("pminud",XMM_66r,16),
1139 /* [3C] */ TNSZ("pmaxsb",XMM_66r,16),TNSZ("pmaxsd",XMM_66r,16),TNSZ("pmaxuw",XMM_66r,16),TNSZ("pmaxud",XMM_66r,16),
1140
1141 /* [40] */ TNSZ("pmulld",XMM_66r,16),TNSZ("phminposuw",XMM_66r,16),INVALID, INVALID,
1142 /* [44] */ INVALID, INVALID, INVALID, INVALID,
1143 /* [48] */ INVALID, INVALID, INVALID, INVALID,
1144 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
1145
1146 /* [50] */ INVALID, INVALID, INVALID, INVALID,
1147 /* [54] */ INVALID, INVALID, INVALID, INVALID,
1148 /* [58] */ INVALID, INVALID, INVALID, INVALID,
1149 /* [5C] */ INVALID, INVALID, INVALID, INVALID,
1150
1151 /* [60] */ INVALID, INVALID, INVALID, INVALID,
1152 /* [64] */ INVALID, INVALID, INVALID, INVALID,
1153 /* [68] */ INVALID, INVALID, INVALID, INVALID,
1154 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
1155
1156 /* [70] */ INVALID, INVALID, INVALID, INVALID,
1157 /* [74] */ INVALID, INVALID, INVALID, INVALID,
1158 /* [78] */ INVALID, INVALID, INVALID, INVALID,
1159 /* [7C] */ INVALID, INVALID, INVALID, INVALID,
1160
1161 /* [80] */ INVALID, INVALID, INVALID, INVALID,
1162 /* [84] */ INVALID, INVALID, INVALID, INVALID,
1163 /* [88] */ INVALID, INVALID, INVALID, INVALID,
1164 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
1165
1166 /* [90] */ INVALID, INVALID, INVALID, INVALID,
1167 /* [94] */ INVALID, INVALID, INVALID, INVALID,
1168 /* [98] */ INVALID, INVALID, INVALID, INVALID,
1169 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
1170
1171 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
1172 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
1173 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
1174 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
1175
1176 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
1177 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
1178 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
1179 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
1180
1181 /* [C0] */ INVALID, INVALID, INVALID, INVALID,
1182 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
1183 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1184 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1185
1186 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1187 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
1188 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
1189 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
1190
1191 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1192 /* [E4] */ INVALID, INVALID, INVALID, INVALID,
1193 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1194 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1195
1196 /* [F0] */ TNS("crc32b",CRC32), TS("crc32",CRC32), INVALID, INVALID,
1197 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1198 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1199 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1200 };
1201
1202 const instable_t dis_opAVX660F38[256] = {
1203 /* [00] */ TNSZ("vpshufb",VEX_RMrX,16),TNSZ("vphaddw",VEX_RMrX,16),TNSZ("vphaddd",VEX_RMrX,16),TNSZ("vphaddsw",VEX_RMrX,16),
1204 /* [04] */ TNSZ("vpmaddubsw",VEX_RMrX,16),TNSZ("vphsubw",VEX_RMrX,16), TNSZ("vphsubd",VEX_RMrX,16),TNSZ("vphsubsw",VEX_RMrX,16),
1205 /* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16),
1206 /* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16),
1207
1208 /* [10] */ INVALID, INVALID, INVALID, INVALID,
1209 /* [14] */ INVALID, INVALID, INVALID, TNSZ("vptest",VEX_RRI,16),
1210 /* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID,
1211 /* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID,
1212
1213 /* [20] */ TNSZ("vpmovsxbw",VEX_MX,16),TNSZ("vpmovsxbd",VEX_MX,16),TNSZ("vpmovsxbq",VEX_MX,16),TNSZ("vpmovsxwd",VEX_MX,16),
1214 /* [24] */ TNSZ("vpmovsxwq",VEX_MX,16),TNSZ("vpmovsxdq",VEX_MX,16),INVALID, INVALID,
1215 /* [28] */ TNSZ("vpmuldq",VEX_RMrX,16),TNSZ("vpcmpeqq",VEX_RMrX,16),TNSZ("vmovntdqa",VEX_MX,16),TNSZ("vpackusdw",VEX_RMrX,16),
1216 /* [2C] */ TNSZ("vmaskmovps",VEX_RMrX,8),TNSZ("vmaskmovpd",VEX_RMrX,16),TNSZ("vmaskmovps",VEX_RRM,8),TNSZ("vmaskmovpd",VEX_RRM,16),
1217
1218 /* [30] */ TNSZ("vpmovzxbw",VEX_MX,16),TNSZ("vpmovzxbd",VEX_MX,16),TNSZ("vpmovzxbq",VEX_MX,16),TNSZ("vpmovzxwd",VEX_MX,16),
1219 /* [34] */ TNSZ("vpmovzxwq",VEX_MX,16),TNSZ("vpmovzxdq",VEX_MX,16),TNSZ("vpermd",VEX_RMrX,16),TNSZ("vpcmpgtq",VEX_RMrX,16),
1220 /* [38] */ TNSZ("vpminsb",VEX_RMrX,16),TNSZ("vpminsd",VEX_RMrX,16),TNSZ("vpminuw",VEX_RMrX,16),TNSZ("vpminud",VEX_RMrX,16),
1221 /* [3C] */ TNSZ("vpmaxsb",VEX_RMrX,16),TNSZ("vpmaxsd",VEX_RMrX,16),TNSZ("vpmaxuw",VEX_RMrX,16),TNSZ("vpmaxud",VEX_RMrX,16),
1222
1223 /* [40] */ TNSZ("vpmulld",VEX_RMrX,16),TNSZ("vphminposuw",VEX_MX,16),INVALID, INVALID,
1224 /* [44] */ INVALID, INVALID, INVALID, INVALID,
1225 /* [48] */ INVALID, INVALID, INVALID, INVALID,
1226 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
1227
1228 /* [50] */ INVALID, INVALID, INVALID, INVALID,
1229 /* [54] */ INVALID, INVALID, INVALID, INVALID,
1230 /* [58] */ TNSZ("vpbroadcastd",VEX_MX,16),TNSZ("vpbroadcastq",VEX_MX,16),TNSZ("vbroadcasti128",VEX_MX,16),INVALID,
1231 /* [5C] */ INVALID, INVALID, INVALID, INVALID,
1232
1233 /* [60] */ INVALID, INVALID, INVALID, INVALID,
1234 /* [64] */ INVALID, INVALID, INVALID, INVALID,
1235 /* [68] */ INVALID, INVALID, INVALID, INVALID,
1236 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
1237
1238 /* [70] */ INVALID, INVALID, INVALID, INVALID,
1239 /* [74] */ INVALID, INVALID, INVALID, INVALID,
1240 /* [78] */ TNSZ("vpbroadcastb",VEX_MX,16),TNSZ("vpbroadcastw",VEX_MX,16),INVALID, INVALID,
1241 /* [7C] */ INVALID, INVALID, INVALID, INVALID,
1242
1243 /* [80] */ INVALID, INVALID, INVALID, INVALID,
1244 /* [84] */ INVALID, INVALID, INVALID, INVALID,
1245 /* [88] */ INVALID, INVALID, INVALID, INVALID,
1246 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
1247
1248 /* [90] */ INVALID, INVALID, INVALID, INVALID,
1249 /* [94] */ INVALID, INVALID, INVALID, INVALID,
1250 /* [98] */ INVALID, INVALID, INVALID, INVALID,
1251 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
1252
1253 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
1254 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
1255 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
1256 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
1257
1258 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
1259 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
1260 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
1261 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
1262
1263 /* [C0] */ INVALID, INVALID, INVALID, INVALID,
1264 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
1265 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1266 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1267
1268 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1269 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
1270 /* [D8] */ INVALID, INVALID, INVALID, TNSZ("vaesimc",VEX_MX,16),
1271 /* [DC] */ TNSZ("vaesenc",VEX_RMrX,16),TNSZ("vaesenclast",VEX_RMrX,16),TNSZ("vaesdec",VEX_RMrX,16),TNSZ("vaesdeclast",VEX_RMrX,16),
1272
1273 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1274 /* [E4] */ INVALID, INVALID, INVALID, INVALID,
1275 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1276 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1277 /* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID,
1278 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1279 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1280 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1281 };
1282
1283 const instable_t dis_op0F3A[256] = {
1284 /* [00] */ INVALID, INVALID, INVALID, INVALID,
1285 /* [04] */ INVALID, INVALID, INVALID, INVALID,
1286 /* [08] */ TNSZ("roundps",XMMP_66r,16),TNSZ("roundpd",XMMP_66r,16),TNSZ("roundss",XMMP_66r,16),TNSZ("roundsd",XMMP_66r,16),
1287 /* [0C] */ TNSZ("blendps",XMMP_66r,16),TNSZ("blendpd",XMMP_66r,16),TNSZ("pblendw",XMMP_66r,16),TNSZ("palignr",XMMP_66o,16),
1288
1289 /* [10] */ INVALID, INVALID, INVALID, INVALID,
1290 /* [14] */ TNSZ("pextrb",XMM3PM_66r,8),TNSZ("pextrw",XMM3PM_66r,16),TSZ("pextr",XMM3PM_66r,16),TNSZ("extractps",XMM3PM_66r,16),
1291 /* [18] */ INVALID, INVALID, INVALID, INVALID,
1292 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
1293
1294 /* [20] */ TNSZ("pinsrb",XMMPRM_66r,8),TNSZ("insertps",XMMP_66r,16),TSZ("pinsr",XMMPRM_66r,16),INVALID,
1295 /* [24] */ INVALID, INVALID, INVALID, INVALID,
1296 /* [28] */ INVALID, INVALID, INVALID, INVALID,
1297 /* [2C] */ INVALID, INVALID, INVALID, INVALID,
1298
1299 /* [30] */ INVALID, INVALID, INVALID, INVALID,
1300 /* [34] */ INVALID, INVALID, INVALID, INVALID,
1301 /* [38] */ INVALID, INVALID, INVALID, INVALID,
1302 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
1303
1304 /* [40] */ TNSZ("dpps",XMMP_66r,16),TNSZ("dppd",XMMP_66r,16),TNSZ("mpsadbw",XMMP_66r,16),INVALID,
1305 /* [44] */ INVALID, INVALID, INVALID, INVALID,
1306 /* [48] */ INVALID, INVALID, INVALID, INVALID,
1307 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
1308
1309 /* [50] */ INVALID, INVALID, INVALID, INVALID,
1310 /* [54] */ INVALID, INVALID, INVALID, INVALID,
1311 /* [58] */ INVALID, INVALID, INVALID, INVALID,
1312 /* [5C] */ INVALID, INVALID, INVALID, INVALID,
1313
1314 /* [60] */ TNSZ("pcmpestrm",XMMP_66r,16),TNSZ("pcmpestri",XMMP_66r,16),TNSZ("pcmpistrm",XMMP_66r,16),TNSZ("pcmpistri",XMMP_66r,16),
1315 /* [64] */ INVALID, INVALID, INVALID, INVALID,
1316 /* [68] */ INVALID, INVALID, INVALID, INVALID,
1317 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
1318
1319 /* [70] */ INVALID, INVALID, INVALID, INVALID,
1320 /* [74] */ INVALID, INVALID, INVALID, INVALID,
1321 /* [78] */ INVALID, INVALID, INVALID, INVALID,
1322 /* [7C] */ INVALID, INVALID, INVALID, INVALID,
1323
1324 /* [80] */ INVALID, INVALID, INVALID, INVALID,
1325 /* [84] */ INVALID, INVALID, INVALID, INVALID,
1326 /* [88] */ INVALID, INVALID, INVALID, INVALID,
1327 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
1328
1329 /* [90] */ INVALID, INVALID, INVALID, INVALID,
1330 /* [94] */ INVALID, INVALID, INVALID, INVALID,
1331 /* [98] */ INVALID, INVALID, INVALID, INVALID,
1332 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
1333
1334 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
1335 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
1336 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
1337 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
1338
1339 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
1340 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
1341 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
1342 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
1343
1344 /* [C0] */ INVALID, INVALID, INVALID, INVALID,
1345 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
1346 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1347 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1348
1349 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1350 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
1351 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
1352 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
1353
1354 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1355 /* [E4] */ INVALID, INVALID, INVALID, INVALID,
1356 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1357 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1358
1359 /* [F0] */ INVALID, INVALID, INVALID, INVALID,
1360 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1361 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1362 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1363 };
1364
1365 const instable_t dis_opAVX660F3A[256] = {
1366 /* [00] */ TNSZ("vpermq",VEX_MXI,16),TNSZ("vpermpd",VEX_MXI,16),TNSZ("vpblendd",VEX_RMRX,16),INVALID,
1367 /* [04] */ TNSZ("vpermilps",VEX_MXI,8),TNSZ("vpermilpd",VEX_MXI,16),TNSZ("vperm2f128",VEX_RMRX,16),INVALID,
1368 /* [08] */ TNSZ("vroundps",VEX_MXI,16),TNSZ("vroundpd",VEX_MXI,16),TNSZ("vroundss",VEX_RMRX,16),TNSZ("vroundsd",VEX_RMRX,16),
1369 /* [0C] */ TNSZ("vblendps",VEX_RMRX,16),TNSZ("vblendpd",VEX_RMRX,16),TNSZ("vpblendw",VEX_RMRX,16),TNSZ("vpalignr",VEX_RMRX,16),
1370
1371 /* [10] */ INVALID, INVALID, INVALID, INVALID,
1372 /* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16),
1373 /* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID,
1374 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
1375
1376 /* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID,
1377 /* [24] */ INVALID, INVALID, INVALID, INVALID,
1378 /* [28] */ INVALID, INVALID, INVALID, INVALID,
1379 /* [2C] */ INVALID, INVALID, INVALID, INVALID,
1380
1381 /* [30] */ INVALID, INVALID, INVALID, INVALID,
1382 /* [34] */ INVALID, INVALID, INVALID, INVALID,
1383 /* [38] */ TNSZ("vinserti128",VEX_RMRX,16),TNSZ("vextracti128",VEX_RIM,16),INVALID, INVALID,
1384 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
1385
1386 /* [40] */ TNSZ("vdpps",VEX_RMRX,16),TNSZ("vdppd",VEX_RMRX,16),TNSZ("vmpsadbw",VEX_RMRX,16),INVALID,
1387 /* [44] */ TNSZ("vpclmulqdq",VEX_RMRX,16),INVALID, INVALID, INVALID,
1388 /* [48] */ INVALID, INVALID, TNSZ("vblendvps",VEX_RMRX,8), TNSZ("vblendvpd",VEX_RMRX,16),
1389 /* [4C] */ TNSZ("vpblendvb",VEX_RMRX,16),INVALID, INVALID, INVALID,
1390
1391 /* [50] */ INVALID, INVALID, INVALID, INVALID,
1392 /* [54] */ INVALID, INVALID, INVALID, INVALID,
1393 /* [58] */ INVALID, INVALID, INVALID, INVALID,
1394 /* [5C] */ INVALID, INVALID, INVALID, INVALID,
1395
1396 /* [60] */ TNSZ("vpcmpestrm",VEX_MXI,16),TNSZ("vpcmpestri",VEX_MXI,16),TNSZ("vpcmpistrm",VEX_MXI,16),TNSZ("vpcmpistri",VEX_MXI,16),
1397 /* [64] */ INVALID, INVALID, INVALID, INVALID,
1398 /* [68] */ INVALID, INVALID, INVALID, INVALID,
1399 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
1400
1401 /* [70] */ INVALID, INVALID, INVALID, INVALID,
1402 /* [74] */ INVALID, INVALID, INVALID, INVALID,
1403 /* [78] */ INVALID, INVALID, INVALID, INVALID,
1404 /* [7C] */ INVALID, INVALID, INVALID, INVALID,
1405
1406 /* [80] */ INVALID, INVALID, INVALID, INVALID,
1407 /* [84] */ INVALID, INVALID, INVALID, INVALID,
1408 /* [88] */ INVALID, INVALID, INVALID, INVALID,
1409 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
1410
1411 /* [90] */ INVALID, INVALID, INVALID, INVALID,
1412 /* [94] */ INVALID, INVALID, INVALID, INVALID,
1413 /* [98] */ INVALID, INVALID, INVALID, INVALID,
1414 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
1415
1416 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
1417 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
1418 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
1419 /* [AC] */ INVALID, INVALID, INVALID, INVALID,
1420
1421 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
1422 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
1423 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
1424 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
1425
1426 /* [C0] */ INVALID, INVALID, INVALID, INVALID,
1427 /* [C4] */ INVALID, INVALID, INVALID, INVALID,
1428 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1429 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1430
1431 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1432 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
1433 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
1434 /* [DC] */ INVALID, INVALID, INVALID, TNSZ("vaeskeygenassist",VEX_MXI,16),
1435
1436 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1437 /* [E4] */ INVALID, INVALID, INVALID, INVALID,
1438 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1439 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1440
1441 /* [F0] */ INVALID, INVALID, INVALID, INVALID,
1442 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1443 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1444 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1445 };
1446
1447 /*
1448 * Decode table for 0x0F opcodes
1449 */
1450
1451 const instable_t dis_op0F[16][16] = {
1452 {
1453 /* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR),
1454 /* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM),
1455 /* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM),
1456 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
1457 }, {
1458 /* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8),
1459 /* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8),
1460 /* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID,
1461 /* APPLE NOTE: Need to handle multi-byte NOP */
1462 /* [1C] */ INVALID, INVALID, INVALID, TS("nop",Mw),
1463 }, {
1464 /* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG),
1465 /* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID,
1466 /* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16),
1467 /* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4),
1468 }, {
1469 /* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM),
1470 /* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID,
1471 /* [38] */ INVALID, INVALID, INVALID, INVALID,
1472 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
1473 }, {
1474 /* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR),
1475 /* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR),
1476 /* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR),
1477 /* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR),
1478 }, {
1479 /* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16),
1480 /* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16),
1481 /* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16),
1482 /* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16),
1483 }, {
1484 /* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8),
1485 /* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8),
1486 /* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8),
1487 /* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8),
1488 }, {
1489 /* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR),
1490 /* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM),
1491 /* [78] */ TNS("INVALID",XMMO), TNS("INVALID",XMMO), INVALID, INVALID,
1492 /* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8),
1493 }, {
1494 /* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D),
1495 /* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D),
1496 /* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D),
1497 /* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D),
1498 }, {
1499 /* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb),
1500 /* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb),
1501 /* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb),
1502 /* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb),
1503 }, {
1504 /* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw),
1505 /* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID,
1506 /* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw),
1507 /* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw),
1508 }, {
1509 /* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw),
1510 /* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ),
1511 /* [B8] */ TNS("INVALID",MRw), INVALID, IND(dis_op0FBA), TS("btc",RMw),
1512 /* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ),
1513 }, {
1514 /* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM),
1515 /* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7),
1516 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1517 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1518 }, {
1519 /* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8),
1520 /* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3),
1521 /* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8),
1522 /* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8),
1523 }, {
1524 /* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8),
1525 /* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8),
1526 /* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8),
1527 /* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8),
1528 }, {
1529 /* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8),
1530 /* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8),
1531 /* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8),
1532 /* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID,
1533 } };
1534
1535 const instable_t dis_opAVX0F[16][16] = {
1536 {
1537 /* [00] */ INVALID, INVALID, INVALID, INVALID,
1538 /* [04] */ INVALID, INVALID, INVALID, INVALID,
1539 /* [08] */ INVALID, INVALID, INVALID, INVALID,
1540 /* [0C] */ INVALID, INVALID, INVALID, INVALID,
1541 }, {
1542 /* [10] */ TNSZ("vmovups",VEX_MX,16), TNSZ("vmovups",VEX_RM,16),TNSZ("vmovlps",VEX_RMrX,8), TNSZ("vmovlps",VEX_RM,8),
1543 /* [14] */ TNSZ("vunpcklps",VEX_RMrX,16),TNSZ("vunpckhps",VEX_RMrX,16),TNSZ("vmovhps",VEX_RMrX,8),TNSZ("vmovhps",VEX_RM,8),
1544 /* [18] */ INVALID, INVALID, INVALID, INVALID,
1545 /* [1C] */ INVALID, INVALID, INVALID, INVALID,
1546 }, {
1547 /* [20] */ INVALID, INVALID, INVALID, INVALID,
1548 /* [24] */ INVALID, INVALID, INVALID, INVALID,
1549 /* [28] */ TNSZ("vmovaps",VEX_MX,16), TNSZ("vmovaps",VEX_RX,16),INVALID, TNSZ("vmovntps",VEX_RM,16),
1550 /* [2C] */ INVALID, INVALID, TNSZ("vucomiss",VEX_MX,4),TNSZ("vcomiss",VEX_MX,4),
1551 }, {
1552 /* [30] */ INVALID, INVALID, INVALID, INVALID,
1553 /* [34] */ INVALID, INVALID, INVALID, INVALID,
1554 /* [38] */ INVALID, INVALID, INVALID, INVALID,
1555 /* [3C] */ INVALID, INVALID, INVALID, INVALID,
1556 }, {
1557 /* [40] */ INVALID, INVALID, INVALID, INVALID,
1558 /* [44] */ INVALID, INVALID, INVALID, INVALID,
1559 /* [48] */ INVALID, INVALID, INVALID, INVALID,
1560 /* [4C] */ INVALID, INVALID, INVALID, INVALID,
1561 }, {
1562 /* [50] */ TNS("vmovmskps",VEX_MR), TNSZ("vsqrtps",VEX_MX,16), TNSZ("vrsqrtps",VEX_MX,16),TNSZ("vrcpps",VEX_MX,16),
1563 /* [54] */ TNSZ("vandps",VEX_RMrX,16), TNSZ("vandnps",VEX_RMrX,16), TNSZ("vorps",VEX_RMrX,16), TNSZ("vxorps",VEX_RMrX,16),
1564 /* [58] */ TNSZ("vaddps",VEX_RMrX,16), TNSZ("vmulps",VEX_RMrX,16), TNSZ("vcvtps2pd",VEX_MX,8),TNSZ("vcvtdq2ps",VEX_MX,16),
1565 /* [5C] */ TNSZ("vsubps",VEX_RMrX,16), TNSZ("vminps",VEX_RMrX,16), TNSZ("vdivps",VEX_RMrX,16), TNSZ("vmaxps",VEX_RMrX,16),
1566 }, {
1567 /* [60] */ INVALID, INVALID, INVALID, INVALID,
1568 /* [64] */ INVALID, INVALID, INVALID, INVALID,
1569 /* [68] */ INVALID, INVALID, INVALID, INVALID,
1570 /* [6C] */ INVALID, INVALID, INVALID, INVALID,
1571 }, {
1572 /* [70] */ INVALID, INVALID, INVALID, INVALID,
1573 /* [74] */ INVALID, INVALID, INVALID, TNS("vzeroupper", VEX_NONE),
1574 /* [78] */ INVALID, INVALID, INVALID, INVALID,
1575 /* [7C] */ INVALID, INVALID, INVALID, INVALID,
1576 }, {
1577 /* [80] */ INVALID, INVALID, INVALID, INVALID,
1578 /* [84] */ INVALID, INVALID, INVALID, INVALID,
1579 /* [88] */ INVALID, INVALID, INVALID, INVALID,
1580 /* [8C] */ INVALID, INVALID, INVALID, INVALID,
1581 }, {
1582 /* [90] */ INVALID, INVALID, INVALID, INVALID,
1583 /* [94] */ INVALID, INVALID, INVALID, INVALID,
1584 /* [98] */ INVALID, INVALID, INVALID, INVALID,
1585 /* [9C] */ INVALID, INVALID, INVALID, INVALID,
1586 }, {
1587 /* [A0] */ INVALID, INVALID, INVALID, INVALID,
1588 /* [A4] */ INVALID, INVALID, INVALID, INVALID,
1589 /* [A8] */ INVALID, INVALID, INVALID, INVALID,
1590 /* [AC] */ INVALID, INVALID, TNSZ("vldmxcsr",VEX_MO,2), INVALID,
1591 }, {
1592 /* [B0] */ INVALID, INVALID, INVALID, INVALID,
1593 /* [B4] */ INVALID, INVALID, INVALID, INVALID,
1594 /* [B8] */ INVALID, INVALID, INVALID, INVALID,
1595 /* [BC] */ INVALID, INVALID, INVALID, INVALID,
1596 }, {
1597 /* [C0] */ INVALID, INVALID, TNSZ("vcmpps",VEX_RMRX,16),INVALID,
1598 /* [C4] */ INVALID, INVALID, TNSZ("vshufps",VEX_RMRX,16),INVALID,
1599 /* [C8] */ INVALID, INVALID, INVALID, INVALID,
1600 /* [CC] */ INVALID, INVALID, INVALID, INVALID,
1601 }, {
1602 /* [D0] */ INVALID, INVALID, INVALID, INVALID,
1603 /* [D4] */ INVALID, INVALID, INVALID, INVALID,
1604 /* [D8] */ INVALID, INVALID, INVALID, INVALID,
1605 /* [DC] */ INVALID, INVALID, INVALID, INVALID,
1606 }, {
1607 /* [E0] */ INVALID, INVALID, INVALID, INVALID,
1608 /* [E4] */ INVALID, INVALID, INVALID, INVALID,
1609 /* [E8] */ INVALID, INVALID, INVALID, INVALID,
1610 /* [EC] */ INVALID, INVALID, INVALID, INVALID,
1611 }, {
1612 /* [F0] */ INVALID, INVALID, INVALID, INVALID,
1613 /* [F4] */ INVALID, INVALID, INVALID, INVALID,
1614 /* [F8] */ INVALID, INVALID, INVALID, INVALID,
1615 /* [FC] */ INVALID, INVALID, INVALID, INVALID,
1616 } };
1617
1618 /*
1619 * Decode table for 0x80 opcodes
1620 */
1621
1622 const instable_t dis_op80[8] = {
1623
1624 /* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw),
1625 /* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw),
1626 };
1627
1628
1629 /*
1630 * Decode table for 0x81 opcodes.
1631 */
1632
1633 const instable_t dis_op81[8] = {
1634
1635 /* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw),
1636 /* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw),
1637 };
1638
1639
1640 /*
1641 * Decode table for 0x82 opcodes.
1642 */
1643
1644 const instable_t dis_op82[8] = {
1645
1646 /* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw),
1647 /* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw),
1648 };
1649 /*
1650 * Decode table for 0x83 opcodes.
1651 */
1652
1653 const instable_t dis_op83[8] = {
1654
1655 /* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw),
1656 /* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw),
1657 };
1658
1659 /*
1660 * Decode table for 0xC0 opcodes.
1661 */
1662
1663 const instable_t dis_opC0[8] = {
1664
1665 /* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI),
1666 /* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI),
1667 };
1668
1669 /*
1670 * Decode table for 0xD0 opcodes.
1671 */
1672
1673 const instable_t dis_opD0[8] = {
1674
1675 /* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv),
1676 /* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv),
1677 };
1678
1679 /*
1680 * Decode table for 0xC1 opcodes.
1681 * 186 instruction set
1682 */
1683
1684 const instable_t dis_opC1[8] = {
1685
1686 /* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI),
1687 /* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI),
1688 };
1689
1690 /*
1691 * Decode table for 0xD1 opcodes.
1692 */
1693
1694 const instable_t dis_opD1[8] = {
1695
1696 /* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv),
1697 /* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv),
1698 };
1699
1700
1701 /*
1702 * Decode table for 0xD2 opcodes.
1703 */
1704
1705 const instable_t dis_opD2[8] = {
1706
1707 /* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv),
1708 /* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv),
1709 };
1710 /*
1711 * Decode table for 0xD3 opcodes.
1712 */
1713
1714 const instable_t dis_opD3[8] = {
1715
1716 /* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv),
1717 /* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv),
1718 };
1719
1720
1721 /*
1722 * Decode table for 0xF6 opcodes.
1723 */
1724
1725 const instable_t dis_opF6[8] = {
1726
1727 /* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw),
1728 /* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA),
1729 };
1730
1731
1732 /*
1733 * Decode table for 0xF7 opcodes.
1734 */
1735
1736 const instable_t dis_opF7[8] = {
1737
1738 /* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw),
1739 /* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA),
1740 };
1741
1742
1743 /*
1744 * Decode table for 0xFE opcodes.
1745 */
1746
1747 const instable_t dis_opFE[8] = {
1748
1749 /* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID,
1750 /* [4] */ INVALID, INVALID, INVALID, INVALID,
1751 };
1752 /*
1753 * Decode table for 0xFF opcodes.
1754 */
1755
1756 const instable_t dis_opFF[8] = {
1757
1758 /* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM),
1759 /* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID,
1760 };
1761
1762 /* for 287 instructions, which are a mess to decode */
1763
1764 const instable_t dis_opFP1n2[8][8] = {
1765 {
1766 /* bit pattern: 1101 1xxx MODxx xR/M */
1767 /* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M),
1768 /* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M),
1769 }, {
1770 /* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M),
1771 /* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2),
1772 }, {
1773 /* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M),
1774 /* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M),
1775 }, {
1776 /* [3,0] */ TNS("fildl",M), INVALID, TNS("fistl",M), TNS("fistpl",M),
1777 /* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10),
1778 }, {
1779 /* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8),
1780 /* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8),
1781 }, {
1782 /* [5,0] */ TNSZ("fldl",M,8), INVALID, TNSZ("fstl",M,8), TNSZ("fstpl",M,8),
1783 /* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2),
1784 }, {
1785 /* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2),
1786 /* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2),
1787 }, {
1788 /* [7,0] */ TNSZ("fild",M,2), INVALID, TNSZ("fist",M,2), TNSZ("fistp",M,2),
1789 /* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8),
1790 } };
1791
1792 const instable_t dis_opFP3[8][8] = {
1793 {
1794 /* bit pattern: 1101 1xxx 11xx xREG */
1795 /* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F),
1796 /* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF),
1797 }, {
1798 /* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F),
1799 /* [1,4] */ INVALID, INVALID, INVALID, INVALID,
1800 }, {
1801 /* [2,0] */ INVALID, INVALID, INVALID, INVALID,
1802 /* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID,
1803 }, {
1804 /* [3,0] */ INVALID, INVALID, INVALID, INVALID,
1805 /* [3,4] */ INVALID, INVALID, INVALID, INVALID,
1806 }, {
1807 /* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F),
1808 /* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF),
1809 }, {
1810 /* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F),
1811 /* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID,
1812 }, {
1813 /* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM),
1814 /* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF),
1815 }, {
1816 /* [7,0] */ TNS("ffreep",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F),
1817 /* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID,
1818 } };
1819
1820 const instable_t dis_opFP4[4][8] = {
1821 {
1822 /* bit pattern: 1101 1001 111x xxxx */
1823 /* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID,
1824 /* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID,
1825 }, {
1826 /* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM),
1827 /* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID,
1828 }, {
1829 /* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM),
1830 /* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM),
1831 }, {
1832 /* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM),
1833 /* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM),
1834 } };
1835
1836 const instable_t dis_opFP5[8] = {
1837 /* bit pattern: 1101 1011 111x xxxx */
1838 /* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM),
1839 /* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID,
1840 };
1841
1842 const instable_t dis_opFP6[8] = {
1843 /* bit pattern: 1101 1011 11yy yxxx */
1844 /* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF),
1845 /* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID,
1846 };
1847
1848 const instable_t dis_opFP7[8] = {
1849 /* bit pattern: 1101 1010 11yy yxxx */
1850 /* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF),
1851 /* [04] */ INVALID, INVALID, INVALID, INVALID,
1852 };
1853
1854 /*
1855 * Main decode table for the op codes. The first two nibbles
1856 * will be used as an index into the table. If there is a
1857 * a need to further decode an instruction, the array to be
1858 * referenced is indicated with the other two entries being
1859 * empty.
1860 */
1861
1862 const instable_t dis_distable[16][16] = {
1863 {
1864 /* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw),
1865 /* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG),
1866 /* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw),
1867 /* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(dis_op0F),
1868 }, {
1869 /* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw),
1870 /* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG),
1871 /* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw),
1872 /* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG),
1873 }, {
1874 /* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw),
1875 /* [2,4] */ TNS("andb",IA), TS("and",IA), TNS("%es:",OVERRIDE), TNSx("daa",NORM),
1876 /* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw),
1877 /* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM),
1878 }, {
1879 /* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw),
1880 /* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNS("%ss:",OVERRIDE), TNSx("aaa",NORM),
1881 /* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw),
1882 /* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNS("%ds:",OVERRIDE), TNSx("aas",NORM),
1883 }, {
1884 /* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
1885 /* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
1886 /* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R),
1887 /* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R),
1888 }, {
1889 /* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R),
1890 /* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R),
1891 /* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R),
1892 /* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R),
1893 }, {
1894 /* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw),
1895 /* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM),
1896 /* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL),
1897 /* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4),
1898 }, {
1899 /* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD),
1900 /* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD),
1901 /* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD),
1902 /* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD),
1903 }, {
1904 /* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83),
1905 /* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw),
1906 /* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw),
1907 /* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M),
1908 }, {
1909 /* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA),
1910 /* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA),
1911 /* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM),
1912 /* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNSx("sahf",NORM), TNSx("lahf",NORM),
1913 }, {
1914 /* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO),
1915 /* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD),
1916 /* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD),
1917 /* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD),
1918 }, {
1919 /* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR),
1920 /* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR),
1921 /* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR),
1922 /* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR),
1923 }, {
1924 /* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM),
1925 /* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw),
1926 /* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM),
1927 /* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM),
1928 }, {
1929 /* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3),
1930 /* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1),
1931
1932 /* 287 instructions. Note that although the indirect field */
1933 /* indicates opFP1n2 for further decoding, this is not necessarily */
1934 /* the case since the opFP arrays are not partitioned according to key1 */
1935 /* and key2. opFP1n2 is given only to indicate that we haven't */
1936 /* finished decoding the instruction. */
1937 /* [D,8] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2),
1938 /* [D,C] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2),
1939 }, {
1940 /* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD),
1941 /* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P),
1942 /* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD),
1943 /* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V),
1944 }, {
1945 /* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX),
1946 /* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7),
1947 /* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM),
1948 /* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF),
1949 } };
1950
1951 /* END CSTYLED */
1952
1953 /*
1954 * common functions to decode and disassemble an x86 or amd64 instruction
1955 */
1956
1957 /*
1958 * These are the individual fields of a REX prefix. Note that a REX
1959 * prefix with none of these set is still needed to:
1960 * - use the MOVSXD (sign extend 32 to 64 bits) instruction
1961 * - access the %sil, %dil, %bpl, %spl registers
1962 */
1963 #define REX_W 0x08 /* 64 bit operand size when set */
1964 #define REX_R 0x04 /* high order bit extension of ModRM reg field */
1965 #define REX_X 0x02 /* high order bit extension of SIB index field */
1966 #define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */
1967
1968 /*
1969 * These are the individual fields of a VEX prefix.
1970 */
1971 #define VEX_R 0x08 /* REX.R in 1's complement form */
1972 #define VEX_X 0x04 /* REX.X in 1's complement form */
1973 #define VEX_B 0x02 /* REX.B in 1's complement form */
1974 /* Vector Length, 0: scalar or 128-bit vector, 1: 256-bit vector */
1975 #define VEX_L 0x04
1976 #define VEX_W 0x08 /* opcode specific, use like REX.W */
1977 #define VEX_m 0x1F /* VEX m-mmmm field */
1978 #define VEX_v 0x78 /* VEX register specifier */
1979 #define VEX_p 0x03 /* VEX pp field, opcode extension */
1980
1981 /* VEX m-mmmm field, only used by three bytes prefix */
1982 #define VEX_m_0F 0x01 /* implied 0F leading opcode byte */
1983 #define VEX_m_0F38 0x02 /* implied 0F 38 leading opcode byte */
1984 #define VEX_m_0F3A 0x03 /* implied 0F 3A leading opcode byte */
1985
1986 /* VEX pp field, providing equivalent functionality of a SIMD prefix */
1987 #define VEX_p_66 0x01
1988 #define VEX_p_F3 0x02
1989 #define VEX_p_F2 0x03
1990
1991 /*
1992 * Even in 64 bit mode, usually only 4 byte immediate operands are supported.
1993 */
1994 static int isize[] = {1, 2, 4, 4};
1995 static int isize64[] = {1, 2, 4, 8};
1996
1997 /*
1998 * Just a bunch of useful macros.
1999 */
2000 #define WBIT(x) (x & 0x1) /* to get w bit */
2001 #define REGNO(x) (x & 0x7) /* to get 3 bit register */
2002 #define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */
2003 #define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1)
2004 #define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1)
2005
2006 #define REG_ONLY 3 /* mode to indicate a register operand (not memory) */
2007
2008 #define BYTE_OPND 0 /* w-bit value indicating byte register */
2009 #define LONG_OPND 1 /* w-bit value indicating opnd_size register */
2010 #define MM_OPND 2 /* "value" used to indicate a mmx reg */
2011 #define XMM_OPND 3 /* "value" used to indicate a xmm reg */
2012 #define SEG_OPND 4 /* "value" used to indicate a segment reg */
2013 #define CONTROL_OPND 5 /* "value" used to indicate a control reg */
2014 #define DEBUG_OPND 6 /* "value" used to indicate a debug reg */
2015 #define TEST_OPND 7 /* "value" used to indicate a test reg */
2016 #define WORD_OPND 8 /* w-bit value indicating word size reg */
2017 #define YMM_OPND 9 /* "value" used to indicate a ymm reg */
2018
2019 /*
2020 * Get the next byte and separate the op code into the high and low nibbles.
2021 */
2022 static int
2023 dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low)
2024 {
2025 int byte;
2026
2027 /*
2028 * x86 instructions have a maximum length of 15 bytes. Bail out if
2029 * we try to read more.
2030 */
2031 if (x->d86_len >= 15)
2032 return (x->d86_error = 1);
2033
2034 if (x->d86_error)
2035 return (1);
2036 byte = x->d86_get_byte(x->d86_data);
2037 if (byte < 0)
2038 return (x->d86_error = 1);
2039 x->d86_bytes[x->d86_len++] = byte;
2040 *low = byte & 0xf; /* ----xxxx low 4 bits */
2041 *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */
2042 return (0);
2043 }
2044
2045 /*
2046 * Get and decode an SIB (scaled index base) byte
2047 */
2048 static void
2049 dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base)
2050 {
2051 int byte;
2052
2053 if (x->d86_error)
2054 return;
2055
2056 byte = x->d86_get_byte(x->d86_data);
2057 if (byte < 0) {
2058 x->d86_error = 1;
2059 return;
2060 }
2061 x->d86_bytes[x->d86_len++] = byte;
2062
2063 *base = byte & 0x7;
2064 *index = (byte >> 3) & 0x7;
2065 *ss = (byte >> 6) & 0x3;
2066 }
2067
2068 /*
2069 * Get the byte following the op code and separate it into the
2070 * mode, register, and r/m fields.
2071 */
2072 static void
2073 dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m)
2074 {
2075 if (x->d86_got_modrm == 0) {
2076 if (x->d86_rmindex == -1)
2077 x->d86_rmindex = x->d86_len;
2078 dtrace_get_SIB(x, mode, reg, r_m);
2079 x->d86_got_modrm = 1;
2080 }
2081 }
2082
2083 /*
2084 * Adjust register selection based on any REX prefix bits present.
2085 */
2086 /*ARGSUSED*/
2087 static void
2088 dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m)
2089 {
2090 #pragma unused (mode)
2091 if (reg != NULL && r_m == NULL) {
2092 if (rex_prefix & REX_B)
2093 *reg += 8;
2094 } else {
2095 if (reg != NULL && (REX_R & rex_prefix) != 0)
2096 *reg += 8;
2097 if (r_m != NULL && (REX_B & rex_prefix) != 0)
2098 *r_m += 8;
2099 }
2100 }
2101
2102 /*
2103 * Adjust register selection based on any VEX prefix bits present.
2104 * Notes: VEX.R, VEX.X and VEX.B use the inverted form compared with REX prefix
2105 */
2106 /*ARGSUSED*/
2107 static void
2108 dtrace_vex_adjust(uint_t vex_byte1, uint_t mode, uint_t *reg, uint_t *r_m)
2109 {
2110 #pragma unused (mode)
2111 if (reg != NULL && r_m == NULL) {
2112 if (!(vex_byte1 & VEX_B))
2113 *reg += 8;
2114 } else {
2115 if (reg != NULL && ((VEX_R & vex_byte1) == 0))
2116 *reg += 8;
2117 if (r_m != NULL && ((VEX_B & vex_byte1) == 0))
2118 *r_m += 8;
2119 }
2120 }
2121 /*
2122 * Get an immediate operand of the given size, with sign extension.
2123 */
2124 static void
2125 dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex)
2126 {
2127 int i;
2128 int byte;
2129 int valsize;
2130
2131 if (x->d86_numopnds < (uint_t)opindex + 1)
2132 x->d86_numopnds = (uint_t)opindex + 1;
2133
2134 switch (wbit) {
2135 case BYTE_OPND:
2136 valsize = 1;
2137 break;
2138 case LONG_OPND:
2139 if (x->d86_opnd_size == SIZE16)
2140 valsize = 2;
2141 else if (x->d86_opnd_size == SIZE32)
2142 valsize = 4;
2143 else
2144 valsize = 8;
2145 break;
2146 case MM_OPND:
2147 case XMM_OPND:
2148 case YMM_OPND:
2149 case SEG_OPND:
2150 case CONTROL_OPND:
2151 case DEBUG_OPND:
2152 case TEST_OPND:
2153 valsize = size;
2154 break;
2155 case WORD_OPND:
2156 valsize = 2;
2157 break;
2158 }
2159 if (valsize < size)
2160 valsize = size;
2161
2162 if (x->d86_error)
2163 return;
2164 x->d86_opnd[opindex].d86_value = 0;
2165 for (i = 0; i < size; ++i) {
2166 byte = x->d86_get_byte(x->d86_data);
2167 if (byte < 0) {
2168 x->d86_error = 1;
2169 return;
2170 }
2171 x->d86_bytes[x->d86_len++] = byte;
2172 x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8);
2173 }
2174 /* Do sign extension */
2175 if (x->d86_bytes[x->d86_len - 1] & 0x80) {
2176 for (; i < (int)sizeof (uint64_t); i++)
2177 x->d86_opnd[opindex].d86_value |=
2178 (uint64_t)0xff << (i * 8);
2179 }
2180 #ifdef DIS_TEXT
2181 x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
2182 x->d86_opnd[opindex].d86_value_size = valsize;
2183 x->d86_imm_bytes += size;
2184 #endif
2185 }
2186
2187 /*
2188 * Get an ip relative operand of the given size, with sign extension.
2189 */
2190 static void
2191 dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex)
2192 {
2193 dtrace_imm_opnd(x, wbit, size, opindex);
2194 #ifdef DIS_TEXT
2195 x->d86_opnd[opindex].d86_mode = MODE_IPREL;
2196 #endif
2197 }
2198
2199 /*
2200 * Check to see if there is a segment override prefix pending.
2201 * If so, print it in the current 'operand' location and set
2202 * the override flag back to false.
2203 */
2204 /*ARGSUSED*/
2205 static void
2206 dtrace_check_override(dis86_t *x, int opindex)
2207 {
2208 #ifdef DIS_TEXT
2209 if (x->d86_seg_prefix) {
2210 (void) strlcat(x->d86_opnd[opindex].d86_prefix,
2211 x->d86_seg_prefix, PFIXLEN);
2212 }
2213 #else
2214 #pragma unused (opindex)
2215 #endif
2216 x->d86_seg_prefix = NULL;
2217 }
2218
2219
2220 /*
2221 * Process a single instruction Register or Memory operand.
2222 *
2223 * mode = addressing mode from ModRM byte
2224 * r_m = r_m (or reg if mode == 3) field from ModRM byte
2225 * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use.
2226 * o = index of operand that we are processing (0, 1 or 2)
2227 *
2228 * the value of reg or r_m must have already been adjusted for any REX prefix.
2229 */
2230 /*ARGSUSED*/
2231 static void
2232 dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex)
2233 {
2234 int have_SIB = 0; /* flag presence of scale-index-byte */
2235 uint_t ss; /* scale-factor from opcode */
2236 uint_t index; /* index register number */
2237 uint_t base; /* base register number */
2238 int dispsize; /* size of displacement in bytes */
2239 #ifdef DIS_TEXT
2240 char *opnd = x->d86_opnd[opindex].d86_opnd;
2241 #else
2242 #pragma unused (wbit)
2243 #endif
2244
2245 if (x->d86_numopnds < (uint_t)opindex + 1)
2246 x->d86_numopnds = (uint_t)opindex + 1;
2247
2248 if (x->d86_error)
2249 return;
2250
2251 /*
2252 * first handle a simple register
2253 */
2254 if (mode == REG_ONLY) {
2255 #ifdef DIS_TEXT
2256 switch (wbit) {
2257 case MM_OPND:
2258 (void) strlcat(opnd, dis_MMREG[r_m], OPLEN);
2259 break;
2260 case XMM_OPND:
2261 (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN);
2262 break;
2263 case YMM_OPND:
2264 (void) strlcat(opnd, dis_YMMREG[r_m], OPLEN);
2265 break;
2266 case SEG_OPND:
2267 (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN);
2268 break;
2269 case CONTROL_OPND:
2270 (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN);
2271 break;
2272 case DEBUG_OPND:
2273 (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN);
2274 break;
2275 case TEST_OPND:
2276 (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN);
2277 break;
2278 case BYTE_OPND:
2279 if (x->d86_rex_prefix == 0)
2280 (void) strlcat(opnd, dis_REG8[r_m], OPLEN);
2281 else
2282 (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN);
2283 break;
2284 case WORD_OPND:
2285 (void) strlcat(opnd, dis_REG16[r_m], OPLEN);
2286 break;
2287 case LONG_OPND:
2288 if (x->d86_opnd_size == SIZE16)
2289 (void) strlcat(opnd, dis_REG16[r_m], OPLEN);
2290 else if (x->d86_opnd_size == SIZE32)
2291 (void) strlcat(opnd, dis_REG32[r_m], OPLEN);
2292 else
2293 (void) strlcat(opnd, dis_REG64[r_m], OPLEN);
2294 break;
2295 }
2296 #endif /* DIS_TEXT */
2297 return;
2298 }
2299
2300 /*
2301 * if symbolic representation, skip override prefix, if any
2302 */
2303 dtrace_check_override(x, opindex);
2304
2305 /*
2306 * Handle 16 bit memory references first, since they decode
2307 * the mode values more simply.
2308 * mode 1 is r_m + 8 bit displacement
2309 * mode 2 is r_m + 16 bit displacement
2310 * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp
2311 */
2312 if (x->d86_addr_size == SIZE16) {
2313 if ((mode == 0 && r_m == 6) || mode == 2)
2314 dtrace_imm_opnd(x, WORD_OPND, 2, opindex);
2315 else if (mode == 1)
2316 dtrace_imm_opnd(x, BYTE_OPND, 1, opindex);
2317 #ifdef DIS_TEXT
2318 if (mode == 0 && r_m == 6)
2319 x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
2320 else if (mode == 0)
2321 x->d86_opnd[opindex].d86_mode = MODE_NONE;
2322 else
2323 x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
2324 (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN);
2325 #endif
2326 return;
2327 }
2328
2329 /*
2330 * 32 and 64 bit addressing modes are more complex since they
2331 * can involve an SIB (scaled index and base) byte to decode.
2332 */
2333 if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) {
2334 have_SIB = 1;
2335 dtrace_get_SIB(x, &ss, &index, &base);
2336 if (x->d86_error)
2337 return;
2338 if (base != 5 || mode != 0)
2339 if (x->d86_rex_prefix & REX_B)
2340 base += 8;
2341 if (x->d86_rex_prefix & REX_X)
2342 index += 8;
2343 } else {
2344 base = r_m;
2345 }
2346
2347 /*
2348 * Compute the displacement size and get its bytes
2349 */
2350 dispsize = 0;
2351
2352 if (mode == 1)
2353 dispsize = 1;
2354 else if (mode == 2)
2355 dispsize = 4;
2356 else if ((r_m & 7) == EBP_REGNO ||
2357 (have_SIB && (base & 7) == EBP_REGNO))
2358 dispsize = 4;
2359
2360 if (dispsize > 0) {
2361 dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND,
2362 dispsize, opindex);
2363 if (x->d86_error)
2364 return;
2365 }
2366
2367 #ifdef DIS_TEXT
2368 if (dispsize > 0)
2369 x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
2370
2371 if (have_SIB == 0) {
2372 if (x->d86_mode == SIZE32) {
2373 if (mode == 0)
2374 (void) strlcat(opnd, dis_addr32_mode0[r_m],
2375 OPLEN);
2376 else
2377 (void) strlcat(opnd, dis_addr32_mode12[r_m],
2378 OPLEN);
2379 } else {
2380 if (mode == 0) {
2381 (void) strlcat(opnd, dis_addr64_mode0[r_m],
2382 OPLEN);
2383 if (r_m == 5) {
2384 x->d86_opnd[opindex].d86_mode =
2385 MODE_RIPREL;
2386 }
2387 } else {
2388 (void) strlcat(opnd, dis_addr64_mode12[r_m],
2389 OPLEN);
2390 }
2391 }
2392 } else {
2393 uint_t need_paren = 0;
2394 char **regs;
2395 if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */
2396 regs = (char **)dis_REG32;
2397 else
2398 regs = (char **)dis_REG64;
2399
2400 /*
2401 * print the base (if any)
2402 */
2403 if (base == EBP_REGNO && mode == 0) {
2404 if (index != ESP_REGNO) {
2405 (void) strlcat(opnd, "(", OPLEN);
2406 need_paren = 1;
2407 }
2408 } else {
2409 (void) strlcat(opnd, "(", OPLEN);
2410 (void) strlcat(opnd, regs[base], OPLEN);
2411 need_paren = 1;
2412 }
2413
2414 /*
2415 * print the index (if any)
2416 */
2417 if (index != ESP_REGNO) {
2418 (void) strlcat(opnd, ",", OPLEN);
2419 (void) strlcat(opnd, regs[index], OPLEN);
2420 (void) strlcat(opnd, dis_scale_factor[ss], OPLEN);
2421 } else
2422 if (need_paren)
2423 (void) strlcat(opnd, ")", OPLEN);
2424 }
2425 #endif
2426 }
2427
2428 /*
2429 * Operand sequence for standard instruction involving one register
2430 * and one register/memory operand.
2431 * wbit indicates a byte(0) or opnd_size(1) operation
2432 * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r")
2433 */
2434 #define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \
2435 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2436 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2437 dtrace_get_operand(x, mode, r_m, wbit, vbit); \
2438 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \
2439 }
2440
2441 /*
2442 * Similar to above, but allows for the two operands to be of different
2443 * classes (ie. wbit).
2444 * wbit is for the r_m operand
2445 * w2 is for the reg operand
2446 */
2447 #define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \
2448 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2449 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2450 dtrace_get_operand(x, mode, r_m, wbit, vbit); \
2451 dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \
2452 }
2453
2454 /*
2455 * Similar, but for 2 operands plus an immediate.
2456 * vbit indicates direction
2457 * 0 for "opcode imm, r, r_m" or
2458 * 1 for "opcode imm, r_m, r"
2459 */
2460 #define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \
2461 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2462 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2463 dtrace_get_operand(x, mode, r_m, wbit, 2-vbit); \
2464 dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \
2465 dtrace_imm_opnd(x, wbit, immsize, 0); \
2466 }
2467
2468 /*
2469 * Similar, but for 2 operands plus two immediates.
2470 */
2471 #define FOUROPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \
2472 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2473 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2474 dtrace_get_operand(x, mode, r_m, wbit, 2); \
2475 dtrace_get_operand(x, REG_ONLY, reg, w2, 3); \
2476 dtrace_imm_opnd(x, wbit, immsize, 1); \
2477 dtrace_imm_opnd(x, wbit, immsize, 0); \
2478 }
2479
2480 /*
2481 * 1 operands plus two immediates.
2482 */
2483 #define ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, wbit, immsize) { \
2484 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2485 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2486 dtrace_get_operand(x, mode, r_m, wbit, 2); \
2487 dtrace_imm_opnd(x, wbit, immsize, 1); \
2488 dtrace_imm_opnd(x, wbit, immsize, 0); \
2489 }
2490
2491 /*
2492 * Dissassemble a single x86 or amd64 instruction.
2493 *
2494 * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64)
2495 * for interpreting instructions.
2496 *
2497 * returns non-zero for bad opcode
2498 */
2499 int
2500 dtrace_disx86(dis86_t *x, uint_t cpu_mode)
2501 {
2502 instable_t *dp; /* decode table being used */
2503 #ifdef DIS_TEXT
2504 uint_t i;
2505 #endif
2506 #ifdef DIS_MEM
2507 uint_t nomem = 0;
2508 #define NOMEM (nomem = 1)
2509 #else
2510 #define NOMEM /* nothing */
2511 #endif
2512 uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */
2513 uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */
2514 uint_t wbit = 0; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */
2515 uint_t w2; /* wbit value for second operand */
2516 uint_t vbit;
2517 uint_t mode = 0; /* mode value from ModRM byte */
2518 uint_t reg; /* reg value from ModRM byte */
2519 uint_t r_m; /* r_m value from ModRM byte */
2520
2521 uint_t opcode1; /* high nibble of 1st byte */
2522 uint_t opcode2; /* low nibble of 1st byte */
2523 uint_t opcode3; /* extra opcode bits usually from ModRM byte */
2524 uint_t opcode4; /* high nibble of 2nd byte */
2525 uint_t opcode5; /* low nibble of 2nd byte */
2526 uint_t opcode6; /* high nibble of 3rd byte */
2527 uint_t opcode7; /* low nibble of 3rd byte */
2528 uint_t opcode_bytes = 1;
2529
2530 /*
2531 * legacy prefixes come in 5 flavors, you should have only one of each
2532 */
2533 uint_t opnd_size_prefix = 0;
2534 uint_t addr_size_prefix = 0;
2535 uint_t segment_prefix = 0;
2536 uint_t lock_prefix = 0;
2537 uint_t rep_prefix = 0;
2538 uint_t rex_prefix = 0; /* amd64 register extension prefix */
2539
2540 /*
2541 * Intel VEX instruction encoding prefix and fields
2542 */
2543
2544 /* 0xC4 means 3 bytes prefix, 0xC5 means 2 bytes prefix */
2545 uint_t vex_prefix = 0;
2546
2547 /*
2548 * VEX prefix byte 1, includes vex.r, vex.x and vex.b
2549 * (for 3 bytes prefix)
2550 */
2551 uint_t vex_byte1 = 0;
2552
2553 /*
2554 * For 32-bit mode, it should prefetch the next byte to
2555 * distinguish between AVX and les/lds
2556 */
2557 uint_t vex_prefetch = 0;
2558
2559 uint_t vex_m = 0;
2560 uint_t vex_v = 0;
2561 uint_t vex_p = 0;
2562 uint_t vex_R = 1;
2563 uint_t vex_X = 1;
2564 uint_t vex_B = 1;
2565 uint_t vex_W = 0;
2566 uint_t vex_L;
2567
2568 size_t off;
2569
2570 instable_t dp_mmx;
2571
2572 x->d86_len = 0;
2573 x->d86_rmindex = -1;
2574 x->d86_rex_prefix = 0;
2575 x->d86_got_modrm = 0;
2576 #ifdef DIS_TEXT
2577 x->d86_numopnds = 0;
2578 x->d86_seg_prefix = NULL;
2579 x->d86_mnem[0] = 0;
2580 for (i = 0; i < 4; ++i) {
2581 x->d86_opnd[i].d86_opnd[0] = 0;
2582 x->d86_opnd[i].d86_prefix[0] = 0;
2583 x->d86_opnd[i].d86_value_size = 0;
2584 x->d86_opnd[i].d86_value = 0;
2585 x->d86_opnd[i].d86_mode = MODE_NONE;
2586 }
2587 #endif
2588 x->d86_error = 0;
2589 x->d86_memsize = 0;
2590
2591 if (cpu_mode == SIZE16) {
2592 opnd_size = SIZE16;
2593 addr_size = SIZE16;
2594 } else if (cpu_mode == SIZE32) {
2595 opnd_size = SIZE32;
2596 addr_size = SIZE32;
2597 } else {
2598 opnd_size = SIZE32;
2599 addr_size = SIZE64;
2600 }
2601
2602 /*
2603 * Get one opcode byte and check for zero padding that follows
2604 * jump tables.
2605 */
2606 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2607 goto error;
2608
2609 if (opcode1 == 0 && opcode2 == 0 &&
2610 x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) {
2611 #ifdef DIS_TEXT
2612 (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN);
2613 x->d86_mnem[OPLEN - 1] = '\0';
2614 #endif
2615 goto done;
2616 }
2617
2618 /*
2619 * Gather up legacy x86 prefix bytes.
2620 */
2621 for (;;) {
2622 uint_t *which_prefix = NULL;
2623
2624 dp = (instable_t *)&dis_distable[opcode1][opcode2];
2625
2626 switch (dp->it_adrmode) {
2627 case PREFIX:
2628 which_prefix = &rep_prefix;
2629 break;
2630 case LOCK:
2631 which_prefix = &lock_prefix;
2632 break;
2633 case OVERRIDE:
2634 which_prefix = &segment_prefix;
2635 #ifdef DIS_TEXT
2636 x->d86_seg_prefix = (char *)dp->it_name;
2637 #endif
2638 if (dp->it_invalid64 && cpu_mode == SIZE64)
2639 goto error;
2640 break;
2641 case AM:
2642 which_prefix = &addr_size_prefix;
2643 break;
2644 case DM:
2645 which_prefix = &opnd_size_prefix;
2646 break;
2647 }
2648 if (which_prefix == NULL)
2649 break;
2650 *which_prefix = (opcode1 << 4) | opcode2;
2651 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2652 goto error;
2653 }
2654
2655 /*
2656 * Handle amd64 mode PREFIX values.
2657 * Some of the segment prefixes are no-ops. (only FS/GS actually work)
2658 * We might have a REX prefix (opcodes 0x40-0x4f)
2659 */
2660 if (cpu_mode == SIZE64) {
2661 if (segment_prefix != 0x64 && segment_prefix != 0x65)
2662 segment_prefix = 0;
2663
2664 if (opcode1 == 0x4) {
2665 rex_prefix = (opcode1 << 4) | opcode2;
2666 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2667 goto error;
2668 dp = (instable_t *)&dis_distable[opcode1][opcode2];
2669 } else if (opcode1 == 0xC &&
2670 (opcode2 == 0x4 || opcode2 == 0x5)) {
2671 /* AVX instructions */
2672 vex_prefix = (opcode1 << 4) | opcode2;
2673 x->d86_rex_prefix = 0x40;
2674 }
2675 } else if (opcode1 == 0xC && (opcode2 == 0x4 || opcode2 == 0x5)) {
2676 /* LDS, LES or AVX */
2677 dtrace_get_modrm(x, &mode, &reg, &r_m);
2678 vex_prefetch = 1;
2679
2680 if (mode == REG_ONLY) {
2681 /* AVX */
2682 vex_prefix = (opcode1 << 4) | opcode2;
2683 x->d86_rex_prefix = 0x40;
2684 opcode3 = (((mode << 3) | reg)>>1) & 0x0F;
2685 opcode4 = ((reg << 3) | r_m) & 0x0F;
2686 }
2687 }
2688
2689 if (vex_prefix == VEX_2bytes) {
2690 if (!vex_prefetch) {
2691 if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0)
2692 goto error;
2693 }
2694 vex_R = ((opcode3 & VEX_R) & 0x0F) >> 3;
2695 vex_L = ((opcode4 & VEX_L) & 0x0F) >> 2;
2696 vex_v = (((opcode3 << 4) | opcode4) & VEX_v) >> 3;
2697 vex_p = opcode4 & VEX_p;
2698 /*
2699 * The vex.x and vex.b bits are not defined in two bytes
2700 * mode vex prefix, their default values are 1
2701 */
2702 vex_byte1 = (opcode3 & VEX_R) | VEX_X | VEX_B;
2703
2704 if (vex_R == 0)
2705 x->d86_rex_prefix |= REX_R;
2706
2707 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2708 goto error;
2709
2710 switch (vex_p) {
2711 case VEX_p_66:
2712 dp = (instable_t *)
2713 &dis_opAVX660F[(opcode1 << 4) | opcode2];
2714 break;
2715 case VEX_p_F3:
2716 dp = (instable_t *)
2717 &dis_opAVXF30F[(opcode1 << 4) | opcode2];
2718 break;
2719 case VEX_p_F2:
2720 dp = (instable_t *)
2721 &dis_opAVXF20F [(opcode1 << 4) | opcode2];
2722 break;
2723 default:
2724 dp = (instable_t *)
2725 &dis_opAVX0F[opcode1][opcode2];
2726
2727 }
2728
2729 } else if (vex_prefix == VEX_3bytes) {
2730 if (!vex_prefetch) {
2731 if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0)
2732 goto error;
2733 }
2734 vex_R = (opcode3 & VEX_R) >> 3;
2735 vex_X = (opcode3 & VEX_X) >> 2;
2736 vex_B = (opcode3 & VEX_B) >> 1;
2737 vex_m = (((opcode3 << 4) | opcode4) & VEX_m);
2738 vex_byte1 = opcode3 & (VEX_R | VEX_X | VEX_B);
2739
2740 if (vex_R == 0)
2741 x->d86_rex_prefix |= REX_R;
2742 if (vex_X == 0)
2743 x->d86_rex_prefix |= REX_X;
2744 if (vex_B == 0)
2745 x->d86_rex_prefix |= REX_B;
2746
2747 if (dtrace_get_opcode(x, &opcode5, &opcode6) != 0)
2748 goto error;
2749 vex_W = (opcode5 & VEX_W) >> 3;
2750 vex_L = (opcode6 & VEX_L) >> 2;
2751 vex_v = (((opcode5 << 4) | opcode6) & VEX_v) >> 3;
2752 vex_p = opcode6 & VEX_p;
2753
2754 if (vex_W)
2755 x->d86_rex_prefix |= REX_W;
2756
2757 /* Only these three vex_m values valid; others are reserved */
2758 if ((vex_m != VEX_m_0F) && (vex_m != VEX_m_0F38) &&
2759 (vex_m != VEX_m_0F3A))
2760 goto error;
2761
2762 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2763 goto error;
2764
2765 switch (vex_p) {
2766 case VEX_p_66:
2767 if (vex_m == VEX_m_0F) {
2768 dp = (instable_t *)
2769 &dis_opAVX660F
2770 [(opcode1 << 4) | opcode2];
2771 } else if (vex_m == VEX_m_0F38) {
2772 dp = (instable_t *)
2773 &dis_opAVX660F38
2774 [(opcode1 << 4) | opcode2];
2775 } else if (vex_m == VEX_m_0F3A) {
2776 dp = (instable_t *)
2777 &dis_opAVX660F3A
2778 [(opcode1 << 4) | opcode2];
2779 } else {
2780 goto error;
2781 }
2782 break;
2783 case VEX_p_F3:
2784 if (vex_m == VEX_m_0F) {
2785 dp = (instable_t *)
2786 &dis_opAVXF30F
2787 [(opcode1 << 4) | opcode2];
2788 } else {
2789 goto error;
2790 }
2791 break;
2792 case VEX_p_F2:
2793 if (vex_m == VEX_m_0F) {
2794 dp = (instable_t *)
2795 &dis_opAVXF20F
2796 [(opcode1 << 4) | opcode2];
2797 } else {
2798 goto error;
2799 }
2800 break;
2801 default:
2802 dp = (instable_t *)
2803 &dis_opAVX0F[opcode1][opcode2];
2804
2805 }
2806 }
2807
2808 if (vex_prefix) {
2809 if (vex_L)
2810 wbit = YMM_OPND;
2811 else
2812 wbit = XMM_OPND;
2813 }
2814
2815 /*
2816 * Deal with selection of operand and address size now.
2817 * Note that the REX.W bit being set causes opnd_size_prefix to be
2818 * ignored.
2819 */
2820 if (cpu_mode == SIZE64) {
2821 if ((rex_prefix & REX_W) || vex_W)
2822 opnd_size = SIZE64;
2823 else if (opnd_size_prefix)
2824 opnd_size = SIZE16;
2825
2826 if (addr_size_prefix)
2827 addr_size = SIZE32;
2828 } else if (cpu_mode == SIZE32) {
2829 if (opnd_size_prefix)
2830 opnd_size = SIZE16;
2831 if (addr_size_prefix)
2832 addr_size = SIZE16;
2833 } else {
2834 if (opnd_size_prefix)
2835 opnd_size = SIZE32;
2836 if (addr_size_prefix)
2837 addr_size = SIZE32;
2838 }
2839
2840 /*
2841 * The pause instruction - a repz'd nop. This doesn't fit
2842 * with any of the other prefix goop added for SSE, so we'll
2843 * special-case it here.
2844 */
2845 if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) {
2846 rep_prefix = 0;
2847 dp = (instable_t *)&dis_opPause;
2848 }
2849
2850 /*
2851 * Some 386 instructions have 2 bytes of opcode before the mod_r/m
2852 * byte so we may need to perform a table indirection.
2853 */
2854 if (dp->it_indirect == (instable_t *)dis_op0F) {
2855 if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0)
2856 goto error;
2857 opcode_bytes = 2;
2858 if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) {
2859 uint_t subcode;
2860
2861 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2862 goto error;
2863 opcode_bytes = 3;
2864 subcode = ((opcode6 & 0x3) << 1) |
2865 ((opcode7 & 0x8) >> 3);
2866 dp = (instable_t *)&dis_op0F7123[opcode5][subcode];
2867 } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) {
2868 dp = (instable_t *)&dis_op0FC8[0];
2869 } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) {
2870 opcode_bytes = 3;
2871 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2872 goto error;
2873 if (opnd_size == SIZE16)
2874 opnd_size = SIZE32;
2875
2876 dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7];
2877 #ifdef DIS_TEXT
2878 if (LIT_STRNEQL(dp->it_name, "INVALID"))
2879 goto error;
2880 #endif
2881 switch (dp->it_adrmode) {
2882 case XMMP_66r:
2883 case XMMPRM_66r:
2884 case XMM3PM_66r:
2885 if (opnd_size_prefix == 0) {
2886 goto error;
2887 }
2888 break;
2889 case XMMP_66o:
2890 if (opnd_size_prefix == 0) {
2891 /* SSSE3 MMX instructions */
2892 dp_mmx = *dp;
2893 dp = &dp_mmx;
2894 dp->it_adrmode = MMOPM_66o;
2895 #ifdef DIS_MEM
2896 dp->it_size = 8;
2897 #endif
2898 }
2899 break;
2900 default:
2901 goto error;
2902 }
2903 } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) {
2904 opcode_bytes = 3;
2905 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2906 goto error;
2907 dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7];
2908 #ifdef DIS_TEXT
2909 if (LIT_STRNEQL(dp->it_name, "INVALID"))
2910 goto error;
2911 #endif
2912 switch (dp->it_adrmode) {
2913 case XMM_66r:
2914 case XMMM_66r:
2915 if (opnd_size_prefix == 0) {
2916 goto error;
2917 }
2918 break;
2919 case XMM_66o:
2920 if (opnd_size_prefix == 0) {
2921 /* SSSE3 MMX instructions */
2922 dp_mmx = *dp;
2923 dp = &dp_mmx;
2924 dp->it_adrmode = MM;
2925 #ifdef DIS_MEM
2926 dp->it_size = 8;
2927 #endif
2928 }
2929 break;
2930 case CRC32:
2931 if (rep_prefix != 0xF2) {
2932 goto error;
2933 }
2934 rep_prefix = 0;
2935 break;
2936 default:
2937 goto error;
2938 }
2939 } else {
2940 dp = (instable_t *)&dis_op0F[opcode4][opcode5];
2941 }
2942 }
2943
2944 /*
2945 * If still not at a TERM decode entry, then a ModRM byte
2946 * exists and its fields further decode the instruction.
2947 */
2948 x->d86_got_modrm = 0;
2949 if (dp->it_indirect != TERM) {
2950 dtrace_get_modrm(x, &mode, &opcode3, &r_m);
2951 if (x->d86_error)
2952 goto error;
2953 reg = opcode3;
2954
2955 /*
2956 * decode 287 instructions (D8-DF) from opcodeN
2957 */
2958 if (opcode1 == 0xD && opcode2 >= 0x8) {
2959 if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4)
2960 dp = (instable_t *)&dis_opFP5[r_m];
2961 else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4)
2962 dp = (instable_t *)&dis_opFP7[opcode3];
2963 else if (opcode2 == 0xB && mode == 0x3)
2964 dp = (instable_t *)&dis_opFP6[opcode3];
2965 else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4)
2966 dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m];
2967 else if (mode == 0x3)
2968 dp = (instable_t *)
2969 &dis_opFP3[opcode2 - 8][opcode3];
2970 else
2971 dp = (instable_t *)
2972 &dis_opFP1n2[opcode2 - 8][opcode3];
2973 } else {
2974 dp = (instable_t *)dp->it_indirect + opcode3;
2975 }
2976 }
2977
2978 /*
2979 * In amd64 bit mode, ARPL opcode is changed to MOVSXD
2980 * (sign extend 32bit to 64 bit)
2981 */
2982 if ((vex_prefix == 0) && cpu_mode == SIZE64 &&
2983 opcode1 == 0x6 && opcode2 == 0x3)
2984 {
2985 dp = (instable_t *)&dis_opMOVSLD;
2986 }
2987
2988 /*
2989 * at this point we should have a correct (or invalid) opcode
2990 */
2991 if ((cpu_mode == SIZE64 && dp->it_invalid64) ||
2992 (cpu_mode != SIZE64 && dp->it_invalid32))
2993 goto error;
2994 if (dp->it_indirect != TERM)
2995 goto error;
2996
2997 /*
2998 * deal with MMX/SSE opcodes which are changed by prefixes
2999 */
3000 switch (dp->it_adrmode) {
3001 case MMO:
3002 case MMOIMPL:
3003 case MMO3P:
3004 case MMOM3:
3005 case MMOMS:
3006 case MMOPM:
3007 case MMOPRM:
3008 case MMOS:
3009 case XMMO:
3010 case XMMOM:
3011 case XMMOMS:
3012 case XMMOPM:
3013 case XMMOS:
3014 case XMMOMX:
3015 case XMMOX3:
3016 case XMMOXMM:
3017 /*
3018 * This is horrible. Some SIMD instructions take the
3019 * form 0x0F 0x?? ..., which is easily decoded using the
3020 * existing tables. Other SIMD instructions use various
3021 * prefix bytes to overload existing instructions. For
3022 * Example, addps is F0, 58, whereas addss is F3 (repz),
3023 * F0, 58. Presumably someone got a raise for this.
3024 *
3025 * If we see one of the instructions which can be
3026 * modified in this way (if we've got one of the SIMDO*
3027 * address modes), we'll check to see if the last prefix
3028 * was a repz. If it was, we strip the prefix from the
3029 * mnemonic, and we indirect using the dis_opSIMDrepz
3030 * table.
3031 */
3032
3033 /*
3034 * Calculate our offset in dis_op0F
3035 */
3036 if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F))
3037 goto error;
3038
3039 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
3040 sizeof (instable_t);
3041
3042 /*
3043 * Rewrite if this instruction used one of the magic prefixes.
3044 */
3045 if (rep_prefix) {
3046 if (rep_prefix == 0xf2)
3047 dp = (instable_t *)&dis_opSIMDrepnz[off];
3048 else
3049 dp = (instable_t *)&dis_opSIMDrepz[off];
3050 rep_prefix = 0;
3051 } else if (opnd_size_prefix) {
3052 dp = (instable_t *)&dis_opSIMDdata16[off];
3053 opnd_size_prefix = 0;
3054 if (opnd_size == SIZE16)
3055 opnd_size = SIZE32;
3056 }
3057 break;
3058
3059 case MMOSH:
3060 /*
3061 * As with the "normal" SIMD instructions, the MMX
3062 * shuffle instructions are overloaded. These
3063 * instructions, however, are special in that they use
3064 * an extra byte, and thus an extra table. As of this
3065 * writing, they only use the opnd_size prefix.
3066 */
3067
3068 /*
3069 * Calculate our offset in dis_op0F7123
3070 */
3071 if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 >
3072 sizeof (dis_op0F7123))
3073 goto error;
3074
3075 if (opnd_size_prefix) {
3076 off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) /
3077 sizeof (instable_t);
3078 dp = (instable_t *)&dis_opSIMD7123[off];
3079 opnd_size_prefix = 0;
3080 if (opnd_size == SIZE16)
3081 opnd_size = SIZE32;
3082 }
3083 break;
3084 case MRw:
3085 if (rep_prefix) {
3086 if (rep_prefix == 0xf3) {
3087
3088 /*
3089 * Calculate our offset in dis_op0F
3090 */
3091 if ((uintptr_t)dp - (uintptr_t)dis_op0F
3092 > sizeof (dis_op0F))
3093 goto error;
3094
3095 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
3096 sizeof (instable_t);
3097
3098 dp = (instable_t *)&dis_opSIMDrepz[off];
3099 rep_prefix = 0;
3100 } else {
3101 goto error;
3102 }
3103 }
3104 break;
3105 }
3106
3107 /*
3108 * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64.
3109 */
3110 if (cpu_mode == SIZE64)
3111 if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop))
3112 opnd_size = SIZE64;
3113
3114 #ifdef DIS_TEXT
3115 /*
3116 * At this point most instructions can format the opcode mnemonic
3117 * including the prefixes.
3118 */
3119 if (lock_prefix)
3120 (void) strlcat(x->d86_mnem, "lock ", OPLEN);
3121
3122 if (rep_prefix == 0xf2)
3123 (void) strlcat(x->d86_mnem, "repnz ", OPLEN);
3124 else if (rep_prefix == 0xf3)
3125 (void) strlcat(x->d86_mnem, "repz ", OPLEN);
3126
3127 if (cpu_mode == SIZE64 && addr_size_prefix)
3128 (void) strlcat(x->d86_mnem, "addr32 ", OPLEN);
3129
3130 if (dp->it_adrmode != CBW &&
3131 dp->it_adrmode != CWD &&
3132 dp->it_adrmode != XMMSFNC) {
3133 if (LIT_STRNEQL(dp->it_name, "INVALID"))
3134 goto error;
3135 (void) strlcat(x->d86_mnem, dp->it_name, OPLEN);
3136 if (dp->it_suffix) {
3137 char *types[] = {"", "w", "l", "q"};
3138 if (opcode_bytes == 2 && opcode4 == 4) {
3139 /* It's a cmovx.yy. Replace the suffix x */
3140 for (i = 5; i < OPLEN; i++) {
3141 if (x->d86_mnem[i] == '.')
3142 break;
3143 }
3144 x->d86_mnem[i - 1] = *types[opnd_size];
3145 } else if ((opnd_size == 2) && (opcode_bytes == 3) &&
3146 ((opcode6 == 1 && opcode7 == 6) ||
3147 (opcode6 == 2 && opcode7 == 2))) {
3148 /*
3149 * To handle PINSRD and PEXTRD
3150 */
3151 (void) strlcat(x->d86_mnem, "d", OPLEN);
3152 } else {
3153 (void) strlcat(x->d86_mnem, types[opnd_size],
3154 OPLEN);
3155 }
3156 }
3157 }
3158 #endif
3159
3160 /*
3161 * Process operands based on the addressing modes.
3162 */
3163 x->d86_mode = cpu_mode;
3164 /*
3165 * In vex mode the rex_prefix has no meaning
3166 */
3167 if (!vex_prefix)
3168 x->d86_rex_prefix = rex_prefix;
3169 x->d86_opnd_size = opnd_size;
3170 x->d86_addr_size = addr_size;
3171 vbit = 0; /* initialize for mem/reg -> reg */
3172 switch (dp->it_adrmode) {
3173 /*
3174 * amd64 instruction to sign extend 32 bit reg/mem operands
3175 * into 64 bit register values
3176 */
3177 case MOVSXZ:
3178 #ifdef DIS_TEXT
3179 if (rex_prefix == 0) {
3180 (void) strncpy(x->d86_mnem, "movzld", OPLEN);
3181 x->d86_mnem[OPLEN - 1] = '\0';
3182 }
3183 #endif
3184 dtrace_get_modrm(x, &mode, &reg, &r_m);
3185 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3186 x->d86_opnd_size = SIZE64;
3187 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3188 x->d86_opnd_size = opnd_size = SIZE32;
3189 wbit = LONG_OPND;
3190 dtrace_get_operand(x, mode, r_m, wbit, 0);
3191 break;
3192
3193 /*
3194 * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF)
3195 * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7)
3196 * wbit lives in 2nd byte, note that operands
3197 * are different sized
3198 */
3199 case MOVZ:
3200 if (rex_prefix & REX_W) {
3201 /* target register size = 64 bit */
3202 x->d86_mnem[5] = 'q';
3203 }
3204 dtrace_get_modrm(x, &mode, &reg, &r_m);
3205 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3206 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3207 x->d86_opnd_size = opnd_size = SIZE16;
3208 wbit = WBIT(opcode5);
3209 dtrace_get_operand(x, mode, r_m, wbit, 0);
3210 break;
3211 case CRC32:
3212 opnd_size = SIZE32;
3213 if (rex_prefix & REX_W)
3214 opnd_size = SIZE64;
3215 x->d86_opnd_size = opnd_size;
3216
3217 dtrace_get_modrm(x, &mode, &reg, &r_m);
3218 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3219 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3220 wbit = WBIT(opcode7);
3221 if (opnd_size_prefix)
3222 x->d86_opnd_size = opnd_size = SIZE16;
3223 dtrace_get_operand(x, mode, r_m, wbit, 0);
3224 break;
3225
3226 /*
3227 * imul instruction, with either 8-bit or longer immediate
3228 * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s)
3229 */
3230 case IMUL:
3231 wbit = LONG_OPND;
3232 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND,
3233 OPSIZE(opnd_size, opcode2 == 0x9), 1);
3234 break;
3235
3236 /* memory or register operand to register, with 'w' bit */
3237 case MRw:
3238 wbit = WBIT(opcode2);
3239 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3240 break;
3241
3242 /* register to memory or register operand, with 'w' bit */
3243 /* arpl happens to fit here also because it is odd */
3244 case RMw:
3245 if (opcode_bytes == 2)
3246 wbit = WBIT(opcode5);
3247 else
3248 wbit = WBIT(opcode2);
3249 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3250 break;
3251
3252 /* xaddb instruction */
3253 case XADDB:
3254 wbit = 0;
3255 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3256 break;
3257
3258 /* MMX register to memory or register operand */
3259 case MMS:
3260 case MMOS:
3261 #ifdef DIS_TEXT
3262 wbit = !LIT_STRNEQL(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3263 #else
3264 wbit = LONG_OPND;
3265 #endif
3266 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
3267 break;
3268
3269 /* MMX register to memory */
3270 case MMOMS:
3271 dtrace_get_modrm(x, &mode, &reg, &r_m);
3272 if (mode == REG_ONLY)
3273 goto error;
3274 wbit = MM_OPND;
3275 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
3276 break;
3277
3278 /* Double shift. Has immediate operand specifying the shift. */
3279 case DSHIFT:
3280 wbit = LONG_OPND;
3281 dtrace_get_modrm(x, &mode, &reg, &r_m);
3282 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3283 dtrace_get_operand(x, mode, r_m, wbit, 2);
3284 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3285 dtrace_imm_opnd(x, wbit, 1, 0);
3286 break;
3287
3288 /*
3289 * Double shift. With no immediate operand, specifies using %cl.
3290 */
3291 case DSHIFTcl:
3292 wbit = LONG_OPND;
3293 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3294 break;
3295
3296 /* immediate to memory or register operand */
3297 case IMlw:
3298 wbit = WBIT(opcode2);
3299 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3300 dtrace_get_operand(x, mode, r_m, wbit, 1);
3301 /*
3302 * Have long immediate for opcode 0x81, but not 0x80 nor 0x83
3303 */
3304 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0);
3305 break;
3306
3307 /* immediate to memory or register operand with the */
3308 /* 'w' bit present */
3309 case IMw:
3310 wbit = WBIT(opcode2);
3311 dtrace_get_modrm(x, &mode, &reg, &r_m);
3312 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3313 dtrace_get_operand(x, mode, r_m, wbit, 1);
3314 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
3315 break;
3316
3317 /* immediate to register with register in low 3 bits */
3318 /* of op code */
3319 case IR:
3320 /* w-bit here (with regs) is bit 3 */
3321 wbit = opcode2 >>3 & 0x1;
3322 reg = REGNO(opcode2);
3323 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3324 mode = REG_ONLY;
3325 r_m = reg;
3326 dtrace_get_operand(x, mode, r_m, wbit, 1);
3327 dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0);
3328 break;
3329
3330 /* MMX immediate shift of register */
3331 case MMSH:
3332 case MMOSH:
3333 wbit = MM_OPND;
3334 goto mm_shift; /* in next case */
3335
3336 /* SIMD immediate shift of register */
3337 case XMMSH:
3338 wbit = XMM_OPND;
3339 mm_shift:
3340 reg = REGNO(opcode7);
3341 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3342 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
3343 dtrace_imm_opnd(x, wbit, 1, 0);
3344 NOMEM;
3345 break;
3346
3347 /* accumulator to memory operand */
3348 case AO:
3349 vbit = 1;
3350 /*FALLTHROUGH*/
3351
3352 /* memory operand to accumulator */
3353 case OA:
3354 wbit = WBIT(opcode2);
3355 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit);
3356 dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit);
3357 #ifdef DIS_TEXT
3358 x->d86_opnd[vbit].d86_mode = MODE_OFFSET;
3359 #endif
3360 break;
3361
3362
3363 /* segment register to memory or register operand */
3364 case SM:
3365 vbit = 1;
3366 /*FALLTHROUGH*/
3367
3368 /* memory or register operand to segment register */
3369 case MS:
3370 dtrace_get_modrm(x, &mode, &reg, &r_m);
3371 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3372 dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit);
3373 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit);
3374 break;
3375
3376 /*
3377 * rotate or shift instructions, which may shift by 1 or
3378 * consult the cl register, depending on the 'v' bit
3379 */
3380 case Mv:
3381 vbit = VBIT(opcode2);
3382 wbit = WBIT(opcode2);
3383 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3384 dtrace_get_operand(x, mode, r_m, wbit, 1);
3385 #ifdef DIS_TEXT
3386 if (vbit) {
3387 (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN);
3388 } else {
3389 x->d86_opnd[0].d86_mode = MODE_SIGNED;
3390 x->d86_opnd[0].d86_value_size = 1;
3391 x->d86_opnd[0].d86_value = 1;
3392 }
3393 #endif
3394 break;
3395 /*
3396 * immediate rotate or shift instructions
3397 */
3398 case MvI:
3399 wbit = WBIT(opcode2);
3400 normal_imm_mem:
3401 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3402 dtrace_get_operand(x, mode, r_m, wbit, 1);
3403 dtrace_imm_opnd(x, wbit, 1, 0);
3404 break;
3405
3406 /* bit test instructions */
3407 case MIb:
3408 wbit = LONG_OPND;
3409 goto normal_imm_mem;
3410
3411 /* single memory or register operand with 'w' bit present */
3412 case Mw:
3413 wbit = WBIT(opcode2);
3414 just_mem:
3415 dtrace_get_modrm(x, &mode, &reg, &r_m);
3416 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3417 dtrace_get_operand(x, mode, r_m, wbit, 0);
3418 break;
3419
3420 case SWAPGS:
3421 if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) {
3422 #ifdef DIS_TEXT
3423 (void) strncpy(x->d86_mnem, "swapgs", OPLEN);
3424 x->d86_mnem[OPLEN - 1] = '\0';
3425 #endif
3426 NOMEM;
3427 break;
3428 }
3429 /*FALLTHROUGH*/
3430
3431 /* prefetch instruction - memory operand, but no memory acess */
3432 case PREF:
3433 NOMEM;
3434 /*FALLTHROUGH*/
3435
3436 /* single memory or register operand */
3437 case M:
3438 wbit = LONG_OPND;
3439 goto just_mem;
3440
3441 /* single memory or register byte operand */
3442 case Mb:
3443 wbit = BYTE_OPND;
3444 goto just_mem;
3445
3446 case MONITOR_MWAIT:
3447 if (mode == 3) {
3448 if (r_m == 0) {
3449 #ifdef DIS_TEXT
3450 (void) strncpy(x->d86_mnem, "monitor", OPLEN);
3451 x->d86_mnem[OPLEN - 1] = '\0';
3452 #endif
3453 NOMEM;
3454 break;
3455 } else if (r_m == 1) {
3456 #ifdef DIS_TEXT
3457 (void) strncpy(x->d86_mnem, "mwait", OPLEN);
3458 x->d86_mnem[OPLEN - 1] = '\0';
3459 #endif
3460 NOMEM;
3461 break;
3462 } else {
3463 goto error;
3464 }
3465 }
3466 /*FALLTHROUGH*/
3467 case XGETBV_XSETBV:
3468 if (mode == 3) {
3469 if (r_m == 0) {
3470 #ifdef DIS_TEXT
3471 (void) strncpy(x->d86_mnem, "xgetbv", OPLEN);
3472 #endif
3473 NOMEM;
3474 break;
3475 } else if (r_m == 1) {
3476 #ifdef DIS_TEXT
3477 (void) strncpy(x->d86_mnem, "xsetbv", OPLEN);
3478 #endif
3479 NOMEM;
3480 break;
3481 } else {
3482 goto error;
3483 }
3484
3485 }
3486 /*FALLTHROUGH*/
3487 case MO:
3488 /* Similar to M, but only memory (no direct registers) */
3489 wbit = LONG_OPND;
3490 dtrace_get_modrm(x, &mode, &reg, &r_m);
3491 if (mode == 3)
3492 goto error;
3493 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3494 dtrace_get_operand(x, mode, r_m, wbit, 0);
3495 break;
3496
3497 /* move special register to register or reverse if vbit */
3498 case SREG:
3499 switch (opcode5) {
3500
3501 case 2:
3502 vbit = 1;
3503 /*FALLTHROUGH*/
3504 case 0:
3505 wbit = CONTROL_OPND;
3506 break;
3507
3508 case 3:
3509 vbit = 1;
3510 /*FALLTHROUGH*/
3511 case 1:
3512 wbit = DEBUG_OPND;
3513 break;
3514
3515 case 6:
3516 vbit = 1;
3517 /*FALLTHROUGH*/
3518 case 4:
3519 wbit = TEST_OPND;
3520 break;
3521
3522 }
3523 dtrace_get_modrm(x, &mode, &reg, &r_m);
3524 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3525 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit);
3526 dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit);
3527 NOMEM;
3528 break;
3529
3530 /*
3531 * single register operand with register in the low 3
3532 * bits of op code
3533 */
3534 case R:
3535 if (opcode_bytes == 2)
3536 reg = REGNO(opcode5);
3537 else
3538 reg = REGNO(opcode2);
3539 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3540 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3541 NOMEM;
3542 break;
3543
3544 /*
3545 * register to accumulator with register in the low 3
3546 * bits of op code, xchg instructions
3547 */
3548 case RA:
3549 NOMEM;
3550 reg = REGNO(opcode2);
3551 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3552 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3553 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1);
3554 break;
3555
3556 /*
3557 * single segment register operand, with register in
3558 * bits 3-4 of op code byte
3559 */
3560 case SEG:
3561 NOMEM;
3562 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3;
3563 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
3564 break;
3565
3566 /*
3567 * single segment register operand, with register in
3568 * bits 3-5 of op code
3569 */
3570 case LSEG:
3571 NOMEM;
3572 /* long seg reg from opcode */
3573 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7;
3574 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
3575 break;
3576
3577 /* memory or register operand to register */
3578 case MR:
3579 if (vex_prefetch) {
3580 x->d86_got_modrm = 1;
3581 }
3582 wbit = LONG_OPND;
3583 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3584 break;
3585
3586 case RM:
3587 wbit = LONG_OPND;
3588 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3589 break;
3590
3591 /* MMX/SIMD-Int memory or mm reg to mm reg */
3592 case MM:
3593 case MMO:
3594 #ifdef DIS_TEXT
3595 wbit = !LIT_STRNEQL(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3596 #else
3597 wbit = LONG_OPND;
3598 #endif
3599 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
3600 break;
3601
3602 case MMOIMPL:
3603 #ifdef DIS_TEXT
3604 wbit = !LIT_STRNEQL(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3605 #else
3606 wbit = LONG_OPND;
3607 #endif
3608 dtrace_get_modrm(x, &mode, &reg, &r_m);
3609 if (mode != REG_ONLY)
3610 goto error;
3611
3612 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3613 dtrace_get_operand(x, mode, r_m, wbit, 0);
3614 dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1);
3615 mode = 0; /* change for memory access size... */
3616 break;
3617
3618 /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */
3619 case MMO3P:
3620 wbit = MM_OPND;
3621 goto xmm3p;
3622 case XMM3P:
3623 wbit = XMM_OPND;
3624 xmm3p:
3625 dtrace_get_modrm(x, &mode, &reg, &r_m);
3626 if (mode != REG_ONLY)
3627 goto error;
3628
3629 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1,
3630 1);
3631 NOMEM;
3632 break;
3633
3634 case XMM3PM_66r:
3635 THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND,
3636 1, 0);
3637 break;
3638
3639 /* MMX/SIMD-Int predicated r32/mem to mm reg */
3640 case MMOPRM:
3641 wbit = LONG_OPND;
3642 w2 = MM_OPND;
3643 goto xmmprm;
3644 case XMMPRM:
3645 case XMMPRM_66r:
3646 wbit = LONG_OPND;
3647 w2 = XMM_OPND;
3648 xmmprm:
3649 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1);
3650 break;
3651
3652 /* MMX/SIMD-Int predicated mm/mem to mm reg */
3653 case MMOPM:
3654 case MMOPM_66o:
3655 wbit = w2 = MM_OPND;
3656 goto xmmprm;
3657
3658 /* MMX/SIMD-Int mm reg to r32 */
3659 case MMOM3:
3660 NOMEM;
3661 dtrace_get_modrm(x, &mode, &reg, &r_m);
3662 if (mode != REG_ONLY)
3663 goto error;
3664 wbit = MM_OPND;
3665 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
3666 break;
3667
3668 /* SIMD memory or xmm reg operand to xmm reg */
3669 case XMM:
3670 case XMM_66o:
3671 case XMM_66r:
3672 case XMMO:
3673 case XMMXIMPL:
3674 wbit = XMM_OPND;
3675 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3676
3677 if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY)
3678 goto error;
3679
3680 #ifdef DIS_TEXT
3681 /*
3682 * movlps and movhlps share opcodes. They differ in the
3683 * addressing modes allowed for their operands.
3684 * movhps and movlhps behave similarly.
3685 */
3686 if (mode == REG_ONLY) {
3687 if (LIT_STRNEQL(dp->it_name, "movlps"))
3688 (void) strncpy(x->d86_mnem, "movhlps", OPLEN);
3689 x->d86_mnem[OPLEN - 1] = '\0';
3690 } else if (LIT_STRNEQL(dp->it_name, "movhps")) {
3691 (void) strncpy(x->d86_mnem, "movlhps", OPLEN);
3692 x->d86_mnem[OPLEN - 1] = '\0';
3693 }
3694 }
3695 #endif
3696 if (dp->it_adrmode == XMMXIMPL)
3697 mode = 0; /* change for memory access size... */
3698 break;
3699
3700 /* SIMD xmm reg to memory or xmm reg */
3701 case XMMS:
3702 case XMMOS:
3703 case XMMMS:
3704 case XMMOMS:
3705 dtrace_get_modrm(x, &mode, &reg, &r_m);
3706 #ifdef DIS_TEXT
3707 if ((LIT_STRNEQL(dp->it_name, "movlps") ||
3708 LIT_STRNEQL(dp->it_name, "movhps") ||
3709 LIT_STRNEQL(dp->it_name, "movntps")) &&
3710 mode == REG_ONLY)
3711 goto error;
3712 #endif
3713 wbit = XMM_OPND;
3714 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
3715 break;
3716
3717 /* SIMD memory to xmm reg */
3718 case XMMM:
3719 case XMMM_66r:
3720 case XMMOM:
3721 wbit = XMM_OPND;
3722 dtrace_get_modrm(x, &mode, &reg, &r_m);
3723 #ifdef DIS_TEXT
3724 if (mode == REG_ONLY) {
3725 if (LIT_STRNEQL(dp->it_name, "movhps")) {
3726 (void) strncpy(x->d86_mnem, "movlhps", OPLEN);
3727 x->d86_mnem[OPLEN - 1] = '\0';
3728 } else
3729 goto error;
3730 }
3731 #endif
3732 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3733 break;
3734
3735 /* SIMD memory or r32 to xmm reg */
3736 case XMM3MX:
3737 wbit = LONG_OPND;
3738 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3739 break;
3740
3741 case XMM3MXS:
3742 wbit = LONG_OPND;
3743 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
3744 break;
3745
3746 /* SIMD memory or mm reg to xmm reg */
3747 case XMMOMX:
3748 /* SIMD mm to xmm */
3749 case XMMMX:
3750 wbit = MM_OPND;
3751 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3752 break;
3753
3754 /* SIMD memory or xmm reg to mm reg */
3755 case XMMXMM:
3756 case XMMOXMM:
3757 case XMMXM:
3758 wbit = XMM_OPND;
3759 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
3760 break;
3761
3762
3763 /* SIMD memory or xmm reg to r32 */
3764 case XMMXM3:
3765 wbit = XMM_OPND;
3766 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
3767 break;
3768
3769 /* SIMD xmm to r32 */
3770 case XMMX3:
3771 case XMMOX3:
3772 dtrace_get_modrm(x, &mode, &reg, &r_m);
3773 if (mode != REG_ONLY)
3774 goto error;
3775 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3776 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
3777 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3778 NOMEM;
3779 break;
3780
3781 /* SIMD predicated memory or xmm reg with/to xmm reg */
3782 case XMMP:
3783 case XMMP_66r:
3784 case XMMP_66o:
3785 case XMMOPM:
3786 wbit = XMM_OPND;
3787 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1,
3788 1);
3789
3790 #ifdef DIS_TEXT
3791 /*
3792 * cmpps and cmpss vary their instruction name based
3793 * on the value of imm8. Other XMMP instructions,
3794 * such as shufps, require explicit specification of
3795 * the predicate.
3796 */
3797 if (dp->it_name[0] == 'c' &&
3798 dp->it_name[1] == 'm' &&
3799 dp->it_name[2] == 'p' &&
3800 strlen(dp->it_name) == 5) {
3801 uchar_t pred = x->d86_opnd[0].d86_value & 0xff;
3802
3803 if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *)))
3804 goto error;
3805
3806 (void) strncpy(x->d86_mnem, "cmp", OPLEN);
3807 x->d86_mnem[OPLEN - 1] = '\0';
3808 (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred],
3809 OPLEN);
3810 (void) strlcat(x->d86_mnem,
3811 dp->it_name + strlen(dp->it_name) - 2,
3812 OPLEN);
3813 x->d86_opnd[0] = x->d86_opnd[1];
3814 x->d86_opnd[1] = x->d86_opnd[2];
3815 x->d86_numopnds = 2;
3816 }
3817 #endif
3818 break;
3819
3820 case XMMX2I:
3821 FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND,
3822 1);
3823 NOMEM;
3824 break;
3825
3826 case XMM2I:
3827 ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1);
3828 NOMEM;
3829 break;
3830
3831 /* immediate operand to accumulator */
3832 case IA:
3833 wbit = WBIT(opcode2);
3834 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
3835 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
3836 NOMEM;
3837 break;
3838
3839 /* memory or register operand to accumulator */
3840 case MA:
3841 wbit = WBIT(opcode2);
3842 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3843 dtrace_get_operand(x, mode, r_m, wbit, 0);
3844 break;
3845
3846 /* si register to di register used to reference memory */
3847 case SD:
3848 #ifdef DIS_TEXT
3849 dtrace_check_override(x, 0);
3850 x->d86_numopnds = 2;
3851 if (addr_size == SIZE64) {
3852 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
3853 OPLEN);
3854 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
3855 OPLEN);
3856 } else if (addr_size == SIZE32) {
3857 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
3858 OPLEN);
3859 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
3860 OPLEN);
3861 } else {
3862 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
3863 OPLEN);
3864 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
3865 OPLEN);
3866 }
3867 #endif
3868 wbit = LONG_OPND;
3869 break;
3870
3871 /* accumulator to di register */
3872 case AD:
3873 wbit = WBIT(opcode2);
3874 #ifdef DIS_TEXT
3875 dtrace_check_override(x, 1);
3876 x->d86_numopnds = 2;
3877 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0);
3878 if (addr_size == SIZE64)
3879 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
3880 OPLEN);
3881 else if (addr_size == SIZE32)
3882 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
3883 OPLEN);
3884 else
3885 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
3886 OPLEN);
3887 #endif
3888 break;
3889
3890 /* si register to accumulator */
3891 case SA:
3892 wbit = WBIT(opcode2);
3893 #ifdef DIS_TEXT
3894 dtrace_check_override(x, 0);
3895 x->d86_numopnds = 2;
3896 if (addr_size == SIZE64)
3897 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
3898 OPLEN);
3899 else if (addr_size == SIZE32)
3900 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
3901 OPLEN);
3902 else
3903 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
3904 OPLEN);
3905 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
3906 #endif
3907 break;
3908
3909 /*
3910 * single operand, a 16/32 bit displacement
3911 */
3912 case D:
3913 wbit = LONG_OPND;
3914 dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
3915 NOMEM;
3916 break;
3917
3918 /* jmp/call indirect to memory or register operand */
3919 case INM:
3920 #ifdef DIS_TEXT
3921 (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN);
3922 #endif
3923 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3924 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
3925 wbit = LONG_OPND;
3926 break;
3927
3928 /*
3929 * for long jumps and long calls -- a new code segment
3930 * register and an offset in IP -- stored in object
3931 * code in reverse order. Note - not valid in amd64
3932 */
3933 case SO:
3934 dtrace_check_override(x, 1);
3935 wbit = LONG_OPND;
3936 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1);
3937 #ifdef DIS_TEXT
3938 x->d86_opnd[1].d86_mode = MODE_SIGNED;
3939 #endif
3940 /* will now get segment operand */
3941 dtrace_imm_opnd(x, wbit, 2, 0);
3942 break;
3943
3944 /*
3945 * jmp/call. single operand, 8 bit displacement.
3946 * added to current EIP in 'compofff'
3947 */
3948 case BD:
3949 dtrace_disp_opnd(x, BYTE_OPND, 1, 0);
3950 NOMEM;
3951 break;
3952
3953 /* single 32/16 bit immediate operand */
3954 case I:
3955 wbit = LONG_OPND;
3956 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
3957 break;
3958
3959 /* single 8 bit immediate operand */
3960 case Ib:
3961 wbit = LONG_OPND;
3962 dtrace_imm_opnd(x, wbit, 1, 0);
3963 break;
3964
3965 case ENTER:
3966 wbit = LONG_OPND;
3967 dtrace_imm_opnd(x, wbit, 2, 0);
3968 dtrace_imm_opnd(x, wbit, 1, 1);
3969 switch (opnd_size) {
3970 case SIZE64:
3971 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8;
3972 break;
3973 case SIZE32:
3974 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4;
3975 break;
3976 case SIZE16:
3977 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2;
3978 break;
3979 }
3980
3981 break;
3982
3983 /* 16-bit immediate operand */
3984 case RET:
3985 wbit = LONG_OPND;
3986 dtrace_imm_opnd(x, wbit, 2, 0);
3987 break;
3988
3989 /* single 8 bit port operand */
3990 case P:
3991 dtrace_check_override(x, 0);
3992 dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
3993 NOMEM;
3994 break;
3995
3996 /* single operand, dx register (variable port instruction) */
3997 case V:
3998 x->d86_numopnds = 1;
3999 dtrace_check_override(x, 0);
4000 #ifdef DIS_TEXT
4001 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN);
4002 #endif
4003 NOMEM;
4004 break;
4005
4006 /*
4007 * The int instruction, which has two forms:
4008 * int 3 (breakpoint) or
4009 * int n, where n is indicated in the subsequent
4010 * byte (format Ib). The int 3 instruction (opcode 0xCC),
4011 * where, although the 3 looks like an operand,
4012 * it is implied by the opcode. It must be converted
4013 * to the correct base and output.
4014 */
4015 case INT3:
4016 #ifdef DIS_TEXT
4017 x->d86_numopnds = 1;
4018 x->d86_opnd[0].d86_mode = MODE_SIGNED;
4019 x->d86_opnd[0].d86_value_size = 1;
4020 x->d86_opnd[0].d86_value = 3;
4021 #endif
4022 NOMEM;
4023 break;
4024
4025 /* single 8 bit immediate operand */
4026 case INTx:
4027 dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
4028 NOMEM;
4029 break;
4030
4031 /* an unused byte must be discarded */
4032 case U:
4033 if (x->d86_get_byte(x->d86_data) < 0)
4034 goto error;
4035 x->d86_len++;
4036 NOMEM;
4037 break;
4038
4039 case CBW:
4040 #ifdef DIS_TEXT
4041 if (opnd_size == SIZE16)
4042 (void) strlcat(x->d86_mnem, "cbtw", OPLEN);
4043 else if (opnd_size == SIZE32)
4044 (void) strlcat(x->d86_mnem, "cwtl", OPLEN);
4045 else
4046 (void) strlcat(x->d86_mnem, "cltq", OPLEN);
4047 #endif
4048 wbit = LONG_OPND;
4049 NOMEM;
4050 break;
4051
4052 case CWD:
4053 #ifdef DIS_TEXT
4054 if (opnd_size == SIZE16)
4055 (void) strlcat(x->d86_mnem, "cwtd", OPLEN);
4056 else if (opnd_size == SIZE32)
4057 (void) strlcat(x->d86_mnem, "cltd", OPLEN);
4058 else
4059 (void) strlcat(x->d86_mnem, "cqtd", OPLEN);
4060 #endif
4061 wbit = LONG_OPND;
4062 NOMEM;
4063 break;
4064
4065 case XMMSFNC:
4066 /*
4067 * sfence is sfence if mode is REG_ONLY. If mode isn't
4068 * REG_ONLY, mnemonic should be 'clflush'.
4069 */
4070 dtrace_get_modrm(x, &mode, &reg, &r_m);
4071
4072 /* sfence doesn't take operands */
4073 #ifdef DIS_TEXT
4074 if (mode == REG_ONLY) {
4075 (void) strlcat(x->d86_mnem, "sfence", OPLEN);
4076 } else {
4077 (void) strlcat(x->d86_mnem, "clflush", OPLEN);
4078 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4079 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
4080 NOMEM;
4081 }
4082 #else
4083 if (mode != REG_ONLY) {
4084 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4085 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4086 NOMEM;
4087 }
4088 #endif
4089 break;
4090
4091 /*
4092 * no disassembly, the mnemonic was all there was so go on
4093 */
4094 case NORM:
4095 if (dp->it_invalid32 && cpu_mode != SIZE64)
4096 goto error;
4097 NOMEM;
4098 /*FALLTHROUGH*/
4099 case IMPLMEM:
4100 break;
4101
4102 case XMMFENCE:
4103 /*
4104 * XRSTOR and LFENCE share the same opcode but differ in mode
4105 */
4106 dtrace_get_modrm(x, &mode, &reg, &r_m);
4107
4108 if (mode == REG_ONLY) {
4109 /*
4110 * Only the following exact byte sequences are allowed:
4111 *
4112 * 0f ae e8 lfence
4113 * 0f ae f0 mfence
4114 */
4115 if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 &&
4116 (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0)
4117 goto error;
4118 } else {
4119 #ifdef DIS_TEXT
4120 (void) strncpy(x->d86_mnem, "xrstor", OPLEN);
4121 #endif
4122 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4123 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
4124 }
4125 break;
4126
4127
4128 /* float reg */
4129 case F:
4130 #ifdef DIS_TEXT
4131 x->d86_numopnds = 1;
4132 (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN);
4133 x->d86_opnd[0].d86_opnd[4] = r_m + '0';
4134 #endif
4135 NOMEM;
4136 break;
4137
4138 /* float reg to float reg, with ret bit present */
4139 case FF:
4140 vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */
4141 /*FALLTHROUGH*/
4142 case FFC: /* case for vbit always = 0 */
4143 #ifdef DIS_TEXT
4144 x->d86_numopnds = 2;
4145 (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN);
4146 (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN);
4147 x->d86_opnd[vbit].d86_opnd[4] = r_m + '0';
4148 #endif
4149 NOMEM;
4150 break;
4151
4152 /* AVX instructions */
4153 case VEX_MO:
4154 /* op(ModR/M.r/m) */
4155 x->d86_numopnds = 1;
4156 dtrace_get_modrm(x, &mode, &reg, &r_m);
4157 #ifdef DIS_TEXT
4158 if ((dp == &dis_opAVX0F[0xA][0xE]) && (reg == 3))
4159 (void) strncpy(x->d86_mnem, "vstmxcsr", OPLEN);
4160 #endif
4161 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4162 dtrace_get_operand(x, mode, r_m, wbit, 0);
4163 break;
4164 case VEX_RMrX:
4165 /* ModR/M.reg := op(VEX.vvvv, ModR/M.r/m) */
4166 x->d86_numopnds = 3;
4167 dtrace_get_modrm(x, &mode, &reg, &r_m);
4168 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4169
4170 if (mode != REG_ONLY) {
4171 if ((dp == &dis_opAVXF20F[0x10]) ||
4172 (dp == &dis_opAVXF30F[0x10])) {
4173 /* vmovsd <m64>, <xmm> */
4174 /* or vmovss <m64>, <xmm> */
4175 x->d86_numopnds = 2;
4176 goto L_VEX_MX;
4177 }
4178 }
4179
4180 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4181 /*
4182 * VEX prefix uses the 1's complement form to encode the
4183 * XMM/YMM regs
4184 */
4185 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4186
4187 if ((dp == &dis_opAVXF20F[0x2A]) ||
4188 (dp == &dis_opAVXF30F[0x2A])) {
4189 /*
4190 * vcvtsi2si </r,m>, <xmm>, <xmm> or vcvtsi2ss </r,m>,
4191 * <xmm>, <xmm>
4192 */
4193 wbit = LONG_OPND;
4194 }
4195 #ifdef DIS_TEXT
4196 else if ((mode == REG_ONLY) &&
4197 (dp == &dis_opAVX0F[0x1][0x6])) { /* vmovlhps */
4198 (void) strncpy(x->d86_mnem, "vmovlhps", OPLEN);
4199 } else if ((mode == REG_ONLY) &&
4200 (dp == &dis_opAVX0F[0x1][0x2])) { /* vmovhlps */
4201 (void) strncpy(x->d86_mnem, "vmovhlps", OPLEN);
4202 }
4203 #endif
4204 dtrace_get_operand(x, mode, r_m, wbit, 0);
4205
4206 break;
4207
4208 case VEX_RRX:
4209 /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */
4210 x->d86_numopnds = 3;
4211
4212 dtrace_get_modrm(x, &mode, &reg, &r_m);
4213 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4214
4215 if (mode != REG_ONLY) {
4216 if ((dp == &dis_opAVXF20F[0x11]) ||
4217 (dp == &dis_opAVXF30F[0x11])) {
4218 /* vmovsd <xmm>, <m64> */
4219 /* or vmovss <xmm>, <m64> */
4220 x->d86_numopnds = 2;
4221 goto L_VEX_RM;
4222 }
4223 }
4224
4225 dtrace_get_operand(x, mode, r_m, wbit, 2);
4226 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4227 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4228 break;
4229
4230 case VEX_RMRX:
4231 /* ModR/M.reg := op(VEX.vvvv, ModR/M.r_m, imm8[7:4]) */
4232 x->d86_numopnds = 4;
4233
4234 dtrace_get_modrm(x, &mode, &reg, &r_m);
4235 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4236 dtrace_get_operand(x, REG_ONLY, reg, wbit, 3);
4237 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2);
4238 if (dp == &dis_opAVX660F3A[0x18]) {
4239 /* vinsertf128 <imm8>, <xmm>, <ymm>, <ymm> */
4240 dtrace_get_operand(x, mode, r_m, XMM_OPND, 1);
4241 } else if ((dp == &dis_opAVX660F3A[0x20]) ||
4242 (dp == & dis_opAVX660F[0xC4])) {
4243 /* vpinsrb <imm8>, <reg/mm>, <xmm>, <xmm> */
4244 /* or vpinsrw <imm8>, <reg/mm>, <xmm>, <xmm> */
4245 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4246 } else if (dp == &dis_opAVX660F3A[0x22]) {
4247 /* vpinsrd/q <imm8>, <reg/mm>, <xmm>, <xmm> */
4248 #ifdef DIS_TEXT
4249 if (vex_W)
4250 x->d86_mnem[6] = 'q';
4251 #endif
4252 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4253 } else {
4254 dtrace_get_operand(x, mode, r_m, wbit, 1);
4255 }
4256
4257 /* one byte immediate number */
4258 dtrace_imm_opnd(x, wbit, 1, 0);
4259
4260 /* vblendvpd, vblendvps, vblendvb use the imm encode the regs */
4261 if ((dp == &dis_opAVX660F3A[0x4A]) ||
4262 (dp == &dis_opAVX660F3A[0x4B]) ||
4263 (dp == &dis_opAVX660F3A[0x4C])) {
4264 #ifdef DIS_TEXT
4265 int regnum = (x->d86_opnd[0].d86_value & 0xF0) >> 4;
4266 #endif
4267 x->d86_opnd[0].d86_mode = MODE_NONE;
4268 #ifdef DIS_TEXT
4269 if (vex_L)
4270 (void) strncpy(x->d86_opnd[0].d86_opnd,
4271 dis_YMMREG[regnum], OPLEN);
4272 else
4273 (void) strncpy(x->d86_opnd[0].d86_opnd,
4274 dis_XMMREG[regnum], OPLEN);
4275 #endif
4276 }
4277 break;
4278
4279 case VEX_MX:
4280 /* ModR/M.reg := op(ModR/M.rm) */
4281 x->d86_numopnds = 2;
4282
4283 dtrace_get_modrm(x, &mode, &reg, &r_m);
4284 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4285 L_VEX_MX:
4286
4287 if ((dp == &dis_opAVXF20F[0xE6]) ||
4288 (dp == &dis_opAVX660F[0x5A]) ||
4289 (dp == &dis_opAVX660F[0xE6])) {
4290 /* vcvtpd2dq <ymm>, <xmm> */
4291 /* or vcvtpd2ps <ymm>, <xmm> */
4292 /* or vcvttpd2dq <ymm>, <xmm> */
4293 dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1);
4294 dtrace_get_operand(x, mode, r_m, wbit, 0);
4295 } else if ((dp == &dis_opAVXF30F[0xE6]) ||
4296 (dp == &dis_opAVX0F[0x5][0xA]) ||
4297 (dp == &dis_opAVX660F38[0x58]) ||
4298 (dp == &dis_opAVX660F38[0x59]) ||
4299 (dp == &dis_opAVX660F38[0x78]) ||
4300 (dp == &dis_opAVX660F38[0x79])) {
4301 /* vcvtdq2pd <xmm>, <ymm> */
4302 /* or vcvtps2pd <xmm>, <ymm> */
4303 /* or vbroadcasts* <xmm>, <ymm> */
4304 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4305 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
4306 } else if (dp == &dis_opAVX660F[0x6E]) {
4307 /* vmovd/q <reg/mem 32/64>, <xmm> */
4308 #ifdef DIS_TEXT
4309 if (vex_W)
4310 x->d86_mnem[4] = 'q';
4311 #endif
4312 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4313 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4314 } else {
4315 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4316 dtrace_get_operand(x, mode, r_m, wbit, 0);
4317 }
4318
4319 break;
4320
4321 case VEX_MXI:
4322 /* ModR/M.reg := op(ModR/M.rm, imm8) */
4323 x->d86_numopnds = 3;
4324
4325 dtrace_get_modrm(x, &mode, &reg, &r_m);
4326 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4327
4328 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4329 dtrace_get_operand(x, mode, r_m, wbit, 1);
4330
4331 /* one byte immediate number */
4332 dtrace_imm_opnd(x, wbit, 1, 0);
4333 break;
4334
4335 case VEX_XXI:
4336 /* VEX.vvvv := op(ModR/M.rm, imm8) */
4337 x->d86_numopnds = 3;
4338
4339 dtrace_get_modrm(x, &mode, &reg, &r_m);
4340 #ifdef DIS_TEXT
4341 (void) strncpy(x->d86_mnem, dis_AVXvgrp7[opcode2 - 1][reg],
4342 OPLEN);
4343 #endif
4344 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4345
4346 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2);
4347 dtrace_get_operand(x, REG_ONLY, r_m, wbit, 1);
4348
4349 /* one byte immediate number */
4350 dtrace_imm_opnd(x, wbit, 1, 0);
4351 break;
4352
4353 case VEX_MR:
4354 /* ModR/M.reg (reg32/64) := op(ModR/M.rm) */
4355 if (dp == &dis_opAVX660F[0xC5]) {
4356 /* vpextrw <imm8>, <xmm>, <reg> */
4357 x->d86_numopnds = 2;
4358 vbit = 2;
4359 } else {
4360 x->d86_numopnds = 2;
4361 vbit = 1;
4362 }
4363
4364 dtrace_get_modrm(x, &mode, &reg, &r_m);
4365 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4366 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, vbit);
4367 dtrace_get_operand(x, mode, r_m, wbit, vbit - 1);
4368
4369 if (vbit == 2)
4370 dtrace_imm_opnd(x, wbit, 1, 0);
4371
4372 break;
4373
4374 case VEX_RRI:
4375 /* implicit(eflags/r32) := op(ModR/M.reg, ModR/M.rm) */
4376 x->d86_numopnds = 2;
4377
4378 dtrace_get_modrm(x, &mode, &reg, &r_m);
4379 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4380 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4381 dtrace_get_operand(x, mode, r_m, wbit, 0);
4382 break;
4383
4384 case VEX_RX:
4385 /* ModR/M.rm := op(ModR/M.reg) */
4386 if (dp == &dis_opAVX660F3A[0x19]) { /* vextractf128 */
4387 x->d86_numopnds = 3;
4388
4389 dtrace_get_modrm(x, &mode, &reg, &r_m);
4390 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4391
4392 dtrace_get_operand(x, mode, r_m, XMM_OPND, 2);
4393 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4394
4395 /* one byte immediate number */
4396 dtrace_imm_opnd(x, wbit, 1, 0);
4397 break;
4398 }
4399
4400 x->d86_numopnds = 2;
4401
4402 dtrace_get_modrm(x, &mode, &reg, &r_m);
4403 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4404 dtrace_get_operand(x, mode, r_m, wbit, 1);
4405 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4406 break;
4407
4408 case VEX_RR:
4409 /* ModR/M.rm := op(ModR/M.reg) */
4410 x->d86_numopnds = 2;
4411
4412 dtrace_get_modrm(x, &mode, &reg, &r_m);
4413 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4414
4415 if (dp == &dis_opAVX660F[0x7E]) {
4416 /* vmovd/q <reg/mem 32/64>, <xmm> */
4417 #ifdef DIS_TEXT
4418 if (vex_W)
4419 x->d86_mnem[4] = 'q';
4420 #endif
4421 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4422 } else
4423 dtrace_get_operand(x, mode, r_m, wbit, 1);
4424
4425 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4426 break;
4427
4428 case VEX_RRi:
4429 /* ModR/M.rm := op(ModR/M.reg, imm) */
4430 x->d86_numopnds = 3;
4431
4432 dtrace_get_modrm(x, &mode, &reg, &r_m);
4433 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4434
4435 #ifdef DIS_TEXT
4436 if (dp == &dis_opAVX660F3A[0x16]) {
4437 /* vpextrd/q <imm>, <xmm>, <reg/mem 32/64> */
4438 if (vex_W)
4439 x->d86_mnem[6] = 'q';
4440 }
4441 #endif
4442 dtrace_get_operand(x, mode, r_m, LONG_OPND, 2);
4443 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4444
4445 /* one byte immediate number */
4446 dtrace_imm_opnd(x, wbit, 1, 0);
4447 break;
4448
4449 case VEX_RIM:
4450 /* ModR/M.rm := op(ModR/M.reg, imm) */
4451 x->d86_numopnds = 3;
4452
4453 dtrace_get_modrm(x, &mode, &reg, &r_m);
4454 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4455
4456 dtrace_get_operand(x, mode, r_m, XMM_OPND, 2);
4457 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4458 /* one byte immediate number */
4459 dtrace_imm_opnd(x, wbit, 1, 0);
4460 break;
4461
4462 case VEX_RM:
4463 /* ModR/M.rm := op(ModR/M.reg) */
4464 if (dp == &dis_opAVX660F3A[0x17]) { /* vextractps */
4465 x->d86_numopnds = 3;
4466
4467 dtrace_get_modrm(x, &mode, &reg, &r_m);
4468 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4469
4470 dtrace_get_operand(x, mode, r_m, LONG_OPND, 2);
4471 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4472 /* one byte immediate number */
4473 dtrace_imm_opnd(x, wbit, 1, 0);
4474 break;
4475 }
4476 x->d86_numopnds = 2;
4477
4478 dtrace_get_modrm(x, &mode, &reg, &r_m);
4479 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4480 L_VEX_RM:
4481 vbit = 1;
4482 dtrace_get_operand(x, mode, r_m, wbit, vbit);
4483 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit - 1);
4484
4485 break;
4486
4487 case VEX_RRM:
4488 /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */
4489 x->d86_numopnds = 3;
4490
4491 dtrace_get_modrm(x, &mode, &reg, &r_m);
4492 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4493 dtrace_get_operand(x, mode, r_m, wbit, 2);
4494 /* VEX use the 1's complement form encode the XMM/YMM regs */
4495 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4496 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4497 break;
4498
4499 case VEX_RMX:
4500 /* ModR/M.reg := op(VEX.vvvv, ModR/M.rm) */
4501 x->d86_numopnds = 3;
4502
4503 dtrace_get_modrm(x, &mode, &reg, &r_m);
4504 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4505 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4506 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4507 dtrace_get_operand(x, REG_ONLY, r_m, wbit, 0);
4508 break;
4509
4510 case VEX_NONE:
4511 #ifdef DIS_TEXT
4512 if (vex_L)
4513 (void) strncpy(x->d86_mnem, "vzeroall", OPLEN);
4514 #endif
4515 break;
4516
4517 /* an invalid op code */
4518 case AM:
4519 case DM:
4520 case OVERRIDE:
4521 case PREFIX:
4522 case UNKNOWN:
4523 NOMEM;
4524 default:
4525 goto error;
4526 } /* end switch */
4527 if (x->d86_error)
4528 goto error;
4529
4530 done:
4531 #ifdef DIS_MEM
4532 /*
4533 * compute the size of any memory accessed by the instruction
4534 */
4535 if (x->d86_memsize != 0) {
4536 return (0);
4537 } else if (dp->it_stackop) {
4538 switch (opnd_size) {
4539 case SIZE16:
4540 x->d86_memsize = 2;
4541 break;
4542 case SIZE32:
4543 x->d86_memsize = 4;
4544 break;
4545 case SIZE64:
4546 x->d86_memsize = 8;
4547 break;
4548 }
4549 } else if (nomem || mode == REG_ONLY) {
4550 x->d86_memsize = 0;
4551
4552 } else if (dp->it_size != 0) {
4553 /*
4554 * In 64 bit mode descriptor table entries
4555 * go up to 10 bytes and popf/pushf are always 8 bytes
4556 */
4557 if (x->d86_mode == SIZE64 && dp->it_size == 6)
4558 x->d86_memsize = 10;
4559 else if (x->d86_mode == SIZE64 && opcode1 == 0x9 &&
4560 (opcode2 == 0xc || opcode2 == 0xd))
4561 x->d86_memsize = 8;
4562 else
4563 x->d86_memsize = dp->it_size;
4564
4565 } else if (wbit == 0) {
4566 x->d86_memsize = 1;
4567
4568 } else if (wbit == LONG_OPND) {
4569 if (opnd_size == SIZE64)
4570 x->d86_memsize = 8;
4571 else if (opnd_size == SIZE32)
4572 x->d86_memsize = 4;
4573 else
4574 x->d86_memsize = 2;
4575
4576 } else if (wbit == SEG_OPND) {
4577 x->d86_memsize = 4;
4578
4579 } else {
4580 x->d86_memsize = 8;
4581 }
4582 #endif
4583 return (0);
4584
4585 error:
4586 #ifdef DIS_TEXT
4587 (void) strlcat(x->d86_mnem, "undef", OPLEN);
4588 #endif
4589 return (1);
4590 }
4591
4592 #ifdef DIS_TEXT
4593
4594 /*
4595 * Some instructions should have immediate operands printed
4596 * as unsigned integers. We compare against this table.
4597 */
4598 static char *unsigned_ops[] = {
4599 "or", "and", "xor", "test", "in", "out", "lcall", "ljmp",
4600 "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl",
4601 0
4602 };
4603
4604
4605 static int
4606 isunsigned_op(char *opcode)
4607 {
4608 char *where;
4609 int i;
4610 int is_unsigned = 0;
4611
4612 /*
4613 * Work back to start of last mnemonic, since we may have
4614 * prefixes on some opcodes.
4615 */
4616 where = opcode + strlen(opcode) - 1;
4617 while (where > opcode && *where != ' ')
4618 --where;
4619 if (*where == ' ')
4620 ++where;
4621
4622 for (i = 0; unsigned_ops[i]; ++i) {
4623 if (strncmp(where, unsigned_ops[i],
4624 strlen(unsigned_ops[i])))
4625 continue;
4626 is_unsigned = 1;
4627 break;
4628 }
4629 return (is_unsigned);
4630 }
4631
4632 /*
4633 * Print a numeric immediate into end of buf, maximum length buflen.
4634 * The immediate may be an address or a displacement. Mask is set
4635 * for address size. If the immediate is a "small negative", or
4636 * if it's a negative displacement of any magnitude, print as -<absval>.
4637 * Respect the "octal" flag. "Small negative" is defined as "in the
4638 * interval [NEG_LIMIT, 0)".
4639 *
4640 * Also, "isunsigned_op()" instructions never print negatives.
4641 *
4642 * Return whether we decided to print a negative value or not.
4643 */
4644
4645 #define NEG_LIMIT -255
4646 enum {IMM, DISP};
4647 enum {POS, TRY_NEG};
4648
4649 static int
4650 print_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf,
4651 size_t buflen, int disp, int try_neg)
4652 {
4653 int curlen;
4654 int64_t sv = (int64_t)usv;
4655 int octal = dis->d86_flags & DIS_F_OCTAL;
4656
4657 curlen = strlen(buf);
4658
4659 if (try_neg == TRY_NEG && sv < 0 &&
4660 (disp || sv >= NEG_LIMIT) &&
4661 !isunsigned_op(dis->d86_mnem)) {
4662 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4663 octal ? "-0%llo" : "-0x%llx", (-sv) & mask);
4664 return (1);
4665 } else {
4666 if (disp == DISP)
4667 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4668 octal ? "+0%llo" : "+0x%llx", usv & mask);
4669 else
4670 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4671 octal ? "0%llo" : "0x%llx", usv & mask);
4672 return (0);
4673
4674 }
4675 }
4676
4677
4678 static int
4679 log2(int size)
4680 {
4681 switch (size) {
4682 case 1: return (0);
4683 case 2: return (1);
4684 case 4: return (2);
4685 case 8: return (3);
4686 }
4687 return (0);
4688 }
4689
4690 /* ARGSUSED */
4691 void
4692 dtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf,
4693 size_t buflen)
4694 {
4695 uint64_t reltgt = 0;
4696 uint64_t tgt = 0;
4697 int curlen;
4698 int (*lookup)(void *, uint64_t, char *, size_t);
4699 int i;
4700 int64_t sv;
4701 uint64_t usv, mask, save_mask, save_usv;
4702 static uint64_t masks[] =
4703 {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL};
4704 save_usv = 0;
4705
4706 dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem);
4707
4708 /*
4709 * For PC-relative jumps, the pc is really the next pc after executing
4710 * this instruction, so increment it appropriately.
4711 */
4712 pc += dis->d86_len;
4713
4714 for (i = 0; i < dis->d86_numopnds; i++) {
4715 d86opnd_t *op = &dis->d86_opnd[i];
4716
4717 if (i != 0)
4718 (void) strlcat(buf, ",", buflen);
4719
4720 (void) strlcat(buf, op->d86_prefix, buflen);
4721
4722 /*
4723 * sv is for the signed, possibly-truncated immediate or
4724 * displacement; usv retains the original size and
4725 * unsignedness for symbol lookup.
4726 */
4727
4728 sv = usv = op->d86_value;
4729
4730 /*
4731 * About masks: for immediates that represent
4732 * addresses, the appropriate display size is
4733 * the effective address size of the instruction.
4734 * This includes MODE_OFFSET, MODE_IPREL, and
4735 * MODE_RIPREL. Immediates that are simply
4736 * immediate values should display in the operand's
4737 * size, however, since they don't represent addresses.
4738 */
4739
4740 /* d86_addr_size is SIZEnn, which is log2(real size) */
4741 mask = masks[dis->d86_addr_size];
4742
4743 /* d86_value_size and d86_imm_bytes are in bytes */
4744 if (op->d86_mode == MODE_SIGNED ||
4745 op->d86_mode == MODE_IMPLIED)
4746 mask = masks[log2(op->d86_value_size)];
4747
4748 switch (op->d86_mode) {
4749
4750 case MODE_NONE:
4751
4752 (void) strlcat(buf, op->d86_opnd, buflen);
4753 break;
4754
4755 case MODE_SIGNED:
4756 case MODE_IMPLIED:
4757 case MODE_OFFSET:
4758
4759 tgt = usv;
4760
4761 if (dis->d86_seg_prefix)
4762 (void) strlcat(buf, dis->d86_seg_prefix,
4763 buflen);
4764
4765 if (op->d86_mode == MODE_SIGNED ||
4766 op->d86_mode == MODE_IMPLIED) {
4767 (void) strlcat(buf, "$", buflen);
4768 }
4769
4770 if (print_imm(dis, usv, mask, buf, buflen,
4771 IMM, TRY_NEG) &&
4772 (op->d86_mode == MODE_SIGNED ||
4773 op->d86_mode == MODE_IMPLIED)) {
4774
4775 /*
4776 * We printed a negative value for an
4777 * immediate that wasn't a
4778 * displacement. Note that fact so we can
4779 * print the positive value as an
4780 * annotation.
4781 */
4782
4783 save_usv = usv;
4784 save_mask = mask;
4785 }
4786 (void) strlcat(buf, op->d86_opnd, buflen);
4787
4788 break;
4789
4790 case MODE_IPREL:
4791 case MODE_RIPREL:
4792
4793 reltgt = pc + sv;
4794
4795 switch (mode) {
4796 case SIZE16:
4797 reltgt = (uint16_t)reltgt;
4798 break;
4799 case SIZE32:
4800 reltgt = (uint32_t)reltgt;
4801 break;
4802 }
4803
4804 (void) print_imm(dis, usv, mask, buf, buflen,
4805 DISP, TRY_NEG);
4806
4807 if (op->d86_mode == MODE_RIPREL)
4808 (void) strlcat(buf, "(%rip)", buflen);
4809 break;
4810 }
4811 }
4812
4813 /*
4814 * The symbol lookups may result in false positives,
4815 * particularly on object files, where small numbers may match
4816 * the 0-relative non-relocated addresses of symbols.
4817 */
4818
4819 lookup = dis->d86_sym_lookup;
4820 if (tgt != 0) {
4821 if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 &&
4822 lookup(dis->d86_data, tgt, NULL, 0) == 0) {
4823 (void) strlcat(buf, "\t<", buflen);
4824 curlen = strlen(buf);
4825 lookup(dis->d86_data, tgt, buf + curlen,
4826 buflen - curlen);
4827 (void) strlcat(buf, ">", buflen);
4828 }
4829
4830 /*
4831 * If we printed a negative immediate above, print the
4832 * positive in case our heuristic was unhelpful
4833 */
4834 if (save_usv) {
4835 (void) strlcat(buf, "\t<", buflen);
4836 (void) print_imm(dis, save_usv, save_mask, buf, buflen,
4837 IMM, POS);
4838 (void) strlcat(buf, ">", buflen);
4839 }
4840 }
4841
4842 if (reltgt != 0) {
4843 /* Print symbol or effective address for reltgt */
4844
4845 (void) strlcat(buf, "\t<", buflen);
4846 curlen = strlen(buf);
4847 lookup(dis->d86_data, reltgt, buf + curlen,
4848 buflen - curlen);
4849 (void) strlcat(buf, ">", buflen);
4850 }
4851 }
4852
4853 #endif /* DIS_TEXT */