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