dis_tables.c revision 238168
1179237Sjb/* 2179237Sjb * CDDL HEADER START 3179237Sjb * 4179237Sjb * The contents of this file are subject to the terms of the 5179237Sjb * Common Development and Distribution License (the "License"). 6179237Sjb * You may not use this file except in compliance with the License. 7179237Sjb * 8179237Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9179237Sjb * or http://www.opensolaris.org/os/licensing. 10179237Sjb * See the License for the specific language governing permissions 11179237Sjb * and limitations under the License. 12179237Sjb * 13179237Sjb * When distributing Covered Code, include this CDDL HEADER in each 14179237Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15179237Sjb * If applicable, add the following below this CDDL HEADER, with the 16179237Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17179237Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18179237Sjb * 19179237Sjb * CDDL HEADER END 20179237Sjb * 21179237Sjb * $FreeBSD: head/sys/cddl/dev/dtrace/amd64/dis_tables.c 238168 2012-07-06 14:41:02Z avg $ 22179237Sjb */ 23179237Sjb/* 24179237Sjb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25179237Sjb * Use is subject to license terms. 26179237Sjb */ 27179237Sjb 28179237Sjb/* Copyright (c) 1988 AT&T */ 29179237Sjb/* All Rights Reserved */ 30179237Sjb 31179237Sjb 32179237Sjb#if defined(sun) 33179237Sjb#pragma ident "@(#)dis_tables.c 1.11 06/03/02 SMI" 34179237Sjb#endif 35179237Sjb 36179237Sjb#include "dis_tables.h" 37179237Sjb 38179237Sjb/* BEGIN CSTYLED */ 39179237Sjb 40179237Sjb/* 41179237Sjb * Disassembly begins in dis_distable, which is equivalent to the One-byte 42179237Sjb * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy). The 43179237Sjb * decoding loops then traverse out through the other tables as necessary to 44179237Sjb * decode a given instruction. 45179237Sjb * 46179237Sjb * The behavior of this file can be controlled by one of the following flags: 47179237Sjb * 48179237Sjb * DIS_TEXT Include text for disassembly 49179237Sjb * DIS_MEM Include memory-size calculations 50179237Sjb * 51179237Sjb * Either or both of these can be defined. 52179237Sjb * 53179237Sjb * This file is not, and will never be, cstyled. If anything, the tables should 54179237Sjb * be taken out another tab stop or two so nothing overlaps. 55179237Sjb */ 56179237Sjb 57179237Sjb/* 58179237Sjb * These functions must be provided for the consumer to do disassembly. 59179237Sjb */ 60179237Sjb#ifdef DIS_TEXT 61179237Sjbextern char *strncpy(char *, const char *, size_t); 62179237Sjbextern size_t strlen(const char *); 63179237Sjbextern int strcmp(const char *, const char *); 64179237Sjbextern int strncmp(const char *, const char *, size_t); 65179237Sjbextern size_t strlcat(char *, const char *, size_t); 66179237Sjb#endif 67179237Sjb 68179237Sjb 69179237Sjb#define TERM NULL /* used to indicate that the 'indirect' */ 70179237Sjb /* field terminates - no pointer. */ 71179237Sjb 72179237Sjb/* Used to decode instructions. */ 73179237Sjbtypedef struct instable { 74179237Sjb const struct instable *it_indirect; /* for decode op codes */ 75179237Sjb uchar_t it_adrmode; 76179237Sjb#ifdef DIS_TEXT 77179237Sjb char it_name[NCPS]; 78179237Sjb uint_t it_suffix:1; /* mneu + "w", "l", or "d" */ 79179237Sjb#endif 80179237Sjb#ifdef DIS_MEM 81179237Sjb uint_t it_size:16; 82179237Sjb#endif 83179237Sjb uint_t it_invalid64:1; /* opcode invalid in amd64 */ 84179237Sjb uint_t it_always64:1; /* 64 bit when in 64 bit mode */ 85179237Sjb uint_t it_invalid32:1; /* invalid in IA32 */ 86179237Sjb uint_t it_stackop:1; /* push/pop stack operation */ 87179237Sjb} instable_t; 88179237Sjb 89179237Sjb/* 90179237Sjb * Instruction formats. 91179237Sjb */ 92179237Sjbenum { 93179237Sjb UNKNOWN, 94179237Sjb MRw, 95179237Sjb IMlw, 96179237Sjb IMw, 97179237Sjb IR, 98179237Sjb OA, 99179237Sjb AO, 100179237Sjb MS, 101179237Sjb SM, 102179237Sjb Mv, 103179237Sjb Mw, 104179237Sjb M, /* register or memory */ 105179237Sjb Mb, /* register or memory, always byte sized */ 106179237Sjb MO, /* memory only (no registers) */ 107179237Sjb PREF, 108179237Sjb SWAPGS, 109179237Sjb R, 110179237Sjb RA, 111179237Sjb SEG, 112179237Sjb MR, 113179237Sjb RM, 114179237Sjb IA, 115179237Sjb MA, 116179237Sjb SD, 117179237Sjb AD, 118179237Sjb SA, 119179237Sjb D, 120179237Sjb INM, 121179237Sjb SO, 122179237Sjb BD, 123179237Sjb I, 124179237Sjb P, 125179237Sjb V, 126179237Sjb DSHIFT, /* for double shift that has an 8-bit immediate */ 127179237Sjb U, 128179237Sjb OVERRIDE, 129179237Sjb NORM, /* instructions w/o ModR/M byte, no memory access */ 130179237Sjb IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */ 131179237Sjb O, /* for call */ 132179237Sjb JTAB, /* jump table */ 133179237Sjb IMUL, /* for 186 iimul instr */ 134179237Sjb CBW, /* so data16 can be evaluated for cbw and variants */ 135179237Sjb MvI, /* for 186 logicals */ 136179237Sjb ENTER, /* for 186 enter instr */ 137179237Sjb RMw, /* for 286 arpl instr */ 138179237Sjb Ib, /* for push immediate byte */ 139179237Sjb F, /* for 287 instructions */ 140179237Sjb FF, /* for 287 instructions */ 141179237Sjb FFC, /* for 287 instructions */ 142179237Sjb DM, /* 16-bit data */ 143179237Sjb AM, /* 16-bit addr */ 144179237Sjb LSEG, /* for 3-bit seg reg encoding */ 145179237Sjb MIb, /* for 386 logicals */ 146179237Sjb SREG, /* for 386 special registers */ 147179237Sjb PREFIX, /* a REP instruction prefix */ 148179237Sjb LOCK, /* a LOCK instruction prefix */ 149179237Sjb INT3, /* The int 3 instruction, which has a fake operand */ 150179237Sjb INTx, /* The normal int instruction, with explicit int num */ 151179237Sjb DSHIFTcl, /* for double shift that implicitly uses %cl */ 152179237Sjb CWD, /* so data16 can be evaluated for cwd and variants */ 153179237Sjb RET, /* single immediate 16-bit operand */ 154179237Sjb MOVZ, /* for movs and movz, with different size operands */ 155179237Sjb XADDB, /* for xaddb */ 156179237Sjb MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */ 157179237Sjb 158179237Sjb/* 159179237Sjb * MMX/SIMD addressing modes. 160179237Sjb */ 161179237Sjb 162179237Sjb MMO, /* Prefixable MMX/SIMD-Int mm/mem -> mm */ 163179237Sjb MMOIMPL, /* Prefixable MMX/SIMD-Int mm -> mm (mem) */ 164179237Sjb MMO3P, /* Prefixable MMX/SIMD-Int mm -> r32,imm8 */ 165179237Sjb MMOM3, /* Prefixable MMX/SIMD-Int mm -> r32 */ 166179237Sjb MMOS, /* Prefixable MMX/SIMD-Int mm -> mm/mem */ 167179237Sjb MMOMS, /* Prefixable MMX/SIMD-Int mm -> mem */ 168179237Sjb MMOPM, /* MMX/SIMD-Int mm/mem -> mm,imm8 */ 169179237Sjb MMOPRM, /* Prefixable MMX/SIMD-Int r32/mem -> mm,imm8 */ 170179237Sjb MMOSH, /* Prefixable MMX mm,imm8 */ 171179237Sjb MM, /* MMX/SIMD-Int mm/mem -> mm */ 172179237Sjb MMS, /* MMX/SIMD-Int mm -> mm/mem */ 173179237Sjb MMSH, /* MMX mm,imm8 */ 174179237Sjb XMMO, /* Prefixable SIMD xmm/mem -> xmm */ 175179237Sjb XMMOS, /* Prefixable SIMD xmm -> xmm/mem */ 176179237Sjb XMMOPM, /* Prefixable SIMD xmm/mem w/to xmm,imm8 */ 177179237Sjb XMMOMX, /* Prefixable SIMD mm/mem -> xmm */ 178179237Sjb XMMOX3, /* Prefixable SIMD xmm -> r32 */ 179179237Sjb XMMOXMM, /* Prefixable SIMD xmm/mem -> mm */ 180179237Sjb XMMOM, /* Prefixable SIMD xmm -> mem */ 181179237Sjb XMMOMS, /* Prefixable SIMD mem -> xmm */ 182179237Sjb XMM, /* SIMD xmm/mem -> xmm */ 183179237Sjb XMMXIMPL, /* SIMD xmm -> xmm (mem) */ 184179237Sjb XMM3P, /* SIMD xmm -> r32,imm8 */ 185179237Sjb XMMP, /* SIMD xmm/mem w/to xmm,imm8 */ 186179237Sjb XMMPRM, /* SIMD r32/mem -> xmm,imm8 */ 187179237Sjb XMMS, /* SIMD xmm -> xmm/mem */ 188179237Sjb XMMM, /* SIMD mem -> xmm */ 189179237Sjb XMMMS, /* SIMD xmm -> mem */ 190179237Sjb XMM3MX, /* SIMD r32/mem -> xmm */ 191179237Sjb XMM3MXS, /* SIMD xmm -> r32/mem */ 192179237Sjb XMMSH, /* SIMD xmm,imm8 */ 193179237Sjb XMMXM3, /* SIMD xmm/mem -> r32 */ 194179237Sjb XMMX3, /* SIMD xmm -> r32 */ 195179237Sjb XMMXMM, /* SIMD xmm/mem -> mm */ 196179237Sjb XMMMX, /* SIMD mm -> xmm */ 197179237Sjb XMMXM, /* SIMD xmm -> mm */ 198179237Sjb XMMFENCE, /* SIMD lfence or mfence */ 199179237Sjb XMMSFNC /* SIMD sfence (none or mem) */ 200179237Sjb}; 201179237Sjb 202179237Sjb#define FILL 0x90 /* Fill byte used for alignment (nop) */ 203179237Sjb 204179237Sjb/* 205179237Sjb** Register numbers for the i386 206179237Sjb*/ 207179237Sjb#define EAX_REGNO 0 208179237Sjb#define ECX_REGNO 1 209179237Sjb#define EDX_REGNO 2 210179237Sjb#define EBX_REGNO 3 211179237Sjb#define ESP_REGNO 4 212179237Sjb#define EBP_REGNO 5 213179237Sjb#define ESI_REGNO 6 214179237Sjb#define EDI_REGNO 7 215179237Sjb 216179237Sjb/* 217179237Sjb * modes for immediate values 218179237Sjb */ 219179237Sjb#define MODE_NONE 0 220179237Sjb#define MODE_IPREL 1 /* signed IP relative value */ 221179237Sjb#define MODE_SIGNED 2 /* sign extended immediate */ 222179237Sjb#define MODE_IMPLIED 3 /* constant value implied from opcode */ 223179237Sjb#define MODE_OFFSET 4 /* offset part of an address */ 224179237Sjb 225179237Sjb/* 226179237Sjb * The letters used in these macros are: 227179237Sjb * IND - indirect to another to another table 228179237Sjb * "T" - means to Terminate indirections (this is the final opcode) 229179237Sjb * "S" - means "operand length suffix required" 230179237Sjb * "NS" - means "no suffix" which is the operand length suffix of the opcode 231179237Sjb * "Z" - means instruction size arg required 232179237Sjb * "u" - means the opcode is invalid in IA32 but valid in amd64 233179237Sjb * "x" - means the opcode is invalid in amd64, but not IA32 234179237Sjb * "y" - means the operand size is always 64 bits in 64 bit mode 235179237Sjb * "p" - means push/pop stack operation 236179237Sjb */ 237179237Sjb 238179237Sjb#if defined(DIS_TEXT) && defined(DIS_MEM) 239179237Sjb#define IND(table) {table, 0, "", 0, 0, 0, 0, 0, 0} 240179237Sjb#define INDx(table) {table, 0, "", 0, 0, 1, 0, 0, 0} 241179237Sjb#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0} 242179237Sjb#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0} 243179237Sjb#define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0} 244179237Sjb#define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0} 245179237Sjb#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1} 246179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0} 247179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0} 248179237Sjb#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0} 249179237Sjb#define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0} 250179237Sjb#define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0} 251179237Sjb#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1} 252179237Sjb#define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0} 253179237Sjb#define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0} 254179237Sjb#define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0} 255179237Sjb#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 256179237Sjb#elif defined(DIS_TEXT) 257179237Sjb#define IND(table) {table, 0, "", 0, 0, 0, 0, 0} 258179237Sjb#define INDx(table) {table, 0, "", 0, 1, 0, 0, 0} 259179237Sjb#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0} 260179237Sjb#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0} 261179237Sjb#define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0} 262179237Sjb#define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0} 263179237Sjb#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1} 264179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0} 265179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0} 266179237Sjb#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0} 267179237Sjb#define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0} 268179237Sjb#define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0} 269179237Sjb#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1} 270179237Sjb#define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0} 271179237Sjb#define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0} 272179237Sjb#define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0} 273179237Sjb#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 274179237Sjb#elif defined(DIS_MEM) 275179237Sjb#define IND(table) {table, 0, 0, 0, 0, 0, 0} 276179237Sjb#define INDx(table) {table, 0, 0, 1, 0, 0, 0} 277179237Sjb#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 278179237Sjb#define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0} 279179237Sjb#define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 280179237Sjb#define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1} 281179237Sjb#define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 282179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 283179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 284179237Sjb#define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 285179237Sjb#define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 286179237Sjb#define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 287179237Sjb#define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1} 288179237Sjb#define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 289179237Sjb#define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0} 290179237Sjb#define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 291179237Sjb#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0} 292179237Sjb#else 293179237Sjb#define IND(table) {table[0], 0, 0, 0, 0, 0} 294179237Sjb#define INDx(table) {table[0], 0, 1, 0, 0, 0} 295179237Sjb#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0} 296179237Sjb#define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0} 297179237Sjb#define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0} 298179237Sjb#define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1} 299179237Sjb#define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0} 300179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 301179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 302179237Sjb#define TS(name, amode) {TERM, amode, 0, 0, 0, 0} 303179237Sjb#define TSx(name, amode) {TERM, amode, 1, 0, 0, 0} 304179237Sjb#define TSy(name, amode) {TERM, amode, 0, 1, 0, 0} 305179237Sjb#define TSp(name, amode) {TERM, amode, 0, 0, 0, 1} 306179237Sjb#define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 307179237Sjb#define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0} 308179237Sjb#define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 309179237Sjb#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0} 310179237Sjb#endif 311179237Sjb 312179237Sjb#ifdef DIS_TEXT 313179237Sjb/* 314179237Sjb * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode 315179237Sjb */ 316179237Sjbconst char *const dis_addr16[3][8] = { 317179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "", 318179237Sjb "(%bx)", 319179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)", 320179237Sjb "(%bx)", 321179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)", 322179237Sjb "(%bx)", 323179237Sjb}; 324179237Sjb 325179237Sjb 326179237Sjb/* 327179237Sjb * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2 328179237Sjb */ 329179237Sjbconst char *const dis_addr32_mode0[16] = { 330179237Sjb "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)", 331179237Sjb "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)" 332179237Sjb}; 333179237Sjb 334179237Sjbconst char *const dis_addr32_mode12[16] = { 335179237Sjb "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)", 336179237Sjb "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)" 337179237Sjb}; 338179237Sjb 339179237Sjb/* 340179237Sjb * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2 341179237Sjb */ 342179237Sjbconst char *const dis_addr64_mode0[16] = { 343179237Sjb "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)", 344179237Sjb "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)" 345179237Sjb}; 346179237Sjbconst char *const dis_addr64_mode12[16] = { 347179237Sjb "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)", 348179237Sjb "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)" 349179237Sjb}; 350179237Sjb 351179237Sjb/* 352179237Sjb * decode for scale from SIB byte 353179237Sjb */ 354179237Sjbconst char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" }; 355179237Sjb 356179237Sjb/* 357179237Sjb * register decoding for normal references to registers (ie. not addressing) 358179237Sjb */ 359179237Sjbconst char *const dis_REG8[16] = { 360179237Sjb "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", 361179237Sjb "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 362179237Sjb}; 363179237Sjb 364179237Sjbconst char *const dis_REG8_REX[16] = { 365179237Sjb "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", 366179237Sjb "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 367179237Sjb}; 368179237Sjb 369179237Sjbconst char *const dis_REG16[16] = { 370179237Sjb "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 371179237Sjb "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" 372179237Sjb}; 373179237Sjb 374179237Sjbconst char *const dis_REG32[16] = { 375179237Sjb "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 376179237Sjb "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" 377179237Sjb}; 378179237Sjb 379179237Sjbconst char *const dis_REG64[16] = { 380179237Sjb "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 381179237Sjb "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 382179237Sjb}; 383179237Sjb 384179237Sjbconst char *const dis_DEBUGREG[16] = { 385179237Sjb "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7", 386179237Sjb "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15" 387179237Sjb}; 388179237Sjb 389179237Sjbconst char *const dis_CONTROLREG[16] = { 390179237Sjb "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?", 391179237Sjb "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?" 392179237Sjb}; 393179237Sjb 394179237Sjbconst char *const dis_TESTREG[16] = { 395179237Sjb "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", 396179237Sjb "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7" 397179237Sjb}; 398179237Sjb 399179237Sjbconst char *const dis_MMREG[16] = { 400179237Sjb "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", 401179237Sjb "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" 402179237Sjb}; 403179237Sjb 404179237Sjbconst char *const dis_XMMREG[16] = { 405179237Sjb "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 406179237Sjb "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 407179237Sjb}; 408179237Sjb 409179237Sjbconst char *const dis_SEGREG[16] = { 410179237Sjb "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>", 411179237Sjb "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>" 412179237Sjb}; 413179237Sjb 414179237Sjb/* 415179237Sjb * SIMD predicate suffixes 416179237Sjb */ 417179237Sjbconst char *const dis_PREDSUFFIX[8] = { 418179237Sjb "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord" 419179237Sjb}; 420179237Sjb 421179237Sjb 422179237Sjb 423179237Sjb#endif /* DIS_TEXT */ 424179237Sjb 425179237Sjb 426179237Sjb 427179237Sjb 428179237Sjb/* 429179237Sjb * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63) 430179237Sjb */ 431179237Sjbconst instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ); 432179237Sjb 433179237Sjb/* 434179237Sjb * "decode table" for pause and clflush instructions 435179237Sjb */ 436179237Sjbconst instable_t dis_opPause = TNS("pause", NORM); 437179237Sjb 438179237Sjb/* 439179237Sjb * Decode table for 0x0F00 opcodes 440179237Sjb */ 441179237Sjbconst instable_t dis_op0F00[8] = { 442179237Sjb 443179237Sjb/* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M), 444179237Sjb/* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID, 445179237Sjb}; 446179237Sjb 447179237Sjb 448179237Sjb/* 449179237Sjb * Decode table for 0x0F01 opcodes 450179237Sjb */ 451179237Sjbconst instable_t dis_op0F01[8] = { 452179237Sjb 453179237Sjb/* [0] */ TNSZ("sgdt",MO,6), TNSZ("sidt",MO,6), TNSZ("lgdt",MO,6), TNSZ("lidt",MO,6), 454179237Sjb/* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS), 455179237Sjb}; 456179237Sjb 457179237Sjb/* 458179237Sjb * Decode table for 0x0F18 opcodes -- SIMD prefetch 459179237Sjb */ 460179237Sjbconst instable_t dis_op0F18[8] = { 461179237Sjb 462179237Sjb/* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF), 463179237Sjb/* [4] */ INVALID, INVALID, INVALID, INVALID, 464179237Sjb}; 465179237Sjb 466179237Sjb/* 467179237Sjb * Decode table for 0x0FAE opcodes -- SIMD state save/restore 468179237Sjb */ 469179237Sjbconst instable_t dis_op0FAE[8] = { 470179237Sjb/* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M), 471179237Sjb/* [4] */ INVALID, TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC), 472179237Sjb}; 473179237Sjb 474179237Sjb/* 475179237Sjb * Decode table for 0x0FBA opcodes 476179237Sjb */ 477179237Sjb 478179237Sjbconst instable_t dis_op0FBA[8] = { 479179237Sjb 480179237Sjb/* [0] */ INVALID, INVALID, INVALID, INVALID, 481179237Sjb/* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb), 482179237Sjb}; 483179237Sjb 484179237Sjb/* 485179237Sjb * Decode table for 0x0FC7 opcode 486179237Sjb */ 487179237Sjb 488179237Sjbconst instable_t dis_op0FC7[8] = { 489179237Sjb 490179237Sjb/* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID, 491179237Sjb/* [4] */ INVALID, INVALID, INVALID, INVALID, 492179237Sjb}; 493179237Sjb 494179237Sjb 495179237Sjb/* 496179237Sjb * Decode table for 0x0FC8 opcode -- 486 bswap instruction 497179237Sjb * 498179237Sjb *bit pattern: 0000 1111 1100 1reg 499179237Sjb */ 500179237Sjbconst instable_t dis_op0FC8[4] = { 501179237Sjb/* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID, 502179237Sjb}; 503179237Sjb 504179237Sjb/* 505179237Sjb * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions 506179237Sjb */ 507179237Sjbconst instable_t dis_op0F7123[4][8] = { 508179237Sjb{ 509179237Sjb/* [70].0 */ INVALID, INVALID, INVALID, INVALID, 510179237Sjb/* .4 */ INVALID, INVALID, INVALID, INVALID, 511179237Sjb}, { 512179237Sjb/* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID, 513179237Sjb/* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID, 514179237Sjb}, { 515179237Sjb/* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID, 516179237Sjb/* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID, 517179237Sjb}, { 518179237Sjb/* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH), 519179237Sjb/* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH), 520179237Sjb} }; 521179237Sjb 522179237Sjb/* 523179237Sjb * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes. 524179237Sjb */ 525179237Sjbconst instable_t dis_opSIMD7123[32] = { 526179237Sjb/* [70].0 */ INVALID, INVALID, INVALID, INVALID, 527179237Sjb/* .4 */ INVALID, INVALID, INVALID, INVALID, 528179237Sjb 529179237Sjb/* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID, 530179237Sjb/* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID, 531179237Sjb 532179237Sjb/* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID, 533179237Sjb/* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID, 534179237Sjb 535179237Sjb/* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH), 536179237Sjb/* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH), 537179237Sjb}; 538179237Sjb 539179237Sjb/* 540179237Sjb * SIMD instructions have been wedged into the existing IA32 instruction 541179237Sjb * set through the use of prefixes. That is, while 0xf0 0x58 may be 542179237Sjb * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different 543179237Sjb * instruction - addss. At present, three prefixes have been coopted in 544179237Sjb * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The 545179237Sjb * following tables are used to provide the prefixed instruction names. 546179237Sjb * The arrays are sparse, but they're fast. 547179237Sjb */ 548179237Sjb 549179237Sjb/* 550179237Sjb * Decode table for SIMD instructions with the address size (0x66) prefix. 551179237Sjb */ 552179237Sjbconst instable_t dis_opSIMDdata16[256] = { 553179237Sjb/* [00] */ INVALID, INVALID, INVALID, INVALID, 554179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 555179237Sjb/* [08] */ INVALID, INVALID, INVALID, INVALID, 556179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 557179237Sjb 558179237Sjb/* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8), 559179237Sjb/* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8), 560179237Sjb/* [18] */ INVALID, INVALID, INVALID, INVALID, 561179237Sjb/* [1C] */ INVALID, INVALID, INVALID, INVALID, 562179237Sjb 563179237Sjb/* [20] */ INVALID, INVALID, INVALID, INVALID, 564179237Sjb/* [24] */ INVALID, INVALID, INVALID, INVALID, 565179237Sjb/* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16), 566179237Sjb/* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8), 567179237Sjb 568179237Sjb/* [30] */ INVALID, INVALID, INVALID, INVALID, 569179237Sjb/* [34] */ INVALID, INVALID, INVALID, INVALID, 570179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 571179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 572179237Sjb 573179237Sjb/* [40] */ INVALID, INVALID, INVALID, INVALID, 574179237Sjb/* [44] */ INVALID, INVALID, INVALID, INVALID, 575179237Sjb/* [48] */ INVALID, INVALID, INVALID, INVALID, 576179237Sjb/* [4C] */ INVALID, INVALID, INVALID, INVALID, 577179237Sjb 578179237Sjb/* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID, 579179237Sjb/* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16), 580179237Sjb/* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16), 581179237Sjb/* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16), 582179237Sjb 583179237Sjb/* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16), 584179237Sjb/* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16), 585179237Sjb/* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16), 586179237Sjb/* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16), 587179237Sjb 588179237Sjb/* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID, 589179237Sjb/* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID, 590179237Sjb/* [78] */ INVALID, INVALID, INVALID, INVALID, 591179237Sjb/* [7C] */ INVALID, INVALID, TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16), 592179237Sjb 593179237Sjb/* [80] */ INVALID, INVALID, INVALID, INVALID, 594179237Sjb/* [84] */ INVALID, INVALID, INVALID, INVALID, 595179237Sjb/* [88] */ INVALID, INVALID, INVALID, INVALID, 596179237Sjb/* [8C] */ INVALID, INVALID, INVALID, INVALID, 597179237Sjb 598179237Sjb/* [90] */ INVALID, INVALID, INVALID, INVALID, 599179237Sjb/* [94] */ INVALID, INVALID, INVALID, INVALID, 600179237Sjb/* [98] */ INVALID, INVALID, INVALID, INVALID, 601179237Sjb/* [9C] */ INVALID, INVALID, INVALID, INVALID, 602179237Sjb 603179237Sjb/* [A0] */ INVALID, INVALID, INVALID, INVALID, 604179237Sjb/* [A4] */ INVALID, INVALID, INVALID, INVALID, 605179237Sjb/* [A8] */ INVALID, INVALID, INVALID, INVALID, 606179237Sjb/* [AC] */ INVALID, INVALID, INVALID, INVALID, 607179237Sjb 608179237Sjb/* [B0] */ INVALID, INVALID, INVALID, INVALID, 609179237Sjb/* [B4] */ INVALID, INVALID, INVALID, INVALID, 610179237Sjb/* [B8] */ INVALID, INVALID, INVALID, INVALID, 611179237Sjb/* [BC] */ INVALID, INVALID, INVALID, INVALID, 612179237Sjb 613179237Sjb/* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID, 614179237Sjb/* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID, 615179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 616179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 617179237Sjb 618179237Sjb/* [D0] */ INVALID, TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16), 619179237Sjb/* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3), 620179237Sjb/* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16), 621179237Sjb/* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16), 622179237Sjb 623179237Sjb/* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16), 624179237Sjb/* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16), 625179237Sjb/* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16), 626179237Sjb/* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16), 627179237Sjb 628179237Sjb/* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16), 629179237Sjb/* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16), 630179237Sjb/* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16), 631179237Sjb/* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID, 632179237Sjb}; 633179237Sjb 634179237Sjb/* 635179237Sjb * Decode table for SIMD instructions with the repnz (0xf2) prefix. 636179237Sjb */ 637179237Sjbconst instable_t dis_opSIMDrepnz[256] = { 638179237Sjb/* [00] */ INVALID, INVALID, INVALID, INVALID, 639179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 640179237Sjb/* [08] */ INVALID, INVALID, INVALID, INVALID, 641179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 642179237Sjb 643179237Sjb/* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), INVALID, INVALID, 644179237Sjb/* [14] */ INVALID, INVALID, INVALID, INVALID, 645179237Sjb/* [18] */ INVALID, INVALID, INVALID, INVALID, 646179237Sjb/* [1C] */ INVALID, INVALID, INVALID, INVALID, 647179237Sjb 648179237Sjb/* [20] */ INVALID, INVALID, INVALID, INVALID, 649179237Sjb/* [24] */ INVALID, INVALID, INVALID, INVALID, 650179237Sjb/* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),INVALID, 651179237Sjb/* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID, 652179237Sjb 653179237Sjb/* [30] */ INVALID, INVALID, INVALID, INVALID, 654179237Sjb/* [34] */ INVALID, INVALID, INVALID, INVALID, 655179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 656179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 657179237Sjb 658179237Sjb/* [40] */ INVALID, INVALID, INVALID, INVALID, 659179237Sjb/* [44] */ INVALID, INVALID, INVALID, INVALID, 660179237Sjb/* [48] */ INVALID, INVALID, INVALID, INVALID, 661179237Sjb/* [4C] */ INVALID, INVALID, INVALID, INVALID, 662179237Sjb 663179237Sjb/* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID, 664179237Sjb/* [54] */ INVALID, INVALID, INVALID, INVALID, 665179237Sjb/* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID, 666179237Sjb/* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8), 667179237Sjb 668179237Sjb/* [60] */ INVALID, INVALID, INVALID, INVALID, 669179237Sjb/* [64] */ INVALID, INVALID, INVALID, INVALID, 670179237Sjb/* [68] */ INVALID, INVALID, INVALID, INVALID, 671179237Sjb/* [6C] */ INVALID, INVALID, INVALID, INVALID, 672179237Sjb 673179237Sjb/* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID, 674179237Sjb/* [74] */ INVALID, INVALID, INVALID, INVALID, 675179237Sjb/* [78] */ INVALID, INVALID, INVALID, INVALID, 676179237Sjb/* [7C] */ INVALID, INVALID, INVALID, INVALID, 677179237Sjb 678179237Sjb/* [80] */ INVALID, INVALID, INVALID, INVALID, 679179237Sjb/* [84] */ INVALID, INVALID, INVALID, INVALID, 680179237Sjb/* [88] */ INVALID, INVALID, INVALID, INVALID, 681179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 682179237Sjb 683179237Sjb/* [90] */ INVALID, INVALID, INVALID, INVALID, 684179237Sjb/* [94] */ INVALID, INVALID, INVALID, INVALID, 685179237Sjb/* [98] */ INVALID, INVALID, INVALID, INVALID, 686179237Sjb/* [9C] */ INVALID, INVALID, INVALID, INVALID, 687179237Sjb 688179237Sjb/* [A0] */ INVALID, INVALID, INVALID, INVALID, 689179237Sjb/* [A4] */ INVALID, INVALID, INVALID, INVALID, 690179237Sjb/* [A8] */ INVALID, INVALID, INVALID, INVALID, 691179237Sjb/* [AC] */ INVALID, INVALID, INVALID, INVALID, 692179237Sjb 693179237Sjb/* [B0] */ INVALID, INVALID, INVALID, INVALID, 694179237Sjb/* [B4] */ INVALID, INVALID, INVALID, INVALID, 695179237Sjb/* [B8] */ INVALID, INVALID, INVALID, INVALID, 696179237Sjb/* [BC] */ INVALID, INVALID, INVALID, INVALID, 697179237Sjb 698179237Sjb/* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID, 699179237Sjb/* [C4] */ INVALID, INVALID, INVALID, INVALID, 700179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 701179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 702179237Sjb 703179237Sjb/* [D0] */ INVALID, INVALID, INVALID, INVALID, 704179237Sjb/* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID, 705179237Sjb/* [D8] */ INVALID, INVALID, INVALID, INVALID, 706179237Sjb/* [DC] */ INVALID, INVALID, INVALID, INVALID, 707179237Sjb 708179237Sjb/* [E0] */ INVALID, INVALID, INVALID, INVALID, 709179237Sjb/* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID, 710179237Sjb/* [E8] */ INVALID, INVALID, INVALID, INVALID, 711179237Sjb/* [EC] */ INVALID, INVALID, INVALID, INVALID, 712179237Sjb 713179237Sjb/* [F0] */ INVALID, INVALID, INVALID, INVALID, 714179237Sjb/* [F4] */ INVALID, INVALID, INVALID, INVALID, 715179237Sjb/* [F8] */ INVALID, INVALID, INVALID, INVALID, 716179237Sjb/* [FC] */ INVALID, INVALID, INVALID, INVALID, 717179237Sjb}; 718179237Sjb 719179237Sjb/* 720179237Sjb * Decode table for SIMD instructions with the repz (0xf3) prefix. 721179237Sjb */ 722179237Sjbconst instable_t dis_opSIMDrepz[256] = { 723179237Sjb/* [00] */ INVALID, INVALID, INVALID, INVALID, 724179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 725179237Sjb/* [08] */ INVALID, INVALID, INVALID, INVALID, 726179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 727179237Sjb 728179237Sjb/* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), INVALID, INVALID, 729179237Sjb/* [14] */ INVALID, INVALID, INVALID, INVALID, 730179237Sjb/* [18] */ INVALID, INVALID, INVALID, INVALID, 731179237Sjb/* [1C] */ INVALID, INVALID, INVALID, INVALID, 732179237Sjb 733179237Sjb/* [20] */ INVALID, INVALID, INVALID, INVALID, 734179237Sjb/* [24] */ INVALID, INVALID, INVALID, INVALID, 735179237Sjb/* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),INVALID, 736179237Sjb/* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID, 737179237Sjb 738179237Sjb/* [30] */ INVALID, INVALID, INVALID, INVALID, 739179237Sjb/* [34] */ INVALID, INVALID, INVALID, INVALID, 740179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 741179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 742179237Sjb 743179237Sjb/* [40] */ INVALID, INVALID, INVALID, INVALID, 744179237Sjb/* [44] */ INVALID, INVALID, INVALID, INVALID, 745179237Sjb/* [48] */ INVALID, INVALID, INVALID, INVALID, 746179237Sjb/* [4C] */ INVALID, INVALID, INVALID, INVALID, 747179237Sjb 748179237Sjb/* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4), 749179237Sjb/* [54] */ INVALID, INVALID, INVALID, INVALID, 750179237Sjb/* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16), 751179237Sjb/* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4), 752179237Sjb 753179237Sjb/* [60] */ INVALID, INVALID, INVALID, INVALID, 754179237Sjb/* [64] */ INVALID, INVALID, INVALID, INVALID, 755179237Sjb/* [68] */ INVALID, INVALID, INVALID, INVALID, 756179237Sjb/* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16), 757179237Sjb 758179237Sjb/* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID, 759179237Sjb/* [74] */ INVALID, INVALID, INVALID, INVALID, 760179237Sjb/* [78] */ INVALID, INVALID, INVALID, INVALID, 761179237Sjb/* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16), 762179237Sjb 763179237Sjb/* [80] */ INVALID, INVALID, INVALID, INVALID, 764179237Sjb/* [84] */ INVALID, INVALID, INVALID, INVALID, 765179237Sjb/* [88] */ INVALID, INVALID, INVALID, INVALID, 766179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 767179237Sjb 768179237Sjb/* [90] */ INVALID, INVALID, INVALID, INVALID, 769179237Sjb/* [94] */ INVALID, INVALID, INVALID, INVALID, 770179237Sjb/* [98] */ INVALID, INVALID, INVALID, INVALID, 771179237Sjb/* [9C] */ INVALID, INVALID, INVALID, INVALID, 772179237Sjb 773179237Sjb/* [A0] */ INVALID, INVALID, INVALID, INVALID, 774179237Sjb/* [A4] */ INVALID, INVALID, INVALID, INVALID, 775179237Sjb/* [A8] */ INVALID, INVALID, INVALID, INVALID, 776179237Sjb/* [AC] */ INVALID, INVALID, INVALID, INVALID, 777179237Sjb 778179237Sjb/* [B0] */ INVALID, INVALID, INVALID, INVALID, 779179237Sjb/* [B4] */ INVALID, INVALID, INVALID, INVALID, 780179237Sjb/* [B8] */ INVALID, INVALID, INVALID, INVALID, 781179237Sjb/* [BC] */ INVALID, INVALID, INVALID, INVALID, 782179237Sjb 783179237Sjb/* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID, 784179237Sjb/* [C4] */ INVALID, INVALID, INVALID, INVALID, 785179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 786179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 787179237Sjb 788179237Sjb/* [D0] */ INVALID, INVALID, INVALID, INVALID, 789179237Sjb/* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID, 790179237Sjb/* [D8] */ INVALID, INVALID, INVALID, INVALID, 791179237Sjb/* [DC] */ INVALID, INVALID, INVALID, INVALID, 792179237Sjb 793179237Sjb/* [E0] */ INVALID, INVALID, INVALID, INVALID, 794179237Sjb/* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID, 795179237Sjb/* [E8] */ INVALID, INVALID, INVALID, INVALID, 796179237Sjb/* [EC] */ INVALID, INVALID, INVALID, INVALID, 797179237Sjb 798179237Sjb/* [F0] */ INVALID, INVALID, INVALID, INVALID, 799179237Sjb/* [F4] */ INVALID, INVALID, INVALID, INVALID, 800179237Sjb/* [F8] */ INVALID, INVALID, INVALID, INVALID, 801179237Sjb/* [FC] */ INVALID, INVALID, INVALID, INVALID, 802179237Sjb}; 803179237Sjb 804179237Sjb/* 805179237Sjb * Decode table for 0x0F opcodes 806179237Sjb */ 807179237Sjb 808179237Sjbconst instable_t dis_op0F[16][16] = { 809179237Sjb{ 810179237Sjb/* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR), 811179237Sjb/* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM), 812179237Sjb/* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM), 813179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 814179237Sjb}, { 815179237Sjb/* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8), 816179237Sjb/* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8), 817179237Sjb/* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID, 818237748Savg/* [1C] */ INVALID, INVALID, INVALID, TNS("nopw", M), 819179237Sjb}, { 820179237Sjb/* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), 821179237Sjb/* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID, 822179237Sjb/* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16), 823179237Sjb/* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4), 824179237Sjb}, { 825179237Sjb/* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM), 826179237Sjb/* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID, 827179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 828179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 829179237Sjb}, { 830179237Sjb/* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR), 831179237Sjb/* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR), 832179237Sjb/* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR), 833179237Sjb/* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR), 834179237Sjb}, { 835179237Sjb/* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16), 836179237Sjb/* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16), 837179237Sjb/* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16), 838179237Sjb/* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16), 839179237Sjb}, { 840179237Sjb/* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8), 841179237Sjb/* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8), 842179237Sjb/* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8), 843179237Sjb/* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8), 844179237Sjb}, { 845179237Sjb/* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR), 846179237Sjb/* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM), 847179237Sjb/* [78] */ INVALID, INVALID, INVALID, INVALID, 848179237Sjb/* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8), 849179237Sjb}, { 850179237Sjb/* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D), 851179237Sjb/* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D), 852179237Sjb/* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D), 853179237Sjb/* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D), 854179237Sjb}, { 855179237Sjb/* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb), 856179237Sjb/* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb), 857179237Sjb/* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb), 858179237Sjb/* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb), 859179237Sjb}, { 860179237Sjb/* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw), 861179237Sjb/* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID, 862179237Sjb/* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw), 863179237Sjb/* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw), 864179237Sjb}, { 865179237Sjb/* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw), 866179237Sjb/* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ), 867179237Sjb/* [B8] */ INVALID, INVALID, IND(dis_op0FBA), TS("btc",RMw), 868179237Sjb/* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ), 869179237Sjb}, { 870179237Sjb/* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM), 871179237Sjb/* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7), 872179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 873179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 874179237Sjb}, { 875179237Sjb/* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8), 876179237Sjb/* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3), 877179237Sjb/* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8), 878179237Sjb/* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8), 879179237Sjb}, { 880179237Sjb/* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8), 881179237Sjb/* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8), 882179237Sjb/* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8), 883179237Sjb/* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8), 884179237Sjb}, { 885179237Sjb/* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8), 886179237Sjb/* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8), 887179237Sjb/* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8), 888179237Sjb/* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID, 889179237Sjb} }; 890179237Sjb 891179237Sjb 892179237Sjb/* 893179237Sjb * Decode table for 0x80 opcodes 894179237Sjb */ 895179237Sjb 896179237Sjbconst instable_t dis_op80[8] = { 897179237Sjb 898179237Sjb/* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw), 899179237Sjb/* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw), 900179237Sjb}; 901179237Sjb 902179237Sjb 903179237Sjb/* 904179237Sjb * Decode table for 0x81 opcodes. 905179237Sjb */ 906179237Sjb 907179237Sjbconst instable_t dis_op81[8] = { 908179237Sjb 909179237Sjb/* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw), 910179237Sjb/* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw), 911179237Sjb}; 912179237Sjb 913179237Sjb 914179237Sjb/* 915179237Sjb * Decode table for 0x82 opcodes. 916179237Sjb */ 917179237Sjb 918179237Sjbconst instable_t dis_op82[8] = { 919179237Sjb 920179237Sjb/* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw), 921179237Sjb/* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw), 922179237Sjb}; 923179237Sjb/* 924179237Sjb * Decode table for 0x83 opcodes. 925179237Sjb */ 926179237Sjb 927179237Sjbconst instable_t dis_op83[8] = { 928179237Sjb 929179237Sjb/* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw), 930179237Sjb/* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw), 931179237Sjb}; 932179237Sjb 933179237Sjb/* 934179237Sjb * Decode table for 0xC0 opcodes. 935179237Sjb */ 936179237Sjb 937179237Sjbconst instable_t dis_opC0[8] = { 938179237Sjb 939179237Sjb/* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI), 940179237Sjb/* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI), 941179237Sjb}; 942179237Sjb 943179237Sjb/* 944179237Sjb * Decode table for 0xD0 opcodes. 945179237Sjb */ 946179237Sjb 947179237Sjbconst instable_t dis_opD0[8] = { 948179237Sjb 949179237Sjb/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 950179237Sjb/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 951179237Sjb}; 952179237Sjb 953179237Sjb/* 954179237Sjb * Decode table for 0xC1 opcodes. 955179237Sjb * 186 instruction set 956179237Sjb */ 957179237Sjb 958179237Sjbconst instable_t dis_opC1[8] = { 959179237Sjb 960179237Sjb/* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI), 961179237Sjb/* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI), 962179237Sjb}; 963179237Sjb 964179237Sjb/* 965179237Sjb * Decode table for 0xD1 opcodes. 966179237Sjb */ 967179237Sjb 968179237Sjbconst instable_t dis_opD1[8] = { 969179237Sjb 970179237Sjb/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 971179237Sjb/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv), 972179237Sjb}; 973179237Sjb 974179237Sjb 975179237Sjb/* 976179237Sjb * Decode table for 0xD2 opcodes. 977179237Sjb */ 978179237Sjb 979179237Sjbconst instable_t dis_opD2[8] = { 980179237Sjb 981179237Sjb/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 982179237Sjb/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 983179237Sjb}; 984179237Sjb/* 985179237Sjb * Decode table for 0xD3 opcodes. 986179237Sjb */ 987179237Sjb 988179237Sjbconst instable_t dis_opD3[8] = { 989179237Sjb 990179237Sjb/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 991179237Sjb/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv), 992179237Sjb}; 993179237Sjb 994179237Sjb 995179237Sjb/* 996179237Sjb * Decode table for 0xF6 opcodes. 997179237Sjb */ 998179237Sjb 999179237Sjbconst instable_t dis_opF6[8] = { 1000179237Sjb 1001179237Sjb/* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw), 1002179237Sjb/* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA), 1003179237Sjb}; 1004179237Sjb 1005179237Sjb 1006179237Sjb/* 1007179237Sjb * Decode table for 0xF7 opcodes. 1008179237Sjb */ 1009179237Sjb 1010179237Sjbconst instable_t dis_opF7[8] = { 1011179237Sjb 1012179237Sjb/* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw), 1013179237Sjb/* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA), 1014179237Sjb}; 1015179237Sjb 1016179237Sjb 1017179237Sjb/* 1018179237Sjb * Decode table for 0xFE opcodes. 1019179237Sjb */ 1020179237Sjb 1021179237Sjbconst instable_t dis_opFE[8] = { 1022179237Sjb 1023179237Sjb/* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID, 1024179237Sjb/* [4] */ INVALID, INVALID, INVALID, INVALID, 1025179237Sjb}; 1026179237Sjb/* 1027179237Sjb * Decode table for 0xFF opcodes. 1028179237Sjb */ 1029179237Sjb 1030179237Sjbconst instable_t dis_opFF[8] = { 1031179237Sjb 1032179237Sjb/* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM), 1033179237Sjb/* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID, 1034179237Sjb}; 1035179237Sjb 1036179237Sjb/* for 287 instructions, which are a mess to decode */ 1037179237Sjb 1038179237Sjbconst instable_t dis_opFP1n2[8][8] = { 1039179237Sjb{ 1040179237Sjb/* bit pattern: 1101 1xxx MODxx xR/M */ 1041179237Sjb/* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M), 1042179237Sjb/* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M), 1043179237Sjb}, { 1044179237Sjb/* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M), 1045179237Sjb/* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2), 1046179237Sjb}, { 1047179237Sjb/* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M), 1048179237Sjb/* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M), 1049179237Sjb}, { 1050179237Sjb/* [3,0] */ TNS("fildl",M), INVALID, TNS("fistl",M), TNS("fistpl",M), 1051179237Sjb/* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10), 1052179237Sjb}, { 1053179237Sjb/* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8), 1054179237Sjb/* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8), 1055179237Sjb}, { 1056179237Sjb/* [5,0] */ TNSZ("fldl",M,8), INVALID, TNSZ("fstl",M,8), TNSZ("fstpl",M,8), 1057179237Sjb/* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2), 1058179237Sjb}, { 1059179237Sjb/* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2), 1060179237Sjb/* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2), 1061179237Sjb}, { 1062179237Sjb/* [7,0] */ TNSZ("fild",M,2), INVALID, TNSZ("fist",M,2), TNSZ("fistp",M,2), 1063179237Sjb/* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8), 1064179237Sjb} }; 1065179237Sjb 1066179237Sjbconst instable_t dis_opFP3[8][8] = { 1067179237Sjb{ 1068179237Sjb/* bit pattern: 1101 1xxx 11xx xREG */ 1069179237Sjb/* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 1070179237Sjb/* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 1071179237Sjb}, { 1072179237Sjb/* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F), 1073179237Sjb/* [1,4] */ INVALID, INVALID, INVALID, INVALID, 1074179237Sjb}, { 1075179237Sjb/* [2,0] */ INVALID, INVALID, INVALID, INVALID, 1076179237Sjb/* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID, 1077179237Sjb}, { 1078179237Sjb/* [3,0] */ INVALID, INVALID, INVALID, INVALID, 1079179237Sjb/* [3,4] */ INVALID, INVALID, INVALID, INVALID, 1080179237Sjb}, { 1081179237Sjb/* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 1082179237Sjb/* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 1083179237Sjb}, { 1084179237Sjb/* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F), 1085179237Sjb/* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID, 1086179237Sjb}, { 1087179237Sjb/* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM), 1088179237Sjb/* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF), 1089179237Sjb}, { 1090179237Sjb/* [7,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F), 1091179237Sjb/* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID, 1092179237Sjb} }; 1093179237Sjb 1094179237Sjbconst instable_t dis_opFP4[4][8] = { 1095179237Sjb{ 1096179237Sjb/* bit pattern: 1101 1001 111x xxxx */ 1097179237Sjb/* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID, 1098179237Sjb/* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID, 1099179237Sjb}, { 1100179237Sjb/* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM), 1101179237Sjb/* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID, 1102179237Sjb}, { 1103179237Sjb/* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM), 1104179237Sjb/* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM), 1105179237Sjb}, { 1106179237Sjb/* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM), 1107179237Sjb/* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM), 1108179237Sjb} }; 1109179237Sjb 1110179237Sjbconst instable_t dis_opFP5[8] = { 1111179237Sjb/* bit pattern: 1101 1011 111x xxxx */ 1112179237Sjb/* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM), 1113179237Sjb/* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID, 1114179237Sjb}; 1115179237Sjb 1116179237Sjbconst instable_t dis_opFP6[8] = { 1117179237Sjb/* bit pattern: 1101 1011 11yy yxxx */ 1118179237Sjb/* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF), 1119179237Sjb/* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID, 1120179237Sjb}; 1121179237Sjb 1122179237Sjbconst instable_t dis_opFP7[8] = { 1123179237Sjb/* bit pattern: 1101 1010 11yy yxxx */ 1124179237Sjb/* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF), 1125179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 1126179237Sjb}; 1127179237Sjb 1128179237Sjb/* 1129179237Sjb * Main decode table for the op codes. The first two nibbles 1130179237Sjb * will be used as an index into the table. If there is a 1131179237Sjb * a need to further decode an instruction, the array to be 1132179237Sjb * referenced is indicated with the other two entries being 1133179237Sjb * empty. 1134179237Sjb */ 1135179237Sjb 1136179237Sjbconst instable_t dis_distable[16][16] = { 1137179237Sjb{ 1138179237Sjb/* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw), 1139179237Sjb/* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG), 1140179237Sjb/* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw), 1141179237Sjb/* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(&dis_op0F[0][0]), 1142179237Sjb}, { 1143179237Sjb/* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw), 1144179237Sjb/* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG), 1145179237Sjb/* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw), 1146179237Sjb/* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG), 1147179237Sjb}, { 1148179237Sjb/* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw), 1149238168Savg/* [2,4] */ TNS("andb",IA), TS("and",IA), TNS("%es:",OVERRIDE), TNSx("daa",NORM), 1150179237Sjb/* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw), 1151238168Savg/* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM), 1152179237Sjb}, { 1153179237Sjb/* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw), 1154238168Savg/* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNS("%ss:",OVERRIDE), TNSx("aaa",NORM), 1155179237Sjb/* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw), 1156238168Savg/* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNS("%ds:",OVERRIDE), TNSx("aas",NORM), 1157179237Sjb}, { 1158179237Sjb/* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 1159179237Sjb/* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 1160179237Sjb/* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 1161179237Sjb/* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 1162179237Sjb}, { 1163179237Sjb/* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 1164179237Sjb/* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 1165179237Sjb/* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 1166179237Sjb/* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 1167179237Sjb}, { 1168179237Sjb/* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw), 1169179237Sjb/* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM), 1170179237Sjb/* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL), 1171179237Sjb/* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4), 1172179237Sjb}, { 1173179237Sjb/* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD), 1174179237Sjb/* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD), 1175179237Sjb/* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD), 1176179237Sjb/* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD), 1177179237Sjb}, { 1178179237Sjb/* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83), 1179179237Sjb/* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw), 1180179237Sjb/* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw), 1181179237Sjb/* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M), 1182179237Sjb}, { 1183179237Sjb/* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 1184179237Sjb/* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 1185179237Sjb/* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM), 1186179237Sjb/* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNSx("sahf",NORM), TNSx("lahf",NORM), 1187179237Sjb}, { 1188179237Sjb/* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO), 1189179237Sjb/* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD), 1190179237Sjb/* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD), 1191179237Sjb/* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD), 1192179237Sjb}, { 1193179237Sjb/* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 1194179237Sjb/* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 1195179237Sjb/* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 1196179237Sjb/* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 1197179237Sjb}, { 1198179237Sjb/* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM), 1199179237Sjb/* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw), 1200179237Sjb/* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM), 1201179237Sjb/* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM), 1202179237Sjb}, { 1203179237Sjb/* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3), 1204179237Sjb/* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1), 1205179237Sjb 1206179237Sjb/* 287 instructions. Note that although the indirect field */ 1207179237Sjb/* indicates opFP1n2 for further decoding, this is not necessarily */ 1208179237Sjb/* the case since the opFP arrays are not partitioned according to key1 */ 1209179237Sjb/* and key2. opFP1n2 is given only to indicate that we haven't */ 1210179237Sjb/* finished decoding the instruction. */ 1211179237Sjb/* [D,8] */ IND(&dis_opFP1n2[0][0]), IND(&dis_opFP1n2[0][0]), IND(&dis_opFP1n2[0][0]), IND(&dis_opFP1n2[0][0]), 1212179237Sjb/* [D,C] */ IND(&dis_opFP1n2[0][0]), IND(&dis_opFP1n2[0][0]), IND(&dis_opFP1n2[0][0]), IND(&dis_opFP1n2[0][0]), 1213179237Sjb}, { 1214179237Sjb/* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD), 1215179237Sjb/* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P), 1216179237Sjb/* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD), 1217179237Sjb/* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V), 1218179237Sjb}, { 1219179237Sjb/* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX), 1220179237Sjb/* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7), 1221179237Sjb/* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM), 1222179237Sjb/* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF), 1223179237Sjb} }; 1224179237Sjb 1225179237Sjb/* END CSTYLED */ 1226179237Sjb 1227179237Sjb/* 1228179237Sjb * common functions to decode and disassemble an x86 or amd64 instruction 1229179237Sjb */ 1230179237Sjb 1231179237Sjb/* 1232179237Sjb * These are the individual fields of a REX prefix. Note that a REX 1233179237Sjb * prefix with none of these set is still needed to: 1234179237Sjb * - use the MOVSXD (sign extend 32 to 64 bits) instruction 1235179237Sjb * - access the %sil, %dil, %bpl, %spl registers 1236179237Sjb */ 1237179237Sjb#define REX_W 0x08 /* 64 bit operand size when set */ 1238179237Sjb#define REX_R 0x04 /* high order bit extension of ModRM reg field */ 1239179237Sjb#define REX_X 0x02 /* high order bit extension of SIB index field */ 1240179237Sjb#define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */ 1241179237Sjb 1242179237Sjbstatic uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */ 1243179237Sjbstatic uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */ 1244179237Sjb 1245179237Sjb/* 1246179237Sjb * Even in 64 bit mode, usually only 4 byte immediate operands are supported. 1247179237Sjb */ 1248179237Sjbstatic int isize[] = {1, 2, 4, 4}; 1249179237Sjbstatic int isize64[] = {1, 2, 4, 8}; 1250179237Sjb 1251179237Sjb/* 1252179237Sjb * Just a bunch of useful macros. 1253179237Sjb */ 1254179237Sjb#define WBIT(x) (x & 0x1) /* to get w bit */ 1255179237Sjb#define REGNO(x) (x & 0x7) /* to get 3 bit register */ 1256179237Sjb#define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */ 1257179237Sjb#define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1) 1258179237Sjb#define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1) 1259179237Sjb 1260179237Sjb#define REG_ONLY 3 /* mode to indicate a register operand (not memory) */ 1261179237Sjb 1262179237Sjb#define BYTE_OPND 0 /* w-bit value indicating byte register */ 1263179237Sjb#define LONG_OPND 1 /* w-bit value indicating opnd_size register */ 1264179237Sjb#define MM_OPND 2 /* "value" used to indicate a mmx reg */ 1265179237Sjb#define XMM_OPND 3 /* "value" used to indicate a xmm reg */ 1266179237Sjb#define SEG_OPND 4 /* "value" used to indicate a segment reg */ 1267179237Sjb#define CONTROL_OPND 5 /* "value" used to indicate a control reg */ 1268179237Sjb#define DEBUG_OPND 6 /* "value" used to indicate a debug reg */ 1269179237Sjb#define TEST_OPND 7 /* "value" used to indicate a test reg */ 1270179237Sjb#define WORD_OPND 8 /* w-bit value indicating word size reg */ 1271179237Sjb 1272179237Sjb/* 1273179237Sjb * Get the next byte and separate the op code into the high and low nibbles. 1274179237Sjb */ 1275179237Sjbstatic int 1276179237Sjbdtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low) 1277179237Sjb{ 1278179237Sjb int byte; 1279179237Sjb 1280179237Sjb /* 1281179237Sjb * x86 instructions have a maximum length of 15 bytes. Bail out if 1282179237Sjb * we try to read more. 1283179237Sjb */ 1284179237Sjb if (x->d86_len >= 15) 1285179237Sjb return (x->d86_error = 1); 1286179237Sjb 1287179237Sjb if (x->d86_error) 1288179237Sjb return (1); 1289179237Sjb byte = x->d86_get_byte(x->d86_data); 1290179237Sjb if (byte < 0) 1291179237Sjb return (x->d86_error = 1); 1292179237Sjb x->d86_bytes[x->d86_len++] = byte; 1293179237Sjb *low = byte & 0xf; /* ----xxxx low 4 bits */ 1294179237Sjb *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */ 1295179237Sjb return (0); 1296179237Sjb} 1297179237Sjb 1298179237Sjb/* 1299179237Sjb * Get and decode an SIB (scaled index base) byte 1300179237Sjb */ 1301179237Sjbstatic void 1302179237Sjbdtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base) 1303179237Sjb{ 1304179237Sjb int byte; 1305179237Sjb 1306179237Sjb if (x->d86_error) 1307179237Sjb return; 1308179237Sjb 1309179237Sjb byte = x->d86_get_byte(x->d86_data); 1310179237Sjb if (byte < 0) { 1311179237Sjb x->d86_error = 1; 1312179237Sjb return; 1313179237Sjb } 1314179237Sjb x->d86_bytes[x->d86_len++] = byte; 1315179237Sjb 1316179237Sjb *base = byte & 0x7; 1317179237Sjb *index = (byte >> 3) & 0x7; 1318179237Sjb *ss = (byte >> 6) & 0x3; 1319179237Sjb} 1320179237Sjb 1321179237Sjb/* 1322179237Sjb * Get the byte following the op code and separate it into the 1323179237Sjb * mode, register, and r/m fields. 1324179237Sjb */ 1325179237Sjbstatic void 1326179237Sjbdtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m) 1327179237Sjb{ 1328179237Sjb if (x->d86_got_modrm == 0) { 1329179237Sjb if (x->d86_rmindex == -1) 1330179237Sjb x->d86_rmindex = x->d86_len; 1331179237Sjb dtrace_get_SIB(x, mode, reg, r_m); 1332179237Sjb x->d86_got_modrm = 1; 1333179237Sjb } 1334179237Sjb} 1335179237Sjb 1336179237Sjb/* 1337179237Sjb * Adjust register selection based on any REX prefix bits present. 1338179237Sjb */ 1339179237Sjb/*ARGSUSED*/ 1340179237Sjbstatic void 1341179237Sjbdtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m) 1342179237Sjb{ 1343179237Sjb if (reg != NULL && r_m == NULL) { 1344179237Sjb if (rex_prefix & REX_B) 1345179237Sjb *reg += 8; 1346179237Sjb } else { 1347179237Sjb if (reg != NULL && (REX_R & rex_prefix) != 0) 1348179237Sjb *reg += 8; 1349179237Sjb if (r_m != NULL && (REX_B & rex_prefix) != 0) 1350179237Sjb *r_m += 8; 1351179237Sjb } 1352179237Sjb} 1353179237Sjb 1354179237Sjb/* 1355179237Sjb * Get an immediate operand of the given size, with sign extension. 1356179237Sjb */ 1357179237Sjbstatic void 1358179237Sjbdtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex) 1359179237Sjb{ 1360179237Sjb int i; 1361179237Sjb int byte; 1362179237Sjb int valsize = 0; 1363179237Sjb 1364179237Sjb if (x->d86_numopnds < opindex + 1) 1365179237Sjb x->d86_numopnds = opindex + 1; 1366179237Sjb 1367179237Sjb switch (wbit) { 1368179237Sjb case BYTE_OPND: 1369179237Sjb valsize = 1; 1370179237Sjb break; 1371179237Sjb case LONG_OPND: 1372179237Sjb if (x->d86_opnd_size == SIZE16) 1373179237Sjb valsize = 2; 1374179237Sjb else if (x->d86_opnd_size == SIZE32) 1375179237Sjb valsize = 4; 1376179237Sjb else 1377179237Sjb valsize = 8; 1378179237Sjb break; 1379179237Sjb case MM_OPND: 1380179237Sjb case XMM_OPND: 1381179237Sjb case SEG_OPND: 1382179237Sjb case CONTROL_OPND: 1383179237Sjb case DEBUG_OPND: 1384179237Sjb case TEST_OPND: 1385179237Sjb valsize = size; 1386179237Sjb break; 1387179237Sjb case WORD_OPND: 1388179237Sjb valsize = 2; 1389179237Sjb break; 1390179237Sjb } 1391179237Sjb if (valsize < size) 1392179237Sjb valsize = size; 1393179237Sjb 1394179237Sjb if (x->d86_error) 1395179237Sjb return; 1396179237Sjb x->d86_opnd[opindex].d86_value = 0; 1397179237Sjb for (i = 0; i < size; ++i) { 1398179237Sjb byte = x->d86_get_byte(x->d86_data); 1399179237Sjb if (byte < 0) { 1400179237Sjb x->d86_error = 1; 1401179237Sjb return; 1402179237Sjb } 1403179237Sjb x->d86_bytes[x->d86_len++] = byte; 1404179237Sjb x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8); 1405179237Sjb } 1406179237Sjb /* Do sign extension */ 1407179237Sjb if (x->d86_bytes[x->d86_len - 1] & 0x80) { 1408179237Sjb for (; i < valsize; i++) 1409179237Sjb x->d86_opnd[opindex].d86_value |= 1410179237Sjb (uint64_t)0xff << (i* 8); 1411179237Sjb } 1412179237Sjb#ifdef DIS_TEXT 1413179237Sjb x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 1414179237Sjb x->d86_opnd[opindex].d86_value_size = valsize; 1415179237Sjb x->d86_imm_bytes += size; 1416179237Sjb#endif 1417179237Sjb} 1418179237Sjb 1419179237Sjb/* 1420179237Sjb * Get an ip relative operand of the given size, with sign extension. 1421179237Sjb */ 1422179237Sjbstatic void 1423179237Sjbdtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex) 1424179237Sjb{ 1425179237Sjb dtrace_imm_opnd(x, wbit, size, opindex); 1426179237Sjb#ifdef DIS_TEXT 1427179237Sjb x->d86_opnd[opindex].d86_mode = MODE_IPREL; 1428179237Sjb#endif 1429179237Sjb} 1430179237Sjb 1431179237Sjb/* 1432179237Sjb * Check to see if there is a segment override prefix pending. 1433179237Sjb * If so, print it in the current 'operand' location and set 1434179237Sjb * the override flag back to false. 1435179237Sjb */ 1436179237Sjb/*ARGSUSED*/ 1437179237Sjbstatic void 1438179237Sjbdtrace_check_override(dis86_t *x, int opindex) 1439179237Sjb{ 1440179237Sjb#ifdef DIS_TEXT 1441179237Sjb if (x->d86_seg_prefix) { 1442179237Sjb (void) strlcat(x->d86_opnd[opindex].d86_prefix, 1443179237Sjb x->d86_seg_prefix, PFIXLEN); 1444179237Sjb } 1445179237Sjb#endif 1446179237Sjb x->d86_seg_prefix = NULL; 1447179237Sjb} 1448179237Sjb 1449179237Sjb 1450179237Sjb/* 1451179237Sjb * Process a single instruction Register or Memory operand. 1452179237Sjb * 1453179237Sjb * mode = addressing mode from ModRM byte 1454179237Sjb * r_m = r_m (or reg if mode == 3) field from ModRM byte 1455179237Sjb * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use. 1456179237Sjb * o = index of operand that we are processing (0, 1 or 2) 1457179237Sjb * 1458179237Sjb * the value of reg or r_m must have already been adjusted for any REX prefix. 1459179237Sjb */ 1460179237Sjb/*ARGSUSED*/ 1461179237Sjbstatic void 1462179237Sjbdtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) 1463179237Sjb{ 1464179237Sjb int have_SIB = 0; /* flag presence of scale-index-byte */ 1465179237Sjb uint_t ss; /* scale-factor from opcode */ 1466179237Sjb uint_t index; /* index register number */ 1467179237Sjb uint_t base; /* base register number */ 1468179237Sjb int dispsize; /* size of displacement in bytes */ 1469179237Sjb#ifdef DIS_TEXT 1470179237Sjb char *opnd = x->d86_opnd[opindex].d86_opnd; 1471179237Sjb#endif 1472179237Sjb 1473179237Sjb if (x->d86_numopnds < opindex + 1) 1474179237Sjb x->d86_numopnds = opindex + 1; 1475179237Sjb 1476179237Sjb if (x->d86_error) 1477179237Sjb return; 1478179237Sjb 1479179237Sjb /* 1480179237Sjb * first handle a simple register 1481179237Sjb */ 1482179237Sjb if (mode == REG_ONLY) { 1483179237Sjb#ifdef DIS_TEXT 1484179237Sjb switch (wbit) { 1485179237Sjb case MM_OPND: 1486179237Sjb (void) strlcat(opnd, dis_MMREG[r_m], OPLEN); 1487179237Sjb break; 1488179237Sjb case XMM_OPND: 1489179237Sjb (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN); 1490179237Sjb break; 1491179237Sjb case SEG_OPND: 1492179237Sjb (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN); 1493179237Sjb break; 1494179237Sjb case CONTROL_OPND: 1495179237Sjb (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); 1496179237Sjb break; 1497179237Sjb case DEBUG_OPND: 1498179237Sjb (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); 1499179237Sjb break; 1500179237Sjb case TEST_OPND: 1501179237Sjb (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN); 1502179237Sjb break; 1503179237Sjb case BYTE_OPND: 1504179237Sjb if (x->d86_rex_prefix == 0) 1505179237Sjb (void) strlcat(opnd, dis_REG8[r_m], OPLEN); 1506179237Sjb else 1507179237Sjb (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN); 1508179237Sjb break; 1509179237Sjb case WORD_OPND: 1510179237Sjb (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 1511179237Sjb break; 1512179237Sjb case LONG_OPND: 1513179237Sjb if (x->d86_opnd_size == SIZE16) 1514179237Sjb (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 1515179237Sjb else if (x->d86_opnd_size == SIZE32) 1516179237Sjb (void) strlcat(opnd, dis_REG32[r_m], OPLEN); 1517179237Sjb else 1518179237Sjb (void) strlcat(opnd, dis_REG64[r_m], OPLEN); 1519179237Sjb break; 1520179237Sjb } 1521179237Sjb#endif /* DIS_TEXT */ 1522179237Sjb return; 1523179237Sjb } 1524179237Sjb 1525179237Sjb /* 1526179237Sjb * if symbolic representation, skip override prefix, if any 1527179237Sjb */ 1528179237Sjb dtrace_check_override(x, opindex); 1529179237Sjb 1530179237Sjb /* 1531179237Sjb * Handle 16 bit memory references first, since they decode 1532179237Sjb * the mode values more simply. 1533179237Sjb * mode 1 is r_m + 8 bit displacement 1534179237Sjb * mode 2 is r_m + 16 bit displacement 1535179237Sjb * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp 1536179237Sjb */ 1537179237Sjb if (x->d86_addr_size == SIZE16) { 1538179237Sjb if ((mode == 0 && r_m == 6) || mode == 2) 1539179237Sjb dtrace_imm_opnd(x, WORD_OPND, 2, opindex); 1540179237Sjb else if (mode == 1) 1541179237Sjb dtrace_imm_opnd(x, BYTE_OPND, 1, opindex); 1542179237Sjb#ifdef DIS_TEXT 1543179237Sjb if (mode == 0 && r_m == 6) 1544179237Sjb x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 1545179237Sjb else if (mode == 0) 1546179237Sjb x->d86_opnd[opindex].d86_mode = MODE_NONE; 1547179237Sjb else 1548179237Sjb x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 1549179237Sjb (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN); 1550179237Sjb#endif 1551179237Sjb return; 1552179237Sjb } 1553179237Sjb 1554179237Sjb /* 1555179237Sjb * 32 and 64 bit addressing modes are more complex since they 1556179237Sjb * can involve an SIB (scaled index and base) byte to decode. 1557179237Sjb */ 1558179237Sjb if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) { 1559179237Sjb have_SIB = 1; 1560179237Sjb dtrace_get_SIB(x, &ss, &index, &base); 1561179237Sjb if (x->d86_error) 1562179237Sjb return; 1563179237Sjb if (base != 5 || mode != 0) 1564179237Sjb if (x->d86_rex_prefix & REX_B) 1565179237Sjb base += 8; 1566179237Sjb if (x->d86_rex_prefix & REX_X) 1567179237Sjb index += 8; 1568179237Sjb } else { 1569179237Sjb base = r_m; 1570179237Sjb } 1571179237Sjb 1572179237Sjb /* 1573179237Sjb * Compute the displacement size and get its bytes 1574179237Sjb */ 1575179237Sjb dispsize = 0; 1576179237Sjb 1577179237Sjb if (mode == 1) 1578179237Sjb dispsize = 1; 1579179237Sjb else if (mode == 2) 1580179237Sjb dispsize = 4; 1581179237Sjb else if ((r_m & 7) == EBP_REGNO || 1582179237Sjb (have_SIB && (base & 7) == EBP_REGNO)) 1583179237Sjb dispsize = 4; 1584179237Sjb 1585179237Sjb if (dispsize > 0) { 1586179237Sjb dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND, 1587179237Sjb dispsize, opindex); 1588179237Sjb if (x->d86_error) 1589179237Sjb return; 1590179237Sjb } 1591179237Sjb 1592179237Sjb#ifdef DIS_TEXT 1593179237Sjb if (dispsize > 0) 1594179237Sjb x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 1595179237Sjb 1596179237Sjb if (have_SIB == 0) { 1597179237Sjb if (x->d86_mode == SIZE32) { 1598179237Sjb if (mode == 0) 1599179237Sjb (void) strlcat(opnd, dis_addr32_mode0[r_m], 1600179237Sjb OPLEN); 1601179237Sjb else 1602179237Sjb (void) strlcat(opnd, dis_addr32_mode12[r_m], 1603179237Sjb OPLEN); 1604179237Sjb } else { 1605179237Sjb if (mode == 0) 1606179237Sjb (void) strlcat(opnd, dis_addr64_mode0[r_m], 1607179237Sjb OPLEN); 1608179237Sjb else 1609179237Sjb (void) strlcat(opnd, dis_addr64_mode12[r_m], 1610179237Sjb OPLEN); 1611179237Sjb } 1612179237Sjb } else { 1613179237Sjb uint_t need_paren = 0; 1614179237Sjb char **regs; 1615179237Sjb if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */ 1616179237Sjb regs = (char **)dis_REG32; 1617179237Sjb else 1618179237Sjb regs = (char **)dis_REG64; 1619179237Sjb 1620179237Sjb /* 1621179237Sjb * print the base (if any) 1622179237Sjb */ 1623179237Sjb if (base == EBP_REGNO && mode == 0) { 1624179237Sjb if (index != ESP_REGNO) { 1625179237Sjb (void) strlcat(opnd, "(", OPLEN); 1626179237Sjb need_paren = 1; 1627179237Sjb } 1628179237Sjb } else { 1629179237Sjb (void) strlcat(opnd, "(", OPLEN); 1630179237Sjb (void) strlcat(opnd, regs[base], OPLEN); 1631179237Sjb need_paren = 1; 1632179237Sjb } 1633179237Sjb 1634179237Sjb /* 1635179237Sjb * print the index (if any) 1636179237Sjb */ 1637179237Sjb if (index != ESP_REGNO) { 1638179237Sjb (void) strlcat(opnd, ",", OPLEN); 1639179237Sjb (void) strlcat(opnd, regs[index], OPLEN); 1640179237Sjb (void) strlcat(opnd, dis_scale_factor[ss], OPLEN); 1641179237Sjb } else 1642179237Sjb if (need_paren) 1643179237Sjb (void) strlcat(opnd, ")", OPLEN); 1644179237Sjb } 1645179237Sjb#endif 1646179237Sjb} 1647179237Sjb 1648179237Sjb/* 1649179237Sjb * Operand sequence for standard instruction involving one register 1650179237Sjb * and one register/memory operand. 1651179237Sjb * wbit indicates a byte(0) or opnd_size(1) operation 1652179237Sjb * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r") 1653179237Sjb */ 1654179237Sjb#define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \ 1655179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); \ 1656179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 1657179237Sjb dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 1658179237Sjb dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \ 1659179237Sjb} 1660179237Sjb 1661179237Sjb/* 1662179237Sjb * Similar to above, but allows for the two operands to be of different 1663179237Sjb * classes (ie. wbit). 1664179237Sjb * wbit is for the r_m operand 1665179237Sjb * w2 is for the reg operand 1666179237Sjb */ 1667179237Sjb#define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \ 1668179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); \ 1669179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 1670179237Sjb dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 1671179237Sjb dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \ 1672179237Sjb} 1673179237Sjb 1674179237Sjb/* 1675179237Sjb * Similar, but for 2 operands plus an immediate. 1676179237Sjb */ 1677179237Sjb#define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \ 1678179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); \ 1679179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 1680179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); \ 1681179237Sjb dtrace_get_operand(x, REG_ONLY, reg, w2, 2); \ 1682179237Sjb dtrace_imm_opnd(x, wbit, immsize, 0); \ 1683179237Sjb} 1684179237Sjb 1685179237Sjb/* 1686179237Sjb * Dissassemble a single x86 or amd64 instruction. 1687179237Sjb * 1688179237Sjb * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64) 1689179237Sjb * for interpreting instructions. 1690179237Sjb * 1691179237Sjb * returns non-zero for bad opcode 1692179237Sjb */ 1693179237Sjbint 1694179237Sjbdtrace_disx86(dis86_t *x, uint_t cpu_mode) 1695179237Sjb{ 1696179237Sjb const instable_t *dp = NULL; /* decode table being used */ 1697179237Sjb#ifdef DIS_TEXT 1698179237Sjb uint_t i; 1699179237Sjb#endif 1700179237Sjb#ifdef DIS_MEM 1701179237Sjb uint_t nomem = 0; 1702179237Sjb#define NOMEM (nomem = 1) 1703179237Sjb#else 1704179237Sjb#define NOMEM /* nothing */ 1705179237Sjb#endif 1706179237Sjb uint_t wbit = 0; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */ 1707179237Sjb uint_t w2; /* wbit value for second operand */ 1708179237Sjb uint_t vbit; 1709179237Sjb uint_t mode = 0; /* mode value from ModRM byte */ 1710179237Sjb uint_t reg; /* reg value from ModRM byte */ 1711179237Sjb uint_t r_m; /* r_m value from ModRM byte */ 1712179237Sjb 1713179237Sjb uint_t opcode1; /* high nibble of 1st byte */ 1714179237Sjb uint_t opcode2; /* low nibble of 1st byte */ 1715179237Sjb uint_t opcode3; /* extra opcode bits usually from ModRM byte */ 1716179237Sjb uint_t opcode4; /* high nibble of 2nd byte */ 1717179237Sjb uint_t opcode5; /* low nibble of 2ne byte */ 1718179237Sjb uint_t opcode6; /* high nibble of 3rd byte */ 1719179237Sjb uint_t opcode7; /* low nibble of 3rd byte */ 1720179237Sjb uint_t opcode_bytes = 1; 1721179237Sjb 1722179237Sjb /* 1723179237Sjb * legacy prefixes come in 5 flavors, you should have only one of each 1724179237Sjb */ 1725179237Sjb uint_t opnd_size_prefix = 0; 1726179237Sjb uint_t addr_size_prefix = 0; 1727179237Sjb uint_t segment_prefix = 0; 1728179237Sjb uint_t lock_prefix = 0; 1729179237Sjb uint_t rep_prefix = 0; 1730179237Sjb uint_t rex_prefix = 0; /* amd64 register extension prefix */ 1731179237Sjb size_t off; 1732179237Sjb 1733179237Sjb x->d86_len = 0; 1734179237Sjb x->d86_rmindex = -1; 1735179237Sjb x->d86_error = 0; 1736179237Sjb#ifdef DIS_TEXT 1737179237Sjb x->d86_numopnds = 0; 1738179237Sjb x->d86_seg_prefix = NULL; 1739179237Sjb x->d86_mneu[0] = 0; 1740179237Sjb for (i = 0; i < 3; ++i) { 1741179237Sjb x->d86_opnd[i].d86_opnd[0] = 0; 1742179237Sjb x->d86_opnd[i].d86_prefix[0] = 0; 1743179237Sjb x->d86_opnd[i].d86_value_size = 0; 1744179237Sjb x->d86_opnd[i].d86_value = 0; 1745179237Sjb x->d86_opnd[i].d86_mode = MODE_NONE; 1746179237Sjb } 1747179237Sjb#endif 1748179237Sjb x->d86_error = 0; 1749179237Sjb x->d86_memsize = 0; 1750179237Sjb 1751179237Sjb if (cpu_mode == SIZE16) { 1752179237Sjb opnd_size = SIZE16; 1753179237Sjb addr_size = SIZE16; 1754179237Sjb } else if (cpu_mode == SIZE32) { 1755179237Sjb opnd_size = SIZE32; 1756179237Sjb addr_size = SIZE32; 1757179237Sjb } else { 1758179237Sjb opnd_size = SIZE32; 1759179237Sjb addr_size = SIZE64; 1760179237Sjb } 1761179237Sjb 1762179237Sjb /* 1763179237Sjb * Get one opcode byte and check for zero padding that follows 1764179237Sjb * jump tables. 1765179237Sjb */ 1766179237Sjb if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 1767179237Sjb goto error; 1768179237Sjb 1769179237Sjb if (opcode1 == 0 && opcode2 == 0 && 1770179237Sjb x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) { 1771179237Sjb#ifdef DIS_TEXT 1772179237Sjb (void) strncpy(x->d86_mneu, ".byte\t0", OPLEN); 1773179237Sjb#endif 1774179237Sjb goto done; 1775179237Sjb } 1776179237Sjb 1777179237Sjb /* 1778179237Sjb * Gather up legacy x86 prefix bytes. 1779179237Sjb */ 1780179237Sjb for (;;) { 1781179237Sjb uint_t *which_prefix = NULL; 1782179237Sjb 1783179237Sjb dp = &dis_distable[opcode1][opcode2]; 1784179237Sjb 1785179237Sjb switch (dp->it_adrmode) { 1786179237Sjb case PREFIX: 1787179237Sjb which_prefix = &rep_prefix; 1788179237Sjb break; 1789179237Sjb case LOCK: 1790179237Sjb which_prefix = &lock_prefix; 1791179237Sjb break; 1792179237Sjb case OVERRIDE: 1793179237Sjb which_prefix = &segment_prefix; 1794179237Sjb#ifdef DIS_TEXT 1795179237Sjb x->d86_seg_prefix = (char *)dp->it_name; 1796179237Sjb#endif 1797179237Sjb if (dp->it_invalid64 && cpu_mode == SIZE64) 1798179237Sjb goto error; 1799179237Sjb break; 1800179237Sjb case AM: 1801179237Sjb which_prefix = &addr_size_prefix; 1802179237Sjb break; 1803179237Sjb case DM: 1804179237Sjb which_prefix = &opnd_size_prefix; 1805179237Sjb break; 1806179237Sjb } 1807179237Sjb if (which_prefix == NULL) 1808179237Sjb break; 1809179237Sjb *which_prefix = (opcode1 << 4) | opcode2; 1810179237Sjb if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 1811179237Sjb goto error; 1812179237Sjb } 1813179237Sjb 1814179237Sjb /* 1815179237Sjb * Handle amd64 mode PREFIX values. 1816179237Sjb * Some of the segment prefixes are no-ops. (only FS/GS actually work) 1817179237Sjb * We might have a REX prefix (opcodes 0x40-0x4f) 1818179237Sjb */ 1819179237Sjb if (cpu_mode == SIZE64) { 1820179237Sjb if (segment_prefix != 0x64 && segment_prefix != 0x65) 1821179237Sjb segment_prefix = 0; 1822179237Sjb 1823179237Sjb if (opcode1 == 0x4) { 1824179237Sjb rex_prefix = (opcode1 << 4) | opcode2; 1825179237Sjb if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 1826179237Sjb goto error; 1827179237Sjb dp = &dis_distable[opcode1][opcode2]; 1828179237Sjb } 1829179237Sjb } 1830179237Sjb 1831179237Sjb /* 1832179237Sjb * Deal with selection of operand and address size now. 1833179237Sjb * Note that the REX.W bit being set causes opnd_size_prefix to be 1834179237Sjb * ignored. 1835179237Sjb */ 1836179237Sjb if (cpu_mode == SIZE64) { 1837179237Sjb if (rex_prefix & 0x08) 1838179237Sjb opnd_size = SIZE64; 1839179237Sjb else if (opnd_size_prefix) 1840179237Sjb opnd_size = SIZE16; 1841179237Sjb 1842179237Sjb if (addr_size_prefix) 1843179237Sjb addr_size = SIZE32; 1844179237Sjb } else if (cpu_mode == SIZE32) { 1845179237Sjb if (opnd_size_prefix) 1846179237Sjb opnd_size = SIZE16; 1847179237Sjb if (addr_size_prefix) 1848179237Sjb addr_size = SIZE16; 1849179237Sjb } else { 1850179237Sjb if (opnd_size_prefix) 1851179237Sjb opnd_size = SIZE32; 1852179237Sjb if (addr_size_prefix) 1853179237Sjb addr_size = SIZE32; 1854179237Sjb } 1855179237Sjb 1856179237Sjb /* 1857179237Sjb * The pause instruction - a repz'd nop. This doesn't fit 1858179237Sjb * with any of the other prefix goop added for SSE, so we'll 1859179237Sjb * special-case it here. 1860179237Sjb */ 1861179237Sjb if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) { 1862179237Sjb rep_prefix = 0; 1863179237Sjb dp = &dis_opPause; 1864179237Sjb } 1865179237Sjb 1866179237Sjb /* 1867179237Sjb * Some 386 instructions have 2 bytes of opcode before the mod_r/m 1868179237Sjb * byte so we may need to perform a table indirection. 1869179237Sjb */ 1870179237Sjb if (dp->it_indirect == dis_op0F[0]) { 1871179237Sjb if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0) 1872179237Sjb goto error; 1873179237Sjb opcode_bytes = 2; 1874179237Sjb if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) { 1875179237Sjb uint_t subcode; 1876179237Sjb 1877179237Sjb if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 1878179237Sjb goto error; 1879179237Sjb opcode_bytes = 3; 1880179237Sjb subcode = ((opcode6 & 0x3) << 1) | 1881179237Sjb ((opcode7 & 0x8) >> 3); 1882179237Sjb dp = &dis_op0F7123[opcode5][subcode]; 1883179237Sjb } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) { 1884179237Sjb dp = &dis_op0FC8[0]; 1885179237Sjb } else { 1886179237Sjb dp = &dis_op0F[opcode4][opcode5]; 1887179237Sjb } 1888179237Sjb } 1889179237Sjb 1890179237Sjb /* 1891179237Sjb * If still not at a TERM decode entry, then a ModRM byte 1892179237Sjb * exists and its fields further decode the instruction. 1893179237Sjb */ 1894179237Sjb x->d86_got_modrm = 0; 1895179237Sjb if (dp->it_indirect != TERM) { 1896179237Sjb dtrace_get_modrm(x, &mode, &opcode3, &r_m); 1897179237Sjb if (x->d86_error) 1898179237Sjb goto error; 1899179237Sjb reg = opcode3; 1900179237Sjb 1901179237Sjb /* 1902179237Sjb * decode 287 instructions (D8-DF) from opcodeN 1903179237Sjb */ 1904179237Sjb if (opcode1 == 0xD && opcode2 >= 0x8) { 1905179237Sjb if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4) 1906179237Sjb dp = &dis_opFP5[r_m]; 1907179237Sjb else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4) 1908179237Sjb dp = &dis_opFP7[opcode3]; 1909179237Sjb else if (opcode2 == 0xB && mode == 0x3) 1910179237Sjb dp = &dis_opFP6[opcode3]; 1911179237Sjb else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4) 1912179237Sjb dp = &dis_opFP4[opcode3 - 4][r_m]; 1913179237Sjb else if (mode == 0x3) 1914179237Sjb dp = &dis_opFP3[opcode2 - 8][opcode3]; 1915179237Sjb else 1916179237Sjb dp = &dis_opFP1n2[opcode2 - 8][opcode3]; 1917179237Sjb } else { 1918179237Sjb dp = dp->it_indirect + opcode3; 1919179237Sjb } 1920179237Sjb } 1921179237Sjb 1922179237Sjb /* 1923179237Sjb * In amd64 bit mode, ARPL opcode is changed to MOVSXD 1924179237Sjb * (sign extend 32bit to 64 bit) 1925179237Sjb */ 1926179237Sjb if (cpu_mode == SIZE64 && opcode1 == 0x6 && opcode2 == 0x3) 1927179237Sjb dp = &dis_opMOVSLD; 1928179237Sjb 1929179237Sjb /* 1930179237Sjb * at this point we should have a correct (or invalid) opcode 1931179237Sjb */ 1932179237Sjb if ((cpu_mode == SIZE64 && dp->it_invalid64) || 1933179237Sjb (cpu_mode != SIZE64 && dp->it_invalid32)) 1934179237Sjb goto error; 1935179237Sjb if (dp->it_indirect != TERM) 1936179237Sjb goto error; 1937179237Sjb 1938179237Sjb /* 1939179237Sjb * deal with MMX/SSE opcodes which are changed by prefixes 1940179237Sjb */ 1941179237Sjb switch (dp->it_adrmode) { 1942179237Sjb case MMO: 1943179237Sjb case MMOIMPL: 1944179237Sjb case MMO3P: 1945179237Sjb case MMOM3: 1946179237Sjb case MMOMS: 1947179237Sjb case MMOPM: 1948179237Sjb case MMOPRM: 1949179237Sjb case MMOS: 1950179237Sjb case XMMO: 1951179237Sjb case XMMOM: 1952179237Sjb case XMMOMS: 1953179237Sjb case XMMOPM: 1954179237Sjb case XMMOS: 1955179237Sjb case XMMOMX: 1956179237Sjb case XMMOX3: 1957179237Sjb case XMMOXMM: 1958179237Sjb /* 1959179237Sjb * This is horrible. Some SIMD instructions take the 1960179237Sjb * form 0x0F 0x?? ..., which is easily decoded using the 1961179237Sjb * existing tables. Other SIMD instructions use various 1962179237Sjb * prefix bytes to overload existing instructions. For 1963179237Sjb * Example, addps is F0, 58, whereas addss is F3 (repz), 1964179237Sjb * F0, 58. Presumably someone got a raise for this. 1965179237Sjb * 1966179237Sjb * If we see one of the instructions which can be 1967179237Sjb * modified in this way (if we've got one of the SIMDO* 1968179237Sjb * address modes), we'll check to see if the last prefix 1969179237Sjb * was a repz. If it was, we strip the prefix from the 1970179237Sjb * mnemonic, and we indirect using the dis_opSIMDrepz 1971179237Sjb * table. 1972179237Sjb */ 1973179237Sjb 1974179237Sjb /* 1975179237Sjb * Calculate our offset in dis_op0F 1976179237Sjb */ 1977179237Sjb if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F)) 1978179237Sjb goto error; 1979179237Sjb 1980179237Sjb off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 1981179237Sjb sizeof (instable_t); 1982179237Sjb 1983179237Sjb /* 1984179237Sjb * Rewrite if this instruction used one of the magic prefixes. 1985179237Sjb */ 1986179237Sjb if (rep_prefix) { 1987179237Sjb if (rep_prefix == 0xf2) 1988179237Sjb dp = &dis_opSIMDrepnz[off]; 1989179237Sjb else 1990179237Sjb dp = &dis_opSIMDrepz[off]; 1991179237Sjb rep_prefix = 0; 1992179237Sjb } else if (opnd_size_prefix) { 1993179237Sjb dp = &dis_opSIMDdata16[off]; 1994179237Sjb opnd_size_prefix = 0; 1995179237Sjb if (opnd_size == SIZE16) 1996179237Sjb opnd_size = SIZE32; 1997179237Sjb } 1998179237Sjb break; 1999179237Sjb 2000179237Sjb case MMOSH: 2001179237Sjb /* 2002179237Sjb * As with the "normal" SIMD instructions, the MMX 2003179237Sjb * shuffle instructions are overloaded. These 2004179237Sjb * instructions, however, are special in that they use 2005179237Sjb * an extra byte, and thus an extra table. As of this 2006179237Sjb * writing, they only use the opnd_size prefix. 2007179237Sjb */ 2008179237Sjb 2009179237Sjb /* 2010179237Sjb * Calculate our offset in dis_op0F7123 2011179237Sjb */ 2012179237Sjb if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 > 2013179237Sjb sizeof (dis_op0F7123)) 2014179237Sjb goto error; 2015179237Sjb 2016179237Sjb if (opnd_size_prefix) { 2017179237Sjb off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) / 2018179237Sjb sizeof (instable_t); 2019179237Sjb dp = &dis_opSIMD7123[off]; 2020179237Sjb opnd_size_prefix = 0; 2021179237Sjb if (opnd_size == SIZE16) 2022179237Sjb opnd_size = SIZE32; 2023179237Sjb } 2024179237Sjb break; 2025179237Sjb } 2026179237Sjb 2027179237Sjb /* 2028179237Sjb * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64. 2029179237Sjb */ 2030179237Sjb if (cpu_mode == SIZE64) 2031179237Sjb if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop)) 2032179237Sjb opnd_size = SIZE64; 2033179237Sjb 2034179237Sjb#ifdef DIS_TEXT 2035179237Sjb /* 2036179237Sjb * At this point most instructions can format the opcode mnemonic 2037179237Sjb * including the prefixes. 2038179237Sjb */ 2039179237Sjb if (lock_prefix) 2040179237Sjb (void) strlcat(x->d86_mneu, "lock ", OPLEN); 2041179237Sjb 2042179237Sjb if (rep_prefix == 0xf2) 2043179237Sjb (void) strlcat(x->d86_mneu, "repnz ", OPLEN); 2044179237Sjb else if (rep_prefix == 0xf3) 2045179237Sjb (void) strlcat(x->d86_mneu, "repz ", OPLEN); 2046179237Sjb 2047179237Sjb if (cpu_mode == SIZE64 && addr_size_prefix) 2048179237Sjb (void) strlcat(x->d86_mneu, "addr32 ", OPLEN); 2049179237Sjb 2050179237Sjb if (dp->it_adrmode != CBW && 2051179237Sjb dp->it_adrmode != CWD && 2052179237Sjb dp->it_adrmode != XMMSFNC) { 2053179237Sjb if (strcmp(dp->it_name, "INVALID") == 0) 2054179237Sjb goto error; 2055179237Sjb (void) strlcat(x->d86_mneu, dp->it_name, OPLEN); 2056179237Sjb if (dp->it_suffix) { 2057179237Sjb char *types[] = {"", "w", "l", "q"}; 2058179237Sjb if (opcode_bytes == 2 && opcode4 == 4) { 2059179237Sjb /* It's a cmovx.yy. Replace the suffix x */ 2060179237Sjb for (i = 5; i < OPLEN; i++) { 2061179237Sjb if (x->d86_mneu[i] == '.') 2062179237Sjb break; 2063179237Sjb } 2064179237Sjb x->d86_mneu[i - 1] = *types[opnd_size]; 2065179237Sjb } else { 2066179237Sjb (void) strlcat(x->d86_mneu, types[opnd_size], 2067179237Sjb OPLEN); 2068179237Sjb } 2069179237Sjb } 2070179237Sjb } 2071179237Sjb#endif 2072179237Sjb 2073179237Sjb /* 2074179237Sjb * Process operands based on the addressing modes. 2075179237Sjb */ 2076179237Sjb x->d86_mode = cpu_mode; 2077179237Sjb x->d86_rex_prefix = rex_prefix; 2078179237Sjb x->d86_opnd_size = opnd_size; 2079179237Sjb x->d86_addr_size = addr_size; 2080179237Sjb vbit = 0; /* initialize for mem/reg -> reg */ 2081179237Sjb switch (dp->it_adrmode) { 2082179237Sjb /* 2083179237Sjb * amd64 instruction to sign extend 32 bit reg/mem operands 2084179237Sjb * into 64 bit register values 2085179237Sjb */ 2086179237Sjb case MOVSXZ: 2087179237Sjb#ifdef DIS_TEXT 2088179237Sjb if (rex_prefix == 0) 2089179237Sjb (void) strncpy(x->d86_mneu, "movzld", OPLEN); 2090179237Sjb#endif 2091179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2092179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2093179237Sjb x->d86_opnd_size = SIZE64; 2094179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2095179237Sjb x->d86_opnd_size = opnd_size = SIZE32; 2096179237Sjb wbit = LONG_OPND; 2097179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 2098179237Sjb break; 2099179237Sjb 2100179237Sjb /* 2101179237Sjb * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF) 2102179237Sjb * movzbl movzbw movzbq (0x0FB6) or mobzwl movzwq (0x0FB7) 2103179237Sjb * wbit lives in 2nd byte, note that operands 2104179237Sjb * are different sized 2105179237Sjb */ 2106179237Sjb case MOVZ: 2107179237Sjb if (rex_prefix & REX_W) { 2108179237Sjb /* target register size = 64 bit */ 2109179237Sjb x->d86_mneu[5] = 'q'; 2110179237Sjb } 2111179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2112179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2113179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2114179237Sjb x->d86_opnd_size = opnd_size = SIZE16; 2115179237Sjb wbit = WBIT(opcode5); 2116179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 2117179237Sjb break; 2118179237Sjb 2119179237Sjb /* 2120179237Sjb * imul instruction, with either 8-bit or longer immediate 2121179237Sjb * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s) 2122179237Sjb */ 2123179237Sjb case IMUL: 2124179237Sjb wbit = LONG_OPND; 2125179237Sjb THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 2126179237Sjb OPSIZE(opnd_size, opcode2 == 0x9)); 2127179237Sjb break; 2128179237Sjb 2129179237Sjb /* memory or register operand to register, with 'w' bit */ 2130179237Sjb case MRw: 2131179237Sjb wbit = WBIT(opcode2); 2132179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 2133179237Sjb break; 2134179237Sjb 2135179237Sjb /* register to memory or register operand, with 'w' bit */ 2136179237Sjb /* arpl happens to fit here also because it is odd */ 2137179237Sjb case RMw: 2138179237Sjb if (opcode_bytes == 2) 2139179237Sjb wbit = WBIT(opcode5); 2140179237Sjb else 2141179237Sjb wbit = WBIT(opcode2); 2142179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2143179237Sjb break; 2144179237Sjb 2145179237Sjb /* xaddb instruction */ 2146179237Sjb case XADDB: 2147179237Sjb wbit = 0; 2148179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2149179237Sjb break; 2150179237Sjb 2151179237Sjb /* MMX register to memory or register operand */ 2152179237Sjb case MMS: 2153179237Sjb case MMOS: 2154179237Sjb#ifdef DIS_TEXT 2155179237Sjb wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 2156179237Sjb#else 2157179237Sjb wbit = LONG_OPND; 2158179237Sjb#endif 2159179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 2160179237Sjb break; 2161179237Sjb 2162179237Sjb /* MMX register to memory */ 2163179237Sjb case MMOMS: 2164179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2165179237Sjb if (mode == REG_ONLY) 2166179237Sjb goto error; 2167179237Sjb wbit = MM_OPND; 2168179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 2169179237Sjb break; 2170179237Sjb 2171179237Sjb /* Double shift. Has immediate operand specifying the shift. */ 2172179237Sjb case DSHIFT: 2173179237Sjb wbit = LONG_OPND; 2174179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2175179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2176179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 2); 2177179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2178179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 2179179237Sjb break; 2180179237Sjb 2181179237Sjb /* 2182179237Sjb * Double shift. With no immediate operand, specifies using %cl. 2183179237Sjb */ 2184179237Sjb case DSHIFTcl: 2185179237Sjb wbit = LONG_OPND; 2186179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2187179237Sjb break; 2188179237Sjb 2189179237Sjb /* immediate to memory or register operand */ 2190179237Sjb case IMlw: 2191179237Sjb wbit = WBIT(opcode2); 2192179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2193179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 2194179237Sjb /* 2195179237Sjb * Have long immediate for opcode 0x81, but not 0x80 nor 0x83 2196179237Sjb */ 2197179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0); 2198179237Sjb break; 2199179237Sjb 2200179237Sjb /* immediate to memory or register operand with the */ 2201179237Sjb /* 'w' bit present */ 2202179237Sjb case IMw: 2203179237Sjb wbit = WBIT(opcode2); 2204179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2205179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2206179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 2207179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 2208179237Sjb break; 2209179237Sjb 2210179237Sjb /* immediate to register with register in low 3 bits */ 2211179237Sjb /* of op code */ 2212179237Sjb case IR: 2213179237Sjb /* w-bit here (with regs) is bit 3 */ 2214179237Sjb wbit = opcode2 >>3 & 0x1; 2215179237Sjb reg = REGNO(opcode2); 2216179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2217179237Sjb mode = REG_ONLY; 2218179237Sjb r_m = reg; 2219179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 2220179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0); 2221179237Sjb break; 2222179237Sjb 2223179237Sjb /* MMX immediate shift of register */ 2224179237Sjb case MMSH: 2225179237Sjb case MMOSH: 2226179237Sjb wbit = MM_OPND; 2227179237Sjb goto mm_shift; /* in next case */ 2228179237Sjb 2229179237Sjb /* SIMD immediate shift of register */ 2230179237Sjb case XMMSH: 2231179237Sjb wbit = XMM_OPND; 2232179237Sjbmm_shift: 2233179237Sjb reg = REGNO(opcode7); 2234179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2235179237Sjb dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 2236179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 2237179237Sjb NOMEM; 2238179237Sjb break; 2239179237Sjb 2240179237Sjb /* accumulator to memory operand */ 2241179237Sjb case AO: 2242179237Sjb vbit = 1; 2243179237Sjb /*FALLTHROUGH*/ 2244179237Sjb 2245179237Sjb /* memory operand to accumulator */ 2246179237Sjb case OA: 2247179237Sjb wbit = WBIT(opcode2); 2248179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit); 2249179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit); 2250179237Sjb#ifdef DIS_TEXT 2251179237Sjb x->d86_opnd[vbit].d86_mode = MODE_OFFSET; 2252179237Sjb#endif 2253179237Sjb break; 2254179237Sjb 2255179237Sjb 2256179237Sjb /* segment register to memory or register operand */ 2257179237Sjb case SM: 2258179237Sjb vbit = 1; 2259179237Sjb /*FALLTHROUGH*/ 2260179237Sjb 2261179237Sjb /* memory or register operand to segment register */ 2262179237Sjb case MS: 2263179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2264179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2265179237Sjb dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit); 2266179237Sjb dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit); 2267179237Sjb break; 2268179237Sjb 2269179237Sjb /* 2270179237Sjb * rotate or shift instructions, which may shift by 1 or 2271179237Sjb * consult the cl register, depending on the 'v' bit 2272179237Sjb */ 2273179237Sjb case Mv: 2274179237Sjb vbit = VBIT(opcode2); 2275179237Sjb wbit = WBIT(opcode2); 2276179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2277179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 2278179237Sjb#ifdef DIS_TEXT 2279179237Sjb if (vbit) { 2280179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); 2281179237Sjb } else { 2282179237Sjb x->d86_opnd[0].d86_mode = MODE_SIGNED; 2283179237Sjb x->d86_opnd[0].d86_value_size = 1; 2284179237Sjb x->d86_opnd[0].d86_value = 1; 2285179237Sjb } 2286179237Sjb#endif 2287179237Sjb break; 2288179237Sjb /* 2289179237Sjb * immediate rotate or shift instructions 2290179237Sjb */ 2291179237Sjb case MvI: 2292179237Sjb wbit = WBIT(opcode2); 2293179237Sjbnormal_imm_mem: 2294179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2295179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 2296179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 2297179237Sjb break; 2298179237Sjb 2299179237Sjb /* bit test instructions */ 2300179237Sjb case MIb: 2301179237Sjb wbit = LONG_OPND; 2302179237Sjb goto normal_imm_mem; 2303179237Sjb 2304179237Sjb /* single memory or register operand with 'w' bit present */ 2305179237Sjb case Mw: 2306179237Sjb wbit = WBIT(opcode2); 2307179237Sjbjust_mem: 2308179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2309179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2310179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 2311179237Sjb break; 2312179237Sjb 2313179237Sjb case SWAPGS: 2314179237Sjb if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) { 2315179237Sjb#ifdef DIS_TEXT 2316179237Sjb (void) strncpy(x->d86_mneu, "swapgs", OPLEN); 2317179237Sjb#endif 2318179237Sjb NOMEM; 2319179237Sjb break; 2320179237Sjb } 2321179237Sjb /*FALLTHROUGH*/ 2322179237Sjb 2323179237Sjb /* prefetch instruction - memory operand, but no memory acess */ 2324179237Sjb case PREF: 2325179237Sjb NOMEM; 2326179237Sjb /*FALLTHROUGH*/ 2327179237Sjb 2328179237Sjb /* single memory or register operand */ 2329179237Sjb case M: 2330179237Sjb wbit = LONG_OPND; 2331179237Sjb goto just_mem; 2332179237Sjb 2333179237Sjb /* single memory or register byte operand */ 2334179237Sjb case Mb: 2335179237Sjb wbit = BYTE_OPND; 2336179237Sjb goto just_mem; 2337179237Sjb 2338179237Sjb case MO: 2339179237Sjb /* Similar to M, but only memory (no direct registers) */ 2340179237Sjb wbit = LONG_OPND; 2341179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2342179237Sjb if (mode == 3) 2343179237Sjb goto error; 2344179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2345179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 2346179237Sjb break; 2347179237Sjb 2348179237Sjb /* move special register to register or reverse if vbit */ 2349179237Sjb case SREG: 2350179237Sjb switch (opcode5) { 2351179237Sjb 2352179237Sjb case 2: 2353179237Sjb vbit = 1; 2354179237Sjb /*FALLTHROUGH*/ 2355179237Sjb case 0: 2356179237Sjb wbit = CONTROL_OPND; 2357179237Sjb break; 2358179237Sjb 2359179237Sjb case 3: 2360179237Sjb vbit = 1; 2361179237Sjb /*FALLTHROUGH*/ 2362179237Sjb case 1: 2363179237Sjb wbit = DEBUG_OPND; 2364179237Sjb break; 2365179237Sjb 2366179237Sjb case 6: 2367179237Sjb vbit = 1; 2368179237Sjb /*FALLTHROUGH*/ 2369179237Sjb case 4: 2370179237Sjb wbit = TEST_OPND; 2371179237Sjb break; 2372179237Sjb 2373179237Sjb } 2374179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2375179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2376179237Sjb dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit); 2377179237Sjb dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit); 2378179237Sjb NOMEM; 2379179237Sjb break; 2380179237Sjb 2381179237Sjb /* 2382179237Sjb * single register operand with register in the low 3 2383179237Sjb * bits of op code 2384179237Sjb */ 2385179237Sjb case R: 2386179237Sjb if (opcode_bytes == 2) 2387179237Sjb reg = REGNO(opcode5); 2388179237Sjb else 2389179237Sjb reg = REGNO(opcode2); 2390179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2391179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 2392179237Sjb NOMEM; 2393179237Sjb break; 2394179237Sjb 2395179237Sjb /* 2396179237Sjb * register to accumulator with register in the low 3 2397179237Sjb * bits of op code, xchg instructions 2398179237Sjb */ 2399179237Sjb case RA: 2400179237Sjb NOMEM; 2401179237Sjb reg = REGNO(opcode2); 2402179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 2403179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 2404179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1); 2405179237Sjb break; 2406179237Sjb 2407179237Sjb /* 2408179237Sjb * single segment register operand, with register in 2409179237Sjb * bits 3-4 of op code byte 2410179237Sjb */ 2411179237Sjb case SEG: 2412179237Sjb NOMEM; 2413179237Sjb reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3; 2414179237Sjb dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 2415179237Sjb break; 2416179237Sjb 2417179237Sjb /* 2418179237Sjb * single segment register operand, with register in 2419179237Sjb * bits 3-5 of op code 2420179237Sjb */ 2421179237Sjb case LSEG: 2422179237Sjb NOMEM; 2423179237Sjb /* long seg reg from opcode */ 2424179237Sjb reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7; 2425179237Sjb dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 2426179237Sjb break; 2427179237Sjb 2428179237Sjb /* memory or register operand to register */ 2429179237Sjb case MR: 2430179237Sjb wbit = LONG_OPND; 2431179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 2432179237Sjb break; 2433179237Sjb 2434179237Sjb case RM: 2435179237Sjb wbit = LONG_OPND; 2436179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 2437179237Sjb break; 2438179237Sjb 2439179237Sjb /* MMX/SIMD-Int memory or mm reg to mm reg */ 2440179237Sjb case MM: 2441179237Sjb case MMO: 2442179237Sjb#ifdef DIS_TEXT 2443179237Sjb wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 2444179237Sjb#else 2445179237Sjb wbit = LONG_OPND; 2446179237Sjb#endif 2447179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 2448179237Sjb break; 2449179237Sjb 2450179237Sjb case MMOIMPL: 2451179237Sjb#ifdef DIS_TEXT 2452179237Sjb wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 2453179237Sjb#else 2454179237Sjb wbit = LONG_OPND; 2455179237Sjb#endif 2456179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2457179237Sjb if (mode != REG_ONLY) 2458179237Sjb goto error; 2459179237Sjb 2460179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2461179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 2462179237Sjb dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1); 2463179237Sjb mode = 0; /* change for memory access size... */ 2464179237Sjb break; 2465179237Sjb 2466179237Sjb /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */ 2467179237Sjb case MMO3P: 2468179237Sjb wbit = MM_OPND; 2469179237Sjb goto xmm3p; 2470179237Sjb case XMM3P: 2471179237Sjb wbit = XMM_OPND; 2472179237Sjbxmm3p: 2473179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2474179237Sjb if (mode != REG_ONLY) 2475179237Sjb goto error; 2476179237Sjb 2477179237Sjb THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1); 2478179237Sjb NOMEM; 2479179237Sjb break; 2480179237Sjb 2481179237Sjb /* MMX/SIMD-Int predicated r32/mem to mm reg */ 2482179237Sjb case MMOPRM: 2483179237Sjb wbit = LONG_OPND; 2484179237Sjb w2 = MM_OPND; 2485179237Sjb goto xmmprm; 2486179237Sjb case XMMPRM: 2487179237Sjb wbit = LONG_OPND; 2488179237Sjb w2 = XMM_OPND; 2489179237Sjbxmmprm: 2490179237Sjb THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1); 2491179237Sjb break; 2492179237Sjb 2493179237Sjb /* MMX/SIMD-Int predicated mm/mem to mm reg */ 2494179237Sjb case MMOPM: 2495179237Sjb wbit = w2 = MM_OPND; 2496179237Sjb goto xmmprm; 2497179237Sjb 2498179237Sjb /* MMX/SIMD-Int mm reg to r32 */ 2499179237Sjb case MMOM3: 2500179237Sjb NOMEM; 2501179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2502179237Sjb if (mode != REG_ONLY) 2503179237Sjb goto error; 2504179237Sjb wbit = MM_OPND; 2505179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 2506179237Sjb break; 2507179237Sjb 2508179237Sjb /* SIMD memory or xmm reg operand to xmm reg */ 2509179237Sjb case XMM: 2510179237Sjb case XMMO: 2511179237Sjb case XMMXIMPL: 2512179237Sjb wbit = XMM_OPND; 2513179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 2514179237Sjb 2515179237Sjb if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY) 2516179237Sjb goto error; 2517179237Sjb 2518179237Sjb#ifdef DIS_TEXT 2519179237Sjb /* 2520179237Sjb * movlps and movhlps share opcodes. They differ in the 2521179237Sjb * addressing modes allowed for their operands. 2522179237Sjb * movhps and movlhps behave similarly. 2523179237Sjb */ 2524179237Sjb if (mode == REG_ONLY) { 2525179237Sjb if (strcmp(dp->it_name, "movlps") == 0) 2526179237Sjb (void) strncpy(x->d86_mneu, "movhlps", OPLEN); 2527179237Sjb else if (strcmp(dp->it_name, "movhps") == 0) 2528179237Sjb (void) strncpy(x->d86_mneu, "movlhps", OPLEN); 2529179237Sjb } 2530179237Sjb#endif 2531179237Sjb if (dp->it_adrmode == XMMXIMPL) 2532179237Sjb mode = 0; /* change for memory access size... */ 2533179237Sjb break; 2534179237Sjb 2535179237Sjb /* SIMD xmm reg to memory or xmm reg */ 2536179237Sjb case XMMS: 2537179237Sjb case XMMOS: 2538179237Sjb case XMMMS: 2539179237Sjb case XMMOMS: 2540179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2541179237Sjb#ifdef DIS_TEXT 2542179237Sjb if ((strcmp(dp->it_name, "movlps") == 0 || 2543179237Sjb strcmp(dp->it_name, "movhps") == 0 || 2544179237Sjb strcmp(dp->it_name, "movntps") == 0) && 2545179237Sjb mode == REG_ONLY) 2546179237Sjb goto error; 2547179237Sjb#endif 2548179237Sjb wbit = XMM_OPND; 2549179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 2550179237Sjb break; 2551179237Sjb 2552179237Sjb /* SIMD memory to xmm reg */ 2553179237Sjb case XMMM: 2554179237Sjb case XMMOM: 2555179237Sjb wbit = XMM_OPND; 2556179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2557179237Sjb#ifdef DIS_TEXT 2558179237Sjb if (mode == REG_ONLY) { 2559179237Sjb if (strcmp(dp->it_name, "movhps") == 0) 2560179237Sjb (void) strncpy(x->d86_mneu, "movlhps", OPLEN); 2561179237Sjb else 2562179237Sjb goto error; 2563179237Sjb } 2564179237Sjb#endif 2565179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 2566179237Sjb break; 2567179237Sjb 2568179237Sjb /* SIMD memory or r32 to xmm reg */ 2569179237Sjb case XMM3MX: 2570179237Sjb wbit = LONG_OPND; 2571179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 2572179237Sjb break; 2573179237Sjb 2574179237Sjb case XMM3MXS: 2575179237Sjb wbit = LONG_OPND; 2576179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 2577179237Sjb break; 2578179237Sjb 2579179237Sjb /* SIMD memory or mm reg to xmm reg */ 2580179237Sjb case XMMOMX: 2581179237Sjb /* SIMD mm to xmm */ 2582179237Sjb case XMMMX: 2583179237Sjb wbit = MM_OPND; 2584179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 2585179237Sjb break; 2586179237Sjb 2587179237Sjb /* SIMD memory or xmm reg to mm reg */ 2588179237Sjb case XMMXMM: 2589179237Sjb case XMMOXMM: 2590179237Sjb case XMMXM: 2591179237Sjb wbit = XMM_OPND; 2592179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 2593179237Sjb break; 2594179237Sjb 2595179237Sjb 2596179237Sjb /* SIMD memory or xmm reg to r32 */ 2597179237Sjb case XMMXM3: 2598179237Sjb wbit = XMM_OPND; 2599179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 2600179237Sjb break; 2601179237Sjb 2602179237Sjb /* SIMD xmm to r32 */ 2603179237Sjb case XMMX3: 2604179237Sjb case XMMOX3: 2605179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2606179237Sjb if (mode != REG_ONLY) 2607179237Sjb goto error; 2608179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2609179237Sjb dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 2610179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 2611179237Sjb NOMEM; 2612179237Sjb break; 2613179237Sjb 2614179237Sjb /* SIMD predicated memory or xmm reg with/to xmm reg */ 2615179237Sjb case XMMP: 2616179237Sjb case XMMOPM: 2617179237Sjb wbit = XMM_OPND; 2618179237Sjb THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 2619179237Sjb 2620179237Sjb#ifdef DIS_TEXT 2621179237Sjb /* 2622179237Sjb * cmpps and cmpss vary their instruction name based 2623179237Sjb * on the value of imm8. Other XMMP instructions, 2624179237Sjb * such as shufps, require explicit specification of 2625179237Sjb * the predicate. 2626179237Sjb */ 2627179237Sjb if (dp->it_name[0] == 'c' && 2628179237Sjb dp->it_name[1] == 'm' && 2629179237Sjb dp->it_name[2] == 'p' && 2630179237Sjb strlen(dp->it_name) == 5) { 2631179237Sjb uchar_t pred = x->d86_opnd[0].d86_value & 0xff; 2632179237Sjb 2633179237Sjb if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *))) 2634179237Sjb goto error; 2635179237Sjb 2636179237Sjb (void) strncpy(x->d86_mneu, "cmp", OPLEN); 2637179237Sjb (void) strlcat(x->d86_mneu, dis_PREDSUFFIX[pred], 2638179237Sjb OPLEN); 2639179237Sjb (void) strlcat(x->d86_mneu, 2640179237Sjb dp->it_name + strlen(dp->it_name) - 2, 2641179237Sjb OPLEN); 2642179237Sjb x->d86_opnd[0] = x->d86_opnd[1]; 2643179237Sjb x->d86_opnd[1] = x->d86_opnd[2]; 2644179237Sjb x->d86_numopnds = 2; 2645179237Sjb } 2646179237Sjb#endif 2647179237Sjb break; 2648179237Sjb 2649179237Sjb /* immediate operand to accumulator */ 2650179237Sjb case IA: 2651179237Sjb wbit = WBIT(opcode2); 2652179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 2653179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 2654179237Sjb NOMEM; 2655179237Sjb break; 2656179237Sjb 2657179237Sjb /* memory or register operand to accumulator */ 2658179237Sjb case MA: 2659179237Sjb wbit = WBIT(opcode2); 2660179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2661179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 2662179237Sjb break; 2663179237Sjb 2664179237Sjb /* si register to di register used to reference memory */ 2665179237Sjb case SD: 2666179237Sjb#ifdef DIS_TEXT 2667179237Sjb dtrace_check_override(x, 0); 2668179237Sjb x->d86_numopnds = 2; 2669179237Sjb if (addr_size == SIZE64) { 2670179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 2671179237Sjb OPLEN); 2672179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 2673179237Sjb OPLEN); 2674179237Sjb } else if (addr_size == SIZE32) { 2675179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 2676179237Sjb OPLEN); 2677179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 2678179237Sjb OPLEN); 2679179237Sjb } else { 2680179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 2681179237Sjb OPLEN); 2682179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 2683179237Sjb OPLEN); 2684179237Sjb } 2685179237Sjb#endif 2686179237Sjb wbit = LONG_OPND; 2687179237Sjb break; 2688179237Sjb 2689179237Sjb /* accumulator to di register */ 2690179237Sjb case AD: 2691179237Sjb wbit = WBIT(opcode2); 2692179237Sjb#ifdef DIS_TEXT 2693179237Sjb dtrace_check_override(x, 1); 2694179237Sjb x->d86_numopnds = 2; 2695179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0); 2696179237Sjb if (addr_size == SIZE64) 2697179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 2698179237Sjb OPLEN); 2699179237Sjb else if (addr_size == SIZE32) 2700179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 2701179237Sjb OPLEN); 2702179237Sjb else 2703179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 2704179237Sjb OPLEN); 2705179237Sjb#endif 2706179237Sjb break; 2707179237Sjb 2708179237Sjb /* si register to accumulator */ 2709179237Sjb case SA: 2710179237Sjb wbit = WBIT(opcode2); 2711179237Sjb#ifdef DIS_TEXT 2712179237Sjb dtrace_check_override(x, 0); 2713179237Sjb x->d86_numopnds = 2; 2714179237Sjb if (addr_size == SIZE64) 2715179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 2716179237Sjb OPLEN); 2717179237Sjb else if (addr_size == SIZE32) 2718179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 2719179237Sjb OPLEN); 2720179237Sjb else 2721179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 2722179237Sjb OPLEN); 2723179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 2724179237Sjb#endif 2725179237Sjb break; 2726179237Sjb 2727179237Sjb /* 2728179237Sjb * single operand, a 16/32 bit displacement 2729179237Sjb */ 2730179237Sjb case D: 2731179237Sjb wbit = LONG_OPND; 2732179237Sjb dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 2733179237Sjb NOMEM; 2734179237Sjb break; 2735179237Sjb 2736179237Sjb /* jmp/call indirect to memory or register operand */ 2737179237Sjb case INM: 2738179237Sjb#ifdef DIS_TEXT 2739179237Sjb (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); 2740179237Sjb#endif 2741179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 2742179237Sjb dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 2743179237Sjb wbit = LONG_OPND; 2744179237Sjb break; 2745179237Sjb 2746179237Sjb /* 2747179237Sjb * for long jumps and long calls -- a new code segment 2748179237Sjb * register and an offset in IP -- stored in object 2749179237Sjb * code in reverse order. Note - not valid in amd64 2750179237Sjb */ 2751179237Sjb case SO: 2752179237Sjb dtrace_check_override(x, 1); 2753179237Sjb wbit = LONG_OPND; 2754179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1); 2755179237Sjb#ifdef DIS_TEXT 2756179237Sjb x->d86_opnd[1].d86_mode = MODE_SIGNED; 2757179237Sjb#endif 2758179237Sjb /* will now get segment operand */ 2759179237Sjb dtrace_imm_opnd(x, wbit, 2, 0); 2760179237Sjb break; 2761179237Sjb 2762179237Sjb /* 2763179237Sjb * jmp/call. single operand, 8 bit displacement. 2764179237Sjb * added to current EIP in 'compofff' 2765179237Sjb */ 2766179237Sjb case BD: 2767179237Sjb dtrace_disp_opnd(x, BYTE_OPND, 1, 0); 2768179237Sjb NOMEM; 2769179237Sjb break; 2770179237Sjb 2771179237Sjb /* single 32/16 bit immediate operand */ 2772179237Sjb case I: 2773179237Sjb wbit = LONG_OPND; 2774179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 2775179237Sjb break; 2776179237Sjb 2777179237Sjb /* single 8 bit immediate operand */ 2778179237Sjb case Ib: 2779179237Sjb wbit = LONG_OPND; 2780179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 2781179237Sjb break; 2782179237Sjb 2783179237Sjb case ENTER: 2784179237Sjb wbit = LONG_OPND; 2785179237Sjb dtrace_imm_opnd(x, wbit, 2, 0); 2786179237Sjb dtrace_imm_opnd(x, wbit, 1, 1); 2787179237Sjb switch (opnd_size) { 2788179237Sjb case SIZE64: 2789179237Sjb x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8; 2790179237Sjb break; 2791179237Sjb case SIZE32: 2792179237Sjb x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4; 2793179237Sjb break; 2794179237Sjb case SIZE16: 2795179237Sjb x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2; 2796179237Sjb break; 2797179237Sjb } 2798179237Sjb 2799179237Sjb break; 2800179237Sjb 2801179237Sjb /* 16-bit immediate operand */ 2802179237Sjb case RET: 2803179237Sjb wbit = LONG_OPND; 2804179237Sjb dtrace_imm_opnd(x, wbit, 2, 0); 2805179237Sjb break; 2806179237Sjb 2807179237Sjb /* single 8 bit port operand */ 2808179237Sjb case P: 2809179237Sjb dtrace_check_override(x, 0); 2810179237Sjb dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 2811179237Sjb NOMEM; 2812179237Sjb break; 2813179237Sjb 2814179237Sjb /* single operand, dx register (variable port instruction) */ 2815179237Sjb case V: 2816179237Sjb x->d86_numopnds = 1; 2817179237Sjb dtrace_check_override(x, 0); 2818179237Sjb#ifdef DIS_TEXT 2819179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); 2820179237Sjb#endif 2821179237Sjb NOMEM; 2822179237Sjb break; 2823179237Sjb 2824179237Sjb /* 2825179237Sjb * The int instruction, which has two forms: 2826179237Sjb * int 3 (breakpoint) or 2827179237Sjb * int n, where n is indicated in the subsequent 2828179237Sjb * byte (format Ib). The int 3 instruction (opcode 0xCC), 2829179237Sjb * where, although the 3 looks like an operand, 2830179237Sjb * it is implied by the opcode. It must be converted 2831179237Sjb * to the correct base and output. 2832179237Sjb */ 2833179237Sjb case INT3: 2834179237Sjb#ifdef DIS_TEXT 2835179237Sjb x->d86_numopnds = 1; 2836179237Sjb x->d86_opnd[0].d86_mode = MODE_SIGNED; 2837179237Sjb x->d86_opnd[0].d86_value_size = 1; 2838179237Sjb x->d86_opnd[0].d86_value = 3; 2839179237Sjb#endif 2840179237Sjb NOMEM; 2841179237Sjb break; 2842179237Sjb 2843179237Sjb /* single 8 bit immediate operand */ 2844179237Sjb case INTx: 2845179237Sjb dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 2846179237Sjb NOMEM; 2847179237Sjb break; 2848179237Sjb 2849179237Sjb /* an unused byte must be discarded */ 2850179237Sjb case U: 2851179237Sjb if (x->d86_get_byte(x->d86_data) < 0) 2852179237Sjb goto error; 2853179237Sjb x->d86_len++; 2854179237Sjb NOMEM; 2855179237Sjb break; 2856179237Sjb 2857179237Sjb case CBW: 2858179237Sjb#ifdef DIS_TEXT 2859179237Sjb if (opnd_size == SIZE16) 2860179237Sjb (void) strlcat(x->d86_mneu, "cbtw", OPLEN); 2861179237Sjb else if (opnd_size == SIZE32) 2862179237Sjb (void) strlcat(x->d86_mneu, "cwtl", OPLEN); 2863179237Sjb else 2864179237Sjb (void) strlcat(x->d86_mneu, "cltq", OPLEN); 2865179237Sjb#endif 2866179237Sjb wbit = LONG_OPND; 2867179237Sjb NOMEM; 2868179237Sjb break; 2869179237Sjb 2870179237Sjb case CWD: 2871179237Sjb#ifdef DIS_TEXT 2872179237Sjb if (opnd_size == SIZE16) 2873179237Sjb (void) strlcat(x->d86_mneu, "cwtd", OPLEN); 2874179237Sjb else if (opnd_size == SIZE32) 2875179237Sjb (void) strlcat(x->d86_mneu, "cltd", OPLEN); 2876179237Sjb else 2877179237Sjb (void) strlcat(x->d86_mneu, "cqtd", OPLEN); 2878179237Sjb#endif 2879179237Sjb wbit = LONG_OPND; 2880179237Sjb NOMEM; 2881179237Sjb break; 2882179237Sjb 2883179237Sjb case XMMSFNC: 2884179237Sjb /* 2885179237Sjb * sfence is sfence if mode is REG_ONLY. If mode isn't 2886179237Sjb * REG_ONLY, mnemonic should be 'clflush'. 2887179237Sjb */ 2888179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 2889179237Sjb 2890179237Sjb /* sfence doesn't take operands */ 2891179237Sjb#ifdef DIS_TEXT 2892179237Sjb if (mode == REG_ONLY) { 2893179237Sjb (void) strlcat(x->d86_mneu, "sfence", OPLEN); 2894179237Sjb } else { 2895179237Sjb (void) strlcat(x->d86_mneu, "clflush", OPLEN); 2896179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2897179237Sjb dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 2898179237Sjb NOMEM; 2899179237Sjb } 2900179237Sjb#else 2901179237Sjb if (mode != REG_ONLY) { 2902179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 2903179237Sjb dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 2904179237Sjb NOMEM; 2905179237Sjb } 2906179237Sjb#endif 2907179237Sjb break; 2908179237Sjb 2909179237Sjb /* 2910179237Sjb * no disassembly, the mnemonic was all there was so go on 2911179237Sjb */ 2912179237Sjb case NORM: 2913179237Sjb if (dp->it_invalid32 && cpu_mode != SIZE64) 2914179237Sjb goto error; 2915179237Sjb NOMEM; 2916179237Sjb /*FALLTHROUGH*/ 2917179237Sjb case IMPLMEM: 2918179237Sjb break; 2919179237Sjb 2920179237Sjb case XMMFENCE: 2921179237Sjb /* 2922179237Sjb * Only the following exact byte sequences are allowed: 2923179237Sjb * 2924179237Sjb * 0f ae e8 lfence 2925179237Sjb * 0f ae f0 mfence 2926179237Sjb */ 2927179237Sjb if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 && 2928179237Sjb (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0) 2929179237Sjb goto error; 2930179237Sjb 2931179237Sjb break; 2932179237Sjb 2933179237Sjb 2934179237Sjb /* float reg */ 2935179237Sjb case F: 2936179237Sjb#ifdef DIS_TEXT 2937179237Sjb x->d86_numopnds = 1; 2938179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); 2939179237Sjb x->d86_opnd[0].d86_opnd[4] = r_m + '0'; 2940179237Sjb#endif 2941179237Sjb NOMEM; 2942179237Sjb break; 2943179237Sjb 2944179237Sjb /* float reg to float reg, with ret bit present */ 2945179237Sjb case FF: 2946179237Sjb vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */ 2947179237Sjb /*FALLTHROUGH*/ 2948179237Sjb case FFC: /* case for vbit always = 0 */ 2949179237Sjb#ifdef DIS_TEXT 2950179237Sjb x->d86_numopnds = 2; 2951179237Sjb (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); 2952179237Sjb (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); 2953179237Sjb x->d86_opnd[vbit].d86_opnd[4] = r_m + '0'; 2954179237Sjb#endif 2955179237Sjb NOMEM; 2956179237Sjb break; 2957179237Sjb 2958179237Sjb /* an invalid op code */ 2959179237Sjb case AM: 2960179237Sjb case DM: 2961179237Sjb case OVERRIDE: 2962179237Sjb case PREFIX: 2963179237Sjb case UNKNOWN: 2964179237Sjb NOMEM; 2965179237Sjb default: 2966179237Sjb goto error; 2967179237Sjb } /* end switch */ 2968179237Sjb if (x->d86_error) 2969179237Sjb goto error; 2970179237Sjb 2971179237Sjbdone: 2972179237Sjb#ifdef DIS_MEM 2973179237Sjb /* 2974179237Sjb * compute the size of any memory accessed by the instruction 2975179237Sjb */ 2976179237Sjb if (x->d86_memsize != 0) { 2977179237Sjb return (0); 2978179237Sjb } else if (dp->it_stackop) { 2979179237Sjb switch (opnd_size) { 2980179237Sjb case SIZE16: 2981179237Sjb x->d86_memsize = 2; 2982179237Sjb break; 2983179237Sjb case SIZE32: 2984179237Sjb x->d86_memsize = 4; 2985179237Sjb break; 2986179237Sjb case SIZE64: 2987179237Sjb x->d86_memsize = 8; 2988179237Sjb break; 2989179237Sjb } 2990179237Sjb } else if (nomem || mode == REG_ONLY) { 2991179237Sjb x->d86_memsize = 0; 2992179237Sjb 2993179237Sjb } else if (dp->it_size != 0) { 2994179237Sjb /* 2995179237Sjb * In 64 bit mode descriptor table entries 2996179237Sjb * go up to 10 bytes and popf/pushf are always 8 bytes 2997179237Sjb */ 2998179237Sjb if (x->d86_mode == SIZE64 && dp->it_size == 6) 2999179237Sjb x->d86_memsize = 10; 3000179237Sjb else if (x->d86_mode == SIZE64 && opcode1 == 0x9 && 3001179237Sjb (opcode2 == 0xc || opcode2 == 0xd)) 3002179237Sjb x->d86_memsize = 8; 3003179237Sjb else 3004179237Sjb x->d86_memsize = dp->it_size; 3005179237Sjb 3006179237Sjb } else if (wbit == 0) { 3007179237Sjb x->d86_memsize = 1; 3008179237Sjb 3009179237Sjb } else if (wbit == LONG_OPND) { 3010179237Sjb if (opnd_size == SIZE64) 3011179237Sjb x->d86_memsize = 8; 3012179237Sjb else if (opnd_size == SIZE32) 3013179237Sjb x->d86_memsize = 4; 3014179237Sjb else 3015179237Sjb x->d86_memsize = 2; 3016179237Sjb 3017179237Sjb } else if (wbit == SEG_OPND) { 3018179237Sjb x->d86_memsize = 4; 3019179237Sjb 3020179237Sjb } else { 3021179237Sjb x->d86_memsize = 8; 3022179237Sjb } 3023179237Sjb#endif 3024179237Sjb return (0); 3025179237Sjb 3026179237Sjberror: 3027179237Sjb#ifdef DIS_TEXT 3028179237Sjb (void) strlcat(x->d86_mneu, "undef", OPLEN); 3029179237Sjb#endif 3030179237Sjb return (1); 3031179237Sjb} 3032179237Sjb 3033179237Sjb#ifdef DIS_TEXT 3034179237Sjb 3035179237Sjb/* 3036179237Sjb * Some instructions should have immediate operands printed 3037179237Sjb * as unsigned integers. We compare against this table. 3038179237Sjb */ 3039179237Sjbstatic char *unsigned_ops[] = { 3040179237Sjb "or", "and", "xor", "test", "in", "out", "lcall", "ljmp", 3041179237Sjb "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl", 3042179237Sjb 0 3043179237Sjb}; 3044179237Sjb 3045179237Sjbstatic int 3046179237Sjbisunsigned_op(char *opcode) 3047179237Sjb{ 3048179237Sjb char *where; 3049179237Sjb int i; 3050179237Sjb int is_unsigned = 0; 3051179237Sjb 3052179237Sjb /* 3053179237Sjb * Work back to start of last mnemonic, since we may have 3054179237Sjb * prefixes on some opcodes. 3055179237Sjb */ 3056179237Sjb where = opcode + strlen(opcode) - 1; 3057179237Sjb while (where > opcode && *where != ' ') 3058179237Sjb --where; 3059179237Sjb if (*where == ' ') 3060179237Sjb ++where; 3061179237Sjb 3062179237Sjb for (i = 0; unsigned_ops[i]; ++i) { 3063179237Sjb if (strncmp(where, unsigned_ops[i], 3064179237Sjb strlen(unsigned_ops[i]))) 3065179237Sjb continue; 3066179237Sjb is_unsigned = 1; 3067179237Sjb break; 3068179237Sjb } 3069179237Sjb return (is_unsigned); 3070179237Sjb} 3071179237Sjb 3072179237Sjb/* ARGSUSED */ 3073179237Sjbvoid 3074179237Sjbdtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf, 3075179237Sjb size_t buflen) 3076179237Sjb{ 3077179237Sjb int i; 3078179237Sjb 3079179237Sjb dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mneu); 3080179237Sjb 3081179237Sjb /* 3082179237Sjb * For PC-relative jumps, the pc is really the next pc after executing 3083179237Sjb * this instruction, so increment it appropriately. 3084179237Sjb */ 3085179237Sjb pc += dis->d86_len; 3086179237Sjb 3087179237Sjb for (i = 0; i < dis->d86_numopnds; i++) { 3088179237Sjb d86opnd_t *op = &dis->d86_opnd[i]; 3089179237Sjb int64_t sv; 3090179237Sjb uint64_t mask; 3091179237Sjb 3092179237Sjb if (i != 0) 3093179237Sjb (void) strlcat(buf, ",", buflen); 3094179237Sjb 3095179237Sjb (void) strlcat(buf, op->d86_prefix, buflen); 3096179237Sjb 3097179237Sjb sv = op->d86_value; 3098179237Sjb 3099179237Sjb switch (op->d86_mode) { 3100179237Sjb 3101179237Sjb case MODE_NONE: 3102179237Sjb 3103179237Sjb (void) strlcat(buf, op->d86_opnd, buflen); 3104179237Sjb break; 3105179237Sjb 3106179237Sjb case MODE_SIGNED: 3107179237Sjb case MODE_IMPLIED: 3108179237Sjb case MODE_OFFSET: 3109179237Sjb 3110179237Sjb if (dis->d86_seg_prefix) 3111179237Sjb (void) strlcat(buf, dis->d86_seg_prefix, 3112179237Sjb buflen); 3113179237Sjb 3114179237Sjb switch (op->d86_value_size) { 3115179237Sjb case 1: 3116179237Sjb sv = (int8_t)sv; 3117179237Sjb mask = 0xff; 3118179237Sjb break; 3119179237Sjb case 2: 3120179237Sjb sv = (int16_t)sv; 3121179237Sjb mask = 0xffff; 3122179237Sjb break; 3123179237Sjb case 4: 3124179237Sjb sv = (int32_t)sv; 3125179237Sjb mask = 0xffffffff; 3126179237Sjb break; 3127179237Sjb case 8: 3128179237Sjb mask = 0xffffffffffffffffULL; 3129179237Sjb break; 3130179237Sjb } 3131179237Sjb 3132179237Sjb if (op->d86_mode == MODE_SIGNED || 3133179237Sjb op->d86_mode == MODE_IMPLIED) 3134179237Sjb (void) strlcat(buf, "$", buflen); 3135179237Sjb 3136179237Sjb if (sv < 0 && sv > -0xffff && 3137179237Sjb !isunsigned_op(dis->d86_mneu)) { 3138179237Sjb dis->d86_sprintf_func(buf + strlen(buf), 3139179237Sjb buflen - strlen(buf), 3140179237Sjb (dis->d86_flags & DIS_OP_OCTAL) ? 3141179237Sjb "-0%llo" : "-0x%llx", -sv & mask); 3142179237Sjb } else { 3143179237Sjb dis->d86_sprintf_func(buf + strlen(buf), 3144179237Sjb buflen - strlen(buf), 3145179237Sjb (dis->d86_flags & DIS_OP_OCTAL) ? 3146179237Sjb "0%llo" : "0x%llx", sv & mask); 3147179237Sjb } 3148179237Sjb (void) strlcat(buf, op->d86_opnd, buflen); 3149179237Sjb break; 3150179237Sjb 3151179237Sjb case MODE_IPREL: 3152179237Sjb 3153179237Sjb switch (op->d86_value_size) { 3154179237Sjb case 1: 3155179237Sjb sv = (int8_t)sv; 3156179237Sjb break; 3157179237Sjb case 2: 3158179237Sjb sv = (int16_t)sv; 3159179237Sjb break; 3160179237Sjb case 4: 3161179237Sjb sv = (int32_t)sv; 3162179237Sjb break; 3163179237Sjb } 3164179237Sjb 3165179237Sjb if (sv < 0) 3166179237Sjb dis->d86_sprintf_func(buf + strlen(buf), 3167179237Sjb buflen - strlen(buf), 3168179237Sjb (dis->d86_flags & DIS_OP_OCTAL) ? 3169179237Sjb "-0%llo" : "-0x%llx", -sv - dis->d86_len); 3170179237Sjb else 3171179237Sjb dis->d86_sprintf_func(buf + strlen(buf), 3172179237Sjb buflen - strlen(buf), 3173179237Sjb (dis->d86_flags & DIS_OP_OCTAL) ? 3174179237Sjb "+0%llo" : "+0x%llx", sv + dis->d86_len); 3175179237Sjb 3176179237Sjb (void) strlcat(buf, "\t<", buflen); 3177179237Sjb 3178179237Sjb if (dis->d86_sym_lookup == NULL || 3179179237Sjb dis->d86_sym_lookup(dis->d86_data, pc + sv, 3180179237Sjb buf + strlen(buf), buflen - strlen(buf)) != 0) 3181179237Sjb dis->d86_sprintf_func(buf + strlen(buf), 3182179237Sjb buflen - strlen(buf), 3183179237Sjb (dis->d86_flags & DIS_OP_OCTAL) ? 3184179237Sjb "0%llo" : "0x%llx", pc + sv); 3185179237Sjb 3186179237Sjb (void) strlcat(buf, ">", buflen); 3187179237Sjb 3188179237Sjb break; 3189179237Sjb } 3190179237Sjb } 3191179237Sjb} 3192179237Sjb 3193179237Sjb#endif /* DIS_TEXT */ 3194