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