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 19cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers#include <inttypes.h> 20cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers 21cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers#include <ostream> 22c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <sstream> 23706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 2407ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 25e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h" 2692301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes#include "thread.h" 270f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes 28706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersnamespace art { 29706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersnamespace x86 { 30706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 31b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogerssize_t DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin) { 32b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers return DumpInstruction(os, begin); 33b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers} 34b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers 35706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersvoid DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) { 36706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers size_t length = 0; 37706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers for (const uint8_t* cur = begin; cur < end; cur += length) { 38706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers length = DumpInstruction(os, cur); 39706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 40706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 41706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 42122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukovstatic const char* gReg8Names[] = { 43122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 44122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov}; 45122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukovstatic const char* gExtReg8Names[] = { 46122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", 47122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l" 48122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov}; 49122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukovstatic const char* gReg16Names[] = { 50122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", 51122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" 52122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov}; 53122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukovstatic const char* gReg32Names[] = { 54122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", 55122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" 56122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov}; 5738e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogersstatic const char* gReg64Names[] = { 5838e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 5938e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 6038e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers}; 61706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 62a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell// 64-bit opcode REX modifier. 63c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampeconstexpr uint8_t REX_W = 8U /* 0b1000 */; 64c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampeconstexpr uint8_t REX_R = 4U /* 0b0100 */; 65c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampeconstexpr uint8_t REX_X = 2U /* 0b0010 */; 66c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampeconstexpr uint8_t REX_B = 1U /* 0b0001 */; 67a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell 6838e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogersstatic void DumpReg0(std::ostream& os, uint8_t rex, size_t reg, 69706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool byte_operand, uint8_t size_override) { 7038e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers DCHECK_LT(reg, (rex == 0) ? 8u : 16u); 71a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell bool rex_w = (rex & REX_W) != 0; 72122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov if (byte_operand) { 73122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << ((rex == 0) ? gReg8Names[reg] : gExtReg8Names[reg]); 74122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov } else if (rex_w) { 75122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << gReg64Names[reg]; 76122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov } else if (size_override == 0x66) { 77122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << gReg16Names[reg]; 78122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov } else { 79122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << gReg32Names[reg]; 80706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 81706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 82706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 8388649c790cb437c130dcb6e428cddeb1ae62601cMark Mendellstatic void DumpAnyReg(std::ostream& os, uint8_t rex, size_t reg, 84122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov bool byte_operand, uint8_t size_override, RegFile reg_file) { 85122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov if (reg_file == GPR) { 86122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov DumpReg0(os, rex, reg, byte_operand, size_override); 87122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov } else if (reg_file == SSE) { 88122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << "xmm" << reg; 89122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov } else { 90122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << "mm" << reg; 91122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov } 92122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov} 93122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov 94706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersstatic void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg, 95bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers bool byte_operand, uint8_t size_override, RegFile reg_file) { 96a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell bool rex_r = (rex & REX_R) != 0; 9738e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers size_t reg_num = rex_r ? (reg + 8) : reg; 98122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov DumpAnyReg(os, rex, reg_num, byte_operand, size_override, reg_file); 99122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov} 100122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov 101122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukovstatic void DumpRmReg(std::ostream& os, uint8_t rex, uint8_t reg, 102122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov bool byte_operand, uint8_t size_override, RegFile reg_file) { 103a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell bool rex_b = (rex & REX_B) != 0; 104122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov size_t reg_num = rex_b ? (reg + 8) : reg; 105122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov DumpAnyReg(os, rex, reg_num, byte_operand, size_override, reg_file); 106122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov} 107122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov 108122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukovstatic void DumpAddrReg(std::ostream& os, uint8_t rex, uint8_t reg) { 109122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov if (rex != 0) { 110122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << gReg64Names[reg]; 111bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 112122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov os << gReg32Names[reg]; 113bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 114706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 115706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 1167caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogersstatic void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) { 117a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell bool rex_b = (rex & REX_B) != 0; 11838e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers size_t reg_num = rex_b ? (reg + 8) : reg; 119122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov DumpAddrReg(os, rex, reg_num); 120706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 121706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 12279bb184ec0a661bf1276eef555dd5e20828bc528Vladimir Kostyukovstatic void DumpOpcodeReg(std::ostream& os, uint8_t rex, uint8_t reg, 12379bb184ec0a661bf1276eef555dd5e20828bc528Vladimir Kostyukov bool byte_operand, uint8_t size_override) { 124a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell bool rex_b = (rex & REX_B) != 0; 125122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov size_t reg_num = rex_b ? (reg + 8) : reg; 12679bb184ec0a661bf1276eef555dd5e20828bc528Vladimir Kostyukov DumpReg0(os, rex, reg_num, byte_operand, size_override); 127706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 128706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 12992301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughesenum SegmentPrefix { 13092301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kCs = 0x2e, 13192301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kSs = 0x36, 13292301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kDs = 0x3e, 13392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kEs = 0x26, 13492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kFs = 0x64, 13592301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes kGs = 0x65, 13692301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes}; 13792301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes 138706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogersstatic void DumpSegmentOverride(std::ostream& os, uint8_t segment_prefix) { 139706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (segment_prefix) { 14092301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kCs: os << "cs:"; break; 14192301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kSs: os << "ss:"; break; 14292301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kDs: os << "ds:"; break; 14392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kEs: os << "es:"; break; 14492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kFs: os << "fs:"; break; 14592301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kGs: os << "gs:"; break; 146706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: break; 147706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 148706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} 149706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 150e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe// Do not inline to avoid Clang stack frame problems. b/18733806 1518683038c1f59bea790d8c7691e40eed7f6250e4aAndreas GampeNO_INLINE 1528683038c1f59bea790d8c7691e40eed7f6250e4aAndreas Gampestatic std::string DumpCodeHex(const uint8_t* begin, const uint8_t* end) { 153e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe std::stringstream hex; 154e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe for (size_t i = 0; begin + i < end; ++i) { 155e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe hex << StringPrintf("%02X", begin[i]); 156e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 157e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe return hex.str(); 158e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe} 159e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe 160e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampestd::string DisassemblerX86::DumpAddress(uint8_t mod, uint8_t rm, uint8_t rex64, uint8_t rex_w, 161e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe bool no_ops, bool byte_operand, bool byte_second_operand, 162e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe uint8_t* prefix, bool load, RegFile src_reg_file, 163e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe RegFile dst_reg_file, const uint8_t** instr, 164e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe uint32_t* address_bits) { 165e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe std::ostringstream address; 166e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (mod == 0 && rm == 5) { 167e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (!supports_rex_) { // Absolute address. 1686a0b920512b72542b3f1a3d232fba7ded45ea455Nicolas Geoffray *address_bits = *reinterpret_cast<const uint32_t*>(*instr); 169e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf("[0x%x]", *address_bits); 170e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else { // 64-bit RIP relative addressing. 171e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf("[RIP + 0x%x]", *reinterpret_cast<const uint32_t*>(*instr)); 172e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 173e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr) += 4; 174e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else if (rm == 4 && mod != 3) { // SIB 175e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe uint8_t sib = **instr; 176e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr)++; 177e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe uint8_t scale = (sib >> 6) & 3; 178e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe uint8_t index = (sib >> 3) & 7; 179e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe uint8_t base = sib & 7; 180e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << "["; 181031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe 182031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe // REX.x is bit 3 of index. 183031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe if ((rex64 & REX_X) != 0) { 184031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe index += 8; 185031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe } 186031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe 187031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe // Mod = 0 && base = 5 (ebp): no base (ignores REX.b). 188031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe bool has_base = false; 189e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (base != 5 || mod != 0) { 190031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe has_base = true; 191e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe DumpBaseReg(address, rex64, base); 192e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 193031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe 194031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe // Index = 4 (esp/rsp) is disallowed. 195e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (index != 4) { 196031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe if (has_base) { 197031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe address << " + "; 198031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe } 199031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe DumpAddrReg(address, rex64, index); 200e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (scale != 0) { 201e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf(" * %d", 1 << scale); 202e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 203e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 204031b00dc87cca699f02ce4206a9ecd99d59090ddAndreas Gampe 205e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (mod == 0) { 206e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (base == 5) { 207e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (index != 4) { 208e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr)); 209e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else { 210e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe // 64-bit low 32-bit absolute address, redundant absolute address encoding on 32-bit. 211e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe *address_bits = *reinterpret_cast<const uint32_t*>(*instr); 212e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf("%d", *address_bits); 213e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 214e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr) += 4; 215e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 216e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else if (mod == 1) { 217e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(*instr)); 218e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr)++; 219e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else if (mod == 2) { 220e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr)); 221e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr) += 4; 222e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 223e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << "]"; 224e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else { 225e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (mod == 3) { 226e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (!no_ops) { 227e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe DumpRmReg(address, rex_w, rm, byte_operand || byte_second_operand, 228e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe prefix[2], load ? src_reg_file : dst_reg_file); 229e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 230e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else { 231e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << "["; 232e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe DumpBaseReg(address, rex64, rm); 233e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe if (mod == 1) { 234e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf(" + %d", *reinterpret_cast<const int8_t*>(*instr)); 235e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr)++; 236e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } else if (mod == 2) { 237e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << StringPrintf(" + %d", *reinterpret_cast<const int32_t*>(*instr)); 238e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe (*instr) += 4; 239e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 240e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe address << "]"; 241e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 242e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe } 243e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe return address.str(); 244e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe} 245e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe 246706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogerssize_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) { 247706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers const uint8_t* begin_instr = instr; 248706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool have_prefixes = true; 249706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t prefix[4] = {0, 0, 0, 0}; 250706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers do { 251706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (*instr) { 2527caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers // Group 1 - lock and repeat prefixes: 253706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xF0: 254706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xF2: 255706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xF3: 256706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[0] = *instr; 257706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 258706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers // Group 2 - segment override prefixes: 25992301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kCs: 26092301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kSs: 26192301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kDs: 26292301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kEs: 26392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kFs: 26492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes case kGs: 265706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[1] = *instr; 266706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 267706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers // Group 3 - operand size override: 268706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x66: 269706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[2] = *instr; 270706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 271706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers // Group 4 - address size override: 272706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x67: 273706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers prefix[3] = *instr; 274706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 275706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: 276706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers have_prefixes = false; 277706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 278706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 279706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (have_prefixes) { 280706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 281706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 282706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } while (have_prefixes); 28338e12034f1ef2b32e98b6e49cb36b7cc37a7f1beIan Rogers uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; 284e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov if (rex != 0) { 285e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov instr++; 286e8861b30ac8b2b1ca49386f9c9218f1d6fedc511Vladimir Kostyukov } 287677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers const char** modrm_opcodes = nullptr; 288706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool has_modrm = false; 289706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool reg_is_opcode = false; 290706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers size_t immediate_bytes = 0; 291706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers size_t branch_bytes = 0; 292e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe std::string opcode_tmp; // Storage to keep StringPrintf result alive. 293e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe const char* opcode0 = ""; // Prefix part. 294e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe const char* opcode1 = ""; // Main opcode. 295e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe const char* opcode2 = ""; // Sub-opcode. E.g., jump type. 296e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe const char* opcode3 = ""; // Mod-rm part. 297e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe const char* opcode4 = ""; // Suffix part. 298706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool store = false; // stores to memory (ie rm is on the left) 299706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool load = false; // loads from memory (ie rm is on the right) 30094f3eb0c757d0a6a145e24ef95ef7d35c091bb01Serguei Katkov bool byte_operand = false; // true when the opcode is dealing with byte operands 301677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers // true when the source operand is a byte register but the target register isn't 302677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers // (ie movsxb/movzxb). 303677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers bool byte_second_operand = false; 304122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov bool target_specific = false; // register name depends on target (64 vs 32 bits). 305706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool ax = false; // implicit use of ax 306e296248a124ed8287b38a9225463696c18d84cd6jeffhao bool cx = false; // implicit use of cx 307706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers bool reg_in_opcode = false; // low 3-bits of opcode encode register parameter 308703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao bool no_ops = false; 309bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers RegFile src_reg_file = GPR; 310bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers RegFile dst_reg_file = GPR; 311706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (*instr) { 312706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers#define DISASSEMBLER_ENTRY(opname, \ 313706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers rm8_r8, rm32_r32, \ 314706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers r8_rm8, r32_rm32, \ 315706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers ax8_i8, ax32_i32) \ 316e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case rm8_r8: opcode1 = #opname; store = true; has_modrm = true; byte_operand = true; break; \ 317e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case rm32_r32: opcode1 = #opname; store = true; has_modrm = true; break; \ 318e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case r8_rm8: opcode1 = #opname; load = true; has_modrm = true; byte_operand = true; break; \ 319e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case r32_rm32: opcode1 = #opname; load = true; has_modrm = true; break; \ 320e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case ax8_i8: opcode1 = #opname; ax = true; immediate_bytes = 1; byte_operand = true; break; \ 321e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case ax32_i32: opcode1 = #opname; ax = true; immediate_bytes = 4; break; 322706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 323706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(add, 324706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x00 /* RegMem8/Reg8 */, 0x01 /* RegMem32/Reg32 */, 325706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x02 /* Reg8/RegMem8 */, 0x03 /* Reg32/RegMem32 */, 326706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x04 /* Rax8/imm8 opcode */, 0x05 /* Rax32/imm32 */) 327706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(or, 328706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x08 /* RegMem8/Reg8 */, 0x09 /* RegMem32/Reg32 */, 329706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x0A /* Reg8/RegMem8 */, 0x0B /* Reg32/RegMem32 */, 330706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x0C /* Rax8/imm8 opcode */, 0x0D /* Rax32/imm32 */) 331706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(adc, 332706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x10 /* RegMem8/Reg8 */, 0x11 /* RegMem32/Reg32 */, 333706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x12 /* Reg8/RegMem8 */, 0x13 /* Reg32/RegMem32 */, 334706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x14 /* Rax8/imm8 opcode */, 0x15 /* Rax32/imm32 */) 335706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(sbb, 336706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x18 /* RegMem8/Reg8 */, 0x19 /* RegMem32/Reg32 */, 337706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x1A /* Reg8/RegMem8 */, 0x1B /* Reg32/RegMem32 */, 338706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x1C /* Rax8/imm8 opcode */, 0x1D /* Rax32/imm32 */) 339706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(and, 340706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x20 /* RegMem8/Reg8 */, 0x21 /* RegMem32/Reg32 */, 341706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x22 /* Reg8/RegMem8 */, 0x23 /* Reg32/RegMem32 */, 342706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x24 /* Rax8/imm8 opcode */, 0x25 /* Rax32/imm32 */) 343706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(sub, 344706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x28 /* RegMem8/Reg8 */, 0x29 /* RegMem32/Reg32 */, 345706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x2A /* Reg8/RegMem8 */, 0x2B /* Reg32/RegMem32 */, 346706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x2C /* Rax8/imm8 opcode */, 0x2D /* Rax32/imm32 */) 347706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(xor, 348706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x30 /* RegMem8/Reg8 */, 0x31 /* RegMem32/Reg32 */, 349706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x32 /* Reg8/RegMem8 */, 0x33 /* Reg32/RegMem32 */, 350706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x34 /* Rax8/imm8 opcode */, 0x35 /* Rax32/imm32 */) 351706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan RogersDISASSEMBLER_ENTRY(cmp, 352706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x38 /* RegMem8/Reg8 */, 0x39 /* RegMem32/Reg32 */, 353706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x3A /* Reg8/RegMem8 */, 0x3B /* Reg32/RegMem32 */, 354706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 0x3C /* Rax8/imm8 opcode */, 0x3D /* Rax32/imm32 */) 355706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 356706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers#undef DISASSEMBLER_ENTRY 357706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: 358e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "push"; 359706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 360122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov target_specific = true; 361706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 362706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: 363e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pop"; 364706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 365122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov target_specific = true; 366706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 36733ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell case 0x63: 368ec95f72490de0a7f86c35de3d00b50bb80d036a1Vladimir Kostyukov if ((rex & REX_W) != 0) { 369e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movsxd"; 37033ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell has_modrm = true; 37133ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell load = true; 37233ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell } else { 37333ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell // In 32-bit mode (!supports_rex_) this is ARPL, with no REX prefix the functionality is the 37433ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell // same as 'mov' but the use of the instruction is discouraged. 375e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 376e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 37733ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell } 37833ecf8d692eb192aa0ddb752d3ffe1e899e0f42eMark Mendell break; 379e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x68: opcode1 = "push"; immediate_bytes = 4; break; 380e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x69: opcode1 = "imul"; load = true; has_modrm = true; immediate_bytes = 4; break; 381e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x6A: opcode1 = "push"; immediate_bytes = 1; break; 382e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x6B: opcode1 = "imul"; load = true; has_modrm = true; immediate_bytes = 1; break; 383706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: 384706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: 385706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers static const char* condition_codes[] = 386b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes {"o", "no", "b/nae/c", "nb/ae/nc", "z/eq", "nz/ne", "be/na", "nbe/a", 387b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes "s", "ns", "p/pe", "np/po", "l/nge", "nl/ge", "le/ng", "nle/g" 388706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers }; 389e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "j"; 390e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = condition_codes[*instr & 0xF]; 391706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers branch_bytes = 1; 392706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 39399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case 0x86: case 0x87: 394e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "xchg"; 39599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru store = true; 39699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru has_modrm = true; 39799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru byte_operand = (*instr == 0x86); 39899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 399e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x88: opcode1 = "mov"; store = true; has_modrm = true; byte_operand = true; break; 400e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x89: opcode1 = "mov"; store = true; has_modrm = true; break; 401e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x8A: opcode1 = "mov"; load = true; has_modrm = true; byte_operand = true; break; 402e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x8B: opcode1 = "mov"; load = true; has_modrm = true; break; 403706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 404706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x0F: // 2 byte extended opcode 405706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 406706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers switch (*instr) { 4077caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x10: case 0x11: 4087caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers if (prefix[0] == 0xF2) { 409e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movsd"; 410fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 4117caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } else if (prefix[0] == 0xF3) { 412e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movss"; 413fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 4147caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } else if (prefix[2] == 0x66) { 415e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movupd"; 416fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 4177caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } else { 418e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movups"; 4197caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers } 4207caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 421bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 4227caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers load = *instr == 0x10; 4237caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers store = !load; 4247caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 4252c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case 0x12: case 0x13: 4262c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru if (prefix[2] == 0x66) { 427e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movlpd"; 4282c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 4292c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } else if (prefix[0] == 0) { 430e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movlps"; 4312c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 4322c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru has_modrm = true; 4332c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru src_reg_file = dst_reg_file = SSE; 4342c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru load = *instr == 0x12; 4352c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru store = !load; 4362c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 4372c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case 0x16: case 0x17: 4382c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru if (prefix[2] == 0x66) { 439e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movhpd"; 4402c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 4412c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } else if (prefix[0] == 0) { 442e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movhps"; 4432c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 4442c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru has_modrm = true; 4452c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru src_reg_file = dst_reg_file = SSE; 4462c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru load = *instr == 0x16; 4472c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru store = !load; 4482c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 4492c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru case 0x28: case 0x29: 4502c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru if (prefix[2] == 0x66) { 451e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movapd"; 4522c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 4532c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } else if (prefix[0] == 0) { 454e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movaps"; 4552c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru } 4562c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru has_modrm = true; 4572c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru src_reg_file = dst_reg_file = SSE; 4582c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru load = *instr == 0x28; 4592c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru store = !load; 4602c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru break; 461fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2A: 462fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 463e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtpi2pd"; 464fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 465fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF2) { 466e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtsi2sd"; 467fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 468fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF3) { 469e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtsi2ss"; 470fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 471fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 472e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtpi2ps"; 473fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 474fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 475fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 476fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 477fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 478fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2C: 479fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 480e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvttpd2pi"; 481fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 482fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF2) { 483e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvttsd2si"; 484fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 485fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF3) { 486e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvttss2si"; 487fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 488fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 489e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvttps2pi"; 490fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 491fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 492fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 493fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = SSE; 494fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 495fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2D: 496fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 497e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtpd2pi"; 498fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 499fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF2) { 500e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtsd2si"; 501fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 502fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else if (prefix[0] == 0xF3) { 503e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtss2si"; 504fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 505fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 506e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtps2pi"; 507fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 508fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 509fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 510fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = SSE; 511fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 512fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2E: 513e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode0 = "u"; 514fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers FALLTHROUGH_INTENDED; 515fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x2F: 516fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 517e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "comisd"; 518fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 519fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 520e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "comiss"; 521fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 522fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 523fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao load = true; 524fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = dst_reg_file = SSE; 525fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 526706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x38: // 3 byte extended opcode 527fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell instr++; 528fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 529fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (*instr) { 53060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case 0x01: 531e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "phaddw"; 53260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji prefix[2] = 0; 53360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji has_modrm = true; 53460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji load = true; 53560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji src_reg_file = dst_reg_file = SSE; 53660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 53760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case 0x02: 538e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "phaddd"; 53960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji prefix[2] = 0; 54060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji has_modrm = true; 54160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji load = true; 54260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji src_reg_file = dst_reg_file = SSE; 54360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 544fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x40: 545e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pmulld"; 546fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 547fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 548fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 549fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 550fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 551fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 552e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F 38 %02X'", *instr); 553e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 554fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 555fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 556e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F 38 %02X'", *instr); 557e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 558fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 559706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 560706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x3A: // 3 byte extended opcode 561fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell instr++; 562fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 563fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (*instr) { 564fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell case 0x0A: 565fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell opcode1 = "roundss"; 566fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell prefix[2] = 0; 567fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell has_modrm = true; 568fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell store = true; 569fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell src_reg_file = SSE; 570fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell dst_reg_file = SSE; 571fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell immediate_bytes = 1; 572fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell break; 573fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell case 0x0B: 574fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell opcode1 = "roundsd"; 575fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell prefix[2] = 0; 576fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell has_modrm = true; 577fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell store = true; 578fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell src_reg_file = SSE; 579fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell dst_reg_file = SSE; 580fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell immediate_bytes = 1; 581fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell break; 582fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x14: 583e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pextrb"; 584fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 585fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 586fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 58760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji src_reg_file = SSE; 588fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 589fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 590dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk case 0x15: 591dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk opcode1 = "pextrw"; 592dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk prefix[2] = 0; 593dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk has_modrm = true; 594dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk store = true; 595dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk src_reg_file = SSE; 596dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk immediate_bytes = 1; 597dd17bc3806e800d3b82d5cb27e85ccc1c4e2ee1dnikolay serdjuk break; 598fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x16: 599e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pextrd"; 600fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 601fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 602fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 60360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji src_reg_file = SSE; 604fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 605fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 606fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 607e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F 3A %02X'", *instr); 608e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 609fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 610fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 611e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F 3A %02X'", *instr); 612e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 613fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 614706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 615bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: 616bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: 617e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cmov"; 618e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = condition_codes[*instr & 0xF]; 619bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru has_modrm = true; 620bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru load = true; 621bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru break; 622bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: 623bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x58: case 0x59: case 0x5C: case 0x5D: case 0x5E: case 0x5F: { 624bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers switch (*instr) { 625e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x50: opcode1 = "movmsk"; break; 626e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x51: opcode1 = "sqrt"; break; 627e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x52: opcode1 = "rsqrt"; break; 628e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x53: opcode1 = "rcp"; break; 629e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x54: opcode1 = "and"; break; 630e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x55: opcode1 = "andn"; break; 631e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x56: opcode1 = "or"; break; 632e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x57: opcode1 = "xor"; break; 633e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x58: opcode1 = "add"; break; 634e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x59: opcode1 = "mul"; break; 635e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x5C: opcode1 = "sub"; break; 636e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x5D: opcode1 = "min"; break; 637e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x5E: opcode1 = "div"; break; 638e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x5F: opcode1 = "max"; break; 6392c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers default: LOG(FATAL) << "Unreachable"; UNREACHABLE(); 640bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 641bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 642e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = "pd"; 643fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 644bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF2) { 645e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = "sd"; 646fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 647bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 648e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = "ss"; 649fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 650bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 651e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = "ps"; 652bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 653bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 654bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 655bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 656bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 657bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 658bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5A: 659bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 660e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtpd2ps"; 661fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 662bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF2) { 663e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtsd2ss"; 664fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 665bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 666e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtss2sd"; 667fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 668bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 669e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtps2pd"; 670bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 671bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 672bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 673bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 674bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 675bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x5B: 676bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 677e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtps2dq"; 678fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 679bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF2) { 680e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "bad opcode F2 0F 5B"; 681bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 682e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvttps2dq"; 683fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 684bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 685e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cvtdq2ps"; 686bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 687bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 688bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 689bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers src_reg_file = dst_reg_file = SSE; 690bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 691b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case 0x60: case 0x61: case 0x62: case 0x6C: 692d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru if (prefix[2] == 0x66) { 693d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru src_reg_file = dst_reg_file = SSE; 694d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru prefix[2] = 0; // Clear prefix now. It has served its purpose as part of the opcode. 695d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru } else { 696d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru src_reg_file = dst_reg_file = MMX; 697d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru } 698b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A switch (*instr) { 699e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x60: opcode1 = "punpcklbw"; break; 700e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x61: opcode1 = "punpcklwd"; break; 701e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x62: opcode1 = "punpckldq"; break; 702e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0x6c: opcode1 = "punpcklqdq"; break; 703b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 704d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru load = true; 705d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru has_modrm = true; 706d3266bcc340d653e178e3ab9d74512c8db122eeeRazvan A Lupusoru break; 707bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x6E: 708bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 709bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers dst_reg_file = SSE; 710fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 711bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 712bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers dst_reg_file = MMX; 713bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 714e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movd"; 715bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 716bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 717bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 718bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers case 0x6F: 719bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers if (prefix[2] == 0x66) { 720fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 721e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movdqa"; 722fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 723bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else if (prefix[0] == 0xF3) { 724fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 725e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movdqu"; 726fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 727bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } else { 728bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers dst_reg_file = MMX; 729e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movq"; 730bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers } 731bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers load = true; 732bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers has_modrm = true; 733bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers break; 734fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0x70: 735fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 736e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pshufd"; 737fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 738fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 739fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 740fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 741fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 742fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else if (prefix[0] == 0xF2) { 743e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pshuflw"; 744fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[0] = 0; 745fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 746fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell store = true; 747fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 748fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 749fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 750e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 751e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 752fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 753fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 754fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x71: 755fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 756fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 757fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 758fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 759fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = MMX; 760fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 761677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* x71_opcodes[] = { 762677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-71", "unknown-71", "psrlw", "unknown-71", 763677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "psraw", "unknown-71", "psllw", "unknown-71"}; 764fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao modrm_opcodes = x71_opcodes; 765fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao reg_is_opcode = true; 766fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 767fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 768fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao immediate_bytes = 1; 769fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 770fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x72: 771fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 772fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 773fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 774fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 775fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = MMX; 776fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 777677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* x72_opcodes[] = { 778677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-72", "unknown-72", "psrld", "unknown-72", 779677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "psrad", "unknown-72", "pslld", "unknown-72"}; 780fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao modrm_opcodes = x72_opcodes; 781fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao reg_is_opcode = true; 782fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 783fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 784fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao immediate_bytes = 1; 785fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 786fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x73: 787fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 788fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = SSE; 789fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 790fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 791fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao dst_reg_file = MMX; 792fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 793677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* x73_opcodes[] = { 794677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-73", "unknown-73", "psrlq", "psrldq", 795677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-73", "unknown-73", "psllq", "unknown-73"}; 796fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao modrm_opcodes = x73_opcodes; 797fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao reg_is_opcode = true; 798fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 799fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 800fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao immediate_bytes = 1; 801fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 802fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come case 0x7C: 803fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come if (prefix[0] == 0xF2) { 804e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "haddps"; 805fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 806fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come } else if (prefix[2] == 0x66) { 807e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "haddpd"; 808fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 809fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come } else { 810e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 811e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 812fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come break; 813fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come } 814fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come src_reg_file = dst_reg_file = SSE; 815fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come has_modrm = true; 816fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come load = true; 817fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come break; 818fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao case 0x7E: 819fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao if (prefix[2] == 0x66) { 820fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = SSE; 821fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 822fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } else { 823fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao src_reg_file = MMX; 824fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao } 825e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movd"; 826fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao has_modrm = true; 827fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao store = true; 828fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao break; 829706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: 830706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: 831e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "j"; 832e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = condition_codes[*instr & 0xF]; 833706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers branch_bytes = 4; 834706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 8357caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: 8367caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: 837e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "set"; 838e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode2 = condition_codes[*instr & 0xF]; 839677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers modrm_opcodes = nullptr; 8407caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers reg_is_opcode = true; 8417caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 8427caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers store = true; 8437caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 8444708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell case 0xA4: 845e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "shld"; 8464708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell has_modrm = true; 8474708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell load = true; 8484708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell immediate_bytes = 1; 8494708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell break; 850f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou case 0xA5: 851e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "shld"; 852f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou has_modrm = true; 853f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou load = true; 854f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou cx = true; 855f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou break; 8564708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell case 0xAC: 857e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "shrd"; 8584708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell has_modrm = true; 8594708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell load = true; 8604708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell immediate_bytes = 1; 8614708dcd68eebf1173aef1097dad8ab13466059aaMark Mendell break; 862f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou case 0xAD: 863e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "shrd"; 864f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou has_modrm = true; 865f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou load = true; 866f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou cx = true; 867f40f890ae3acd7b3275355ec90e2814bba8d4fd6Yixin Shou break; 868703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0xAE: 869703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao if (prefix[0] == 0xF3) { 8705e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode 871677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* xAE_opcodes[] = { 872677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", 873677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"}; 874703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao modrm_opcodes = xAE_opcodes; 875703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao reg_is_opcode = true; 876703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 877703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao uint8_t reg_or_opcode = (instr[1] >> 3) & 7; 878703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao switch (reg_or_opcode) { 879703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0: 880703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kFs; 881703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 882703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 883703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 1: 884703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kGs; 885703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 886703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 887703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 2: 888703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kFs; 889703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao store = true; 890703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 891703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 3: 892703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao prefix[1] = kGs; 893703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao store = true; 894703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 895703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao default: 896703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 897703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 898703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 899703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } else { 900677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* xAE_opcodes[] = { 901677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", 902677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-AE", "lfence", "mfence", "sfence"}; 903703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao modrm_opcodes = xAE_opcodes; 904703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao reg_is_opcode = true; 905703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 906703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 907703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao no_ops = true; 908703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao } 909703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 910677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xAF: 911e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "imul"; 912677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 913677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers load = true; 914677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 915677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xB1: 916e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cmpxchg"; 917677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 918677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers store = true; 919677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 920677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xB6: 921e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movzxb"; 922677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 923677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers load = true; 924677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers byte_second_operand = true; 925677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 926677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xB7: 927e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movzxw"; 928677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 929677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers load = true; 930677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 931677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xBE: 932e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movsxb"; 933677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 934677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers load = true; 935677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers byte_second_operand = true; 936677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers rex |= (rex == 0 ? 0 : REX_W); 937677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 938677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xBF: 939e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movsxw"; 940677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 941677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers load = true; 942677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 943677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers case 0xC3: 944e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movnti"; 945677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers store = true; 946677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers has_modrm = true; 947677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers break; 948fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xC5: 949fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 950e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pextrw"; 951fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 952fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 953bd4e6a828fc4aefea7d34a1bbedb81c560c60b6bnikolay serdjuk load = true; 95460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji src_reg_file = SSE; 955fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell immediate_bytes = 1; 956fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 957e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 958e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 959fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 960fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 961fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come case 0xC6: 962fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come if (prefix[2] == 0x66) { 963e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "shufpd"; 964fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come prefix[2] = 0; 965fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come } else { 966e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "shufps"; 967fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come } 968fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come has_modrm = true; 969fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come store = true; 970fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come src_reg_file = dst_reg_file = SSE; 971fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come immediate_bytes = 1; 972fb0fecffb31398adb6f74f58482f2c4aac95b9bfOlivier Come break; 97370b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko case 0xC7: 974677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* x0FxC7_opcodes[] = { 975677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", 976677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7"}; 97770b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko modrm_opcodes = x0FxC7_opcodes; 97870b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko has_modrm = true; 97970b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko reg_is_opcode = true; 98070b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko store = true; 98170b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko break; 982a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: 983e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "bswap"; 984a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko reg_in_opcode = true; 985a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko break; 986b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case 0xD4: 987b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (prefix[2] == 0x66) { 988b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A src_reg_file = dst_reg_file = SSE; 989b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A prefix[2] = 0; 990b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 991b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A src_reg_file = dst_reg_file = MMX; 992b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 993e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "paddq"; 994b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A prefix[2] = 0; 995b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A has_modrm = true; 996b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A load = true; 997b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 998fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xDB: 999fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 1000fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 1001fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1002fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 1003fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 1004fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1005e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pand"; 1006fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 1007fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 1008fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 1009fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1010fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xD5: 1011fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 1012e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pmullw"; 1013fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 1014fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 1015fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 1016fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 1017fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 1018e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 1019e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 1020fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1021fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1022fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xEB: 1023fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 1024fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 1025fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1026fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 1027fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 1028fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1029e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "por"; 1030fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 1031fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 1032fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 1033fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1034fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xEF: 1035fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 1036fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 1037fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1038fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 1039fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 1040fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1041e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pxor"; 1042fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 1043fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 1044fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 1045fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1046b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case 0xF4: 1047b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case 0xF6: 1048fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xF8: 1049fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xF9: 1050fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFA: 1051b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case 0xFB: 1052fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFC: 1053fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFD: 1054fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case 0xFE: 1055fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell if (prefix[2] == 0x66) { 1056fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = SSE; 1057fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode 1058fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } else { 1059fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell src_reg_file = dst_reg_file = MMX; 1060fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1061b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A switch (*instr) { 1062e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF4: opcode1 = "pmuludq"; break; 1063e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF6: opcode1 = "psadbw"; break; 1064e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF8: opcode1 = "psubb"; break; 1065e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF9: opcode1 = "psubw"; break; 1066e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xFA: opcode1 = "psubd"; break; 1067e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xFB: opcode1 = "psubq"; break; 1068e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xFC: opcode1 = "paddb"; break; 1069e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xFD: opcode1 = "paddw"; break; 1070e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xFE: opcode1 = "paddd"; break; 1071b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1072fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell prefix[2] = 0; 1073fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell has_modrm = true; 1074fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell load = true; 1075fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1076706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: 1077e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '0F %02X'", *instr); 1078e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 1079706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 1080706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1081706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 1082706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0x80: case 0x81: case 0x82: case 0x83: 1083706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers static const char* x80_opcodes[] = {"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"}; 1084706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers modrm_opcodes = x80_opcodes; 1085706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers has_modrm = true; 1086706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_is_opcode = true; 1087706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers store = true; 1088706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers byte_operand = (*instr & 1) == 0; 1089706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers immediate_bytes = *instr == 0x81 ? 4 : 1; 1090706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 1091703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0x84: case 0x85: 1092e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "test"; 1093703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 1094703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao load = true; 1095703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao byte_operand = (*instr & 1) == 0; 1096703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 10977caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0x8D: 1098e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "lea"; 10997caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 11007caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers load = true; 11017caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 1102703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao case 0x8F: 1103e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "pop"; 1104703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao has_modrm = true; 1105703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao reg_is_opcode = true; 1106703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao store = true; 1107703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao break; 11082bf31e67694da24a19fc1f328285cebb1a4b9964Mark Mendell case 0x99: 1109e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "cdq"; 11102bf31e67694da24a19fc1f328285cebb1a4b9964Mark Mendell break; 1111d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov case 0x9B: 1112d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov if (instr[1] == 0xDF && instr[2] == 0xE0) { 1113e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "fstsw\tax"; 1114d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov instr += 2; 1115d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov } else { 1116e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 1117e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 1118d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov } 1119d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov break; 11204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell case 0xAF: 1121e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = (prefix[2] == 0x66 ? "scasw" : "scasl"); 11224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell break; 1123706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: 1124e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "mov"; 1125706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers immediate_bytes = 1; 1126a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell byte_operand = true; 1127706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 112879bb184ec0a661bf1276eef555dd5e20828bc528Vladimir Kostyukov byte_operand = true; 1129706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 1130706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: 1131ec95f72490de0a7f86c35de3d00b50bb80d036a1Vladimir Kostyukov if ((rex & REX_W) != 0) { 1132e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "movabsq"; 11335192cbb12856b12620dc346758605baaa1469cedYixin Shou immediate_bytes = 8; 11345192cbb12856b12620dc346758605baaa1469cedYixin Shou reg_in_opcode = true; 11355192cbb12856b12620dc346758605baaa1469cedYixin Shou break; 11365192cbb12856b12620dc346758605baaa1469cedYixin Shou } 1137e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "mov"; 1138706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers immediate_bytes = 4; 1139706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers reg_in_opcode = true; 1140706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 11417caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers case 0xC0: case 0xC1: 1142e296248a124ed8287b38a9225463696c18d84cd6jeffhao case 0xD0: case 0xD1: case 0xD2: case 0xD3: 11437caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers static const char* shift_opcodes[] = 11447caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers {"rol", "ror", "rcl", "rcr", "shl", "shr", "unknown-shift", "sar"}; 11457caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers modrm_opcodes = shift_opcodes; 11467caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers has_modrm = true; 11477caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers reg_is_opcode = true; 11487caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers store = true; 114916b5c294c37460b51dc1f5296000cc80bbd33419Elliott Hughes immediate_bytes = ((*instr & 0xf0) == 0xc0) ? 1 : 0; 1150e296248a124ed8287b38a9225463696c18d84cd6jeffhao cx = (*instr == 0xD2) || (*instr == 0xD3); 1151e296248a124ed8287b38a9225463696c18d84cd6jeffhao byte_operand = (*instr == 0xC0); 11527caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers break; 1153e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xC3: opcode1 = "ret"; break; 1154a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell case 0xC6: 1155677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* c6_opcodes[] = {"mov", "unknown-c6", "unknown-c6", 1156677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-c6", "unknown-c6", "unknown-c6", 1157677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-c6", "unknown-c6"}; 1158a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell modrm_opcodes = c6_opcodes; 1159a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell store = true; 1160a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell immediate_bytes = 1; 1161a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell has_modrm = true; 1162a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell reg_is_opcode = true; 1163a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell byte_operand = true; 1164a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell break; 11650589ca9245849df238812444952c674e01361f2aElliott Hughes case 0xC7: 1166677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* c7_opcodes[] = {"mov", "unknown-c7", "unknown-c7", 1167677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-c7", "unknown-c7", "unknown-c7", 1168677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-c7", "unknown-c7"}; 11690589ca9245849df238812444952c674e01361f2aElliott Hughes modrm_opcodes = c7_opcodes; 11700589ca9245849df238812444952c674e01361f2aElliott Hughes store = true; 11710589ca9245849df238812444952c674e01361f2aElliott Hughes immediate_bytes = 4; 11720589ca9245849df238812444952c674e01361f2aElliott Hughes has_modrm = true; 11730589ca9245849df238812444952c674e01361f2aElliott Hughes reg_is_opcode = true; 11740589ca9245849df238812444952c674e01361f2aElliott Hughes break; 1175e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xCC: opcode1 = "int 3"; break; 1176d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell case 0xD9: 1177d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov if (instr[1] == 0xF8) { 1178e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "fprem"; 1179d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov instr++; 1180d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov } else { 1181d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov static const char* d9_opcodes[] = {"flds", "unknown-d9", "fsts", "fstps", "fldenv", "fldcw", 1182d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov "fnstenv", "fnstcw"}; 1183d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov modrm_opcodes = d9_opcodes; 1184d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov store = true; 1185d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov has_modrm = true; 1186d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov reg_is_opcode = true; 1187d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov } 1188d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov break; 1189d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov case 0xDA: 1190d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov if (instr[1] == 0xE9) { 1191e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = "fucompp"; 1192d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov instr++; 1193d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov } else { 1194e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 1195e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 1196d48b8a2bc111d30ebafdd2c661e9c0789f5c66a7Vladimir Kostyukov } 1197d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell break; 1198614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru case 0xDB: 1199677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* db_opcodes[] = {"fildl", "unknown-db", "unknown-db", 1200677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-db", "unknown-db", "unknown-db", 1201677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-db", "unknown-db"}; 1202614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru modrm_opcodes = db_opcodes; 1203614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru load = true; 1204614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru has_modrm = true; 1205614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru reg_is_opcode = true; 1206614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru break; 1207d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell case 0xDD: 1208677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* dd_opcodes[] = {"fldl", "fisttp", "fstl", 1209677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "fstpl", "frstor", "unknown-dd", 1210677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "fnsave", "fnstsw"}; 1211d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell modrm_opcodes = dd_opcodes; 1212d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell store = true; 1213d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell has_modrm = true; 1214d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell reg_is_opcode = true; 1215d19b55a05b52b7f7da9f894eba63ed03e2a62283Mark Mendell break; 1216614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru case 0xDF: 1217677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* df_opcodes[] = {"fild", "unknown-df", "unknown-df", 1218677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-df", "unknown-df", "fildll", 1219677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "unknown-df", "unknown-df"}; 1220614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru modrm_opcodes = df_opcodes; 1221614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru load = true; 1222614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru has_modrm = true; 1223614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru reg_is_opcode = true; 1224614c2b4e219631e8c190fd9fd5d4d9cd343434e1Razvan A Lupusoru break; 1225e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xE3: opcode1 = "jecxz"; branch_bytes = 1; break; 1226e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xE8: opcode1 = "call"; branch_bytes = 4; break; 1227e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xE9: opcode1 = "jmp"; branch_bytes = 4; break; 1228e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xEB: opcode1 = "jmp"; branch_bytes = 1; break; 1229e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF5: opcode1 = "cmc"; break; 1230174651dea03956e160a2cff0d842954823c49134jeffhao case 0xF6: case 0xF7: 1231677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* f7_opcodes[] = { 1232677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "test", "unknown-f7", "not", "neg", "mul edx:eax, eax *", 1233677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "imul edx:eax, eax *", "div edx:eax, edx:eax /", 1234677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "idiv edx:eax, edx:eax /"}; 1235174651dea03956e160a2cff0d842954823c49134jeffhao modrm_opcodes = f7_opcodes; 1236174651dea03956e160a2cff0d842954823c49134jeffhao has_modrm = true; 1237174651dea03956e160a2cff0d842954823c49134jeffhao reg_is_opcode = true; 1238174651dea03956e160a2cff0d842954823c49134jeffhao store = true; 1239174651dea03956e160a2cff0d842954823c49134jeffhao immediate_bytes = ((instr[1] & 0x38) == 0) ? 1 : 0; 1240174651dea03956e160a2cff0d842954823c49134jeffhao break; 1241706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers case 0xFF: 1242e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov { 1243677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers static const char* ff_opcodes[] = { 1244677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "inc", "dec", "call", "call", 1245677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers "jmp", "jmp", "push", "unknown-ff"}; 1246e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov modrm_opcodes = ff_opcodes; 1247e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov has_modrm = true; 1248e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov reg_is_opcode = true; 1249e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov load = true; 1250e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov const uint8_t opcode_digit = (instr[1] >> 3) & 7; 1251e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov // 'call', 'jmp' and 'push' are target specific instructions 1252e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov if (opcode_digit == 2 || opcode_digit == 4 || opcode_digit == 6) { 1253e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov target_specific = true; 1254e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov } 1255e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov } 1256706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 1257706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers default: 1258e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode_tmp = StringPrintf("unknown opcode '%02X'", *instr); 1259e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode1 = opcode_tmp.c_str(); 1260706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers break; 1261706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1262706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers std::ostringstream args; 1263122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov // We force the REX prefix to be available for 64-bit target 1264122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov // in order to dump addr (base/index) registers correctly. 1265122113a8a233f824c014a8fe9d90626218c4dccaVladimir Kostyukov uint8_t rex64 = supports_rex_ ? (rex | 0x40) : rex; 1266e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov // REX.W should be forced for 64-target and target-specific instructions (i.e., push or pop). 1267e443a8063518fb1c5229afa3081b9fd1f6d33b16Vladimir Kostyukov uint8_t rex_w = (supports_rex_ && target_specific) ? (rex | 0x48) : rex; 1268706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (reg_in_opcode) { 1269706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DCHECK(!has_modrm); 127079bb184ec0a661bf1276eef555dd5e20828bc528Vladimir Kostyukov DumpOpcodeReg(args, rex_w, *instr & 0x7, byte_operand, prefix[2]); 1271706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1272706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 127392301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes uint32_t address_bits = 0; 1274706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (has_modrm) { 1275706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t modrm = *instr; 1276706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 1277706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t mod = modrm >> 6; 1278706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t reg_or_opcode = (modrm >> 3) & 7; 1279706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers uint8_t rm = modrm & 7; 1280e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe std::string address = DumpAddress(mod, rm, rex64, rex_w, no_ops, byte_operand, 1281e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe byte_second_operand, prefix, load, src_reg_file, dst_reg_file, 1282e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe &instr, &address_bits); 1283706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 1284677c12fe1939cad5795e7c9f4738941508c4d56fIan Rogers if (reg_is_opcode && modrm_opcodes != nullptr) { 1285e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode3 = modrm_opcodes[reg_or_opcode]; 1286706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1287a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell 1288a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell // Add opcode suffixes to indicate size. 1289a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell if (byte_operand) { 1290e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode4 = "b"; 1291a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell } else if ((rex & REX_W) != 0) { 1292e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode4 = "q"; 1293a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell } else if (prefix[2] == 0x66) { 1294e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe opcode4 = "w"; 1295a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell } 1296a33720c7370d1c9e0d6569d7126bb06f2083c614Mark Mendell 1297706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (load) { 1298706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (!reg_is_opcode) { 1299bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], dst_reg_file); 1300706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << ", "; 1301706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1302706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DumpSegmentOverride(args, prefix[1]); 1303e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe args << address; 1304706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else { 1305706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DCHECK(store); 1306706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DumpSegmentOverride(args, prefix[1]); 1307e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe args << address; 1308706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (!reg_is_opcode) { 1309706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << ", "; 1310bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg(args, rex, reg_or_opcode, byte_operand, prefix[2], src_reg_file); 1311706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1312706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1313706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1314706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (ax) { 1315fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao // If this opcode implicitly uses ax, ax is always the first arg. 1316bf989802bfcd0a0e1d27feb6b67b19cccb7b31e8Ian Rogers DumpReg(args, rex, 0 /* EAX */, byte_operand, prefix[2], GPR); 1317706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1318e296248a124ed8287b38a9225463696c18d84cd6jeffhao if (cx) { 1319e296248a124ed8287b38a9225463696c18d84cd6jeffhao args << ", "; 1320e296248a124ed8287b38a9225463696c18d84cd6jeffhao DumpReg(args, rex, 1 /* ECX */, true, prefix[2], GPR); 1321e296248a124ed8287b38a9225463696c18d84cd6jeffhao } 1322706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (immediate_bytes > 0) { 1323e296248a124ed8287b38a9225463696c18d84cd6jeffhao if (has_modrm || reg_in_opcode || ax || cx) { 1324706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << ", "; 1325706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1326706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (immediate_bytes == 1) { 1327706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers args << StringPrintf("%d", *reinterpret_cast<const int8_t*>(instr)); 1328706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 13295192cbb12856b12620dc346758605baaa1469cedYixin Shou } else if (immediate_bytes == 4) { 133067d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell if (prefix[2] == 0x66) { // Operand size override from 32-bit to 16-bit. 133167d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell args << StringPrintf("%d", *reinterpret_cast<const int16_t*>(instr)); 133267d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell instr += 2; 133367d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell } else { 133467d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell args << StringPrintf("%d", *reinterpret_cast<const int32_t*>(instr)); 133567d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell instr += 4; 133667d18be2a5bddbd8ee9ef144b34ccaeba08a1db2Mark Mendell } 13375192cbb12856b12620dc346758605baaa1469cedYixin Shou } else { 13385192cbb12856b12620dc346758605baaa1469cedYixin Shou CHECK_EQ(immediate_bytes, 8u); 13395192cbb12856b12620dc346758605baaa1469cedYixin Shou args << StringPrintf("%" PRId64, *reinterpret_cast<const int64_t*>(instr)); 13405192cbb12856b12620dc346758605baaa1469cedYixin Shou instr += 8; 1341706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1342706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else if (branch_bytes > 0) { 1343706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers DCHECK(!has_modrm); 1344706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers int32_t displacement; 1345706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers if (branch_bytes == 1) { 1346706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers displacement = *reinterpret_cast<const int8_t*>(instr); 1347706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr++; 1348706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } else { 1349706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers CHECK_EQ(branch_bytes, 4u); 1350706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers displacement = *reinterpret_cast<const int32_t*>(instr); 1351706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers instr += 4; 1352706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 13532cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom args << StringPrintf("%+d (", displacement) 13542cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom << FormatInstructionPointer(instr + displacement) 13552cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom << ")"; 1356706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers } 1357dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (prefix[1] == kFs && !supports_rex_) { 135892301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes args << " ; "; 1359dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers Thread::DumpThreadOffset<4>(args, address_bits); 1360dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers } 1361dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (prefix[1] == kGs && supports_rex_) { 1362dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers args << " ; "; 1363dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers Thread::DumpThreadOffset<8>(args, address_bits); 136492301d97693ea52f5f6a9bc62d0c7fc611f87c7bElliott Hughes } 1365e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe const char* prefix_str; 13665e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers switch (prefix[0]) { 1367e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF0: prefix_str = "lock "; break; 1368e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF2: prefix_str = "repne "; break; 1369e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0xF3: prefix_str = "repe "; break; 1370e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe case 0: prefix_str = ""; break; 13712c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers default: LOG(FATAL) << "Unreachable"; UNREACHABLE(); 13725e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers } 13732cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom os << FormatInstructionPointer(begin_instr) 1374e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe << StringPrintf(": %22s \t%-7s%s%s%s%s%s ", DumpCodeHex(begin_instr, instr).c_str(), 1375e5eb7060dbacfd7c768692a8fcc4a6017d0bd1ccAndreas Gampe prefix_str, opcode0, opcode1, opcode2, opcode3, opcode4) 13765e588b3c9af58ef54dcdd2cf129472dbe923a5bfIan Rogers << args.str() << '\n'; 1377706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers return instr - begin_instr; 13787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // NOLINT(readability/fn_size) 1379706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers 1380706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} // namespace x86 1381706a10ea53a32455c6b3ffc5e5e0e1f6f191ec2aIan Rogers} // namespace art 1382