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