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