Deleted Added
full compact
dis_tables.c (265273) dis_tables.c (270186)
1/*
2 *
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
1/*
2 *
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
24 */
25
26/*
27 * Copyright (c) 2010, Intel Corporation.
28 * All rights reserved.
29 */
30
31/* Copyright (c) 1988 AT&T */
32/* All Rights Reserved */
33
34/*
25 */
26
27/*
28 * Copyright (c) 2010, Intel Corporation.
29 * All rights reserved.
30 */
31
32/* Copyright (c) 1988 AT&T */
33/* All Rights Reserved */
34
35/*
35 * $FreeBSD: stable/10/sys/cddl/dev/dtrace/x86/dis_tables.c 262542 2014-02-27 01:04:35Z markj $
36 * $FreeBSD: stable/10/sys/cddl/dev/dtrace/x86/dis_tables.c 270186 2014-08-19 23:15:47Z grehan $
36 */
37
38#include "dis_tables.h"
39
40/* BEGIN CSTYLED */
41
42/*
43 * Disassembly begins in dis_distable, which is equivalent to the One-byte
44 * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy). The
45 * decoding loops then traverse out through the other tables as necessary to
46 * decode a given instruction.
47 *
48 * The behavior of this file can be controlled by one of the following flags:
49 *
50 * DIS_TEXT Include text for disassembly
51 * DIS_MEM Include memory-size calculations
52 *
53 * Either or both of these can be defined.
54 *
55 * This file is not, and will never be, cstyled. If anything, the tables should
56 * be taken out another tab stop or two so nothing overlaps.
57 */
58
59/*
60 * These functions must be provided for the consumer to do disassembly.
61 */
62#ifdef DIS_TEXT
63extern char *strncpy(char *, const char *, size_t);
64extern size_t strlen(const char *);
65extern int strcmp(const char *, const char *);
66extern int strncmp(const char *, const char *, size_t);
67extern size_t strlcat(char *, const char *, size_t);
68#endif
69
70
71#define TERM 0 /* used to indicate that the 'indirect' */
72 /* field terminates - no pointer. */
73
74/* Used to decode instructions. */
75typedef struct instable {
76 struct instable *it_indirect; /* for decode op codes */
77 uchar_t it_adrmode;
78#ifdef DIS_TEXT
79 char it_name[NCPS];
80 uint_t it_suffix:1; /* mnem + "w", "l", or "d" */
81#endif
82#ifdef DIS_MEM
83 uint_t it_size:16;
84#endif
85 uint_t it_invalid64:1; /* opcode invalid in amd64 */
86 uint_t it_always64:1; /* 64 bit when in 64 bit mode */
87 uint_t it_invalid32:1; /* invalid in IA32 */
88 uint_t it_stackop:1; /* push/pop stack operation */
89} instable_t;
90
91/*
92 * Instruction formats.
93 */
94enum {
95 UNKNOWN,
96 MRw,
97 IMlw,
98 IMw,
99 IR,
100 OA,
101 AO,
102 MS,
103 SM,
104 Mv,
105 Mw,
106 M, /* register or memory */
37 */
38
39#include "dis_tables.h"
40
41/* BEGIN CSTYLED */
42
43/*
44 * Disassembly begins in dis_distable, which is equivalent to the One-byte
45 * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy). The
46 * decoding loops then traverse out through the other tables as necessary to
47 * decode a given instruction.
48 *
49 * The behavior of this file can be controlled by one of the following flags:
50 *
51 * DIS_TEXT Include text for disassembly
52 * DIS_MEM Include memory-size calculations
53 *
54 * Either or both of these can be defined.
55 *
56 * This file is not, and will never be, cstyled. If anything, the tables should
57 * be taken out another tab stop or two so nothing overlaps.
58 */
59
60/*
61 * These functions must be provided for the consumer to do disassembly.
62 */
63#ifdef DIS_TEXT
64extern char *strncpy(char *, const char *, size_t);
65extern size_t strlen(const char *);
66extern int strcmp(const char *, const char *);
67extern int strncmp(const char *, const char *, size_t);
68extern size_t strlcat(char *, const char *, size_t);
69#endif
70
71
72#define TERM 0 /* used to indicate that the 'indirect' */
73 /* field terminates - no pointer. */
74
75/* Used to decode instructions. */
76typedef struct instable {
77 struct instable *it_indirect; /* for decode op codes */
78 uchar_t it_adrmode;
79#ifdef DIS_TEXT
80 char it_name[NCPS];
81 uint_t it_suffix:1; /* mnem + "w", "l", or "d" */
82#endif
83#ifdef DIS_MEM
84 uint_t it_size:16;
85#endif
86 uint_t it_invalid64:1; /* opcode invalid in amd64 */
87 uint_t it_always64:1; /* 64 bit when in 64 bit mode */
88 uint_t it_invalid32:1; /* invalid in IA32 */
89 uint_t it_stackop:1; /* push/pop stack operation */
90} instable_t;
91
92/*
93 * Instruction formats.
94 */
95enum {
96 UNKNOWN,
97 MRw,
98 IMlw,
99 IMw,
100 IR,
101 OA,
102 AO,
103 MS,
104 SM,
105 Mv,
106 Mw,
107 M, /* register or memory */
108 MG9, /* register or memory in group 9 (prefix optional) */
107 Mb, /* register or memory, always byte sized */
108 MO, /* memory only (no registers) */
109 PREF,
109 Mb, /* register or memory, always byte sized */
110 MO, /* memory only (no registers) */
111 PREF,
110 SWAPGS,
112 SWAPGS_RDTSCP,
111 MONITOR_MWAIT,
112 R,
113 RA,
114 SEG,
115 MR,
116 RM,
113 MONITOR_MWAIT,
114 R,
115 RA,
116 SEG,
117 MR,
118 RM,
119 RM_66r, /* RM, but with a required 0x66 prefix */
117 IA,
118 MA,
119 SD,
120 AD,
121 SA,
122 D,
123 INM,
124 SO,
125 BD,
126 I,
127 P,
128 V,
129 DSHIFT, /* for double shift that has an 8-bit immediate */
130 U,
131 OVERRIDE,
132 NORM, /* instructions w/o ModR/M byte, no memory access */
133 IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */
134 O, /* for call */
135 JTAB, /* jump table */
136 IMUL, /* for 186 iimul instr */
137 CBW, /* so data16 can be evaluated for cbw and variants */
138 MvI, /* for 186 logicals */
139 ENTER, /* for 186 enter instr */
140 RMw, /* for 286 arpl instr */
141 Ib, /* for push immediate byte */
142 F, /* for 287 instructions */
143 FF, /* for 287 instructions */
144 FFC, /* for 287 instructions */
145 DM, /* 16-bit data */
146 AM, /* 16-bit addr */
147 LSEG, /* for 3-bit seg reg encoding */
148 MIb, /* for 386 logicals */
149 SREG, /* for 386 special registers */
150 PREFIX, /* a REP instruction prefix */
151 LOCK, /* a LOCK instruction prefix */
152 INT3, /* The int 3 instruction, which has a fake operand */
153 INTx, /* The normal int instruction, with explicit int num */
154 DSHIFTcl, /* for double shift that implicitly uses %cl */
155 CWD, /* so data16 can be evaluated for cwd and variants */
156 RET, /* single immediate 16-bit operand */
157 MOVZ, /* for movs and movz, with different size operands */
158 CRC32, /* for crc32, with different size operands */
159 XADDB, /* for xaddb */
160 MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */
161 MOVBE, /* movbe instruction */
162
163/*
164 * MMX/SIMD addressing modes.
165 */
166
167 MMO, /* Prefixable MMX/SIMD-Int mm/mem -> mm */
168 MMOIMPL, /* Prefixable MMX/SIMD-Int mm -> mm (mem) */
169 MMO3P, /* Prefixable MMX/SIMD-Int mm -> r32,imm8 */
170 MMOM3, /* Prefixable MMX/SIMD-Int mm -> r32 */
171 MMOS, /* Prefixable MMX/SIMD-Int mm -> mm/mem */
172 MMOMS, /* Prefixable MMX/SIMD-Int mm -> mem */
173 MMOPM, /* MMX/SIMD-Int mm/mem -> mm,imm8 */
174 MMOPM_66o, /* MMX/SIMD-Int 0x66 optional mm/mem -> mm,imm8 */
175 MMOPRM, /* Prefixable MMX/SIMD-Int r32/mem -> mm,imm8 */
176 MMOSH, /* Prefixable MMX mm,imm8 */
177 MM, /* MMX/SIMD-Int mm/mem -> mm */
178 MMS, /* MMX/SIMD-Int mm -> mm/mem */
179 MMSH, /* MMX mm,imm8 */
180 XMMO, /* Prefixable SIMD xmm/mem -> xmm */
181 XMMOS, /* Prefixable SIMD xmm -> xmm/mem */
182 XMMOPM, /* Prefixable SIMD xmm/mem w/to xmm,imm8 */
183 XMMOMX, /* Prefixable SIMD mm/mem -> xmm */
184 XMMOX3, /* Prefixable SIMD xmm -> r32 */
185 XMMOXMM, /* Prefixable SIMD xmm/mem -> mm */
186 XMMOM, /* Prefixable SIMD xmm -> mem */
187 XMMOMS, /* Prefixable SIMD mem -> xmm */
188 XMM, /* SIMD xmm/mem -> xmm */
189 XMM_66r, /* SIMD 0x66 prefix required xmm/mem -> xmm */
190 XMM_66o, /* SIMD 0x66 prefix optional xmm/mem -> xmm */
191 XMMXIMPL, /* SIMD xmm -> xmm (mem) */
192 XMM3P, /* SIMD xmm -> r32,imm8 */
193 XMM3PM_66r, /* SIMD 0x66 prefix required xmm -> r32/mem,imm8 */
194 XMMP, /* SIMD xmm/mem w/to xmm,imm8 */
195 XMMP_66o, /* SIMD 0x66 prefix optional xmm/mem w/to xmm,imm8 */
196 XMMP_66r, /* SIMD 0x66 prefix required xmm/mem w/to xmm,imm8 */
197 XMMPRM, /* SIMD r32/mem -> xmm,imm8 */
198 XMMPRM_66r, /* SIMD 0x66 prefix required r32/mem -> xmm,imm8 */
199 XMMS, /* SIMD xmm -> xmm/mem */
200 XMMM, /* SIMD mem -> xmm */
201 XMMM_66r, /* SIMD 0x66 prefix required mem -> xmm */
202 XMMMS, /* SIMD xmm -> mem */
203 XMM3MX, /* SIMD r32/mem -> xmm */
204 XMM3MXS, /* SIMD xmm -> r32/mem */
205 XMMSH, /* SIMD xmm,imm8 */
206 XMMXM3, /* SIMD xmm/mem -> r32 */
207 XMMX3, /* SIMD xmm -> r32 */
208 XMMXMM, /* SIMD xmm/mem -> mm */
209 XMMMX, /* SIMD mm -> xmm */
210 XMMXM, /* SIMD xmm -> mm */
211 XMMX2I, /* SIMD xmm -> xmm, imm, imm */
212 XMM2I, /* SIMD xmm, imm, imm */
213 XMMFENCE, /* SIMD lfence or mfence */
214 XMMSFNC, /* SIMD sfence (none or mem) */
215 XGETBV_XSETBV,
216 VEX_NONE, /* VEX no operand */
217 VEX_MO, /* VEX mod_rm -> implicit reg */
218 VEX_RMrX, /* VEX VEX.vvvv, mod_rm -> mod_reg */
219 VEX_RRX, /* VEX VEX.vvvv, mod_reg -> mod_rm */
220 VEX_RMRX, /* VEX VEX.vvvv, mod_rm, imm8[7:4] -> mod_reg */
221 VEX_MX, /* VEX mod_rm -> mod_reg */
222 VEX_MXI, /* VEX mod_rm, imm8 -> mod_reg */
223 VEX_XXI, /* VEX mod_rm, imm8 -> VEX.vvvv */
224 VEX_MR, /* VEX mod_rm -> mod_reg */
225 VEX_RRI, /* VEX mod_reg, mod_rm -> implicit(eflags/r32) */
226 VEX_RX, /* VEX mod_reg -> mod_rm */
227 VEX_RR, /* VEX mod_rm -> mod_reg */
228 VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */
229 VEX_RM, /* VEX mod_reg -> mod_rm */
230 VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */
120 IA,
121 MA,
122 SD,
123 AD,
124 SA,
125 D,
126 INM,
127 SO,
128 BD,
129 I,
130 P,
131 V,
132 DSHIFT, /* for double shift that has an 8-bit immediate */
133 U,
134 OVERRIDE,
135 NORM, /* instructions w/o ModR/M byte, no memory access */
136 IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */
137 O, /* for call */
138 JTAB, /* jump table */
139 IMUL, /* for 186 iimul instr */
140 CBW, /* so data16 can be evaluated for cbw and variants */
141 MvI, /* for 186 logicals */
142 ENTER, /* for 186 enter instr */
143 RMw, /* for 286 arpl instr */
144 Ib, /* for push immediate byte */
145 F, /* for 287 instructions */
146 FF, /* for 287 instructions */
147 FFC, /* for 287 instructions */
148 DM, /* 16-bit data */
149 AM, /* 16-bit addr */
150 LSEG, /* for 3-bit seg reg encoding */
151 MIb, /* for 386 logicals */
152 SREG, /* for 386 special registers */
153 PREFIX, /* a REP instruction prefix */
154 LOCK, /* a LOCK instruction prefix */
155 INT3, /* The int 3 instruction, which has a fake operand */
156 INTx, /* The normal int instruction, with explicit int num */
157 DSHIFTcl, /* for double shift that implicitly uses %cl */
158 CWD, /* so data16 can be evaluated for cwd and variants */
159 RET, /* single immediate 16-bit operand */
160 MOVZ, /* for movs and movz, with different size operands */
161 CRC32, /* for crc32, with different size operands */
162 XADDB, /* for xaddb */
163 MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */
164 MOVBE, /* movbe instruction */
165
166/*
167 * MMX/SIMD addressing modes.
168 */
169
170 MMO, /* Prefixable MMX/SIMD-Int mm/mem -> mm */
171 MMOIMPL, /* Prefixable MMX/SIMD-Int mm -> mm (mem) */
172 MMO3P, /* Prefixable MMX/SIMD-Int mm -> r32,imm8 */
173 MMOM3, /* Prefixable MMX/SIMD-Int mm -> r32 */
174 MMOS, /* Prefixable MMX/SIMD-Int mm -> mm/mem */
175 MMOMS, /* Prefixable MMX/SIMD-Int mm -> mem */
176 MMOPM, /* MMX/SIMD-Int mm/mem -> mm,imm8 */
177 MMOPM_66o, /* MMX/SIMD-Int 0x66 optional mm/mem -> mm,imm8 */
178 MMOPRM, /* Prefixable MMX/SIMD-Int r32/mem -> mm,imm8 */
179 MMOSH, /* Prefixable MMX mm,imm8 */
180 MM, /* MMX/SIMD-Int mm/mem -> mm */
181 MMS, /* MMX/SIMD-Int mm -> mm/mem */
182 MMSH, /* MMX mm,imm8 */
183 XMMO, /* Prefixable SIMD xmm/mem -> xmm */
184 XMMOS, /* Prefixable SIMD xmm -> xmm/mem */
185 XMMOPM, /* Prefixable SIMD xmm/mem w/to xmm,imm8 */
186 XMMOMX, /* Prefixable SIMD mm/mem -> xmm */
187 XMMOX3, /* Prefixable SIMD xmm -> r32 */
188 XMMOXMM, /* Prefixable SIMD xmm/mem -> mm */
189 XMMOM, /* Prefixable SIMD xmm -> mem */
190 XMMOMS, /* Prefixable SIMD mem -> xmm */
191 XMM, /* SIMD xmm/mem -> xmm */
192 XMM_66r, /* SIMD 0x66 prefix required xmm/mem -> xmm */
193 XMM_66o, /* SIMD 0x66 prefix optional xmm/mem -> xmm */
194 XMMXIMPL, /* SIMD xmm -> xmm (mem) */
195 XMM3P, /* SIMD xmm -> r32,imm8 */
196 XMM3PM_66r, /* SIMD 0x66 prefix required xmm -> r32/mem,imm8 */
197 XMMP, /* SIMD xmm/mem w/to xmm,imm8 */
198 XMMP_66o, /* SIMD 0x66 prefix optional xmm/mem w/to xmm,imm8 */
199 XMMP_66r, /* SIMD 0x66 prefix required xmm/mem w/to xmm,imm8 */
200 XMMPRM, /* SIMD r32/mem -> xmm,imm8 */
201 XMMPRM_66r, /* SIMD 0x66 prefix required r32/mem -> xmm,imm8 */
202 XMMS, /* SIMD xmm -> xmm/mem */
203 XMMM, /* SIMD mem -> xmm */
204 XMMM_66r, /* SIMD 0x66 prefix required mem -> xmm */
205 XMMMS, /* SIMD xmm -> mem */
206 XMM3MX, /* SIMD r32/mem -> xmm */
207 XMM3MXS, /* SIMD xmm -> r32/mem */
208 XMMSH, /* SIMD xmm,imm8 */
209 XMMXM3, /* SIMD xmm/mem -> r32 */
210 XMMX3, /* SIMD xmm -> r32 */
211 XMMXMM, /* SIMD xmm/mem -> mm */
212 XMMMX, /* SIMD mm -> xmm */
213 XMMXM, /* SIMD xmm -> mm */
214 XMMX2I, /* SIMD xmm -> xmm, imm, imm */
215 XMM2I, /* SIMD xmm, imm, imm */
216 XMMFENCE, /* SIMD lfence or mfence */
217 XMMSFNC, /* SIMD sfence (none or mem) */
218 XGETBV_XSETBV,
219 VEX_NONE, /* VEX no operand */
220 VEX_MO, /* VEX mod_rm -> implicit reg */
221 VEX_RMrX, /* VEX VEX.vvvv, mod_rm -> mod_reg */
222 VEX_RRX, /* VEX VEX.vvvv, mod_reg -> mod_rm */
223 VEX_RMRX, /* VEX VEX.vvvv, mod_rm, imm8[7:4] -> mod_reg */
224 VEX_MX, /* VEX mod_rm -> mod_reg */
225 VEX_MXI, /* VEX mod_rm, imm8 -> mod_reg */
226 VEX_XXI, /* VEX mod_rm, imm8 -> VEX.vvvv */
227 VEX_MR, /* VEX mod_rm -> mod_reg */
228 VEX_RRI, /* VEX mod_reg, mod_rm -> implicit(eflags/r32) */
229 VEX_RX, /* VEX mod_reg -> mod_rm */
230 VEX_RR, /* VEX mod_rm -> mod_reg */
231 VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */
232 VEX_RM, /* VEX mod_reg -> mod_rm */
233 VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */
231 VEX_RMX /* VEX VEX.vvvv, mod_rm -> mod_reg */
234 VEX_RMX, /* VEX VEX.vvvv, mod_rm -> mod_reg */
235 VMx, /* vmcall/vmlaunch/vmresume/vmxoff */
236 VMxo, /* VMx instruction with optional prefix */
237 SVM /* AMD SVM instructions */
232};
233
234/*
235 * VEX prefixes
236 */
237#define VEX_2bytes 0xC5 /* the first byte of two-byte form */
238#define VEX_3bytes 0xC4 /* the first byte of three-byte form */
239
240#define FILL 0x90 /* Fill byte used for alignment (nop) */
241
242/*
243** Register numbers for the i386
244*/
245#define EAX_REGNO 0
246#define ECX_REGNO 1
247#define EDX_REGNO 2
248#define EBX_REGNO 3
249#define ESP_REGNO 4
250#define EBP_REGNO 5
251#define ESI_REGNO 6
252#define EDI_REGNO 7
253
254/*
255 * modes for immediate values
256 */
257#define MODE_NONE 0
258#define MODE_IPREL 1 /* signed IP relative value */
259#define MODE_SIGNED 2 /* sign extended immediate */
260#define MODE_IMPLIED 3 /* constant value implied from opcode */
261#define MODE_OFFSET 4 /* offset part of an address */
262#define MODE_RIPREL 5 /* like IPREL, but from %rip (amd64) */
263
264/*
265 * The letters used in these macros are:
266 * IND - indirect to another to another table
267 * "T" - means to Terminate indirections (this is the final opcode)
268 * "S" - means "operand length suffix required"
269 * "NS" - means "no suffix" which is the operand length suffix of the opcode
270 * "Z" - means instruction size arg required
271 * "u" - means the opcode is invalid in IA32 but valid in amd64
272 * "x" - means the opcode is invalid in amd64, but not IA32
273 * "y" - means the operand size is always 64 bits in 64 bit mode
274 * "p" - means push/pop stack operation
275 */
276
277#if defined(DIS_TEXT) && defined(DIS_MEM)
278#define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0}
279#define INDx(table) {(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0}
280#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0}
281#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0}
282#define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0}
283#define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0}
284#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1}
285#define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0}
286#define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0}
287#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0}
288#define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0}
289#define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0}
290#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1}
291#define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0}
292#define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0}
293#define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0}
294#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
295#elif defined(DIS_TEXT)
296#define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0}
297#define INDx(table) {(instable_t *)table, 0, "", 0, 1, 0, 0, 0}
298#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0}
299#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0}
300#define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0}
301#define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0}
302#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1}
303#define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0}
304#define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0}
305#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0}
306#define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0}
307#define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0}
308#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1}
309#define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0}
310#define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0}
311#define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0}
312#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
313#elif defined(DIS_MEM)
314#define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0, 0}
315#define INDx(table) {(instable_t *)table, 0, 0, 1, 0, 0, 0}
316#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0}
317#define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0}
318#define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0}
319#define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1}
320#define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0}
321#define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0}
322#define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0}
323#define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0}
324#define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0}
325#define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0}
326#define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1}
327#define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0}
328#define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0}
329#define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0}
330#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0}
331#else
332#define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0}
333#define INDx(table) {(instable_t *)table, 0, 1, 0, 0, 0}
334#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0}
335#define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0}
336#define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0}
337#define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1}
338#define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0}
339#define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0}
340#define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0}
341#define TS(name, amode) {TERM, amode, 0, 0, 0, 0}
342#define TSx(name, amode) {TERM, amode, 1, 0, 0, 0}
343#define TSy(name, amode) {TERM, amode, 0, 1, 0, 0}
344#define TSp(name, amode) {TERM, amode, 0, 0, 0, 1}
345#define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0}
346#define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0}
347#define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0}
348#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0}
349#endif
350
351#ifdef DIS_TEXT
352/*
353 * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode
354 */
355const char *const dis_addr16[3][8] = {
356"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "",
357 "(%bx)",
358"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)",
359 "(%bx)",
360"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)",
361 "(%bx)",
362};
363
364
365/*
366 * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2
367 */
368const char *const dis_addr32_mode0[16] = {
369 "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)",
370 "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)"
371};
372
373const char *const dis_addr32_mode12[16] = {
374 "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)",
375 "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)"
376};
377
378/*
379 * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2
380 */
381const char *const dis_addr64_mode0[16] = {
382 "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)",
383 "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)"
384};
385const char *const dis_addr64_mode12[16] = {
386 "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)",
387 "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)"
388};
389
390/*
391 * decode for scale from SIB byte
392 */
393const char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" };
394
395/*
396 * register decoding for normal references to registers (ie. not addressing)
397 */
398const char *const dis_REG8[16] = {
399 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
400 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
401};
402
403const char *const dis_REG8_REX[16] = {
404 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
405 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
406};
407
408const char *const dis_REG16[16] = {
409 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
410 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
411};
412
413const char *const dis_REG32[16] = {
414 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
415 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
416};
417
418const char *const dis_REG64[16] = {
419 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
420 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
421};
422
423const char *const dis_DEBUGREG[16] = {
424 "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7",
425 "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15"
426};
427
428const char *const dis_CONTROLREG[16] = {
429 "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?",
430 "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?"
431};
432
433const char *const dis_TESTREG[16] = {
434 "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
435 "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7"
436};
437
438const char *const dis_MMREG[16] = {
439 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
440 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
441};
442
443const char *const dis_XMMREG[16] = {
444 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
445 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15"
446};
447
448const char *const dis_YMMREG[16] = {
449 "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7",
450 "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15"
451};
452
453const char *const dis_SEGREG[16] = {
454 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>",
455 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>"
456};
457
458/*
459 * SIMD predicate suffixes
460 */
461const char *const dis_PREDSUFFIX[8] = {
462 "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord"
463};
464
465const char *const dis_AVXvgrp7[3][8] = {
466 /*0 1 2 3 4 5 6 7*/
467/*71*/ {"", "", "vpsrlw", "", "vpsraw", "", "vpsllw", ""},
468/*72*/ {"", "", "vpsrld", "", "vpsrad", "", "vpslld", ""},
469/*73*/ {"", "", "vpsrlq", "vpsrldq", "", "", "vpsllq", "vpslldq"}
470};
471
472#endif /* DIS_TEXT */
473
474/*
475 * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63)
476 */
477const instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ);
478
479/*
480 * "decode table" for pause and clflush instructions
481 */
482const instable_t dis_opPause = TNS("pause", NORM);
483
484/*
485 * Decode table for 0x0F00 opcodes
486 */
487const instable_t dis_op0F00[8] = {
488
489/* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M),
490/* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID,
491};
492
493
494/*
495 * Decode table for 0x0F01 opcodes
496 */
497const instable_t dis_op0F01[8] = {
498
238};
239
240/*
241 * VEX prefixes
242 */
243#define VEX_2bytes 0xC5 /* the first byte of two-byte form */
244#define VEX_3bytes 0xC4 /* the first byte of three-byte form */
245
246#define FILL 0x90 /* Fill byte used for alignment (nop) */
247
248/*
249** Register numbers for the i386
250*/
251#define EAX_REGNO 0
252#define ECX_REGNO 1
253#define EDX_REGNO 2
254#define EBX_REGNO 3
255#define ESP_REGNO 4
256#define EBP_REGNO 5
257#define ESI_REGNO 6
258#define EDI_REGNO 7
259
260/*
261 * modes for immediate values
262 */
263#define MODE_NONE 0
264#define MODE_IPREL 1 /* signed IP relative value */
265#define MODE_SIGNED 2 /* sign extended immediate */
266#define MODE_IMPLIED 3 /* constant value implied from opcode */
267#define MODE_OFFSET 4 /* offset part of an address */
268#define MODE_RIPREL 5 /* like IPREL, but from %rip (amd64) */
269
270/*
271 * The letters used in these macros are:
272 * IND - indirect to another to another table
273 * "T" - means to Terminate indirections (this is the final opcode)
274 * "S" - means "operand length suffix required"
275 * "NS" - means "no suffix" which is the operand length suffix of the opcode
276 * "Z" - means instruction size arg required
277 * "u" - means the opcode is invalid in IA32 but valid in amd64
278 * "x" - means the opcode is invalid in amd64, but not IA32
279 * "y" - means the operand size is always 64 bits in 64 bit mode
280 * "p" - means push/pop stack operation
281 */
282
283#if defined(DIS_TEXT) && defined(DIS_MEM)
284#define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0}
285#define INDx(table) {(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0}
286#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0}
287#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0}
288#define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0}
289#define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0}
290#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1}
291#define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0}
292#define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0}
293#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0}
294#define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0}
295#define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0}
296#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1}
297#define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0}
298#define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0}
299#define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0}
300#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
301#elif defined(DIS_TEXT)
302#define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0}
303#define INDx(table) {(instable_t *)table, 0, "", 0, 1, 0, 0, 0}
304#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0}
305#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0}
306#define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0}
307#define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0}
308#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1}
309#define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0}
310#define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0}
311#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0}
312#define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0}
313#define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0}
314#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1}
315#define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0}
316#define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0}
317#define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0}
318#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0}
319#elif defined(DIS_MEM)
320#define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0, 0}
321#define INDx(table) {(instable_t *)table, 0, 0, 1, 0, 0, 0}
322#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0}
323#define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0}
324#define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0}
325#define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1}
326#define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0}
327#define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0}
328#define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0}
329#define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0}
330#define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0}
331#define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0}
332#define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1}
333#define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0}
334#define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0}
335#define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0}
336#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0}
337#else
338#define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0}
339#define INDx(table) {(instable_t *)table, 0, 1, 0, 0, 0}
340#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0}
341#define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0}
342#define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0}
343#define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1}
344#define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0}
345#define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0}
346#define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0}
347#define TS(name, amode) {TERM, amode, 0, 0, 0, 0}
348#define TSx(name, amode) {TERM, amode, 1, 0, 0, 0}
349#define TSy(name, amode) {TERM, amode, 0, 1, 0, 0}
350#define TSp(name, amode) {TERM, amode, 0, 0, 0, 1}
351#define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0}
352#define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0}
353#define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0}
354#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0}
355#endif
356
357#ifdef DIS_TEXT
358/*
359 * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode
360 */
361const char *const dis_addr16[3][8] = {
362"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "",
363 "(%bx)",
364"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)",
365 "(%bx)",
366"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)",
367 "(%bx)",
368};
369
370
371/*
372 * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2
373 */
374const char *const dis_addr32_mode0[16] = {
375 "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)",
376 "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)"
377};
378
379const char *const dis_addr32_mode12[16] = {
380 "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)",
381 "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)"
382};
383
384/*
385 * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2
386 */
387const char *const dis_addr64_mode0[16] = {
388 "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)",
389 "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)"
390};
391const char *const dis_addr64_mode12[16] = {
392 "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)",
393 "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)"
394};
395
396/*
397 * decode for scale from SIB byte
398 */
399const char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" };
400
401/*
402 * register decoding for normal references to registers (ie. not addressing)
403 */
404const char *const dis_REG8[16] = {
405 "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
406 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
407};
408
409const char *const dis_REG8_REX[16] = {
410 "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
411 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
412};
413
414const char *const dis_REG16[16] = {
415 "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
416 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
417};
418
419const char *const dis_REG32[16] = {
420 "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
421 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
422};
423
424const char *const dis_REG64[16] = {
425 "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
426 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
427};
428
429const char *const dis_DEBUGREG[16] = {
430 "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7",
431 "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15"
432};
433
434const char *const dis_CONTROLREG[16] = {
435 "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?",
436 "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?"
437};
438
439const char *const dis_TESTREG[16] = {
440 "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
441 "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7"
442};
443
444const char *const dis_MMREG[16] = {
445 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
446 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
447};
448
449const char *const dis_XMMREG[16] = {
450 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
451 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15"
452};
453
454const char *const dis_YMMREG[16] = {
455 "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7",
456 "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15"
457};
458
459const char *const dis_SEGREG[16] = {
460 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>",
461 "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>"
462};
463
464/*
465 * SIMD predicate suffixes
466 */
467const char *const dis_PREDSUFFIX[8] = {
468 "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord"
469};
470
471const char *const dis_AVXvgrp7[3][8] = {
472 /*0 1 2 3 4 5 6 7*/
473/*71*/ {"", "", "vpsrlw", "", "vpsraw", "", "vpsllw", ""},
474/*72*/ {"", "", "vpsrld", "", "vpsrad", "", "vpslld", ""},
475/*73*/ {"", "", "vpsrlq", "vpsrldq", "", "", "vpsllq", "vpslldq"}
476};
477
478#endif /* DIS_TEXT */
479
480/*
481 * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63)
482 */
483const instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ);
484
485/*
486 * "decode table" for pause and clflush instructions
487 */
488const instable_t dis_opPause = TNS("pause", NORM);
489
490/*
491 * Decode table for 0x0F00 opcodes
492 */
493const instable_t dis_op0F00[8] = {
494
495/* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M),
496/* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID,
497};
498
499
500/*
501 * Decode table for 0x0F01 opcodes
502 */
503const instable_t dis_op0F01[8] = {
504
499/* [0] */ TNSZ("sgdt",MO,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",MO,6),
500/* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS),
505/* [0] */ TNSZ("sgdt",VMx,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",SVM,6),
506/* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS_RDTSCP),
501};
502
503/*
504 * Decode table for 0x0F18 opcodes -- SIMD prefetch
505 */
506const instable_t dis_op0F18[8] = {
507
508/* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF),
509/* [4] */ INVALID, INVALID, INVALID, INVALID,
510};
511
512/*
513 * Decode table for 0x0FAE opcodes -- SIMD state save/restore
514 */
515const instable_t dis_op0FAE[8] = {
516/* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M),
517/* [4] */ TNSZ("xsave",M,512), TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC),
518};
519
520/*
521 * Decode table for 0x0FBA opcodes
522 */
523
524const instable_t dis_op0FBA[8] = {
525
526/* [0] */ INVALID, INVALID, INVALID, INVALID,
527/* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb),
528};
529
530/*
507};
508
509/*
510 * Decode table for 0x0F18 opcodes -- SIMD prefetch
511 */
512const instable_t dis_op0F18[8] = {
513
514/* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF),
515/* [4] */ INVALID, INVALID, INVALID, INVALID,
516};
517
518/*
519 * Decode table for 0x0FAE opcodes -- SIMD state save/restore
520 */
521const instable_t dis_op0FAE[8] = {
522/* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M),
523/* [4] */ TNSZ("xsave",M,512), TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC),
524};
525
526/*
527 * Decode table for 0x0FBA opcodes
528 */
529
530const instable_t dis_op0FBA[8] = {
531
532/* [0] */ INVALID, INVALID, INVALID, INVALID,
533/* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb),
534};
535
536/*
531 * Decode table for 0x0FC7 opcode
537 * Decode table for 0x0FC7 opcode (group 9)
532 */
533
534const instable_t dis_op0FC7[8] = {
535
536/* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID,
538 */
539
540const instable_t dis_op0FC7[8] = {
541
542/* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID,
537/* [4] */ INVALID, INVALID, INVALID, INVALID,
543/* [4] */ INVALID, INVALID, TNS("vmptrld",MG9), TNS("vmptrst",MG9),
538};
539
544};
545
546/*
547 * Decode table for 0x0FC7 opcode (group 9) mode 3
548 */
540
549
550const instable_t dis_op0FC7m3[8] = {
551
552/* [0] */ INVALID, INVALID, INVALID, INVALID,
553/* [4] */ INVALID, INVALID, TNS("rdrand",MG9), INVALID,
554};
555
541/*
556/*
557 * Decode table for 0x0FC7 opcode with 0x66 prefix
558 */
559
560const instable_t dis_op660FC7[8] = {
561
562/* [0] */ INVALID, INVALID, INVALID, INVALID,
563/* [4] */ INVALID, INVALID, TNS("vmclear",M), INVALID,
564};
565
566/*
567 * Decode table for 0x0FC7 opcode with 0xF3 prefix
568 */
569
570const instable_t dis_opF30FC7[8] = {
571
572/* [0] */ INVALID, INVALID, INVALID, INVALID,
573/* [4] */ INVALID, INVALID, TNS("vmxon",M), INVALID,
574};
575
576/*
542 * Decode table for 0x0FC8 opcode -- 486 bswap instruction
543 *
544 *bit pattern: 0000 1111 1100 1reg
545 */
546const instable_t dis_op0FC8[4] = {
547/* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID,
548};
549
550/*
551 * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions
552 */
553const instable_t dis_op0F7123[4][8] = {
554{
555/* [70].0 */ INVALID, INVALID, INVALID, INVALID,
556/* .4 */ INVALID, INVALID, INVALID, INVALID,
557}, {
558/* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID,
559/* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID,
560}, {
561/* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID,
562/* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID,
563}, {
564/* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH),
565/* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH),
566} };
567
568/*
569 * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes.
570 */
571const instable_t dis_opSIMD7123[32] = {
572/* [70].0 */ INVALID, INVALID, INVALID, INVALID,
573/* .4 */ INVALID, INVALID, INVALID, INVALID,
574
575/* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID,
576/* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID,
577
578/* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID,
579/* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID,
580
581/* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH),
582/* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH),
583};
584
585/*
586 * SIMD instructions have been wedged into the existing IA32 instruction
587 * set through the use of prefixes. That is, while 0xf0 0x58 may be
588 * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different
589 * instruction - addss. At present, three prefixes have been coopted in
590 * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The
591 * following tables are used to provide the prefixed instruction names.
592 * The arrays are sparse, but they're fast.
593 */
594
595/*
596 * Decode table for SIMD instructions with the address size (0x66) prefix.
597 */
598const instable_t dis_opSIMDdata16[256] = {
599/* [00] */ INVALID, INVALID, INVALID, INVALID,
600/* [04] */ INVALID, INVALID, INVALID, INVALID,
601/* [08] */ INVALID, INVALID, INVALID, INVALID,
602/* [0C] */ INVALID, INVALID, INVALID, INVALID,
603
604/* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8),
605/* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8),
606/* [18] */ INVALID, INVALID, INVALID, INVALID,
607/* [1C] */ INVALID, INVALID, INVALID, INVALID,
608
609/* [20] */ INVALID, INVALID, INVALID, INVALID,
610/* [24] */ INVALID, INVALID, INVALID, INVALID,
611/* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16),
612/* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8),
613
614/* [30] */ INVALID, INVALID, INVALID, INVALID,
615/* [34] */ INVALID, INVALID, INVALID, INVALID,
616/* [38] */ INVALID, INVALID, INVALID, INVALID,
617/* [3C] */ INVALID, INVALID, INVALID, INVALID,
618
619/* [40] */ INVALID, INVALID, INVALID, INVALID,
620/* [44] */ INVALID, INVALID, INVALID, INVALID,
621/* [48] */ INVALID, INVALID, INVALID, INVALID,
622/* [4C] */ INVALID, INVALID, INVALID, INVALID,
623
624/* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID,
625/* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16),
626/* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16),
627/* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16),
628
629/* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16),
630/* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16),
631/* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16),
632/* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16),
633
634/* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID,
635/* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID,
636/* [78] */ TNSZ("extrq",XMM2I,16), TNSZ("extrq",XMM,16), INVALID, INVALID,
637/* [7C] */ INVALID, INVALID, TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16),
638
639/* [80] */ INVALID, INVALID, INVALID, INVALID,
640/* [84] */ INVALID, INVALID, INVALID, INVALID,
641/* [88] */ INVALID, INVALID, INVALID, INVALID,
642/* [8C] */ INVALID, INVALID, INVALID, INVALID,
643
644/* [90] */ INVALID, INVALID, INVALID, INVALID,
645/* [94] */ INVALID, INVALID, INVALID, INVALID,
646/* [98] */ INVALID, INVALID, INVALID, INVALID,
647/* [9C] */ INVALID, INVALID, INVALID, INVALID,
648
649/* [A0] */ INVALID, INVALID, INVALID, INVALID,
650/* [A4] */ INVALID, INVALID, INVALID, INVALID,
651/* [A8] */ INVALID, INVALID, INVALID, INVALID,
652/* [AC] */ INVALID, INVALID, INVALID, INVALID,
653
654/* [B0] */ INVALID, INVALID, INVALID, INVALID,
655/* [B4] */ INVALID, INVALID, INVALID, INVALID,
656/* [B8] */ INVALID, INVALID, INVALID, INVALID,
657/* [BC] */ INVALID, INVALID, INVALID, INVALID,
658
659/* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID,
660/* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID,
661/* [C8] */ INVALID, INVALID, INVALID, INVALID,
662/* [CC] */ INVALID, INVALID, INVALID, INVALID,
663
664/* [D0] */ INVALID, TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16),
665/* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3),
666/* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16),
667/* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16),
668
669/* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16),
670/* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16),
671/* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16),
672/* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16),
673
674/* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16),
675/* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16),
676/* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16),
677/* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID,
678};
679
680const instable_t dis_opAVX660F[256] = {
681/* [00] */ INVALID, INVALID, INVALID, INVALID,
682/* [04] */ INVALID, INVALID, INVALID, INVALID,
683/* [08] */ INVALID, INVALID, INVALID, INVALID,
684/* [0C] */ INVALID, INVALID, INVALID, INVALID,
685
686/* [10] */ TNSZ("vmovupd",VEX_MX,16), TNSZ("vmovupd",VEX_RX,16), TNSZ("vmovlpd",VEX_RMrX,8), TNSZ("vmovlpd",VEX_RM,8),
687/* [14] */ TNSZ("vunpcklpd",VEX_RMrX,16),TNSZ("vunpckhpd",VEX_RMrX,16),TNSZ("vmovhpd",VEX_RMrX,8), TNSZ("vmovhpd",VEX_RM,8),
688/* [18] */ INVALID, INVALID, INVALID, INVALID,
689/* [1C] */ INVALID, INVALID, INVALID, INVALID,
690
691/* [20] */ INVALID, INVALID, INVALID, INVALID,
692/* [24] */ INVALID, INVALID, INVALID, INVALID,
693/* [28] */ TNSZ("vmovapd",VEX_MX,16), TNSZ("vmovapd",VEX_RX,16), INVALID, TNSZ("vmovntpd",VEX_RM,16),
694/* [2C] */ INVALID, INVALID, TNSZ("vucomisd",VEX_MX,8),TNSZ("vcomisd",VEX_MX,8),
695
696/* [30] */ INVALID, INVALID, INVALID, INVALID,
697/* [34] */ INVALID, INVALID, INVALID, INVALID,
698/* [38] */ INVALID, INVALID, INVALID, INVALID,
699/* [3C] */ INVALID, INVALID, INVALID, INVALID,
700
701/* [40] */ INVALID, INVALID, INVALID, INVALID,
702/* [44] */ INVALID, INVALID, INVALID, INVALID,
703/* [48] */ INVALID, INVALID, INVALID, INVALID,
704/* [4C] */ INVALID, INVALID, INVALID, INVALID,
705
706/* [50] */ TNS("vmovmskpd",VEX_MR), TNSZ("vsqrtpd",VEX_MX,16), INVALID, INVALID,
707/* [54] */ TNSZ("vandpd",VEX_RMrX,16), TNSZ("vandnpd",VEX_RMrX,16), TNSZ("vorpd",VEX_RMrX,16), TNSZ("vxorpd",VEX_RMrX,16),
708/* [58] */ TNSZ("vaddpd",VEX_RMrX,16), TNSZ("vmulpd",VEX_RMrX,16), TNSZ("vcvtpd2ps",VEX_MX,16),TNSZ("vcvtps2dq",VEX_MX,16),
709/* [5C] */ TNSZ("vsubpd",VEX_RMrX,16), TNSZ("vminpd",VEX_RMrX,16), TNSZ("vdivpd",VEX_RMrX,16), TNSZ("vmaxpd",VEX_RMrX,16),
710
711/* [60] */ TNSZ("vpunpcklbw",VEX_RMrX,16),TNSZ("vpunpcklwd",VEX_RMrX,16),TNSZ("vpunpckldq",VEX_RMrX,16),TNSZ("vpacksswb",VEX_RMrX,16),
712/* [64] */ TNSZ("vpcmpgtb",VEX_RMrX,16), TNSZ("vpcmpgtw",VEX_RMrX,16), TNSZ("vpcmpgtd",VEX_RMrX,16), TNSZ("vpackuswb",VEX_RMrX,16),
713/* [68] */ TNSZ("vpunpckhbw",VEX_RMrX,16),TNSZ("vpunpckhwd",VEX_RMrX,16),TNSZ("vpunpckhdq",VEX_RMrX,16),TNSZ("vpackssdw",VEX_RMrX,16),
714/* [6C] */ TNSZ("vpunpcklqdq",VEX_RMrX,16),TNSZ("vpunpckhqdq",VEX_RMrX,16),TNSZ("vmovd",VEX_MX,4),TNSZ("vmovdqa",VEX_MX,16),
715
716/* [70] */ TNSZ("vpshufd",VEX_MXI,16), TNSZ("vgrp71",VEX_XXI,16), TNSZ("vgrp72",VEX_XXI,16), TNSZ("vgrp73",VEX_XXI,16),
717/* [74] */ TNSZ("vpcmpeqb",VEX_RMrX,16), TNSZ("vpcmpeqw",VEX_RMrX,16), TNSZ("vpcmpeqd",VEX_RMrX,16), INVALID,
718/* [78] */ INVALID, INVALID, INVALID, INVALID,
719/* [7C] */ TNSZ("vhaddpd",VEX_RMrX,16), TNSZ("vhsubpd",VEX_RMrX,16), TNSZ("vmovd",VEX_RR,4), TNSZ("vmovdqa",VEX_RX,16),
720
721/* [80] */ INVALID, INVALID, INVALID, INVALID,
722/* [84] */ INVALID, INVALID, INVALID, INVALID,
723/* [88] */ INVALID, INVALID, INVALID, INVALID,
724/* [8C] */ INVALID, INVALID, INVALID, INVALID,
725
726/* [90] */ INVALID, INVALID, INVALID, INVALID,
727/* [94] */ INVALID, INVALID, INVALID, INVALID,
728/* [98] */ INVALID, INVALID, INVALID, INVALID,
729/* [9C] */ INVALID, INVALID, INVALID, INVALID,
730
731/* [A0] */ INVALID, INVALID, INVALID, INVALID,
732/* [A4] */ INVALID, INVALID, INVALID, INVALID,
733/* [A8] */ INVALID, INVALID, INVALID, INVALID,
734/* [AC] */ INVALID, INVALID, INVALID, INVALID,
735
736/* [B0] */ INVALID, INVALID, INVALID, INVALID,
737/* [B4] */ INVALID, INVALID, INVALID, INVALID,
738/* [B8] */ INVALID, INVALID, INVALID, INVALID,
739/* [BC] */ INVALID, INVALID, INVALID, INVALID,
740
741/* [C0] */ INVALID, INVALID, TNSZ("vcmppd",VEX_RMRX,16), INVALID,
742/* [C4] */ TNSZ("vpinsrw",VEX_RMRX,2),TNS("vpextrw",VEX_MR), TNSZ("vshufpd",VEX_RMRX,16), INVALID,
743/* [C8] */ INVALID, INVALID, INVALID, INVALID,
744/* [CC] */ INVALID, INVALID, INVALID, INVALID,
745
746/* [D0] */ TNSZ("vaddsubpd",VEX_RMrX,16),TNSZ("vpsrlw",VEX_RMrX,16), TNSZ("vpsrld",VEX_RMrX,16), TNSZ("vpsrlq",VEX_RMrX,16),
747/* [D4] */ TNSZ("vpaddq",VEX_RMrX,16), TNSZ("vpmullw",VEX_RMrX,16), TNSZ("vmovq",VEX_RX,8), TNS("vpmovmskb",VEX_MR),
748/* [D8] */ TNSZ("vpsubusb",VEX_RMrX,16), TNSZ("vpsubusw",VEX_RMrX,16), TNSZ("vpminub",VEX_RMrX,16), TNSZ("vpand",VEX_RMrX,16),
749/* [DC] */ TNSZ("vpaddusb",VEX_RMrX,16), TNSZ("vpaddusw",VEX_RMrX,16), TNSZ("vpmaxub",VEX_RMrX,16), TNSZ("vpandn",VEX_RMrX,16),
750
751/* [E0] */ TNSZ("vpavgb",VEX_RMrX,16), TNSZ("vpsraw",VEX_RMrX,16), TNSZ("vpsrad",VEX_RMrX,16), TNSZ("vpavgw",VEX_RMrX,16),
752/* [E4] */ TNSZ("vpmulhuw",VEX_RMrX,16), TNSZ("vpmulhw",VEX_RMrX,16), TNSZ("vcvttpd2dq",VEX_MX,16),TNSZ("vmovntdq",VEX_RM,16),
753/* [E8] */ TNSZ("vpsubsb",VEX_RMrX,16), TNSZ("vpsubsw",VEX_RMrX,16), TNSZ("vpminsw",VEX_RMrX,16), TNSZ("vpor",VEX_RMrX,16),
754/* [EC] */ TNSZ("vpaddsb",VEX_RMrX,16), TNSZ("vpaddsw",VEX_RMrX,16), TNSZ("vpmaxsw",VEX_RMrX,16), TNSZ("vpxor",VEX_RMrX,16),
755
756/* [F0] */ INVALID, TNSZ("vpsllw",VEX_RMrX,16), TNSZ("vpslld",VEX_RMrX,16), TNSZ("vpsllq",VEX_RMrX,16),
757/* [F4] */ TNSZ("vpmuludq",VEX_RMrX,16), TNSZ("vpmaddwd",VEX_RMrX,16), TNSZ("vpsadbw",VEX_RMrX,16), TNS("vmaskmovdqu",VEX_MX),
758/* [F8] */ TNSZ("vpsubb",VEX_RMrX,16), TNSZ("vpsubw",VEX_RMrX,16), TNSZ("vpsubd",VEX_RMrX,16), TNSZ("vpsubq",VEX_RMrX,16),
759/* [FC] */ TNSZ("vpaddb",VEX_RMrX,16), TNSZ("vpaddw",VEX_RMrX,16), TNSZ("vpaddd",VEX_RMrX,16), INVALID,
760};
761
762/*
763 * Decode table for SIMD instructions with the repnz (0xf2) prefix.
764 */
765const instable_t dis_opSIMDrepnz[256] = {
766/* [00] */ INVALID, INVALID, INVALID, INVALID,
767/* [04] */ INVALID, INVALID, INVALID, INVALID,
768/* [08] */ INVALID, INVALID, INVALID, INVALID,
769/* [0C] */ INVALID, INVALID, INVALID, INVALID,
770
771/* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), INVALID, INVALID,
772/* [14] */ INVALID, INVALID, INVALID, INVALID,
773/* [18] */ INVALID, INVALID, INVALID, INVALID,
774/* [1C] */ INVALID, INVALID, INVALID, INVALID,
775
776/* [20] */ INVALID, INVALID, INVALID, INVALID,
777/* [24] */ INVALID, INVALID, INVALID, INVALID,
778/* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),TNSZ("movntsd",XMMMS,8),
779/* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID,
780
781/* [30] */ INVALID, INVALID, INVALID, INVALID,
782/* [34] */ INVALID, INVALID, INVALID, INVALID,
783/* [38] */ INVALID, INVALID, INVALID, INVALID,
784/* [3C] */ INVALID, INVALID, INVALID, INVALID,
785
786/* [40] */ INVALID, INVALID, INVALID, INVALID,
787/* [44] */ INVALID, INVALID, INVALID, INVALID,
788/* [48] */ INVALID, INVALID, INVALID, INVALID,
789/* [4C] */ INVALID, INVALID, INVALID, INVALID,
790
791/* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID,
792/* [54] */ INVALID, INVALID, INVALID, INVALID,
793/* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID,
794/* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8),
795
796/* [60] */ INVALID, INVALID, INVALID, INVALID,
797/* [64] */ INVALID, INVALID, INVALID, INVALID,
798/* [68] */ INVALID, INVALID, INVALID, INVALID,
799/* [6C] */ INVALID, INVALID, INVALID, INVALID,
800
801/* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID,
802/* [74] */ INVALID, INVALID, INVALID, INVALID,
803/* [78] */ TNSZ("insertq",XMMX2I,16),TNSZ("insertq",XMM,8),INVALID, INVALID,
804/* [7C] */ INVALID, INVALID, INVALID, INVALID,
805
806/* [80] */ INVALID, INVALID, INVALID, INVALID,
807/* [84] */ INVALID, INVALID, INVALID, INVALID,
808/* [88] */ INVALID, INVALID, INVALID, INVALID,
809/* [0C] */ INVALID, INVALID, INVALID, INVALID,
810
811/* [90] */ INVALID, INVALID, INVALID, INVALID,
812/* [94] */ INVALID, INVALID, INVALID, INVALID,
813/* [98] */ INVALID, INVALID, INVALID, INVALID,
814/* [9C] */ INVALID, INVALID, INVALID, INVALID,
815
816/* [A0] */ INVALID, INVALID, INVALID, INVALID,
817/* [A4] */ INVALID, INVALID, INVALID, INVALID,
818/* [A8] */ INVALID, INVALID, INVALID, INVALID,
819/* [AC] */ INVALID, INVALID, INVALID, INVALID,
820
821/* [B0] */ INVALID, INVALID, INVALID, INVALID,
822/* [B4] */ INVALID, INVALID, INVALID, INVALID,
823/* [B8] */ INVALID, INVALID, INVALID, INVALID,
824/* [BC] */ INVALID, INVALID, INVALID, INVALID,
825
826/* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID,
827/* [C4] */ INVALID, INVALID, INVALID, INVALID,
828/* [C8] */ INVALID, INVALID, INVALID, INVALID,
829/* [CC] */ INVALID, INVALID, INVALID, INVALID,
830
831/* [D0] */ INVALID, INVALID, INVALID, INVALID,
832/* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID,
833/* [D8] */ INVALID, INVALID, INVALID, INVALID,
834/* [DC] */ INVALID, INVALID, INVALID, INVALID,
835
836/* [E0] */ INVALID, INVALID, INVALID, INVALID,
837/* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID,
838/* [E8] */ INVALID, INVALID, INVALID, INVALID,
839/* [EC] */ INVALID, INVALID, INVALID, INVALID,
840
841/* [F0] */ INVALID, INVALID, INVALID, INVALID,
842/* [F4] */ INVALID, INVALID, INVALID, INVALID,
843/* [F8] */ INVALID, INVALID, INVALID, INVALID,
844/* [FC] */ INVALID, INVALID, INVALID, INVALID,
845};
846
847const instable_t dis_opAVXF20F[256] = {
848/* [00] */ INVALID, INVALID, INVALID, INVALID,
849/* [04] */ INVALID, INVALID, INVALID, INVALID,
850/* [08] */ INVALID, INVALID, INVALID, INVALID,
851/* [0C] */ INVALID, INVALID, INVALID, INVALID,
852
853/* [10] */ TNSZ("vmovsd",VEX_RMrX,8), TNSZ("vmovsd",VEX_RRX,8), TNSZ("vmovddup",VEX_MX,8), INVALID,
854/* [14] */ INVALID, INVALID, INVALID, INVALID,
855/* [18] */ INVALID, INVALID, INVALID, INVALID,
856/* [1C] */ INVALID, INVALID, INVALID, INVALID,
857
858/* [20] */ INVALID, INVALID, INVALID, INVALID,
859/* [24] */ INVALID, INVALID, INVALID, INVALID,
860/* [28] */ INVALID, INVALID, TNSZ("vcvtsi2sd",VEX_RMrX,4),INVALID,
861/* [2C] */ TNSZ("vcvttsd2si",VEX_MR,8),TNSZ("vcvtsd2si",VEX_MR,8),INVALID, INVALID,
862
863/* [30] */ INVALID, INVALID, INVALID, INVALID,
864/* [34] */ INVALID, INVALID, INVALID, INVALID,
865/* [38] */ INVALID, INVALID, INVALID, INVALID,
866/* [3C] */ INVALID, INVALID, INVALID, INVALID,
867
868/* [40] */ INVALID, INVALID, INVALID, INVALID,
869/* [44] */ INVALID, INVALID, INVALID, INVALID,
870/* [48] */ INVALID, INVALID, INVALID, INVALID,
871/* [4C] */ INVALID, INVALID, INVALID, INVALID,
872
873/* [50] */ INVALID, TNSZ("vsqrtsd",VEX_RMrX,8), INVALID, INVALID,
874/* [54] */ INVALID, INVALID, INVALID, INVALID,
875/* [58] */ TNSZ("vaddsd",VEX_RMrX,8), TNSZ("vmulsd",VEX_RMrX,8), TNSZ("vcvtsd2ss",VEX_RMrX,8), INVALID,
876/* [5C] */ TNSZ("vsubsd",VEX_RMrX,8), TNSZ("vminsd",VEX_RMrX,8), TNSZ("vdivsd",VEX_RMrX,8), TNSZ("vmaxsd",VEX_RMrX,8),
877
878/* [60] */ INVALID, INVALID, INVALID, INVALID,
879/* [64] */ INVALID, INVALID, INVALID, INVALID,
880/* [68] */ INVALID, INVALID, INVALID, INVALID,
881/* [6C] */ INVALID, INVALID, INVALID, INVALID,
882
883/* [70] */ TNSZ("vpshuflw",VEX_MXI,16),INVALID, INVALID, INVALID,
884/* [74] */ INVALID, INVALID, INVALID, INVALID,
885/* [78] */ INVALID, INVALID, INVALID, INVALID,
886/* [7C] */ TNSZ("vhaddps",VEX_RMrX,8), TNSZ("vhsubps",VEX_RMrX,8), INVALID, INVALID,
887
888/* [80] */ INVALID, INVALID, INVALID, INVALID,
889/* [84] */ INVALID, INVALID, INVALID, INVALID,
890/* [88] */ INVALID, INVALID, INVALID, INVALID,
891/* [0C] */ INVALID, INVALID, INVALID, INVALID,
892
893/* [90] */ INVALID, INVALID, INVALID, INVALID,
894/* [94] */ INVALID, INVALID, INVALID, INVALID,
895/* [98] */ INVALID, INVALID, INVALID, INVALID,
896/* [9C] */ INVALID, INVALID, INVALID, INVALID,
897
898/* [A0] */ INVALID, INVALID, INVALID, INVALID,
899/* [A4] */ INVALID, INVALID, INVALID, INVALID,
900/* [A8] */ INVALID, INVALID, INVALID, INVALID,
901/* [AC] */ INVALID, INVALID, INVALID, INVALID,
902
903/* [B0] */ INVALID, INVALID, INVALID, INVALID,
904/* [B4] */ INVALID, INVALID, INVALID, INVALID,
905/* [B8] */ INVALID, INVALID, INVALID, INVALID,
906/* [BC] */ INVALID, INVALID, INVALID, INVALID,
907
908/* [C0] */ INVALID, INVALID, TNSZ("vcmpsd",VEX_RMRX,8), INVALID,
909/* [C4] */ INVALID, INVALID, INVALID, INVALID,
910/* [C8] */ INVALID, INVALID, INVALID, INVALID,
911/* [CC] */ INVALID, INVALID, INVALID, INVALID,
912
913/* [D0] */ TNSZ("vaddsubps",VEX_RMrX,8), INVALID, INVALID, INVALID,
914/* [D4] */ INVALID, INVALID, INVALID, INVALID,
915/* [D8] */ INVALID, INVALID, INVALID, INVALID,
916/* [DC] */ INVALID, INVALID, INVALID, INVALID,
917
918/* [E0] */ INVALID, INVALID, INVALID, INVALID,
919/* [E4] */ INVALID, INVALID, TNSZ("vcvtpd2dq",VEX_MX,16),INVALID,
920/* [E8] */ INVALID, INVALID, INVALID, INVALID,
921/* [EC] */ INVALID, INVALID, INVALID, INVALID,
922
923/* [F0] */ TNSZ("vlddqu",VEX_MX,16), INVALID, INVALID, INVALID,
924/* [F4] */ INVALID, INVALID, INVALID, INVALID,
925/* [F8] */ INVALID, INVALID, INVALID, INVALID,
926/* [FC] */ INVALID, INVALID, INVALID, INVALID,
927};
928
929/*
930 * Decode table for SIMD instructions with the repz (0xf3) prefix.
931 */
932const instable_t dis_opSIMDrepz[256] = {
933/* [00] */ INVALID, INVALID, INVALID, INVALID,
934/* [04] */ INVALID, INVALID, INVALID, INVALID,
935/* [08] */ INVALID, INVALID, INVALID, INVALID,
936/* [0C] */ INVALID, INVALID, INVALID, INVALID,
937
938/* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), INVALID, INVALID,
939/* [14] */ INVALID, INVALID, INVALID, INVALID,
940/* [18] */ INVALID, INVALID, INVALID, INVALID,
941/* [1C] */ INVALID, INVALID, INVALID, INVALID,
942
943/* [20] */ INVALID, INVALID, INVALID, INVALID,
944/* [24] */ INVALID, INVALID, INVALID, INVALID,
945/* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),TNSZ("movntss",XMMMS,4),
946/* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID,
947
948/* [30] */ INVALID, INVALID, INVALID, INVALID,
949/* [34] */ INVALID, INVALID, INVALID, INVALID,
950/* [38] */ INVALID, INVALID, INVALID, INVALID,
951/* [3C] */ INVALID, INVALID, INVALID, INVALID,
952
953/* [40] */ INVALID, INVALID, INVALID, INVALID,
954/* [44] */ INVALID, INVALID, INVALID, INVALID,
955/* [48] */ INVALID, INVALID, INVALID, INVALID,
956/* [4C] */ INVALID, INVALID, INVALID, INVALID,
957
958/* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4),
959/* [54] */ INVALID, INVALID, INVALID, INVALID,
960/* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16),
961/* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4),
962
963/* [60] */ INVALID, INVALID, INVALID, INVALID,
964/* [64] */ INVALID, INVALID, INVALID, INVALID,
965/* [68] */ INVALID, INVALID, INVALID, INVALID,
966/* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16),
967
968/* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID,
969/* [74] */ INVALID, INVALID, INVALID, INVALID,
970/* [78] */ INVALID, INVALID, INVALID, INVALID,
971/* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16),
972
973/* [80] */ INVALID, INVALID, INVALID, INVALID,
974/* [84] */ INVALID, INVALID, INVALID, INVALID,
975/* [88] */ INVALID, INVALID, INVALID, INVALID,
976/* [0C] */ INVALID, INVALID, INVALID, INVALID,
977
978/* [90] */ INVALID, INVALID, INVALID, INVALID,
979/* [94] */ INVALID, INVALID, INVALID, INVALID,
980/* [98] */ INVALID, INVALID, INVALID, INVALID,
981/* [9C] */ INVALID, INVALID, INVALID, INVALID,
982
983/* [A0] */ INVALID, INVALID, INVALID, INVALID,
984/* [A4] */ INVALID, INVALID, INVALID, INVALID,
985/* [A8] */ INVALID, INVALID, INVALID, INVALID,
986/* [AC] */ INVALID, INVALID, INVALID, INVALID,
987
988/* [B0] */ INVALID, INVALID, INVALID, INVALID,
989/* [B4] */ INVALID, INVALID, INVALID, INVALID,
990/* [B8] */ TS("popcnt",MRw), INVALID, INVALID, INVALID,
991/* [BC] */ INVALID, TS("lzcnt",MRw), INVALID, INVALID,
992
993/* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID,
994/* [C4] */ INVALID, INVALID, INVALID, INVALID,
995/* [C8] */ INVALID, INVALID, INVALID, INVALID,
996/* [CC] */ INVALID, INVALID, INVALID, INVALID,
997
998/* [D0] */ INVALID, INVALID, INVALID, INVALID,
999/* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID,
1000/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1001/* [DC] */ INVALID, INVALID, INVALID, INVALID,
1002
1003/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1004/* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID,
1005/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1006/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1007
1008/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1009/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1010/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1011/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1012};
1013
1014const instable_t dis_opAVXF30F[256] = {
1015/* [00] */ INVALID, INVALID, INVALID, INVALID,
1016/* [04] */ INVALID, INVALID, INVALID, INVALID,
1017/* [08] */ INVALID, INVALID, INVALID, INVALID,
1018/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1019
1020/* [10] */ TNSZ("vmovss",VEX_RMrX,4), TNSZ("vmovss",VEX_RRX,4), TNSZ("vmovsldup",VEX_MX,4), INVALID,
1021/* [14] */ INVALID, INVALID, TNSZ("vmovshdup",VEX_MX,4), INVALID,
1022/* [18] */ INVALID, INVALID, INVALID, INVALID,
1023/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1024
1025/* [20] */ INVALID, INVALID, INVALID, INVALID,
1026/* [24] */ INVALID, INVALID, INVALID, INVALID,
1027/* [28] */ INVALID, INVALID, TNSZ("vcvtsi2ss",VEX_RMrX,4),INVALID,
1028/* [2C] */ TNSZ("vcvttss2si",VEX_MR,4),TNSZ("vcvtss2si",VEX_MR,4),INVALID, INVALID,
1029
1030/* [30] */ INVALID, INVALID, INVALID, INVALID,
1031/* [34] */ INVALID, INVALID, INVALID, INVALID,
1032/* [38] */ INVALID, INVALID, INVALID, INVALID,
1033/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1034
1035/* [40] */ INVALID, INVALID, INVALID, INVALID,
1036/* [44] */ INVALID, INVALID, INVALID, INVALID,
1037/* [48] */ INVALID, INVALID, INVALID, INVALID,
1038/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1039
1040/* [50] */ INVALID, TNSZ("vsqrtss",VEX_RMrX,4), TNSZ("vrsqrtss",VEX_RMrX,4), TNSZ("vrcpss",VEX_RMrX,4),
1041/* [54] */ INVALID, INVALID, INVALID, INVALID,
1042/* [58] */ TNSZ("vaddss",VEX_RMrX,4), TNSZ("vmulss",VEX_RMrX,4), TNSZ("vcvtss2sd",VEX_RMrX,4), TNSZ("vcvttps2dq",VEX_MX,16),
1043/* [5C] */ TNSZ("vsubss",VEX_RMrX,4), TNSZ("vminss",VEX_RMrX,4), TNSZ("vdivss",VEX_RMrX,4), TNSZ("vmaxss",VEX_RMrX,4),
1044
1045/* [60] */ INVALID, INVALID, INVALID, INVALID,
1046/* [64] */ INVALID, INVALID, INVALID, INVALID,
1047/* [68] */ INVALID, INVALID, INVALID, INVALID,
1048/* [6C] */ INVALID, INVALID, INVALID, TNSZ("vmovdqu",VEX_MX,16),
1049
1050/* [70] */ TNSZ("vpshufhw",VEX_MXI,16),INVALID, INVALID, INVALID,
1051/* [74] */ INVALID, INVALID, INVALID, INVALID,
1052/* [78] */ INVALID, INVALID, INVALID, INVALID,
1053/* [7C] */ INVALID, INVALID, TNSZ("vmovq",VEX_MX,8), TNSZ("vmovdqu",VEX_RX,16),
1054
1055/* [80] */ INVALID, INVALID, INVALID, INVALID,
1056/* [84] */ INVALID, INVALID, INVALID, INVALID,
1057/* [88] */ INVALID, INVALID, INVALID, INVALID,
1058/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1059
1060/* [90] */ INVALID, INVALID, INVALID, INVALID,
1061/* [94] */ INVALID, INVALID, INVALID, INVALID,
1062/* [98] */ INVALID, INVALID, INVALID, INVALID,
1063/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1064
1065/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1066/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1067/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1068/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1069
1070/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1071/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1072/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1073/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1074
1075/* [C0] */ INVALID, INVALID, TNSZ("vcmpss",VEX_RMRX,4), INVALID,
1076/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1077/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1078/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1079
1080/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1081/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1082/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1083/* [DC] */ INVALID, INVALID, INVALID, INVALID,
1084
1085/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1086/* [E4] */ INVALID, INVALID, TNSZ("vcvtdq2pd",VEX_MX,8), INVALID,
1087/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1088/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1089
1090/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1091/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1092/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1093/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1094};
1095/*
1096 * The following two tables are used to encode crc32 and movbe
1097 * since they share the same opcodes.
1098 */
1099const instable_t dis_op0F38F0[2] = {
1100/* [00] */ TNS("crc32b",CRC32),
1101 TS("movbe",MOVBE),
1102};
1103
1104const instable_t dis_op0F38F1[2] = {
1105/* [00] */ TS("crc32",CRC32),
1106 TS("movbe",MOVBE),
1107};
1108
1109const instable_t dis_op0F38[256] = {
1110/* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16),
1111/* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16),
1112/* [08] */ TNSZ("psignb",XMM_66o,16),TNSZ("psignw",XMM_66o,16),TNSZ("psignd",XMM_66o,16),TNSZ("pmulhrsw",XMM_66o,16),
1113/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1114
1115/* [10] */ TNSZ("pblendvb",XMM_66r,16),INVALID, INVALID, INVALID,
1116/* [14] */ TNSZ("blendvps",XMM_66r,16),TNSZ("blendvpd",XMM_66r,16),INVALID, TNSZ("ptest",XMM_66r,16),
1117/* [18] */ INVALID, INVALID, INVALID, INVALID,
1118/* [1C] */ TNSZ("pabsb",XMM_66o,16),TNSZ("pabsw",XMM_66o,16),TNSZ("pabsd",XMM_66o,16),INVALID,
1119
1120/* [20] */ TNSZ("pmovsxbw",XMM_66r,16),TNSZ("pmovsxbd",XMM_66r,16),TNSZ("pmovsxbq",XMM_66r,16),TNSZ("pmovsxwd",XMM_66r,16),
1121/* [24] */ TNSZ("pmovsxwq",XMM_66r,16),TNSZ("pmovsxdq",XMM_66r,16),INVALID, INVALID,
1122/* [28] */ TNSZ("pmuldq",XMM_66r,16),TNSZ("pcmpeqq",XMM_66r,16),TNSZ("movntdqa",XMMM_66r,16),TNSZ("packusdw",XMM_66r,16),
1123/* [2C] */ INVALID, INVALID, INVALID, INVALID,
1124
1125/* [30] */ TNSZ("pmovzxbw",XMM_66r,16),TNSZ("pmovzxbd",XMM_66r,16),TNSZ("pmovzxbq",XMM_66r,16),TNSZ("pmovzxwd",XMM_66r,16),
1126/* [34] */ TNSZ("pmovzxwq",XMM_66r,16),TNSZ("pmovzxdq",XMM_66r,16),INVALID, TNSZ("pcmpgtq",XMM_66r,16),
1127/* [38] */ TNSZ("pminsb",XMM_66r,16),TNSZ("pminsd",XMM_66r,16),TNSZ("pminuw",XMM_66r,16),TNSZ("pminud",XMM_66r,16),
1128/* [3C] */ TNSZ("pmaxsb",XMM_66r,16),TNSZ("pmaxsd",XMM_66r,16),TNSZ("pmaxuw",XMM_66r,16),TNSZ("pmaxud",XMM_66r,16),
1129
1130/* [40] */ TNSZ("pmulld",XMM_66r,16),TNSZ("phminposuw",XMM_66r,16),INVALID, INVALID,
1131/* [44] */ INVALID, INVALID, INVALID, INVALID,
1132/* [48] */ INVALID, INVALID, INVALID, INVALID,
1133/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1134
1135/* [50] */ INVALID, INVALID, INVALID, INVALID,
1136/* [54] */ INVALID, INVALID, INVALID, INVALID,
1137/* [58] */ INVALID, INVALID, INVALID, INVALID,
1138/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1139
1140/* [60] */ INVALID, INVALID, INVALID, INVALID,
1141/* [64] */ INVALID, INVALID, INVALID, INVALID,
1142/* [68] */ INVALID, INVALID, INVALID, INVALID,
1143/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1144
1145/* [70] */ INVALID, INVALID, INVALID, INVALID,
1146/* [74] */ INVALID, INVALID, INVALID, INVALID,
1147/* [78] */ INVALID, INVALID, INVALID, INVALID,
1148/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1149
577 * Decode table for 0x0FC8 opcode -- 486 bswap instruction
578 *
579 *bit pattern: 0000 1111 1100 1reg
580 */
581const instable_t dis_op0FC8[4] = {
582/* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID,
583};
584
585/*
586 * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions
587 */
588const instable_t dis_op0F7123[4][8] = {
589{
590/* [70].0 */ INVALID, INVALID, INVALID, INVALID,
591/* .4 */ INVALID, INVALID, INVALID, INVALID,
592}, {
593/* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID,
594/* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID,
595}, {
596/* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID,
597/* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID,
598}, {
599/* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH),
600/* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH),
601} };
602
603/*
604 * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes.
605 */
606const instable_t dis_opSIMD7123[32] = {
607/* [70].0 */ INVALID, INVALID, INVALID, INVALID,
608/* .4 */ INVALID, INVALID, INVALID, INVALID,
609
610/* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID,
611/* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID,
612
613/* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID,
614/* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID,
615
616/* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH),
617/* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH),
618};
619
620/*
621 * SIMD instructions have been wedged into the existing IA32 instruction
622 * set through the use of prefixes. That is, while 0xf0 0x58 may be
623 * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different
624 * instruction - addss. At present, three prefixes have been coopted in
625 * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The
626 * following tables are used to provide the prefixed instruction names.
627 * The arrays are sparse, but they're fast.
628 */
629
630/*
631 * Decode table for SIMD instructions with the address size (0x66) prefix.
632 */
633const instable_t dis_opSIMDdata16[256] = {
634/* [00] */ INVALID, INVALID, INVALID, INVALID,
635/* [04] */ INVALID, INVALID, INVALID, INVALID,
636/* [08] */ INVALID, INVALID, INVALID, INVALID,
637/* [0C] */ INVALID, INVALID, INVALID, INVALID,
638
639/* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8),
640/* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8),
641/* [18] */ INVALID, INVALID, INVALID, INVALID,
642/* [1C] */ INVALID, INVALID, INVALID, INVALID,
643
644/* [20] */ INVALID, INVALID, INVALID, INVALID,
645/* [24] */ INVALID, INVALID, INVALID, INVALID,
646/* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16),
647/* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8),
648
649/* [30] */ INVALID, INVALID, INVALID, INVALID,
650/* [34] */ INVALID, INVALID, INVALID, INVALID,
651/* [38] */ INVALID, INVALID, INVALID, INVALID,
652/* [3C] */ INVALID, INVALID, INVALID, INVALID,
653
654/* [40] */ INVALID, INVALID, INVALID, INVALID,
655/* [44] */ INVALID, INVALID, INVALID, INVALID,
656/* [48] */ INVALID, INVALID, INVALID, INVALID,
657/* [4C] */ INVALID, INVALID, INVALID, INVALID,
658
659/* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID,
660/* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16),
661/* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16),
662/* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16),
663
664/* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16),
665/* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16),
666/* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16),
667/* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16),
668
669/* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID,
670/* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID,
671/* [78] */ TNSZ("extrq",XMM2I,16), TNSZ("extrq",XMM,16), INVALID, INVALID,
672/* [7C] */ INVALID, INVALID, TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16),
673
674/* [80] */ INVALID, INVALID, INVALID, INVALID,
675/* [84] */ INVALID, INVALID, INVALID, INVALID,
676/* [88] */ INVALID, INVALID, INVALID, INVALID,
677/* [8C] */ INVALID, INVALID, INVALID, INVALID,
678
679/* [90] */ INVALID, INVALID, INVALID, INVALID,
680/* [94] */ INVALID, INVALID, INVALID, INVALID,
681/* [98] */ INVALID, INVALID, INVALID, INVALID,
682/* [9C] */ INVALID, INVALID, INVALID, INVALID,
683
684/* [A0] */ INVALID, INVALID, INVALID, INVALID,
685/* [A4] */ INVALID, INVALID, INVALID, INVALID,
686/* [A8] */ INVALID, INVALID, INVALID, INVALID,
687/* [AC] */ INVALID, INVALID, INVALID, INVALID,
688
689/* [B0] */ INVALID, INVALID, INVALID, INVALID,
690/* [B4] */ INVALID, INVALID, INVALID, INVALID,
691/* [B8] */ INVALID, INVALID, INVALID, INVALID,
692/* [BC] */ INVALID, INVALID, INVALID, INVALID,
693
694/* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID,
695/* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID,
696/* [C8] */ INVALID, INVALID, INVALID, INVALID,
697/* [CC] */ INVALID, INVALID, INVALID, INVALID,
698
699/* [D0] */ INVALID, TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16),
700/* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3),
701/* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16),
702/* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16),
703
704/* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16),
705/* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16),
706/* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16),
707/* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16),
708
709/* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16),
710/* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16),
711/* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16),
712/* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID,
713};
714
715const instable_t dis_opAVX660F[256] = {
716/* [00] */ INVALID, INVALID, INVALID, INVALID,
717/* [04] */ INVALID, INVALID, INVALID, INVALID,
718/* [08] */ INVALID, INVALID, INVALID, INVALID,
719/* [0C] */ INVALID, INVALID, INVALID, INVALID,
720
721/* [10] */ TNSZ("vmovupd",VEX_MX,16), TNSZ("vmovupd",VEX_RX,16), TNSZ("vmovlpd",VEX_RMrX,8), TNSZ("vmovlpd",VEX_RM,8),
722/* [14] */ TNSZ("vunpcklpd",VEX_RMrX,16),TNSZ("vunpckhpd",VEX_RMrX,16),TNSZ("vmovhpd",VEX_RMrX,8), TNSZ("vmovhpd",VEX_RM,8),
723/* [18] */ INVALID, INVALID, INVALID, INVALID,
724/* [1C] */ INVALID, INVALID, INVALID, INVALID,
725
726/* [20] */ INVALID, INVALID, INVALID, INVALID,
727/* [24] */ INVALID, INVALID, INVALID, INVALID,
728/* [28] */ TNSZ("vmovapd",VEX_MX,16), TNSZ("vmovapd",VEX_RX,16), INVALID, TNSZ("vmovntpd",VEX_RM,16),
729/* [2C] */ INVALID, INVALID, TNSZ("vucomisd",VEX_MX,8),TNSZ("vcomisd",VEX_MX,8),
730
731/* [30] */ INVALID, INVALID, INVALID, INVALID,
732/* [34] */ INVALID, INVALID, INVALID, INVALID,
733/* [38] */ INVALID, INVALID, INVALID, INVALID,
734/* [3C] */ INVALID, INVALID, INVALID, INVALID,
735
736/* [40] */ INVALID, INVALID, INVALID, INVALID,
737/* [44] */ INVALID, INVALID, INVALID, INVALID,
738/* [48] */ INVALID, INVALID, INVALID, INVALID,
739/* [4C] */ INVALID, INVALID, INVALID, INVALID,
740
741/* [50] */ TNS("vmovmskpd",VEX_MR), TNSZ("vsqrtpd",VEX_MX,16), INVALID, INVALID,
742/* [54] */ TNSZ("vandpd",VEX_RMrX,16), TNSZ("vandnpd",VEX_RMrX,16), TNSZ("vorpd",VEX_RMrX,16), TNSZ("vxorpd",VEX_RMrX,16),
743/* [58] */ TNSZ("vaddpd",VEX_RMrX,16), TNSZ("vmulpd",VEX_RMrX,16), TNSZ("vcvtpd2ps",VEX_MX,16),TNSZ("vcvtps2dq",VEX_MX,16),
744/* [5C] */ TNSZ("vsubpd",VEX_RMrX,16), TNSZ("vminpd",VEX_RMrX,16), TNSZ("vdivpd",VEX_RMrX,16), TNSZ("vmaxpd",VEX_RMrX,16),
745
746/* [60] */ TNSZ("vpunpcklbw",VEX_RMrX,16),TNSZ("vpunpcklwd",VEX_RMrX,16),TNSZ("vpunpckldq",VEX_RMrX,16),TNSZ("vpacksswb",VEX_RMrX,16),
747/* [64] */ TNSZ("vpcmpgtb",VEX_RMrX,16), TNSZ("vpcmpgtw",VEX_RMrX,16), TNSZ("vpcmpgtd",VEX_RMrX,16), TNSZ("vpackuswb",VEX_RMrX,16),
748/* [68] */ TNSZ("vpunpckhbw",VEX_RMrX,16),TNSZ("vpunpckhwd",VEX_RMrX,16),TNSZ("vpunpckhdq",VEX_RMrX,16),TNSZ("vpackssdw",VEX_RMrX,16),
749/* [6C] */ TNSZ("vpunpcklqdq",VEX_RMrX,16),TNSZ("vpunpckhqdq",VEX_RMrX,16),TNSZ("vmovd",VEX_MX,4),TNSZ("vmovdqa",VEX_MX,16),
750
751/* [70] */ TNSZ("vpshufd",VEX_MXI,16), TNSZ("vgrp71",VEX_XXI,16), TNSZ("vgrp72",VEX_XXI,16), TNSZ("vgrp73",VEX_XXI,16),
752/* [74] */ TNSZ("vpcmpeqb",VEX_RMrX,16), TNSZ("vpcmpeqw",VEX_RMrX,16), TNSZ("vpcmpeqd",VEX_RMrX,16), INVALID,
753/* [78] */ INVALID, INVALID, INVALID, INVALID,
754/* [7C] */ TNSZ("vhaddpd",VEX_RMrX,16), TNSZ("vhsubpd",VEX_RMrX,16), TNSZ("vmovd",VEX_RR,4), TNSZ("vmovdqa",VEX_RX,16),
755
756/* [80] */ INVALID, INVALID, INVALID, INVALID,
757/* [84] */ INVALID, INVALID, INVALID, INVALID,
758/* [88] */ INVALID, INVALID, INVALID, INVALID,
759/* [8C] */ INVALID, INVALID, INVALID, INVALID,
760
761/* [90] */ INVALID, INVALID, INVALID, INVALID,
762/* [94] */ INVALID, INVALID, INVALID, INVALID,
763/* [98] */ INVALID, INVALID, INVALID, INVALID,
764/* [9C] */ INVALID, INVALID, INVALID, INVALID,
765
766/* [A0] */ INVALID, INVALID, INVALID, INVALID,
767/* [A4] */ INVALID, INVALID, INVALID, INVALID,
768/* [A8] */ INVALID, INVALID, INVALID, INVALID,
769/* [AC] */ INVALID, INVALID, INVALID, INVALID,
770
771/* [B0] */ INVALID, INVALID, INVALID, INVALID,
772/* [B4] */ INVALID, INVALID, INVALID, INVALID,
773/* [B8] */ INVALID, INVALID, INVALID, INVALID,
774/* [BC] */ INVALID, INVALID, INVALID, INVALID,
775
776/* [C0] */ INVALID, INVALID, TNSZ("vcmppd",VEX_RMRX,16), INVALID,
777/* [C4] */ TNSZ("vpinsrw",VEX_RMRX,2),TNS("vpextrw",VEX_MR), TNSZ("vshufpd",VEX_RMRX,16), INVALID,
778/* [C8] */ INVALID, INVALID, INVALID, INVALID,
779/* [CC] */ INVALID, INVALID, INVALID, INVALID,
780
781/* [D0] */ TNSZ("vaddsubpd",VEX_RMrX,16),TNSZ("vpsrlw",VEX_RMrX,16), TNSZ("vpsrld",VEX_RMrX,16), TNSZ("vpsrlq",VEX_RMrX,16),
782/* [D4] */ TNSZ("vpaddq",VEX_RMrX,16), TNSZ("vpmullw",VEX_RMrX,16), TNSZ("vmovq",VEX_RX,8), TNS("vpmovmskb",VEX_MR),
783/* [D8] */ TNSZ("vpsubusb",VEX_RMrX,16), TNSZ("vpsubusw",VEX_RMrX,16), TNSZ("vpminub",VEX_RMrX,16), TNSZ("vpand",VEX_RMrX,16),
784/* [DC] */ TNSZ("vpaddusb",VEX_RMrX,16), TNSZ("vpaddusw",VEX_RMrX,16), TNSZ("vpmaxub",VEX_RMrX,16), TNSZ("vpandn",VEX_RMrX,16),
785
786/* [E0] */ TNSZ("vpavgb",VEX_RMrX,16), TNSZ("vpsraw",VEX_RMrX,16), TNSZ("vpsrad",VEX_RMrX,16), TNSZ("vpavgw",VEX_RMrX,16),
787/* [E4] */ TNSZ("vpmulhuw",VEX_RMrX,16), TNSZ("vpmulhw",VEX_RMrX,16), TNSZ("vcvttpd2dq",VEX_MX,16),TNSZ("vmovntdq",VEX_RM,16),
788/* [E8] */ TNSZ("vpsubsb",VEX_RMrX,16), TNSZ("vpsubsw",VEX_RMrX,16), TNSZ("vpminsw",VEX_RMrX,16), TNSZ("vpor",VEX_RMrX,16),
789/* [EC] */ TNSZ("vpaddsb",VEX_RMrX,16), TNSZ("vpaddsw",VEX_RMrX,16), TNSZ("vpmaxsw",VEX_RMrX,16), TNSZ("vpxor",VEX_RMrX,16),
790
791/* [F0] */ INVALID, TNSZ("vpsllw",VEX_RMrX,16), TNSZ("vpslld",VEX_RMrX,16), TNSZ("vpsllq",VEX_RMrX,16),
792/* [F4] */ TNSZ("vpmuludq",VEX_RMrX,16), TNSZ("vpmaddwd",VEX_RMrX,16), TNSZ("vpsadbw",VEX_RMrX,16), TNS("vmaskmovdqu",VEX_MX),
793/* [F8] */ TNSZ("vpsubb",VEX_RMrX,16), TNSZ("vpsubw",VEX_RMrX,16), TNSZ("vpsubd",VEX_RMrX,16), TNSZ("vpsubq",VEX_RMrX,16),
794/* [FC] */ TNSZ("vpaddb",VEX_RMrX,16), TNSZ("vpaddw",VEX_RMrX,16), TNSZ("vpaddd",VEX_RMrX,16), INVALID,
795};
796
797/*
798 * Decode table for SIMD instructions with the repnz (0xf2) prefix.
799 */
800const instable_t dis_opSIMDrepnz[256] = {
801/* [00] */ INVALID, INVALID, INVALID, INVALID,
802/* [04] */ INVALID, INVALID, INVALID, INVALID,
803/* [08] */ INVALID, INVALID, INVALID, INVALID,
804/* [0C] */ INVALID, INVALID, INVALID, INVALID,
805
806/* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), INVALID, INVALID,
807/* [14] */ INVALID, INVALID, INVALID, INVALID,
808/* [18] */ INVALID, INVALID, INVALID, INVALID,
809/* [1C] */ INVALID, INVALID, INVALID, INVALID,
810
811/* [20] */ INVALID, INVALID, INVALID, INVALID,
812/* [24] */ INVALID, INVALID, INVALID, INVALID,
813/* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),TNSZ("movntsd",XMMMS,8),
814/* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID,
815
816/* [30] */ INVALID, INVALID, INVALID, INVALID,
817/* [34] */ INVALID, INVALID, INVALID, INVALID,
818/* [38] */ INVALID, INVALID, INVALID, INVALID,
819/* [3C] */ INVALID, INVALID, INVALID, INVALID,
820
821/* [40] */ INVALID, INVALID, INVALID, INVALID,
822/* [44] */ INVALID, INVALID, INVALID, INVALID,
823/* [48] */ INVALID, INVALID, INVALID, INVALID,
824/* [4C] */ INVALID, INVALID, INVALID, INVALID,
825
826/* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID,
827/* [54] */ INVALID, INVALID, INVALID, INVALID,
828/* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID,
829/* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8),
830
831/* [60] */ INVALID, INVALID, INVALID, INVALID,
832/* [64] */ INVALID, INVALID, INVALID, INVALID,
833/* [68] */ INVALID, INVALID, INVALID, INVALID,
834/* [6C] */ INVALID, INVALID, INVALID, INVALID,
835
836/* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID,
837/* [74] */ INVALID, INVALID, INVALID, INVALID,
838/* [78] */ TNSZ("insertq",XMMX2I,16),TNSZ("insertq",XMM,8),INVALID, INVALID,
839/* [7C] */ INVALID, INVALID, INVALID, INVALID,
840
841/* [80] */ INVALID, INVALID, INVALID, INVALID,
842/* [84] */ INVALID, INVALID, INVALID, INVALID,
843/* [88] */ INVALID, INVALID, INVALID, INVALID,
844/* [0C] */ INVALID, INVALID, INVALID, INVALID,
845
846/* [90] */ INVALID, INVALID, INVALID, INVALID,
847/* [94] */ INVALID, INVALID, INVALID, INVALID,
848/* [98] */ INVALID, INVALID, INVALID, INVALID,
849/* [9C] */ INVALID, INVALID, INVALID, INVALID,
850
851/* [A0] */ INVALID, INVALID, INVALID, INVALID,
852/* [A4] */ INVALID, INVALID, INVALID, INVALID,
853/* [A8] */ INVALID, INVALID, INVALID, INVALID,
854/* [AC] */ INVALID, INVALID, INVALID, INVALID,
855
856/* [B0] */ INVALID, INVALID, INVALID, INVALID,
857/* [B4] */ INVALID, INVALID, INVALID, INVALID,
858/* [B8] */ INVALID, INVALID, INVALID, INVALID,
859/* [BC] */ INVALID, INVALID, INVALID, INVALID,
860
861/* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID,
862/* [C4] */ INVALID, INVALID, INVALID, INVALID,
863/* [C8] */ INVALID, INVALID, INVALID, INVALID,
864/* [CC] */ INVALID, INVALID, INVALID, INVALID,
865
866/* [D0] */ INVALID, INVALID, INVALID, INVALID,
867/* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID,
868/* [D8] */ INVALID, INVALID, INVALID, INVALID,
869/* [DC] */ INVALID, INVALID, INVALID, INVALID,
870
871/* [E0] */ INVALID, INVALID, INVALID, INVALID,
872/* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID,
873/* [E8] */ INVALID, INVALID, INVALID, INVALID,
874/* [EC] */ INVALID, INVALID, INVALID, INVALID,
875
876/* [F0] */ INVALID, INVALID, INVALID, INVALID,
877/* [F4] */ INVALID, INVALID, INVALID, INVALID,
878/* [F8] */ INVALID, INVALID, INVALID, INVALID,
879/* [FC] */ INVALID, INVALID, INVALID, INVALID,
880};
881
882const instable_t dis_opAVXF20F[256] = {
883/* [00] */ INVALID, INVALID, INVALID, INVALID,
884/* [04] */ INVALID, INVALID, INVALID, INVALID,
885/* [08] */ INVALID, INVALID, INVALID, INVALID,
886/* [0C] */ INVALID, INVALID, INVALID, INVALID,
887
888/* [10] */ TNSZ("vmovsd",VEX_RMrX,8), TNSZ("vmovsd",VEX_RRX,8), TNSZ("vmovddup",VEX_MX,8), INVALID,
889/* [14] */ INVALID, INVALID, INVALID, INVALID,
890/* [18] */ INVALID, INVALID, INVALID, INVALID,
891/* [1C] */ INVALID, INVALID, INVALID, INVALID,
892
893/* [20] */ INVALID, INVALID, INVALID, INVALID,
894/* [24] */ INVALID, INVALID, INVALID, INVALID,
895/* [28] */ INVALID, INVALID, TNSZ("vcvtsi2sd",VEX_RMrX,4),INVALID,
896/* [2C] */ TNSZ("vcvttsd2si",VEX_MR,8),TNSZ("vcvtsd2si",VEX_MR,8),INVALID, INVALID,
897
898/* [30] */ INVALID, INVALID, INVALID, INVALID,
899/* [34] */ INVALID, INVALID, INVALID, INVALID,
900/* [38] */ INVALID, INVALID, INVALID, INVALID,
901/* [3C] */ INVALID, INVALID, INVALID, INVALID,
902
903/* [40] */ INVALID, INVALID, INVALID, INVALID,
904/* [44] */ INVALID, INVALID, INVALID, INVALID,
905/* [48] */ INVALID, INVALID, INVALID, INVALID,
906/* [4C] */ INVALID, INVALID, INVALID, INVALID,
907
908/* [50] */ INVALID, TNSZ("vsqrtsd",VEX_RMrX,8), INVALID, INVALID,
909/* [54] */ INVALID, INVALID, INVALID, INVALID,
910/* [58] */ TNSZ("vaddsd",VEX_RMrX,8), TNSZ("vmulsd",VEX_RMrX,8), TNSZ("vcvtsd2ss",VEX_RMrX,8), INVALID,
911/* [5C] */ TNSZ("vsubsd",VEX_RMrX,8), TNSZ("vminsd",VEX_RMrX,8), TNSZ("vdivsd",VEX_RMrX,8), TNSZ("vmaxsd",VEX_RMrX,8),
912
913/* [60] */ INVALID, INVALID, INVALID, INVALID,
914/* [64] */ INVALID, INVALID, INVALID, INVALID,
915/* [68] */ INVALID, INVALID, INVALID, INVALID,
916/* [6C] */ INVALID, INVALID, INVALID, INVALID,
917
918/* [70] */ TNSZ("vpshuflw",VEX_MXI,16),INVALID, INVALID, INVALID,
919/* [74] */ INVALID, INVALID, INVALID, INVALID,
920/* [78] */ INVALID, INVALID, INVALID, INVALID,
921/* [7C] */ TNSZ("vhaddps",VEX_RMrX,8), TNSZ("vhsubps",VEX_RMrX,8), INVALID, INVALID,
922
923/* [80] */ INVALID, INVALID, INVALID, INVALID,
924/* [84] */ INVALID, INVALID, INVALID, INVALID,
925/* [88] */ INVALID, INVALID, INVALID, INVALID,
926/* [0C] */ INVALID, INVALID, INVALID, INVALID,
927
928/* [90] */ INVALID, INVALID, INVALID, INVALID,
929/* [94] */ INVALID, INVALID, INVALID, INVALID,
930/* [98] */ INVALID, INVALID, INVALID, INVALID,
931/* [9C] */ INVALID, INVALID, INVALID, INVALID,
932
933/* [A0] */ INVALID, INVALID, INVALID, INVALID,
934/* [A4] */ INVALID, INVALID, INVALID, INVALID,
935/* [A8] */ INVALID, INVALID, INVALID, INVALID,
936/* [AC] */ INVALID, INVALID, INVALID, INVALID,
937
938/* [B0] */ INVALID, INVALID, INVALID, INVALID,
939/* [B4] */ INVALID, INVALID, INVALID, INVALID,
940/* [B8] */ INVALID, INVALID, INVALID, INVALID,
941/* [BC] */ INVALID, INVALID, INVALID, INVALID,
942
943/* [C0] */ INVALID, INVALID, TNSZ("vcmpsd",VEX_RMRX,8), INVALID,
944/* [C4] */ INVALID, INVALID, INVALID, INVALID,
945/* [C8] */ INVALID, INVALID, INVALID, INVALID,
946/* [CC] */ INVALID, INVALID, INVALID, INVALID,
947
948/* [D0] */ TNSZ("vaddsubps",VEX_RMrX,8), INVALID, INVALID, INVALID,
949/* [D4] */ INVALID, INVALID, INVALID, INVALID,
950/* [D8] */ INVALID, INVALID, INVALID, INVALID,
951/* [DC] */ INVALID, INVALID, INVALID, INVALID,
952
953/* [E0] */ INVALID, INVALID, INVALID, INVALID,
954/* [E4] */ INVALID, INVALID, TNSZ("vcvtpd2dq",VEX_MX,16),INVALID,
955/* [E8] */ INVALID, INVALID, INVALID, INVALID,
956/* [EC] */ INVALID, INVALID, INVALID, INVALID,
957
958/* [F0] */ TNSZ("vlddqu",VEX_MX,16), INVALID, INVALID, INVALID,
959/* [F4] */ INVALID, INVALID, INVALID, INVALID,
960/* [F8] */ INVALID, INVALID, INVALID, INVALID,
961/* [FC] */ INVALID, INVALID, INVALID, INVALID,
962};
963
964/*
965 * Decode table for SIMD instructions with the repz (0xf3) prefix.
966 */
967const instable_t dis_opSIMDrepz[256] = {
968/* [00] */ INVALID, INVALID, INVALID, INVALID,
969/* [04] */ INVALID, INVALID, INVALID, INVALID,
970/* [08] */ INVALID, INVALID, INVALID, INVALID,
971/* [0C] */ INVALID, INVALID, INVALID, INVALID,
972
973/* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), INVALID, INVALID,
974/* [14] */ INVALID, INVALID, INVALID, INVALID,
975/* [18] */ INVALID, INVALID, INVALID, INVALID,
976/* [1C] */ INVALID, INVALID, INVALID, INVALID,
977
978/* [20] */ INVALID, INVALID, INVALID, INVALID,
979/* [24] */ INVALID, INVALID, INVALID, INVALID,
980/* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),TNSZ("movntss",XMMMS,4),
981/* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID,
982
983/* [30] */ INVALID, INVALID, INVALID, INVALID,
984/* [34] */ INVALID, INVALID, INVALID, INVALID,
985/* [38] */ INVALID, INVALID, INVALID, INVALID,
986/* [3C] */ INVALID, INVALID, INVALID, INVALID,
987
988/* [40] */ INVALID, INVALID, INVALID, INVALID,
989/* [44] */ INVALID, INVALID, INVALID, INVALID,
990/* [48] */ INVALID, INVALID, INVALID, INVALID,
991/* [4C] */ INVALID, INVALID, INVALID, INVALID,
992
993/* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4),
994/* [54] */ INVALID, INVALID, INVALID, INVALID,
995/* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16),
996/* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4),
997
998/* [60] */ INVALID, INVALID, INVALID, INVALID,
999/* [64] */ INVALID, INVALID, INVALID, INVALID,
1000/* [68] */ INVALID, INVALID, INVALID, INVALID,
1001/* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16),
1002
1003/* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID,
1004/* [74] */ INVALID, INVALID, INVALID, INVALID,
1005/* [78] */ INVALID, INVALID, INVALID, INVALID,
1006/* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16),
1007
1008/* [80] */ INVALID, INVALID, INVALID, INVALID,
1009/* [84] */ INVALID, INVALID, INVALID, INVALID,
1010/* [88] */ INVALID, INVALID, INVALID, INVALID,
1011/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1012
1013/* [90] */ INVALID, INVALID, INVALID, INVALID,
1014/* [94] */ INVALID, INVALID, INVALID, INVALID,
1015/* [98] */ INVALID, INVALID, INVALID, INVALID,
1016/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1017
1018/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1019/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1020/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1021/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1022
1023/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1024/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1025/* [B8] */ TS("popcnt",MRw), INVALID, INVALID, INVALID,
1026/* [BC] */ INVALID, TS("lzcnt",MRw), INVALID, INVALID,
1027
1028/* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID,
1029/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1030/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1031/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1032
1033/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1034/* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID,
1035/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1036/* [DC] */ INVALID, INVALID, INVALID, INVALID,
1037
1038/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1039/* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID,
1040/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1041/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1042
1043/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1044/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1045/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1046/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1047};
1048
1049const instable_t dis_opAVXF30F[256] = {
1050/* [00] */ INVALID, INVALID, INVALID, INVALID,
1051/* [04] */ INVALID, INVALID, INVALID, INVALID,
1052/* [08] */ INVALID, INVALID, INVALID, INVALID,
1053/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1054
1055/* [10] */ TNSZ("vmovss",VEX_RMrX,4), TNSZ("vmovss",VEX_RRX,4), TNSZ("vmovsldup",VEX_MX,4), INVALID,
1056/* [14] */ INVALID, INVALID, TNSZ("vmovshdup",VEX_MX,4), INVALID,
1057/* [18] */ INVALID, INVALID, INVALID, INVALID,
1058/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1059
1060/* [20] */ INVALID, INVALID, INVALID, INVALID,
1061/* [24] */ INVALID, INVALID, INVALID, INVALID,
1062/* [28] */ INVALID, INVALID, TNSZ("vcvtsi2ss",VEX_RMrX,4),INVALID,
1063/* [2C] */ TNSZ("vcvttss2si",VEX_MR,4),TNSZ("vcvtss2si",VEX_MR,4),INVALID, INVALID,
1064
1065/* [30] */ INVALID, INVALID, INVALID, INVALID,
1066/* [34] */ INVALID, INVALID, INVALID, INVALID,
1067/* [38] */ INVALID, INVALID, INVALID, INVALID,
1068/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1069
1070/* [40] */ INVALID, INVALID, INVALID, INVALID,
1071/* [44] */ INVALID, INVALID, INVALID, INVALID,
1072/* [48] */ INVALID, INVALID, INVALID, INVALID,
1073/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1074
1075/* [50] */ INVALID, TNSZ("vsqrtss",VEX_RMrX,4), TNSZ("vrsqrtss",VEX_RMrX,4), TNSZ("vrcpss",VEX_RMrX,4),
1076/* [54] */ INVALID, INVALID, INVALID, INVALID,
1077/* [58] */ TNSZ("vaddss",VEX_RMrX,4), TNSZ("vmulss",VEX_RMrX,4), TNSZ("vcvtss2sd",VEX_RMrX,4), TNSZ("vcvttps2dq",VEX_MX,16),
1078/* [5C] */ TNSZ("vsubss",VEX_RMrX,4), TNSZ("vminss",VEX_RMrX,4), TNSZ("vdivss",VEX_RMrX,4), TNSZ("vmaxss",VEX_RMrX,4),
1079
1080/* [60] */ INVALID, INVALID, INVALID, INVALID,
1081/* [64] */ INVALID, INVALID, INVALID, INVALID,
1082/* [68] */ INVALID, INVALID, INVALID, INVALID,
1083/* [6C] */ INVALID, INVALID, INVALID, TNSZ("vmovdqu",VEX_MX,16),
1084
1085/* [70] */ TNSZ("vpshufhw",VEX_MXI,16),INVALID, INVALID, INVALID,
1086/* [74] */ INVALID, INVALID, INVALID, INVALID,
1087/* [78] */ INVALID, INVALID, INVALID, INVALID,
1088/* [7C] */ INVALID, INVALID, TNSZ("vmovq",VEX_MX,8), TNSZ("vmovdqu",VEX_RX,16),
1089
1090/* [80] */ INVALID, INVALID, INVALID, INVALID,
1091/* [84] */ INVALID, INVALID, INVALID, INVALID,
1092/* [88] */ INVALID, INVALID, INVALID, INVALID,
1093/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1094
1095/* [90] */ INVALID, INVALID, INVALID, INVALID,
1096/* [94] */ INVALID, INVALID, INVALID, INVALID,
1097/* [98] */ INVALID, INVALID, INVALID, INVALID,
1098/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1099
1100/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1101/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1102/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1103/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1104
1105/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1106/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1107/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1108/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1109
1110/* [C0] */ INVALID, INVALID, TNSZ("vcmpss",VEX_RMRX,4), INVALID,
1111/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1112/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1113/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1114
1115/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1116/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1117/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1118/* [DC] */ INVALID, INVALID, INVALID, INVALID,
1119
1120/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1121/* [E4] */ INVALID, INVALID, TNSZ("vcvtdq2pd",VEX_MX,8), INVALID,
1122/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1123/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1124
1125/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1126/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1127/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1128/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1129};
1130/*
1131 * The following two tables are used to encode crc32 and movbe
1132 * since they share the same opcodes.
1133 */
1134const instable_t dis_op0F38F0[2] = {
1135/* [00] */ TNS("crc32b",CRC32),
1136 TS("movbe",MOVBE),
1137};
1138
1139const instable_t dis_op0F38F1[2] = {
1140/* [00] */ TS("crc32",CRC32),
1141 TS("movbe",MOVBE),
1142};
1143
1144const instable_t dis_op0F38[256] = {
1145/* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16),
1146/* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16),
1147/* [08] */ TNSZ("psignb",XMM_66o,16),TNSZ("psignw",XMM_66o,16),TNSZ("psignd",XMM_66o,16),TNSZ("pmulhrsw",XMM_66o,16),
1148/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1149
1150/* [10] */ TNSZ("pblendvb",XMM_66r,16),INVALID, INVALID, INVALID,
1151/* [14] */ TNSZ("blendvps",XMM_66r,16),TNSZ("blendvpd",XMM_66r,16),INVALID, TNSZ("ptest",XMM_66r,16),
1152/* [18] */ INVALID, INVALID, INVALID, INVALID,
1153/* [1C] */ TNSZ("pabsb",XMM_66o,16),TNSZ("pabsw",XMM_66o,16),TNSZ("pabsd",XMM_66o,16),INVALID,
1154
1155/* [20] */ TNSZ("pmovsxbw",XMM_66r,16),TNSZ("pmovsxbd",XMM_66r,16),TNSZ("pmovsxbq",XMM_66r,16),TNSZ("pmovsxwd",XMM_66r,16),
1156/* [24] */ TNSZ("pmovsxwq",XMM_66r,16),TNSZ("pmovsxdq",XMM_66r,16),INVALID, INVALID,
1157/* [28] */ TNSZ("pmuldq",XMM_66r,16),TNSZ("pcmpeqq",XMM_66r,16),TNSZ("movntdqa",XMMM_66r,16),TNSZ("packusdw",XMM_66r,16),
1158/* [2C] */ INVALID, INVALID, INVALID, INVALID,
1159
1160/* [30] */ TNSZ("pmovzxbw",XMM_66r,16),TNSZ("pmovzxbd",XMM_66r,16),TNSZ("pmovzxbq",XMM_66r,16),TNSZ("pmovzxwd",XMM_66r,16),
1161/* [34] */ TNSZ("pmovzxwq",XMM_66r,16),TNSZ("pmovzxdq",XMM_66r,16),INVALID, TNSZ("pcmpgtq",XMM_66r,16),
1162/* [38] */ TNSZ("pminsb",XMM_66r,16),TNSZ("pminsd",XMM_66r,16),TNSZ("pminuw",XMM_66r,16),TNSZ("pminud",XMM_66r,16),
1163/* [3C] */ TNSZ("pmaxsb",XMM_66r,16),TNSZ("pmaxsd",XMM_66r,16),TNSZ("pmaxuw",XMM_66r,16),TNSZ("pmaxud",XMM_66r,16),
1164
1165/* [40] */ TNSZ("pmulld",XMM_66r,16),TNSZ("phminposuw",XMM_66r,16),INVALID, INVALID,
1166/* [44] */ INVALID, INVALID, INVALID, INVALID,
1167/* [48] */ INVALID, INVALID, INVALID, INVALID,
1168/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1169
1170/* [50] */ INVALID, INVALID, INVALID, INVALID,
1171/* [54] */ INVALID, INVALID, INVALID, INVALID,
1172/* [58] */ INVALID, INVALID, INVALID, INVALID,
1173/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1174
1175/* [60] */ INVALID, INVALID, INVALID, INVALID,
1176/* [64] */ INVALID, INVALID, INVALID, INVALID,
1177/* [68] */ INVALID, INVALID, INVALID, INVALID,
1178/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1179
1180/* [70] */ INVALID, INVALID, INVALID, INVALID,
1181/* [74] */ INVALID, INVALID, INVALID, INVALID,
1182/* [78] */ INVALID, INVALID, INVALID, INVALID,
1183/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1184
1150/* [80] */ INVALID, INVALID, INVALID, INVALID,
1185/* [80] */ TNSy("invept", RM_66r), TNSy("invvpid", RM_66r),INVALID, INVALID,
1151/* [84] */ INVALID, INVALID, INVALID, INVALID,
1152/* [88] */ INVALID, INVALID, INVALID, INVALID,
1153/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1154
1155/* [90] */ INVALID, INVALID, INVALID, INVALID,
1156/* [94] */ INVALID, INVALID, INVALID, INVALID,
1157/* [98] */ INVALID, INVALID, INVALID, INVALID,
1158/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1159
1160/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1161/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1162/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1163/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1164
1165/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1166/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1167/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1168/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1169
1170/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1171/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1172/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1173/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1174
1175/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1176/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1177/* [D8] */ INVALID, INVALID, INVALID, TNSZ("aesimc",XMM_66r,16),
1178/* [DC] */ TNSZ("aesenc",XMM_66r,16),TNSZ("aesenclast",XMM_66r,16),TNSZ("aesdec",XMM_66r,16),TNSZ("aesdeclast",XMM_66r,16),
1179
1180/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1181/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1182/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1183/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1184/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID,
1185/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1186/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1187/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1188};
1189
1190const instable_t dis_opAVX660F38[256] = {
1191/* [00] */ TNSZ("vpshufb",VEX_RMrX,16),TNSZ("vphaddw",VEX_RMrX,16),TNSZ("vphaddd",VEX_RMrX,16),TNSZ("vphaddsw",VEX_RMrX,16),
1192/* [04] */ TNSZ("vpmaddubsw",VEX_RMrX,16),TNSZ("vphsubw",VEX_RMrX,16), TNSZ("vphsubd",VEX_RMrX,16),TNSZ("vphsubsw",VEX_RMrX,16),
1193/* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16),
1194/* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16),
1195
1186/* [84] */ INVALID, INVALID, INVALID, INVALID,
1187/* [88] */ INVALID, INVALID, INVALID, INVALID,
1188/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1189
1190/* [90] */ INVALID, INVALID, INVALID, INVALID,
1191/* [94] */ INVALID, INVALID, INVALID, INVALID,
1192/* [98] */ INVALID, INVALID, INVALID, INVALID,
1193/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1194
1195/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1196/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1197/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1198/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1199
1200/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1201/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1202/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1203/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1204
1205/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1206/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1207/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1208/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1209
1210/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1211/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1212/* [D8] */ INVALID, INVALID, INVALID, TNSZ("aesimc",XMM_66r,16),
1213/* [DC] */ TNSZ("aesenc",XMM_66r,16),TNSZ("aesenclast",XMM_66r,16),TNSZ("aesdec",XMM_66r,16),TNSZ("aesdeclast",XMM_66r,16),
1214
1215/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1216/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1217/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1218/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1219/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID,
1220/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1221/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1222/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1223};
1224
1225const instable_t dis_opAVX660F38[256] = {
1226/* [00] */ TNSZ("vpshufb",VEX_RMrX,16),TNSZ("vphaddw",VEX_RMrX,16),TNSZ("vphaddd",VEX_RMrX,16),TNSZ("vphaddsw",VEX_RMrX,16),
1227/* [04] */ TNSZ("vpmaddubsw",VEX_RMrX,16),TNSZ("vphsubw",VEX_RMrX,16), TNSZ("vphsubd",VEX_RMrX,16),TNSZ("vphsubsw",VEX_RMrX,16),
1228/* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16),
1229/* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16),
1230
1196/* [10] */ INVALID, INVALID, INVALID, INVALID,
1231/* [10] */ INVALID, INVALID, INVALID, TNSZ("vcvtph2ps",VEX_MX,16),
1197/* [14] */ INVALID, INVALID, INVALID, TNSZ("vptest",VEX_RRI,16),
1198/* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID,
1199/* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID,
1200
1201/* [20] */ TNSZ("vpmovsxbw",VEX_MX,16),TNSZ("vpmovsxbd",VEX_MX,16),TNSZ("vpmovsxbq",VEX_MX,16),TNSZ("vpmovsxwd",VEX_MX,16),
1202/* [24] */ TNSZ("vpmovsxwq",VEX_MX,16),TNSZ("vpmovsxdq",VEX_MX,16),INVALID, INVALID,
1203/* [28] */ TNSZ("vpmuldq",VEX_RMrX,16),TNSZ("vpcmpeqq",VEX_RMrX,16),TNSZ("vmovntdqa",VEX_MX,16),TNSZ("vpackusdw",VEX_RMrX,16),
1204/* [2C] */ TNSZ("vmaskmovps",VEX_RMrX,8),TNSZ("vmaskmovpd",VEX_RMrX,16),TNSZ("vmaskmovps",VEX_RRM,8),TNSZ("vmaskmovpd",VEX_RRM,16),
1205
1206/* [30] */ TNSZ("vpmovzxbw",VEX_MX,16),TNSZ("vpmovzxbd",VEX_MX,16),TNSZ("vpmovzxbq",VEX_MX,16),TNSZ("vpmovzxwd",VEX_MX,16),
1207/* [34] */ TNSZ("vpmovzxwq",VEX_MX,16),TNSZ("vpmovzxdq",VEX_MX,16),INVALID, TNSZ("vpcmpgtq",VEX_RMrX,16),
1208/* [38] */ TNSZ("vpminsb",VEX_RMrX,16),TNSZ("vpminsd",VEX_RMrX,16),TNSZ("vpminuw",VEX_RMrX,16),TNSZ("vpminud",VEX_RMrX,16),
1209/* [3C] */ TNSZ("vpmaxsb",VEX_RMrX,16),TNSZ("vpmaxsd",VEX_RMrX,16),TNSZ("vpmaxuw",VEX_RMrX,16),TNSZ("vpmaxud",VEX_RMrX,16),
1210
1211/* [40] */ TNSZ("vpmulld",VEX_RMrX,16),TNSZ("vphminposuw",VEX_MX,16),INVALID, INVALID,
1212/* [44] */ INVALID, INVALID, INVALID, INVALID,
1213/* [48] */ INVALID, INVALID, INVALID, INVALID,
1214/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1215
1216/* [50] */ INVALID, INVALID, INVALID, INVALID,
1217/* [54] */ INVALID, INVALID, INVALID, INVALID,
1218/* [58] */ INVALID, INVALID, INVALID, INVALID,
1219/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1220
1221/* [60] */ INVALID, INVALID, INVALID, INVALID,
1222/* [64] */ INVALID, INVALID, INVALID, INVALID,
1223/* [68] */ INVALID, INVALID, INVALID, INVALID,
1224/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1225
1226/* [70] */ INVALID, INVALID, INVALID, INVALID,
1227/* [74] */ INVALID, INVALID, INVALID, INVALID,
1228/* [78] */ INVALID, INVALID, INVALID, INVALID,
1229/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1230
1231/* [80] */ INVALID, INVALID, INVALID, INVALID,
1232/* [84] */ INVALID, INVALID, INVALID, INVALID,
1233/* [88] */ INVALID, INVALID, INVALID, INVALID,
1234/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1235
1236/* [90] */ INVALID, INVALID, INVALID, INVALID,
1237/* [94] */ INVALID, INVALID, INVALID, INVALID,
1238/* [98] */ INVALID, INVALID, INVALID, INVALID,
1239/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1240
1241/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1242/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1243/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1244/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1245
1246/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1247/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1248/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1249/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1250
1251/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1252/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1253/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1254/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1255
1256/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1257/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1258/* [D8] */ INVALID, INVALID, INVALID, TNSZ("vaesimc",VEX_MX,16),
1259/* [DC] */ TNSZ("vaesenc",VEX_RMrX,16),TNSZ("vaesenclast",VEX_RMrX,16),TNSZ("vaesdec",VEX_RMrX,16),TNSZ("vaesdeclast",VEX_RMrX,16),
1260
1261/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1262/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1263/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1264/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1265/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID,
1266/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1267/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1268/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1269};
1270
1271const instable_t dis_op0F3A[256] = {
1272/* [00] */ INVALID, INVALID, INVALID, INVALID,
1273/* [04] */ INVALID, INVALID, INVALID, INVALID,
1274/* [08] */ TNSZ("roundps",XMMP_66r,16),TNSZ("roundpd",XMMP_66r,16),TNSZ("roundss",XMMP_66r,16),TNSZ("roundsd",XMMP_66r,16),
1275/* [0C] */ TNSZ("blendps",XMMP_66r,16),TNSZ("blendpd",XMMP_66r,16),TNSZ("pblendw",XMMP_66r,16),TNSZ("palignr",XMMP_66o,16),
1276
1277/* [10] */ INVALID, INVALID, INVALID, INVALID,
1278/* [14] */ TNSZ("pextrb",XMM3PM_66r,8),TNSZ("pextrw",XMM3PM_66r,16),TSZ("pextr",XMM3PM_66r,16),TNSZ("extractps",XMM3PM_66r,16),
1279/* [18] */ INVALID, INVALID, INVALID, INVALID,
1280/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1281
1282/* [20] */ TNSZ("pinsrb",XMMPRM_66r,8),TNSZ("insertps",XMMP_66r,16),TSZ("pinsr",XMMPRM_66r,16),INVALID,
1283/* [24] */ INVALID, INVALID, INVALID, INVALID,
1284/* [28] */ INVALID, INVALID, INVALID, INVALID,
1285/* [2C] */ INVALID, INVALID, INVALID, INVALID,
1286
1287/* [30] */ INVALID, INVALID, INVALID, INVALID,
1288/* [34] */ INVALID, INVALID, INVALID, INVALID,
1289/* [38] */ INVALID, INVALID, INVALID, INVALID,
1290/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1291
1292/* [40] */ TNSZ("dpps",XMMP_66r,16),TNSZ("dppd",XMMP_66r,16),TNSZ("mpsadbw",XMMP_66r,16),INVALID,
1293/* [44] */ TNSZ("pclmulqdq",XMMP_66r,16),INVALID, INVALID, INVALID,
1294/* [48] */ INVALID, INVALID, INVALID, INVALID,
1295/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1296
1297/* [50] */ INVALID, INVALID, INVALID, INVALID,
1298/* [54] */ INVALID, INVALID, INVALID, INVALID,
1299/* [58] */ INVALID, INVALID, INVALID, INVALID,
1300/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1301
1302/* [60] */ TNSZ("pcmpestrm",XMMP_66r,16),TNSZ("pcmpestri",XMMP_66r,16),TNSZ("pcmpistrm",XMMP_66r,16),TNSZ("pcmpistri",XMMP_66r,16),
1303/* [64] */ INVALID, INVALID, INVALID, INVALID,
1304/* [68] */ INVALID, INVALID, INVALID, INVALID,
1305/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1306
1307/* [70] */ INVALID, INVALID, INVALID, INVALID,
1308/* [74] */ INVALID, INVALID, INVALID, INVALID,
1309/* [78] */ INVALID, INVALID, INVALID, INVALID,
1310/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1311
1312/* [80] */ INVALID, INVALID, INVALID, INVALID,
1313/* [84] */ INVALID, INVALID, INVALID, INVALID,
1314/* [88] */ INVALID, INVALID, INVALID, INVALID,
1315/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1316
1317/* [90] */ INVALID, INVALID, INVALID, INVALID,
1318/* [94] */ INVALID, INVALID, INVALID, INVALID,
1319/* [98] */ INVALID, INVALID, INVALID, INVALID,
1320/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1321
1322/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1323/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1324/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1325/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1326
1327/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1328/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1329/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1330/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1331
1332/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1333/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1334/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1335/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1336
1337/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1338/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1339/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1340/* [DC] */ INVALID, INVALID, INVALID, TNSZ("aeskeygenassist",XMMP_66r,16),
1341
1342/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1343/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1344/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1345/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1346
1347/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1348/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1349/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1350/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1351};
1352
1353const instable_t dis_opAVX660F3A[256] = {
1354/* [00] */ INVALID, INVALID, INVALID, INVALID,
1355/* [04] */ TNSZ("vpermilps",VEX_MXI,8),TNSZ("vpermilpd",VEX_MXI,16),TNSZ("vperm2f128",VEX_RMRX,16),INVALID,
1356/* [08] */ TNSZ("vroundps",VEX_MXI,16),TNSZ("vroundpd",VEX_MXI,16),TNSZ("vroundss",VEX_RMRX,16),TNSZ("vroundsd",VEX_RMRX,16),
1357/* [0C] */ TNSZ("vblendps",VEX_RMRX,16),TNSZ("vblendpd",VEX_RMRX,16),TNSZ("vpblendw",VEX_RMRX,16),TNSZ("vpalignr",VEX_RMRX,16),
1358
1359/* [10] */ INVALID, INVALID, INVALID, INVALID,
1360/* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16),
1361/* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID,
1232/* [14] */ INVALID, INVALID, INVALID, TNSZ("vptest",VEX_RRI,16),
1233/* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID,
1234/* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID,
1235
1236/* [20] */ TNSZ("vpmovsxbw",VEX_MX,16),TNSZ("vpmovsxbd",VEX_MX,16),TNSZ("vpmovsxbq",VEX_MX,16),TNSZ("vpmovsxwd",VEX_MX,16),
1237/* [24] */ TNSZ("vpmovsxwq",VEX_MX,16),TNSZ("vpmovsxdq",VEX_MX,16),INVALID, INVALID,
1238/* [28] */ TNSZ("vpmuldq",VEX_RMrX,16),TNSZ("vpcmpeqq",VEX_RMrX,16),TNSZ("vmovntdqa",VEX_MX,16),TNSZ("vpackusdw",VEX_RMrX,16),
1239/* [2C] */ TNSZ("vmaskmovps",VEX_RMrX,8),TNSZ("vmaskmovpd",VEX_RMrX,16),TNSZ("vmaskmovps",VEX_RRM,8),TNSZ("vmaskmovpd",VEX_RRM,16),
1240
1241/* [30] */ TNSZ("vpmovzxbw",VEX_MX,16),TNSZ("vpmovzxbd",VEX_MX,16),TNSZ("vpmovzxbq",VEX_MX,16),TNSZ("vpmovzxwd",VEX_MX,16),
1242/* [34] */ TNSZ("vpmovzxwq",VEX_MX,16),TNSZ("vpmovzxdq",VEX_MX,16),INVALID, TNSZ("vpcmpgtq",VEX_RMrX,16),
1243/* [38] */ TNSZ("vpminsb",VEX_RMrX,16),TNSZ("vpminsd",VEX_RMrX,16),TNSZ("vpminuw",VEX_RMrX,16),TNSZ("vpminud",VEX_RMrX,16),
1244/* [3C] */ TNSZ("vpmaxsb",VEX_RMrX,16),TNSZ("vpmaxsd",VEX_RMrX,16),TNSZ("vpmaxuw",VEX_RMrX,16),TNSZ("vpmaxud",VEX_RMrX,16),
1245
1246/* [40] */ TNSZ("vpmulld",VEX_RMrX,16),TNSZ("vphminposuw",VEX_MX,16),INVALID, INVALID,
1247/* [44] */ INVALID, INVALID, INVALID, INVALID,
1248/* [48] */ INVALID, INVALID, INVALID, INVALID,
1249/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1250
1251/* [50] */ INVALID, INVALID, INVALID, INVALID,
1252/* [54] */ INVALID, INVALID, INVALID, INVALID,
1253/* [58] */ INVALID, INVALID, INVALID, INVALID,
1254/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1255
1256/* [60] */ INVALID, INVALID, INVALID, INVALID,
1257/* [64] */ INVALID, INVALID, INVALID, INVALID,
1258/* [68] */ INVALID, INVALID, INVALID, INVALID,
1259/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1260
1261/* [70] */ INVALID, INVALID, INVALID, INVALID,
1262/* [74] */ INVALID, INVALID, INVALID, INVALID,
1263/* [78] */ INVALID, INVALID, INVALID, INVALID,
1264/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1265
1266/* [80] */ INVALID, INVALID, INVALID, INVALID,
1267/* [84] */ INVALID, INVALID, INVALID, INVALID,
1268/* [88] */ INVALID, INVALID, INVALID, INVALID,
1269/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1270
1271/* [90] */ INVALID, INVALID, INVALID, INVALID,
1272/* [94] */ INVALID, INVALID, INVALID, INVALID,
1273/* [98] */ INVALID, INVALID, INVALID, INVALID,
1274/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1275
1276/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1277/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1278/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1279/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1280
1281/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1282/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1283/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1284/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1285
1286/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1287/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1288/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1289/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1290
1291/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1292/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1293/* [D8] */ INVALID, INVALID, INVALID, TNSZ("vaesimc",VEX_MX,16),
1294/* [DC] */ TNSZ("vaesenc",VEX_RMrX,16),TNSZ("vaesenclast",VEX_RMrX,16),TNSZ("vaesdec",VEX_RMrX,16),TNSZ("vaesdeclast",VEX_RMrX,16),
1295
1296/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1297/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1298/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1299/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1300/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID,
1301/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1302/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1303/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1304};
1305
1306const instable_t dis_op0F3A[256] = {
1307/* [00] */ INVALID, INVALID, INVALID, INVALID,
1308/* [04] */ INVALID, INVALID, INVALID, INVALID,
1309/* [08] */ TNSZ("roundps",XMMP_66r,16),TNSZ("roundpd",XMMP_66r,16),TNSZ("roundss",XMMP_66r,16),TNSZ("roundsd",XMMP_66r,16),
1310/* [0C] */ TNSZ("blendps",XMMP_66r,16),TNSZ("blendpd",XMMP_66r,16),TNSZ("pblendw",XMMP_66r,16),TNSZ("palignr",XMMP_66o,16),
1311
1312/* [10] */ INVALID, INVALID, INVALID, INVALID,
1313/* [14] */ TNSZ("pextrb",XMM3PM_66r,8),TNSZ("pextrw",XMM3PM_66r,16),TSZ("pextr",XMM3PM_66r,16),TNSZ("extractps",XMM3PM_66r,16),
1314/* [18] */ INVALID, INVALID, INVALID, INVALID,
1315/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1316
1317/* [20] */ TNSZ("pinsrb",XMMPRM_66r,8),TNSZ("insertps",XMMP_66r,16),TSZ("pinsr",XMMPRM_66r,16),INVALID,
1318/* [24] */ INVALID, INVALID, INVALID, INVALID,
1319/* [28] */ INVALID, INVALID, INVALID, INVALID,
1320/* [2C] */ INVALID, INVALID, INVALID, INVALID,
1321
1322/* [30] */ INVALID, INVALID, INVALID, INVALID,
1323/* [34] */ INVALID, INVALID, INVALID, INVALID,
1324/* [38] */ INVALID, INVALID, INVALID, INVALID,
1325/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1326
1327/* [40] */ TNSZ("dpps",XMMP_66r,16),TNSZ("dppd",XMMP_66r,16),TNSZ("mpsadbw",XMMP_66r,16),INVALID,
1328/* [44] */ TNSZ("pclmulqdq",XMMP_66r,16),INVALID, INVALID, INVALID,
1329/* [48] */ INVALID, INVALID, INVALID, INVALID,
1330/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1331
1332/* [50] */ INVALID, INVALID, INVALID, INVALID,
1333/* [54] */ INVALID, INVALID, INVALID, INVALID,
1334/* [58] */ INVALID, INVALID, INVALID, INVALID,
1335/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1336
1337/* [60] */ TNSZ("pcmpestrm",XMMP_66r,16),TNSZ("pcmpestri",XMMP_66r,16),TNSZ("pcmpistrm",XMMP_66r,16),TNSZ("pcmpistri",XMMP_66r,16),
1338/* [64] */ INVALID, INVALID, INVALID, INVALID,
1339/* [68] */ INVALID, INVALID, INVALID, INVALID,
1340/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1341
1342/* [70] */ INVALID, INVALID, INVALID, INVALID,
1343/* [74] */ INVALID, INVALID, INVALID, INVALID,
1344/* [78] */ INVALID, INVALID, INVALID, INVALID,
1345/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1346
1347/* [80] */ INVALID, INVALID, INVALID, INVALID,
1348/* [84] */ INVALID, INVALID, INVALID, INVALID,
1349/* [88] */ INVALID, INVALID, INVALID, INVALID,
1350/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1351
1352/* [90] */ INVALID, INVALID, INVALID, INVALID,
1353/* [94] */ INVALID, INVALID, INVALID, INVALID,
1354/* [98] */ INVALID, INVALID, INVALID, INVALID,
1355/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1356
1357/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1358/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1359/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1360/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1361
1362/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1363/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1364/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1365/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1366
1367/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1368/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1369/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1370/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1371
1372/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1373/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1374/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1375/* [DC] */ INVALID, INVALID, INVALID, TNSZ("aeskeygenassist",XMMP_66r,16),
1376
1377/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1378/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1379/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1380/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1381
1382/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1383/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1384/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1385/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1386};
1387
1388const instable_t dis_opAVX660F3A[256] = {
1389/* [00] */ INVALID, INVALID, INVALID, INVALID,
1390/* [04] */ TNSZ("vpermilps",VEX_MXI,8),TNSZ("vpermilpd",VEX_MXI,16),TNSZ("vperm2f128",VEX_RMRX,16),INVALID,
1391/* [08] */ TNSZ("vroundps",VEX_MXI,16),TNSZ("vroundpd",VEX_MXI,16),TNSZ("vroundss",VEX_RMRX,16),TNSZ("vroundsd",VEX_RMRX,16),
1392/* [0C] */ TNSZ("vblendps",VEX_RMRX,16),TNSZ("vblendpd",VEX_RMRX,16),TNSZ("vpblendw",VEX_RMRX,16),TNSZ("vpalignr",VEX_RMRX,16),
1393
1394/* [10] */ INVALID, INVALID, INVALID, INVALID,
1395/* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16),
1396/* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID,
1362/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1397/* [1C] */ INVALID, TNSZ("vcvtps2ph",VEX_RX,16), INVALID, INVALID,
1363
1364/* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID,
1365/* [24] */ INVALID, INVALID, INVALID, INVALID,
1366/* [28] */ INVALID, INVALID, INVALID, INVALID,
1367/* [2C] */ INVALID, INVALID, INVALID, INVALID,
1368
1369/* [30] */ INVALID, INVALID, INVALID, INVALID,
1370/* [34] */ INVALID, INVALID, INVALID, INVALID,
1371/* [38] */ INVALID, INVALID, INVALID, INVALID,
1372/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1373
1374/* [40] */ TNSZ("vdpps",VEX_RMRX,16),TNSZ("vdppd",VEX_RMRX,16),TNSZ("vmpsadbw",VEX_RMRX,16),INVALID,
1375/* [44] */ TNSZ("vpclmulqdq",VEX_RMRX,16),INVALID, INVALID, INVALID,
1376/* [48] */ INVALID, INVALID, TNSZ("vblendvps",VEX_RMRX,8), TNSZ("vblendvpd",VEX_RMRX,16),
1377/* [4C] */ TNSZ("vpblendvb",VEX_RMRX,16),INVALID, INVALID, INVALID,
1378
1379/* [50] */ INVALID, INVALID, INVALID, INVALID,
1380/* [54] */ INVALID, INVALID, INVALID, INVALID,
1381/* [58] */ INVALID, INVALID, INVALID, INVALID,
1382/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1383
1384/* [60] */ TNSZ("vpcmpestrm",VEX_MXI,16),TNSZ("vpcmpestri",VEX_MXI,16),TNSZ("vpcmpistrm",VEX_MXI,16),TNSZ("vpcmpistri",VEX_MXI,16),
1385/* [64] */ INVALID, INVALID, INVALID, INVALID,
1386/* [68] */ INVALID, INVALID, INVALID, INVALID,
1387/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1388
1389/* [70] */ INVALID, INVALID, INVALID, INVALID,
1390/* [74] */ INVALID, INVALID, INVALID, INVALID,
1391/* [78] */ INVALID, INVALID, INVALID, INVALID,
1392/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1393
1394/* [80] */ INVALID, INVALID, INVALID, INVALID,
1395/* [84] */ INVALID, INVALID, INVALID, INVALID,
1396/* [88] */ INVALID, INVALID, INVALID, INVALID,
1397/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1398
1399/* [90] */ INVALID, INVALID, INVALID, INVALID,
1400/* [94] */ INVALID, INVALID, INVALID, INVALID,
1401/* [98] */ INVALID, INVALID, INVALID, INVALID,
1402/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1403
1404/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1405/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1406/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1407/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1408
1409/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1410/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1411/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1412/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1413
1414/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1415/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1416/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1417/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1418
1419/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1420/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1421/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1422/* [DC] */ INVALID, INVALID, INVALID, TNSZ("vaeskeygenassist",VEX_MXI,16),
1423
1424/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1425/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1426/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1427/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1428
1429/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1430/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1431/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1432/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1433};
1434
1435/*
1436 * Decode table for 0x0F opcodes
1437 */
1438
1439const instable_t dis_op0F[16][16] = {
1440{
1441/* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR),
1442/* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM),
1443/* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM),
1444/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1445}, {
1446/* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8),
1447/* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8),
1448/* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID,
1398
1399/* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID,
1400/* [24] */ INVALID, INVALID, INVALID, INVALID,
1401/* [28] */ INVALID, INVALID, INVALID, INVALID,
1402/* [2C] */ INVALID, INVALID, INVALID, INVALID,
1403
1404/* [30] */ INVALID, INVALID, INVALID, INVALID,
1405/* [34] */ INVALID, INVALID, INVALID, INVALID,
1406/* [38] */ INVALID, INVALID, INVALID, INVALID,
1407/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1408
1409/* [40] */ TNSZ("vdpps",VEX_RMRX,16),TNSZ("vdppd",VEX_RMRX,16),TNSZ("vmpsadbw",VEX_RMRX,16),INVALID,
1410/* [44] */ TNSZ("vpclmulqdq",VEX_RMRX,16),INVALID, INVALID, INVALID,
1411/* [48] */ INVALID, INVALID, TNSZ("vblendvps",VEX_RMRX,8), TNSZ("vblendvpd",VEX_RMRX,16),
1412/* [4C] */ TNSZ("vpblendvb",VEX_RMRX,16),INVALID, INVALID, INVALID,
1413
1414/* [50] */ INVALID, INVALID, INVALID, INVALID,
1415/* [54] */ INVALID, INVALID, INVALID, INVALID,
1416/* [58] */ INVALID, INVALID, INVALID, INVALID,
1417/* [5C] */ INVALID, INVALID, INVALID, INVALID,
1418
1419/* [60] */ TNSZ("vpcmpestrm",VEX_MXI,16),TNSZ("vpcmpestri",VEX_MXI,16),TNSZ("vpcmpistrm",VEX_MXI,16),TNSZ("vpcmpistri",VEX_MXI,16),
1420/* [64] */ INVALID, INVALID, INVALID, INVALID,
1421/* [68] */ INVALID, INVALID, INVALID, INVALID,
1422/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1423
1424/* [70] */ INVALID, INVALID, INVALID, INVALID,
1425/* [74] */ INVALID, INVALID, INVALID, INVALID,
1426/* [78] */ INVALID, INVALID, INVALID, INVALID,
1427/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1428
1429/* [80] */ INVALID, INVALID, INVALID, INVALID,
1430/* [84] */ INVALID, INVALID, INVALID, INVALID,
1431/* [88] */ INVALID, INVALID, INVALID, INVALID,
1432/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1433
1434/* [90] */ INVALID, INVALID, INVALID, INVALID,
1435/* [94] */ INVALID, INVALID, INVALID, INVALID,
1436/* [98] */ INVALID, INVALID, INVALID, INVALID,
1437/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1438
1439/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1440/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1441/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1442/* [AC] */ INVALID, INVALID, INVALID, INVALID,
1443
1444/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1445/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1446/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1447/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1448
1449/* [C0] */ INVALID, INVALID, INVALID, INVALID,
1450/* [C4] */ INVALID, INVALID, INVALID, INVALID,
1451/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1452/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1453
1454/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1455/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1456/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1457/* [DC] */ INVALID, INVALID, INVALID, TNSZ("vaeskeygenassist",VEX_MXI,16),
1458
1459/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1460/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1461/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1462/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1463
1464/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1465/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1466/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1467/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1468};
1469
1470/*
1471 * Decode table for 0x0F opcodes
1472 */
1473
1474const instable_t dis_op0F[16][16] = {
1475{
1476/* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR),
1477/* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM),
1478/* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM),
1479/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1480}, {
1481/* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8),
1482/* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8),
1483/* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID,
1449/* [1C] */ INVALID, INVALID, INVALID, TS("nopw", Mw),
1484/* [1C] */ INVALID, INVALID, INVALID, TS("nop",Mw),
1450}, {
1451/* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG),
1452/* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID,
1453/* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16),
1454/* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4),
1455}, {
1456/* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM),
1457/* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID,
1458/* [38] */ INVALID, INVALID, INVALID, INVALID,
1459/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1460}, {
1461/* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR),
1462/* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR),
1463/* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR),
1464/* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR),
1465}, {
1466/* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16),
1467/* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16),
1468/* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16),
1469/* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16),
1470}, {
1471/* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8),
1472/* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8),
1473/* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8),
1474/* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8),
1475}, {
1476/* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR),
1477/* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM),
1485}, {
1486/* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG),
1487/* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID,
1488/* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16),
1489/* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4),
1490}, {
1491/* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM),
1492/* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID,
1493/* [38] */ INVALID, INVALID, INVALID, INVALID,
1494/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1495}, {
1496/* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR),
1497/* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR),
1498/* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR),
1499/* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR),
1500}, {
1501/* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16),
1502/* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16),
1503/* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16),
1504/* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16),
1505}, {
1506/* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8),
1507/* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8),
1508/* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8),
1509/* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8),
1510}, {
1511/* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR),
1512/* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM),
1478/* [78] */ TNS("INVALID",XMMO), TNS("INVALID",XMMO), INVALID, INVALID,
1513/* [78] */ TNSy("vmread",RM), TNSy("vmwrite",MR), INVALID, INVALID,
1479/* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8),
1480}, {
1481/* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D),
1482/* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D),
1483/* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D),
1484/* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D),
1485}, {
1486/* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb),
1487/* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb),
1488/* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb),
1489/* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb),
1490}, {
1491/* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw),
1492/* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID,
1493/* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw),
1494/* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw),
1495}, {
1496/* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw),
1497/* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ),
1498/* [B8] */ TNS("INVALID",MRw), INVALID, IND(dis_op0FBA), TS("btc",RMw),
1499/* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ),
1500}, {
1501/* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM),
1502/* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7),
1503/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1504/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1505}, {
1506/* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8),
1507/* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3),
1508/* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8),
1509/* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8),
1510}, {
1511/* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8),
1512/* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8),
1513/* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8),
1514/* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8),
1515}, {
1516/* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8),
1517/* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8),
1518/* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8),
1519/* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID,
1520} };
1521
1522const instable_t dis_opAVX0F[16][16] = {
1523{
1524/* [00] */ INVALID, INVALID, INVALID, INVALID,
1525/* [04] */ INVALID, INVALID, INVALID, INVALID,
1526/* [08] */ INVALID, INVALID, INVALID, INVALID,
1527/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1528}, {
1529/* [10] */ TNSZ("vmovups",VEX_MX,16), TNSZ("vmovups",VEX_RM,16),TNSZ("vmovlps",VEX_RMrX,8), TNSZ("vmovlps",VEX_RM,8),
1530/* [14] */ TNSZ("vunpcklps",VEX_RMrX,16),TNSZ("vunpckhps",VEX_RMrX,16),TNSZ("vmovhps",VEX_RMrX,8),TNSZ("vmovhps",VEX_RM,8),
1531/* [18] */ INVALID, INVALID, INVALID, INVALID,
1532/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1533}, {
1534/* [20] */ INVALID, INVALID, INVALID, INVALID,
1535/* [24] */ INVALID, INVALID, INVALID, INVALID,
1536/* [28] */ TNSZ("vmovaps",VEX_MX,16), TNSZ("vmovaps",VEX_RX,16),INVALID, TNSZ("vmovntps",VEX_RM,16),
1537/* [2C] */ INVALID, INVALID, TNSZ("vucomiss",VEX_MX,4),TNSZ("vcomiss",VEX_MX,4),
1538}, {
1539/* [30] */ INVALID, INVALID, INVALID, INVALID,
1540/* [34] */ INVALID, INVALID, INVALID, INVALID,
1541/* [38] */ INVALID, INVALID, INVALID, INVALID,
1542/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1543}, {
1544/* [40] */ INVALID, INVALID, INVALID, INVALID,
1545/* [44] */ INVALID, INVALID, INVALID, INVALID,
1546/* [48] */ INVALID, INVALID, INVALID, INVALID,
1547/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1548}, {
1549/* [50] */ TNS("vmovmskps",VEX_MR), TNSZ("vsqrtps",VEX_MX,16), TNSZ("vrsqrtps",VEX_MX,16),TNSZ("vrcpps",VEX_MX,16),
1550/* [54] */ TNSZ("vandps",VEX_RMrX,16), TNSZ("vandnps",VEX_RMrX,16), TNSZ("vorps",VEX_RMrX,16), TNSZ("vxorps",VEX_RMrX,16),
1551/* [58] */ TNSZ("vaddps",VEX_RMrX,16), TNSZ("vmulps",VEX_RMrX,16), TNSZ("vcvtps2pd",VEX_MX,8),TNSZ("vcvtdq2ps",VEX_MX,16),
1552/* [5C] */ TNSZ("vsubps",VEX_RMrX,16), TNSZ("vminps",VEX_RMrX,16), TNSZ("vdivps",VEX_RMrX,16), TNSZ("vmaxps",VEX_RMrX,16),
1553}, {
1554/* [60] */ INVALID, INVALID, INVALID, INVALID,
1555/* [64] */ INVALID, INVALID, INVALID, INVALID,
1556/* [68] */ INVALID, INVALID, INVALID, INVALID,
1557/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1558}, {
1559/* [70] */ INVALID, INVALID, INVALID, INVALID,
1560/* [74] */ INVALID, INVALID, INVALID, TNS("vzeroupper", VEX_NONE),
1561/* [78] */ INVALID, INVALID, INVALID, INVALID,
1562/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1563}, {
1564/* [80] */ INVALID, INVALID, INVALID, INVALID,
1565/* [84] */ INVALID, INVALID, INVALID, INVALID,
1566/* [88] */ INVALID, INVALID, INVALID, INVALID,
1567/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1568}, {
1569/* [90] */ INVALID, INVALID, INVALID, INVALID,
1570/* [94] */ INVALID, INVALID, INVALID, INVALID,
1571/* [98] */ INVALID, INVALID, INVALID, INVALID,
1572/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1573}, {
1574/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1575/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1576/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1577/* [AC] */ INVALID, INVALID, TNSZ("vldmxcsr",VEX_MO,2), INVALID,
1578}, {
1579/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1580/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1581/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1582/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1583}, {
1584/* [C0] */ INVALID, INVALID, TNSZ("vcmpps",VEX_RMRX,16),INVALID,
1585/* [C4] */ INVALID, INVALID, TNSZ("vshufps",VEX_RMRX,16),INVALID,
1586/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1587/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1588}, {
1589/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1590/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1591/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1592/* [DC] */ INVALID, INVALID, INVALID, INVALID,
1593}, {
1594/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1595/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1596/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1597/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1598}, {
1599/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1600/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1601/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1602/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1603} };
1604
1605/*
1606 * Decode table for 0x80 opcodes
1607 */
1608
1609const instable_t dis_op80[8] = {
1610
1611/* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw),
1612/* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw),
1613};
1614
1615
1616/*
1617 * Decode table for 0x81 opcodes.
1618 */
1619
1620const instable_t dis_op81[8] = {
1621
1622/* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw),
1623/* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw),
1624};
1625
1626
1627/*
1628 * Decode table for 0x82 opcodes.
1629 */
1630
1631const instable_t dis_op82[8] = {
1632
1633/* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw),
1634/* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw),
1635};
1636/*
1637 * Decode table for 0x83 opcodes.
1638 */
1639
1640const instable_t dis_op83[8] = {
1641
1642/* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw),
1643/* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw),
1644};
1645
1646/*
1647 * Decode table for 0xC0 opcodes.
1648 */
1649
1650const instable_t dis_opC0[8] = {
1651
1652/* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI),
1653/* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI),
1654};
1655
1656/*
1657 * Decode table for 0xD0 opcodes.
1658 */
1659
1660const instable_t dis_opD0[8] = {
1661
1662/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv),
1663/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv),
1664};
1665
1666/*
1667 * Decode table for 0xC1 opcodes.
1668 * 186 instruction set
1669 */
1670
1671const instable_t dis_opC1[8] = {
1672
1673/* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI),
1674/* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI),
1675};
1676
1677/*
1678 * Decode table for 0xD1 opcodes.
1679 */
1680
1681const instable_t dis_opD1[8] = {
1682
1683/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv),
1684/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv),
1685};
1686
1687
1688/*
1689 * Decode table for 0xD2 opcodes.
1690 */
1691
1692const instable_t dis_opD2[8] = {
1693
1694/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv),
1695/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv),
1696};
1697/*
1698 * Decode table for 0xD3 opcodes.
1699 */
1700
1701const instable_t dis_opD3[8] = {
1702
1703/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv),
1704/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv),
1705};
1706
1707
1708/*
1709 * Decode table for 0xF6 opcodes.
1710 */
1711
1712const instable_t dis_opF6[8] = {
1713
1714/* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw),
1715/* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA),
1716};
1717
1718
1719/*
1720 * Decode table for 0xF7 opcodes.
1721 */
1722
1723const instable_t dis_opF7[8] = {
1724
1725/* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw),
1726/* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA),
1727};
1728
1729
1730/*
1731 * Decode table for 0xFE opcodes.
1732 */
1733
1734const instable_t dis_opFE[8] = {
1735
1736/* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID,
1737/* [4] */ INVALID, INVALID, INVALID, INVALID,
1738};
1739/*
1740 * Decode table for 0xFF opcodes.
1741 */
1742
1743const instable_t dis_opFF[8] = {
1744
1745/* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM),
1746/* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID,
1747};
1748
1749/* for 287 instructions, which are a mess to decode */
1750
1751const instable_t dis_opFP1n2[8][8] = {
1752{
1753/* bit pattern: 1101 1xxx MODxx xR/M */
1754/* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M),
1755/* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M),
1756}, {
1757/* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M),
1758/* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2),
1759}, {
1760/* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M),
1761/* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M),
1762}, {
1763/* [3,0] */ TNS("fildl",M), INVALID, TNS("fistl",M), TNS("fistpl",M),
1764/* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10),
1765}, {
1766/* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8),
1767/* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8),
1768}, {
1769/* [5,0] */ TNSZ("fldl",M,8), INVALID, TNSZ("fstl",M,8), TNSZ("fstpl",M,8),
1770/* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2),
1771}, {
1772/* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2),
1773/* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2),
1774}, {
1775/* [7,0] */ TNSZ("fild",M,2), INVALID, TNSZ("fist",M,2), TNSZ("fistp",M,2),
1776/* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8),
1777} };
1778
1779const instable_t dis_opFP3[8][8] = {
1780{
1781/* bit pattern: 1101 1xxx 11xx xREG */
1782/* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F),
1783/* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF),
1784}, {
1785/* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F),
1786/* [1,4] */ INVALID, INVALID, INVALID, INVALID,
1787}, {
1788/* [2,0] */ INVALID, INVALID, INVALID, INVALID,
1789/* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID,
1790}, {
1791/* [3,0] */ INVALID, INVALID, INVALID, INVALID,
1792/* [3,4] */ INVALID, INVALID, INVALID, INVALID,
1793}, {
1794/* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F),
1795/* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF),
1796}, {
1797/* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F),
1798/* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID,
1799}, {
1800/* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM),
1801/* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF),
1802}, {
1803/* [7,0] */ TNS("ffreep",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F),
1804/* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID,
1805} };
1806
1807const instable_t dis_opFP4[4][8] = {
1808{
1809/* bit pattern: 1101 1001 111x xxxx */
1810/* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID,
1811/* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID,
1812}, {
1813/* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM),
1814/* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID,
1815}, {
1816/* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM),
1817/* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM),
1818}, {
1819/* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM),
1820/* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM),
1821} };
1822
1823const instable_t dis_opFP5[8] = {
1824/* bit pattern: 1101 1011 111x xxxx */
1825/* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM),
1826/* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID,
1827};
1828
1829const instable_t dis_opFP6[8] = {
1830/* bit pattern: 1101 1011 11yy yxxx */
1831/* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF),
1832/* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID,
1833};
1834
1835const instable_t dis_opFP7[8] = {
1836/* bit pattern: 1101 1010 11yy yxxx */
1837/* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF),
1838/* [04] */ INVALID, INVALID, INVALID, INVALID,
1839};
1840
1841/*
1842 * Main decode table for the op codes. The first two nibbles
1843 * will be used as an index into the table. If there is a
1844 * a need to further decode an instruction, the array to be
1845 * referenced is indicated with the other two entries being
1846 * empty.
1847 */
1848
1849const instable_t dis_distable[16][16] = {
1850{
1851/* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw),
1852/* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG),
1853/* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw),
1854/* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(dis_op0F),
1855}, {
1856/* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw),
1857/* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG),
1858/* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw),
1859/* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG),
1860}, {
1861/* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw),
1514/* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8),
1515}, {
1516/* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D),
1517/* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D),
1518/* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D),
1519/* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D),
1520}, {
1521/* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb),
1522/* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb),
1523/* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb),
1524/* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb),
1525}, {
1526/* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw),
1527/* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID,
1528/* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw),
1529/* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw),
1530}, {
1531/* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw),
1532/* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ),
1533/* [B8] */ TNS("INVALID",MRw), INVALID, IND(dis_op0FBA), TS("btc",RMw),
1534/* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ),
1535}, {
1536/* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM),
1537/* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7),
1538/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1539/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1540}, {
1541/* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8),
1542/* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3),
1543/* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8),
1544/* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8),
1545}, {
1546/* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8),
1547/* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8),
1548/* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8),
1549/* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8),
1550}, {
1551/* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8),
1552/* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8),
1553/* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8),
1554/* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID,
1555} };
1556
1557const instable_t dis_opAVX0F[16][16] = {
1558{
1559/* [00] */ INVALID, INVALID, INVALID, INVALID,
1560/* [04] */ INVALID, INVALID, INVALID, INVALID,
1561/* [08] */ INVALID, INVALID, INVALID, INVALID,
1562/* [0C] */ INVALID, INVALID, INVALID, INVALID,
1563}, {
1564/* [10] */ TNSZ("vmovups",VEX_MX,16), TNSZ("vmovups",VEX_RM,16),TNSZ("vmovlps",VEX_RMrX,8), TNSZ("vmovlps",VEX_RM,8),
1565/* [14] */ TNSZ("vunpcklps",VEX_RMrX,16),TNSZ("vunpckhps",VEX_RMrX,16),TNSZ("vmovhps",VEX_RMrX,8),TNSZ("vmovhps",VEX_RM,8),
1566/* [18] */ INVALID, INVALID, INVALID, INVALID,
1567/* [1C] */ INVALID, INVALID, INVALID, INVALID,
1568}, {
1569/* [20] */ INVALID, INVALID, INVALID, INVALID,
1570/* [24] */ INVALID, INVALID, INVALID, INVALID,
1571/* [28] */ TNSZ("vmovaps",VEX_MX,16), TNSZ("vmovaps",VEX_RX,16),INVALID, TNSZ("vmovntps",VEX_RM,16),
1572/* [2C] */ INVALID, INVALID, TNSZ("vucomiss",VEX_MX,4),TNSZ("vcomiss",VEX_MX,4),
1573}, {
1574/* [30] */ INVALID, INVALID, INVALID, INVALID,
1575/* [34] */ INVALID, INVALID, INVALID, INVALID,
1576/* [38] */ INVALID, INVALID, INVALID, INVALID,
1577/* [3C] */ INVALID, INVALID, INVALID, INVALID,
1578}, {
1579/* [40] */ INVALID, INVALID, INVALID, INVALID,
1580/* [44] */ INVALID, INVALID, INVALID, INVALID,
1581/* [48] */ INVALID, INVALID, INVALID, INVALID,
1582/* [4C] */ INVALID, INVALID, INVALID, INVALID,
1583}, {
1584/* [50] */ TNS("vmovmskps",VEX_MR), TNSZ("vsqrtps",VEX_MX,16), TNSZ("vrsqrtps",VEX_MX,16),TNSZ("vrcpps",VEX_MX,16),
1585/* [54] */ TNSZ("vandps",VEX_RMrX,16), TNSZ("vandnps",VEX_RMrX,16), TNSZ("vorps",VEX_RMrX,16), TNSZ("vxorps",VEX_RMrX,16),
1586/* [58] */ TNSZ("vaddps",VEX_RMrX,16), TNSZ("vmulps",VEX_RMrX,16), TNSZ("vcvtps2pd",VEX_MX,8),TNSZ("vcvtdq2ps",VEX_MX,16),
1587/* [5C] */ TNSZ("vsubps",VEX_RMrX,16), TNSZ("vminps",VEX_RMrX,16), TNSZ("vdivps",VEX_RMrX,16), TNSZ("vmaxps",VEX_RMrX,16),
1588}, {
1589/* [60] */ INVALID, INVALID, INVALID, INVALID,
1590/* [64] */ INVALID, INVALID, INVALID, INVALID,
1591/* [68] */ INVALID, INVALID, INVALID, INVALID,
1592/* [6C] */ INVALID, INVALID, INVALID, INVALID,
1593}, {
1594/* [70] */ INVALID, INVALID, INVALID, INVALID,
1595/* [74] */ INVALID, INVALID, INVALID, TNS("vzeroupper", VEX_NONE),
1596/* [78] */ INVALID, INVALID, INVALID, INVALID,
1597/* [7C] */ INVALID, INVALID, INVALID, INVALID,
1598}, {
1599/* [80] */ INVALID, INVALID, INVALID, INVALID,
1600/* [84] */ INVALID, INVALID, INVALID, INVALID,
1601/* [88] */ INVALID, INVALID, INVALID, INVALID,
1602/* [8C] */ INVALID, INVALID, INVALID, INVALID,
1603}, {
1604/* [90] */ INVALID, INVALID, INVALID, INVALID,
1605/* [94] */ INVALID, INVALID, INVALID, INVALID,
1606/* [98] */ INVALID, INVALID, INVALID, INVALID,
1607/* [9C] */ INVALID, INVALID, INVALID, INVALID,
1608}, {
1609/* [A0] */ INVALID, INVALID, INVALID, INVALID,
1610/* [A4] */ INVALID, INVALID, INVALID, INVALID,
1611/* [A8] */ INVALID, INVALID, INVALID, INVALID,
1612/* [AC] */ INVALID, INVALID, TNSZ("vldmxcsr",VEX_MO,2), INVALID,
1613}, {
1614/* [B0] */ INVALID, INVALID, INVALID, INVALID,
1615/* [B4] */ INVALID, INVALID, INVALID, INVALID,
1616/* [B8] */ INVALID, INVALID, INVALID, INVALID,
1617/* [BC] */ INVALID, INVALID, INVALID, INVALID,
1618}, {
1619/* [C0] */ INVALID, INVALID, TNSZ("vcmpps",VEX_RMRX,16),INVALID,
1620/* [C4] */ INVALID, INVALID, TNSZ("vshufps",VEX_RMRX,16),INVALID,
1621/* [C8] */ INVALID, INVALID, INVALID, INVALID,
1622/* [CC] */ INVALID, INVALID, INVALID, INVALID,
1623}, {
1624/* [D0] */ INVALID, INVALID, INVALID, INVALID,
1625/* [D4] */ INVALID, INVALID, INVALID, INVALID,
1626/* [D8] */ INVALID, INVALID, INVALID, INVALID,
1627/* [DC] */ INVALID, INVALID, INVALID, INVALID,
1628}, {
1629/* [E0] */ INVALID, INVALID, INVALID, INVALID,
1630/* [E4] */ INVALID, INVALID, INVALID, INVALID,
1631/* [E8] */ INVALID, INVALID, INVALID, INVALID,
1632/* [EC] */ INVALID, INVALID, INVALID, INVALID,
1633}, {
1634/* [F0] */ INVALID, INVALID, INVALID, INVALID,
1635/* [F4] */ INVALID, INVALID, INVALID, INVALID,
1636/* [F8] */ INVALID, INVALID, INVALID, INVALID,
1637/* [FC] */ INVALID, INVALID, INVALID, INVALID,
1638} };
1639
1640/*
1641 * Decode table for 0x80 opcodes
1642 */
1643
1644const instable_t dis_op80[8] = {
1645
1646/* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw),
1647/* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw),
1648};
1649
1650
1651/*
1652 * Decode table for 0x81 opcodes.
1653 */
1654
1655const instable_t dis_op81[8] = {
1656
1657/* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw),
1658/* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw),
1659};
1660
1661
1662/*
1663 * Decode table for 0x82 opcodes.
1664 */
1665
1666const instable_t dis_op82[8] = {
1667
1668/* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw),
1669/* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw),
1670};
1671/*
1672 * Decode table for 0x83 opcodes.
1673 */
1674
1675const instable_t dis_op83[8] = {
1676
1677/* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw),
1678/* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw),
1679};
1680
1681/*
1682 * Decode table for 0xC0 opcodes.
1683 */
1684
1685const instable_t dis_opC0[8] = {
1686
1687/* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI),
1688/* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI),
1689};
1690
1691/*
1692 * Decode table for 0xD0 opcodes.
1693 */
1694
1695const instable_t dis_opD0[8] = {
1696
1697/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv),
1698/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv),
1699};
1700
1701/*
1702 * Decode table for 0xC1 opcodes.
1703 * 186 instruction set
1704 */
1705
1706const instable_t dis_opC1[8] = {
1707
1708/* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI),
1709/* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI),
1710};
1711
1712/*
1713 * Decode table for 0xD1 opcodes.
1714 */
1715
1716const instable_t dis_opD1[8] = {
1717
1718/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv),
1719/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv),
1720};
1721
1722
1723/*
1724 * Decode table for 0xD2 opcodes.
1725 */
1726
1727const instable_t dis_opD2[8] = {
1728
1729/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv),
1730/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv),
1731};
1732/*
1733 * Decode table for 0xD3 opcodes.
1734 */
1735
1736const instable_t dis_opD3[8] = {
1737
1738/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv),
1739/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv),
1740};
1741
1742
1743/*
1744 * Decode table for 0xF6 opcodes.
1745 */
1746
1747const instable_t dis_opF6[8] = {
1748
1749/* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw),
1750/* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA),
1751};
1752
1753
1754/*
1755 * Decode table for 0xF7 opcodes.
1756 */
1757
1758const instable_t dis_opF7[8] = {
1759
1760/* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw),
1761/* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA),
1762};
1763
1764
1765/*
1766 * Decode table for 0xFE opcodes.
1767 */
1768
1769const instable_t dis_opFE[8] = {
1770
1771/* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID,
1772/* [4] */ INVALID, INVALID, INVALID, INVALID,
1773};
1774/*
1775 * Decode table for 0xFF opcodes.
1776 */
1777
1778const instable_t dis_opFF[8] = {
1779
1780/* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM),
1781/* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID,
1782};
1783
1784/* for 287 instructions, which are a mess to decode */
1785
1786const instable_t dis_opFP1n2[8][8] = {
1787{
1788/* bit pattern: 1101 1xxx MODxx xR/M */
1789/* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M),
1790/* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M),
1791}, {
1792/* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M),
1793/* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2),
1794}, {
1795/* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M),
1796/* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M),
1797}, {
1798/* [3,0] */ TNS("fildl",M), INVALID, TNS("fistl",M), TNS("fistpl",M),
1799/* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10),
1800}, {
1801/* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8),
1802/* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8),
1803}, {
1804/* [5,0] */ TNSZ("fldl",M,8), INVALID, TNSZ("fstl",M,8), TNSZ("fstpl",M,8),
1805/* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2),
1806}, {
1807/* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2),
1808/* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2),
1809}, {
1810/* [7,0] */ TNSZ("fild",M,2), INVALID, TNSZ("fist",M,2), TNSZ("fistp",M,2),
1811/* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8),
1812} };
1813
1814const instable_t dis_opFP3[8][8] = {
1815{
1816/* bit pattern: 1101 1xxx 11xx xREG */
1817/* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F),
1818/* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF),
1819}, {
1820/* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F),
1821/* [1,4] */ INVALID, INVALID, INVALID, INVALID,
1822}, {
1823/* [2,0] */ INVALID, INVALID, INVALID, INVALID,
1824/* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID,
1825}, {
1826/* [3,0] */ INVALID, INVALID, INVALID, INVALID,
1827/* [3,4] */ INVALID, INVALID, INVALID, INVALID,
1828}, {
1829/* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F),
1830/* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF),
1831}, {
1832/* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F),
1833/* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID,
1834}, {
1835/* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM),
1836/* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF),
1837}, {
1838/* [7,0] */ TNS("ffreep",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F),
1839/* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID,
1840} };
1841
1842const instable_t dis_opFP4[4][8] = {
1843{
1844/* bit pattern: 1101 1001 111x xxxx */
1845/* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID,
1846/* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID,
1847}, {
1848/* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM),
1849/* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID,
1850}, {
1851/* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM),
1852/* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM),
1853}, {
1854/* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM),
1855/* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM),
1856} };
1857
1858const instable_t dis_opFP5[8] = {
1859/* bit pattern: 1101 1011 111x xxxx */
1860/* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM),
1861/* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID,
1862};
1863
1864const instable_t dis_opFP6[8] = {
1865/* bit pattern: 1101 1011 11yy yxxx */
1866/* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF),
1867/* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID,
1868};
1869
1870const instable_t dis_opFP7[8] = {
1871/* bit pattern: 1101 1010 11yy yxxx */
1872/* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF),
1873/* [04] */ INVALID, INVALID, INVALID, INVALID,
1874};
1875
1876/*
1877 * Main decode table for the op codes. The first two nibbles
1878 * will be used as an index into the table. If there is a
1879 * a need to further decode an instruction, the array to be
1880 * referenced is indicated with the other two entries being
1881 * empty.
1882 */
1883
1884const instable_t dis_distable[16][16] = {
1885{
1886/* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw),
1887/* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG),
1888/* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw),
1889/* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(dis_op0F),
1890}, {
1891/* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw),
1892/* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG),
1893/* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw),
1894/* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG),
1895}, {
1896/* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw),
1862/* [2,4] */ TNS("andb",IA), TS("and",IA), TNS("%es:",OVERRIDE), TNSx("daa",NORM),
1897/* [2,4] */ TNS("andb",IA), TS("and",IA), TNSx("%es:",OVERRIDE), TNSx("daa",NORM),
1863/* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw),
1864/* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM),
1865}, {
1866/* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw),
1898/* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw),
1899/* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM),
1900}, {
1901/* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw),
1867/* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNS("%ss:",OVERRIDE), TNSx("aaa",NORM),
1902/* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNSx("%ss:",OVERRIDE), TNSx("aaa",NORM),
1868/* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw),
1903/* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw),
1869/* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNS("%ds:",OVERRIDE), TNSx("aas",NORM),
1904/* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNSx("%ds:",OVERRIDE), TNSx("aas",NORM),
1870}, {
1871/* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
1872/* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
1873/* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R),
1874/* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R),
1875}, {
1876/* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R),
1877/* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R),
1878/* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R),
1879/* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R),
1880}, {
1881/* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw),
1882/* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM),
1883/* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL),
1884/* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4),
1885}, {
1886/* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD),
1887/* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD),
1888/* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD),
1889/* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD),
1890}, {
1891/* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83),
1892/* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw),
1893/* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw),
1894/* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M),
1895}, {
1896/* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA),
1897/* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA),
1898/* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM),
1899/* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNSx("sahf",NORM), TNSx("lahf",NORM),
1900}, {
1901/* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO),
1902/* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD),
1903/* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD),
1904/* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD),
1905}, {
1906/* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR),
1907/* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR),
1908/* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR),
1909/* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR),
1910}, {
1911/* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM),
1912/* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw),
1913/* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM),
1914/* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM),
1915}, {
1916/* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3),
1917/* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1),
1918
1919/* 287 instructions. Note that although the indirect field */
1920/* indicates opFP1n2 for further decoding, this is not necessarily */
1921/* the case since the opFP arrays are not partitioned according to key1 */
1922/* and key2. opFP1n2 is given only to indicate that we haven't */
1923/* finished decoding the instruction. */
1924/* [D,8] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2),
1925/* [D,C] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2),
1926}, {
1927/* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD),
1928/* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P),
1929/* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD),
1930/* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V),
1931}, {
1932/* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX),
1933/* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7),
1934/* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM),
1935/* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF),
1936} };
1937
1938/* END CSTYLED */
1939
1940/*
1941 * common functions to decode and disassemble an x86 or amd64 instruction
1942 */
1943
1944/*
1945 * These are the individual fields of a REX prefix. Note that a REX
1946 * prefix with none of these set is still needed to:
1947 * - use the MOVSXD (sign extend 32 to 64 bits) instruction
1948 * - access the %sil, %dil, %bpl, %spl registers
1949 */
1950#define REX_W 0x08 /* 64 bit operand size when set */
1951#define REX_R 0x04 /* high order bit extension of ModRM reg field */
1952#define REX_X 0x02 /* high order bit extension of SIB index field */
1953#define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */
1954
1955/*
1956 * These are the individual fields of a VEX prefix.
1957 */
1958#define VEX_R 0x08 /* REX.R in 1's complement form */
1959#define VEX_X 0x04 /* REX.X in 1's complement form */
1960#define VEX_B 0x02 /* REX.B in 1's complement form */
1961/* Vector Length, 0: scalar or 128-bit vector, 1: 256-bit vector */
1962#define VEX_L 0x04
1963#define VEX_W 0x08 /* opcode specific, use like REX.W */
1964#define VEX_m 0x1F /* VEX m-mmmm field */
1965#define VEX_v 0x78 /* VEX register specifier */
1966#define VEX_p 0x03 /* VEX pp field, opcode extension */
1967
1968/* VEX m-mmmm field, only used by three bytes prefix */
1969#define VEX_m_0F 0x01 /* implied 0F leading opcode byte */
1970#define VEX_m_0F38 0x02 /* implied 0F 38 leading opcode byte */
1971#define VEX_m_0F3A 0x03 /* implied 0F 3A leading opcode byte */
1972
1973/* VEX pp field, providing equivalent functionality of a SIMD prefix */
1974#define VEX_p_66 0x01
1975#define VEX_p_F3 0x02
1976#define VEX_p_F2 0x03
1977
1978/*
1979 * Even in 64 bit mode, usually only 4 byte immediate operands are supported.
1980 */
1981static int isize[] = {1, 2, 4, 4};
1982static int isize64[] = {1, 2, 4, 8};
1983
1984/*
1985 * Just a bunch of useful macros.
1986 */
1987#define WBIT(x) (x & 0x1) /* to get w bit */
1988#define REGNO(x) (x & 0x7) /* to get 3 bit register */
1989#define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */
1990#define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1)
1991#define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1)
1992
1993#define REG_ONLY 3 /* mode to indicate a register operand (not memory) */
1994
1995#define BYTE_OPND 0 /* w-bit value indicating byte register */
1996#define LONG_OPND 1 /* w-bit value indicating opnd_size register */
1997#define MM_OPND 2 /* "value" used to indicate a mmx reg */
1998#define XMM_OPND 3 /* "value" used to indicate a xmm reg */
1999#define SEG_OPND 4 /* "value" used to indicate a segment reg */
2000#define CONTROL_OPND 5 /* "value" used to indicate a control reg */
2001#define DEBUG_OPND 6 /* "value" used to indicate a debug reg */
2002#define TEST_OPND 7 /* "value" used to indicate a test reg */
2003#define WORD_OPND 8 /* w-bit value indicating word size reg */
2004#define YMM_OPND 9 /* "value" used to indicate a ymm reg */
2005
2006/*
2007 * Get the next byte and separate the op code into the high and low nibbles.
2008 */
2009static int
2010dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low)
2011{
2012 int byte;
2013
2014 /*
2015 * x86 instructions have a maximum length of 15 bytes. Bail out if
2016 * we try to read more.
2017 */
2018 if (x->d86_len >= 15)
2019 return (x->d86_error = 1);
2020
2021 if (x->d86_error)
2022 return (1);
2023 byte = x->d86_get_byte(x->d86_data);
2024 if (byte < 0)
2025 return (x->d86_error = 1);
2026 x->d86_bytes[x->d86_len++] = byte;
2027 *low = byte & 0xf; /* ----xxxx low 4 bits */
2028 *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */
2029 return (0);
2030}
2031
2032/*
2033 * Get and decode an SIB (scaled index base) byte
2034 */
2035static void
2036dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base)
2037{
2038 int byte;
2039
2040 if (x->d86_error)
2041 return;
2042
2043 byte = x->d86_get_byte(x->d86_data);
2044 if (byte < 0) {
2045 x->d86_error = 1;
2046 return;
2047 }
2048 x->d86_bytes[x->d86_len++] = byte;
2049
2050 *base = byte & 0x7;
2051 *index = (byte >> 3) & 0x7;
2052 *ss = (byte >> 6) & 0x3;
2053}
2054
2055/*
2056 * Get the byte following the op code and separate it into the
2057 * mode, register, and r/m fields.
2058 */
2059static void
2060dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m)
2061{
2062 if (x->d86_got_modrm == 0) {
2063 if (x->d86_rmindex == -1)
2064 x->d86_rmindex = x->d86_len;
2065 dtrace_get_SIB(x, mode, reg, r_m);
2066 x->d86_got_modrm = 1;
2067 }
2068}
2069
2070/*
2071 * Adjust register selection based on any REX prefix bits present.
2072 */
2073/*ARGSUSED*/
2074static void
2075dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m)
2076{
2077 if (reg != NULL && r_m == NULL) {
2078 if (rex_prefix & REX_B)
2079 *reg += 8;
2080 } else {
2081 if (reg != NULL && (REX_R & rex_prefix) != 0)
2082 *reg += 8;
2083 if (r_m != NULL && (REX_B & rex_prefix) != 0)
2084 *r_m += 8;
2085 }
2086}
2087
2088/*
2089 * Adjust register selection based on any VEX prefix bits present.
2090 * Notes: VEX.R, VEX.X and VEX.B use the inverted form compared with REX prefix
2091 */
2092/*ARGSUSED*/
2093static void
2094dtrace_vex_adjust(uint_t vex_byte1, uint_t mode, uint_t *reg, uint_t *r_m)
2095{
2096 if (reg != NULL && r_m == NULL) {
2097 if (!(vex_byte1 & VEX_B))
2098 *reg += 8;
2099 } else {
2100 if (reg != NULL && ((VEX_R & vex_byte1) == 0))
2101 *reg += 8;
2102 if (r_m != NULL && ((VEX_B & vex_byte1) == 0))
2103 *r_m += 8;
2104 }
2105}
2106
2107/*
2108 * Get an immediate operand of the given size, with sign extension.
2109 */
2110static void
2111dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex)
2112{
2113 int i;
2114 int byte;
2115 int valsize;
2116
2117 if (x->d86_numopnds < opindex + 1)
2118 x->d86_numopnds = opindex + 1;
2119
2120 switch (wbit) {
2121 case BYTE_OPND:
2122 valsize = 1;
2123 break;
2124 case LONG_OPND:
2125 if (x->d86_opnd_size == SIZE16)
2126 valsize = 2;
2127 else if (x->d86_opnd_size == SIZE32)
2128 valsize = 4;
2129 else
2130 valsize = 8;
2131 break;
2132 case MM_OPND:
2133 case XMM_OPND:
2134 case YMM_OPND:
2135 case SEG_OPND:
2136 case CONTROL_OPND:
2137 case DEBUG_OPND:
2138 case TEST_OPND:
2139 valsize = size;
2140 break;
2141 case WORD_OPND:
2142 valsize = 2;
2143 break;
2144 }
2145 if (valsize < size)
2146 valsize = size;
2147
2148 if (x->d86_error)
2149 return;
2150 x->d86_opnd[opindex].d86_value = 0;
2151 for (i = 0; i < size; ++i) {
2152 byte = x->d86_get_byte(x->d86_data);
2153 if (byte < 0) {
2154 x->d86_error = 1;
2155 return;
2156 }
2157 x->d86_bytes[x->d86_len++] = byte;
2158 x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8);
2159 }
2160 /* Do sign extension */
2161 if (x->d86_bytes[x->d86_len - 1] & 0x80) {
2162 for (; i < sizeof (uint64_t); i++)
2163 x->d86_opnd[opindex].d86_value |=
2164 (uint64_t)0xff << (i * 8);
2165 }
2166#ifdef DIS_TEXT
2167 x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
2168 x->d86_opnd[opindex].d86_value_size = valsize;
2169 x->d86_imm_bytes += size;
2170#endif
2171}
2172
2173/*
2174 * Get an ip relative operand of the given size, with sign extension.
2175 */
2176static void
2177dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex)
2178{
2179 dtrace_imm_opnd(x, wbit, size, opindex);
2180#ifdef DIS_TEXT
2181 x->d86_opnd[opindex].d86_mode = MODE_IPREL;
2182#endif
2183}
2184
2185/*
2186 * Check to see if there is a segment override prefix pending.
2187 * If so, print it in the current 'operand' location and set
2188 * the override flag back to false.
2189 */
2190/*ARGSUSED*/
2191static void
2192dtrace_check_override(dis86_t *x, int opindex)
2193{
2194#ifdef DIS_TEXT
2195 if (x->d86_seg_prefix) {
2196 (void) strlcat(x->d86_opnd[opindex].d86_prefix,
2197 x->d86_seg_prefix, PFIXLEN);
2198 }
2199#endif
2200 x->d86_seg_prefix = NULL;
2201}
2202
2203
2204/*
2205 * Process a single instruction Register or Memory operand.
2206 *
2207 * mode = addressing mode from ModRM byte
2208 * r_m = r_m (or reg if mode == 3) field from ModRM byte
2209 * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use.
2210 * o = index of operand that we are processing (0, 1 or 2)
2211 *
2212 * the value of reg or r_m must have already been adjusted for any REX prefix.
2213 */
2214/*ARGSUSED*/
2215static void
2216dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex)
2217{
2218 int have_SIB = 0; /* flag presence of scale-index-byte */
2219 uint_t ss; /* scale-factor from opcode */
2220 uint_t index; /* index register number */
2221 uint_t base; /* base register number */
2222 int dispsize; /* size of displacement in bytes */
2223#ifdef DIS_TEXT
2224 char *opnd = x->d86_opnd[opindex].d86_opnd;
2225#endif
2226
2227 if (x->d86_numopnds < opindex + 1)
2228 x->d86_numopnds = opindex + 1;
2229
2230 if (x->d86_error)
2231 return;
2232
2233 /*
2234 * first handle a simple register
2235 */
2236 if (mode == REG_ONLY) {
2237#ifdef DIS_TEXT
2238 switch (wbit) {
2239 case MM_OPND:
2240 (void) strlcat(opnd, dis_MMREG[r_m], OPLEN);
2241 break;
2242 case XMM_OPND:
2243 (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN);
2244 break;
2245 case YMM_OPND:
2246 (void) strlcat(opnd, dis_YMMREG[r_m], OPLEN);
2247 break;
2248 case SEG_OPND:
2249 (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN);
2250 break;
2251 case CONTROL_OPND:
2252 (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN);
2253 break;
2254 case DEBUG_OPND:
2255 (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN);
2256 break;
2257 case TEST_OPND:
2258 (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN);
2259 break;
2260 case BYTE_OPND:
2261 if (x->d86_rex_prefix == 0)
2262 (void) strlcat(opnd, dis_REG8[r_m], OPLEN);
2263 else
2264 (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN);
2265 break;
2266 case WORD_OPND:
2267 (void) strlcat(opnd, dis_REG16[r_m], OPLEN);
2268 break;
2269 case LONG_OPND:
2270 if (x->d86_opnd_size == SIZE16)
2271 (void) strlcat(opnd, dis_REG16[r_m], OPLEN);
2272 else if (x->d86_opnd_size == SIZE32)
2273 (void) strlcat(opnd, dis_REG32[r_m], OPLEN);
2274 else
2275 (void) strlcat(opnd, dis_REG64[r_m], OPLEN);
2276 break;
2277 }
2278#endif /* DIS_TEXT */
2279 return;
2280 }
2281
2282 /*
2283 * if symbolic representation, skip override prefix, if any
2284 */
2285 dtrace_check_override(x, opindex);
2286
2287 /*
2288 * Handle 16 bit memory references first, since they decode
2289 * the mode values more simply.
2290 * mode 1 is r_m + 8 bit displacement
2291 * mode 2 is r_m + 16 bit displacement
2292 * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp
2293 */
2294 if (x->d86_addr_size == SIZE16) {
2295 if ((mode == 0 && r_m == 6) || mode == 2)
2296 dtrace_imm_opnd(x, WORD_OPND, 2, opindex);
2297 else if (mode == 1)
2298 dtrace_imm_opnd(x, BYTE_OPND, 1, opindex);
2299#ifdef DIS_TEXT
2300 if (mode == 0 && r_m == 6)
2301 x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
2302 else if (mode == 0)
2303 x->d86_opnd[opindex].d86_mode = MODE_NONE;
2304 else
2305 x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
2306 (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN);
2307#endif
2308 return;
2309 }
2310
2311 /*
2312 * 32 and 64 bit addressing modes are more complex since they
2313 * can involve an SIB (scaled index and base) byte to decode.
2314 */
2315 if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) {
2316 have_SIB = 1;
2317 dtrace_get_SIB(x, &ss, &index, &base);
2318 if (x->d86_error)
2319 return;
2320 if (base != 5 || mode != 0)
2321 if (x->d86_rex_prefix & REX_B)
2322 base += 8;
2323 if (x->d86_rex_prefix & REX_X)
2324 index += 8;
2325 } else {
2326 base = r_m;
2327 }
2328
2329 /*
2330 * Compute the displacement size and get its bytes
2331 */
2332 dispsize = 0;
2333
2334 if (mode == 1)
2335 dispsize = 1;
2336 else if (mode == 2)
2337 dispsize = 4;
2338 else if ((r_m & 7) == EBP_REGNO ||
2339 (have_SIB && (base & 7) == EBP_REGNO))
2340 dispsize = 4;
2341
2342 if (dispsize > 0) {
2343 dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND,
2344 dispsize, opindex);
2345 if (x->d86_error)
2346 return;
2347 }
2348
2349#ifdef DIS_TEXT
2350 if (dispsize > 0)
2351 x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
2352
2353 if (have_SIB == 0) {
2354 if (x->d86_mode == SIZE32) {
2355 if (mode == 0)
2356 (void) strlcat(opnd, dis_addr32_mode0[r_m],
2357 OPLEN);
2358 else
2359 (void) strlcat(opnd, dis_addr32_mode12[r_m],
2360 OPLEN);
2361 } else {
2362 if (mode == 0) {
2363 (void) strlcat(opnd, dis_addr64_mode0[r_m],
2364 OPLEN);
2365 if (r_m == 5) {
2366 x->d86_opnd[opindex].d86_mode =
2367 MODE_RIPREL;
2368 }
2369 } else {
2370 (void) strlcat(opnd, dis_addr64_mode12[r_m],
2371 OPLEN);
2372 }
2373 }
2374 } else {
2375 uint_t need_paren = 0;
2376 char **regs;
2377 if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */
2378 regs = (char **)dis_REG32;
2379 else
2380 regs = (char **)dis_REG64;
2381
2382 /*
2383 * print the base (if any)
2384 */
2385 if (base == EBP_REGNO && mode == 0) {
2386 if (index != ESP_REGNO) {
2387 (void) strlcat(opnd, "(", OPLEN);
2388 need_paren = 1;
2389 }
2390 } else {
2391 (void) strlcat(opnd, "(", OPLEN);
2392 (void) strlcat(opnd, regs[base], OPLEN);
2393 need_paren = 1;
2394 }
2395
2396 /*
2397 * print the index (if any)
2398 */
2399 if (index != ESP_REGNO) {
2400 (void) strlcat(opnd, ",", OPLEN);
2401 (void) strlcat(opnd, regs[index], OPLEN);
2402 (void) strlcat(opnd, dis_scale_factor[ss], OPLEN);
2403 } else
2404 if (need_paren)
2405 (void) strlcat(opnd, ")", OPLEN);
2406 }
2407#endif
2408}
2409
2410/*
2411 * Operand sequence for standard instruction involving one register
2412 * and one register/memory operand.
2413 * wbit indicates a byte(0) or opnd_size(1) operation
2414 * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r")
2415 */
2416#define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \
2417 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2418 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2419 dtrace_get_operand(x, mode, r_m, wbit, vbit); \
2420 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \
2421}
2422
2423/*
2424 * Similar to above, but allows for the two operands to be of different
2425 * classes (ie. wbit).
2426 * wbit is for the r_m operand
2427 * w2 is for the reg operand
2428 */
2429#define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \
2430 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2431 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2432 dtrace_get_operand(x, mode, r_m, wbit, vbit); \
2433 dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \
2434}
2435
2436/*
2437 * Similar, but for 2 operands plus an immediate.
2438 * vbit indicates direction
2439 * 0 for "opcode imm, r, r_m" or
2440 * 1 for "opcode imm, r_m, r"
2441 */
2442#define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \
2443 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2444 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2445 dtrace_get_operand(x, mode, r_m, wbit, 2-vbit); \
2446 dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \
2447 dtrace_imm_opnd(x, wbit, immsize, 0); \
2448}
2449
2450/*
2451 * Similar, but for 2 operands plus two immediates.
2452 */
2453#define FOUROPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \
2454 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2455 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2456 dtrace_get_operand(x, mode, r_m, wbit, 2); \
2457 dtrace_get_operand(x, REG_ONLY, reg, w2, 3); \
2458 dtrace_imm_opnd(x, wbit, immsize, 1); \
2459 dtrace_imm_opnd(x, wbit, immsize, 0); \
2460}
2461
2462/*
2463 * 1 operands plus two immediates.
2464 */
2465#define ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, wbit, immsize) { \
2466 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2467 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2468 dtrace_get_operand(x, mode, r_m, wbit, 2); \
2469 dtrace_imm_opnd(x, wbit, immsize, 1); \
2470 dtrace_imm_opnd(x, wbit, immsize, 0); \
2471}
2472
2473/*
2474 * Dissassemble a single x86 or amd64 instruction.
2475 *
2476 * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64)
2477 * for interpreting instructions.
2478 *
2479 * returns non-zero for bad opcode
2480 */
2481int
2482dtrace_disx86(dis86_t *x, uint_t cpu_mode)
2483{
2484 instable_t *dp; /* decode table being used */
2485#ifdef DIS_TEXT
2486 uint_t i;
2487#endif
2488#ifdef DIS_MEM
2489 uint_t nomem = 0;
2490#define NOMEM (nomem = 1)
2491#else
2492#define NOMEM /* nothing */
2493#endif
2494 uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */
2495 uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */
2496 uint_t wbit; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */
2497 uint_t w2; /* wbit value for second operand */
2498 uint_t vbit;
2499 uint_t mode = 0; /* mode value from ModRM byte */
2500 uint_t reg; /* reg value from ModRM byte */
2501 uint_t r_m; /* r_m value from ModRM byte */
2502
2503 uint_t opcode1; /* high nibble of 1st byte */
2504 uint_t opcode2; /* low nibble of 1st byte */
2505 uint_t opcode3; /* extra opcode bits usually from ModRM byte */
2506 uint_t opcode4; /* high nibble of 2nd byte */
2507 uint_t opcode5; /* low nibble of 2nd byte */
2508 uint_t opcode6; /* high nibble of 3rd byte */
2509 uint_t opcode7; /* low nibble of 3rd byte */
2510 uint_t opcode_bytes = 1;
2511
2512 /*
2513 * legacy prefixes come in 5 flavors, you should have only one of each
2514 */
2515 uint_t opnd_size_prefix = 0;
2516 uint_t addr_size_prefix = 0;
2517 uint_t segment_prefix = 0;
2518 uint_t lock_prefix = 0;
2519 uint_t rep_prefix = 0;
2520 uint_t rex_prefix = 0; /* amd64 register extension prefix */
2521
2522 /*
2523 * Intel VEX instruction encoding prefix and fields
2524 */
2525
2526 /* 0xC4 means 3 bytes prefix, 0xC5 means 2 bytes prefix */
2527 uint_t vex_prefix = 0;
2528
2529 /*
2530 * VEX prefix byte 1, includes vex.r, vex.x and vex.b
2531 * (for 3 bytes prefix)
2532 */
2533 uint_t vex_byte1 = 0;
2534
2535 /*
2536 * For 32-bit mode, it should prefetch the next byte to
2537 * distinguish between AVX and les/lds
2538 */
2539 uint_t vex_prefetch = 0;
2540
2541 uint_t vex_m = 0;
2542 uint_t vex_v = 0;
2543 uint_t vex_p = 0;
2544 uint_t vex_R = 1;
2545 uint_t vex_X = 1;
2546 uint_t vex_B = 1;
2547 uint_t vex_W = 0;
2548 uint_t vex_L;
2549
2550
2551 size_t off;
2552
2553 instable_t dp_mmx;
2554
2555 x->d86_len = 0;
2556 x->d86_rmindex = -1;
2557 x->d86_error = 0;
2558#ifdef DIS_TEXT
2559 x->d86_numopnds = 0;
2560 x->d86_seg_prefix = NULL;
2561 x->d86_mnem[0] = 0;
2562 for (i = 0; i < 4; ++i) {
2563 x->d86_opnd[i].d86_opnd[0] = 0;
2564 x->d86_opnd[i].d86_prefix[0] = 0;
2565 x->d86_opnd[i].d86_value_size = 0;
2566 x->d86_opnd[i].d86_value = 0;
2567 x->d86_opnd[i].d86_mode = MODE_NONE;
2568 }
2569#endif
2570 x->d86_rex_prefix = 0;
2571 x->d86_got_modrm = 0;
2572 x->d86_memsize = 0;
2573
2574 if (cpu_mode == SIZE16) {
2575 opnd_size = SIZE16;
2576 addr_size = SIZE16;
2577 } else if (cpu_mode == SIZE32) {
2578 opnd_size = SIZE32;
2579 addr_size = SIZE32;
2580 } else {
2581 opnd_size = SIZE32;
2582 addr_size = SIZE64;
2583 }
2584
2585 /*
2586 * Get one opcode byte and check for zero padding that follows
2587 * jump tables.
2588 */
2589 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2590 goto error;
2591
2592 if (opcode1 == 0 && opcode2 == 0 &&
2593 x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) {
2594#ifdef DIS_TEXT
2595 (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN);
2596#endif
2597 goto done;
2598 }
2599
2600 /*
2601 * Gather up legacy x86 prefix bytes.
2602 */
2603 for (;;) {
2604 uint_t *which_prefix = NULL;
2605
2606 dp = (instable_t *)&dis_distable[opcode1][opcode2];
2607
2608 switch (dp->it_adrmode) {
2609 case PREFIX:
2610 which_prefix = &rep_prefix;
2611 break;
2612 case LOCK:
2613 which_prefix = &lock_prefix;
2614 break;
2615 case OVERRIDE:
2616 which_prefix = &segment_prefix;
2617#ifdef DIS_TEXT
2618 x->d86_seg_prefix = (char *)dp->it_name;
2619#endif
2620 if (dp->it_invalid64 && cpu_mode == SIZE64)
2621 goto error;
2622 break;
2623 case AM:
2624 which_prefix = &addr_size_prefix;
2625 break;
2626 case DM:
2627 which_prefix = &opnd_size_prefix;
2628 break;
2629 }
2630 if (which_prefix == NULL)
2631 break;
2632 *which_prefix = (opcode1 << 4) | opcode2;
2633 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2634 goto error;
2635 }
2636
2637 /*
2638 * Handle amd64 mode PREFIX values.
2639 * Some of the segment prefixes are no-ops. (only FS/GS actually work)
2640 * We might have a REX prefix (opcodes 0x40-0x4f)
2641 */
2642 if (cpu_mode == SIZE64) {
2643 if (segment_prefix != 0x64 && segment_prefix != 0x65)
2644 segment_prefix = 0;
2645
2646 if (opcode1 == 0x4) {
2647 rex_prefix = (opcode1 << 4) | opcode2;
2648 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2649 goto error;
2650 dp = (instable_t *)&dis_distable[opcode1][opcode2];
2651 } else if (opcode1 == 0xC &&
2652 (opcode2 == 0x4 || opcode2 == 0x5)) {
2653 /* AVX instructions */
2654 vex_prefix = (opcode1 << 4) | opcode2;
2655 x->d86_rex_prefix = 0x40;
2656 }
2657 } else if (opcode1 == 0xC && (opcode2 == 0x4 || opcode2 == 0x5)) {
2658 /* LDS, LES or AVX */
2659 dtrace_get_modrm(x, &mode, &reg, &r_m);
2660 vex_prefetch = 1;
2661
2662 if (mode == REG_ONLY) {
2663 /* AVX */
2664 vex_prefix = (opcode1 << 4) | opcode2;
2665 x->d86_rex_prefix = 0x40;
2666 opcode3 = (((mode << 3) | reg)>>1) & 0x0F;
2667 opcode4 = ((reg << 3) | r_m) & 0x0F;
2668 }
2669 }
2670
2671 if (vex_prefix == VEX_2bytes) {
2672 if (!vex_prefetch) {
2673 if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0)
2674 goto error;
2675 }
2676 vex_R = ((opcode3 & VEX_R) & 0x0F) >> 3;
2677 vex_L = ((opcode4 & VEX_L) & 0x0F) >> 2;
2678 vex_v = (((opcode3 << 4) | opcode4) & VEX_v) >> 3;
2679 vex_p = opcode4 & VEX_p;
2680 /*
2681 * The vex.x and vex.b bits are not defined in two bytes
2682 * mode vex prefix, their default values are 1
2683 */
2684 vex_byte1 = (opcode3 & VEX_R) | VEX_X | VEX_B;
2685
2686 if (vex_R == 0)
2687 x->d86_rex_prefix |= REX_R;
2688
2689 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2690 goto error;
2691
2692 switch (vex_p) {
2693 case VEX_p_66:
2694 dp = (instable_t *)
2695 &dis_opAVX660F[(opcode1 << 4) | opcode2];
2696 break;
2697 case VEX_p_F3:
2698 dp = (instable_t *)
2699 &dis_opAVXF30F[(opcode1 << 4) | opcode2];
2700 break;
2701 case VEX_p_F2:
2702 dp = (instable_t *)
2703 &dis_opAVXF20F [(opcode1 << 4) | opcode2];
2704 break;
2705 default:
2706 dp = (instable_t *)
2707 &dis_opAVX0F[opcode1][opcode2];
2708
2709 }
2710
2711 } else if (vex_prefix == VEX_3bytes) {
2712 if (!vex_prefetch) {
2713 if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0)
2714 goto error;
2715 }
2716 vex_R = (opcode3 & VEX_R) >> 3;
2717 vex_X = (opcode3 & VEX_X) >> 2;
2718 vex_B = (opcode3 & VEX_B) >> 1;
2719 vex_m = (((opcode3 << 4) | opcode4) & VEX_m);
2720 vex_byte1 = opcode3 & (VEX_R | VEX_X | VEX_B);
2721
2722 if (vex_R == 0)
2723 x->d86_rex_prefix |= REX_R;
2724 if (vex_X == 0)
2725 x->d86_rex_prefix |= REX_X;
2726 if (vex_B == 0)
2727 x->d86_rex_prefix |= REX_B;
2728
2729 if (dtrace_get_opcode(x, &opcode5, &opcode6) != 0)
2730 goto error;
2731 vex_W = (opcode5 & VEX_W) >> 3;
2732 vex_L = (opcode6 & VEX_L) >> 2;
2733 vex_v = (((opcode5 << 4) | opcode6) & VEX_v) >> 3;
2734 vex_p = opcode6 & VEX_p;
2735
2736 if (vex_W)
2737 x->d86_rex_prefix |= REX_W;
2738
2739 /* Only these three vex_m values valid; others are reserved */
2740 if ((vex_m != VEX_m_0F) && (vex_m != VEX_m_0F38) &&
2741 (vex_m != VEX_m_0F3A))
2742 goto error;
2743
2744 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2745 goto error;
2746
2747 switch (vex_p) {
2748 case VEX_p_66:
2749 if (vex_m == VEX_m_0F) {
2750 dp = (instable_t *)
2751 &dis_opAVX660F
2752 [(opcode1 << 4) | opcode2];
2753 } else if (vex_m == VEX_m_0F38) {
2754 dp = (instable_t *)
2755 &dis_opAVX660F38
2756 [(opcode1 << 4) | opcode2];
2757 } else if (vex_m == VEX_m_0F3A) {
2758 dp = (instable_t *)
2759 &dis_opAVX660F3A
2760 [(opcode1 << 4) | opcode2];
2761 } else {
2762 goto error;
2763 }
2764 break;
2765 case VEX_p_F3:
2766 if (vex_m == VEX_m_0F) {
2767 dp = (instable_t *)
2768 &dis_opAVXF30F
2769 [(opcode1 << 4) | opcode2];
2770 } else {
2771 goto error;
2772 }
2773 break;
2774 case VEX_p_F2:
2775 if (vex_m == VEX_m_0F) {
2776 dp = (instable_t *)
2777 &dis_opAVXF20F
2778 [(opcode1 << 4) | opcode2];
2779 } else {
2780 goto error;
2781 }
2782 break;
2783 default:
2784 dp = (instable_t *)
2785 &dis_opAVX0F[opcode1][opcode2];
2786
2787 }
2788 }
2789 if (vex_prefix) {
2790 if (vex_L)
2791 wbit = YMM_OPND;
2792 else
2793 wbit = XMM_OPND;
2794 }
2795
2796 /*
2797 * Deal with selection of operand and address size now.
2798 * Note that the REX.W bit being set causes opnd_size_prefix to be
2799 * ignored.
2800 */
2801 if (cpu_mode == SIZE64) {
2802 if ((rex_prefix & REX_W) || vex_W)
2803 opnd_size = SIZE64;
2804 else if (opnd_size_prefix)
2805 opnd_size = SIZE16;
2806
2807 if (addr_size_prefix)
2808 addr_size = SIZE32;
2809 } else if (cpu_mode == SIZE32) {
2810 if (opnd_size_prefix)
2811 opnd_size = SIZE16;
2812 if (addr_size_prefix)
2813 addr_size = SIZE16;
2814 } else {
2815 if (opnd_size_prefix)
2816 opnd_size = SIZE32;
2817 if (addr_size_prefix)
2818 addr_size = SIZE32;
2819 }
2820 /*
2821 * The pause instruction - a repz'd nop. This doesn't fit
2822 * with any of the other prefix goop added for SSE, so we'll
2823 * special-case it here.
2824 */
2825 if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) {
2826 rep_prefix = 0;
2827 dp = (instable_t *)&dis_opPause;
2828 }
2829
2830 /*
2831 * Some 386 instructions have 2 bytes of opcode before the mod_r/m
2832 * byte so we may need to perform a table indirection.
2833 */
2834 if (dp->it_indirect == (instable_t *)dis_op0F) {
2835 if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0)
2836 goto error;
2837 opcode_bytes = 2;
2838 if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) {
2839 uint_t subcode;
2840
2841 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2842 goto error;
2843 opcode_bytes = 3;
2844 subcode = ((opcode6 & 0x3) << 1) |
2845 ((opcode7 & 0x8) >> 3);
2846 dp = (instable_t *)&dis_op0F7123[opcode5][subcode];
2847 } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) {
2848 dp = (instable_t *)&dis_op0FC8[0];
2849 } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) {
2850 opcode_bytes = 3;
2851 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2852 goto error;
2853 if (opnd_size == SIZE16)
2854 opnd_size = SIZE32;
2855
2856 dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7];
2857#ifdef DIS_TEXT
2858 if (strcmp(dp->it_name, "INVALID") == 0)
2859 goto error;
2860#endif
2861 switch (dp->it_adrmode) {
2862 case XMMP_66r:
2863 case XMMPRM_66r:
2864 case XMM3PM_66r:
2865 if (opnd_size_prefix == 0) {
2866 goto error;
2867 }
2868 break;
2869 case XMMP_66o:
2870 if (opnd_size_prefix == 0) {
2871 /* SSSE3 MMX instructions */
2872 dp_mmx = *dp;
2873 dp = &dp_mmx;
2874 dp->it_adrmode = MMOPM_66o;
2875#ifdef DIS_MEM
2876 dp->it_size = 8;
2877#endif
2878 }
2879 break;
2880 default:
2881 goto error;
2882 }
2883 } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) {
2884 opcode_bytes = 3;
2885 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2886 goto error;
2887 dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7];
2888
2889 /*
2890 * Both crc32 and movbe have the same 3rd opcode
2891 * byte of either 0xF0 or 0xF1, so we use another
2892 * indirection to distinguish between the two.
2893 */
2894 if (dp->it_indirect == (instable_t *)dis_op0F38F0 ||
2895 dp->it_indirect == (instable_t *)dis_op0F38F1) {
2896
2897 dp = dp->it_indirect;
2898 if (rep_prefix != 0xF2) {
2899 /* It is movbe */
2900 dp++;
2901 }
2902 }
2903#ifdef DIS_TEXT
2904 if (strcmp(dp->it_name, "INVALID") == 0)
2905 goto error;
2906#endif
2907 switch (dp->it_adrmode) {
1905}, {
1906/* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
1907/* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
1908/* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R),
1909/* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R),
1910}, {
1911/* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R),
1912/* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R),
1913/* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R),
1914/* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R),
1915}, {
1916/* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw),
1917/* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM),
1918/* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL),
1919/* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4),
1920}, {
1921/* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD),
1922/* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD),
1923/* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD),
1924/* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD),
1925}, {
1926/* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83),
1927/* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw),
1928/* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw),
1929/* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M),
1930}, {
1931/* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA),
1932/* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA),
1933/* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM),
1934/* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNSx("sahf",NORM), TNSx("lahf",NORM),
1935}, {
1936/* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO),
1937/* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD),
1938/* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD),
1939/* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD),
1940}, {
1941/* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR),
1942/* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR),
1943/* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR),
1944/* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR),
1945}, {
1946/* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM),
1947/* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw),
1948/* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM),
1949/* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM),
1950}, {
1951/* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3),
1952/* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1),
1953
1954/* 287 instructions. Note that although the indirect field */
1955/* indicates opFP1n2 for further decoding, this is not necessarily */
1956/* the case since the opFP arrays are not partitioned according to key1 */
1957/* and key2. opFP1n2 is given only to indicate that we haven't */
1958/* finished decoding the instruction. */
1959/* [D,8] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2),
1960/* [D,C] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2),
1961}, {
1962/* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD),
1963/* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P),
1964/* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD),
1965/* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V),
1966}, {
1967/* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX),
1968/* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7),
1969/* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM),
1970/* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF),
1971} };
1972
1973/* END CSTYLED */
1974
1975/*
1976 * common functions to decode and disassemble an x86 or amd64 instruction
1977 */
1978
1979/*
1980 * These are the individual fields of a REX prefix. Note that a REX
1981 * prefix with none of these set is still needed to:
1982 * - use the MOVSXD (sign extend 32 to 64 bits) instruction
1983 * - access the %sil, %dil, %bpl, %spl registers
1984 */
1985#define REX_W 0x08 /* 64 bit operand size when set */
1986#define REX_R 0x04 /* high order bit extension of ModRM reg field */
1987#define REX_X 0x02 /* high order bit extension of SIB index field */
1988#define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */
1989
1990/*
1991 * These are the individual fields of a VEX prefix.
1992 */
1993#define VEX_R 0x08 /* REX.R in 1's complement form */
1994#define VEX_X 0x04 /* REX.X in 1's complement form */
1995#define VEX_B 0x02 /* REX.B in 1's complement form */
1996/* Vector Length, 0: scalar or 128-bit vector, 1: 256-bit vector */
1997#define VEX_L 0x04
1998#define VEX_W 0x08 /* opcode specific, use like REX.W */
1999#define VEX_m 0x1F /* VEX m-mmmm field */
2000#define VEX_v 0x78 /* VEX register specifier */
2001#define VEX_p 0x03 /* VEX pp field, opcode extension */
2002
2003/* VEX m-mmmm field, only used by three bytes prefix */
2004#define VEX_m_0F 0x01 /* implied 0F leading opcode byte */
2005#define VEX_m_0F38 0x02 /* implied 0F 38 leading opcode byte */
2006#define VEX_m_0F3A 0x03 /* implied 0F 3A leading opcode byte */
2007
2008/* VEX pp field, providing equivalent functionality of a SIMD prefix */
2009#define VEX_p_66 0x01
2010#define VEX_p_F3 0x02
2011#define VEX_p_F2 0x03
2012
2013/*
2014 * Even in 64 bit mode, usually only 4 byte immediate operands are supported.
2015 */
2016static int isize[] = {1, 2, 4, 4};
2017static int isize64[] = {1, 2, 4, 8};
2018
2019/*
2020 * Just a bunch of useful macros.
2021 */
2022#define WBIT(x) (x & 0x1) /* to get w bit */
2023#define REGNO(x) (x & 0x7) /* to get 3 bit register */
2024#define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */
2025#define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1)
2026#define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1)
2027
2028#define REG_ONLY 3 /* mode to indicate a register operand (not memory) */
2029
2030#define BYTE_OPND 0 /* w-bit value indicating byte register */
2031#define LONG_OPND 1 /* w-bit value indicating opnd_size register */
2032#define MM_OPND 2 /* "value" used to indicate a mmx reg */
2033#define XMM_OPND 3 /* "value" used to indicate a xmm reg */
2034#define SEG_OPND 4 /* "value" used to indicate a segment reg */
2035#define CONTROL_OPND 5 /* "value" used to indicate a control reg */
2036#define DEBUG_OPND 6 /* "value" used to indicate a debug reg */
2037#define TEST_OPND 7 /* "value" used to indicate a test reg */
2038#define WORD_OPND 8 /* w-bit value indicating word size reg */
2039#define YMM_OPND 9 /* "value" used to indicate a ymm reg */
2040
2041/*
2042 * Get the next byte and separate the op code into the high and low nibbles.
2043 */
2044static int
2045dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low)
2046{
2047 int byte;
2048
2049 /*
2050 * x86 instructions have a maximum length of 15 bytes. Bail out if
2051 * we try to read more.
2052 */
2053 if (x->d86_len >= 15)
2054 return (x->d86_error = 1);
2055
2056 if (x->d86_error)
2057 return (1);
2058 byte = x->d86_get_byte(x->d86_data);
2059 if (byte < 0)
2060 return (x->d86_error = 1);
2061 x->d86_bytes[x->d86_len++] = byte;
2062 *low = byte & 0xf; /* ----xxxx low 4 bits */
2063 *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */
2064 return (0);
2065}
2066
2067/*
2068 * Get and decode an SIB (scaled index base) byte
2069 */
2070static void
2071dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base)
2072{
2073 int byte;
2074
2075 if (x->d86_error)
2076 return;
2077
2078 byte = x->d86_get_byte(x->d86_data);
2079 if (byte < 0) {
2080 x->d86_error = 1;
2081 return;
2082 }
2083 x->d86_bytes[x->d86_len++] = byte;
2084
2085 *base = byte & 0x7;
2086 *index = (byte >> 3) & 0x7;
2087 *ss = (byte >> 6) & 0x3;
2088}
2089
2090/*
2091 * Get the byte following the op code and separate it into the
2092 * mode, register, and r/m fields.
2093 */
2094static void
2095dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m)
2096{
2097 if (x->d86_got_modrm == 0) {
2098 if (x->d86_rmindex == -1)
2099 x->d86_rmindex = x->d86_len;
2100 dtrace_get_SIB(x, mode, reg, r_m);
2101 x->d86_got_modrm = 1;
2102 }
2103}
2104
2105/*
2106 * Adjust register selection based on any REX prefix bits present.
2107 */
2108/*ARGSUSED*/
2109static void
2110dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m)
2111{
2112 if (reg != NULL && r_m == NULL) {
2113 if (rex_prefix & REX_B)
2114 *reg += 8;
2115 } else {
2116 if (reg != NULL && (REX_R & rex_prefix) != 0)
2117 *reg += 8;
2118 if (r_m != NULL && (REX_B & rex_prefix) != 0)
2119 *r_m += 8;
2120 }
2121}
2122
2123/*
2124 * Adjust register selection based on any VEX prefix bits present.
2125 * Notes: VEX.R, VEX.X and VEX.B use the inverted form compared with REX prefix
2126 */
2127/*ARGSUSED*/
2128static void
2129dtrace_vex_adjust(uint_t vex_byte1, uint_t mode, uint_t *reg, uint_t *r_m)
2130{
2131 if (reg != NULL && r_m == NULL) {
2132 if (!(vex_byte1 & VEX_B))
2133 *reg += 8;
2134 } else {
2135 if (reg != NULL && ((VEX_R & vex_byte1) == 0))
2136 *reg += 8;
2137 if (r_m != NULL && ((VEX_B & vex_byte1) == 0))
2138 *r_m += 8;
2139 }
2140}
2141
2142/*
2143 * Get an immediate operand of the given size, with sign extension.
2144 */
2145static void
2146dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex)
2147{
2148 int i;
2149 int byte;
2150 int valsize;
2151
2152 if (x->d86_numopnds < opindex + 1)
2153 x->d86_numopnds = opindex + 1;
2154
2155 switch (wbit) {
2156 case BYTE_OPND:
2157 valsize = 1;
2158 break;
2159 case LONG_OPND:
2160 if (x->d86_opnd_size == SIZE16)
2161 valsize = 2;
2162 else if (x->d86_opnd_size == SIZE32)
2163 valsize = 4;
2164 else
2165 valsize = 8;
2166 break;
2167 case MM_OPND:
2168 case XMM_OPND:
2169 case YMM_OPND:
2170 case SEG_OPND:
2171 case CONTROL_OPND:
2172 case DEBUG_OPND:
2173 case TEST_OPND:
2174 valsize = size;
2175 break;
2176 case WORD_OPND:
2177 valsize = 2;
2178 break;
2179 }
2180 if (valsize < size)
2181 valsize = size;
2182
2183 if (x->d86_error)
2184 return;
2185 x->d86_opnd[opindex].d86_value = 0;
2186 for (i = 0; i < size; ++i) {
2187 byte = x->d86_get_byte(x->d86_data);
2188 if (byte < 0) {
2189 x->d86_error = 1;
2190 return;
2191 }
2192 x->d86_bytes[x->d86_len++] = byte;
2193 x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8);
2194 }
2195 /* Do sign extension */
2196 if (x->d86_bytes[x->d86_len - 1] & 0x80) {
2197 for (; i < sizeof (uint64_t); i++)
2198 x->d86_opnd[opindex].d86_value |=
2199 (uint64_t)0xff << (i * 8);
2200 }
2201#ifdef DIS_TEXT
2202 x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
2203 x->d86_opnd[opindex].d86_value_size = valsize;
2204 x->d86_imm_bytes += size;
2205#endif
2206}
2207
2208/*
2209 * Get an ip relative operand of the given size, with sign extension.
2210 */
2211static void
2212dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex)
2213{
2214 dtrace_imm_opnd(x, wbit, size, opindex);
2215#ifdef DIS_TEXT
2216 x->d86_opnd[opindex].d86_mode = MODE_IPREL;
2217#endif
2218}
2219
2220/*
2221 * Check to see if there is a segment override prefix pending.
2222 * If so, print it in the current 'operand' location and set
2223 * the override flag back to false.
2224 */
2225/*ARGSUSED*/
2226static void
2227dtrace_check_override(dis86_t *x, int opindex)
2228{
2229#ifdef DIS_TEXT
2230 if (x->d86_seg_prefix) {
2231 (void) strlcat(x->d86_opnd[opindex].d86_prefix,
2232 x->d86_seg_prefix, PFIXLEN);
2233 }
2234#endif
2235 x->d86_seg_prefix = NULL;
2236}
2237
2238
2239/*
2240 * Process a single instruction Register or Memory operand.
2241 *
2242 * mode = addressing mode from ModRM byte
2243 * r_m = r_m (or reg if mode == 3) field from ModRM byte
2244 * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use.
2245 * o = index of operand that we are processing (0, 1 or 2)
2246 *
2247 * the value of reg or r_m must have already been adjusted for any REX prefix.
2248 */
2249/*ARGSUSED*/
2250static void
2251dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex)
2252{
2253 int have_SIB = 0; /* flag presence of scale-index-byte */
2254 uint_t ss; /* scale-factor from opcode */
2255 uint_t index; /* index register number */
2256 uint_t base; /* base register number */
2257 int dispsize; /* size of displacement in bytes */
2258#ifdef DIS_TEXT
2259 char *opnd = x->d86_opnd[opindex].d86_opnd;
2260#endif
2261
2262 if (x->d86_numopnds < opindex + 1)
2263 x->d86_numopnds = opindex + 1;
2264
2265 if (x->d86_error)
2266 return;
2267
2268 /*
2269 * first handle a simple register
2270 */
2271 if (mode == REG_ONLY) {
2272#ifdef DIS_TEXT
2273 switch (wbit) {
2274 case MM_OPND:
2275 (void) strlcat(opnd, dis_MMREG[r_m], OPLEN);
2276 break;
2277 case XMM_OPND:
2278 (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN);
2279 break;
2280 case YMM_OPND:
2281 (void) strlcat(opnd, dis_YMMREG[r_m], OPLEN);
2282 break;
2283 case SEG_OPND:
2284 (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN);
2285 break;
2286 case CONTROL_OPND:
2287 (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN);
2288 break;
2289 case DEBUG_OPND:
2290 (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN);
2291 break;
2292 case TEST_OPND:
2293 (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN);
2294 break;
2295 case BYTE_OPND:
2296 if (x->d86_rex_prefix == 0)
2297 (void) strlcat(opnd, dis_REG8[r_m], OPLEN);
2298 else
2299 (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN);
2300 break;
2301 case WORD_OPND:
2302 (void) strlcat(opnd, dis_REG16[r_m], OPLEN);
2303 break;
2304 case LONG_OPND:
2305 if (x->d86_opnd_size == SIZE16)
2306 (void) strlcat(opnd, dis_REG16[r_m], OPLEN);
2307 else if (x->d86_opnd_size == SIZE32)
2308 (void) strlcat(opnd, dis_REG32[r_m], OPLEN);
2309 else
2310 (void) strlcat(opnd, dis_REG64[r_m], OPLEN);
2311 break;
2312 }
2313#endif /* DIS_TEXT */
2314 return;
2315 }
2316
2317 /*
2318 * if symbolic representation, skip override prefix, if any
2319 */
2320 dtrace_check_override(x, opindex);
2321
2322 /*
2323 * Handle 16 bit memory references first, since they decode
2324 * the mode values more simply.
2325 * mode 1 is r_m + 8 bit displacement
2326 * mode 2 is r_m + 16 bit displacement
2327 * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp
2328 */
2329 if (x->d86_addr_size == SIZE16) {
2330 if ((mode == 0 && r_m == 6) || mode == 2)
2331 dtrace_imm_opnd(x, WORD_OPND, 2, opindex);
2332 else if (mode == 1)
2333 dtrace_imm_opnd(x, BYTE_OPND, 1, opindex);
2334#ifdef DIS_TEXT
2335 if (mode == 0 && r_m == 6)
2336 x->d86_opnd[opindex].d86_mode = MODE_SIGNED;
2337 else if (mode == 0)
2338 x->d86_opnd[opindex].d86_mode = MODE_NONE;
2339 else
2340 x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
2341 (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN);
2342#endif
2343 return;
2344 }
2345
2346 /*
2347 * 32 and 64 bit addressing modes are more complex since they
2348 * can involve an SIB (scaled index and base) byte to decode.
2349 */
2350 if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) {
2351 have_SIB = 1;
2352 dtrace_get_SIB(x, &ss, &index, &base);
2353 if (x->d86_error)
2354 return;
2355 if (base != 5 || mode != 0)
2356 if (x->d86_rex_prefix & REX_B)
2357 base += 8;
2358 if (x->d86_rex_prefix & REX_X)
2359 index += 8;
2360 } else {
2361 base = r_m;
2362 }
2363
2364 /*
2365 * Compute the displacement size and get its bytes
2366 */
2367 dispsize = 0;
2368
2369 if (mode == 1)
2370 dispsize = 1;
2371 else if (mode == 2)
2372 dispsize = 4;
2373 else if ((r_m & 7) == EBP_REGNO ||
2374 (have_SIB && (base & 7) == EBP_REGNO))
2375 dispsize = 4;
2376
2377 if (dispsize > 0) {
2378 dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND,
2379 dispsize, opindex);
2380 if (x->d86_error)
2381 return;
2382 }
2383
2384#ifdef DIS_TEXT
2385 if (dispsize > 0)
2386 x->d86_opnd[opindex].d86_mode = MODE_OFFSET;
2387
2388 if (have_SIB == 0) {
2389 if (x->d86_mode == SIZE32) {
2390 if (mode == 0)
2391 (void) strlcat(opnd, dis_addr32_mode0[r_m],
2392 OPLEN);
2393 else
2394 (void) strlcat(opnd, dis_addr32_mode12[r_m],
2395 OPLEN);
2396 } else {
2397 if (mode == 0) {
2398 (void) strlcat(opnd, dis_addr64_mode0[r_m],
2399 OPLEN);
2400 if (r_m == 5) {
2401 x->d86_opnd[opindex].d86_mode =
2402 MODE_RIPREL;
2403 }
2404 } else {
2405 (void) strlcat(opnd, dis_addr64_mode12[r_m],
2406 OPLEN);
2407 }
2408 }
2409 } else {
2410 uint_t need_paren = 0;
2411 char **regs;
2412 if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */
2413 regs = (char **)dis_REG32;
2414 else
2415 regs = (char **)dis_REG64;
2416
2417 /*
2418 * print the base (if any)
2419 */
2420 if (base == EBP_REGNO && mode == 0) {
2421 if (index != ESP_REGNO) {
2422 (void) strlcat(opnd, "(", OPLEN);
2423 need_paren = 1;
2424 }
2425 } else {
2426 (void) strlcat(opnd, "(", OPLEN);
2427 (void) strlcat(opnd, regs[base], OPLEN);
2428 need_paren = 1;
2429 }
2430
2431 /*
2432 * print the index (if any)
2433 */
2434 if (index != ESP_REGNO) {
2435 (void) strlcat(opnd, ",", OPLEN);
2436 (void) strlcat(opnd, regs[index], OPLEN);
2437 (void) strlcat(opnd, dis_scale_factor[ss], OPLEN);
2438 } else
2439 if (need_paren)
2440 (void) strlcat(opnd, ")", OPLEN);
2441 }
2442#endif
2443}
2444
2445/*
2446 * Operand sequence for standard instruction involving one register
2447 * and one register/memory operand.
2448 * wbit indicates a byte(0) or opnd_size(1) operation
2449 * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r")
2450 */
2451#define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \
2452 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2453 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2454 dtrace_get_operand(x, mode, r_m, wbit, vbit); \
2455 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \
2456}
2457
2458/*
2459 * Similar to above, but allows for the two operands to be of different
2460 * classes (ie. wbit).
2461 * wbit is for the r_m operand
2462 * w2 is for the reg operand
2463 */
2464#define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \
2465 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2466 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2467 dtrace_get_operand(x, mode, r_m, wbit, vbit); \
2468 dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \
2469}
2470
2471/*
2472 * Similar, but for 2 operands plus an immediate.
2473 * vbit indicates direction
2474 * 0 for "opcode imm, r, r_m" or
2475 * 1 for "opcode imm, r_m, r"
2476 */
2477#define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \
2478 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2479 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2480 dtrace_get_operand(x, mode, r_m, wbit, 2-vbit); \
2481 dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \
2482 dtrace_imm_opnd(x, wbit, immsize, 0); \
2483}
2484
2485/*
2486 * Similar, but for 2 operands plus two immediates.
2487 */
2488#define FOUROPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \
2489 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2490 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2491 dtrace_get_operand(x, mode, r_m, wbit, 2); \
2492 dtrace_get_operand(x, REG_ONLY, reg, w2, 3); \
2493 dtrace_imm_opnd(x, wbit, immsize, 1); \
2494 dtrace_imm_opnd(x, wbit, immsize, 0); \
2495}
2496
2497/*
2498 * 1 operands plus two immediates.
2499 */
2500#define ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, wbit, immsize) { \
2501 dtrace_get_modrm(x, &mode, &reg, &r_m); \
2502 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m); \
2503 dtrace_get_operand(x, mode, r_m, wbit, 2); \
2504 dtrace_imm_opnd(x, wbit, immsize, 1); \
2505 dtrace_imm_opnd(x, wbit, immsize, 0); \
2506}
2507
2508/*
2509 * Dissassemble a single x86 or amd64 instruction.
2510 *
2511 * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64)
2512 * for interpreting instructions.
2513 *
2514 * returns non-zero for bad opcode
2515 */
2516int
2517dtrace_disx86(dis86_t *x, uint_t cpu_mode)
2518{
2519 instable_t *dp; /* decode table being used */
2520#ifdef DIS_TEXT
2521 uint_t i;
2522#endif
2523#ifdef DIS_MEM
2524 uint_t nomem = 0;
2525#define NOMEM (nomem = 1)
2526#else
2527#define NOMEM /* nothing */
2528#endif
2529 uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */
2530 uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */
2531 uint_t wbit; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */
2532 uint_t w2; /* wbit value for second operand */
2533 uint_t vbit;
2534 uint_t mode = 0; /* mode value from ModRM byte */
2535 uint_t reg; /* reg value from ModRM byte */
2536 uint_t r_m; /* r_m value from ModRM byte */
2537
2538 uint_t opcode1; /* high nibble of 1st byte */
2539 uint_t opcode2; /* low nibble of 1st byte */
2540 uint_t opcode3; /* extra opcode bits usually from ModRM byte */
2541 uint_t opcode4; /* high nibble of 2nd byte */
2542 uint_t opcode5; /* low nibble of 2nd byte */
2543 uint_t opcode6; /* high nibble of 3rd byte */
2544 uint_t opcode7; /* low nibble of 3rd byte */
2545 uint_t opcode_bytes = 1;
2546
2547 /*
2548 * legacy prefixes come in 5 flavors, you should have only one of each
2549 */
2550 uint_t opnd_size_prefix = 0;
2551 uint_t addr_size_prefix = 0;
2552 uint_t segment_prefix = 0;
2553 uint_t lock_prefix = 0;
2554 uint_t rep_prefix = 0;
2555 uint_t rex_prefix = 0; /* amd64 register extension prefix */
2556
2557 /*
2558 * Intel VEX instruction encoding prefix and fields
2559 */
2560
2561 /* 0xC4 means 3 bytes prefix, 0xC5 means 2 bytes prefix */
2562 uint_t vex_prefix = 0;
2563
2564 /*
2565 * VEX prefix byte 1, includes vex.r, vex.x and vex.b
2566 * (for 3 bytes prefix)
2567 */
2568 uint_t vex_byte1 = 0;
2569
2570 /*
2571 * For 32-bit mode, it should prefetch the next byte to
2572 * distinguish between AVX and les/lds
2573 */
2574 uint_t vex_prefetch = 0;
2575
2576 uint_t vex_m = 0;
2577 uint_t vex_v = 0;
2578 uint_t vex_p = 0;
2579 uint_t vex_R = 1;
2580 uint_t vex_X = 1;
2581 uint_t vex_B = 1;
2582 uint_t vex_W = 0;
2583 uint_t vex_L;
2584
2585
2586 size_t off;
2587
2588 instable_t dp_mmx;
2589
2590 x->d86_len = 0;
2591 x->d86_rmindex = -1;
2592 x->d86_error = 0;
2593#ifdef DIS_TEXT
2594 x->d86_numopnds = 0;
2595 x->d86_seg_prefix = NULL;
2596 x->d86_mnem[0] = 0;
2597 for (i = 0; i < 4; ++i) {
2598 x->d86_opnd[i].d86_opnd[0] = 0;
2599 x->d86_opnd[i].d86_prefix[0] = 0;
2600 x->d86_opnd[i].d86_value_size = 0;
2601 x->d86_opnd[i].d86_value = 0;
2602 x->d86_opnd[i].d86_mode = MODE_NONE;
2603 }
2604#endif
2605 x->d86_rex_prefix = 0;
2606 x->d86_got_modrm = 0;
2607 x->d86_memsize = 0;
2608
2609 if (cpu_mode == SIZE16) {
2610 opnd_size = SIZE16;
2611 addr_size = SIZE16;
2612 } else if (cpu_mode == SIZE32) {
2613 opnd_size = SIZE32;
2614 addr_size = SIZE32;
2615 } else {
2616 opnd_size = SIZE32;
2617 addr_size = SIZE64;
2618 }
2619
2620 /*
2621 * Get one opcode byte and check for zero padding that follows
2622 * jump tables.
2623 */
2624 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2625 goto error;
2626
2627 if (opcode1 == 0 && opcode2 == 0 &&
2628 x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) {
2629#ifdef DIS_TEXT
2630 (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN);
2631#endif
2632 goto done;
2633 }
2634
2635 /*
2636 * Gather up legacy x86 prefix bytes.
2637 */
2638 for (;;) {
2639 uint_t *which_prefix = NULL;
2640
2641 dp = (instable_t *)&dis_distable[opcode1][opcode2];
2642
2643 switch (dp->it_adrmode) {
2644 case PREFIX:
2645 which_prefix = &rep_prefix;
2646 break;
2647 case LOCK:
2648 which_prefix = &lock_prefix;
2649 break;
2650 case OVERRIDE:
2651 which_prefix = &segment_prefix;
2652#ifdef DIS_TEXT
2653 x->d86_seg_prefix = (char *)dp->it_name;
2654#endif
2655 if (dp->it_invalid64 && cpu_mode == SIZE64)
2656 goto error;
2657 break;
2658 case AM:
2659 which_prefix = &addr_size_prefix;
2660 break;
2661 case DM:
2662 which_prefix = &opnd_size_prefix;
2663 break;
2664 }
2665 if (which_prefix == NULL)
2666 break;
2667 *which_prefix = (opcode1 << 4) | opcode2;
2668 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2669 goto error;
2670 }
2671
2672 /*
2673 * Handle amd64 mode PREFIX values.
2674 * Some of the segment prefixes are no-ops. (only FS/GS actually work)
2675 * We might have a REX prefix (opcodes 0x40-0x4f)
2676 */
2677 if (cpu_mode == SIZE64) {
2678 if (segment_prefix != 0x64 && segment_prefix != 0x65)
2679 segment_prefix = 0;
2680
2681 if (opcode1 == 0x4) {
2682 rex_prefix = (opcode1 << 4) | opcode2;
2683 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2684 goto error;
2685 dp = (instable_t *)&dis_distable[opcode1][opcode2];
2686 } else if (opcode1 == 0xC &&
2687 (opcode2 == 0x4 || opcode2 == 0x5)) {
2688 /* AVX instructions */
2689 vex_prefix = (opcode1 << 4) | opcode2;
2690 x->d86_rex_prefix = 0x40;
2691 }
2692 } else if (opcode1 == 0xC && (opcode2 == 0x4 || opcode2 == 0x5)) {
2693 /* LDS, LES or AVX */
2694 dtrace_get_modrm(x, &mode, &reg, &r_m);
2695 vex_prefetch = 1;
2696
2697 if (mode == REG_ONLY) {
2698 /* AVX */
2699 vex_prefix = (opcode1 << 4) | opcode2;
2700 x->d86_rex_prefix = 0x40;
2701 opcode3 = (((mode << 3) | reg)>>1) & 0x0F;
2702 opcode4 = ((reg << 3) | r_m) & 0x0F;
2703 }
2704 }
2705
2706 if (vex_prefix == VEX_2bytes) {
2707 if (!vex_prefetch) {
2708 if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0)
2709 goto error;
2710 }
2711 vex_R = ((opcode3 & VEX_R) & 0x0F) >> 3;
2712 vex_L = ((opcode4 & VEX_L) & 0x0F) >> 2;
2713 vex_v = (((opcode3 << 4) | opcode4) & VEX_v) >> 3;
2714 vex_p = opcode4 & VEX_p;
2715 /*
2716 * The vex.x and vex.b bits are not defined in two bytes
2717 * mode vex prefix, their default values are 1
2718 */
2719 vex_byte1 = (opcode3 & VEX_R) | VEX_X | VEX_B;
2720
2721 if (vex_R == 0)
2722 x->d86_rex_prefix |= REX_R;
2723
2724 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2725 goto error;
2726
2727 switch (vex_p) {
2728 case VEX_p_66:
2729 dp = (instable_t *)
2730 &dis_opAVX660F[(opcode1 << 4) | opcode2];
2731 break;
2732 case VEX_p_F3:
2733 dp = (instable_t *)
2734 &dis_opAVXF30F[(opcode1 << 4) | opcode2];
2735 break;
2736 case VEX_p_F2:
2737 dp = (instable_t *)
2738 &dis_opAVXF20F [(opcode1 << 4) | opcode2];
2739 break;
2740 default:
2741 dp = (instable_t *)
2742 &dis_opAVX0F[opcode1][opcode2];
2743
2744 }
2745
2746 } else if (vex_prefix == VEX_3bytes) {
2747 if (!vex_prefetch) {
2748 if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0)
2749 goto error;
2750 }
2751 vex_R = (opcode3 & VEX_R) >> 3;
2752 vex_X = (opcode3 & VEX_X) >> 2;
2753 vex_B = (opcode3 & VEX_B) >> 1;
2754 vex_m = (((opcode3 << 4) | opcode4) & VEX_m);
2755 vex_byte1 = opcode3 & (VEX_R | VEX_X | VEX_B);
2756
2757 if (vex_R == 0)
2758 x->d86_rex_prefix |= REX_R;
2759 if (vex_X == 0)
2760 x->d86_rex_prefix |= REX_X;
2761 if (vex_B == 0)
2762 x->d86_rex_prefix |= REX_B;
2763
2764 if (dtrace_get_opcode(x, &opcode5, &opcode6) != 0)
2765 goto error;
2766 vex_W = (opcode5 & VEX_W) >> 3;
2767 vex_L = (opcode6 & VEX_L) >> 2;
2768 vex_v = (((opcode5 << 4) | opcode6) & VEX_v) >> 3;
2769 vex_p = opcode6 & VEX_p;
2770
2771 if (vex_W)
2772 x->d86_rex_prefix |= REX_W;
2773
2774 /* Only these three vex_m values valid; others are reserved */
2775 if ((vex_m != VEX_m_0F) && (vex_m != VEX_m_0F38) &&
2776 (vex_m != VEX_m_0F3A))
2777 goto error;
2778
2779 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0)
2780 goto error;
2781
2782 switch (vex_p) {
2783 case VEX_p_66:
2784 if (vex_m == VEX_m_0F) {
2785 dp = (instable_t *)
2786 &dis_opAVX660F
2787 [(opcode1 << 4) | opcode2];
2788 } else if (vex_m == VEX_m_0F38) {
2789 dp = (instable_t *)
2790 &dis_opAVX660F38
2791 [(opcode1 << 4) | opcode2];
2792 } else if (vex_m == VEX_m_0F3A) {
2793 dp = (instable_t *)
2794 &dis_opAVX660F3A
2795 [(opcode1 << 4) | opcode2];
2796 } else {
2797 goto error;
2798 }
2799 break;
2800 case VEX_p_F3:
2801 if (vex_m == VEX_m_0F) {
2802 dp = (instable_t *)
2803 &dis_opAVXF30F
2804 [(opcode1 << 4) | opcode2];
2805 } else {
2806 goto error;
2807 }
2808 break;
2809 case VEX_p_F2:
2810 if (vex_m == VEX_m_0F) {
2811 dp = (instable_t *)
2812 &dis_opAVXF20F
2813 [(opcode1 << 4) | opcode2];
2814 } else {
2815 goto error;
2816 }
2817 break;
2818 default:
2819 dp = (instable_t *)
2820 &dis_opAVX0F[opcode1][opcode2];
2821
2822 }
2823 }
2824 if (vex_prefix) {
2825 if (vex_L)
2826 wbit = YMM_OPND;
2827 else
2828 wbit = XMM_OPND;
2829 }
2830
2831 /*
2832 * Deal with selection of operand and address size now.
2833 * Note that the REX.W bit being set causes opnd_size_prefix to be
2834 * ignored.
2835 */
2836 if (cpu_mode == SIZE64) {
2837 if ((rex_prefix & REX_W) || vex_W)
2838 opnd_size = SIZE64;
2839 else if (opnd_size_prefix)
2840 opnd_size = SIZE16;
2841
2842 if (addr_size_prefix)
2843 addr_size = SIZE32;
2844 } else if (cpu_mode == SIZE32) {
2845 if (opnd_size_prefix)
2846 opnd_size = SIZE16;
2847 if (addr_size_prefix)
2848 addr_size = SIZE16;
2849 } else {
2850 if (opnd_size_prefix)
2851 opnd_size = SIZE32;
2852 if (addr_size_prefix)
2853 addr_size = SIZE32;
2854 }
2855 /*
2856 * The pause instruction - a repz'd nop. This doesn't fit
2857 * with any of the other prefix goop added for SSE, so we'll
2858 * special-case it here.
2859 */
2860 if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) {
2861 rep_prefix = 0;
2862 dp = (instable_t *)&dis_opPause;
2863 }
2864
2865 /*
2866 * Some 386 instructions have 2 bytes of opcode before the mod_r/m
2867 * byte so we may need to perform a table indirection.
2868 */
2869 if (dp->it_indirect == (instable_t *)dis_op0F) {
2870 if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0)
2871 goto error;
2872 opcode_bytes = 2;
2873 if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) {
2874 uint_t subcode;
2875
2876 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2877 goto error;
2878 opcode_bytes = 3;
2879 subcode = ((opcode6 & 0x3) << 1) |
2880 ((opcode7 & 0x8) >> 3);
2881 dp = (instable_t *)&dis_op0F7123[opcode5][subcode];
2882 } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) {
2883 dp = (instable_t *)&dis_op0FC8[0];
2884 } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) {
2885 opcode_bytes = 3;
2886 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2887 goto error;
2888 if (opnd_size == SIZE16)
2889 opnd_size = SIZE32;
2890
2891 dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7];
2892#ifdef DIS_TEXT
2893 if (strcmp(dp->it_name, "INVALID") == 0)
2894 goto error;
2895#endif
2896 switch (dp->it_adrmode) {
2897 case XMMP_66r:
2898 case XMMPRM_66r:
2899 case XMM3PM_66r:
2900 if (opnd_size_prefix == 0) {
2901 goto error;
2902 }
2903 break;
2904 case XMMP_66o:
2905 if (opnd_size_prefix == 0) {
2906 /* SSSE3 MMX instructions */
2907 dp_mmx = *dp;
2908 dp = &dp_mmx;
2909 dp->it_adrmode = MMOPM_66o;
2910#ifdef DIS_MEM
2911 dp->it_size = 8;
2912#endif
2913 }
2914 break;
2915 default:
2916 goto error;
2917 }
2918 } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) {
2919 opcode_bytes = 3;
2920 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0)
2921 goto error;
2922 dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7];
2923
2924 /*
2925 * Both crc32 and movbe have the same 3rd opcode
2926 * byte of either 0xF0 or 0xF1, so we use another
2927 * indirection to distinguish between the two.
2928 */
2929 if (dp->it_indirect == (instable_t *)dis_op0F38F0 ||
2930 dp->it_indirect == (instable_t *)dis_op0F38F1) {
2931
2932 dp = dp->it_indirect;
2933 if (rep_prefix != 0xF2) {
2934 /* It is movbe */
2935 dp++;
2936 }
2937 }
2938#ifdef DIS_TEXT
2939 if (strcmp(dp->it_name, "INVALID") == 0)
2940 goto error;
2941#endif
2942 switch (dp->it_adrmode) {
2943 case RM_66r:
2908 case XMM_66r:
2909 case XMMM_66r:
2910 if (opnd_size_prefix == 0) {
2911 goto error;
2912 }
2913 break;
2914 case XMM_66o:
2915 if (opnd_size_prefix == 0) {
2916 /* SSSE3 MMX instructions */
2917 dp_mmx = *dp;
2918 dp = &dp_mmx;
2919 dp->it_adrmode = MM;
2920#ifdef DIS_MEM
2921 dp->it_size = 8;
2922#endif
2923 }
2924 break;
2925 case CRC32:
2926 if (rep_prefix != 0xF2) {
2927 goto error;
2928 }
2929 rep_prefix = 0;
2930 break;
2931 case MOVBE:
2932 if (rep_prefix != 0x0) {
2933 goto error;
2934 }
2935 break;
2936 default:
2937 goto error;
2938 }
2939 } else {
2940 dp = (instable_t *)&dis_op0F[opcode4][opcode5];
2941 }
2942 }
2943
2944 /*
2945 * If still not at a TERM decode entry, then a ModRM byte
2946 * exists and its fields further decode the instruction.
2947 */
2948 x->d86_got_modrm = 0;
2949 if (dp->it_indirect != TERM) {
2950 dtrace_get_modrm(x, &mode, &opcode3, &r_m);
2951 if (x->d86_error)
2952 goto error;
2953 reg = opcode3;
2954
2955 /*
2956 * decode 287 instructions (D8-DF) from opcodeN
2957 */
2958 if (opcode1 == 0xD && opcode2 >= 0x8) {
2959 if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4)
2960 dp = (instable_t *)&dis_opFP5[r_m];
2961 else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4)
2962 dp = (instable_t *)&dis_opFP7[opcode3];
2963 else if (opcode2 == 0xB && mode == 0x3)
2964 dp = (instable_t *)&dis_opFP6[opcode3];
2965 else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4)
2966 dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m];
2967 else if (mode == 0x3)
2968 dp = (instable_t *)
2969 &dis_opFP3[opcode2 - 8][opcode3];
2970 else
2971 dp = (instable_t *)
2972 &dis_opFP1n2[opcode2 - 8][opcode3];
2973 } else {
2974 dp = (instable_t *)dp->it_indirect + opcode3;
2975 }
2976 }
2977
2978 /*
2979 * In amd64 bit mode, ARPL opcode is changed to MOVSXD
2980 * (sign extend 32bit to 64 bit)
2981 */
2982 if ((vex_prefix == 0) && cpu_mode == SIZE64 &&
2983 opcode1 == 0x6 && opcode2 == 0x3)
2984 dp = (instable_t *)&dis_opMOVSLD;
2985
2986 /*
2987 * at this point we should have a correct (or invalid) opcode
2988 */
2989 if (cpu_mode == SIZE64 && dp->it_invalid64 ||
2990 cpu_mode != SIZE64 && dp->it_invalid32)
2991 goto error;
2992 if (dp->it_indirect != TERM)
2993 goto error;
2994
2995 /*
2996 * deal with MMX/SSE opcodes which are changed by prefixes
2997 */
2998 switch (dp->it_adrmode) {
2999 case MMO:
3000 case MMOIMPL:
3001 case MMO3P:
3002 case MMOM3:
3003 case MMOMS:
3004 case MMOPM:
3005 case MMOPRM:
3006 case MMOS:
3007 case XMMO:
3008 case XMMOM:
3009 case XMMOMS:
3010 case XMMOPM:
3011 case XMMOS:
3012 case XMMOMX:
3013 case XMMOX3:
3014 case XMMOXMM:
3015 /*
3016 * This is horrible. Some SIMD instructions take the
3017 * form 0x0F 0x?? ..., which is easily decoded using the
3018 * existing tables. Other SIMD instructions use various
3019 * prefix bytes to overload existing instructions. For
3020 * Example, addps is F0, 58, whereas addss is F3 (repz),
3021 * F0, 58. Presumably someone got a raise for this.
3022 *
3023 * If we see one of the instructions which can be
3024 * modified in this way (if we've got one of the SIMDO*
3025 * address modes), we'll check to see if the last prefix
3026 * was a repz. If it was, we strip the prefix from the
3027 * mnemonic, and we indirect using the dis_opSIMDrepz
3028 * table.
3029 */
3030
3031 /*
3032 * Calculate our offset in dis_op0F
3033 */
3034 if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F))
3035 goto error;
3036
3037 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
3038 sizeof (instable_t);
3039
3040 /*
3041 * Rewrite if this instruction used one of the magic prefixes.
3042 */
3043 if (rep_prefix) {
3044 if (rep_prefix == 0xf2)
3045 dp = (instable_t *)&dis_opSIMDrepnz[off];
3046 else
3047 dp = (instable_t *)&dis_opSIMDrepz[off];
3048 rep_prefix = 0;
3049 } else if (opnd_size_prefix) {
3050 dp = (instable_t *)&dis_opSIMDdata16[off];
3051 opnd_size_prefix = 0;
3052 if (opnd_size == SIZE16)
3053 opnd_size = SIZE32;
3054 }
3055 break;
3056
2944 case XMM_66r:
2945 case XMMM_66r:
2946 if (opnd_size_prefix == 0) {
2947 goto error;
2948 }
2949 break;
2950 case XMM_66o:
2951 if (opnd_size_prefix == 0) {
2952 /* SSSE3 MMX instructions */
2953 dp_mmx = *dp;
2954 dp = &dp_mmx;
2955 dp->it_adrmode = MM;
2956#ifdef DIS_MEM
2957 dp->it_size = 8;
2958#endif
2959 }
2960 break;
2961 case CRC32:
2962 if (rep_prefix != 0xF2) {
2963 goto error;
2964 }
2965 rep_prefix = 0;
2966 break;
2967 case MOVBE:
2968 if (rep_prefix != 0x0) {
2969 goto error;
2970 }
2971 break;
2972 default:
2973 goto error;
2974 }
2975 } else {
2976 dp = (instable_t *)&dis_op0F[opcode4][opcode5];
2977 }
2978 }
2979
2980 /*
2981 * If still not at a TERM decode entry, then a ModRM byte
2982 * exists and its fields further decode the instruction.
2983 */
2984 x->d86_got_modrm = 0;
2985 if (dp->it_indirect != TERM) {
2986 dtrace_get_modrm(x, &mode, &opcode3, &r_m);
2987 if (x->d86_error)
2988 goto error;
2989 reg = opcode3;
2990
2991 /*
2992 * decode 287 instructions (D8-DF) from opcodeN
2993 */
2994 if (opcode1 == 0xD && opcode2 >= 0x8) {
2995 if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4)
2996 dp = (instable_t *)&dis_opFP5[r_m];
2997 else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4)
2998 dp = (instable_t *)&dis_opFP7[opcode3];
2999 else if (opcode2 == 0xB && mode == 0x3)
3000 dp = (instable_t *)&dis_opFP6[opcode3];
3001 else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4)
3002 dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m];
3003 else if (mode == 0x3)
3004 dp = (instable_t *)
3005 &dis_opFP3[opcode2 - 8][opcode3];
3006 else
3007 dp = (instable_t *)
3008 &dis_opFP1n2[opcode2 - 8][opcode3];
3009 } else {
3010 dp = (instable_t *)dp->it_indirect + opcode3;
3011 }
3012 }
3013
3014 /*
3015 * In amd64 bit mode, ARPL opcode is changed to MOVSXD
3016 * (sign extend 32bit to 64 bit)
3017 */
3018 if ((vex_prefix == 0) && cpu_mode == SIZE64 &&
3019 opcode1 == 0x6 && opcode2 == 0x3)
3020 dp = (instable_t *)&dis_opMOVSLD;
3021
3022 /*
3023 * at this point we should have a correct (or invalid) opcode
3024 */
3025 if (cpu_mode == SIZE64 && dp->it_invalid64 ||
3026 cpu_mode != SIZE64 && dp->it_invalid32)
3027 goto error;
3028 if (dp->it_indirect != TERM)
3029 goto error;
3030
3031 /*
3032 * deal with MMX/SSE opcodes which are changed by prefixes
3033 */
3034 switch (dp->it_adrmode) {
3035 case MMO:
3036 case MMOIMPL:
3037 case MMO3P:
3038 case MMOM3:
3039 case MMOMS:
3040 case MMOPM:
3041 case MMOPRM:
3042 case MMOS:
3043 case XMMO:
3044 case XMMOM:
3045 case XMMOMS:
3046 case XMMOPM:
3047 case XMMOS:
3048 case XMMOMX:
3049 case XMMOX3:
3050 case XMMOXMM:
3051 /*
3052 * This is horrible. Some SIMD instructions take the
3053 * form 0x0F 0x?? ..., which is easily decoded using the
3054 * existing tables. Other SIMD instructions use various
3055 * prefix bytes to overload existing instructions. For
3056 * Example, addps is F0, 58, whereas addss is F3 (repz),
3057 * F0, 58. Presumably someone got a raise for this.
3058 *
3059 * If we see one of the instructions which can be
3060 * modified in this way (if we've got one of the SIMDO*
3061 * address modes), we'll check to see if the last prefix
3062 * was a repz. If it was, we strip the prefix from the
3063 * mnemonic, and we indirect using the dis_opSIMDrepz
3064 * table.
3065 */
3066
3067 /*
3068 * Calculate our offset in dis_op0F
3069 */
3070 if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F))
3071 goto error;
3072
3073 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
3074 sizeof (instable_t);
3075
3076 /*
3077 * Rewrite if this instruction used one of the magic prefixes.
3078 */
3079 if (rep_prefix) {
3080 if (rep_prefix == 0xf2)
3081 dp = (instable_t *)&dis_opSIMDrepnz[off];
3082 else
3083 dp = (instable_t *)&dis_opSIMDrepz[off];
3084 rep_prefix = 0;
3085 } else if (opnd_size_prefix) {
3086 dp = (instable_t *)&dis_opSIMDdata16[off];
3087 opnd_size_prefix = 0;
3088 if (opnd_size == SIZE16)
3089 opnd_size = SIZE32;
3090 }
3091 break;
3092
3093 case MG9:
3094 /*
3095 * More horribleness: the group 9 (0xF0 0xC7) instructions are
3096 * allowed an optional prefix of 0x66 or 0xF3. This is similar
3097 * to the SIMD business described above, but with a different
3098 * addressing mode (and an indirect table), so we deal with it
3099 * separately (if similarly).
3100 *
3101 * Intel further complicated this with the release of Ivy Bridge
3102 * where they overloaded these instructions based on the ModR/M
3103 * bytes. The VMX instructions have a mode of 0 since they are
3104 * memory instructions but rdrand instructions have a mode of
3105 * 0b11 (REG_ONLY) because they only operate on registers. While
3106 * there are different prefix formats, for now it is sufficient
3107 * to use a single different table.
3108 */
3109
3110 /*
3111 * Calculate our offset in dis_op0FC7 (the group 9 table)
3112 */
3113 if ((uintptr_t)dp - (uintptr_t)dis_op0FC7 > sizeof (dis_op0FC7))
3114 goto error;
3115
3116 off = ((uintptr_t)dp - (uintptr_t)dis_op0FC7) /
3117 sizeof (instable_t);
3118
3119 /*
3120 * If we have a mode of 0b11 then we have to rewrite this.
3121 */
3122 dtrace_get_modrm(x, &mode, &reg, &r_m);
3123 if (mode == REG_ONLY) {
3124 dp = (instable_t *)&dis_op0FC7m3[off];
3125 break;
3126 }
3127
3128 /*
3129 * Rewrite if this instruction used one of the magic prefixes.
3130 */
3131 if (rep_prefix) {
3132 if (rep_prefix == 0xf3)
3133 dp = (instable_t *)&dis_opF30FC7[off];
3134 else
3135 goto error;
3136 rep_prefix = 0;
3137 } else if (opnd_size_prefix) {
3138 dp = (instable_t *)&dis_op660FC7[off];
3139 opnd_size_prefix = 0;
3140 if (opnd_size == SIZE16)
3141 opnd_size = SIZE32;
3142 }
3143 break;
3144
3145
3057 case MMOSH:
3058 /*
3059 * As with the "normal" SIMD instructions, the MMX
3060 * shuffle instructions are overloaded. These
3061 * instructions, however, are special in that they use
3062 * an extra byte, and thus an extra table. As of this
3063 * writing, they only use the opnd_size prefix.
3064 */
3065
3066 /*
3067 * Calculate our offset in dis_op0F7123
3068 */
3069 if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 >
3070 sizeof (dis_op0F7123))
3071 goto error;
3072
3073 if (opnd_size_prefix) {
3074 off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) /
3075 sizeof (instable_t);
3076 dp = (instable_t *)&dis_opSIMD7123[off];
3077 opnd_size_prefix = 0;
3078 if (opnd_size == SIZE16)
3079 opnd_size = SIZE32;
3080 }
3081 break;
3082 case MRw:
3083 if (rep_prefix) {
3084 if (rep_prefix == 0xf3) {
3085
3086 /*
3087 * Calculate our offset in dis_op0F
3088 */
3089 if ((uintptr_t)dp - (uintptr_t)dis_op0F
3090 > sizeof (dis_op0F))
3091 goto error;
3092
3093 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
3094 sizeof (instable_t);
3095
3096 dp = (instable_t *)&dis_opSIMDrepz[off];
3097 rep_prefix = 0;
3098 } else {
3099 goto error;
3100 }
3101 }
3102 break;
3103 }
3104
3105 /*
3106 * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64.
3107 */
3108 if (cpu_mode == SIZE64)
3109 if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop))
3110 opnd_size = SIZE64;
3111
3112#ifdef DIS_TEXT
3113 /*
3114 * At this point most instructions can format the opcode mnemonic
3115 * including the prefixes.
3116 */
3117 if (lock_prefix)
3118 (void) strlcat(x->d86_mnem, "lock ", OPLEN);
3119
3120 if (rep_prefix == 0xf2)
3121 (void) strlcat(x->d86_mnem, "repnz ", OPLEN);
3122 else if (rep_prefix == 0xf3)
3123 (void) strlcat(x->d86_mnem, "repz ", OPLEN);
3124
3125 if (cpu_mode == SIZE64 && addr_size_prefix)
3126 (void) strlcat(x->d86_mnem, "addr32 ", OPLEN);
3127
3128 if (dp->it_adrmode != CBW &&
3129 dp->it_adrmode != CWD &&
3130 dp->it_adrmode != XMMSFNC) {
3131 if (strcmp(dp->it_name, "INVALID") == 0)
3132 goto error;
3133 (void) strlcat(x->d86_mnem, dp->it_name, OPLEN);
3134 if (dp->it_suffix) {
3135 char *types[] = {"", "w", "l", "q"};
3136 if (opcode_bytes == 2 && opcode4 == 4) {
3137 /* It's a cmovx.yy. Replace the suffix x */
3138 for (i = 5; i < OPLEN; i++) {
3139 if (x->d86_mnem[i] == '.')
3140 break;
3141 }
3142 x->d86_mnem[i - 1] = *types[opnd_size];
3143 } else if ((opnd_size == 2) && (opcode_bytes == 3) &&
3144 ((opcode6 == 1 && opcode7 == 6) ||
3145 (opcode6 == 2 && opcode7 == 2))) {
3146 /*
3147 * To handle PINSRD and PEXTRD
3148 */
3149 (void) strlcat(x->d86_mnem, "d", OPLEN);
3150 } else {
3151 (void) strlcat(x->d86_mnem, types[opnd_size],
3152 OPLEN);
3153 }
3154 }
3155 }
3156#endif
3157
3158 /*
3159 * Process operands based on the addressing modes.
3160 */
3161 x->d86_mode = cpu_mode;
3162 /*
3163 * In vex mode the rex_prefix has no meaning
3164 */
3165 if (!vex_prefix)
3166 x->d86_rex_prefix = rex_prefix;
3167 x->d86_opnd_size = opnd_size;
3168 x->d86_addr_size = addr_size;
3169 vbit = 0; /* initialize for mem/reg -> reg */
3170 switch (dp->it_adrmode) {
3171 /*
3172 * amd64 instruction to sign extend 32 bit reg/mem operands
3173 * into 64 bit register values
3174 */
3175 case MOVSXZ:
3176#ifdef DIS_TEXT
3177 if (rex_prefix == 0)
3178 (void) strncpy(x->d86_mnem, "movzld", OPLEN);
3179#endif
3180 dtrace_get_modrm(x, &mode, &reg, &r_m);
3181 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3182 x->d86_opnd_size = SIZE64;
3183 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3184 x->d86_opnd_size = opnd_size = SIZE32;
3185 wbit = LONG_OPND;
3186 dtrace_get_operand(x, mode, r_m, wbit, 0);
3187 break;
3188
3189 /*
3190 * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF)
3191 * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7)
3192 * wbit lives in 2nd byte, note that operands
3193 * are different sized
3194 */
3195 case MOVZ:
3196 if (rex_prefix & REX_W) {
3197 /* target register size = 64 bit */
3198 x->d86_mnem[5] = 'q';
3199 }
3200 dtrace_get_modrm(x, &mode, &reg, &r_m);
3201 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3202 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3203 x->d86_opnd_size = opnd_size = SIZE16;
3204 wbit = WBIT(opcode5);
3205 dtrace_get_operand(x, mode, r_m, wbit, 0);
3206 break;
3207 case CRC32:
3208 opnd_size = SIZE32;
3209 if (rex_prefix & REX_W)
3210 opnd_size = SIZE64;
3211 x->d86_opnd_size = opnd_size;
3212
3213 dtrace_get_modrm(x, &mode, &reg, &r_m);
3214 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3215 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3216 wbit = WBIT(opcode7);
3217 if (opnd_size_prefix)
3218 x->d86_opnd_size = opnd_size = SIZE16;
3219 dtrace_get_operand(x, mode, r_m, wbit, 0);
3220 break;
3221 case MOVBE:
3222 opnd_size = SIZE32;
3223 if (rex_prefix & REX_W)
3224 opnd_size = SIZE64;
3225 x->d86_opnd_size = opnd_size;
3226
3227 dtrace_get_modrm(x, &mode, &reg, &r_m);
3228 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3229 wbit = WBIT(opcode7);
3230 if (opnd_size_prefix)
3231 x->d86_opnd_size = opnd_size = SIZE16;
3232 if (wbit) {
3233 /* reg -> mem */
3234 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3235 dtrace_get_operand(x, mode, r_m, wbit, 1);
3236 } else {
3237 /* mem -> reg */
3238 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3239 dtrace_get_operand(x, mode, r_m, wbit, 0);
3240 }
3241 break;
3242
3243 /*
3244 * imul instruction, with either 8-bit or longer immediate
3245 * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s)
3246 */
3247 case IMUL:
3248 wbit = LONG_OPND;
3249 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND,
3250 OPSIZE(opnd_size, opcode2 == 0x9), 1);
3251 break;
3252
3253 /* memory or register operand to register, with 'w' bit */
3254 case MRw:
3255 wbit = WBIT(opcode2);
3256 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3257 break;
3258
3259 /* register to memory or register operand, with 'w' bit */
3260 /* arpl happens to fit here also because it is odd */
3261 case RMw:
3262 if (opcode_bytes == 2)
3263 wbit = WBIT(opcode5);
3264 else
3265 wbit = WBIT(opcode2);
3266 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3267 break;
3268
3269 /* xaddb instruction */
3270 case XADDB:
3271 wbit = 0;
3272 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3273 break;
3274
3275 /* MMX register to memory or register operand */
3276 case MMS:
3277 case MMOS:
3278#ifdef DIS_TEXT
3279 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3280#else
3281 wbit = LONG_OPND;
3282#endif
3283 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
3284 break;
3285
3286 /* MMX register to memory */
3287 case MMOMS:
3288 dtrace_get_modrm(x, &mode, &reg, &r_m);
3289 if (mode == REG_ONLY)
3290 goto error;
3291 wbit = MM_OPND;
3292 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
3293 break;
3294
3295 /* Double shift. Has immediate operand specifying the shift. */
3296 case DSHIFT:
3297 wbit = LONG_OPND;
3298 dtrace_get_modrm(x, &mode, &reg, &r_m);
3299 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3300 dtrace_get_operand(x, mode, r_m, wbit, 2);
3301 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3302 dtrace_imm_opnd(x, wbit, 1, 0);
3303 break;
3304
3305 /*
3306 * Double shift. With no immediate operand, specifies using %cl.
3307 */
3308 case DSHIFTcl:
3309 wbit = LONG_OPND;
3310 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3311 break;
3312
3313 /* immediate to memory or register operand */
3314 case IMlw:
3315 wbit = WBIT(opcode2);
3316 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3317 dtrace_get_operand(x, mode, r_m, wbit, 1);
3318 /*
3319 * Have long immediate for opcode 0x81, but not 0x80 nor 0x83
3320 */
3321 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0);
3322 break;
3323
3324 /* immediate to memory or register operand with the */
3325 /* 'w' bit present */
3326 case IMw:
3327 wbit = WBIT(opcode2);
3328 dtrace_get_modrm(x, &mode, &reg, &r_m);
3329 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3330 dtrace_get_operand(x, mode, r_m, wbit, 1);
3331 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
3332 break;
3333
3334 /* immediate to register with register in low 3 bits */
3335 /* of op code */
3336 case IR:
3337 /* w-bit here (with regs) is bit 3 */
3338 wbit = opcode2 >>3 & 0x1;
3339 reg = REGNO(opcode2);
3340 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3341 mode = REG_ONLY;
3342 r_m = reg;
3343 dtrace_get_operand(x, mode, r_m, wbit, 1);
3344 dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0);
3345 break;
3346
3347 /* MMX immediate shift of register */
3348 case MMSH:
3349 case MMOSH:
3350 wbit = MM_OPND;
3351 goto mm_shift; /* in next case */
3352
3353 /* SIMD immediate shift of register */
3354 case XMMSH:
3355 wbit = XMM_OPND;
3356mm_shift:
3357 reg = REGNO(opcode7);
3358 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3359 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
3360 dtrace_imm_opnd(x, wbit, 1, 0);
3361 NOMEM;
3362 break;
3363
3364 /* accumulator to memory operand */
3365 case AO:
3366 vbit = 1;
3367 /*FALLTHROUGH*/
3368
3369 /* memory operand to accumulator */
3370 case OA:
3371 wbit = WBIT(opcode2);
3372 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit);
3373 dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit);
3374#ifdef DIS_TEXT
3375 x->d86_opnd[vbit].d86_mode = MODE_OFFSET;
3376#endif
3377 break;
3378
3379
3380 /* segment register to memory or register operand */
3381 case SM:
3382 vbit = 1;
3383 /*FALLTHROUGH*/
3384
3385 /* memory or register operand to segment register */
3386 case MS:
3387 dtrace_get_modrm(x, &mode, &reg, &r_m);
3388 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3389 dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit);
3390 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit);
3391 break;
3392
3393 /*
3394 * rotate or shift instructions, which may shift by 1 or
3395 * consult the cl register, depending on the 'v' bit
3396 */
3397 case Mv:
3398 vbit = VBIT(opcode2);
3399 wbit = WBIT(opcode2);
3400 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3401 dtrace_get_operand(x, mode, r_m, wbit, 1);
3402#ifdef DIS_TEXT
3403 if (vbit) {
3404 (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN);
3405 } else {
3406 x->d86_opnd[0].d86_mode = MODE_SIGNED;
3407 x->d86_opnd[0].d86_value_size = 1;
3408 x->d86_opnd[0].d86_value = 1;
3409 }
3410#endif
3411 break;
3412 /*
3413 * immediate rotate or shift instructions
3414 */
3415 case MvI:
3416 wbit = WBIT(opcode2);
3417normal_imm_mem:
3418 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3419 dtrace_get_operand(x, mode, r_m, wbit, 1);
3420 dtrace_imm_opnd(x, wbit, 1, 0);
3421 break;
3422
3423 /* bit test instructions */
3424 case MIb:
3425 wbit = LONG_OPND;
3426 goto normal_imm_mem;
3427
3428 /* single memory or register operand with 'w' bit present */
3429 case Mw:
3430 wbit = WBIT(opcode2);
3431just_mem:
3432 dtrace_get_modrm(x, &mode, &reg, &r_m);
3433 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3434 dtrace_get_operand(x, mode, r_m, wbit, 0);
3435 break;
3436
3146 case MMOSH:
3147 /*
3148 * As with the "normal" SIMD instructions, the MMX
3149 * shuffle instructions are overloaded. These
3150 * instructions, however, are special in that they use
3151 * an extra byte, and thus an extra table. As of this
3152 * writing, they only use the opnd_size prefix.
3153 */
3154
3155 /*
3156 * Calculate our offset in dis_op0F7123
3157 */
3158 if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 >
3159 sizeof (dis_op0F7123))
3160 goto error;
3161
3162 if (opnd_size_prefix) {
3163 off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) /
3164 sizeof (instable_t);
3165 dp = (instable_t *)&dis_opSIMD7123[off];
3166 opnd_size_prefix = 0;
3167 if (opnd_size == SIZE16)
3168 opnd_size = SIZE32;
3169 }
3170 break;
3171 case MRw:
3172 if (rep_prefix) {
3173 if (rep_prefix == 0xf3) {
3174
3175 /*
3176 * Calculate our offset in dis_op0F
3177 */
3178 if ((uintptr_t)dp - (uintptr_t)dis_op0F
3179 > sizeof (dis_op0F))
3180 goto error;
3181
3182 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) /
3183 sizeof (instable_t);
3184
3185 dp = (instable_t *)&dis_opSIMDrepz[off];
3186 rep_prefix = 0;
3187 } else {
3188 goto error;
3189 }
3190 }
3191 break;
3192 }
3193
3194 /*
3195 * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64.
3196 */
3197 if (cpu_mode == SIZE64)
3198 if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop))
3199 opnd_size = SIZE64;
3200
3201#ifdef DIS_TEXT
3202 /*
3203 * At this point most instructions can format the opcode mnemonic
3204 * including the prefixes.
3205 */
3206 if (lock_prefix)
3207 (void) strlcat(x->d86_mnem, "lock ", OPLEN);
3208
3209 if (rep_prefix == 0xf2)
3210 (void) strlcat(x->d86_mnem, "repnz ", OPLEN);
3211 else if (rep_prefix == 0xf3)
3212 (void) strlcat(x->d86_mnem, "repz ", OPLEN);
3213
3214 if (cpu_mode == SIZE64 && addr_size_prefix)
3215 (void) strlcat(x->d86_mnem, "addr32 ", OPLEN);
3216
3217 if (dp->it_adrmode != CBW &&
3218 dp->it_adrmode != CWD &&
3219 dp->it_adrmode != XMMSFNC) {
3220 if (strcmp(dp->it_name, "INVALID") == 0)
3221 goto error;
3222 (void) strlcat(x->d86_mnem, dp->it_name, OPLEN);
3223 if (dp->it_suffix) {
3224 char *types[] = {"", "w", "l", "q"};
3225 if (opcode_bytes == 2 && opcode4 == 4) {
3226 /* It's a cmovx.yy. Replace the suffix x */
3227 for (i = 5; i < OPLEN; i++) {
3228 if (x->d86_mnem[i] == '.')
3229 break;
3230 }
3231 x->d86_mnem[i - 1] = *types[opnd_size];
3232 } else if ((opnd_size == 2) && (opcode_bytes == 3) &&
3233 ((opcode6 == 1 && opcode7 == 6) ||
3234 (opcode6 == 2 && opcode7 == 2))) {
3235 /*
3236 * To handle PINSRD and PEXTRD
3237 */
3238 (void) strlcat(x->d86_mnem, "d", OPLEN);
3239 } else {
3240 (void) strlcat(x->d86_mnem, types[opnd_size],
3241 OPLEN);
3242 }
3243 }
3244 }
3245#endif
3246
3247 /*
3248 * Process operands based on the addressing modes.
3249 */
3250 x->d86_mode = cpu_mode;
3251 /*
3252 * In vex mode the rex_prefix has no meaning
3253 */
3254 if (!vex_prefix)
3255 x->d86_rex_prefix = rex_prefix;
3256 x->d86_opnd_size = opnd_size;
3257 x->d86_addr_size = addr_size;
3258 vbit = 0; /* initialize for mem/reg -> reg */
3259 switch (dp->it_adrmode) {
3260 /*
3261 * amd64 instruction to sign extend 32 bit reg/mem operands
3262 * into 64 bit register values
3263 */
3264 case MOVSXZ:
3265#ifdef DIS_TEXT
3266 if (rex_prefix == 0)
3267 (void) strncpy(x->d86_mnem, "movzld", OPLEN);
3268#endif
3269 dtrace_get_modrm(x, &mode, &reg, &r_m);
3270 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3271 x->d86_opnd_size = SIZE64;
3272 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3273 x->d86_opnd_size = opnd_size = SIZE32;
3274 wbit = LONG_OPND;
3275 dtrace_get_operand(x, mode, r_m, wbit, 0);
3276 break;
3277
3278 /*
3279 * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF)
3280 * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7)
3281 * wbit lives in 2nd byte, note that operands
3282 * are different sized
3283 */
3284 case MOVZ:
3285 if (rex_prefix & REX_W) {
3286 /* target register size = 64 bit */
3287 x->d86_mnem[5] = 'q';
3288 }
3289 dtrace_get_modrm(x, &mode, &reg, &r_m);
3290 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3291 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3292 x->d86_opnd_size = opnd_size = SIZE16;
3293 wbit = WBIT(opcode5);
3294 dtrace_get_operand(x, mode, r_m, wbit, 0);
3295 break;
3296 case CRC32:
3297 opnd_size = SIZE32;
3298 if (rex_prefix & REX_W)
3299 opnd_size = SIZE64;
3300 x->d86_opnd_size = opnd_size;
3301
3302 dtrace_get_modrm(x, &mode, &reg, &r_m);
3303 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3304 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3305 wbit = WBIT(opcode7);
3306 if (opnd_size_prefix)
3307 x->d86_opnd_size = opnd_size = SIZE16;
3308 dtrace_get_operand(x, mode, r_m, wbit, 0);
3309 break;
3310 case MOVBE:
3311 opnd_size = SIZE32;
3312 if (rex_prefix & REX_W)
3313 opnd_size = SIZE64;
3314 x->d86_opnd_size = opnd_size;
3315
3316 dtrace_get_modrm(x, &mode, &reg, &r_m);
3317 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3318 wbit = WBIT(opcode7);
3319 if (opnd_size_prefix)
3320 x->d86_opnd_size = opnd_size = SIZE16;
3321 if (wbit) {
3322 /* reg -> mem */
3323 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3324 dtrace_get_operand(x, mode, r_m, wbit, 1);
3325 } else {
3326 /* mem -> reg */
3327 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3328 dtrace_get_operand(x, mode, r_m, wbit, 0);
3329 }
3330 break;
3331
3332 /*
3333 * imul instruction, with either 8-bit or longer immediate
3334 * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s)
3335 */
3336 case IMUL:
3337 wbit = LONG_OPND;
3338 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND,
3339 OPSIZE(opnd_size, opcode2 == 0x9), 1);
3340 break;
3341
3342 /* memory or register operand to register, with 'w' bit */
3343 case MRw:
3344 wbit = WBIT(opcode2);
3345 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3346 break;
3347
3348 /* register to memory or register operand, with 'w' bit */
3349 /* arpl happens to fit here also because it is odd */
3350 case RMw:
3351 if (opcode_bytes == 2)
3352 wbit = WBIT(opcode5);
3353 else
3354 wbit = WBIT(opcode2);
3355 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3356 break;
3357
3358 /* xaddb instruction */
3359 case XADDB:
3360 wbit = 0;
3361 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3362 break;
3363
3364 /* MMX register to memory or register operand */
3365 case MMS:
3366 case MMOS:
3367#ifdef DIS_TEXT
3368 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3369#else
3370 wbit = LONG_OPND;
3371#endif
3372 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
3373 break;
3374
3375 /* MMX register to memory */
3376 case MMOMS:
3377 dtrace_get_modrm(x, &mode, &reg, &r_m);
3378 if (mode == REG_ONLY)
3379 goto error;
3380 wbit = MM_OPND;
3381 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1);
3382 break;
3383
3384 /* Double shift. Has immediate operand specifying the shift. */
3385 case DSHIFT:
3386 wbit = LONG_OPND;
3387 dtrace_get_modrm(x, &mode, &reg, &r_m);
3388 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3389 dtrace_get_operand(x, mode, r_m, wbit, 2);
3390 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3391 dtrace_imm_opnd(x, wbit, 1, 0);
3392 break;
3393
3394 /*
3395 * Double shift. With no immediate operand, specifies using %cl.
3396 */
3397 case DSHIFTcl:
3398 wbit = LONG_OPND;
3399 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3400 break;
3401
3402 /* immediate to memory or register operand */
3403 case IMlw:
3404 wbit = WBIT(opcode2);
3405 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3406 dtrace_get_operand(x, mode, r_m, wbit, 1);
3407 /*
3408 * Have long immediate for opcode 0x81, but not 0x80 nor 0x83
3409 */
3410 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0);
3411 break;
3412
3413 /* immediate to memory or register operand with the */
3414 /* 'w' bit present */
3415 case IMw:
3416 wbit = WBIT(opcode2);
3417 dtrace_get_modrm(x, &mode, &reg, &r_m);
3418 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3419 dtrace_get_operand(x, mode, r_m, wbit, 1);
3420 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
3421 break;
3422
3423 /* immediate to register with register in low 3 bits */
3424 /* of op code */
3425 case IR:
3426 /* w-bit here (with regs) is bit 3 */
3427 wbit = opcode2 >>3 & 0x1;
3428 reg = REGNO(opcode2);
3429 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3430 mode = REG_ONLY;
3431 r_m = reg;
3432 dtrace_get_operand(x, mode, r_m, wbit, 1);
3433 dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0);
3434 break;
3435
3436 /* MMX immediate shift of register */
3437 case MMSH:
3438 case MMOSH:
3439 wbit = MM_OPND;
3440 goto mm_shift; /* in next case */
3441
3442 /* SIMD immediate shift of register */
3443 case XMMSH:
3444 wbit = XMM_OPND;
3445mm_shift:
3446 reg = REGNO(opcode7);
3447 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3448 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
3449 dtrace_imm_opnd(x, wbit, 1, 0);
3450 NOMEM;
3451 break;
3452
3453 /* accumulator to memory operand */
3454 case AO:
3455 vbit = 1;
3456 /*FALLTHROUGH*/
3457
3458 /* memory operand to accumulator */
3459 case OA:
3460 wbit = WBIT(opcode2);
3461 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit);
3462 dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit);
3463#ifdef DIS_TEXT
3464 x->d86_opnd[vbit].d86_mode = MODE_OFFSET;
3465#endif
3466 break;
3467
3468
3469 /* segment register to memory or register operand */
3470 case SM:
3471 vbit = 1;
3472 /*FALLTHROUGH*/
3473
3474 /* memory or register operand to segment register */
3475 case MS:
3476 dtrace_get_modrm(x, &mode, &reg, &r_m);
3477 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3478 dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit);
3479 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit);
3480 break;
3481
3482 /*
3483 * rotate or shift instructions, which may shift by 1 or
3484 * consult the cl register, depending on the 'v' bit
3485 */
3486 case Mv:
3487 vbit = VBIT(opcode2);
3488 wbit = WBIT(opcode2);
3489 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3490 dtrace_get_operand(x, mode, r_m, wbit, 1);
3491#ifdef DIS_TEXT
3492 if (vbit) {
3493 (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN);
3494 } else {
3495 x->d86_opnd[0].d86_mode = MODE_SIGNED;
3496 x->d86_opnd[0].d86_value_size = 1;
3497 x->d86_opnd[0].d86_value = 1;
3498 }
3499#endif
3500 break;
3501 /*
3502 * immediate rotate or shift instructions
3503 */
3504 case MvI:
3505 wbit = WBIT(opcode2);
3506normal_imm_mem:
3507 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3508 dtrace_get_operand(x, mode, r_m, wbit, 1);
3509 dtrace_imm_opnd(x, wbit, 1, 0);
3510 break;
3511
3512 /* bit test instructions */
3513 case MIb:
3514 wbit = LONG_OPND;
3515 goto normal_imm_mem;
3516
3517 /* single memory or register operand with 'w' bit present */
3518 case Mw:
3519 wbit = WBIT(opcode2);
3520just_mem:
3521 dtrace_get_modrm(x, &mode, &reg, &r_m);
3522 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3523 dtrace_get_operand(x, mode, r_m, wbit, 0);
3524 break;
3525
3437 case SWAPGS:
3526 case SWAPGS_RDTSCP:
3438 if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) {
3439#ifdef DIS_TEXT
3440 (void) strncpy(x->d86_mnem, "swapgs", OPLEN);
3441#endif
3442 NOMEM;
3443 break;
3527 if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) {
3528#ifdef DIS_TEXT
3529 (void) strncpy(x->d86_mnem, "swapgs", OPLEN);
3530#endif
3531 NOMEM;
3532 break;
3533 } else if (mode == 3 && r_m == 1) {
3534#ifdef DIS_TEXT
3535 (void) strncpy(x->d86_mnem, "rdtscp", OPLEN);
3536#endif
3537 NOMEM;
3538 break;
3444 }
3539 }
3540
3445 /*FALLTHROUGH*/
3446
3447 /* prefetch instruction - memory operand, but no memory acess */
3448 case PREF:
3449 NOMEM;
3450 /*FALLTHROUGH*/
3451
3452 /* single memory or register operand */
3453 case M:
3541 /*FALLTHROUGH*/
3542
3543 /* prefetch instruction - memory operand, but no memory acess */
3544 case PREF:
3545 NOMEM;
3546 /*FALLTHROUGH*/
3547
3548 /* single memory or register operand */
3549 case M:
3550 case MG9:
3454 wbit = LONG_OPND;
3455 goto just_mem;
3456
3457 /* single memory or register byte operand */
3458 case Mb:
3459 wbit = BYTE_OPND;
3460 goto just_mem;
3461
3551 wbit = LONG_OPND;
3552 goto just_mem;
3553
3554 /* single memory or register byte operand */
3555 case Mb:
3556 wbit = BYTE_OPND;
3557 goto just_mem;
3558
3559 case VMx:
3560 if (mode == 3) {
3561#ifdef DIS_TEXT
3562 char *vminstr;
3563
3564 switch (r_m) {
3565 case 1:
3566 vminstr = "vmcall";
3567 break;
3568 case 2:
3569 vminstr = "vmlaunch";
3570 break;
3571 case 3:
3572 vminstr = "vmresume";
3573 break;
3574 case 4:
3575 vminstr = "vmxoff";
3576 break;
3577 default:
3578 goto error;
3579 }
3580
3581 (void) strncpy(x->d86_mnem, vminstr, OPLEN);
3582#else
3583 if (r_m < 1 || r_m > 4)
3584 goto error;
3585#endif
3586
3587 NOMEM;
3588 break;
3589 }
3590 /*FALLTHROUGH*/
3591 case SVM:
3592 if (mode == 3) {
3593#ifdef DIS_TEXT
3594 char *vinstr;
3595
3596 switch (r_m) {
3597 case 0:
3598 vinstr = "vmrun";
3599 break;
3600 case 1:
3601 vinstr = "vmmcall";
3602 break;
3603 case 2:
3604 vinstr = "vmload";
3605 break;
3606 case 3:
3607 vinstr = "vmsave";
3608 break;
3609 case 4:
3610 vinstr = "stgi";
3611 break;
3612 case 5:
3613 vinstr = "clgi";
3614 break;
3615 case 6:
3616 vinstr = "skinit";
3617 break;
3618 case 7:
3619 vinstr = "invlpga";
3620 break;
3621 }
3622
3623 (void) strncpy(x->d86_mnem, vinstr, OPLEN);
3624#endif
3625 NOMEM;
3626 break;
3627 }
3628 /*FALLTHROUGH*/
3462 case MONITOR_MWAIT:
3463 if (mode == 3) {
3464 if (r_m == 0) {
3465#ifdef DIS_TEXT
3466 (void) strncpy(x->d86_mnem, "monitor", OPLEN);
3467#endif
3468 NOMEM;
3469 break;
3470 } else if (r_m == 1) {
3471#ifdef DIS_TEXT
3472 (void) strncpy(x->d86_mnem, "mwait", OPLEN);
3473#endif
3474 NOMEM;
3475 break;
3476 } else {
3477 goto error;
3478 }
3479 }
3480 /*FALLTHROUGH*/
3481 case XGETBV_XSETBV:
3482 if (mode == 3) {
3483 if (r_m == 0) {
3484#ifdef DIS_TEXT
3485 (void) strncpy(x->d86_mnem, "xgetbv", OPLEN);
3486#endif
3487 NOMEM;
3488 break;
3489 } else if (r_m == 1) {
3490#ifdef DIS_TEXT
3491 (void) strncpy(x->d86_mnem, "xsetbv", OPLEN);
3492#endif
3493 NOMEM;
3494 break;
3495 } else {
3496 goto error;
3497 }
3498
3499 }
3500 /*FALLTHROUGH*/
3501 case MO:
3502 /* Similar to M, but only memory (no direct registers) */
3503 wbit = LONG_OPND;
3504 dtrace_get_modrm(x, &mode, &reg, &r_m);
3505 if (mode == 3)
3506 goto error;
3507 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3508 dtrace_get_operand(x, mode, r_m, wbit, 0);
3509 break;
3510
3511 /* move special register to register or reverse if vbit */
3512 case SREG:
3513 switch (opcode5) {
3514
3515 case 2:
3516 vbit = 1;
3517 /*FALLTHROUGH*/
3518 case 0:
3519 wbit = CONTROL_OPND;
3520 break;
3521
3522 case 3:
3523 vbit = 1;
3524 /*FALLTHROUGH*/
3525 case 1:
3526 wbit = DEBUG_OPND;
3527 break;
3528
3529 case 6:
3530 vbit = 1;
3531 /*FALLTHROUGH*/
3532 case 4:
3533 wbit = TEST_OPND;
3534 break;
3535
3536 }
3537 dtrace_get_modrm(x, &mode, &reg, &r_m);
3538 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3539 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit);
3540 dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit);
3541 NOMEM;
3542 break;
3543
3544 /*
3545 * single register operand with register in the low 3
3546 * bits of op code
3547 */
3548 case R:
3549 if (opcode_bytes == 2)
3550 reg = REGNO(opcode5);
3551 else
3552 reg = REGNO(opcode2);
3553 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3554 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3555 NOMEM;
3556 break;
3557
3558 /*
3559 * register to accumulator with register in the low 3
3560 * bits of op code, xchg instructions
3561 */
3562 case RA:
3563 NOMEM;
3564 reg = REGNO(opcode2);
3565 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3566 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3567 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1);
3568 break;
3569
3570 /*
3571 * single segment register operand, with register in
3572 * bits 3-4 of op code byte
3573 */
3574 case SEG:
3575 NOMEM;
3576 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3;
3577 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
3578 break;
3579
3580 /*
3581 * single segment register operand, with register in
3582 * bits 3-5 of op code
3583 */
3584 case LSEG:
3585 NOMEM;
3586 /* long seg reg from opcode */
3587 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7;
3588 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
3589 break;
3590
3591 /* memory or register operand to register */
3592 case MR:
3593 if (vex_prefetch)
3594 x->d86_got_modrm = 1;
3595 wbit = LONG_OPND;
3596 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3597 break;
3598
3599 case RM:
3629 case MONITOR_MWAIT:
3630 if (mode == 3) {
3631 if (r_m == 0) {
3632#ifdef DIS_TEXT
3633 (void) strncpy(x->d86_mnem, "monitor", OPLEN);
3634#endif
3635 NOMEM;
3636 break;
3637 } else if (r_m == 1) {
3638#ifdef DIS_TEXT
3639 (void) strncpy(x->d86_mnem, "mwait", OPLEN);
3640#endif
3641 NOMEM;
3642 break;
3643 } else {
3644 goto error;
3645 }
3646 }
3647 /*FALLTHROUGH*/
3648 case XGETBV_XSETBV:
3649 if (mode == 3) {
3650 if (r_m == 0) {
3651#ifdef DIS_TEXT
3652 (void) strncpy(x->d86_mnem, "xgetbv", OPLEN);
3653#endif
3654 NOMEM;
3655 break;
3656 } else if (r_m == 1) {
3657#ifdef DIS_TEXT
3658 (void) strncpy(x->d86_mnem, "xsetbv", OPLEN);
3659#endif
3660 NOMEM;
3661 break;
3662 } else {
3663 goto error;
3664 }
3665
3666 }
3667 /*FALLTHROUGH*/
3668 case MO:
3669 /* Similar to M, but only memory (no direct registers) */
3670 wbit = LONG_OPND;
3671 dtrace_get_modrm(x, &mode, &reg, &r_m);
3672 if (mode == 3)
3673 goto error;
3674 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3675 dtrace_get_operand(x, mode, r_m, wbit, 0);
3676 break;
3677
3678 /* move special register to register or reverse if vbit */
3679 case SREG:
3680 switch (opcode5) {
3681
3682 case 2:
3683 vbit = 1;
3684 /*FALLTHROUGH*/
3685 case 0:
3686 wbit = CONTROL_OPND;
3687 break;
3688
3689 case 3:
3690 vbit = 1;
3691 /*FALLTHROUGH*/
3692 case 1:
3693 wbit = DEBUG_OPND;
3694 break;
3695
3696 case 6:
3697 vbit = 1;
3698 /*FALLTHROUGH*/
3699 case 4:
3700 wbit = TEST_OPND;
3701 break;
3702
3703 }
3704 dtrace_get_modrm(x, &mode, &reg, &r_m);
3705 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3706 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit);
3707 dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit);
3708 NOMEM;
3709 break;
3710
3711 /*
3712 * single register operand with register in the low 3
3713 * bits of op code
3714 */
3715 case R:
3716 if (opcode_bytes == 2)
3717 reg = REGNO(opcode5);
3718 else
3719 reg = REGNO(opcode2);
3720 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3721 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3722 NOMEM;
3723 break;
3724
3725 /*
3726 * register to accumulator with register in the low 3
3727 * bits of op code, xchg instructions
3728 */
3729 case RA:
3730 NOMEM;
3731 reg = REGNO(opcode2);
3732 dtrace_rex_adjust(rex_prefix, mode, &reg, NULL);
3733 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0);
3734 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1);
3735 break;
3736
3737 /*
3738 * single segment register operand, with register in
3739 * bits 3-4 of op code byte
3740 */
3741 case SEG:
3742 NOMEM;
3743 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3;
3744 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
3745 break;
3746
3747 /*
3748 * single segment register operand, with register in
3749 * bits 3-5 of op code
3750 */
3751 case LSEG:
3752 NOMEM;
3753 /* long seg reg from opcode */
3754 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7;
3755 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0);
3756 break;
3757
3758 /* memory or register operand to register */
3759 case MR:
3760 if (vex_prefetch)
3761 x->d86_got_modrm = 1;
3762 wbit = LONG_OPND;
3763 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3764 break;
3765
3766 case RM:
3767 case RM_66r:
3600 wbit = LONG_OPND;
3601 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3602 break;
3603
3604 /* MMX/SIMD-Int memory or mm reg to mm reg */
3605 case MM:
3606 case MMO:
3607#ifdef DIS_TEXT
3608 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3609#else
3610 wbit = LONG_OPND;
3611#endif
3612 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
3613 break;
3614
3615 case MMOIMPL:
3616#ifdef DIS_TEXT
3617 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3618#else
3619 wbit = LONG_OPND;
3620#endif
3621 dtrace_get_modrm(x, &mode, &reg, &r_m);
3622 if (mode != REG_ONLY)
3623 goto error;
3624
3625 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3626 dtrace_get_operand(x, mode, r_m, wbit, 0);
3627 dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1);
3628 mode = 0; /* change for memory access size... */
3629 break;
3630
3631 /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */
3632 case MMO3P:
3633 wbit = MM_OPND;
3634 goto xmm3p;
3635 case XMM3P:
3636 wbit = XMM_OPND;
3637xmm3p:
3638 dtrace_get_modrm(x, &mode, &reg, &r_m);
3639 if (mode != REG_ONLY)
3640 goto error;
3641
3642 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1,
3643 1);
3644 NOMEM;
3645 break;
3646
3647 case XMM3PM_66r:
3648 THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND,
3649 1, 0);
3650 break;
3651
3652 /* MMX/SIMD-Int predicated r32/mem to mm reg */
3653 case MMOPRM:
3654 wbit = LONG_OPND;
3655 w2 = MM_OPND;
3656 goto xmmprm;
3657 case XMMPRM:
3658 case XMMPRM_66r:
3659 wbit = LONG_OPND;
3660 w2 = XMM_OPND;
3661xmmprm:
3662 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1);
3663 break;
3664
3665 /* MMX/SIMD-Int predicated mm/mem to mm reg */
3666 case MMOPM:
3667 case MMOPM_66o:
3668 wbit = w2 = MM_OPND;
3669 goto xmmprm;
3670
3671 /* MMX/SIMD-Int mm reg to r32 */
3672 case MMOM3:
3673 NOMEM;
3674 dtrace_get_modrm(x, &mode, &reg, &r_m);
3675 if (mode != REG_ONLY)
3676 goto error;
3677 wbit = MM_OPND;
3678 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
3679 break;
3680
3681 /* SIMD memory or xmm reg operand to xmm reg */
3682 case XMM:
3683 case XMM_66o:
3684 case XMM_66r:
3685 case XMMO:
3686 case XMMXIMPL:
3687 wbit = XMM_OPND;
3688 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3689
3690 if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY)
3691 goto error;
3692
3693#ifdef DIS_TEXT
3694 /*
3695 * movlps and movhlps share opcodes. They differ in the
3696 * addressing modes allowed for their operands.
3697 * movhps and movlhps behave similarly.
3698 */
3699 if (mode == REG_ONLY) {
3700 if (strcmp(dp->it_name, "movlps") == 0)
3701 (void) strncpy(x->d86_mnem, "movhlps", OPLEN);
3702 else if (strcmp(dp->it_name, "movhps") == 0)
3703 (void) strncpy(x->d86_mnem, "movlhps", OPLEN);
3704 }
3705#endif
3706 if (dp->it_adrmode == XMMXIMPL)
3707 mode = 0; /* change for memory access size... */
3708 break;
3709
3710 /* SIMD xmm reg to memory or xmm reg */
3711 case XMMS:
3712 case XMMOS:
3713 case XMMMS:
3714 case XMMOMS:
3715 dtrace_get_modrm(x, &mode, &reg, &r_m);
3716#ifdef DIS_TEXT
3717 if ((strcmp(dp->it_name, "movlps") == 0 ||
3718 strcmp(dp->it_name, "movhps") == 0 ||
3719 strcmp(dp->it_name, "movntps") == 0) &&
3720 mode == REG_ONLY)
3721 goto error;
3722#endif
3723 wbit = XMM_OPND;
3724 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
3725 break;
3726
3727 /* SIMD memory to xmm reg */
3728 case XMMM:
3729 case XMMM_66r:
3730 case XMMOM:
3731 wbit = XMM_OPND;
3732 dtrace_get_modrm(x, &mode, &reg, &r_m);
3733#ifdef DIS_TEXT
3734 if (mode == REG_ONLY) {
3735 if (strcmp(dp->it_name, "movhps") == 0)
3736 (void) strncpy(x->d86_mnem, "movlhps", OPLEN);
3737 else
3738 goto error;
3739 }
3740#endif
3741 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3742 break;
3743
3744 /* SIMD memory or r32 to xmm reg */
3745 case XMM3MX:
3746 wbit = LONG_OPND;
3747 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3748 break;
3749
3750 case XMM3MXS:
3751 wbit = LONG_OPND;
3752 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
3753 break;
3754
3755 /* SIMD memory or mm reg to xmm reg */
3756 case XMMOMX:
3757 /* SIMD mm to xmm */
3758 case XMMMX:
3759 wbit = MM_OPND;
3760 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3761 break;
3762
3763 /* SIMD memory or xmm reg to mm reg */
3764 case XMMXMM:
3765 case XMMOXMM:
3766 case XMMXM:
3767 wbit = XMM_OPND;
3768 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
3769 break;
3770
3771
3772 /* SIMD memory or xmm reg to r32 */
3773 case XMMXM3:
3774 wbit = XMM_OPND;
3775 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
3776 break;
3777
3778 /* SIMD xmm to r32 */
3779 case XMMX3:
3780 case XMMOX3:
3781 dtrace_get_modrm(x, &mode, &reg, &r_m);
3782 if (mode != REG_ONLY)
3783 goto error;
3784 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3785 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
3786 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3787 NOMEM;
3788 break;
3789
3790 /* SIMD predicated memory or xmm reg with/to xmm reg */
3791 case XMMP:
3792 case XMMP_66r:
3793 case XMMP_66o:
3794 case XMMOPM:
3795 wbit = XMM_OPND;
3796 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1,
3797 1);
3798
3799#ifdef DIS_TEXT
3800 /*
3801 * cmpps and cmpss vary their instruction name based
3802 * on the value of imm8. Other XMMP instructions,
3803 * such as shufps, require explicit specification of
3804 * the predicate.
3805 */
3806 if (dp->it_name[0] == 'c' &&
3807 dp->it_name[1] == 'm' &&
3808 dp->it_name[2] == 'p' &&
3809 strlen(dp->it_name) == 5) {
3810 uchar_t pred = x->d86_opnd[0].d86_value & 0xff;
3811
3812 if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *)))
3813 goto error;
3814
3815 (void) strncpy(x->d86_mnem, "cmp", OPLEN);
3816 (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred],
3817 OPLEN);
3818 (void) strlcat(x->d86_mnem,
3819 dp->it_name + strlen(dp->it_name) - 2,
3820 OPLEN);
3821 x->d86_opnd[0] = x->d86_opnd[1];
3822 x->d86_opnd[1] = x->d86_opnd[2];
3823 x->d86_numopnds = 2;
3824 }
3825#endif
3826 break;
3827
3828 case XMMX2I:
3829 FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND,
3830 1);
3831 NOMEM;
3832 break;
3833
3834 case XMM2I:
3835 ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1);
3836 NOMEM;
3837 break;
3838
3839 /* immediate operand to accumulator */
3840 case IA:
3841 wbit = WBIT(opcode2);
3842 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
3843 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
3844 NOMEM;
3845 break;
3846
3847 /* memory or register operand to accumulator */
3848 case MA:
3849 wbit = WBIT(opcode2);
3850 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3851 dtrace_get_operand(x, mode, r_m, wbit, 0);
3852 break;
3853
3854 /* si register to di register used to reference memory */
3855 case SD:
3856#ifdef DIS_TEXT
3857 dtrace_check_override(x, 0);
3858 x->d86_numopnds = 2;
3859 if (addr_size == SIZE64) {
3860 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
3861 OPLEN);
3862 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
3863 OPLEN);
3864 } else if (addr_size == SIZE32) {
3865 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
3866 OPLEN);
3867 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
3868 OPLEN);
3869 } else {
3870 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
3871 OPLEN);
3872 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
3873 OPLEN);
3874 }
3875#endif
3876 wbit = LONG_OPND;
3877 break;
3878
3879 /* accumulator to di register */
3880 case AD:
3881 wbit = WBIT(opcode2);
3882#ifdef DIS_TEXT
3883 dtrace_check_override(x, 1);
3884 x->d86_numopnds = 2;
3885 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0);
3886 if (addr_size == SIZE64)
3887 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
3888 OPLEN);
3889 else if (addr_size == SIZE32)
3890 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
3891 OPLEN);
3892 else
3893 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
3894 OPLEN);
3895#endif
3896 break;
3897
3898 /* si register to accumulator */
3899 case SA:
3900 wbit = WBIT(opcode2);
3901#ifdef DIS_TEXT
3902 dtrace_check_override(x, 0);
3903 x->d86_numopnds = 2;
3904 if (addr_size == SIZE64)
3905 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
3906 OPLEN);
3907 else if (addr_size == SIZE32)
3908 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
3909 OPLEN);
3910 else
3911 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
3912 OPLEN);
3913 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
3914#endif
3915 break;
3916
3917 /*
3918 * single operand, a 16/32 bit displacement
3919 */
3920 case D:
3921 wbit = LONG_OPND;
3922 dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
3923 NOMEM;
3924 break;
3925
3926 /* jmp/call indirect to memory or register operand */
3927 case INM:
3928#ifdef DIS_TEXT
3929 (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN);
3930#endif
3931 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
3932 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
3933 wbit = LONG_OPND;
3934 break;
3935
3936 /*
3937 * for long jumps and long calls -- a new code segment
3938 * register and an offset in IP -- stored in object
3939 * code in reverse order. Note - not valid in amd64
3940 */
3941 case SO:
3942 dtrace_check_override(x, 1);
3943 wbit = LONG_OPND;
3944 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1);
3945#ifdef DIS_TEXT
3946 x->d86_opnd[1].d86_mode = MODE_SIGNED;
3947#endif
3948 /* will now get segment operand */
3949 dtrace_imm_opnd(x, wbit, 2, 0);
3950 break;
3951
3952 /*
3953 * jmp/call. single operand, 8 bit displacement.
3954 * added to current EIP in 'compofff'
3955 */
3956 case BD:
3957 dtrace_disp_opnd(x, BYTE_OPND, 1, 0);
3958 NOMEM;
3959 break;
3960
3961 /* single 32/16 bit immediate operand */
3962 case I:
3963 wbit = LONG_OPND;
3964 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
3965 break;
3966
3967 /* single 8 bit immediate operand */
3968 case Ib:
3969 wbit = LONG_OPND;
3970 dtrace_imm_opnd(x, wbit, 1, 0);
3971 break;
3972
3973 case ENTER:
3974 wbit = LONG_OPND;
3975 dtrace_imm_opnd(x, wbit, 2, 0);
3976 dtrace_imm_opnd(x, wbit, 1, 1);
3977 switch (opnd_size) {
3978 case SIZE64:
3979 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8;
3980 break;
3981 case SIZE32:
3982 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4;
3983 break;
3984 case SIZE16:
3985 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2;
3986 break;
3987 }
3988
3989 break;
3990
3991 /* 16-bit immediate operand */
3992 case RET:
3993 wbit = LONG_OPND;
3994 dtrace_imm_opnd(x, wbit, 2, 0);
3995 break;
3996
3997 /* single 8 bit port operand */
3998 case P:
3999 dtrace_check_override(x, 0);
4000 dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
4001 NOMEM;
4002 break;
4003
4004 /* single operand, dx register (variable port instruction) */
4005 case V:
4006 x->d86_numopnds = 1;
4007 dtrace_check_override(x, 0);
4008#ifdef DIS_TEXT
4009 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN);
4010#endif
4011 NOMEM;
4012 break;
4013
4014 /*
4015 * The int instruction, which has two forms:
4016 * int 3 (breakpoint) or
4017 * int n, where n is indicated in the subsequent
4018 * byte (format Ib). The int 3 instruction (opcode 0xCC),
4019 * where, although the 3 looks like an operand,
4020 * it is implied by the opcode. It must be converted
4021 * to the correct base and output.
4022 */
4023 case INT3:
4024#ifdef DIS_TEXT
4025 x->d86_numopnds = 1;
4026 x->d86_opnd[0].d86_mode = MODE_SIGNED;
4027 x->d86_opnd[0].d86_value_size = 1;
4028 x->d86_opnd[0].d86_value = 3;
4029#endif
4030 NOMEM;
4031 break;
4032
4033 /* single 8 bit immediate operand */
4034 case INTx:
4035 dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
4036 NOMEM;
4037 break;
4038
4039 /* an unused byte must be discarded */
4040 case U:
4041 if (x->d86_get_byte(x->d86_data) < 0)
4042 goto error;
4043 x->d86_len++;
4044 NOMEM;
4045 break;
4046
4047 case CBW:
4048#ifdef DIS_TEXT
4049 if (opnd_size == SIZE16)
4050 (void) strlcat(x->d86_mnem, "cbtw", OPLEN);
4051 else if (opnd_size == SIZE32)
4052 (void) strlcat(x->d86_mnem, "cwtl", OPLEN);
4053 else
4054 (void) strlcat(x->d86_mnem, "cltq", OPLEN);
4055#endif
4056 wbit = LONG_OPND;
4057 NOMEM;
4058 break;
4059
4060 case CWD:
4061#ifdef DIS_TEXT
4062 if (opnd_size == SIZE16)
4063 (void) strlcat(x->d86_mnem, "cwtd", OPLEN);
4064 else if (opnd_size == SIZE32)
4065 (void) strlcat(x->d86_mnem, "cltd", OPLEN);
4066 else
4067 (void) strlcat(x->d86_mnem, "cqtd", OPLEN);
4068#endif
4069 wbit = LONG_OPND;
4070 NOMEM;
4071 break;
4072
4073 case XMMSFNC:
4074 /*
4075 * sfence is sfence if mode is REG_ONLY. If mode isn't
4076 * REG_ONLY, mnemonic should be 'clflush'.
4077 */
4078 dtrace_get_modrm(x, &mode, &reg, &r_m);
4079
4080 /* sfence doesn't take operands */
4081#ifdef DIS_TEXT
4082 if (mode == REG_ONLY) {
4083 (void) strlcat(x->d86_mnem, "sfence", OPLEN);
4084 } else {
4085 (void) strlcat(x->d86_mnem, "clflush", OPLEN);
4086 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4087 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
4088 NOMEM;
4089 }
4090#else
4091 if (mode != REG_ONLY) {
4092 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4093 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4094 NOMEM;
4095 }
4096#endif
4097 break;
4098
4099 /*
4100 * no disassembly, the mnemonic was all there was so go on
4101 */
4102 case NORM:
4103 if (dp->it_invalid32 && cpu_mode != SIZE64)
4104 goto error;
4105 NOMEM;
4106 /*FALLTHROUGH*/
4107 case IMPLMEM:
4108 break;
4109
4110 case XMMFENCE:
4111 /*
4112 * XRSTOR and LFENCE share the same opcode but differ in mode
4113 */
4114 dtrace_get_modrm(x, &mode, &reg, &r_m);
4115
4116 if (mode == REG_ONLY) {
4117 /*
4118 * Only the following exact byte sequences are allowed:
4119 *
4120 * 0f ae e8 lfence
4121 * 0f ae f0 mfence
4122 */
4123 if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 &&
4124 (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0)
4125 goto error;
4126 } else {
4127#ifdef DIS_TEXT
4128 (void) strncpy(x->d86_mnem, "xrstor", OPLEN);
4129#endif
4130 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4131 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
4132 }
4133 break;
4134
4135 /* float reg */
4136 case F:
4137#ifdef DIS_TEXT
4138 x->d86_numopnds = 1;
4139 (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN);
4140 x->d86_opnd[0].d86_opnd[4] = r_m + '0';
4141#endif
4142 NOMEM;
4143 break;
4144
4145 /* float reg to float reg, with ret bit present */
4146 case FF:
4147 vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */
4148 /*FALLTHROUGH*/
4149 case FFC: /* case for vbit always = 0 */
4150#ifdef DIS_TEXT
4151 x->d86_numopnds = 2;
4152 (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN);
4153 (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN);
4154 x->d86_opnd[vbit].d86_opnd[4] = r_m + '0';
4155#endif
4156 NOMEM;
4157 break;
4158
4159 /* AVX instructions */
4160 case VEX_MO:
4161 /* op(ModR/M.r/m) */
4162 x->d86_numopnds = 1;
4163 dtrace_get_modrm(x, &mode, &reg, &r_m);
4164#ifdef DIS_TEXT
4165 if ((dp == &dis_opAVX0F[0xA][0xE]) && (reg == 3))
4166 (void) strncpy(x->d86_mnem, "vstmxcsr", OPLEN);
4167#endif
4168 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4169 dtrace_get_operand(x, mode, r_m, wbit, 0);
4170 break;
4171 case VEX_RMrX:
4172 /* ModR/M.reg := op(VEX.vvvv, ModR/M.r/m) */
4173 x->d86_numopnds = 3;
4174 dtrace_get_modrm(x, &mode, &reg, &r_m);
4175 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4176
4177 if (mode != REG_ONLY) {
4178 if ((dp == &dis_opAVXF20F[0x10]) ||
4179 (dp == &dis_opAVXF30F[0x10])) {
4180 /* vmovsd <m64>, <xmm> */
4181 /* or vmovss <m64>, <xmm> */
4182 x->d86_numopnds = 2;
4183 goto L_VEX_MX;
4184 }
4185 }
4186
4187 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4188 /*
4189 * VEX prefix uses the 1's complement form to encode the
4190 * XMM/YMM regs
4191 */
4192 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4193
4194 if ((dp == &dis_opAVXF20F[0x2A]) ||
4195 (dp == &dis_opAVXF30F[0x2A])) {
4196 /*
4197 * vcvtsi2si </r,m>, <xmm>, <xmm> or vcvtsi2ss </r,m>,
4198 * <xmm>, <xmm>
4199 */
4200 wbit = LONG_OPND;
4201 }
4202#ifdef DIS_TEXT
4203 else if ((mode == REG_ONLY) &&
4204 (dp == &dis_opAVX0F[0x1][0x6])) { /* vmovlhps */
4205 (void) strncpy(x->d86_mnem, "vmovlhps", OPLEN);
4206 } else if ((mode == REG_ONLY) &&
4207 (dp == &dis_opAVX0F[0x1][0x2])) { /* vmovhlps */
4208 (void) strncpy(x->d86_mnem, "vmovhlps", OPLEN);
4209 }
4210#endif
4211 dtrace_get_operand(x, mode, r_m, wbit, 0);
4212
4213 break;
4214
4215 case VEX_RRX:
4216 /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */
4217 x->d86_numopnds = 3;
4218
4219 dtrace_get_modrm(x, &mode, &reg, &r_m);
4220 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4221
4222 if (mode != REG_ONLY) {
4223 if ((dp == &dis_opAVXF20F[0x11]) ||
4224 (dp == &dis_opAVXF30F[0x11])) {
4225 /* vmovsd <xmm>, <m64> */
4226 /* or vmovss <xmm>, <m64> */
4227 x->d86_numopnds = 2;
4228 goto L_VEX_RM;
4229 }
4230 }
4231
4232 dtrace_get_operand(x, mode, r_m, wbit, 2);
4233 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4234 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4235 break;
4236
4237 case VEX_RMRX:
4238 /* ModR/M.reg := op(VEX.vvvv, ModR/M.r_m, imm8[7:4]) */
4239 x->d86_numopnds = 4;
4240
4241 dtrace_get_modrm(x, &mode, &reg, &r_m);
4242 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4243 dtrace_get_operand(x, REG_ONLY, reg, wbit, 3);
4244 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2);
4245 if (dp == &dis_opAVX660F3A[0x18]) {
4246 /* vinsertf128 <imm8>, <xmm>, <ymm>, <ymm> */
4247 dtrace_get_operand(x, mode, r_m, XMM_OPND, 1);
4248 } else if ((dp == &dis_opAVX660F3A[0x20]) ||
4249 (dp == & dis_opAVX660F[0xC4])) {
4250 /* vpinsrb <imm8>, <reg/mm>, <xmm>, <xmm> */
4251 /* or vpinsrw <imm8>, <reg/mm>, <xmm>, <xmm> */
4252 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4253 } else if (dp == &dis_opAVX660F3A[0x22]) {
4254 /* vpinsrd/q <imm8>, <reg/mm>, <xmm>, <xmm> */
4255#ifdef DIS_TEXT
4256 if (vex_W)
4257 x->d86_mnem[6] = 'q';
4258#endif
4259 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4260 } else {
4261 dtrace_get_operand(x, mode, r_m, wbit, 1);
4262 }
4263
4264 /* one byte immediate number */
4265 dtrace_imm_opnd(x, wbit, 1, 0);
4266
4267 /* vblendvpd, vblendvps, vblendvb use the imm encode the regs */
4268 if ((dp == &dis_opAVX660F3A[0x4A]) ||
4269 (dp == &dis_opAVX660F3A[0x4B]) ||
4270 (dp == &dis_opAVX660F3A[0x4C])) {
4271#ifdef DIS_TEXT
4272 int regnum = (x->d86_opnd[0].d86_value & 0xF0) >> 4;
4273#endif
4274 x->d86_opnd[0].d86_mode = MODE_NONE;
4275#ifdef DIS_TEXT
4276 if (vex_L)
4277 (void) strncpy(x->d86_opnd[0].d86_opnd,
4278 dis_YMMREG[regnum], OPLEN);
4279 else
4280 (void) strncpy(x->d86_opnd[0].d86_opnd,
4281 dis_XMMREG[regnum], OPLEN);
4282#endif
4283 }
4284 break;
4285
4286 case VEX_MX:
4287 /* ModR/M.reg := op(ModR/M.rm) */
4288 x->d86_numopnds = 2;
4289
4290 dtrace_get_modrm(x, &mode, &reg, &r_m);
4291 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4292L_VEX_MX:
4293
4294 if ((dp == &dis_opAVXF20F[0xE6]) ||
4295 (dp == &dis_opAVX660F[0x5A]) ||
4296 (dp == &dis_opAVX660F[0xE6])) {
4297 /* vcvtpd2dq <ymm>, <xmm> */
4298 /* or vcvtpd2ps <ymm>, <xmm> */
4299 /* or vcvttpd2dq <ymm>, <xmm> */
4300 dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1);
4301 dtrace_get_operand(x, mode, r_m, wbit, 0);
4302 } else if ((dp == &dis_opAVXF30F[0xE6]) ||
3768 wbit = LONG_OPND;
3769 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
3770 break;
3771
3772 /* MMX/SIMD-Int memory or mm reg to mm reg */
3773 case MM:
3774 case MMO:
3775#ifdef DIS_TEXT
3776 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3777#else
3778 wbit = LONG_OPND;
3779#endif
3780 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
3781 break;
3782
3783 case MMOIMPL:
3784#ifdef DIS_TEXT
3785 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND;
3786#else
3787 wbit = LONG_OPND;
3788#endif
3789 dtrace_get_modrm(x, &mode, &reg, &r_m);
3790 if (mode != REG_ONLY)
3791 goto error;
3792
3793 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3794 dtrace_get_operand(x, mode, r_m, wbit, 0);
3795 dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1);
3796 mode = 0; /* change for memory access size... */
3797 break;
3798
3799 /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */
3800 case MMO3P:
3801 wbit = MM_OPND;
3802 goto xmm3p;
3803 case XMM3P:
3804 wbit = XMM_OPND;
3805xmm3p:
3806 dtrace_get_modrm(x, &mode, &reg, &r_m);
3807 if (mode != REG_ONLY)
3808 goto error;
3809
3810 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1,
3811 1);
3812 NOMEM;
3813 break;
3814
3815 case XMM3PM_66r:
3816 THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND,
3817 1, 0);
3818 break;
3819
3820 /* MMX/SIMD-Int predicated r32/mem to mm reg */
3821 case MMOPRM:
3822 wbit = LONG_OPND;
3823 w2 = MM_OPND;
3824 goto xmmprm;
3825 case XMMPRM:
3826 case XMMPRM_66r:
3827 wbit = LONG_OPND;
3828 w2 = XMM_OPND;
3829xmmprm:
3830 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1);
3831 break;
3832
3833 /* MMX/SIMD-Int predicated mm/mem to mm reg */
3834 case MMOPM:
3835 case MMOPM_66o:
3836 wbit = w2 = MM_OPND;
3837 goto xmmprm;
3838
3839 /* MMX/SIMD-Int mm reg to r32 */
3840 case MMOM3:
3841 NOMEM;
3842 dtrace_get_modrm(x, &mode, &reg, &r_m);
3843 if (mode != REG_ONLY)
3844 goto error;
3845 wbit = MM_OPND;
3846 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
3847 break;
3848
3849 /* SIMD memory or xmm reg operand to xmm reg */
3850 case XMM:
3851 case XMM_66o:
3852 case XMM_66r:
3853 case XMMO:
3854 case XMMXIMPL:
3855 wbit = XMM_OPND;
3856 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
3857
3858 if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY)
3859 goto error;
3860
3861#ifdef DIS_TEXT
3862 /*
3863 * movlps and movhlps share opcodes. They differ in the
3864 * addressing modes allowed for their operands.
3865 * movhps and movlhps behave similarly.
3866 */
3867 if (mode == REG_ONLY) {
3868 if (strcmp(dp->it_name, "movlps") == 0)
3869 (void) strncpy(x->d86_mnem, "movhlps", OPLEN);
3870 else if (strcmp(dp->it_name, "movhps") == 0)
3871 (void) strncpy(x->d86_mnem, "movlhps", OPLEN);
3872 }
3873#endif
3874 if (dp->it_adrmode == XMMXIMPL)
3875 mode = 0; /* change for memory access size... */
3876 break;
3877
3878 /* SIMD xmm reg to memory or xmm reg */
3879 case XMMS:
3880 case XMMOS:
3881 case XMMMS:
3882 case XMMOMS:
3883 dtrace_get_modrm(x, &mode, &reg, &r_m);
3884#ifdef DIS_TEXT
3885 if ((strcmp(dp->it_name, "movlps") == 0 ||
3886 strcmp(dp->it_name, "movhps") == 0 ||
3887 strcmp(dp->it_name, "movntps") == 0) &&
3888 mode == REG_ONLY)
3889 goto error;
3890#endif
3891 wbit = XMM_OPND;
3892 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
3893 break;
3894
3895 /* SIMD memory to xmm reg */
3896 case XMMM:
3897 case XMMM_66r:
3898 case XMMOM:
3899 wbit = XMM_OPND;
3900 dtrace_get_modrm(x, &mode, &reg, &r_m);
3901#ifdef DIS_TEXT
3902 if (mode == REG_ONLY) {
3903 if (strcmp(dp->it_name, "movhps") == 0)
3904 (void) strncpy(x->d86_mnem, "movlhps", OPLEN);
3905 else
3906 goto error;
3907 }
3908#endif
3909 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3910 break;
3911
3912 /* SIMD memory or r32 to xmm reg */
3913 case XMM3MX:
3914 wbit = LONG_OPND;
3915 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3916 break;
3917
3918 case XMM3MXS:
3919 wbit = LONG_OPND;
3920 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1);
3921 break;
3922
3923 /* SIMD memory or mm reg to xmm reg */
3924 case XMMOMX:
3925 /* SIMD mm to xmm */
3926 case XMMMX:
3927 wbit = MM_OPND;
3928 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0);
3929 break;
3930
3931 /* SIMD memory or xmm reg to mm reg */
3932 case XMMXMM:
3933 case XMMOXMM:
3934 case XMMXM:
3935 wbit = XMM_OPND;
3936 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0);
3937 break;
3938
3939
3940 /* SIMD memory or xmm reg to r32 */
3941 case XMMXM3:
3942 wbit = XMM_OPND;
3943 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0);
3944 break;
3945
3946 /* SIMD xmm to r32 */
3947 case XMMX3:
3948 case XMMOX3:
3949 dtrace_get_modrm(x, &mode, &reg, &r_m);
3950 if (mode != REG_ONLY)
3951 goto error;
3952 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
3953 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
3954 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1);
3955 NOMEM;
3956 break;
3957
3958 /* SIMD predicated memory or xmm reg with/to xmm reg */
3959 case XMMP:
3960 case XMMP_66r:
3961 case XMMP_66o:
3962 case XMMOPM:
3963 wbit = XMM_OPND;
3964 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1,
3965 1);
3966
3967#ifdef DIS_TEXT
3968 /*
3969 * cmpps and cmpss vary their instruction name based
3970 * on the value of imm8. Other XMMP instructions,
3971 * such as shufps, require explicit specification of
3972 * the predicate.
3973 */
3974 if (dp->it_name[0] == 'c' &&
3975 dp->it_name[1] == 'm' &&
3976 dp->it_name[2] == 'p' &&
3977 strlen(dp->it_name) == 5) {
3978 uchar_t pred = x->d86_opnd[0].d86_value & 0xff;
3979
3980 if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *)))
3981 goto error;
3982
3983 (void) strncpy(x->d86_mnem, "cmp", OPLEN);
3984 (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred],
3985 OPLEN);
3986 (void) strlcat(x->d86_mnem,
3987 dp->it_name + strlen(dp->it_name) - 2,
3988 OPLEN);
3989 x->d86_opnd[0] = x->d86_opnd[1];
3990 x->d86_opnd[1] = x->d86_opnd[2];
3991 x->d86_numopnds = 2;
3992 }
3993#endif
3994 break;
3995
3996 case XMMX2I:
3997 FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND,
3998 1);
3999 NOMEM;
4000 break;
4001
4002 case XMM2I:
4003 ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1);
4004 NOMEM;
4005 break;
4006
4007 /* immediate operand to accumulator */
4008 case IA:
4009 wbit = WBIT(opcode2);
4010 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
4011 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0);
4012 NOMEM;
4013 break;
4014
4015 /* memory or register operand to accumulator */
4016 case MA:
4017 wbit = WBIT(opcode2);
4018 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
4019 dtrace_get_operand(x, mode, r_m, wbit, 0);
4020 break;
4021
4022 /* si register to di register used to reference memory */
4023 case SD:
4024#ifdef DIS_TEXT
4025 dtrace_check_override(x, 0);
4026 x->d86_numopnds = 2;
4027 if (addr_size == SIZE64) {
4028 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
4029 OPLEN);
4030 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
4031 OPLEN);
4032 } else if (addr_size == SIZE32) {
4033 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
4034 OPLEN);
4035 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
4036 OPLEN);
4037 } else {
4038 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
4039 OPLEN);
4040 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
4041 OPLEN);
4042 }
4043#endif
4044 wbit = LONG_OPND;
4045 break;
4046
4047 /* accumulator to di register */
4048 case AD:
4049 wbit = WBIT(opcode2);
4050#ifdef DIS_TEXT
4051 dtrace_check_override(x, 1);
4052 x->d86_numopnds = 2;
4053 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0);
4054 if (addr_size == SIZE64)
4055 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)",
4056 OPLEN);
4057 else if (addr_size == SIZE32)
4058 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)",
4059 OPLEN);
4060 else
4061 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)",
4062 OPLEN);
4063#endif
4064 break;
4065
4066 /* si register to accumulator */
4067 case SA:
4068 wbit = WBIT(opcode2);
4069#ifdef DIS_TEXT
4070 dtrace_check_override(x, 0);
4071 x->d86_numopnds = 2;
4072 if (addr_size == SIZE64)
4073 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)",
4074 OPLEN);
4075 else if (addr_size == SIZE32)
4076 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)",
4077 OPLEN);
4078 else
4079 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)",
4080 OPLEN);
4081 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1);
4082#endif
4083 break;
4084
4085 /*
4086 * single operand, a 16/32 bit displacement
4087 */
4088 case D:
4089 wbit = LONG_OPND;
4090 dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
4091 NOMEM;
4092 break;
4093
4094 /* jmp/call indirect to memory or register operand */
4095 case INM:
4096#ifdef DIS_TEXT
4097 (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN);
4098#endif
4099 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m);
4100 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4101 wbit = LONG_OPND;
4102 break;
4103
4104 /*
4105 * for long jumps and long calls -- a new code segment
4106 * register and an offset in IP -- stored in object
4107 * code in reverse order. Note - not valid in amd64
4108 */
4109 case SO:
4110 dtrace_check_override(x, 1);
4111 wbit = LONG_OPND;
4112 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1);
4113#ifdef DIS_TEXT
4114 x->d86_opnd[1].d86_mode = MODE_SIGNED;
4115#endif
4116 /* will now get segment operand */
4117 dtrace_imm_opnd(x, wbit, 2, 0);
4118 break;
4119
4120 /*
4121 * jmp/call. single operand, 8 bit displacement.
4122 * added to current EIP in 'compofff'
4123 */
4124 case BD:
4125 dtrace_disp_opnd(x, BYTE_OPND, 1, 0);
4126 NOMEM;
4127 break;
4128
4129 /* single 32/16 bit immediate operand */
4130 case I:
4131 wbit = LONG_OPND;
4132 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0);
4133 break;
4134
4135 /* single 8 bit immediate operand */
4136 case Ib:
4137 wbit = LONG_OPND;
4138 dtrace_imm_opnd(x, wbit, 1, 0);
4139 break;
4140
4141 case ENTER:
4142 wbit = LONG_OPND;
4143 dtrace_imm_opnd(x, wbit, 2, 0);
4144 dtrace_imm_opnd(x, wbit, 1, 1);
4145 switch (opnd_size) {
4146 case SIZE64:
4147 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8;
4148 break;
4149 case SIZE32:
4150 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4;
4151 break;
4152 case SIZE16:
4153 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2;
4154 break;
4155 }
4156
4157 break;
4158
4159 /* 16-bit immediate operand */
4160 case RET:
4161 wbit = LONG_OPND;
4162 dtrace_imm_opnd(x, wbit, 2, 0);
4163 break;
4164
4165 /* single 8 bit port operand */
4166 case P:
4167 dtrace_check_override(x, 0);
4168 dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
4169 NOMEM;
4170 break;
4171
4172 /* single operand, dx register (variable port instruction) */
4173 case V:
4174 x->d86_numopnds = 1;
4175 dtrace_check_override(x, 0);
4176#ifdef DIS_TEXT
4177 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN);
4178#endif
4179 NOMEM;
4180 break;
4181
4182 /*
4183 * The int instruction, which has two forms:
4184 * int 3 (breakpoint) or
4185 * int n, where n is indicated in the subsequent
4186 * byte (format Ib). The int 3 instruction (opcode 0xCC),
4187 * where, although the 3 looks like an operand,
4188 * it is implied by the opcode. It must be converted
4189 * to the correct base and output.
4190 */
4191 case INT3:
4192#ifdef DIS_TEXT
4193 x->d86_numopnds = 1;
4194 x->d86_opnd[0].d86_mode = MODE_SIGNED;
4195 x->d86_opnd[0].d86_value_size = 1;
4196 x->d86_opnd[0].d86_value = 3;
4197#endif
4198 NOMEM;
4199 break;
4200
4201 /* single 8 bit immediate operand */
4202 case INTx:
4203 dtrace_imm_opnd(x, BYTE_OPND, 1, 0);
4204 NOMEM;
4205 break;
4206
4207 /* an unused byte must be discarded */
4208 case U:
4209 if (x->d86_get_byte(x->d86_data) < 0)
4210 goto error;
4211 x->d86_len++;
4212 NOMEM;
4213 break;
4214
4215 case CBW:
4216#ifdef DIS_TEXT
4217 if (opnd_size == SIZE16)
4218 (void) strlcat(x->d86_mnem, "cbtw", OPLEN);
4219 else if (opnd_size == SIZE32)
4220 (void) strlcat(x->d86_mnem, "cwtl", OPLEN);
4221 else
4222 (void) strlcat(x->d86_mnem, "cltq", OPLEN);
4223#endif
4224 wbit = LONG_OPND;
4225 NOMEM;
4226 break;
4227
4228 case CWD:
4229#ifdef DIS_TEXT
4230 if (opnd_size == SIZE16)
4231 (void) strlcat(x->d86_mnem, "cwtd", OPLEN);
4232 else if (opnd_size == SIZE32)
4233 (void) strlcat(x->d86_mnem, "cltd", OPLEN);
4234 else
4235 (void) strlcat(x->d86_mnem, "cqtd", OPLEN);
4236#endif
4237 wbit = LONG_OPND;
4238 NOMEM;
4239 break;
4240
4241 case XMMSFNC:
4242 /*
4243 * sfence is sfence if mode is REG_ONLY. If mode isn't
4244 * REG_ONLY, mnemonic should be 'clflush'.
4245 */
4246 dtrace_get_modrm(x, &mode, &reg, &r_m);
4247
4248 /* sfence doesn't take operands */
4249#ifdef DIS_TEXT
4250 if (mode == REG_ONLY) {
4251 (void) strlcat(x->d86_mnem, "sfence", OPLEN);
4252 } else {
4253 (void) strlcat(x->d86_mnem, "clflush", OPLEN);
4254 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4255 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
4256 NOMEM;
4257 }
4258#else
4259 if (mode != REG_ONLY) {
4260 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4261 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4262 NOMEM;
4263 }
4264#endif
4265 break;
4266
4267 /*
4268 * no disassembly, the mnemonic was all there was so go on
4269 */
4270 case NORM:
4271 if (dp->it_invalid32 && cpu_mode != SIZE64)
4272 goto error;
4273 NOMEM;
4274 /*FALLTHROUGH*/
4275 case IMPLMEM:
4276 break;
4277
4278 case XMMFENCE:
4279 /*
4280 * XRSTOR and LFENCE share the same opcode but differ in mode
4281 */
4282 dtrace_get_modrm(x, &mode, &reg, &r_m);
4283
4284 if (mode == REG_ONLY) {
4285 /*
4286 * Only the following exact byte sequences are allowed:
4287 *
4288 * 0f ae e8 lfence
4289 * 0f ae f0 mfence
4290 */
4291 if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 &&
4292 (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0)
4293 goto error;
4294 } else {
4295#ifdef DIS_TEXT
4296 (void) strncpy(x->d86_mnem, "xrstor", OPLEN);
4297#endif
4298 dtrace_rex_adjust(rex_prefix, mode, &reg, &r_m);
4299 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0);
4300 }
4301 break;
4302
4303 /* float reg */
4304 case F:
4305#ifdef DIS_TEXT
4306 x->d86_numopnds = 1;
4307 (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN);
4308 x->d86_opnd[0].d86_opnd[4] = r_m + '0';
4309#endif
4310 NOMEM;
4311 break;
4312
4313 /* float reg to float reg, with ret bit present */
4314 case FF:
4315 vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */
4316 /*FALLTHROUGH*/
4317 case FFC: /* case for vbit always = 0 */
4318#ifdef DIS_TEXT
4319 x->d86_numopnds = 2;
4320 (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN);
4321 (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN);
4322 x->d86_opnd[vbit].d86_opnd[4] = r_m + '0';
4323#endif
4324 NOMEM;
4325 break;
4326
4327 /* AVX instructions */
4328 case VEX_MO:
4329 /* op(ModR/M.r/m) */
4330 x->d86_numopnds = 1;
4331 dtrace_get_modrm(x, &mode, &reg, &r_m);
4332#ifdef DIS_TEXT
4333 if ((dp == &dis_opAVX0F[0xA][0xE]) && (reg == 3))
4334 (void) strncpy(x->d86_mnem, "vstmxcsr", OPLEN);
4335#endif
4336 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4337 dtrace_get_operand(x, mode, r_m, wbit, 0);
4338 break;
4339 case VEX_RMrX:
4340 /* ModR/M.reg := op(VEX.vvvv, ModR/M.r/m) */
4341 x->d86_numopnds = 3;
4342 dtrace_get_modrm(x, &mode, &reg, &r_m);
4343 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4344
4345 if (mode != REG_ONLY) {
4346 if ((dp == &dis_opAVXF20F[0x10]) ||
4347 (dp == &dis_opAVXF30F[0x10])) {
4348 /* vmovsd <m64>, <xmm> */
4349 /* or vmovss <m64>, <xmm> */
4350 x->d86_numopnds = 2;
4351 goto L_VEX_MX;
4352 }
4353 }
4354
4355 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4356 /*
4357 * VEX prefix uses the 1's complement form to encode the
4358 * XMM/YMM regs
4359 */
4360 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4361
4362 if ((dp == &dis_opAVXF20F[0x2A]) ||
4363 (dp == &dis_opAVXF30F[0x2A])) {
4364 /*
4365 * vcvtsi2si </r,m>, <xmm>, <xmm> or vcvtsi2ss </r,m>,
4366 * <xmm>, <xmm>
4367 */
4368 wbit = LONG_OPND;
4369 }
4370#ifdef DIS_TEXT
4371 else if ((mode == REG_ONLY) &&
4372 (dp == &dis_opAVX0F[0x1][0x6])) { /* vmovlhps */
4373 (void) strncpy(x->d86_mnem, "vmovlhps", OPLEN);
4374 } else if ((mode == REG_ONLY) &&
4375 (dp == &dis_opAVX0F[0x1][0x2])) { /* vmovhlps */
4376 (void) strncpy(x->d86_mnem, "vmovhlps", OPLEN);
4377 }
4378#endif
4379 dtrace_get_operand(x, mode, r_m, wbit, 0);
4380
4381 break;
4382
4383 case VEX_RRX:
4384 /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */
4385 x->d86_numopnds = 3;
4386
4387 dtrace_get_modrm(x, &mode, &reg, &r_m);
4388 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4389
4390 if (mode != REG_ONLY) {
4391 if ((dp == &dis_opAVXF20F[0x11]) ||
4392 (dp == &dis_opAVXF30F[0x11])) {
4393 /* vmovsd <xmm>, <m64> */
4394 /* or vmovss <xmm>, <m64> */
4395 x->d86_numopnds = 2;
4396 goto L_VEX_RM;
4397 }
4398 }
4399
4400 dtrace_get_operand(x, mode, r_m, wbit, 2);
4401 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4402 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4403 break;
4404
4405 case VEX_RMRX:
4406 /* ModR/M.reg := op(VEX.vvvv, ModR/M.r_m, imm8[7:4]) */
4407 x->d86_numopnds = 4;
4408
4409 dtrace_get_modrm(x, &mode, &reg, &r_m);
4410 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4411 dtrace_get_operand(x, REG_ONLY, reg, wbit, 3);
4412 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2);
4413 if (dp == &dis_opAVX660F3A[0x18]) {
4414 /* vinsertf128 <imm8>, <xmm>, <ymm>, <ymm> */
4415 dtrace_get_operand(x, mode, r_m, XMM_OPND, 1);
4416 } else if ((dp == &dis_opAVX660F3A[0x20]) ||
4417 (dp == & dis_opAVX660F[0xC4])) {
4418 /* vpinsrb <imm8>, <reg/mm>, <xmm>, <xmm> */
4419 /* or vpinsrw <imm8>, <reg/mm>, <xmm>, <xmm> */
4420 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4421 } else if (dp == &dis_opAVX660F3A[0x22]) {
4422 /* vpinsrd/q <imm8>, <reg/mm>, <xmm>, <xmm> */
4423#ifdef DIS_TEXT
4424 if (vex_W)
4425 x->d86_mnem[6] = 'q';
4426#endif
4427 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4428 } else {
4429 dtrace_get_operand(x, mode, r_m, wbit, 1);
4430 }
4431
4432 /* one byte immediate number */
4433 dtrace_imm_opnd(x, wbit, 1, 0);
4434
4435 /* vblendvpd, vblendvps, vblendvb use the imm encode the regs */
4436 if ((dp == &dis_opAVX660F3A[0x4A]) ||
4437 (dp == &dis_opAVX660F3A[0x4B]) ||
4438 (dp == &dis_opAVX660F3A[0x4C])) {
4439#ifdef DIS_TEXT
4440 int regnum = (x->d86_opnd[0].d86_value & 0xF0) >> 4;
4441#endif
4442 x->d86_opnd[0].d86_mode = MODE_NONE;
4443#ifdef DIS_TEXT
4444 if (vex_L)
4445 (void) strncpy(x->d86_opnd[0].d86_opnd,
4446 dis_YMMREG[regnum], OPLEN);
4447 else
4448 (void) strncpy(x->d86_opnd[0].d86_opnd,
4449 dis_XMMREG[regnum], OPLEN);
4450#endif
4451 }
4452 break;
4453
4454 case VEX_MX:
4455 /* ModR/M.reg := op(ModR/M.rm) */
4456 x->d86_numopnds = 2;
4457
4458 dtrace_get_modrm(x, &mode, &reg, &r_m);
4459 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4460L_VEX_MX:
4461
4462 if ((dp == &dis_opAVXF20F[0xE6]) ||
4463 (dp == &dis_opAVX660F[0x5A]) ||
4464 (dp == &dis_opAVX660F[0xE6])) {
4465 /* vcvtpd2dq <ymm>, <xmm> */
4466 /* or vcvtpd2ps <ymm>, <xmm> */
4467 /* or vcvttpd2dq <ymm>, <xmm> */
4468 dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1);
4469 dtrace_get_operand(x, mode, r_m, wbit, 0);
4470 } else if ((dp == &dis_opAVXF30F[0xE6]) ||
4303 (dp == &dis_opAVX0F[0x5][0xA])) {
4471 (dp == &dis_opAVX0F[0x5][0xA]) ||
4472 (dp == &dis_opAVX660F38[0x13])) {
4304 /* vcvtdq2pd <xmm>, <ymm> */
4305 /* or vcvtps2pd <xmm>, <ymm> */
4306 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4307 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
4308 } else if (dp == &dis_opAVX660F[0x6E]) {
4309 /* vmovd/q <reg/mem 32/64>, <xmm> */
4310#ifdef DIS_TEXT
4311 if (vex_W)
4312 x->d86_mnem[4] = 'q';
4313#endif
4314 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4315 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4316 } else {
4317 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4318 dtrace_get_operand(x, mode, r_m, wbit, 0);
4319 }
4320
4321 break;
4322
4323 case VEX_MXI:
4324 /* ModR/M.reg := op(ModR/M.rm, imm8) */
4325 x->d86_numopnds = 3;
4326
4327 dtrace_get_modrm(x, &mode, &reg, &r_m);
4328 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4329
4330 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4331 dtrace_get_operand(x, mode, r_m, wbit, 1);
4332
4333 /* one byte immediate number */
4334 dtrace_imm_opnd(x, wbit, 1, 0);
4335 break;
4336
4337 case VEX_XXI:
4338 /* VEX.vvvv := op(ModR/M.rm, imm8) */
4339 x->d86_numopnds = 3;
4340
4341 dtrace_get_modrm(x, &mode, &reg, &r_m);
4342#ifdef DIS_TEXT
4343 (void) strncpy(x->d86_mnem, dis_AVXvgrp7[opcode2 - 1][reg],
4344 OPLEN);
4345#endif
4346 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4347
4348 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2);
4349 dtrace_get_operand(x, REG_ONLY, r_m, wbit, 1);
4350
4351 /* one byte immediate number */
4352 dtrace_imm_opnd(x, wbit, 1, 0);
4353 break;
4354
4355 case VEX_MR:
4356 /* ModR/M.reg (reg32/64) := op(ModR/M.rm) */
4357 if (dp == &dis_opAVX660F[0xC5]) {
4358 /* vpextrw <imm8>, <xmm>, <reg> */
4359 x->d86_numopnds = 2;
4360 vbit = 2;
4361 } else {
4362 x->d86_numopnds = 2;
4363 vbit = 1;
4364 }
4365
4366 dtrace_get_modrm(x, &mode, &reg, &r_m);
4367 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4368 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, vbit);
4369 dtrace_get_operand(x, mode, r_m, wbit, vbit - 1);
4370
4371 if (vbit == 2)
4372 dtrace_imm_opnd(x, wbit, 1, 0);
4373
4374 break;
4375
4376 case VEX_RRI:
4377 /* implicit(eflags/r32) := op(ModR/M.reg, ModR/M.rm) */
4378 x->d86_numopnds = 2;
4379
4380 dtrace_get_modrm(x, &mode, &reg, &r_m);
4381 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4382 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4383 dtrace_get_operand(x, mode, r_m, wbit, 0);
4384 break;
4385
4386 case VEX_RX:
4387 /* ModR/M.rm := op(ModR/M.reg) */
4473 /* vcvtdq2pd <xmm>, <ymm> */
4474 /* or vcvtps2pd <xmm>, <ymm> */
4475 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4476 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0);
4477 } else if (dp == &dis_opAVX660F[0x6E]) {
4478 /* vmovd/q <reg/mem 32/64>, <xmm> */
4479#ifdef DIS_TEXT
4480 if (vex_W)
4481 x->d86_mnem[4] = 'q';
4482#endif
4483 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4484 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0);
4485 } else {
4486 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4487 dtrace_get_operand(x, mode, r_m, wbit, 0);
4488 }
4489
4490 break;
4491
4492 case VEX_MXI:
4493 /* ModR/M.reg := op(ModR/M.rm, imm8) */
4494 x->d86_numopnds = 3;
4495
4496 dtrace_get_modrm(x, &mode, &reg, &r_m);
4497 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4498
4499 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4500 dtrace_get_operand(x, mode, r_m, wbit, 1);
4501
4502 /* one byte immediate number */
4503 dtrace_imm_opnd(x, wbit, 1, 0);
4504 break;
4505
4506 case VEX_XXI:
4507 /* VEX.vvvv := op(ModR/M.rm, imm8) */
4508 x->d86_numopnds = 3;
4509
4510 dtrace_get_modrm(x, &mode, &reg, &r_m);
4511#ifdef DIS_TEXT
4512 (void) strncpy(x->d86_mnem, dis_AVXvgrp7[opcode2 - 1][reg],
4513 OPLEN);
4514#endif
4515 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4516
4517 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2);
4518 dtrace_get_operand(x, REG_ONLY, r_m, wbit, 1);
4519
4520 /* one byte immediate number */
4521 dtrace_imm_opnd(x, wbit, 1, 0);
4522 break;
4523
4524 case VEX_MR:
4525 /* ModR/M.reg (reg32/64) := op(ModR/M.rm) */
4526 if (dp == &dis_opAVX660F[0xC5]) {
4527 /* vpextrw <imm8>, <xmm>, <reg> */
4528 x->d86_numopnds = 2;
4529 vbit = 2;
4530 } else {
4531 x->d86_numopnds = 2;
4532 vbit = 1;
4533 }
4534
4535 dtrace_get_modrm(x, &mode, &reg, &r_m);
4536 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4537 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, vbit);
4538 dtrace_get_operand(x, mode, r_m, wbit, vbit - 1);
4539
4540 if (vbit == 2)
4541 dtrace_imm_opnd(x, wbit, 1, 0);
4542
4543 break;
4544
4545 case VEX_RRI:
4546 /* implicit(eflags/r32) := op(ModR/M.reg, ModR/M.rm) */
4547 x->d86_numopnds = 2;
4548
4549 dtrace_get_modrm(x, &mode, &reg, &r_m);
4550 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4551 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4552 dtrace_get_operand(x, mode, r_m, wbit, 0);
4553 break;
4554
4555 case VEX_RX:
4556 /* ModR/M.rm := op(ModR/M.reg) */
4388 if (dp == &dis_opAVX660F3A[0x19]) { /* vextractf128 */
4557 /* vextractf128 || vcvtps2ph */
4558 if (dp == &dis_opAVX660F3A[0x19] ||
4559 dp == &dis_opAVX660F3A[0x1d]) {
4389 x->d86_numopnds = 3;
4390
4391 dtrace_get_modrm(x, &mode, &reg, &r_m);
4392 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4393
4394 dtrace_get_operand(x, mode, r_m, XMM_OPND, 2);
4395 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4396
4397 /* one byte immediate number */
4398 dtrace_imm_opnd(x, wbit, 1, 0);
4399 break;
4400 }
4401
4402 x->d86_numopnds = 2;
4403
4404 dtrace_get_modrm(x, &mode, &reg, &r_m);
4405 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4406 dtrace_get_operand(x, mode, r_m, wbit, 1);
4407 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4408 break;
4409
4410 case VEX_RR:
4411 /* ModR/M.rm := op(ModR/M.reg) */
4412 x->d86_numopnds = 2;
4413
4414 dtrace_get_modrm(x, &mode, &reg, &r_m);
4415 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4416
4417 if (dp == &dis_opAVX660F[0x7E]) {
4418 /* vmovd/q <reg/mem 32/64>, <xmm> */
4419#ifdef DIS_TEXT
4420 if (vex_W)
4421 x->d86_mnem[4] = 'q';
4422#endif
4423 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4424 } else
4425 dtrace_get_operand(x, mode, r_m, wbit, 1);
4426
4427 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4428 break;
4429
4430 case VEX_RRi:
4431 /* ModR/M.rm := op(ModR/M.reg, imm) */
4432 x->d86_numopnds = 3;
4433
4434 dtrace_get_modrm(x, &mode, &reg, &r_m);
4435 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4436
4437#ifdef DIS_TEXT
4438 if (dp == &dis_opAVX660F3A[0x16]) {
4439 /* vpextrd/q <imm>, <xmm>, <reg/mem 32/64> */
4440 if (vex_W)
4441 x->d86_mnem[6] = 'q';
4442 }
4443#endif
4444 dtrace_get_operand(x, mode, r_m, LONG_OPND, 2);
4445 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4446
4447 /* one byte immediate number */
4448 dtrace_imm_opnd(x, wbit, 1, 0);
4449 break;
4450
4451 case VEX_RM:
4452 /* ModR/M.rm := op(ModR/M.reg) */
4453 if (dp == &dis_opAVX660F3A[0x17]) { /* vextractps */
4454 x->d86_numopnds = 3;
4455
4456 dtrace_get_modrm(x, &mode, &reg, &r_m);
4457 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4458
4459 dtrace_get_operand(x, mode, r_m, LONG_OPND, 2);
4460 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4461 /* one byte immediate number */
4462 dtrace_imm_opnd(x, wbit, 1, 0);
4463 break;
4464 }
4465 x->d86_numopnds = 2;
4466
4467 dtrace_get_modrm(x, &mode, &reg, &r_m);
4468 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4469L_VEX_RM:
4470 vbit = 1;
4471 dtrace_get_operand(x, mode, r_m, wbit, vbit);
4472 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit - 1);
4473
4474 break;
4475
4476 case VEX_RRM:
4477 /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */
4478 x->d86_numopnds = 3;
4479
4480 dtrace_get_modrm(x, &mode, &reg, &r_m);
4481 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4482 dtrace_get_operand(x, mode, r_m, wbit, 2);
4483 /* VEX use the 1's complement form encode the XMM/YMM regs */
4484 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4485 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4486 break;
4487
4488 case VEX_RMX:
4489 /* ModR/M.reg := op(VEX.vvvv, ModR/M.rm) */
4490 x->d86_numopnds = 3;
4491
4492 dtrace_get_modrm(x, &mode, &reg, &r_m);
4493 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4494 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4495 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4496 dtrace_get_operand(x, REG_ONLY, r_m, wbit, 0);
4497 break;
4498
4499 case VEX_NONE:
4500#ifdef DIS_TEXT
4501 if (vex_L)
4502 (void) strncpy(x->d86_mnem, "vzeroall", OPLEN);
4503#endif
4504 break;
4505 /* an invalid op code */
4506 case AM:
4507 case DM:
4508 case OVERRIDE:
4509 case PREFIX:
4510 case UNKNOWN:
4511 NOMEM;
4512 default:
4513 goto error;
4514 } /* end switch */
4515 if (x->d86_error)
4516 goto error;
4517
4518done:
4519#ifdef DIS_MEM
4520 /*
4521 * compute the size of any memory accessed by the instruction
4522 */
4523 if (x->d86_memsize != 0) {
4524 return (0);
4525 } else if (dp->it_stackop) {
4526 switch (opnd_size) {
4527 case SIZE16:
4528 x->d86_memsize = 2;
4529 break;
4530 case SIZE32:
4531 x->d86_memsize = 4;
4532 break;
4533 case SIZE64:
4534 x->d86_memsize = 8;
4535 break;
4536 }
4537 } else if (nomem || mode == REG_ONLY) {
4538 x->d86_memsize = 0;
4539
4540 } else if (dp->it_size != 0) {
4541 /*
4542 * In 64 bit mode descriptor table entries
4543 * go up to 10 bytes and popf/pushf are always 8 bytes
4544 */
4545 if (x->d86_mode == SIZE64 && dp->it_size == 6)
4546 x->d86_memsize = 10;
4547 else if (x->d86_mode == SIZE64 && opcode1 == 0x9 &&
4548 (opcode2 == 0xc || opcode2 == 0xd))
4549 x->d86_memsize = 8;
4550 else
4551 x->d86_memsize = dp->it_size;
4552
4553 } else if (wbit == 0) {
4554 x->d86_memsize = 1;
4555
4556 } else if (wbit == LONG_OPND) {
4557 if (opnd_size == SIZE64)
4558 x->d86_memsize = 8;
4559 else if (opnd_size == SIZE32)
4560 x->d86_memsize = 4;
4561 else
4562 x->d86_memsize = 2;
4563
4564 } else if (wbit == SEG_OPND) {
4565 x->d86_memsize = 4;
4566
4567 } else {
4568 x->d86_memsize = 8;
4569 }
4570#endif
4571 return (0);
4572
4573error:
4574#ifdef DIS_TEXT
4575 (void) strlcat(x->d86_mnem, "undef", OPLEN);
4576#endif
4577 return (1);
4578}
4579
4580#ifdef DIS_TEXT
4581
4582/*
4583 * Some instructions should have immediate operands printed
4584 * as unsigned integers. We compare against this table.
4585 */
4586static char *unsigned_ops[] = {
4587 "or", "and", "xor", "test", "in", "out", "lcall", "ljmp",
4588 "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl",
4589 0
4590};
4591
4592
4593static int
4594isunsigned_op(char *opcode)
4595{
4596 char *where;
4597 int i;
4598 int is_unsigned = 0;
4599
4600 /*
4601 * Work back to start of last mnemonic, since we may have
4602 * prefixes on some opcodes.
4603 */
4604 where = opcode + strlen(opcode) - 1;
4605 while (where > opcode && *where != ' ')
4606 --where;
4607 if (*where == ' ')
4608 ++where;
4609
4610 for (i = 0; unsigned_ops[i]; ++i) {
4611 if (strncmp(where, unsigned_ops[i],
4612 strlen(unsigned_ops[i])))
4613 continue;
4614 is_unsigned = 1;
4615 break;
4616 }
4617 return (is_unsigned);
4618}
4619
4620/*
4621 * Print a numeric immediate into end of buf, maximum length buflen.
4622 * The immediate may be an address or a displacement. Mask is set
4623 * for address size. If the immediate is a "small negative", or
4624 * if it's a negative displacement of any magnitude, print as -<absval>.
4625 * Respect the "octal" flag. "Small negative" is defined as "in the
4626 * interval [NEG_LIMIT, 0)".
4627 *
4628 * Also, "isunsigned_op()" instructions never print negatives.
4629 *
4630 * Return whether we decided to print a negative value or not.
4631 */
4632
4633#define NEG_LIMIT -255
4634enum {IMM, DISP};
4635enum {POS, TRY_NEG};
4636
4637static int
4638print_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf,
4639 size_t buflen, int disp, int try_neg)
4640{
4641 int curlen;
4642 int64_t sv = (int64_t)usv;
4643 int octal = dis->d86_flags & DIS_F_OCTAL;
4644
4645 curlen = strlen(buf);
4646
4647 if (try_neg == TRY_NEG && sv < 0 &&
4648 (disp || sv >= NEG_LIMIT) &&
4649 !isunsigned_op(dis->d86_mnem)) {
4650 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4651 octal ? "-0%llo" : "-0x%llx", (-sv) & mask);
4652 return (1);
4653 } else {
4654 if (disp == DISP)
4655 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4656 octal ? "+0%llo" : "+0x%llx", usv & mask);
4657 else
4658 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4659 octal ? "0%llo" : "0x%llx", usv & mask);
4660 return (0);
4661
4662 }
4663}
4664
4665
4666static int
4667log2(int size)
4668{
4669 switch (size) {
4670 case 1: return (0);
4671 case 2: return (1);
4672 case 4: return (2);
4673 case 8: return (3);
4674 }
4675 return (0);
4676}
4677
4678/* ARGSUSED */
4679void
4680dtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf,
4681 size_t buflen)
4682{
4683 uint64_t reltgt = 0;
4684 uint64_t tgt = 0;
4685 int curlen;
4686 int (*lookup)(void *, uint64_t, char *, size_t);
4687 int i;
4688 int64_t sv;
4689 uint64_t usv, mask, save_mask, save_usv;
4690 static uint64_t masks[] =
4691 {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL};
4692 save_usv = 0;
4693
4694 dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem);
4695
4696 /*
4697 * For PC-relative jumps, the pc is really the next pc after executing
4698 * this instruction, so increment it appropriately.
4699 */
4700 pc += dis->d86_len;
4701
4702 for (i = 0; i < dis->d86_numopnds; i++) {
4703 d86opnd_t *op = &dis->d86_opnd[i];
4704
4705 if (i != 0)
4706 (void) strlcat(buf, ",", buflen);
4707
4708 (void) strlcat(buf, op->d86_prefix, buflen);
4709
4710 /*
4711 * sv is for the signed, possibly-truncated immediate or
4712 * displacement; usv retains the original size and
4713 * unsignedness for symbol lookup.
4714 */
4715
4716 sv = usv = op->d86_value;
4717
4718 /*
4719 * About masks: for immediates that represent
4720 * addresses, the appropriate display size is
4721 * the effective address size of the instruction.
4722 * This includes MODE_OFFSET, MODE_IPREL, and
4723 * MODE_RIPREL. Immediates that are simply
4724 * immediate values should display in the operand's
4725 * size, however, since they don't represent addresses.
4726 */
4727
4728 /* d86_addr_size is SIZEnn, which is log2(real size) */
4729 mask = masks[dis->d86_addr_size];
4730
4731 /* d86_value_size and d86_imm_bytes are in bytes */
4732 if (op->d86_mode == MODE_SIGNED ||
4733 op->d86_mode == MODE_IMPLIED)
4734 mask = masks[log2(op->d86_value_size)];
4735
4736 switch (op->d86_mode) {
4737
4738 case MODE_NONE:
4739
4740 (void) strlcat(buf, op->d86_opnd, buflen);
4741 break;
4742
4743 case MODE_SIGNED:
4744 case MODE_IMPLIED:
4745 case MODE_OFFSET:
4746
4747 tgt = usv;
4748
4749 if (dis->d86_seg_prefix)
4750 (void) strlcat(buf, dis->d86_seg_prefix,
4751 buflen);
4752
4753 if (op->d86_mode == MODE_SIGNED ||
4754 op->d86_mode == MODE_IMPLIED) {
4755 (void) strlcat(buf, "$", buflen);
4756 }
4757
4758 if (print_imm(dis, usv, mask, buf, buflen,
4759 IMM, TRY_NEG) &&
4760 (op->d86_mode == MODE_SIGNED ||
4761 op->d86_mode == MODE_IMPLIED)) {
4762
4763 /*
4764 * We printed a negative value for an
4765 * immediate that wasn't a
4766 * displacement. Note that fact so we can
4767 * print the positive value as an
4768 * annotation.
4769 */
4770
4771 save_usv = usv;
4772 save_mask = mask;
4773 }
4774 (void) strlcat(buf, op->d86_opnd, buflen);
4775
4776 break;
4777
4778 case MODE_IPREL:
4779 case MODE_RIPREL:
4780
4781 reltgt = pc + sv;
4782
4783 switch (mode) {
4784 case SIZE16:
4785 reltgt = (uint16_t)reltgt;
4786 break;
4787 case SIZE32:
4788 reltgt = (uint32_t)reltgt;
4789 break;
4790 }
4791
4792 (void) print_imm(dis, usv, mask, buf, buflen,
4793 DISP, TRY_NEG);
4794
4795 if (op->d86_mode == MODE_RIPREL)
4796 (void) strlcat(buf, "(%rip)", buflen);
4797 break;
4798 }
4799 }
4800
4801 /*
4802 * The symbol lookups may result in false positives,
4803 * particularly on object files, where small numbers may match
4804 * the 0-relative non-relocated addresses of symbols.
4805 */
4806
4807 lookup = dis->d86_sym_lookup;
4808 if (tgt != 0) {
4809 if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 &&
4810 lookup(dis->d86_data, tgt, NULL, 0) == 0) {
4811 (void) strlcat(buf, "\t<", buflen);
4812 curlen = strlen(buf);
4813 lookup(dis->d86_data, tgt, buf + curlen,
4814 buflen - curlen);
4815 (void) strlcat(buf, ">", buflen);
4816 }
4817
4818 /*
4819 * If we printed a negative immediate above, print the
4820 * positive in case our heuristic was unhelpful
4821 */
4822 if (save_usv) {
4823 (void) strlcat(buf, "\t<", buflen);
4824 (void) print_imm(dis, save_usv, save_mask, buf, buflen,
4825 IMM, POS);
4826 (void) strlcat(buf, ">", buflen);
4827 }
4828 }
4829
4830 if (reltgt != 0) {
4831 /* Print symbol or effective address for reltgt */
4832
4833 (void) strlcat(buf, "\t<", buflen);
4834 curlen = strlen(buf);
4835 lookup(dis->d86_data, reltgt, buf + curlen,
4836 buflen - curlen);
4837 (void) strlcat(buf, ">", buflen);
4838 }
4839}
4840
4841#endif /* DIS_TEXT */
4560 x->d86_numopnds = 3;
4561
4562 dtrace_get_modrm(x, &mode, &reg, &r_m);
4563 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4564
4565 dtrace_get_operand(x, mode, r_m, XMM_OPND, 2);
4566 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4567
4568 /* one byte immediate number */
4569 dtrace_imm_opnd(x, wbit, 1, 0);
4570 break;
4571 }
4572
4573 x->d86_numopnds = 2;
4574
4575 dtrace_get_modrm(x, &mode, &reg, &r_m);
4576 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4577 dtrace_get_operand(x, mode, r_m, wbit, 1);
4578 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4579 break;
4580
4581 case VEX_RR:
4582 /* ModR/M.rm := op(ModR/M.reg) */
4583 x->d86_numopnds = 2;
4584
4585 dtrace_get_modrm(x, &mode, &reg, &r_m);
4586 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4587
4588 if (dp == &dis_opAVX660F[0x7E]) {
4589 /* vmovd/q <reg/mem 32/64>, <xmm> */
4590#ifdef DIS_TEXT
4591 if (vex_W)
4592 x->d86_mnem[4] = 'q';
4593#endif
4594 dtrace_get_operand(x, mode, r_m, LONG_OPND, 1);
4595 } else
4596 dtrace_get_operand(x, mode, r_m, wbit, 1);
4597
4598 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4599 break;
4600
4601 case VEX_RRi:
4602 /* ModR/M.rm := op(ModR/M.reg, imm) */
4603 x->d86_numopnds = 3;
4604
4605 dtrace_get_modrm(x, &mode, &reg, &r_m);
4606 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4607
4608#ifdef DIS_TEXT
4609 if (dp == &dis_opAVX660F3A[0x16]) {
4610 /* vpextrd/q <imm>, <xmm>, <reg/mem 32/64> */
4611 if (vex_W)
4612 x->d86_mnem[6] = 'q';
4613 }
4614#endif
4615 dtrace_get_operand(x, mode, r_m, LONG_OPND, 2);
4616 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4617
4618 /* one byte immediate number */
4619 dtrace_imm_opnd(x, wbit, 1, 0);
4620 break;
4621
4622 case VEX_RM:
4623 /* ModR/M.rm := op(ModR/M.reg) */
4624 if (dp == &dis_opAVX660F3A[0x17]) { /* vextractps */
4625 x->d86_numopnds = 3;
4626
4627 dtrace_get_modrm(x, &mode, &reg, &r_m);
4628 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4629
4630 dtrace_get_operand(x, mode, r_m, LONG_OPND, 2);
4631 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
4632 /* one byte immediate number */
4633 dtrace_imm_opnd(x, wbit, 1, 0);
4634 break;
4635 }
4636 x->d86_numopnds = 2;
4637
4638 dtrace_get_modrm(x, &mode, &reg, &r_m);
4639 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4640L_VEX_RM:
4641 vbit = 1;
4642 dtrace_get_operand(x, mode, r_m, wbit, vbit);
4643 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit - 1);
4644
4645 break;
4646
4647 case VEX_RRM:
4648 /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */
4649 x->d86_numopnds = 3;
4650
4651 dtrace_get_modrm(x, &mode, &reg, &r_m);
4652 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4653 dtrace_get_operand(x, mode, r_m, wbit, 2);
4654 /* VEX use the 1's complement form encode the XMM/YMM regs */
4655 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4656 dtrace_get_operand(x, REG_ONLY, reg, wbit, 0);
4657 break;
4658
4659 case VEX_RMX:
4660 /* ModR/M.reg := op(VEX.vvvv, ModR/M.rm) */
4661 x->d86_numopnds = 3;
4662
4663 dtrace_get_modrm(x, &mode, &reg, &r_m);
4664 dtrace_vex_adjust(vex_byte1, mode, &reg, &r_m);
4665 dtrace_get_operand(x, REG_ONLY, reg, wbit, 2);
4666 dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1);
4667 dtrace_get_operand(x, REG_ONLY, r_m, wbit, 0);
4668 break;
4669
4670 case VEX_NONE:
4671#ifdef DIS_TEXT
4672 if (vex_L)
4673 (void) strncpy(x->d86_mnem, "vzeroall", OPLEN);
4674#endif
4675 break;
4676 /* an invalid op code */
4677 case AM:
4678 case DM:
4679 case OVERRIDE:
4680 case PREFIX:
4681 case UNKNOWN:
4682 NOMEM;
4683 default:
4684 goto error;
4685 } /* end switch */
4686 if (x->d86_error)
4687 goto error;
4688
4689done:
4690#ifdef DIS_MEM
4691 /*
4692 * compute the size of any memory accessed by the instruction
4693 */
4694 if (x->d86_memsize != 0) {
4695 return (0);
4696 } else if (dp->it_stackop) {
4697 switch (opnd_size) {
4698 case SIZE16:
4699 x->d86_memsize = 2;
4700 break;
4701 case SIZE32:
4702 x->d86_memsize = 4;
4703 break;
4704 case SIZE64:
4705 x->d86_memsize = 8;
4706 break;
4707 }
4708 } else if (nomem || mode == REG_ONLY) {
4709 x->d86_memsize = 0;
4710
4711 } else if (dp->it_size != 0) {
4712 /*
4713 * In 64 bit mode descriptor table entries
4714 * go up to 10 bytes and popf/pushf are always 8 bytes
4715 */
4716 if (x->d86_mode == SIZE64 && dp->it_size == 6)
4717 x->d86_memsize = 10;
4718 else if (x->d86_mode == SIZE64 && opcode1 == 0x9 &&
4719 (opcode2 == 0xc || opcode2 == 0xd))
4720 x->d86_memsize = 8;
4721 else
4722 x->d86_memsize = dp->it_size;
4723
4724 } else if (wbit == 0) {
4725 x->d86_memsize = 1;
4726
4727 } else if (wbit == LONG_OPND) {
4728 if (opnd_size == SIZE64)
4729 x->d86_memsize = 8;
4730 else if (opnd_size == SIZE32)
4731 x->d86_memsize = 4;
4732 else
4733 x->d86_memsize = 2;
4734
4735 } else if (wbit == SEG_OPND) {
4736 x->d86_memsize = 4;
4737
4738 } else {
4739 x->d86_memsize = 8;
4740 }
4741#endif
4742 return (0);
4743
4744error:
4745#ifdef DIS_TEXT
4746 (void) strlcat(x->d86_mnem, "undef", OPLEN);
4747#endif
4748 return (1);
4749}
4750
4751#ifdef DIS_TEXT
4752
4753/*
4754 * Some instructions should have immediate operands printed
4755 * as unsigned integers. We compare against this table.
4756 */
4757static char *unsigned_ops[] = {
4758 "or", "and", "xor", "test", "in", "out", "lcall", "ljmp",
4759 "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl",
4760 0
4761};
4762
4763
4764static int
4765isunsigned_op(char *opcode)
4766{
4767 char *where;
4768 int i;
4769 int is_unsigned = 0;
4770
4771 /*
4772 * Work back to start of last mnemonic, since we may have
4773 * prefixes on some opcodes.
4774 */
4775 where = opcode + strlen(opcode) - 1;
4776 while (where > opcode && *where != ' ')
4777 --where;
4778 if (*where == ' ')
4779 ++where;
4780
4781 for (i = 0; unsigned_ops[i]; ++i) {
4782 if (strncmp(where, unsigned_ops[i],
4783 strlen(unsigned_ops[i])))
4784 continue;
4785 is_unsigned = 1;
4786 break;
4787 }
4788 return (is_unsigned);
4789}
4790
4791/*
4792 * Print a numeric immediate into end of buf, maximum length buflen.
4793 * The immediate may be an address or a displacement. Mask is set
4794 * for address size. If the immediate is a "small negative", or
4795 * if it's a negative displacement of any magnitude, print as -<absval>.
4796 * Respect the "octal" flag. "Small negative" is defined as "in the
4797 * interval [NEG_LIMIT, 0)".
4798 *
4799 * Also, "isunsigned_op()" instructions never print negatives.
4800 *
4801 * Return whether we decided to print a negative value or not.
4802 */
4803
4804#define NEG_LIMIT -255
4805enum {IMM, DISP};
4806enum {POS, TRY_NEG};
4807
4808static int
4809print_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf,
4810 size_t buflen, int disp, int try_neg)
4811{
4812 int curlen;
4813 int64_t sv = (int64_t)usv;
4814 int octal = dis->d86_flags & DIS_F_OCTAL;
4815
4816 curlen = strlen(buf);
4817
4818 if (try_neg == TRY_NEG && sv < 0 &&
4819 (disp || sv >= NEG_LIMIT) &&
4820 !isunsigned_op(dis->d86_mnem)) {
4821 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4822 octal ? "-0%llo" : "-0x%llx", (-sv) & mask);
4823 return (1);
4824 } else {
4825 if (disp == DISP)
4826 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4827 octal ? "+0%llo" : "+0x%llx", usv & mask);
4828 else
4829 dis->d86_sprintf_func(buf + curlen, buflen - curlen,
4830 octal ? "0%llo" : "0x%llx", usv & mask);
4831 return (0);
4832
4833 }
4834}
4835
4836
4837static int
4838log2(int size)
4839{
4840 switch (size) {
4841 case 1: return (0);
4842 case 2: return (1);
4843 case 4: return (2);
4844 case 8: return (3);
4845 }
4846 return (0);
4847}
4848
4849/* ARGSUSED */
4850void
4851dtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf,
4852 size_t buflen)
4853{
4854 uint64_t reltgt = 0;
4855 uint64_t tgt = 0;
4856 int curlen;
4857 int (*lookup)(void *, uint64_t, char *, size_t);
4858 int i;
4859 int64_t sv;
4860 uint64_t usv, mask, save_mask, save_usv;
4861 static uint64_t masks[] =
4862 {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL};
4863 save_usv = 0;
4864
4865 dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem);
4866
4867 /*
4868 * For PC-relative jumps, the pc is really the next pc after executing
4869 * this instruction, so increment it appropriately.
4870 */
4871 pc += dis->d86_len;
4872
4873 for (i = 0; i < dis->d86_numopnds; i++) {
4874 d86opnd_t *op = &dis->d86_opnd[i];
4875
4876 if (i != 0)
4877 (void) strlcat(buf, ",", buflen);
4878
4879 (void) strlcat(buf, op->d86_prefix, buflen);
4880
4881 /*
4882 * sv is for the signed, possibly-truncated immediate or
4883 * displacement; usv retains the original size and
4884 * unsignedness for symbol lookup.
4885 */
4886
4887 sv = usv = op->d86_value;
4888
4889 /*
4890 * About masks: for immediates that represent
4891 * addresses, the appropriate display size is
4892 * the effective address size of the instruction.
4893 * This includes MODE_OFFSET, MODE_IPREL, and
4894 * MODE_RIPREL. Immediates that are simply
4895 * immediate values should display in the operand's
4896 * size, however, since they don't represent addresses.
4897 */
4898
4899 /* d86_addr_size is SIZEnn, which is log2(real size) */
4900 mask = masks[dis->d86_addr_size];
4901
4902 /* d86_value_size and d86_imm_bytes are in bytes */
4903 if (op->d86_mode == MODE_SIGNED ||
4904 op->d86_mode == MODE_IMPLIED)
4905 mask = masks[log2(op->d86_value_size)];
4906
4907 switch (op->d86_mode) {
4908
4909 case MODE_NONE:
4910
4911 (void) strlcat(buf, op->d86_opnd, buflen);
4912 break;
4913
4914 case MODE_SIGNED:
4915 case MODE_IMPLIED:
4916 case MODE_OFFSET:
4917
4918 tgt = usv;
4919
4920 if (dis->d86_seg_prefix)
4921 (void) strlcat(buf, dis->d86_seg_prefix,
4922 buflen);
4923
4924 if (op->d86_mode == MODE_SIGNED ||
4925 op->d86_mode == MODE_IMPLIED) {
4926 (void) strlcat(buf, "$", buflen);
4927 }
4928
4929 if (print_imm(dis, usv, mask, buf, buflen,
4930 IMM, TRY_NEG) &&
4931 (op->d86_mode == MODE_SIGNED ||
4932 op->d86_mode == MODE_IMPLIED)) {
4933
4934 /*
4935 * We printed a negative value for an
4936 * immediate that wasn't a
4937 * displacement. Note that fact so we can
4938 * print the positive value as an
4939 * annotation.
4940 */
4941
4942 save_usv = usv;
4943 save_mask = mask;
4944 }
4945 (void) strlcat(buf, op->d86_opnd, buflen);
4946
4947 break;
4948
4949 case MODE_IPREL:
4950 case MODE_RIPREL:
4951
4952 reltgt = pc + sv;
4953
4954 switch (mode) {
4955 case SIZE16:
4956 reltgt = (uint16_t)reltgt;
4957 break;
4958 case SIZE32:
4959 reltgt = (uint32_t)reltgt;
4960 break;
4961 }
4962
4963 (void) print_imm(dis, usv, mask, buf, buflen,
4964 DISP, TRY_NEG);
4965
4966 if (op->d86_mode == MODE_RIPREL)
4967 (void) strlcat(buf, "(%rip)", buflen);
4968 break;
4969 }
4970 }
4971
4972 /*
4973 * The symbol lookups may result in false positives,
4974 * particularly on object files, where small numbers may match
4975 * the 0-relative non-relocated addresses of symbols.
4976 */
4977
4978 lookup = dis->d86_sym_lookup;
4979 if (tgt != 0) {
4980 if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 &&
4981 lookup(dis->d86_data, tgt, NULL, 0) == 0) {
4982 (void) strlcat(buf, "\t<", buflen);
4983 curlen = strlen(buf);
4984 lookup(dis->d86_data, tgt, buf + curlen,
4985 buflen - curlen);
4986 (void) strlcat(buf, ">", buflen);
4987 }
4988
4989 /*
4990 * If we printed a negative immediate above, print the
4991 * positive in case our heuristic was unhelpful
4992 */
4993 if (save_usv) {
4994 (void) strlcat(buf, "\t<", buflen);
4995 (void) print_imm(dis, save_usv, save_mask, buf, buflen,
4996 IMM, POS);
4997 (void) strlcat(buf, ">", buflen);
4998 }
4999 }
5000
5001 if (reltgt != 0) {
5002 /* Print symbol or effective address for reltgt */
5003
5004 (void) strlcat(buf, "\t<", buflen);
5005 curlen = strlen(buf);
5006 lookup(dis->d86_data, reltgt, buf + curlen,
5007 buflen - curlen);
5008 (void) strlcat(buf, ">", buflen);
5009 }
5010}
5011
5012#endif /* DIS_TEXT */