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