1 /* 2 * 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #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 /* 1417 * Even in 64 bit mode, usually only 4 byte immediate operands are supported. 1418 */ 1419 static int isize[] = {1, 2, 4, 4}; 1420 static int isize64[] = {1, 2, 4, 8}; 1421 1422 /* 1423 * Just a bunch of useful macros. 1424 */ 1425 #define WBIT(x) (x & 0x1) /* to get w bit */ 1426 #define REGNO(x) (x & 0x7) /* to get 3 bit register */ 1427 #define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */ 1428 #define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1) 1429 #define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1) 1430 1431 #define REG_ONLY 3 /* mode to indicate a register operand (not memory) */ 1432 1433 #define BYTE_OPND 0 /* w-bit value indicating byte register */ 1434 #define LONG_OPND 1 /* w-bit value indicating opnd_size register */ 1435 #define MM_OPND 2 /* "value" used to indicate a mmx reg */ 1436 #define XMM_OPND 3 /* "value" used to indicate a xmm reg */ 1437 #define SEG_OPND 4 /* "value" used to indicate a segment reg */ 1438 #define CONTROL_OPND 5 /* "value" used to indicate a control reg */ 1439 #define DEBUG_OPND 6 /* "value" used to indicate a debug reg */ 1440 #define TEST_OPND 7 /* "value" used to indicate a test reg */ 1441 #define WORD_OPND 8 /* w-bit value indicating word size reg */ 1442 1443 /* 1444 * Get the next byte and separate the op code into the high and low nibbles. 1445 */ 1446 static int 1447 dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low) 1448 { 1449 int byte; 1450 1451 /* 1452 * x86 instructions have a maximum length of 15 bytes. Bail out if 1453 * we try to read more. 1454 */ 1455 if (x->d86_len >= 15) 1456 return (x->d86_error = 1); 1457 1458 if (x->d86_error) 1459 return (1); 1460 byte = x->d86_get_byte(x->d86_data); 1461 if (byte < 0) 1462 return (x->d86_error = 1); 1463 x->d86_bytes[x->d86_len++] = byte; 1464 *low = byte & 0xf; /* ----xxxx low 4 bits */ 1465 *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */ 1466 return (0); 1467 } 1468 1469 /* 1470 * Get and decode an SIB (scaled index base) byte 1471 */ 1472 static void 1473 dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base) 1474 { 1475 int byte; 1476 1477 if (x->d86_error) 1478 return; 1479 1480 byte = x->d86_get_byte(x->d86_data); 1481 if (byte < 0) { 1482 x->d86_error = 1; 1483 return; 1484 } 1485 x->d86_bytes[x->d86_len++] = byte; 1486 1487 *base = byte & 0x7; 1488 *index = (byte >> 3) & 0x7; 1489 *ss = (byte >> 6) & 0x3; 1490 } 1491 1492 /* 1493 * Get the byte following the op code and separate it into the 1494 * mode, register, and r/m fields. 1495 */ 1496 static void 1497 dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m) 1498 { 1499 if (x->d86_got_modrm == 0) { 1500 if (x->d86_rmindex == -1) 1501 x->d86_rmindex = x->d86_len; 1502 dtrace_get_SIB(x, mode, reg, r_m); 1503 x->d86_got_modrm = 1; 1504 } 1505 } 1506 1507 /* 1508 * Adjust register selection based on any REX prefix bits present. 1509 */ 1510 /*ARGSUSED*/ 1511 static void 1512 dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m) 1513 { 1514 if (reg != NULL && r_m == NULL) { 1515 if (rex_prefix & REX_B) 1516 *reg += 8; 1517 } else { 1518 if (reg != NULL && (REX_R & rex_prefix) != 0) 1519 *reg += 8; 1520 if (r_m != NULL && (REX_B & rex_prefix) != 0) 1521 *r_m += 8; 1522 } 1523 } 1524 1525 /* 1526 * Get an immediate operand of the given size, with sign extension. 1527 */ 1528 static void 1529 dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex) 1530 { 1531 int i; 1532 int byte; 1533 int valsize; 1534 1535 if (x->d86_numopnds < opindex + 1) 1536 x->d86_numopnds = opindex + 1; 1537 1538 switch (wbit) { 1539 case BYTE_OPND: 1540 valsize = 1; 1541 break; 1542 case LONG_OPND: 1543 if (x->d86_opnd_size == SIZE16) 1544 valsize = 2; 1545 else if (x->d86_opnd_size == SIZE32) 1546 valsize = 4; 1547 else 1548 valsize = 8; 1549 break; 1550 case MM_OPND: 1551 case XMM_OPND: 1552 case SEG_OPND: 1553 case CONTROL_OPND: 1554 case DEBUG_OPND: 1555 case TEST_OPND: 1556 valsize = size; 1557 break; 1558 case WORD_OPND: 1559 valsize = 2; 1560 break; 1561 } 1562 if (valsize < size) 1563 valsize = size; 1564 1565 if (x->d86_error) 1566 return; 1567 x->d86_opnd[opindex].d86_value = 0; 1568 for (i = 0; i < size; ++i) { 1569 byte = x->d86_get_byte(x->d86_data); 1570 if (byte < 0) { 1571 x->d86_error = 1; 1572 return; 1573 } 1574 x->d86_bytes[x->d86_len++] = byte; 1575 x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8); 1576 } 1577 /* Do sign extension */ 1578 if (x->d86_bytes[x->d86_len - 1] & 0x80) { 1579 for (; i < sizeof (uint64_t); i++) 1580 x->d86_opnd[opindex].d86_value |= 1581 (uint64_t)0xff << (i * 8); 1582 } 1583 #ifdef DIS_TEXT 1584 x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 1585 x->d86_opnd[opindex].d86_value_size = valsize; 1586 x->d86_imm_bytes += size; 1587 #endif 1588 } 1589 1590 /* 1591 * Get an ip relative operand of the given size, with sign extension. 1592 */ 1593 static void 1594 dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex) 1595 { 1596 dtrace_imm_opnd(x, wbit, size, opindex); 1597 #ifdef DIS_TEXT 1598 x->d86_opnd[opindex].d86_mode = MODE_IPREL; 1599 #endif 1600 } 1601 1602 /* 1603 * Check to see if there is a segment override prefix pending. 1604 * If so, print it in the current 'operand' location and set 1605 * the override flag back to false. 1606 */ 1607 /*ARGSUSED*/ 1608 static void 1609 dtrace_check_override(dis86_t *x, int opindex) 1610 { 1611 #ifdef DIS_TEXT 1612 if (x->d86_seg_prefix) { 1613 (void) strlcat(x->d86_opnd[opindex].d86_prefix, 1614 x->d86_seg_prefix, PFIXLEN); 1615 } 1616 #endif 1617 x->d86_seg_prefix = NULL; 1618 } 1619 1620 1621 /* 1622 * Process a single instruction Register or Memory operand. 1623 * 1624 * mode = addressing mode from ModRM byte 1625 * r_m = r_m (or reg if mode == 3) field from ModRM byte 1626 * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use. 1627 * o = index of operand that we are processing (0, 1 or 2) 1628 * 1629 * the value of reg or r_m must have already been adjusted for any REX prefix. 1630 */ 1631 /*ARGSUSED*/ 1632 static void 1633 dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) 1634 { 1635 int have_SIB = 0; /* flag presence of scale-index-byte */ 1636 uint_t ss; /* scale-factor from opcode */ 1637 uint_t index; /* index register number */ 1638 uint_t base; /* base register number */ 1639 int dispsize; /* size of displacement in bytes */ 1640 #ifdef DIS_TEXT 1641 char *opnd = x->d86_opnd[opindex].d86_opnd; 1642 #endif 1643 1644 if (x->d86_numopnds < opindex + 1) 1645 x->d86_numopnds = opindex + 1; 1646 1647 if (x->d86_error) 1648 return; 1649 1650 /* 1651 * first handle a simple register 1652 */ 1653 if (mode == REG_ONLY) { 1654 #ifdef DIS_TEXT 1655 switch (wbit) { 1656 case MM_OPND: 1657 (void) strlcat(opnd, dis_MMREG[r_m], OPLEN); 1658 break; 1659 case XMM_OPND: 1660 (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN); 1661 break; 1662 case SEG_OPND: 1663 (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN); 1664 break; 1665 case CONTROL_OPND: 1666 (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); 1667 break; 1668 case DEBUG_OPND: 1669 (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); 1670 break; 1671 case TEST_OPND: 1672 (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN); 1673 break; 1674 case BYTE_OPND: 1675 if (x->d86_rex_prefix == 0) 1676 (void) strlcat(opnd, dis_REG8[r_m], OPLEN); 1677 else 1678 (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN); 1679 break; 1680 case WORD_OPND: 1681 (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 1682 break; 1683 case LONG_OPND: 1684 if (x->d86_opnd_size == SIZE16) 1685 (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 1686 else if (x->d86_opnd_size == SIZE32) 1687 (void) strlcat(opnd, dis_REG32[r_m], OPLEN); 1688 else 1689 (void) strlcat(opnd, dis_REG64[r_m], OPLEN); 1690 break; 1691 } 1692 #endif /* DIS_TEXT */ 1693 return; 1694 } 1695 1696 /* 1697 * if symbolic representation, skip override prefix, if any 1698 */ 1699 dtrace_check_override(x, opindex); 1700 1701 /* 1702 * Handle 16 bit memory references first, since they decode 1703 * the mode values more simply. 1704 * mode 1 is r_m + 8 bit displacement 1705 * mode 2 is r_m + 16 bit displacement 1706 * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp 1707 */ 1708 if (x->d86_addr_size == SIZE16) { 1709 if ((mode == 0 && r_m == 6) || mode == 2) 1710 dtrace_imm_opnd(x, WORD_OPND, 2, opindex); 1711 else if (mode == 1) 1712 dtrace_imm_opnd(x, BYTE_OPND, 1, opindex); 1713 #ifdef DIS_TEXT 1714 if (mode == 0 && r_m == 6) 1715 x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 1716 else if (mode == 0) 1717 x->d86_opnd[opindex].d86_mode = MODE_NONE; 1718 else 1719 x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 1720 (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN); 1721 #endif 1722 return; 1723 } 1724 1725 /* 1726 * 32 and 64 bit addressing modes are more complex since they 1727 * can involve an SIB (scaled index and base) byte to decode. 1728 */ 1729 if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) { 1730 have_SIB = 1; 1731 dtrace_get_SIB(x, &ss, &index, &base); 1732 if (x->d86_error) 1733 return; 1734 if (base != 5 || mode != 0) 1735 if (x->d86_rex_prefix & REX_B) 1736 base += 8; 1737 if (x->d86_rex_prefix & REX_X) 1738 index += 8; 1739 } else { 1740 base = r_m; 1741 } 1742 1743 /* 1744 * Compute the displacement size and get its bytes 1745 */ 1746 dispsize = 0; 1747 1748 if (mode == 1) 1749 dispsize = 1; 1750 else if (mode == 2) 1751 dispsize = 4; 1752 else if ((r_m & 7) == EBP_REGNO || 1753 (have_SIB && (base & 7) == EBP_REGNO)) 1754 dispsize = 4; 1755 1756 if (dispsize > 0) { 1757 dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND, 1758 dispsize, opindex); 1759 if (x->d86_error) 1760 return; 1761 } 1762 1763 #ifdef DIS_TEXT 1764 if (dispsize > 0) 1765 x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 1766 1767 if (have_SIB == 0) { 1768 if (x->d86_mode == SIZE32) { 1769 if (mode == 0) 1770 (void) strlcat(opnd, dis_addr32_mode0[r_m], 1771 OPLEN); 1772 else 1773 (void) strlcat(opnd, dis_addr32_mode12[r_m], 1774 OPLEN); 1775 } else { 1776 if (mode == 0) { 1777 (void) strlcat(opnd, dis_addr64_mode0[r_m], 1778 OPLEN); 1779 if (r_m == 5) { 1780 x->d86_opnd[opindex].d86_mode = 1781 MODE_RIPREL; 1782 } 1783 } else { 1784 (void) strlcat(opnd, dis_addr64_mode12[r_m], 1785 OPLEN); 1786 } 1787 } 1788 } else { 1789 uint_t need_paren = 0; 1790 char **regs; 1791 if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */ 1792 regs = (char **)dis_REG32; 1793 else 1794 regs = (char **)dis_REG64; 1795 1796 /* 1797 * print the base (if any) 1798 */ 1799 if (base == EBP_REGNO && mode == 0) { 1800 if (index != ESP_REGNO) { 1801 (void) strlcat(opnd, "(", OPLEN); 1802 need_paren = 1; 1803 } 1804 } else { 1805 (void) strlcat(opnd, "(", OPLEN); 1806 (void) strlcat(opnd, regs[base], OPLEN); 1807 need_paren = 1; 1808 } 1809 1810 /* 1811 * print the index (if any) 1812 */ 1813 if (index != ESP_REGNO) { 1814 (void) strlcat(opnd, ",", OPLEN); 1815 (void) strlcat(opnd, regs[index], OPLEN); 1816 (void) strlcat(opnd, dis_scale_factor[ss], OPLEN); 1817 } else 1818 if (need_paren) 1819 (void) strlcat(opnd, ")", OPLEN); 1820 } 1821 #endif 1822 } 1823 1824 /* 1825 * Operand sequence for standard instruction involving one register 1826 * and one register/memory operand. 1827 * wbit indicates a byte(0) or opnd_size(1) operation 1828 * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r") 1829 */ 1830 #define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \ 1831 dtrace_get_modrm(x, &mode, ®, &r_m); \ 1832 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 1833 dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 1834 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \ 1835 } 1836 1837 /* 1838 * Similar to above, but allows for the two operands to be of different 1839 * classes (ie. wbit). 1840 * wbit is for the r_m operand 1841 * w2 is for the reg operand 1842 */ 1843 #define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \ 1844 dtrace_get_modrm(x, &mode, ®, &r_m); \ 1845 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 1846 dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 1847 dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \ 1848 } 1849 1850 /* 1851 * Similar, but for 2 operands plus an immediate. 1852 * vbit indicates direction 1853 * 0 for "opcode imm, r, r_m" or 1854 * 1 for "opcode imm, r_m, r" 1855 */ 1856 #define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \ 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, 2-vbit); \ 1860 dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \ 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 opnd_size; /* SIZE16, SIZE32 or SIZE64 */ 1909 uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */ 1910 uint_t wbit; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */ 1911 uint_t w2; /* wbit value for second operand */ 1912 uint_t vbit; 1913 uint_t mode = 0; /* mode value from ModRM byte */ 1914 uint_t reg; /* reg value from ModRM byte */ 1915 uint_t r_m; /* r_m value from ModRM byte */ 1916 1917 uint_t opcode1; /* high nibble of 1st byte */ 1918 uint_t opcode2; /* low nibble of 1st byte */ 1919 uint_t opcode3; /* extra opcode bits usually from ModRM byte */ 1920 uint_t opcode4; /* high nibble of 2nd byte */ 1921 uint_t opcode5; /* low nibble of 2nd byte */ 1922 uint_t opcode6; /* high nibble of 3rd byte */ 1923 uint_t opcode7; /* low nibble of 3rd byte */ 1924 uint_t opcode_bytes = 1; 1925 1926 /* 1927 * legacy prefixes come in 5 flavors, you should have only one of each 1928 */ 1929 uint_t opnd_size_prefix = 0; 1930 uint_t addr_size_prefix = 0; 1931 uint_t segment_prefix = 0; 1932 uint_t lock_prefix = 0; 1933 uint_t rep_prefix = 0; 1934 uint_t rex_prefix = 0; /* amd64 register extension prefix */ 1935 size_t off; 1936 1937 instable_t dp_mmx; 1938 1939 x->d86_len = 0; 1940 x->d86_rmindex = -1; 1941 x->d86_error = 0; 1942 #ifdef DIS_TEXT 1943 x->d86_numopnds = 0; 1944 x->d86_seg_prefix = NULL; 1945 x->d86_mnem[0] = 0; 1946 for (i = 0; i < 4; ++i) { 1947 x->d86_opnd[i].d86_opnd[0] = 0; 1948 x->d86_opnd[i].d86_prefix[0] = 0; 1949 x->d86_opnd[i].d86_value_size = 0; 1950 x->d86_opnd[i].d86_value = 0; 1951 x->d86_opnd[i].d86_mode = MODE_NONE; 1952 } 1953 #endif 1954 x->d86_error = 0; 1955 x->d86_memsize = 0; 1956 1957 if (cpu_mode == SIZE16) { 1958 opnd_size = SIZE16; 1959 addr_size = SIZE16; 1960 } else if (cpu_mode == SIZE32) { 1961 opnd_size = SIZE32; 1962 addr_size = SIZE32; 1963 } else { 1964 opnd_size = SIZE32; 1965 addr_size = SIZE64; 1966 } 1967 1968 /* 1969 * Get one opcode byte and check for zero padding that follows 1970 * jump tables. 1971 */ 1972 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 1973 goto error; 1974 1975 if (opcode1 == 0 && opcode2 == 0 && 1976 x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) { 1977 #ifdef DIS_TEXT 1978 (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN); 1979 #endif 1980 goto done; 1981 } 1982 1983 /* 1984 * Gather up legacy x86 prefix bytes. 1985 */ 1986 for (;;) { 1987 uint_t *which_prefix = NULL; 1988 1989 dp = (instable_t *)&dis_distable[opcode1][opcode2]; 1990 1991 switch (dp->it_adrmode) { 1992 case PREFIX: 1993 which_prefix = &rep_prefix; 1994 break; 1995 case LOCK: 1996 which_prefix = &lock_prefix; 1997 break; 1998 case OVERRIDE: 1999 which_prefix = &segment_prefix; 2000 #ifdef DIS_TEXT 2001 x->d86_seg_prefix = (char *)dp->it_name; 2002 #endif 2003 if (dp->it_invalid64 && cpu_mode == SIZE64) 2004 goto error; 2005 break; 2006 case AM: 2007 which_prefix = &addr_size_prefix; 2008 break; 2009 case DM: 2010 which_prefix = &opnd_size_prefix; 2011 break; 2012 } 2013 if (which_prefix == NULL) 2014 break; 2015 *which_prefix = (opcode1 << 4) | opcode2; 2016 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2017 goto error; 2018 } 2019 2020 /* 2021 * Handle amd64 mode PREFIX values. 2022 * Some of the segment prefixes are no-ops. (only FS/GS actually work) 2023 * We might have a REX prefix (opcodes 0x40-0x4f) 2024 */ 2025 if (cpu_mode == SIZE64) { 2026 if (segment_prefix != 0x64 && segment_prefix != 0x65) 2027 segment_prefix = 0; 2028 2029 if (opcode1 == 0x4) { 2030 rex_prefix = (opcode1 << 4) | opcode2; 2031 if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2032 goto error; 2033 dp = (instable_t *)&dis_distable[opcode1][opcode2]; 2034 } 2035 } 2036 2037 /* 2038 * Deal with selection of operand and address size now. 2039 * Note that the REX.W bit being set causes opnd_size_prefix to be 2040 * ignored. 2041 */ 2042 if (cpu_mode == SIZE64) { 2043 if (rex_prefix & REX_W) 2044 opnd_size = SIZE64; 2045 else if (opnd_size_prefix) 2046 opnd_size = SIZE16; 2047 2048 if (addr_size_prefix) 2049 addr_size = SIZE32; 2050 } else if (cpu_mode == SIZE32) { 2051 if (opnd_size_prefix) 2052 opnd_size = SIZE16; 2053 if (addr_size_prefix) 2054 addr_size = SIZE16; 2055 } else { 2056 if (opnd_size_prefix) 2057 opnd_size = SIZE32; 2058 if (addr_size_prefix) 2059 addr_size = SIZE32; 2060 } 2061 2062 /* 2063 * The pause instruction - a repz'd nop. This doesn't fit 2064 * with any of the other prefix goop added for SSE, so we'll 2065 * special-case it here. 2066 */ 2067 if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) { 2068 rep_prefix = 0; 2069 dp = (instable_t *)&dis_opPause; 2070 } 2071 2072 /* 2073 * Some 386 instructions have 2 bytes of opcode before the mod_r/m 2074 * byte so we may need to perform a table indirection. 2075 */ 2076 if (dp->it_indirect == (instable_t *)dis_op0F) { 2077 if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0) 2078 goto error; 2079 opcode_bytes = 2; 2080 if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) { 2081 uint_t subcode; 2082 2083 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 2084 goto error; 2085 opcode_bytes = 3; 2086 subcode = ((opcode6 & 0x3) << 1) | 2087 ((opcode7 & 0x8) >> 3); 2088 dp = (instable_t *)&dis_op0F7123[opcode5][subcode]; 2089 } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) { 2090 dp = (instable_t *)&dis_op0FC8[0]; 2091 } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) { 2092 opcode_bytes = 3; 2093 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 2094 goto error; 2095 if (opnd_size == SIZE16) 2096 opnd_size = SIZE32; 2097 2098 dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7]; 2099 #ifdef DIS_TEXT 2100 if (strcmp(dp->it_name, "INVALID") == 0) 2101 goto error; 2102 #endif 2103 switch (dp->it_adrmode) { 2104 case XMMP_66r: 2105 case XMMPRM_66r: 2106 case XMM3PM_66r: 2107 if (opnd_size_prefix == 0) { 2108 goto error; 2109 } 2110 break; 2111 case XMMP_66o: 2112 if (opnd_size_prefix == 0) { 2113 /* SSSE3 MMX instructions */ 2114 dp_mmx = *dp; 2115 dp = &dp_mmx; 2116 dp->it_adrmode = MMOPM_66o; 2117 #ifdef DIS_MEM 2118 dp->it_size = 8; 2119 #endif 2120 } 2121 break; 2122 default: 2123 goto error; 2124 } 2125 } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) { 2126 opcode_bytes = 3; 2127 if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 2128 goto error; 2129 dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7]; 2130 #ifdef DIS_TEXT 2131 if (strcmp(dp->it_name, "INVALID") == 0) 2132 goto error; 2133 #endif 2134 switch (dp->it_adrmode) { 2135 case XMM_66r: 2136 case XMMM_66r: 2137 if (opnd_size_prefix == 0) { 2138 goto error; 2139 } 2140 break; 2141 case XMM_66o: 2142 if (opnd_size_prefix == 0) { 2143 /* SSSE3 MMX instructions */ 2144 dp_mmx = *dp; 2145 dp = &dp_mmx; 2146 dp->it_adrmode = MM; 2147 #ifdef DIS_MEM 2148 dp->it_size = 8; 2149 #endif 2150 } 2151 break; 2152 case CRC32: 2153 if (rep_prefix != 0xF2) { 2154 goto error; 2155 } 2156 rep_prefix = 0; 2157 break; 2158 default: 2159 goto error; 2160 } 2161 } else { 2162 dp = (instable_t *)&dis_op0F[opcode4][opcode5]; 2163 } 2164 } 2165 2166 /* 2167 * If still not at a TERM decode entry, then a ModRM byte 2168 * exists and its fields further decode the instruction. 2169 */ 2170 x->d86_got_modrm = 0; 2171 if (dp->it_indirect != TERM) { 2172 dtrace_get_modrm(x, &mode, &opcode3, &r_m); 2173 if (x->d86_error) 2174 goto error; 2175 reg = opcode3; 2176 2177 /* 2178 * decode 287 instructions (D8-DF) from opcodeN 2179 */ 2180 if (opcode1 == 0xD && opcode2 >= 0x8) { 2181 if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4) 2182 dp = (instable_t *)&dis_opFP5[r_m]; 2183 else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4) 2184 dp = (instable_t *)&dis_opFP7[opcode3]; 2185 else if (opcode2 == 0xB && mode == 0x3) 2186 dp = (instable_t *)&dis_opFP6[opcode3]; 2187 else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4) 2188 dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m]; 2189 else if (mode == 0x3) 2190 dp = (instable_t *) 2191 &dis_opFP3[opcode2 - 8][opcode3]; 2192 else 2193 dp = (instable_t *) 2194 &dis_opFP1n2[opcode2 - 8][opcode3]; 2195 } else { 2196 dp = (instable_t *)dp->it_indirect + opcode3; 2197 } 2198 } 2199 2200 /* 2201 * In amd64 bit mode, ARPL opcode is changed to MOVSXD 2202 * (sign extend 32bit to 64 bit) 2203 */ 2204 if (cpu_mode == SIZE64 && opcode1 == 0x6 && opcode2 == 0x3) 2205 dp = (instable_t *)&dis_opMOVSLD; 2206 2207 /* 2208 * at this point we should have a correct (or invalid) opcode 2209 */ 2210 if (cpu_mode == SIZE64 && dp->it_invalid64 || 2211 cpu_mode != SIZE64 && dp->it_invalid32) 2212 goto error; 2213 if (dp->it_indirect != TERM) 2214 goto error; 2215 2216 /* 2217 * deal with MMX/SSE opcodes which are changed by prefixes 2218 */ 2219 switch (dp->it_adrmode) { 2220 case MMO: 2221 case MMOIMPL: 2222 case MMO3P: 2223 case MMOM3: 2224 case MMOMS: 2225 case MMOPM: 2226 case MMOPRM: 2227 case MMOS: 2228 case XMMO: 2229 case XMMOM: 2230 case XMMOMS: 2231 case XMMOPM: 2232 case XMMOS: 2233 case XMMOMX: 2234 case XMMOX3: 2235 case XMMOXMM: 2236 /* 2237 * This is horrible. Some SIMD instructions take the 2238 * form 0x0F 0x?? ..., which is easily decoded using the 2239 * existing tables. Other SIMD instructions use various 2240 * prefix bytes to overload existing instructions. For 2241 * Example, addps is F0, 58, whereas addss is F3 (repz), 2242 * F0, 58. Presumably someone got a raise for this. 2243 * 2244 * If we see one of the instructions which can be 2245 * modified in this way (if we've got one of the SIMDO* 2246 * address modes), we'll check to see if the last prefix 2247 * was a repz. If it was, we strip the prefix from the 2248 * mnemonic, and we indirect using the dis_opSIMDrepz 2249 * table. 2250 */ 2251 2252 /* 2253 * Calculate our offset in dis_op0F 2254 */ 2255 if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F)) 2256 goto error; 2257 2258 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 2259 sizeof (instable_t); 2260 2261 /* 2262 * Rewrite if this instruction used one of the magic prefixes. 2263 */ 2264 if (rep_prefix) { 2265 if (rep_prefix == 0xf2) 2266 dp = (instable_t *)&dis_opSIMDrepnz[off]; 2267 else 2268 dp = (instable_t *)&dis_opSIMDrepz[off]; 2269 rep_prefix = 0; 2270 } else if (opnd_size_prefix) { 2271 dp = (instable_t *)&dis_opSIMDdata16[off]; 2272 opnd_size_prefix = 0; 2273 if (opnd_size == SIZE16) 2274 opnd_size = SIZE32; 2275 } 2276 break; 2277 2278 case MMOSH: 2279 /* 2280 * As with the "normal" SIMD instructions, the MMX 2281 * shuffle instructions are overloaded. These 2282 * instructions, however, are special in that they use 2283 * an extra byte, and thus an extra table. As of this 2284 * writing, they only use the opnd_size prefix. 2285 */ 2286 2287 /* 2288 * Calculate our offset in dis_op0F7123 2289 */ 2290 if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 > 2291 sizeof (dis_op0F7123)) 2292 goto error; 2293 2294 if (opnd_size_prefix) { 2295 off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) / 2296 sizeof (instable_t); 2297 dp = (instable_t *)&dis_opSIMD7123[off]; 2298 opnd_size_prefix = 0; 2299 if (opnd_size == SIZE16) 2300 opnd_size = SIZE32; 2301 } 2302 break; 2303 case MRw: 2304 if (rep_prefix) { 2305 if (rep_prefix == 0xf3) { 2306 2307 /* 2308 * Calculate our offset in dis_op0F 2309 */ 2310 if ((uintptr_t)dp - (uintptr_t)dis_op0F 2311 > sizeof (dis_op0F)) 2312 goto error; 2313 2314 off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 2315 sizeof (instable_t); 2316 2317 dp = (instable_t *)&dis_opSIMDrepz[off]; 2318 rep_prefix = 0; 2319 } else { 2320 goto error; 2321 } 2322 } 2323 break; 2324 } 2325 2326 /* 2327 * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64. 2328 */ 2329 if (cpu_mode == SIZE64) 2330 if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop)) 2331 opnd_size = SIZE64; 2332 2333 #ifdef DIS_TEXT 2334 /* 2335 * At this point most instructions can format the opcode mnemonic 2336 * including the prefixes. 2337 */ 2338 if (lock_prefix) 2339 (void) strlcat(x->d86_mnem, "lock ", OPLEN); 2340 2341 if (rep_prefix == 0xf2) 2342 (void) strlcat(x->d86_mnem, "repnz ", OPLEN); 2343 else if (rep_prefix == 0xf3) 2344 (void) strlcat(x->d86_mnem, "repz ", OPLEN); 2345 2346 if (cpu_mode == SIZE64 && addr_size_prefix) 2347 (void) strlcat(x->d86_mnem, "addr32 ", OPLEN); 2348 2349 if (dp->it_adrmode != CBW && 2350 dp->it_adrmode != CWD && 2351 dp->it_adrmode != XMMSFNC) { 2352 if (strcmp(dp->it_name, "INVALID") == 0) 2353 goto error; 2354 (void) strlcat(x->d86_mnem, dp->it_name, OPLEN); 2355 if (dp->it_suffix) { 2356 char *types[] = {"", "w", "l", "q"}; 2357 if (opcode_bytes == 2 && opcode4 == 4) { 2358 /* It's a cmovx.yy. Replace the suffix x */ 2359 for (i = 5; i < OPLEN; i++) { 2360 if (x->d86_mnem[i] == '.') 2361 break; 2362 } 2363 x->d86_mnem[i - 1] = *types[opnd_size]; 2364 } else if ((opnd_size == 2) && (opcode_bytes == 3) && 2365 ((opcode6 == 1 && opcode7 == 6) || 2366 (opcode6 == 2 && opcode7 == 2))) { 2367 /* 2368 * To handle PINSRD and PEXTRD 2369 */ 2370 (void) strlcat(x->d86_mnem, "d", OPLEN); 2371 } else { 2372 (void) strlcat(x->d86_mnem, types[opnd_size], 2373 OPLEN); 2374 } 2375 } 2376 } 2377 #endif 2378 2379 /* 2380 * Process operands based on the addressing modes. 2381 */ 2382 x->d86_mode = cpu_mode; 2383 x->d86_rex_prefix = rex_prefix; 2384 x->d86_opnd_size = opnd_size; 2385 x->d86_addr_size = addr_size; 2386 vbit = 0; /* initialize for mem/reg -> reg */ 2387 switch (dp->it_adrmode) { 2388 /* 2389 * amd64 instruction to sign extend 32 bit reg/mem operands 2390 * into 64 bit register values 2391 */ 2392 case MOVSXZ: 2393 #ifdef DIS_TEXT 2394 if (rex_prefix == 0) 2395 (void) strncpy(x->d86_mnem, "movzld", OPLEN); 2396 #endif 2397 dtrace_get_modrm(x, &mode, ®, &r_m); 2398 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2399 x->d86_opnd_size = SIZE64; 2400 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2401 x->d86_opnd_size = opnd_size = SIZE32; 2402 wbit = LONG_OPND; 2403 dtrace_get_operand(x, mode, r_m, wbit, 0); 2404 break; 2405 2406 /* 2407 * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF) 2408 * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7) 2409 * wbit lives in 2nd byte, note that operands 2410 * are different sized 2411 */ 2412 case MOVZ: 2413 if (rex_prefix & REX_W) { 2414 /* target register size = 64 bit */ 2415 x->d86_mnem[5] = 'q'; 2416 } 2417 dtrace_get_modrm(x, &mode, ®, &r_m); 2418 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2419 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2420 x->d86_opnd_size = opnd_size = SIZE16; 2421 wbit = WBIT(opcode5); 2422 dtrace_get_operand(x, mode, r_m, wbit, 0); 2423 break; 2424 case CRC32: 2425 opnd_size = SIZE32; 2426 if (rex_prefix & REX_W) 2427 opnd_size = SIZE64; 2428 x->d86_opnd_size = opnd_size; 2429 2430 dtrace_get_modrm(x, &mode, ®, &r_m); 2431 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2432 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2433 wbit = WBIT(opcode7); 2434 if (opnd_size_prefix) 2435 x->d86_opnd_size = opnd_size = SIZE16; 2436 dtrace_get_operand(x, mode, r_m, wbit, 0); 2437 break; 2438 2439 /* 2440 * imul instruction, with either 8-bit or longer immediate 2441 * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s) 2442 */ 2443 case IMUL: 2444 wbit = LONG_OPND; 2445 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 2446 OPSIZE(opnd_size, opcode2 == 0x9), 1); 2447 break; 2448 2449 /* memory or register operand to register, with 'w' bit */ 2450 case MRw: 2451 wbit = WBIT(opcode2); 2452 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 2453 break; 2454 2455 /* register to memory or register operand, with 'w' bit */ 2456 /* arpl happens to fit here also because it is odd */ 2457 case RMw: 2458 if (opcode_bytes == 2) 2459 wbit = WBIT(opcode5); 2460 else 2461 wbit = WBIT(opcode2); 2462 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2463 break; 2464 2465 /* xaddb instruction */ 2466 case XADDB: 2467 wbit = 0; 2468 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2469 break; 2470 2471 /* MMX register to memory or register operand */ 2472 case MMS: 2473 case MMOS: 2474 #ifdef DIS_TEXT 2475 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 2476 #else 2477 wbit = LONG_OPND; 2478 #endif 2479 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 2480 break; 2481 2482 /* MMX register to memory */ 2483 case MMOMS: 2484 dtrace_get_modrm(x, &mode, ®, &r_m); 2485 if (mode == REG_ONLY) 2486 goto error; 2487 wbit = MM_OPND; 2488 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 2489 break; 2490 2491 /* Double shift. Has immediate operand specifying the shift. */ 2492 case DSHIFT: 2493 wbit = LONG_OPND; 2494 dtrace_get_modrm(x, &mode, ®, &r_m); 2495 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2496 dtrace_get_operand(x, mode, r_m, wbit, 2); 2497 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2498 dtrace_imm_opnd(x, wbit, 1, 0); 2499 break; 2500 2501 /* 2502 * Double shift. With no immediate operand, specifies using %cl. 2503 */ 2504 case DSHIFTcl: 2505 wbit = LONG_OPND; 2506 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2507 break; 2508 2509 /* immediate to memory or register operand */ 2510 case IMlw: 2511 wbit = WBIT(opcode2); 2512 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2513 dtrace_get_operand(x, mode, r_m, wbit, 1); 2514 /* 2515 * Have long immediate for opcode 0x81, but not 0x80 nor 0x83 2516 */ 2517 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0); 2518 break; 2519 2520 /* immediate to memory or register operand with the */ 2521 /* 'w' bit present */ 2522 case IMw: 2523 wbit = WBIT(opcode2); 2524 dtrace_get_modrm(x, &mode, ®, &r_m); 2525 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2526 dtrace_get_operand(x, mode, r_m, wbit, 1); 2527 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 2528 break; 2529 2530 /* immediate to register with register in low 3 bits */ 2531 /* of op code */ 2532 case IR: 2533 /* w-bit here (with regs) is bit 3 */ 2534 wbit = opcode2 >>3 & 0x1; 2535 reg = REGNO(opcode2); 2536 dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2537 mode = REG_ONLY; 2538 r_m = reg; 2539 dtrace_get_operand(x, mode, r_m, wbit, 1); 2540 dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0); 2541 break; 2542 2543 /* MMX immediate shift of register */ 2544 case MMSH: 2545 case MMOSH: 2546 wbit = MM_OPND; 2547 goto mm_shift; /* in next case */ 2548 2549 /* SIMD immediate shift of register */ 2550 case XMMSH: 2551 wbit = XMM_OPND; 2552 mm_shift: 2553 reg = REGNO(opcode7); 2554 dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2555 dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 2556 dtrace_imm_opnd(x, wbit, 1, 0); 2557 NOMEM; 2558 break; 2559 2560 /* accumulator to memory operand */ 2561 case AO: 2562 vbit = 1; 2563 /*FALLTHROUGH*/ 2564 2565 /* memory operand to accumulator */ 2566 case OA: 2567 wbit = WBIT(opcode2); 2568 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit); 2569 dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit); 2570 #ifdef DIS_TEXT 2571 x->d86_opnd[vbit].d86_mode = MODE_OFFSET; 2572 #endif 2573 break; 2574 2575 2576 /* segment register to memory or register operand */ 2577 case SM: 2578 vbit = 1; 2579 /*FALLTHROUGH*/ 2580 2581 /* memory or register operand to segment register */ 2582 case MS: 2583 dtrace_get_modrm(x, &mode, ®, &r_m); 2584 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2585 dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit); 2586 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit); 2587 break; 2588 2589 /* 2590 * rotate or shift instructions, which may shift by 1 or 2591 * consult the cl register, depending on the 'v' bit 2592 */ 2593 case Mv: 2594 vbit = VBIT(opcode2); 2595 wbit = WBIT(opcode2); 2596 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2597 dtrace_get_operand(x, mode, r_m, wbit, 1); 2598 #ifdef DIS_TEXT 2599 if (vbit) { 2600 (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); 2601 } else { 2602 x->d86_opnd[0].d86_mode = MODE_SIGNED; 2603 x->d86_opnd[0].d86_value_size = 1; 2604 x->d86_opnd[0].d86_value = 1; 2605 } 2606 #endif 2607 break; 2608 /* 2609 * immediate rotate or shift instructions 2610 */ 2611 case MvI: 2612 wbit = WBIT(opcode2); 2613 normal_imm_mem: 2614 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2615 dtrace_get_operand(x, mode, r_m, wbit, 1); 2616 dtrace_imm_opnd(x, wbit, 1, 0); 2617 break; 2618 2619 /* bit test instructions */ 2620 case MIb: 2621 wbit = LONG_OPND; 2622 goto normal_imm_mem; 2623 2624 /* single memory or register operand with 'w' bit present */ 2625 case Mw: 2626 wbit = WBIT(opcode2); 2627 just_mem: 2628 dtrace_get_modrm(x, &mode, ®, &r_m); 2629 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2630 dtrace_get_operand(x, mode, r_m, wbit, 0); 2631 break; 2632 2633 case SWAPGS: 2634 if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) { 2635 #ifdef DIS_TEXT 2636 (void) strncpy(x->d86_mnem, "swapgs", OPLEN); 2637 #endif 2638 NOMEM; 2639 break; 2640 } 2641 /*FALLTHROUGH*/ 2642 2643 /* prefetch instruction - memory operand, but no memory acess */ 2644 case PREF: 2645 NOMEM; 2646 /*FALLTHROUGH*/ 2647 2648 /* single memory or register operand */ 2649 case M: 2650 wbit = LONG_OPND; 2651 goto just_mem; 2652 2653 /* single memory or register byte operand */ 2654 case Mb: 2655 wbit = BYTE_OPND; 2656 goto just_mem; 2657 2658 case MONITOR_MWAIT: 2659 if (mode == 3) { 2660 if (r_m == 0) { 2661 #ifdef DIS_TEXT 2662 (void) strncpy(x->d86_mnem, "monitor", OPLEN); 2663 #endif 2664 NOMEM; 2665 break; 2666 } else if (r_m == 1) { 2667 #ifdef DIS_TEXT 2668 (void) strncpy(x->d86_mnem, "mwait", OPLEN); 2669 #endif 2670 NOMEM; 2671 break; 2672 } else { 2673 goto error; 2674 } 2675 } 2676 /*FALLTHROUGH*/ 2677 2678 case MO: 2679 /* Similar to M, but only memory (no direct registers) */ 2680 wbit = LONG_OPND; 2681 dtrace_get_modrm(x, &mode, ®, &r_m); 2682 if (mode == 3) 2683 goto error; 2684 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2685 dtrace_get_operand(x, mode, r_m, wbit, 0); 2686 break; 2687 2688 /* move special register to register or reverse if vbit */ 2689 case SREG: 2690 switch (opcode5) { 2691 2692 case 2: 2693 vbit = 1; 2694 /*FALLTHROUGH*/ 2695 case 0: 2696 wbit = CONTROL_OPND; 2697 break; 2698 2699 case 3: 2700 vbit = 1; 2701 /*FALLTHROUGH*/ 2702 case 1: 2703 wbit = DEBUG_OPND; 2704 break; 2705 2706 case 6: 2707 vbit = 1; 2708 /*FALLTHROUGH*/ 2709 case 4: 2710 wbit = TEST_OPND; 2711 break; 2712 2713 } 2714 dtrace_get_modrm(x, &mode, ®, &r_m); 2715 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2716 dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit); 2717 dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit); 2718 NOMEM; 2719 break; 2720 2721 /* 2722 * single register operand with register in the low 3 2723 * bits of op code 2724 */ 2725 case R: 2726 if (opcode_bytes == 2) 2727 reg = REGNO(opcode5); 2728 else 2729 reg = REGNO(opcode2); 2730 dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2731 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 2732 NOMEM; 2733 break; 2734 2735 /* 2736 * register to accumulator with register in the low 3 2737 * bits of op code, xchg instructions 2738 */ 2739 case RA: 2740 NOMEM; 2741 reg = REGNO(opcode2); 2742 dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2743 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 2744 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1); 2745 break; 2746 2747 /* 2748 * single segment register operand, with register in 2749 * bits 3-4 of op code byte 2750 */ 2751 case SEG: 2752 NOMEM; 2753 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3; 2754 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 2755 break; 2756 2757 /* 2758 * single segment register operand, with register in 2759 * bits 3-5 of op code 2760 */ 2761 case LSEG: 2762 NOMEM; 2763 /* long seg reg from opcode */ 2764 reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7; 2765 dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 2766 break; 2767 2768 /* memory or register operand to register */ 2769 case MR: 2770 wbit = LONG_OPND; 2771 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 2772 break; 2773 2774 case RM: 2775 wbit = LONG_OPND; 2776 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2777 break; 2778 2779 /* MMX/SIMD-Int memory or mm reg to mm reg */ 2780 case MM: 2781 case MMO: 2782 #ifdef DIS_TEXT 2783 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 2784 #else 2785 wbit = LONG_OPND; 2786 #endif 2787 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 2788 break; 2789 2790 case MMOIMPL: 2791 #ifdef DIS_TEXT 2792 wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 2793 #else 2794 wbit = LONG_OPND; 2795 #endif 2796 dtrace_get_modrm(x, &mode, ®, &r_m); 2797 if (mode != REG_ONLY) 2798 goto error; 2799 2800 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2801 dtrace_get_operand(x, mode, r_m, wbit, 0); 2802 dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1); 2803 mode = 0; /* change for memory access size... */ 2804 break; 2805 2806 /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */ 2807 case MMO3P: 2808 wbit = MM_OPND; 2809 goto xmm3p; 2810 case XMM3P: 2811 wbit = XMM_OPND; 2812 xmm3p: 2813 dtrace_get_modrm(x, &mode, ®, &r_m); 2814 if (mode != REG_ONLY) 2815 goto error; 2816 2817 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1, 2818 1); 2819 NOMEM; 2820 break; 2821 2822 case XMM3PM_66r: 2823 THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND, 2824 1, 0); 2825 break; 2826 2827 /* MMX/SIMD-Int predicated r32/mem to mm reg */ 2828 case MMOPRM: 2829 wbit = LONG_OPND; 2830 w2 = MM_OPND; 2831 goto xmmprm; 2832 case XMMPRM: 2833 case XMMPRM_66r: 2834 wbit = LONG_OPND; 2835 w2 = XMM_OPND; 2836 xmmprm: 2837 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1); 2838 break; 2839 2840 /* MMX/SIMD-Int predicated mm/mem to mm reg */ 2841 case MMOPM: 2842 case MMOPM_66o: 2843 wbit = w2 = MM_OPND; 2844 goto xmmprm; 2845 2846 /* MMX/SIMD-Int mm reg to r32 */ 2847 case MMOM3: 2848 NOMEM; 2849 dtrace_get_modrm(x, &mode, ®, &r_m); 2850 if (mode != REG_ONLY) 2851 goto error; 2852 wbit = MM_OPND; 2853 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 2854 break; 2855 2856 /* SIMD memory or xmm reg operand to xmm reg */ 2857 case XMM: 2858 case XMM_66o: 2859 case XMM_66r: 2860 case XMMO: 2861 case XMMXIMPL: 2862 wbit = XMM_OPND; 2863 STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 2864 2865 if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY) 2866 goto error; 2867 2868 #ifdef DIS_TEXT 2869 /* 2870 * movlps and movhlps share opcodes. They differ in the 2871 * addressing modes allowed for their operands. 2872 * movhps and movlhps behave similarly. 2873 */ 2874 if (mode == REG_ONLY) { 2875 if (strcmp(dp->it_name, "movlps") == 0) 2876 (void) strncpy(x->d86_mnem, "movhlps", OPLEN); 2877 else if (strcmp(dp->it_name, "movhps") == 0) 2878 (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 2879 } 2880 #endif 2881 if (dp->it_adrmode == XMMXIMPL) 2882 mode = 0; /* change for memory access size... */ 2883 break; 2884 2885 /* SIMD xmm reg to memory or xmm reg */ 2886 case XMMS: 2887 case XMMOS: 2888 case XMMMS: 2889 case XMMOMS: 2890 dtrace_get_modrm(x, &mode, ®, &r_m); 2891 #ifdef DIS_TEXT 2892 if ((strcmp(dp->it_name, "movlps") == 0 || 2893 strcmp(dp->it_name, "movhps") == 0 || 2894 strcmp(dp->it_name, "movntps") == 0) && 2895 mode == REG_ONLY) 2896 goto error; 2897 #endif 2898 wbit = XMM_OPND; 2899 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 2900 break; 2901 2902 /* SIMD memory to xmm reg */ 2903 case XMMM: 2904 case XMMM_66r: 2905 case XMMOM: 2906 wbit = XMM_OPND; 2907 dtrace_get_modrm(x, &mode, ®, &r_m); 2908 #ifdef DIS_TEXT 2909 if (mode == REG_ONLY) { 2910 if (strcmp(dp->it_name, "movhps") == 0) 2911 (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 2912 else 2913 goto error; 2914 } 2915 #endif 2916 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 2917 break; 2918 2919 /* SIMD memory or r32 to xmm reg */ 2920 case XMM3MX: 2921 wbit = LONG_OPND; 2922 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 2923 break; 2924 2925 case XMM3MXS: 2926 wbit = LONG_OPND; 2927 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 2928 break; 2929 2930 /* SIMD memory or mm reg to xmm reg */ 2931 case XMMOMX: 2932 /* SIMD mm to xmm */ 2933 case XMMMX: 2934 wbit = MM_OPND; 2935 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 2936 break; 2937 2938 /* SIMD memory or xmm reg to mm reg */ 2939 case XMMXMM: 2940 case XMMOXMM: 2941 case XMMXM: 2942 wbit = XMM_OPND; 2943 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 2944 break; 2945 2946 2947 /* SIMD memory or xmm reg to r32 */ 2948 case XMMXM3: 2949 wbit = XMM_OPND; 2950 MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 2951 break; 2952 2953 /* SIMD xmm to r32 */ 2954 case XMMX3: 2955 case XMMOX3: 2956 dtrace_get_modrm(x, &mode, ®, &r_m); 2957 if (mode != REG_ONLY) 2958 goto error; 2959 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2960 dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 2961 dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2962 NOMEM; 2963 break; 2964 2965 /* SIMD predicated memory or xmm reg with/to xmm reg */ 2966 case XMMP: 2967 case XMMP_66r: 2968 case XMMP_66o: 2969 case XMMOPM: 2970 wbit = XMM_OPND; 2971 THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1, 2972 1); 2973 2974 #ifdef DIS_TEXT 2975 /* 2976 * cmpps and cmpss vary their instruction name based 2977 * on the value of imm8. Other XMMP instructions, 2978 * such as shufps, require explicit specification of 2979 * the predicate. 2980 */ 2981 if (dp->it_name[0] == 'c' && 2982 dp->it_name[1] == 'm' && 2983 dp->it_name[2] == 'p' && 2984 strlen(dp->it_name) == 5) { 2985 uchar_t pred = x->d86_opnd[0].d86_value & 0xff; 2986 2987 if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *))) 2988 goto error; 2989 2990 (void) strncpy(x->d86_mnem, "cmp", OPLEN); 2991 (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred], 2992 OPLEN); 2993 (void) strlcat(x->d86_mnem, 2994 dp->it_name + strlen(dp->it_name) - 2, 2995 OPLEN); 2996 x->d86_opnd[0] = x->d86_opnd[1]; 2997 x->d86_opnd[1] = x->d86_opnd[2]; 2998 x->d86_numopnds = 2; 2999 } 3000 #endif 3001 break; 3002 3003 case XMMX2I: 3004 FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND, 3005 1); 3006 NOMEM; 3007 break; 3008 3009 case XMM2I: 3010 ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1); 3011 NOMEM; 3012 break; 3013 3014 /* immediate operand to accumulator */ 3015 case IA: 3016 wbit = WBIT(opcode2); 3017 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 3018 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 3019 NOMEM; 3020 break; 3021 3022 /* memory or register operand to accumulator */ 3023 case MA: 3024 wbit = WBIT(opcode2); 3025 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3026 dtrace_get_operand(x, mode, r_m, wbit, 0); 3027 break; 3028 3029 /* si register to di register used to reference memory */ 3030 case SD: 3031 #ifdef DIS_TEXT 3032 dtrace_check_override(x, 0); 3033 x->d86_numopnds = 2; 3034 if (addr_size == SIZE64) { 3035 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 3036 OPLEN); 3037 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 3038 OPLEN); 3039 } else if (addr_size == SIZE32) { 3040 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 3041 OPLEN); 3042 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 3043 OPLEN); 3044 } else { 3045 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 3046 OPLEN); 3047 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 3048 OPLEN); 3049 } 3050 #endif 3051 wbit = LONG_OPND; 3052 break; 3053 3054 /* accumulator to di register */ 3055 case AD: 3056 wbit = WBIT(opcode2); 3057 #ifdef DIS_TEXT 3058 dtrace_check_override(x, 1); 3059 x->d86_numopnds = 2; 3060 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0); 3061 if (addr_size == SIZE64) 3062 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 3063 OPLEN); 3064 else if (addr_size == SIZE32) 3065 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 3066 OPLEN); 3067 else 3068 (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 3069 OPLEN); 3070 #endif 3071 break; 3072 3073 /* si register to accumulator */ 3074 case SA: 3075 wbit = WBIT(opcode2); 3076 #ifdef DIS_TEXT 3077 dtrace_check_override(x, 0); 3078 x->d86_numopnds = 2; 3079 if (addr_size == SIZE64) 3080 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 3081 OPLEN); 3082 else if (addr_size == SIZE32) 3083 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 3084 OPLEN); 3085 else 3086 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 3087 OPLEN); 3088 dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 3089 #endif 3090 break; 3091 3092 /* 3093 * single operand, a 16/32 bit displacement 3094 */ 3095 case D: 3096 wbit = LONG_OPND; 3097 dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 3098 NOMEM; 3099 break; 3100 3101 /* jmp/call indirect to memory or register operand */ 3102 case INM: 3103 #ifdef DIS_TEXT 3104 (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); 3105 #endif 3106 dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3107 dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 3108 wbit = LONG_OPND; 3109 break; 3110 3111 /* 3112 * for long jumps and long calls -- a new code segment 3113 * register and an offset in IP -- stored in object 3114 * code in reverse order. Note - not valid in amd64 3115 */ 3116 case SO: 3117 dtrace_check_override(x, 1); 3118 wbit = LONG_OPND; 3119 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1); 3120 #ifdef DIS_TEXT 3121 x->d86_opnd[1].d86_mode = MODE_SIGNED; 3122 #endif 3123 /* will now get segment operand */ 3124 dtrace_imm_opnd(x, wbit, 2, 0); 3125 break; 3126 3127 /* 3128 * jmp/call. single operand, 8 bit displacement. 3129 * added to current EIP in 'compofff' 3130 */ 3131 case BD: 3132 dtrace_disp_opnd(x, BYTE_OPND, 1, 0); 3133 NOMEM; 3134 break; 3135 3136 /* single 32/16 bit immediate operand */ 3137 case I: 3138 wbit = LONG_OPND; 3139 dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 3140 break; 3141 3142 /* single 8 bit immediate operand */ 3143 case Ib: 3144 wbit = LONG_OPND; 3145 dtrace_imm_opnd(x, wbit, 1, 0); 3146 break; 3147 3148 case ENTER: 3149 wbit = LONG_OPND; 3150 dtrace_imm_opnd(x, wbit, 2, 0); 3151 dtrace_imm_opnd(x, wbit, 1, 1); 3152 switch (opnd_size) { 3153 case SIZE64: 3154 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8; 3155 break; 3156 case SIZE32: 3157 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4; 3158 break; 3159 case SIZE16: 3160 x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2; 3161 break; 3162 } 3163 3164 break; 3165 3166 /* 16-bit immediate operand */ 3167 case RET: 3168 wbit = LONG_OPND; 3169 dtrace_imm_opnd(x, wbit, 2, 0); 3170 break; 3171 3172 /* single 8 bit port operand */ 3173 case P: 3174 dtrace_check_override(x, 0); 3175 dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 3176 NOMEM; 3177 break; 3178 3179 /* single operand, dx register (variable port instruction) */ 3180 case V: 3181 x->d86_numopnds = 1; 3182 dtrace_check_override(x, 0); 3183 #ifdef DIS_TEXT 3184 (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); 3185 #endif 3186 NOMEM; 3187 break; 3188 3189 /* 3190 * The int instruction, which has two forms: 3191 * int 3 (breakpoint) or 3192 * int n, where n is indicated in the subsequent 3193 * byte (format Ib). The int 3 instruction (opcode 0xCC), 3194 * where, although the 3 looks like an operand, 3195 * it is implied by the opcode. It must be converted 3196 * to the correct base and output. 3197 */ 3198 case INT3: 3199 #ifdef DIS_TEXT 3200 x->d86_numopnds = 1; 3201 x->d86_opnd[0].d86_mode = MODE_SIGNED; 3202 x->d86_opnd[0].d86_value_size = 1; 3203 x->d86_opnd[0].d86_value = 3; 3204 #endif 3205 NOMEM; 3206 break; 3207 3208 /* single 8 bit immediate operand */ 3209 case INTx: 3210 dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 3211 NOMEM; 3212 break; 3213 3214 /* an unused byte must be discarded */ 3215 case U: 3216 if (x->d86_get_byte(x->d86_data) < 0) 3217 goto error; 3218 x->d86_len++; 3219 NOMEM; 3220 break; 3221 3222 case CBW: 3223 #ifdef DIS_TEXT 3224 if (opnd_size == SIZE16) 3225 (void) strlcat(x->d86_mnem, "cbtw", OPLEN); 3226 else if (opnd_size == SIZE32) 3227 (void) strlcat(x->d86_mnem, "cwtl", OPLEN); 3228 else 3229 (void) strlcat(x->d86_mnem, "cltq", OPLEN); 3230 #endif 3231 wbit = LONG_OPND; 3232 NOMEM; 3233 break; 3234 3235 case CWD: 3236 #ifdef DIS_TEXT 3237 if (opnd_size == SIZE16) 3238 (void) strlcat(x->d86_mnem, "cwtd", OPLEN); 3239 else if (opnd_size == SIZE32) 3240 (void) strlcat(x->d86_mnem, "cltd", OPLEN); 3241 else 3242 (void) strlcat(x->d86_mnem, "cqtd", OPLEN); 3243 #endif 3244 wbit = LONG_OPND; 3245 NOMEM; 3246 break; 3247 3248 case XMMSFNC: 3249 /* 3250 * sfence is sfence if mode is REG_ONLY. If mode isn't 3251 * REG_ONLY, mnemonic should be 'clflush'. 3252 */ 3253 dtrace_get_modrm(x, &mode, ®, &r_m); 3254 3255 /* sfence doesn't take operands */ 3256 #ifdef DIS_TEXT 3257 if (mode == REG_ONLY) { 3258 (void) strlcat(x->d86_mnem, "sfence", OPLEN); 3259 } else { 3260 (void) strlcat(x->d86_mnem, "clflush", OPLEN); 3261 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3262 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 3263 NOMEM; 3264 } 3265 #else 3266 if (mode != REG_ONLY) { 3267 dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3268 dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 3269 NOMEM; 3270 } 3271 #endif 3272 break; 3273 3274 /* 3275 * no disassembly, the mnemonic was all there was so go on 3276 */ 3277 case NORM: 3278 if (dp->it_invalid32 && cpu_mode != SIZE64) 3279 goto error; 3280 NOMEM; 3281 /*FALLTHROUGH*/ 3282 case IMPLMEM: 3283 break; 3284 3285 case XMMFENCE: 3286 /* 3287 * Only the following exact byte sequences are allowed: 3288 * 3289 * 0f ae e8 lfence 3290 * 0f ae f0 mfence 3291 */ 3292 if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 && 3293 (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0) 3294 goto error; 3295 3296 break; 3297 3298 3299 /* float reg */ 3300 case F: 3301 #ifdef DIS_TEXT 3302 x->d86_numopnds = 1; 3303 (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); 3304 x->d86_opnd[0].d86_opnd[4] = r_m + '0'; 3305 #endif 3306 NOMEM; 3307 break; 3308 3309 /* float reg to float reg, with ret bit present */ 3310 case FF: 3311 vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */ 3312 /*FALLTHROUGH*/ 3313 case FFC: /* case for vbit always = 0 */ 3314 #ifdef DIS_TEXT 3315 x->d86_numopnds = 2; 3316 (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); 3317 (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); 3318 x->d86_opnd[vbit].d86_opnd[4] = r_m + '0'; 3319 #endif 3320 NOMEM; 3321 break; 3322 3323 /* an invalid op code */ 3324 case AM: 3325 case DM: 3326 case OVERRIDE: 3327 case PREFIX: 3328 case UNKNOWN: 3329 NOMEM; 3330 default: 3331 goto error; 3332 } /* end switch */ 3333 if (x->d86_error) 3334 goto error; 3335 3336 done: 3337 #ifdef DIS_MEM 3338 /* 3339 * compute the size of any memory accessed by the instruction 3340 */ 3341 if (x->d86_memsize != 0) { 3342 return (0); 3343 } else if (dp->it_stackop) { 3344 switch (opnd_size) { 3345 case SIZE16: 3346 x->d86_memsize = 2; 3347 break; 3348 case SIZE32: 3349 x->d86_memsize = 4; 3350 break; 3351 case SIZE64: 3352 x->d86_memsize = 8; 3353 break; 3354 } 3355 } else if (nomem || mode == REG_ONLY) { 3356 x->d86_memsize = 0; 3357 3358 } else if (dp->it_size != 0) { 3359 /* 3360 * In 64 bit mode descriptor table entries 3361 * go up to 10 bytes and popf/pushf are always 8 bytes 3362 */ 3363 if (x->d86_mode == SIZE64 && dp->it_size == 6) 3364 x->d86_memsize = 10; 3365 else if (x->d86_mode == SIZE64 && opcode1 == 0x9 && 3366 (opcode2 == 0xc || opcode2 == 0xd)) 3367 x->d86_memsize = 8; 3368 else 3369 x->d86_memsize = dp->it_size; 3370 3371 } else if (wbit == 0) { 3372 x->d86_memsize = 1; 3373 3374 } else if (wbit == LONG_OPND) { 3375 if (opnd_size == SIZE64) 3376 x->d86_memsize = 8; 3377 else if (opnd_size == SIZE32) 3378 x->d86_memsize = 4; 3379 else 3380 x->d86_memsize = 2; 3381 3382 } else if (wbit == SEG_OPND) { 3383 x->d86_memsize = 4; 3384 3385 } else { 3386 x->d86_memsize = 8; 3387 } 3388 #endif 3389 return (0); 3390 3391 error: 3392 #ifdef DIS_TEXT 3393 (void) strlcat(x->d86_mnem, "undef", OPLEN); 3394 #endif 3395 return (1); 3396 } 3397 3398 #ifdef DIS_TEXT 3399 3400 /* 3401 * Some instructions should have immediate operands printed 3402 * as unsigned integers. We compare against this table. 3403 */ 3404 static char *unsigned_ops[] = { 3405 "or", "and", "xor", "test", "in", "out", "lcall", "ljmp", 3406 "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl", 3407 0 3408 }; 3409 3410 3411 static int 3412 isunsigned_op(char *opcode) 3413 { 3414 char *where; 3415 int i; 3416 int is_unsigned = 0; 3417 3418 /* 3419 * Work back to start of last mnemonic, since we may have 3420 * prefixes on some opcodes. 3421 */ 3422 where = opcode + strlen(opcode) - 1; 3423 while (where > opcode && *where != ' ') 3424 --where; 3425 if (*where == ' ') 3426 ++where; 3427 3428 for (i = 0; unsigned_ops[i]; ++i) { 3429 if (strncmp(where, unsigned_ops[i], 3430 strlen(unsigned_ops[i]))) 3431 continue; 3432 is_unsigned = 1; 3433 break; 3434 } 3435 return (is_unsigned); 3436 } 3437 3438 /* 3439 * Print a numeric immediate into end of buf, maximum length buflen. 3440 * The immediate may be an address or a displacement. Mask is set 3441 * for address size. If the immediate is a "small negative", or 3442 * if it's a negative displacement of any magnitude, print as -<absval>. 3443 * Respect the "octal" flag. "Small negative" is defined as "in the 3444 * interval [NEG_LIMIT, 0)". 3445 * 3446 * Also, "isunsigned_op()" instructions never print negatives. 3447 * 3448 * Return whether we decided to print a negative value or not. 3449 */ 3450 3451 #define NEG_LIMIT -255 3452 enum {IMM, DISP}; 3453 enum {POS, TRY_NEG}; 3454 3455 static int 3456 print_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf, 3457 size_t buflen, int disp, int try_neg) 3458 { 3459 int curlen; 3460 int64_t sv = (int64_t)usv; 3461 int octal = dis->d86_flags & DIS_F_OCTAL; 3462 3463 curlen = strlen(buf); 3464 3465 if (try_neg == TRY_NEG && sv < 0 && 3466 (disp || sv >= NEG_LIMIT) && 3467 !isunsigned_op(dis->d86_mnem)) { 3468 dis->d86_sprintf_func(buf + curlen, buflen - curlen, 3469 octal ? "-0%llo" : "-0x%llx", (-sv) & mask); 3470 return (1); 3471 } else { 3472 if (disp == DISP) 3473 dis->d86_sprintf_func(buf + curlen, buflen - curlen, 3474 octal ? "+0%llo" : "+0x%llx", usv & mask); 3475 else 3476 dis->d86_sprintf_func(buf + curlen, buflen - curlen, 3477 octal ? "0%llo" : "0x%llx", usv & mask); 3478 return (0); 3479 3480 } 3481 } 3482 3483 3484 static int 3485 log2(int size) 3486 { 3487 switch (size) { 3488 case 1: return (0); 3489 case 2: return (1); 3490 case 4: return (2); 3491 case 8: return (3); 3492 } 3493 return (0); 3494 } 3495 3496 /* ARGSUSED */ 3497 void 3498 dtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf, 3499 size_t buflen) 3500 { 3501 uint64_t reltgt = 0; 3502 uint64_t tgt = 0; 3503 int curlen; 3504 int (*lookup)(void *, uint64_t, char *, size_t); 3505 int i; 3506 int64_t sv; 3507 uint64_t usv, mask, save_mask, save_usv; 3508 static uint64_t masks[] = 3509 {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL}; 3510 save_usv = 0; 3511 3512 dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem); 3513 3514 /* 3515 * For PC-relative jumps, the pc is really the next pc after executing 3516 * this instruction, so increment it appropriately. 3517 */ 3518 pc += dis->d86_len; 3519 3520 for (i = 0; i < dis->d86_numopnds; i++) { 3521 d86opnd_t *op = &dis->d86_opnd[i]; 3522 3523 if (i != 0) 3524 (void) strlcat(buf, ",", buflen); 3525 3526 (void) strlcat(buf, op->d86_prefix, buflen); 3527 3528 /* 3529 * sv is for the signed, possibly-truncated immediate or 3530 * displacement; usv retains the original size and 3531 * unsignedness for symbol lookup. 3532 */ 3533 3534 sv = usv = op->d86_value; 3535 3536 /* 3537 * About masks: for immediates that represent 3538 * addresses, the appropriate display size is 3539 * the effective address size of the instruction. 3540 * This includes MODE_OFFSET, MODE_IPREL, and 3541 * MODE_RIPREL. Immediates that are simply 3542 * immediate values should display in the operand's 3543 * size, however, since they don't represent addresses. 3544 */ 3545 3546 /* d86_addr_size is SIZEnn, which is log2(real size) */ 3547 mask = masks[dis->d86_addr_size]; 3548 3549 /* d86_value_size and d86_imm_bytes are in bytes */ 3550 if (op->d86_mode == MODE_SIGNED || 3551 op->d86_mode == MODE_IMPLIED) 3552 mask = masks[log2(op->d86_value_size)]; 3553 3554 switch (op->d86_mode) { 3555 3556 case MODE_NONE: 3557 3558 (void) strlcat(buf, op->d86_opnd, buflen); 3559 break; 3560 3561 case MODE_SIGNED: 3562 case MODE_IMPLIED: 3563 case MODE_OFFSET: 3564 3565 tgt = usv; 3566 3567 if (dis->d86_seg_prefix) 3568 (void) strlcat(buf, dis->d86_seg_prefix, 3569 buflen); 3570 3571 if (op->d86_mode == MODE_SIGNED || 3572 op->d86_mode == MODE_IMPLIED) { 3573 (void) strlcat(buf, "$", buflen); 3574 } 3575 3576 if (print_imm(dis, usv, mask, buf, buflen, 3577 IMM, TRY_NEG) && 3578 (op->d86_mode == MODE_SIGNED || 3579 op->d86_mode == MODE_IMPLIED)) { 3580 3581 /* 3582 * We printed a negative value for an 3583 * immediate that wasn't a 3584 * displacement. Note that fact so we can 3585 * print the positive value as an 3586 * annotation. 3587 */ 3588 3589 save_usv = usv; 3590 save_mask = mask; 3591 } 3592 (void) strlcat(buf, op->d86_opnd, buflen); 3593 3594 break; 3595 3596 case MODE_IPREL: 3597 case MODE_RIPREL: 3598 3599 reltgt = pc + sv; 3600 3601 switch (mode) { 3602 case SIZE16: 3603 reltgt = (uint16_t)reltgt; 3604 break; 3605 case SIZE32: 3606 reltgt = (uint32_t)reltgt; 3607 break; 3608 } 3609 3610 (void) print_imm(dis, usv, mask, buf, buflen, 3611 DISP, TRY_NEG); 3612 3613 if (op->d86_mode == MODE_RIPREL) 3614 (void) strlcat(buf, "(%rip)", buflen); 3615 break; 3616 } 3617 } 3618 3619 /* 3620 * The symbol lookups may result in false positives, 3621 * particularly on object files, where small numbers may match 3622 * the 0-relative non-relocated addresses of symbols. 3623 */ 3624 3625 lookup = dis->d86_sym_lookup; 3626 if (tgt != 0) { 3627 if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 && 3628 lookup(dis->d86_data, tgt, NULL, 0) == 0) { 3629 (void) strlcat(buf, "\t<", buflen); 3630 curlen = strlen(buf); 3631 lookup(dis->d86_data, tgt, buf + curlen, 3632 buflen - curlen); 3633 (void) strlcat(buf, ">", buflen); 3634 } 3635 3636 /* 3637 * If we printed a negative immediate above, print the 3638 * positive in case our heuristic was unhelpful 3639 */ 3640 if (save_usv) { 3641 (void) strlcat(buf, "\t<", buflen); 3642 (void) print_imm(dis, save_usv, save_mask, buf, buflen, 3643 IMM, POS); 3644 (void) strlcat(buf, ">", buflen); 3645 } 3646 } 3647 3648 if (reltgt != 0) { 3649 /* Print symbol or effective address for reltgt */ 3650 3651 (void) strlcat(buf, "\t<", buflen); 3652 curlen = strlen(buf); 3653 lookup(dis->d86_data, reltgt, buf + curlen, 3654 buflen - curlen); 3655 (void) strlcat(buf, ">", buflen); 3656 } 3657 } 3658 3659 #endif /* DIS_TEXT */ 3660