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