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