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