disassembler_x86.cc revision fe94578b63380f464c3abd5c156b7b31d068db6c
1706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers/* 2706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * Copyright (C) 2012 The Android Open Source Project 3706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * 4706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 5706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * you may not use this file except in compliance with the License. 6706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * You may obtain a copy of the License at 7706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * 8706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * http://www.apache.org/licenses/LICENSE-2.0 9706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * 10706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * Unless required by applicable law or agreed to in writing, software 11706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * distributed under the License is distributed on an "AS IS" BASIS, 12706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * See the License for the specific language governing permissions and 14706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers * limitations under the License. 15706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers */ 16706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 17706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers#include "disassembler_x86.h" 18706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 19706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers#include <iostream> 20706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 2107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 22e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 2392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes#include "thread.h" 240f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes 25706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersnamespace art { 26706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersnamespace x86 { 27706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 28b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogerssize_t DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin) { 29b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers return DumpInstruction(os, begin); 30b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers} 31b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers 32706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersvoid DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) { 33706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers size_t length = 0; 34706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers for (const uint8_t* cur = begin; cur < end; cur += length) { 35706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers length = DumpInstruction(os, cur); 36706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 37706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 38706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 39706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersstatic const char* gReg8Names[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; 40703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhaostatic const char* gReg16Names[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; 41703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhaostatic const char* gReg32Names[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; 4238e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogersstatic const char* gReg64Names[] = { 4338e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 4438e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 4538e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers}; 46706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 4738e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogersstatic void DumpReg0(std::ostream& os, uint8_t rex, size_t reg, 48706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool byte_operand, uint8_t size_override) { 4938e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers DCHECK_LT(reg, (rex == 0) ? 8u : 16u); 5038e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers bool rex_w = (rex & 0b1000) != 0; 5138e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers size_t size = byte_operand ? 1 : (size_override == 0x66 ? 2 : (rex_w ? 8 :4)); 52706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (size) { 53706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 1: os << gReg8Names[reg]; break; 54706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 2: os << gReg16Names[reg]; break; 55706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 4: os << gReg32Names[reg]; break; 5638e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers case 8: os << gReg64Names[reg]; break; 57706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: LOG(FATAL) << "unexpected size " << size; 58706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 59706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 60706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 61bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogersenum RegFile { GPR, MMX, SSE }; 62bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers 63706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersstatic void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg, 64bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers bool byte_operand, uint8_t size_override, RegFile reg_file) { 6538e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers bool rex_r = (rex & 0b0100) != 0; 6638e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers size_t reg_num = rex_r ? (reg + 8) : reg; 67bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (reg_file == GPR) { 68bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg0(os, rex, reg_num, byte_operand, size_override); 69bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (reg_file == SSE) { 70bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers os << "xmm" << reg_num; 71bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 72bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers os << "mm" << reg_num; 73bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 74706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 75706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 767caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogersstatic void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) { 7738e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers bool rex_b = (rex & 0b0001) != 0; 7838e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers size_t reg_num = rex_b ? (reg + 8) : reg; 797caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers DumpReg0(os, rex, reg_num, false, 0); 80706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 81706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 827caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogersstatic void DumpIndexReg(std::ostream& os, uint8_t rex, uint8_t reg) { 8338e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers bool rex_x = (rex & 0b0010) != 0; 8438e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers uint8_t reg_num = rex_x ? (reg + 8) : reg; 857caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers DumpReg0(os, rex, reg_num, false, 0); 86706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 87706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 8892301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughesenum SegmentPrefix { 8992301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kCs = 0x2e, 9092301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kSs = 0x36, 9192301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kDs = 0x3e, 9292301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kEs = 0x26, 9392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kFs = 0x64, 9492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kGs = 0x65, 9592301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes}; 9692301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes 97706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersstatic void DumpSegmentOverride(std::ostream& os, uint8_t segment_prefix) { 98706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (segment_prefix) { 9992301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kCs: os << "cs:"; break; 10092301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kSs: os << "ss:"; break; 10192301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kDs: os << "ds:"; break; 10292301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kEs: os << "es:"; break; 10392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kFs: os << "fs:"; break; 10492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kGs: os << "gs:"; break; 105706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: break; 106706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 107706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 108706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 109706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogerssize_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) { 110706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers const uint8_t* begin_instr = instr; 111706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool have_prefixes = true; 112706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t prefix[4] = {0, 0, 0, 0}; 113706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers const char** modrm_opcodes = NULL; 114706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers do { 115706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (*instr) { 1167caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers // Group 1 - lock and repeat prefixes: 117706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xF0: 118706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xF2: 119706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xF3: 120706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[0] = *instr; 121706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 122706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers // Group 2 - segment override prefixes: 12392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kCs: 12492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kSs: 12592301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kDs: 12692301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kEs: 12792301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kFs: 12892301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kGs: 129706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[1] = *instr; 130706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 131706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers // Group 3 - operand size override: 132706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x66: 133706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[2] = *instr; 134706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 135706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers // Group 4 - address size override: 136706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x67: 137706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[3] = *instr; 138706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 139706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: 140706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers have_prefixes = false; 141706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 142706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 143706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (have_prefixes) { 144706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 145706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 146706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } while (have_prefixes); 14738e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; 148e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (rex != 0) { 149e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov instr++; 150e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } 151706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool has_modrm = false; 152706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool reg_is_opcode = false; 153706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers size_t immediate_bytes = 0; 154706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers size_t branch_bytes = 0; 155706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers std::ostringstream opcode; 156706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool store = false; // stores to memory (ie rm is on the left) 157706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool load = false; // loads from memory (ie rm is on the right) 158706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool byte_operand = false; 159706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool ax = false; // implicit use of ax 160e296248a124ed8287b38a9225463696c18d84cd6jeffhao bool cx = false; // implicit use of cx 161706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool reg_in_opcode = false; // low 3-bits of opcode encode register parameter 162703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao bool no_ops = false; 163bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers RegFile src_reg_file = GPR; 164bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers RegFile dst_reg_file = GPR; 165706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (*instr) { 166706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers#define DISASSEMBLER_ENTRY(opname, \ 167706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers rm8_r8, rm32_r32, \ 168706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers r8_rm8, r32_rm32, \ 169706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers ax8_i8, ax32_i32) \ 170706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case rm8_r8: opcode << #opname; store = true; has_modrm = true; byte_operand = true; break; \ 171706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case rm32_r32: opcode << #opname; store = true; has_modrm = true; break; \ 172706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case r8_rm8: opcode << #opname; load = true; has_modrm = true; byte_operand = true; break; \ 173706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case r32_rm32: opcode << #opname; load = true; has_modrm = true; break; \ 174706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case ax8_i8: opcode << #opname; ax = true; immediate_bytes = 1; byte_operand = true; break; \ 175706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case ax32_i32: opcode << #opname; ax = true; immediate_bytes = 4; break; 176706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 177706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(add, 178706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x00 /* RegMem8/Reg8 */, 0x01 /* RegMem32/Reg32 */, 179706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x02 /* Reg8/RegMem8 */, 0x03 /* Reg32/RegMem32 */, 180706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */) 181706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(or, 182706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x08 /* RegMem8/Reg8 */, 0x09 /* RegMem32/Reg32 */, 183706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x0A /* Reg8/RegMem8 */, 0x0B /* Reg32/RegMem32 */, 184706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */) 185706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(adc, 186706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x10 /* RegMem8/Reg8 */, 0x11 /* RegMem32/Reg32 */, 187706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x12 /* Reg8/RegMem8 */, 0x13 /* Reg32/RegMem32 */, 188706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */) 189706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(sbb, 190706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x18 /* RegMem8/Reg8 */, 0x19 /* RegMem32/Reg32 */, 191706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x1A /* Reg8/RegMem8 */, 0x1B /* Reg32/RegMem32 */, 192706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */) 193706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(and, 194706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x20 /* RegMem8/Reg8 */, 0x21 /* RegMem32/Reg32 */, 195706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x22 /* Reg8/RegMem8 */, 0x23 /* Reg32/RegMem32 */, 196706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */) 197706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(sub, 198706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x28 /* RegMem8/Reg8 */, 0x29 /* RegMem32/Reg32 */, 199706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x2A /* Reg8/RegMem8 */, 0x2B /* Reg32/RegMem32 */, 200706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */) 201706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(xor, 202706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x30 /* RegMem8/Reg8 */, 0x31 /* RegMem32/Reg32 */, 203706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x32 /* Reg8/RegMem8 */, 0x33 /* Reg32/RegMem32 */, 204706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */) 205706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(cmp, 206706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x38 /* RegMem8/Reg8 */, 0x39 /* RegMem32/Reg32 */, 207706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x3A /* Reg8/RegMem8 */, 0x3B /* Reg32/RegMem32 */, 208706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */) 209706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 210706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers#undef DISASSEMBLER_ENTRY 211706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: 212706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << "push"; 213706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 214706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 215706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: 216706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << "pop"; 217706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 218706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 219706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x68: opcode << "push"; immediate_bytes = 4; break; 220d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell case 0x69: opcode << "imul"; load = true; has_modrm = true; immediate_bytes = 4; break; 221706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x6A: opcode << "push"; immediate_bytes = 1; break; 222d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell case 0x6B: opcode << "imul"; load = true; has_modrm = true; immediate_bytes = 1; break; 223706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: 224706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: 225706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers static const char* condition_codes[] = 226b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes {"o", "no", "b/nae/c", "nb/ae/nc", "z/eq", "nz/ne", "be/na", "nbe/a", 227b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes "s", "ns", "p/pe", "np/po", "l/nge", "nl/ge", "le/ng", "nle/g" 228706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers }; 229706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << "j" << condition_codes[*instr & 0xF]; 230706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers branch_bytes = 1; 231706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 23299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case 0x86: case 0x87: 23399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru opcode << "xchg"; 23499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru store = true; 23599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru has_modrm = true; 23699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru byte_operand = (*instr == 0x86); 23799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 238706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x88: opcode << "mov"; store = true; has_modrm = true; byte_operand = true; break; 239706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x89: opcode << "mov"; store = true; has_modrm = true; break; 240706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x8A: opcode << "mov"; load = true; has_modrm = true; byte_operand = true; break; 241706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x8B: opcode << "mov"; load = true; has_modrm = true; break; 242706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 243706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x0F: // 2 byte extended opcode 244706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 245706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (*instr) { 2467caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x10: case 0x11: 2477caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers if (prefix[0] == 0xF2) { 2487caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers opcode << "movsd"; 249fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 2507caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } else if (prefix[0] == 0xF3) { 2517caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers opcode << "movss"; 252fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 2537caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } else if (prefix[2] == 0x66) { 2547caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers opcode << "movupd"; 255fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 2567caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } else { 2577caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers opcode << "movups"; 2587caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } 2597caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 260bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 2617caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers load = *instr == 0x10; 2627caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers store = !load; 2637caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 2642c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case 0x12: case 0x13: 2652c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru if (prefix[2] == 0x66) { 2662c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode << "movlpd"; 2672c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 2682c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } else if (prefix[0] == 0) { 2692c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode << "movlps"; 2702c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 2712c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru has_modrm = true; 2722c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru src_reg_file = dst_reg_file = SSE; 2732c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru load = *instr == 0x12; 2742c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru store = !load; 2752c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2762c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case 0x16: case 0x17: 2772c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru if (prefix[2] == 0x66) { 2782c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode << "movhpd"; 2792c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 2802c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } else if (prefix[0] == 0) { 2812c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode << "movhps"; 2822c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 2832c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru has_modrm = true; 2842c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru src_reg_file = dst_reg_file = SSE; 2852c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru load = *instr == 0x16; 2862c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru store = !load; 2872c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 2882c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case 0x28: case 0x29: 2892c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru if (prefix[2] == 0x66) { 2902c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode << "movapd"; 2912c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 2922c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } else if (prefix[0] == 0) { 2932c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru opcode << "movaps"; 2942c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 2952c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru has_modrm = true; 2962c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru src_reg_file = dst_reg_file = SSE; 2972c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru load = *instr == 0x28; 2982c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru store = !load; 2992c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 300fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2A: 301fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 302fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtpi2pd"; 303fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 304fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF2) { 305fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtsi2sd"; 306fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 307fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF3) { 308fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtsi2ss"; 309fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 310fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 311fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtpi2ps"; 312fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 313fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 314fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 315fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 316fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 317fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2C: 318fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 319fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvttpd2pi"; 320fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 321fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF2) { 322fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvttsd2si"; 323fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 324fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF3) { 325fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvttss2si"; 326fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 327fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 328fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvttps2pi"; 329fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 330fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 331fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 332fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = SSE; 333fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 334fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2D: 335fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 336fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtpd2pi"; 337fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 338fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF2) { 339fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtsd2si"; 340fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 341fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF3) { 342fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtss2si"; 343fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 344fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 345fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "cvtps2pi"; 346fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 347fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 348fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 349fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = SSE; 350fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 351fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2E: 352fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "u"; 353fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao // FALLTHROUGH 354fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2F: 355fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 356fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "comisd"; 357fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 358fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 359fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "comiss"; 360fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 361fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 362fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 363fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = dst_reg_file = SSE; 364fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 365706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x38: // 3 byte extended opcode 366fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell instr++; 367fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 368fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (*instr) { 369fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x40: 370fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pmulld"; 371fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 372fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 373fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 374fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 375fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 376fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 377fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F 38 %02X'", *instr); 378fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 379fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 380fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F 38 %02X'", *instr); 381fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 382706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 383706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x3A: // 3 byte extended opcode 384fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell instr++; 385fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 386fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (*instr) { 387fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x14: 388fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pextrb"; 389fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 390fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 391fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 392fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell dst_reg_file = SSE; 393fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 394fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 395fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x16: 396fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pextrd"; 397fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 398fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 399fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 400fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell dst_reg_file = SSE; 401fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 402fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 403fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 404fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F 3A %02X'", *instr); 405fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 406fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 407fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F 3A %02X'", *instr); 408fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 409706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 410bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: 411bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: 412bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru opcode << "cmov" << condition_codes[*instr & 0xF]; 413bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru has_modrm = true; 414bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru load = true; 415bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru break; 416bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: 417bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x58: case 0x59: case 0x5C: case 0x5D: case 0x5E: case 0x5F: { 418bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers switch (*instr) { 419bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x50: opcode << "movmsk"; break; 420bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x51: opcode << "sqrt"; break; 421bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x52: opcode << "rsqrt"; break; 422bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x53: opcode << "rcp"; break; 423bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x54: opcode << "and"; break; 424bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x55: opcode << "andn"; break; 425bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x56: opcode << "or"; break; 426bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x57: opcode << "xor"; break; 427bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x58: opcode << "add"; break; 428bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x59: opcode << "mul"; break; 429bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5C: opcode << "sub"; break; 430bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5D: opcode << "min"; break; 431bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5E: opcode << "div"; break; 432bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5F: opcode << "max"; break; 433bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers default: LOG(FATAL) << "Unreachable"; 434bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 435bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 436bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "pd"; 437fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 438bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF2) { 439bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "sd"; 440fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 441bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 442bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "ss"; 443fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 444bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 445bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "ps"; 446bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 447bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 448bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 449bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 450bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 451bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 452bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5A: 453bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 454bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvtpd2ps"; 455fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 456bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF2) { 457bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvtsd2ss"; 458fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 459bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 460bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvtss2sd"; 461fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 462bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 463bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvtps2pd"; 464bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 465bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 466bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 467bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 468bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 469bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5B: 470bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 471bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvtps2dq"; 472fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 473bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF2) { 474bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "bad opcode F2 0F 5B"; 475bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 476bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvttps2dq"; 477fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 478bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 479bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "cvtdq2ps"; 480bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 481bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 482bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 483bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 484bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 485d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru case 0x62: 486d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru if (prefix[2] == 0x66) { 487d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru src_reg_file = dst_reg_file = SSE; 488d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru prefix[2] = 0; // Clear prefix now. It has served its purpose as part of the opcode. 489d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru } else { 490d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru src_reg_file = dst_reg_file = MMX; 491d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru } 492d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru opcode << "punpckldq"; 493d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru load = true; 494d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru has_modrm = true; 495d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru break; 496bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x6E: 497bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 498bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers dst_reg_file = SSE; 499fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 500bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 501bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers dst_reg_file = MMX; 502bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 503fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "movd"; 504bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 505bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 506bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 507bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x6F: 508bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 509fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 510bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "movdqa"; 511fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 512bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 513fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 514bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "movdqu"; 515fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 516bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 517bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers dst_reg_file = MMX; 518bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers opcode << "movq"; 519bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 520bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 521bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 522bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 523fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x70: 524fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 525fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pshufd"; 526fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 527fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 528fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 529fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 530fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 531fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else if (prefix[0] == 0xF2) { 532fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pshuflw"; 533fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[0] = 0; 534fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 535fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 536fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 537fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 538fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 539fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F %02X'", *instr); 540fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 541fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 542fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x71: 543fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 544fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 545fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 546fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 547fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = MMX; 548fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 549fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao static const char* x71_opcodes[] = {"unknown-71", "unknown-71", "psrlw", "unknown-71", "psraw", "unknown-71", "psllw", "unknown-71"}; 550fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao modrm_opcodes = x71_opcodes; 551fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao reg_is_opcode = true; 552fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 553fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 554fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao immediate_bytes = 1; 555fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 556fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x72: 557fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 558fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 559fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 560fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 561fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = MMX; 562fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 563fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao static const char* x72_opcodes[] = {"unknown-72", "unknown-72", "psrld", "unknown-72", "psrad", "unknown-72", "pslld", "unknown-72"}; 564fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao modrm_opcodes = x72_opcodes; 565fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao reg_is_opcode = true; 566fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 567fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 568fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao immediate_bytes = 1; 569fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 570fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x73: 571fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 572fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 573fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 574fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 575fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = MMX; 576fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 577fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao static const char* x73_opcodes[] = {"unknown-73", "unknown-73", "psrlq", "unknown-73", "unknown-73", "unknown-73", "psllq", "unknown-73"}; 578fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao modrm_opcodes = x73_opcodes; 579fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao reg_is_opcode = true; 580fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 581fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 582fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao immediate_bytes = 1; 583fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 584fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x7E: 585fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 586fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = SSE; 587fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 588fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 589fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = MMX; 590fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 591fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao opcode << "movd"; 592fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 593fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 594fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 595706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: 596706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: 597706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << "j" << condition_codes[*instr & 0xF]; 598706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers branch_bytes = 4; 599706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 6007caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: 6017caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: 6027caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers opcode << "set" << condition_codes[*instr & 0xF]; 6037caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers modrm_opcodes = NULL; 6047caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers reg_is_opcode = true; 6057caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 6067caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers store = true; 6077caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 6084708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell case 0xA4: 6094708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell opcode << "shld"; 6104708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell has_modrm = true; 6114708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell load = true; 6124708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell immediate_bytes = 1; 6134708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell break; 6144708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell case 0xAC: 6154708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell opcode << "shrd"; 6164708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell has_modrm = true; 6174708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell load = true; 6184708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell immediate_bytes = 1; 6194708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell break; 620703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0xAE: 621703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao if (prefix[0] == 0xF3) { 6225e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 623703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao static const char* xAE_opcodes[] = {"rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"}; 624703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao modrm_opcodes = xAE_opcodes; 625703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao reg_is_opcode = true; 626703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 627703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao uint8_t reg_or_opcode = (instr[1] >> 3) & 7; 628703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao switch (reg_or_opcode) { 629703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0: 630703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kFs; 631703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 632703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 633703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 1: 634703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kGs; 635703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 636703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 637703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 2: 638703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kFs; 639703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao store = true; 640703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 641703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 3: 642703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kGs; 643703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao store = true; 644703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 645703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao default: 646703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 647703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 648703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 649703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 650703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao static const char* xAE_opcodes[] = {"unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", "lfence", "mfence", "sfence"}; 651703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao modrm_opcodes = xAE_opcodes; 652703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao reg_is_opcode = true; 653703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 654703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 655703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao no_ops = true; 656703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 657703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 658f723f0cdc693f81581c0781fa472b1c85a8b42d6Mark Mendell case 0xAF: opcode << "imul"; has_modrm = true; load = true; break; 6598302576126efae240eb21c7545cda7982437bd26jeffhao case 0xB1: opcode << "cmpxchg"; has_modrm = true; store = true; break; 6607caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0xB6: opcode << "movzxb"; has_modrm = true; load = true; break; 6617caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0xB7: opcode << "movzxw"; has_modrm = true; load = true; break; 662854029c13351fd3a8f7794eb6c2c73af0fde8ac8jeffhao case 0xBE: opcode << "movsxb"; has_modrm = true; load = true; break; 663854029c13351fd3a8f7794eb6c2c73af0fde8ac8jeffhao case 0xBF: opcode << "movsxw"; has_modrm = true; load = true; break; 664fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xC5: 665fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 666fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pextrw"; 667fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 668fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 669fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 670fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 671fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 672fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 673fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F %02X'", *instr); 674fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 675fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 67670b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko case 0xC7: 67770b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko static const char* x0FxC7_opcodes[] = { "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7" }; 67870b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko modrm_opcodes = x0FxC7_opcodes; 67970b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko has_modrm = true; 68070b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko reg_is_opcode = true; 68170b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko store = true; 68270b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko break; 683a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: 684a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko opcode << "bswap"; 685a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko reg_in_opcode = true; 686a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko break; 687fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xDB: 688fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 689fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 690fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 691fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 692fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 693fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 694fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pand"; 695fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 696fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 697fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 698fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 699fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xD5: 700fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 701fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pmullw"; 702fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 703fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 704fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 705fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 706fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 707fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << StringPrintf("unknown opcode '0F %02X'", *instr); 708fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 709fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 710fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xEB: 711fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 712fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 713fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 714fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 715fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 716fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 717fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "por"; 718fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 719fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 720fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 721fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 722fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xEF: 723fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 724fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 725fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 726fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 727fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 728fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 729fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "pxor"; 730fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 731fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 732fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 733fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 734fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xF8: 735fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 736fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 737fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 738fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 739fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 740fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 741fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "psubb"; 742fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 743fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 744fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 745fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 746fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xF9: 747fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 748fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 749fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 750fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 751fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 752fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 753fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "psubw"; 754fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 755fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 756fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 757fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 758fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFA: 759fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 760fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 761fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 762fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 763fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 764fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 765fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "psubd"; 766fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 767fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 768fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 769fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 770fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFC: 771fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 772fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 773fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 774fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 775fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 776fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 777fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "paddb"; 778fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 779fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 780fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 781fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 782fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFD: 783fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 784fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 785fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 786fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 787fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 788fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 789fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "paddw"; 790fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 791fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 792fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 793fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 794fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFE: 795fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 796fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 797fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 798fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 799fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 800fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 801fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode << "paddd"; 802fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 803fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 804fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 805fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 806706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: 807706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << StringPrintf("unknown opcode '0F %02X'", *instr); 808706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 809706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 810706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 811706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x80: case 0x81: case 0x82: case 0x83: 812706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers static const char* x80_opcodes[] = {"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"}; 813706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers modrm_opcodes = x80_opcodes; 814706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers has_modrm = true; 815706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_is_opcode = true; 816706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers store = true; 817706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers byte_operand = (*instr & 1) == 0; 818706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers immediate_bytes = *instr == 0x81 ? 4 : 1; 819706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 820703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0x84: case 0x85: 821703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao opcode << "test"; 822703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 823703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 824703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao byte_operand = (*instr & 1) == 0; 825703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 8267caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x8D: 8277caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers opcode << "lea"; 8287caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 8297caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers load = true; 8307caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 831703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0x8F: 832703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao opcode << "pop"; 833703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 834703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao reg_is_opcode = true; 835703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao store = true; 836703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 8372bf31e67694da24a19fc1f328285cebb1a4b9964Mark Mendell case 0x99: 8382bf31e67694da24a19fc1f328285cebb1a4b9964Mark Mendell opcode << "cdq"; 8392bf31e67694da24a19fc1f328285cebb1a4b9964Mark Mendell break; 8404028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell case 0xAF: 8414028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell opcode << (prefix[2] == 0x66 ? "scasw" : "scasl"); 8424028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell break; 843706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: 844706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << "mov"; 845706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers immediate_bytes = 1; 846706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 847706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 848706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: 849706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << "mov"; 850706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers immediate_bytes = 4; 851706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 852706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 8537caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0xC0: case 0xC1: 854e296248a124ed8287b38a9225463696c18d84cd6jeffhao case 0xD0: case 0xD1: case 0xD2: case 0xD3: 8557caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers static const char* shift_opcodes[] = 8567caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers {"rol", "ror", "rcl", "rcr", "shl", "shr", "unknown-shift", "sar"}; 8577caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers modrm_opcodes = shift_opcodes; 8587caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 8597caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers reg_is_opcode = true; 8607caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers store = true; 86116b5c294c37460b51dc1f5296000cc80bbd33419Elliott Hughes immediate_bytes = ((*instr & 0xf0) == 0xc0) ? 1 : 0; 862e296248a124ed8287b38a9225463696c18d84cd6jeffhao cx = (*instr == 0xD2) || (*instr == 0xD3); 863e296248a124ed8287b38a9225463696c18d84cd6jeffhao byte_operand = (*instr == 0xC0); 8647caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 865706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xC3: opcode << "ret"; break; 8660589ca9245849df238812444952c674e01361f2aElliott Hughes case 0xC7: 8670589ca9245849df238812444952c674e01361f2aElliott Hughes static const char* c7_opcodes[] = {"mov", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7"}; 8680589ca9245849df238812444952c674e01361f2aElliott Hughes modrm_opcodes = c7_opcodes; 8690589ca9245849df238812444952c674e01361f2aElliott Hughes store = true; 8700589ca9245849df238812444952c674e01361f2aElliott Hughes immediate_bytes = 4; 8710589ca9245849df238812444952c674e01361f2aElliott Hughes has_modrm = true; 8720589ca9245849df238812444952c674e01361f2aElliott Hughes reg_is_opcode = true; 8730589ca9245849df238812444952c674e01361f2aElliott Hughes break; 8747caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0xCC: opcode << "int 3"; break; 875d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell case 0xD9: 876d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell static const char* d9_opcodes[] = {"flds", "unknown-d9", "fsts", "fstps", "fldenv", "fldcw", "fnstenv", "fnstcw"}; 877d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell modrm_opcodes = d9_opcodes; 878d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell store = true; 879d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell has_modrm = true; 880d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell reg_is_opcode = true; 881d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell break; 882614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru case 0xDB: 883614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru static const char* db_opcodes[] = {"fildl", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db"}; 884614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru modrm_opcodes = db_opcodes; 885614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru load = true; 886614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru has_modrm = true; 887614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru reg_is_opcode = true; 888614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru break; 889d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell case 0xDD: 890d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell static const char* dd_opcodes[] = {"fldl", "fisttp", "fstl", "fstpl", "frstor", "unknown-dd", "fnsave", "fnstsw"}; 891d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell modrm_opcodes = dd_opcodes; 892d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell store = true; 893d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell has_modrm = true; 894d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell reg_is_opcode = true; 895d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell break; 896614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru case 0xDF: 897614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru static const char* df_opcodes[] = {"fild", "unknown-df", "unknown-df", "unknown-df", "unknown-df", "fildll", "unknown-df", "unknown-df"}; 898614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru modrm_opcodes = df_opcodes; 899614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru load = true; 900614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru has_modrm = true; 901614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru reg_is_opcode = true; 902614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru break; 9034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell case 0xE3: opcode << "jecxz"; branch_bytes = 1; break; 9047caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0xE8: opcode << "call"; branch_bytes = 4; break; 905706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xE9: opcode << "jmp"; branch_bytes = 4; break; 906706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xEB: opcode << "jmp"; branch_bytes = 1; break; 90777ae36b35d47393335bf5399cab9c91ccf08e88fjeffhao case 0xF5: opcode << "cmc"; break; 908174651dea03956e160a2cff0d842954823c49134jeffhao case 0xF6: case 0xF7: 909174651dea03956e160a2cff0d842954823c49134jeffhao static const char* f7_opcodes[] = {"test", "unknown-f7", "not", "neg", "mul edx:eax, eax *", "imul edx:eax, eax *", "div edx:eax, edx:eax /", "idiv edx:eax, edx:eax /"}; 910174651dea03956e160a2cff0d842954823c49134jeffhao modrm_opcodes = f7_opcodes; 911174651dea03956e160a2cff0d842954823c49134jeffhao has_modrm = true; 912174651dea03956e160a2cff0d842954823c49134jeffhao reg_is_opcode = true; 913174651dea03956e160a2cff0d842954823c49134jeffhao store = true; 914174651dea03956e160a2cff0d842954823c49134jeffhao immediate_bytes = ((instr[1] & 0x38) == 0) ? 1 : 0; 915174651dea03956e160a2cff0d842954823c49134jeffhao break; 916706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xFF: 917706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers static const char* ff_opcodes[] = {"inc", "dec", "call", "call", "jmp", "jmp", "push", "unknown-ff"}; 918706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers modrm_opcodes = ff_opcodes; 919706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers has_modrm = true; 920706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_is_opcode = true; 921706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers load = true; 922706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 923706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: 924706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << StringPrintf("unknown opcode '%02X'", *instr); 925706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 926706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 927706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers std::ostringstream args; 928706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (reg_in_opcode) { 929706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DCHECK(!has_modrm); 930fba52f1b4bf753790c1d98265c4b0fabb54c7536Vladimir Kostyukov DumpBaseReg(args, rex, *instr & 0x7); 931706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 932706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 93392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes uint32_t address_bits = 0; 934706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (has_modrm) { 935706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t modrm = *instr; 936706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 937706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t mod = modrm >> 6; 938706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t reg_or_opcode = (modrm >> 3) & 7; 939706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t rm = modrm & 7; 940706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers std::ostringstream address; 941e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (mod == 0 && rm == 5) { 942e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (!supports_rex_) { // Absolute address. 943e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address_bits = *reinterpret_cast<const uint32_t*>(instr); 944e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address << StringPrintf("[0x%x]", address_bits); 945e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } else { // 64-bit RIP relative addressing. 946e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address << StringPrintf("[RIP + 0x%x]", *reinterpret_cast<const uint32_t*>(instr)); 947e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } 948706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr += 4; 949706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else if (rm == 4 && mod != 3) { // SIB 950706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t sib = *instr; 951706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 952e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov uint8_t scale = (sib >> 6) & 3; 953706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t index = (sib >> 3) & 7; 954706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t base = sib & 7; 955706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << "["; 956706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (base != 5 || mod != 0) { 9577caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers DumpBaseReg(address, rex, base); 958706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (index != 4) { 959706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << " + "; 960706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 961706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 962706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (index != 4) { 9637caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers DumpIndexReg(address, rex, index); 964e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (scale != 0) { 965e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address << StringPrintf(" * %d", 1 << scale); 966706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 967706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 968e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (mod == 0) { 969e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (base == 5) { 970e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (index != 4) { 971e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(instr)); 972e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } else { 973e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov // 64-bit low 32-bit absolute address, redundant absolute address encoding on 32-bit. 974e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address_bits = *reinterpret_cast<const uint32_t*>(instr); 975e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov address << StringPrintf("%d", address_bits); 976e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } 977e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov instr += 4; 978e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } 979e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } else if (mod == 1) { 980706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(instr)); 981706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 982706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else if (mod == 2) { 983706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(instr)); 984706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr += 4; 985706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 986706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << "]"; 987706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else { 988bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (mod == 3) { 989703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao if (!no_ops) { 990703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao DumpReg(address, rex, rm, byte_operand, prefix[2], load ? src_reg_file : dst_reg_file); 991703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 992bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 993706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << "["; 994bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpBaseReg(address, rex, rm); 995bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (mod == 1) { 996bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(instr)); 997bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers instr++; 998bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (mod == 2) { 999bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(instr)); 1000bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers instr += 4; 1001bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 1002706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers address << "]"; 1003706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1004706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1005706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 10067caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers if (reg_is_opcode && modrm_opcodes != NULL) { 1007706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers opcode << modrm_opcodes[reg_or_opcode]; 1008706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1009706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (load) { 1010706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (!reg_is_opcode) { 1011bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], dst_reg_file); 1012706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << ", "; 1013706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1014706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DumpSegmentOverride(args, prefix[1]); 1015706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << address.str(); 1016706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else { 1017706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DCHECK(store); 1018706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DumpSegmentOverride(args, prefix[1]); 1019706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << address.str(); 1020706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (!reg_is_opcode) { 1021706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << ", "; 1022bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], src_reg_file); 1023706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1024706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1025706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1026706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (ax) { 1027fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao // If this opcode implicitly uses ax, ax is always the first arg. 1028bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg(args, rex, 0 /* EAX */, byte_operand, prefix[2], GPR); 1029706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1030e296248a124ed8287b38a9225463696c18d84cd6jeffhao if (cx) { 1031e296248a124ed8287b38a9225463696c18d84cd6jeffhao args << ", "; 1032e296248a124ed8287b38a9225463696c18d84cd6jeffhao DumpReg(args, rex, 1 /* ECX */, true, prefix[2], GPR); 1033e296248a124ed8287b38a9225463696c18d84cd6jeffhao } 1034706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (immediate_bytes > 0) { 1035e296248a124ed8287b38a9225463696c18d84cd6jeffhao if (has_modrm || reg_in_opcode || ax || cx) { 1036706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << ", "; 1037706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1038706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (immediate_bytes == 1) { 1039706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << StringPrintf("%d", *reinterpret_cast<const int8_t*>(instr)); 1040706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 1041706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else { 1042706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers CHECK_EQ(immediate_bytes, 4u); 1043706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << StringPrintf("%d", *reinterpret_cast<const int32_t*>(instr)); 1044706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr += 4; 1045706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1046706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else if (branch_bytes > 0) { 1047706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DCHECK(!has_modrm); 1048706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers int32_t displacement; 1049706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (branch_bytes == 1) { 1050706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers displacement = *reinterpret_cast<const int8_t*>(instr); 1051706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 1052706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else { 1053706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers CHECK_EQ(branch_bytes, 4u); 1054706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers displacement = *reinterpret_cast<const int32_t*>(instr); 1055706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr += 4; 1056706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 105714178a99fd397737124e65d5ccb9446f85c5ca93Elliott Hughes args << StringPrintf("%+d (%p)", displacement, instr + displacement); 1058706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1059dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (prefix[1] == kFs && !supports_rex_) { 106092301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes args << " ; "; 1061dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers Thread::DumpThreadOffset<4>(args, address_bits); 1062dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers } 1063dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (prefix[1] == kGs && supports_rex_) { 1064dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers args << " ; "; 1065dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers Thread::DumpThreadOffset<8>(args, address_bits); 106692301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes } 106728fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughes std::stringstream hex; 1068706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers for (size_t i = 0; begin_instr + i < instr; ++i) { 106928fa76d17d741238da86dbdb47f721ae97c9eac8Elliott Hughes hex << StringPrintf("%02X", begin_instr[i]); 1070706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 10715e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers std::stringstream prefixed_opcode; 10725e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers switch (prefix[0]) { 10735e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers case 0xF0: prefixed_opcode << "lock "; break; 10745e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers case 0xF2: prefixed_opcode << "repne "; break; 10755e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers case 0xF3: prefixed_opcode << "repe "; break; 10765e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers case 0: break; 10775e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers default: LOG(FATAL) << "Unreachable"; 10785e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers } 10795e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers prefixed_opcode << opcode.str(); 10805e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers os << StringPrintf("%p: %22s \t%-7s ", begin_instr, hex.str().c_str(), 10815e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers prefixed_opcode.str().c_str()) 10825e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers << args.str() << '\n'; 1083706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers return instr - begin_instr; 10847934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // NOLINT(readability/fn_size) 1085706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 1086706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} // namespace x86 1087706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} // namespace art 1088