disasm-x64.cc revision 3ce2e2076e8e3e60cf1810eec160ea2d8557e9e7
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h> 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdio.h> 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandType { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNSET_OP_ORDER = 0, 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operand size decides between 16, 32 and 64 bit operands. 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REG_OPER_OP_ORDER = 1, // Register destination, operand source. 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OPER_REG_OP_ORDER = 2, // Operand destination, register source. 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fixed 8-bit operands. 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_SIZE_OPERAND_FLAG = 4, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG, 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic { 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int b; // -1 terminates, otherwise must be in range (0..255) 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order_; 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic two_operands_instr[] = { 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x00, BYTE_OPER_REG_OP_ORDER, "add" }, 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x01, OPER_REG_OP_ORDER, "add" }, 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x02, BYTE_REG_OPER_OP_ORDER, "add" }, 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x03, REG_OPER_OP_ORDER, "add" }, 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x08, BYTE_OPER_REG_OP_ORDER, "or" }, 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x09, OPER_REG_OP_ORDER, "or" }, 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" }, 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x0B, REG_OPER_OP_ORDER, "or" }, 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" }, 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x11, OPER_REG_OP_ORDER, "adc" }, 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" }, 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x13, REG_OPER_OP_ORDER, "adc" }, 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" }, 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x19, OPER_REG_OP_ORDER, "sbb" }, 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" }, 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x1B, REG_OPER_OP_ORDER, "sbb" }, 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x20, BYTE_OPER_REG_OP_ORDER, "and" }, 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x21, OPER_REG_OP_ORDER, "and" }, 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x22, BYTE_REG_OPER_OP_ORDER, "and" }, 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x23, REG_OPER_OP_ORDER, "and" }, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" }, 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x29, OPER_REG_OP_ORDER, "sub" }, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" }, 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x2B, REG_OPER_OP_ORDER, "sub" }, 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" }, 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x31, OPER_REG_OP_ORDER, "xor" }, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" }, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x33, REG_OPER_OP_ORDER, "xor" }, 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" }, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x39, OPER_REG_OP_ORDER, "cmp" }, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" }, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x3B, REG_OPER_OP_ORDER, "cmp" }, 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x63, REG_OPER_OP_ORDER, "movsxlq" }, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x84, BYTE_REG_OPER_OP_ORDER, "test" }, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x85, REG_OPER_OP_ORDER, "test" }, 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" }, 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x87, REG_OPER_OP_ORDER, "xchg" }, 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" }, 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x89, OPER_REG_OP_ORDER, "mov" }, 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" }, 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x8B, REG_OPER_OP_ORDER, "mov" }, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x8D, REG_OPER_OP_ORDER, "lea" }, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic zero_operands_instr[] = { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xC3, UNSET_OP_ORDER, "ret" }, 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xC9, UNSET_OP_ORDER, "leave" }, 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xF4, UNSET_OP_ORDER, "hlt" }, 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xCC, UNSET_OP_ORDER, "int3" }, 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x60, UNSET_OP_ORDER, "pushad" }, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x61, UNSET_OP_ORDER, "popad" }, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9C, UNSET_OP_ORDER, "pushfd" }, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9D, UNSET_OP_ORDER, "popfd" }, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9E, UNSET_OP_ORDER, "sahf" }, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x99, UNSET_OP_ORDER, "cdq" }, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9B, UNSET_OP_ORDER, "fwait" }, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic call_jump_instr[] = { 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xE8, UNSET_OP_ORDER, "call" }, 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xE9, UNSET_OP_ORDER, "jmp" }, 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic short_immediate_instr[] = { 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x05, UNSET_OP_ORDER, "add" }, 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x0D, UNSET_OP_ORDER, "or" }, 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x15, UNSET_OP_ORDER, "adc" }, 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x1D, UNSET_OP_ORDER, "sbb" }, 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x25, UNSET_OP_ORDER, "and" }, 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x2D, UNSET_OP_ORDER, "sub" }, 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x35, UNSET_OP_ORDER, "xor" }, 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x3D, UNSET_OP_ORDER, "cmp" }, 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* conditional_code_suffix[] = { 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "o", "no", "c", "nc", "z", "nz", "na", "a", 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "s", "ns", "pe", "po", "l", "ge", "le", "g" 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType { 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_INSTR, 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ZERO_OPERANDS_INSTR, 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TWO_OPERANDS_INSTR, 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JUMP_CONDITIONAL_SHORT_INSTR, 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REGISTER_INSTR, 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PUSHPOP_INSTR, // Has implicit 64-bit operand size. 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MOVE_REG_INSTR, 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_JUMP_INSTR, 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SHORT_IMMEDIATE_INSTR 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionType type; 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order_; 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size_operation; // Fixed 8-bit operation. 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable { 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionTable(); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& Get(byte x) const { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instructions_[x]; 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc instructions_[256]; 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Clear(); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Init(); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CopyTable(ByteMnemonic bm[], InstructionType type); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetTableRange(InstructionType type, byte start, byte end, bool byte_size, 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AddJumpConditionalShort(); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() { 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Init(); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() { 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < 256; i++) { 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].mnem = "(bad)"; 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].type = NO_INSTR; 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].op_order_ = UNSET_OP_ORDER; 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].byte_size_operation = false; 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() { 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(call_jump_instr, CALL_JUMP_INSTR); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddJumpConditionalShort(); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push"); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop"); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov"); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; bm[i].b >= 0; i++) { 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[bm[i].b]; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = bm[i].mnem; 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order = bm[i].op_order_; 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->op_order_ = 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(id->type == NO_INSTR); // Information not already entered 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type, 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size, 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem) { 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = start; b <= end; b++) { 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(id->type == NO_INSTR); // Information already entered 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = mnem; 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->byte_size_operation = byte_size; 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() { 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = 0x70; b <= 0x7F; b++) { 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(id->type == NO_INSTR); // Information already entered 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = NULL; // Computed depending on condition code. 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = JUMP_CONDITIONAL_SHORT_INSTR; 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionTable instruction_table; 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionDesc cmov_instructions[16] = { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false} 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DisassemblerX64 implementation. 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum UnimplementedOpcodeAction { 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CONTINUE_ON_UNIMPLEMENTED_OPCODE, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ABORT_ON_UNIMPLEMENTED_OPCODE 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A new DisassemblerX64 object is created to disassemble each instruction. 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The object can only disassemble a single instruction. 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerX64 { 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerX64(const NameConverter& converter, 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedOpcodeAction unimplemented_action = 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ABORT_ON_UNIMPLEMENTED_OPCODE) 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_(0), 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort_on_unimplemented_( 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE), 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rex_(0), 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_(0), 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block group_1_prefix_(0), 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_(false) { 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[0] = '\0'; 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~DisassemblerX64() { 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum OperandSize { 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_SIZE = 0, 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WORD_SIZE = 1, 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DOUBLEWORD_SIZE = 2, 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block QUADWORD_SIZE = 3 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const NameConverter& converter_; 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int tmp_buffer_pos_; 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented_; 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prefixes parsed 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte rex_; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Byte size operand override. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size_operand_; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void setRex(byte rex) { 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0x40, rex & 0xF0); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rex_ = rex; 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex() { return rex_ != 0; } 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_b() { return (rex_ & 0x01) != 0; } 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Actual number of base register given the low bits and the rex.b state. 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_x() { return (rex_ & 0x02) != 0; } 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_r() { return (rex_ & 0x04) != 0; } 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_w() { return (rex_ & 0x08) != 0; } 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandSize operand_size() { 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (byte_size_operand_) return BYTE_SIZE; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rex_w()) return QUADWORD_SIZE; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (operand_size_ != 0) return WORD_SIZE; 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return DOUBLEWORD_SIZE; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char operand_size_code() { 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "bwlq"[operand_size()]; 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfCPURegister(int reg) const { 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfCPURegister(reg); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfByteCPURegister(int reg) const { 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfByteCPURegister(reg); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfXMMRegister(int reg) const { 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfXMMRegister(reg); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(byte* addr) const { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfAddress(addr); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Disassembler helper functions. 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void get_modrm(byte data, 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* mod, 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* regop, 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* rm) { 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *mod = (data >> 6) & 3; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0); 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rm = (data & 7) | (rex_b() ? 8 : 0); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void get_sib(byte data, 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* scale, 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* index, 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* base) { 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *scale = (data >> 6) & 3; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *base = (data & 7) | (rex_b() ? 8 : 0); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperandHelper(byte* modrmp, 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegisterNameMapping register_name); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperand(byte* modrmp); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightByteOperand(byte* modrmp); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintOperands(const char* mnem, 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order, 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediate(byte* data, OperandSize size); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediateOp(byte* data); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* TwoByteMnemonic(byte opcode); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int TwoByteOpcodeInstruction(byte* data); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int F7Instruction(byte* data); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int ShiftInstruction(byte* data); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpShort(byte* data); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditional(byte* data); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditionalShort(byte* data); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SetCC(byte* data); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int FPUInstruction(byte* data); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AppendToBuffer(const char* format, ...); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UnimplementedInstruction() { 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (abort_on_unimplemented_) { 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(false); 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("'Unimplemented Instruction'"); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerX64::AppendToBuffer(const char* format, ...) { 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = v8::internal::OS::VSNPrintF(buf, format, args); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ += result; 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperandHelper( 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* modrmp, 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegisterNameMapping register_name) { 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*modrmp, &mod, ®op, &rm); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (mod) { 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rm & 7) == 5) { 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[0x%x]", disp); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((rm & 7) == 4) { 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Codes for SIB byte. 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // index == rsp means no index. Only use sib byte with no index for 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rsp and r12 base. 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(base)); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (base == 5) { 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // base == rbp means no base register (when mod == 0). 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s*%d+0x%x]", 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, disp); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (index != 4 && base != 5) { 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base+index*scale] 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d]", 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: // fall through 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rm & 7) == 4) { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : *reinterpret_cast<char*>(modrmp + 2); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-disp > 0) { 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s-0x%x]", (this->*register_name)(base), -disp); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+0x%x]", (this->*register_name)(base), disp); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-disp > 0) { 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d-0x%x]", 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block -disp); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d+0x%x]", 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disp); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 6 : 3; 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No sib. 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : *reinterpret_cast<char*>(modrmp + 1); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-disp > 0) { 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s-0x%x]", (this->*register_name)(rm), -disp); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (mod == 2) ? 5 : 2; 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", (this->*register_name)(rm)); 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediate(byte* data, OperandSize size) { 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t value; 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count; 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (size) { 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BYTE_SIZE: 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *data; 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 1; 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case WORD_SIZE: 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<int16_t*>(data); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 2; 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<uint32_t*>(data); 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 4; 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<int32_t*>(data); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 4; 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = 0; // Initialize variables on all paths to satisfy the compiler. 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 0; 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%" V8_PTR_PREFIX "x", value); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return count; 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperand(byte* modrmp) { 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerX64::NameOfCPURegister); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightByteOperand(byte* modrmp) { 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerX64::NameOfByteCPURegister); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data. 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintOperands(const char* mnem, 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order, 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data) { 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *data; 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int advance = 0; 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* register_name = 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ ? NameOfByteCPURegister(regop) 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : NameOfCPURegister(regop); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (op_order) { 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REG_OPER_OP_ORDER: { 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s,", 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block register_name); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = byte_size_operand_ ? PrintRightByteOperand(data) 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : PrintRightOperand(data); 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case OPER_REG_OP_ORDER: { 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c ", mnem, operand_size_code()); 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = byte_size_operand_ ? PrintRightByteOperand(data) 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : PrintRightOperand(data); 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", register_name); 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return advance; 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte. 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'. 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediateOp(byte* data) { 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size_immediate = (*data & 0x02) != 0; 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data + 1); 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "Imm???"; 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "add"; 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "or"; 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "adc"; 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "and"; 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "sub"; 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "xor"; 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "cmp"; 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c ", mnem, operand_size_code()); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x"); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size(); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count += PrintImmediate(data + 1 + count, immediate_size); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count; 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::F7Instruction(byte* data) { 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(*data == 0xF7); 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data + 1); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3 && regop != 0) { 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "not"; 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "neg"; 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "mul"; 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "idiv"; 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s", 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm)); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (mod == 3 && regop == 0) { 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data + 2); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test%c %s,0x%x", 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm), 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (regop == 0) { 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test%c ", operand_size_code()); 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count); 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 4 /*int32_t*/; 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::ShiftInstruction(byte* data) { 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte op = *data & (~1); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op != 0xD0 && op != 0xD2 && op != 0xC0) { 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data + 1); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block regop &= 0x7; // The REX.R bit does not affect the operation. 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm8 = -1; 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_bytes = 2; 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod != 3) { 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "rol"; 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "ror"; 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "rcl"; 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "rcr"; 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "shl"; 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "shr"; 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "sar"; 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(mnem != NULL); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op == 0xD0) { 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = 1; 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (op == 0xC0) { 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = *(data + 2); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_bytes = 3; 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s,", 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ ? NameOfByteCPURegister(rm) 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : NameOfCPURegister(rm)); 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op == 0xD2) { 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("cl"); 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%d", imm8); 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpShort(byte* data) { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(*data == 0xEB); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data + 1); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("jmp %s", NameOfAddress(dest)); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditional(byte* data) { 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(*data == 0x0F); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data + 1) & 0x0F; 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = conditional_code_suffix[cond]; 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; // includes 0x0F 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditionalShort(byte* data) { 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *data & 0x0F; 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data + 1); 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = conditional_code_suffix[cond]; 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::SetCC(byte* data) { 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block assert(*data == 0x0F); 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data + 1) & 0x0F; 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = conditional_code_suffix[cond]; 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("set%s%c ", mnem, operand_size_code()); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRightByteOperand(data + 2); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; // includes 0x0F 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::FPUInstruction(byte* data) { 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b1 = *data; 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b2 = *(data + 1); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b1 == 0xD9) { 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (b2) { 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xE0: 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fchs"; 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xE1: 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fabs"; 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xE4: 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "ftst"; 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF5: 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fprem1"; 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fincstp"; 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xE8: 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fld1"; 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEE: 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fldz"; 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF8: 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fprem"; 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mnem != NULL) { 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((b2 & 0xF8) == 0xC8) { 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("fxch st%d", b2 & 0x7); 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data + 1), &mod, ®op, &rm); 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fld_s"; 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fstp_s"; 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return count + 1; 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b1 == 0xDD) { 8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int mod, regop, rm; 8643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block get_modrm(*(data + 1), &mod, ®op, &rm); 8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (mod == 3) { 8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block switch (regop) { 8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case 0: 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AppendToBuffer("ffree st%d", rm & 7); 8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block case 2: 8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block AppendToBuffer("fstp st%d", rm & 7); 8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block default: 8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UnimplementedInstruction(); 8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block break; 8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fld_d"; 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fstp_d"; 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return count + 1; 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b1 == 0xDB) { 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data + 1), &mod, ®op, &rm); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fild_s"; 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fist_s"; 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fistp_s"; 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return count + 1; 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b1 == 0xDF) { 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0xE0) { 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("fnstsw_ax"); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data + 1), &mod, ®op, &rm); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fild_d"; 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fistp_d"; 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return count + 1; 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b1 == 0xDC || b1 == 0xDE) { 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_pop = (b1 == 0xDE); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_pop && b2 == 0xD9) { 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("fcompp"); 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "FP0xDC"; 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (b2 & 0xF8) { 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC0: 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fadd"; 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xE8: 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fsub"; 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC8: 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fmul"; 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF8: 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "fdiv"; 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%s st%d", mnem, is_pop ? "p" : "", b2 & 0x7); 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b1 == 0xDA && b2 == 0xE9) { 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "fucompp"; 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("Unknown FP instruction"); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all two-byte opcodes, which start with 0x0F. 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix. 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A. 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte opcode = *(data + 1); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* current = data + 2; 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // At return, "current" points to the start of the next instruction. 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnemonic = TwoByteMnemonic(opcode); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (opcode == 0x1F) { 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOP 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current++; 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == 4) { // SIB byte present. 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current++; 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 1) { // Byte displacement. 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += 1; 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (mod == 2) { // 32-bit displacement. 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += 4; 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } // else no immediate displacement. 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("nop"); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0xA2 || opcode == 0x31) { 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RDTSC or CPUID 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnemonic); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF0) == 0x40) { 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CMOVcc: conditional move. 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int condition = opcode & 0x0F; 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& idesc = cmov_instructions[condition]; 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ = idesc.byte_size_operation; 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintOperands(idesc.mnem, idesc.op_order_, current); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF0) == 0x80) { 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jcc: Conditional jump (branch). 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = data + JumpConditional(data); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 || 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block opcode == 0xB7 || opcode == 0xAF) { 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Size-extending moves, IMUL. 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF0) == 0x90) { 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SETcc: Set byte on condition. Needs pointer to beginning of instruction. 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = data + SetCC(data); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) { 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SHLD, SHRD (double-precision shift), BTS (bit set). 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnemonic); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintRightOperand(current); 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (opcode == 0xAB) { 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (group_1_prefix_ == 0xF2) { 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Beginning of instructions with prefix 0xF2. 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (opcode == 0x11 || opcode == 0x10) { 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // MOVSD: Move scalar double-precision fp to/from/between XMM registers. 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd "); 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (opcode == 0x11) { 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintRightOperand(current); 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s,", NameOfXMMRegister(regop)); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintRightOperand(current); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0x2A) { 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CVTSI2SD: integer to XMM double conversion. 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF8) == 0x58) { 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // XMM arithmetic. Mnemonic was retrieved at the start of this function. 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,%s", mnemonic, NameOfXMMRegister(regop), 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfXMMRegister(rm)); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) { 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction with prefix 0xF3. 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CVTTSS2SI: Convert scalar single-precision FP to dword integer. 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Assert that mod is not 3, so source is memory, not an XMM register. 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((*current & 0xC0) != 0xC0); 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current); 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return current - data; 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for two-byte opcode instructions starting with 0x0F. 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The argument is the second byte of the two-byte opcode. 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here. 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DisassemblerX64::TwoByteMnemonic(byte opcode) { 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (opcode) { 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x1F: 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "nop"; 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x2A: // F2 prefix. 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "cvtsi2sd"; 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x31: 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "rdtsc"; 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x58: // F2 prefix. 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "addsd"; 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x59: // F2 prefix. 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "mulsd"; 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5C: // F2 prefix. 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "subsd"; 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5E: // F2 prefix. 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "divsd"; 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA2: 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "cpuid"; 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA5: 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "shld"; 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAB: 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "bts"; 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAD: 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "shrd"; 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAF: 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "imul"; 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB6: 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movzxb"; 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB7: 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movzxw"; 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBE: 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movsxb"; 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBF: 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movsxw"; 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembles the instruction at instr, and writes it into out_buffer. 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer, 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instr) { 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ = 0; // starting to write as position 0 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data = instr; 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool processed = true; // Will be set to false if the current instruction 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is not in 'instructions' table. 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte current; 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scan for prefixes. 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = *data; 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current == 0x66) { // Group 3 prefix. 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_ = current; 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((current & 0xF0) == 0x40) { // REX prefix. 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block setRex(current); 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rex_w()) AppendToBuffer("REX.W "); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix. 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block group_1_prefix_ = current; 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Not a prefix - an opcode. 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& idesc = instruction_table.Get(current); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ = idesc.byte_size_operation; 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (idesc.type) { 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ZERO_OPERANDS_INSTR: 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(idesc.mnem); 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TWO_OPERANDS_INSTR: 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case JUMP_CONDITIONAL_SHORT_INSTR: 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditionalShort(data); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REGISTER_INSTR: 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s", 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idesc.mnem, 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(base_reg(current & 0x07))); 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case PUSHPOP_INSTR: 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idesc.mnem, 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(base_reg(current & 0x07))); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOVE_REG_INSTR: { 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = NULL; 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (operand_size()) { 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case WORD_SIZE: 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 9; 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov%c %s,%s", 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(base_reg(current & 0x07)), 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfAddress(addr)); 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CALL_JUMP_INSTR: { 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5; 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SHORT_IMMEDIATE_INSTR: { 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s rax, %s", idesc.mnem, NameOfAddress(addr)); 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NO_INSTR: 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block processed = false; 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // This type is not implemented. 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The first byte didn't match any of the simple opcodes, so we 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // need to do special processing on it. 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!processed) { 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (*data) { 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC2: 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1)); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x69: // fall through 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6B: { 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data + 1), &mod, ®op, &rm); 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data == 0x6B ? *(data + 2) 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : *reinterpret_cast<int32_t*>(data + 2); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop), 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm), imm); 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2 + (*data == 0x6B ? 1 : 4); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF6: { 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data + 1), &mod, ®op, &rm); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3 && regop == 0) { 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2)); 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x81: // fall through 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x83: // 0x81 with sign extension bit set 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintImmediateOp(data); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x0F: 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += TwoByteOpcodeInstruction(data); 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x8F: { 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == 0) { 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("pop "); 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFF: { 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "inc"; 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "dec"; 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "call"; 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "jmp"; 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "push"; 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "???"; 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "), 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code()); 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC7: // imm32, fall through 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC6: // imm8 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_byte = *data == 0xC6; 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov%c ", is_byte ? 'b' : operand_size_code()); 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = is_byte ? *data : *reinterpret_cast<int32_t*>(data); 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += is_byte ? 1 : 4; 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x80: { 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("cmpb "); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data; 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x88: // 8bit, fall through 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x89: // 32bit 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_byte = *data == 0x88; 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov%c ", is_byte ? 'b' : operand_size_code()); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x90: 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x91: 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x92: 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x93: 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x94: 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x95: 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x96: 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x97: { 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg = (current & 0x7) | (rex_b() ? 8 : 0); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (reg == 0) { 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("nop"); // Common name for xchg rax,rax. 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("xchg%c rax, %s", 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(reg)); 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFE: { 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3 && regop == 1) { 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("decb %s", NameOfCPURegister(rm)); 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x68: 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1)); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6A: 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA1: // Fall through. 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA3: 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (operand_size()) { 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: { 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* memory_location = NameOfAddress( 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>( 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(data + 1))); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0xA1) { // Opcode 0xA1 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movzxlq rax,(%s)", memory_location); 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Opcode 0xA3 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movzxlq (%s),rax", memory_location); 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: { 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // New x64 instruction mov rax,(imm_64). 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* memory_location = NameOfAddress( 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<byte**>(data + 1)); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0xA1) { // Opcode 0xA1 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movq rax,(%s)", memory_location); 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Opcode 0xA3 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movq (%s),rax", memory_location); 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 9; 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA8: 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1)); 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA9: { 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t value = 0; 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (operand_size()) { 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case WORD_SIZE: 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<uint16_t*>(data + 1); 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<uint32_t*>(data + 1); 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<int32_t*>(data + 1); 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x", 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value); 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD1: // fall through 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD3: // fall through 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC1: 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += ShiftInstruction(data); 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD0: // fall through 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD2: // fall through 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC0: 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ = true; 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += ShiftInstruction(data); 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD9: // fall through 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDA: // fall through 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDB: // fall through 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDC: // fall through 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDD: // fall through 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDE: // fall through 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDF: 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += FPUInstruction(data); 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEB: 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpShort(data); 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += F7Instruction(data); 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 1; 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } // !processed 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[tmp_buffer_pos_] = '\0'; 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instr_len = data - instr; 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(instr_len > 0); // Ensure progress. 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int outp = 0; 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bytes. 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = instr; bp < data; bp++) { 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, "%02x", *bp); 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - instr_len; i >= 0; i--) { 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, " "); 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, " %s", 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_.start()); 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr_len; 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[16] = { 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[16] = { 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l" 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[16] = { 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static v8::internal::EmbeddedVector<char, 32> tmp_buffer; 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr); 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return tmp_buffer.start(); 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 16) 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return cpu_regs[reg]; 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 16) 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return byte_cpu_regs[reg]; 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 16) 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return xmm_regs[reg]; 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // X64 does not embed debug strings at the moment. 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) { } 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() { } 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE); 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(buffer, instruction); 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The X64 assembler does not use constant pools. 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p", prev_pc); 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = prev_pc; bp < pc; bp++) { 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%02x", *bp); 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " %s\n", buffer.start()); 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1602