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