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