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