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