1e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Copyright 2011 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" 33f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 34f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 35f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h" 373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "lazy-instance.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandType { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNSET_OP_ORDER = 0, 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Operand size decides between 16, 32 and 64 bit operands. 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REG_OPER_OP_ORDER = 1, // Register destination, operand source. 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OPER_REG_OP_ORDER = 2, // Operand destination, register source. 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fixed 8-bit operands. 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_SIZE_OPERAND_FLAG = 4, 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG, 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic { 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int b; // -1 terminates, otherwise must be in range (0..255) 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order_; 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic two_operands_instr[] = { 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x00, BYTE_OPER_REG_OP_ORDER, "add" }, 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x01, OPER_REG_OP_ORDER, "add" }, 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x02, BYTE_REG_OPER_OP_ORDER, "add" }, 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x03, REG_OPER_OP_ORDER, "add" }, 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x08, BYTE_OPER_REG_OP_ORDER, "or" }, 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x09, OPER_REG_OP_ORDER, "or" }, 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" }, 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x0B, REG_OPER_OP_ORDER, "or" }, 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" }, 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x11, OPER_REG_OP_ORDER, "adc" }, 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" }, 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x13, REG_OPER_OP_ORDER, "adc" }, 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" }, 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x19, OPER_REG_OP_ORDER, "sbb" }, 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" }, 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x1B, REG_OPER_OP_ORDER, "sbb" }, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x20, BYTE_OPER_REG_OP_ORDER, "and" }, 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x21, OPER_REG_OP_ORDER, "and" }, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x22, BYTE_REG_OPER_OP_ORDER, "and" }, 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x23, REG_OPER_OP_ORDER, "and" }, 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" }, 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x29, OPER_REG_OP_ORDER, "sub" }, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" }, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x2B, REG_OPER_OP_ORDER, "sub" }, 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" }, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x31, OPER_REG_OP_ORDER, "xor" }, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" }, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x33, REG_OPER_OP_ORDER, "xor" }, 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" }, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x39, OPER_REG_OP_ORDER, "cmp" }, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" }, 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x3B, REG_OPER_OP_ORDER, "cmp" }, 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x63, REG_OPER_OP_ORDER, "movsxlq" }, 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x84, BYTE_REG_OPER_OP_ORDER, "test" }, 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x85, REG_OPER_OP_ORDER, "test" }, 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" }, 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x87, REG_OPER_OP_ORDER, "xchg" }, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" }, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x89, OPER_REG_OP_ORDER, "mov" }, 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" }, 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x8B, REG_OPER_OP_ORDER, "mov" }, 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x8D, REG_OPER_OP_ORDER, "lea" }, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = { 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xC3, UNSET_OP_ORDER, "ret" }, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xC9, UNSET_OP_ORDER, "leave" }, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xF4, UNSET_OP_ORDER, "hlt" }, 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 0xFC, UNSET_OP_ORDER, "cld" }, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xCC, UNSET_OP_ORDER, "int3" }, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x60, UNSET_OP_ORDER, "pushad" }, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x61, UNSET_OP_ORDER, "popad" }, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9C, UNSET_OP_ORDER, "pushfd" }, 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9D, UNSET_OP_ORDER, "popfd" }, 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9E, UNSET_OP_ORDER, "sahf" }, 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x99, UNSET_OP_ORDER, "cdq" }, 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x9B, UNSET_OP_ORDER, "fwait" }, 122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke { 0xA4, UNSET_OP_ORDER, "movs" }, 123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke { 0xA5, UNSET_OP_ORDER, "movs" }, 124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke { 0xA6, UNSET_OP_ORDER, "cmps" }, 125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke { 0xA7, UNSET_OP_ORDER, "cmps" }, 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xE8, UNSET_OP_ORDER, "call" }, 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0xE9, UNSET_OP_ORDER, "jmp" }, 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x05, UNSET_OP_ORDER, "add" }, 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x0D, UNSET_OP_ORDER, "or" }, 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x15, UNSET_OP_ORDER, "adc" }, 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x1D, UNSET_OP_ORDER, "sbb" }, 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x25, UNSET_OP_ORDER, "and" }, 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x2D, UNSET_OP_ORDER, "sub" }, 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x35, UNSET_OP_ORDER, "xor" }, 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 0x3D, UNSET_OP_ORDER, "cmp" }, 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { -1, UNSET_OP_ORDER, "" } 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_code_suffix[] = { 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "o", "no", "c", "nc", "z", "nz", "na", "a", 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "s", "ns", "pe", "po", "l", "ge", "le", "g" 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_INSTR, 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ZERO_OPERANDS_INSTR, 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TWO_OPERANDS_INSTR, 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JUMP_CONDITIONAL_SHORT_INSTR, 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REGISTER_INSTR, 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PUSHPOP_INSTR, // Has implicit 64-bit operand size. 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MOVE_REG_INSTR, 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_JUMP_INSTR, 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SHORT_IMMEDIATE_INSTR 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeenum Prefixes { 170d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ESCAPE_PREFIX = 0x0F, 171d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke OPERAND_SIZE_OVERRIDE_PREFIX = 0x66, 172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67, 173d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke REPNE_PREFIX = 0xF2, 174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke REP_PREFIX = 0xF3, 175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke REPEQ_PREFIX = REP_PREFIX 176d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc { 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionType type; 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order_; 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size_operation; // Fixed 8-bit operation. 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable { 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionTable(); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& Get(byte x) const { 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instructions_[x]; 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc instructions_[256]; 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Clear(); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Init(); 19869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void CopyTable(const ByteMnemonic bm[], InstructionType type); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetTableRange(InstructionType type, byte start, byte end, bool byte_size, 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AddJumpConditionalShort(); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() { 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Init(); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() { 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < 256; i++) { 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].mnem = "(bad)"; 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].type = NO_INSTR; 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].op_order_ = UNSET_OP_ORDER; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].byte_size_operation = false; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() { 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(call_jump_instr, CALL_JUMP_INSTR); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddJumpConditionalShort(); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push"); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop"); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov"); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[], 23469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch InstructionType type) { 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; bm[i].b >= 0; i++) { 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[bm[i].b]; 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = bm[i].mnem; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order = bm[i].op_order_; 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->op_order_ = 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG); 241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type, 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size, 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem) { 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = start; b <= end; b++) { 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = mnem; 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->byte_size_operation = byte_size; 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() { 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = 0x70; b <= 0x7F; b++) { 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = NULL; // Computed depending on condition code. 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = JUMP_CONDITIONAL_SHORT_INSTR; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic v8::internal::LazyInstance<InstructionTable>::type instruction_table = 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAZY_INSTANCE_INITIALIZER; 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionDesc cmov_instructions[16] = { 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false} 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DisassemblerX64 implementation. 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum UnimplementedOpcodeAction { 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CONTINUE_ON_UNIMPLEMENTED_OPCODE, 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ABORT_ON_UNIMPLEMENTED_OPCODE 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A new DisassemblerX64 object is created to disassemble each instruction. 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The object can only disassemble a single instruction. 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerX64 { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerX64(const NameConverter& converter, 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedOpcodeAction unimplemented_action = 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ABORT_ON_UNIMPLEMENTED_OPCODE) 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_(0), 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort_on_unimplemented_( 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE), 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rex_(0), 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_(0), 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block group_1_prefix_(0), 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_(false) { 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[0] = '\0'; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~DisassemblerX64() { 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum OperandSize { 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BYTE_SIZE = 0, 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WORD_SIZE = 1, 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DOUBLEWORD_SIZE = 2, 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block QUADWORD_SIZE = 3 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const NameConverter& converter_; 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int tmp_buffer_pos_; 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented_; 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prefixes parsed 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte rex_; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Byte size operand override. 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size_operand_; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void setRex(byte rex) { 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0x40, rex & 0xF0); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rex_ = rex; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex() { return rex_ != 0; } 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_b() { return (rex_ & 0x01) != 0; } 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Actual number of base register given the low bits and the rex.b state. 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_x() { return (rex_ & 0x02) != 0; } 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_r() { return (rex_ & 0x04) != 0; } 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool rex_w() { return (rex_ & 0x08) != 0; } 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandSize operand_size() { 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (byte_size_operand_) return BYTE_SIZE; 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rex_w()) return QUADWORD_SIZE; 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (operand_size_ != 0) return WORD_SIZE; 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return DOUBLEWORD_SIZE; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char operand_size_code() { 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "bwlq"[operand_size()]; 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfCPURegister(int reg) const { 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfCPURegister(reg); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfByteCPURegister(int reg) const { 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfByteCPURegister(reg); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfXMMRegister(int reg) const { 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfXMMRegister(reg); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(byte* addr) const { 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfAddress(addr); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Disassembler helper functions. 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void get_modrm(byte data, 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* mod, 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* regop, 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* rm) { 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *mod = (data >> 6) & 3; 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rm = (data & 7) | (rex_b() ? 8 : 0); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void get_sib(byte data, 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* scale, 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* index, 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int* base) { 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *scale = (data >> 6) & 3; 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *base = (data & 7) | (rex_b() ? 8 : 0); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperandHelper(byte* modrmp, 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegisterNameMapping register_name); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperand(byte* modrmp); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightByteOperand(byte* modrmp); 418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int PrintRightXMMOperand(byte* modrmp); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintOperands(const char* mnem, 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order, 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediate(byte* data, OperandSize size); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediateOp(byte* data); 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* TwoByteMnemonic(byte opcode); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int TwoByteOpcodeInstruction(byte* data); 426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int F6F7Instruction(byte* data); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int ShiftInstruction(byte* data); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpShort(byte* data); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditional(byte* data); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditionalShort(byte* data); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SetCC(byte* data); 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int FPUInstruction(byte* data); 433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AppendToBuffer(const char* format, ...); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UnimplementedInstruction() { 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (abort_on_unimplemented_) { 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(false); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("'Unimplemented Instruction'"); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerX64::AppendToBuffer(const char* format, ...) { 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = v8::internal::OS::VSNPrintF(buf, format, args); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ += result; 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperandHelper( 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* modrmp, 45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping direct_register_name) { 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*modrmp, &mod, ®op, &rm); 46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerX64::NameOfCPURegister; 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (mod) { 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rm & 7) == 5) { 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[0x%x]", disp); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((rm & 7) == 4) { 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Codes for SIB byte. 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // index == rsp means no index. Only use sib byte with no index for 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rsp and r12 base. 4788defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("[%s]", NameOfCPURegister(base)); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (base == 5) { 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // base == rbp means no base register (when mod == 0). 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s*%d+0x%x]", 4848defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(index), 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, disp); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (index != 4 && base != 5) { 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base+index*scale] 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d]", 4908defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(base), 4918defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(index), 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 4998defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("[%s]", NameOfCPURegister(rm)); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: // fall through 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if ((rm & 7) == 4) { 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : *reinterpret_cast<char*>(modrmp + 2); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-disp > 0) { 5138defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("[%s-0x%x]", NameOfCPURegister(base), -disp); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 5158defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("[%s+0x%x]", NameOfCPURegister(base), disp); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-disp > 0) { 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d-0x%x]", 5208defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(base), 5218defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(index), 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block -disp); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d+0x%x]", 5268defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(base), 5278defd9ff6930b4e24729971a61cf7469daf119beSteve Block NameOfCPURegister(index), 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disp); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 6 : 3; 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No sib. 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : *reinterpret_cast<char*>(modrmp + 1); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-disp > 0) { 5388defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("[%s-0x%x]", NameOfCPURegister(rm), -disp); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 5408defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (mod == 2) ? 5 : 2; 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", (this->*register_name)(rm)); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediate(byte* data, OperandSize size) { 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t value; 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count; 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (size) { 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case BYTE_SIZE: 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *data; 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 1; 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case WORD_SIZE: 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<int16_t*>(data); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 2; 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<uint32_t*>(data); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 4; 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<int32_t*>(data); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 4; 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = 0; // Initialize variables on all paths to satisfy the compiler. 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count = 0; 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%" V8_PTR_PREFIX "x", value); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return count; 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperand(byte* modrmp) { 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerX64::NameOfCPURegister); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightByteOperand(byte* modrmp) { 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerX64::NameOfByteCPURegister); 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::PrintRightXMMOperand(byte* modrmp) { 599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return PrintRightOperandHelper(modrmp, 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block &DisassemblerX64::NameOfXMMRegister); 601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data. 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintOperands(const char* mnem, 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandType op_order, 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data) { 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *data; 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int advance = 0; 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* register_name = 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ ? NameOfByteCPURegister(regop) 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : NameOfCPURegister(regop); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (op_order) { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REG_OPER_OP_ORDER: { 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s,", 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block register_name); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = byte_size_operand_ ? PrintRightByteOperand(data) 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : PrintRightOperand(data); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case OPER_REG_OP_ORDER: { 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c ", mnem, operand_size_code()); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = byte_size_operand_ ? PrintRightByteOperand(data) 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : PrintRightOperand(data); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", register_name); 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return advance; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte. 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'. 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediateOp(byte* data) { 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool byte_size_immediate = (*data & 0x02) != 0; 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data + 1); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "Imm???"; 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "add"; 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "or"; 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "adc"; 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 6598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 3: 6608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch mnem = "sbb"; 6618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "and"; 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "sub"; 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "xor"; 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "cmp"; 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c ", mnem, operand_size_code()); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data + 1); 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x"); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size(); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block count += PrintImmediate(data + 1 + count, immediate_size); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count; 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::F6F7Instruction(byte* data) { 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(*data == 0xF7 || *data == 0xF6); 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data + 1); 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3 && regop != 0) { 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "not"; 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "neg"; 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "mul"; 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "idiv"; 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s", 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm)); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (regop == 0) { 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test%c ", operand_size_code()); 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int count = PrintRightOperand(data + 1); // Use name of 64-bit register. 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer(",0x"); 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block count += PrintImmediate(data + 1 + count, operand_size()); 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 1 + count; 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::ShiftInstruction(byte* data) { 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte op = *data & (~1); 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op != 0xD0 && op != 0xD2 && op != 0xC0) { 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data + 1); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block regop &= 0x7; // The REX.R bit does not affect the operation. 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm8 = -1; 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_bytes = 2; 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod != 3) { 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "rol"; 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "ror"; 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "rcl"; 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "rcr"; 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "shl"; 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "shr"; 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "sar"; 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NE(NULL, mnem); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op == 0xD0) { 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = 1; 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (op == 0xC0) { 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = *(data + 2); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_bytes = 3; 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s,", 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ ? NameOfByteCPURegister(rm) 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : NameOfCPURegister(rm)); 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op == 0xD2) { 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("cl"); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%d", imm8); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpShort(byte* data) { 794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xEB, *data); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data + 1); 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("jmp %s", NameOfAddress(dest)); 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditional(byte* data) { 804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data + 1) & 0x0F; 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6; 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = conditional_code_suffix[cond]; 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; // includes 0x0F 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditionalShort(byte* data) { 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *data & 0x0F; 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data + 1); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = conditional_code_suffix[cond]; 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("j%s %s", mnem, NameOfAddress(dest)); 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::SetCC(byte* data) { 826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data + 1) & 0x0F; 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = conditional_code_suffix[cond]; 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("set%s%c ", mnem, operand_size_code()); 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRightByteOperand(data + 2); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 3; // includes 0x0F 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::FPUInstruction(byte* data) { 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte escape_opcode = *data; 838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xD8, escape_opcode & 0xF8); 839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte = *(data+1); 840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte >= 0xC0) { 842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return RegisterFPUInstruction(escape_opcode, modrm_byte); 843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::MemoryFPUInstruction(int escape_opcode, 849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int modrm_byte, 850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte* modrm_start) { 851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: switch (regop) { 855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_s"; break; 856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_s"; break; 857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fstcw"; break; 858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: switch (regop) { 863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fild_s"; break; 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 1: mnem = "fisttp_s"; break; 865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 2: mnem = "fist_s"; break; 866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fistp_s"; break; 867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: switch (regop) { 872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_d"; break; 873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_d"; break; 874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: switch (regop) { 879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 5: mnem = "fild_d"; break; 880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fistp_d"; break; 881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s ", mnem); 888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int count = PrintRightOperand(modrm_start); 889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return count + 1; 890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::RegisterFPUInstruction(int escape_opcode, 893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte) { 894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool has_register = false; // Is the FPU register encoded in modrm_byte? 895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: 899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: 903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 9040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 0xC0: 9050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mnem = "fld"; 9060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen has_register = true; 9070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: 909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fxch"; 910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte) { 914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE0: mnem = "fchs"; break; 915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE1: mnem = "fabs"; break; 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xE3: mnem = "fninit"; break; 917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE4: mnem = "ftst"; break; 918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fld1"; break; 9190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 0xEB: mnem = "fldpi"; break; 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xED: mnem = "fldln2"; break; 921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xEE: mnem = "fldz"; break; 9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xF0: mnem = "f2xm1"; break; 923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xF1: mnem = "fyl2x"; break; 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xF2: mnem = "fptan"; break; 925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF5: mnem = "fprem1"; break; 926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF7: mnem = "fincstp"; break; 927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fprem"; break; 9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFD: mnem = "fscale"; break; 929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFE: mnem = "fsin"; break; 930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFF: mnem = "fcos"; break; 931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDA: 937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE9) { 938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucompp"; 939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: 945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if ((modrm_byte & 0xF8) == 0xE8) { 946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomi"; 947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (modrm_byte == 0xE2) { 949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fclex"; 950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDC: 956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "fadd"; break; 959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsub"; break; 960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmul"; break; 961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdiv"; break; 962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: 967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "ffree"; break; 970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: mnem = "fstp"; break; 971d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDE: 976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xD9) { 977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fcompp"; 978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 979d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "faddp"; break; 982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsubp"; break; 983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmulp"; break; 984d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdivp"; break; 985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: 991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE0) { 992d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fnstsw_ax"; 993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if ((modrm_byte & 0xF8) == 0xE8) { 994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomip"; 995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 998d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 999d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 1000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (has_register) { 1003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 1004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all two-byte opcodes, which start with 0x0F. 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix. 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A. 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte opcode = *(data + 1); 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* current = data + 2; 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // At return, "current" points to the start of the next instruction. 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnemonic = TwoByteMnemonic(opcode); 1020402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (operand_size_ == 0x66) { 1021402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // 0x66 0x0F prefix. 1022402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int mod, regop, rm; 10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (opcode == 0x3A) { 10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block byte third_byte = *current; 10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current = data + 3; 10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (third_byte == 0x17) { 10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*current, &mod, ®op, &rm); 10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("extractps "); // reg/m32, xmm, imm8 10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current += PrintRightOperand(current); 10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer(", %s, %d", NameOfCPURegister(regop), (*current) & 3); 10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current += 1; 1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (third_byte == 0x0b) { 1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*current, &mod, ®op, &rm); 1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // roundsd xmm, xmm/m64, imm8 1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("roundsd %s, ", NameOfCPURegister(regop)); 1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightOperand(current); 1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer(", %d", (*current) & 3); 1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += 1; 10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1042402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*current, &mod, ®op, &rm); 10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (opcode == 0x1f) { 10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current++; 10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (rm == 4) { // SIB byte present. 10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current++; 10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (mod == 1) { // Byte displacement. 10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current += 1; 10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (mod == 2) { // 32-bit displacement. 10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current += 4; 10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } // else no immediate displacement. 10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); 10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (opcode == 0x28) { 1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop)); 1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0x29) { 1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("movapd "); 1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0x6E) { 10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("mov%c %s,", 10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block rex_w() ? 'q' : 'd', 10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop)); 10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current += PrintRightOperand(current); 10671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (opcode == 0x6F) { 10681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("movdqa %s,", 10691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfXMMRegister(regop)); 107044f0eee88ff00398ff7f715fab053374d808c90dSteve Block current += PrintRightXMMOperand(current); 10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (opcode == 0x7E) { 1072bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch AppendToBuffer("mov%c ", 1073bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch rex_w() ? 'q' : 'd'); 1074bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch current += PrintRightOperand(current); 1075bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch AppendToBuffer(", %s", NameOfXMMRegister(regop)); 10761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (opcode == 0x7F) { 10771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("movdqa "); 107844f0eee88ff00398ff7f715fab053374d808c90dSteve Block current += PrintRightXMMOperand(current); 10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0xD6) { 1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("movq "); 1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer(", %s", NameOfXMMRegister(regop)); 10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (opcode == 0x50) { 10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop)); 10863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current += PrintRightXMMOperand(current); 10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* mnemonic = "?"; 10893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (opcode == 0x54) { 1090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mnemonic = "andpd"; 1091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (opcode == 0x56) { 1092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mnemonic = "orpd"; 1093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (opcode == 0x57) { 10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mnemonic = "xorpd"; 10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (opcode == 0x2E) { 10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block mnemonic = "ucomisd"; 10978defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else if (opcode == 0x2F) { 10988defd9ff6930b4e24729971a61cf7469daf119beSteve Block mnemonic = "comisd"; 10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); 11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current += PrintRightXMMOperand(current); 11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1106402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else if (group_1_prefix_ == 0xF2) { 1107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Beginning of instructions with prefix 0xF2. 1108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (opcode == 0x11 || opcode == 0x10) { 1110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // MOVSD: Move scalar double-precision fp to/from/between XMM registers. 1111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AppendToBuffer("movsd "); 1112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int mod, regop, rm; 1113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu get_modrm(*current, &mod, ®op, &rm); 1114402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (opcode == 0x11) { 111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block current += PrintRightXMMOperand(current); 1116402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1118402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AppendToBuffer("%s,", NameOfXMMRegister(regop)); 111944f0eee88ff00398ff7f715fab053374d808c90dSteve Block current += PrintRightXMMOperand(current); 1120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1121402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else if (opcode == 0x2A) { 1122402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // CVTSI2SD: integer to XMM double conversion. 1123402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int mod, regop, rm; 1124402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu get_modrm(*current, &mod, ®op, &rm); 11258defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop)); 1126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu current += PrintRightOperand(current); 11270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (opcode == 0x2C) { 11280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // CVTTSD2SI: 11290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Convert with truncation scalar double-precision FP to integer. 11300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int mod, regop, rm; 11310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen get_modrm(*current, &mod, ®op, &rm); 11320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("cvttsd2si%c %s,", 11330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen operand_size_code(), NameOfCPURegister(regop)); 11340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen current += PrintRightXMMOperand(current); 11350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (opcode == 0x2D) { 11360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // CVTSD2SI: Convert scalar double-precision FP to integer. 11370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int mod, regop, rm; 11380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen get_modrm(*current, &mod, ®op, &rm); 11390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("cvtsd2si%c %s,", 11400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen operand_size_code(), NameOfCPURegister(regop)); 11410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen current += PrintRightXMMOperand(current); 11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { 1143402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // XMM arithmetic. Mnemonic was retrieved at the start of this function. 1144402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int mod, regop, rm; 1145402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu get_modrm(*current, &mod, ®op, &rm); 1146402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); 1147402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu current += PrintRightXMMOperand(current); 1148402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1149402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu UnimplementedInstruction(); 1150402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (group_1_prefix_ == 0xF3) { 11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Instructions with prefix 0xF3. 11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (opcode == 0x11 || opcode == 0x10) { 11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block // MOVSS: Move scalar double-precision fp to/from/between XMM registers. 11558defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("movss "); 11568defd9ff6930b4e24729971a61cf7469daf119beSteve Block int mod, regop, rm; 11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block get_modrm(*current, &mod, ®op, &rm); 11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block if (opcode == 0x11) { 11598defd9ff6930b4e24729971a61cf7469daf119beSteve Block current += PrintRightOperand(current); 11608defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 11618defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else { 11628defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("%s,", NameOfXMMRegister(regop)); 11638defd9ff6930b4e24729971a61cf7469daf119beSteve Block current += PrintRightOperand(current); 11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 11658defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else if (opcode == 0x2A) { 11668defd9ff6930b4e24729971a61cf7469daf119beSteve Block // CVTSI2SS: integer to XMM single conversion. 11678defd9ff6930b4e24729971a61cf7469daf119beSteve Block int mod, regop, rm; 11688defd9ff6930b4e24729971a61cf7469daf119beSteve Block get_modrm(*current, &mod, ®op, &rm); 11698defd9ff6930b4e24729971a61cf7469daf119beSteve Block AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop)); 11708defd9ff6930b4e24729971a61cf7469daf119beSteve Block current += PrintRightOperand(current); 11718defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else if (opcode == 0x2C) { 11720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // CVTTSS2SI: 11730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Convert with truncation scalar single-precision FP to dword integer. 11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int mod, regop, rm; 11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block get_modrm(*current, &mod, ®op, &rm); 11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("cvttss2si%c %s,", 11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block operand_size_code(), NameOfCPURegister(regop)); 11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current += PrintRightXMMOperand(current); 11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (opcode == 0x5A) { 11800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // CVTSS2SD: 11810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Convert scalar single-precision FP to scalar double-precision FP. 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*current, &mod, ®op, &rm); 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current += PrintRightXMMOperand(current); 1186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0x7E) { 1187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*current, &mod, ®op, &rm); 1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("movq %s, ", NameOfXMMRegister(regop)); 1190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else if (opcode == 0x1F) { 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOP 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current++; 11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (rm == 4) { // SIB byte present. 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current++; 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 1) { // Byte displacement. 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += 1; 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (mod == 2) { // 32-bit displacement. 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += 4; 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } // else no immediate displacement. 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("nop"); 1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0x28) { 1210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // movaps xmm, xmm/m128 1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*current, &mod, ®op, &rm); 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("movaps %s, ", NameOfXMMRegister(regop)); 1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0x29) { 1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // movaps xmm/m128, xmm 1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*current, &mod, ®op, &rm); 1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("movaps "); 1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer(", %s", NameOfXMMRegister(regop)); 1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1224402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else if (opcode == 0xA2 || opcode == 0x31) { 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RDTSC or CPUID 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnemonic); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF0) == 0x40) { 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // CMOVcc: conditional move. 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int condition = opcode & 0x0F; 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& idesc = cmov_instructions[condition]; 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ = idesc.byte_size_operation; 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintOperands(idesc.mnem, idesc.op_order_, current); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (opcode == 0x57) { 1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // xorps xmm, xmm/m128 1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*current, &mod, ®op, &rm); 1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("xorps %s, ", NameOfXMMRegister(regop)); 1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current += PrintRightXMMOperand(current); 1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF0) == 0x80) { 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jcc: Conditional jump (branch). 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = data + JumpConditional(data); 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 || 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block opcode == 0xB7 || opcode == 0xAF) { 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Size-extending moves, IMUL. 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current); 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((opcode & 0xF0) == 0x90) { 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SETcc: Set byte on condition. Needs pointer to beginning of instruction. 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = data + SetCC(data); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) { 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SHLD, SHRD (double-precision shift), BTS (bit set). 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnemonic); 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*current, &mod, ®op, &rm); 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current += PrintRightOperand(current); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (opcode == 0xAB) { 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<int>(current - data); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for two-byte opcode instructions starting with 0x0F. 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The argument is the second byte of the two-byte opcode. 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here. 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DisassemblerX64::TwoByteMnemonic(byte opcode) { 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (opcode) { 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x1F: 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "nop"; 12808defd9ff6930b4e24729971a61cf7469daf119beSteve Block case 0x2A: // F2/F3 prefix. 12818defd9ff6930b4e24729971a61cf7469daf119beSteve Block return "cvtsi2s"; 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x31: 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "rdtsc"; 12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x51: // F2 prefix. 12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return "sqrtsd"; 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x58: // F2 prefix. 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "addsd"; 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x59: // F2 prefix. 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "mulsd"; 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5C: // F2 prefix. 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "subsd"; 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5E: // F2 prefix. 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "divsd"; 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA2: 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "cpuid"; 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA5: 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "shld"; 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAB: 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "bts"; 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAD: 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "shrd"; 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAF: 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "imul"; 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB6: 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movzxb"; 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB7: 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movzxw"; 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBE: 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movsxb"; 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBF: 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "movsxw"; 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembles the instruction at instr, and writes it into out_buffer. 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer, 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instr) { 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ = 0; // starting to write as position 0 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data = instr; 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool processed = true; // Will be set to false if the current instruction 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is not in 'instructions' table. 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte current; 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Scan for prefixes. 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current = *data; 1330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix. 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_ = current; 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((current & 0xF0) == 0x40) { // REX prefix. 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block setRex(current); 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rex_w()) AppendToBuffer("REX.W "); 1335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block group_1_prefix_ = current; 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Not a prefix - an opcode. 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const InstructionDesc& idesc = instruction_table.Get().Get(current); 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ = idesc.byte_size_operation; 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (idesc.type) { 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ZERO_OPERANDS_INSTR: 1347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (current >= 0xA4 && current <= 0xA7) { 1348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // String move or compare operations. 1349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (group_1_prefix_ == REP_PREFIX) { 1350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // REP. 1351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke AppendToBuffer("rep "); 1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (rex_w()) AppendToBuffer("REX.W "); 1354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke AppendToBuffer("%s%c", idesc.mnem, operand_size_code()); 1355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } else { 1356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke AppendToBuffer("%s", idesc.mnem, operand_size_code()); 1357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TWO_OPERANDS_INSTR: 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case JUMP_CONDITIONAL_SHORT_INSTR: 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditionalShort(data); 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REGISTER_INSTR: 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s%c %s", 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idesc.mnem, 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(base_reg(current & 0x07))); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case PUSHPOP_INSTR: 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block idesc.mnem, 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(base_reg(current & 0x07))); 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOVE_REG_INSTR: { 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = NULL; 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (operand_size()) { 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case WORD_SIZE: 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 9; 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov%c %s,%s", 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(base_reg(current & 0x07)), 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfAddress(addr)); 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CALL_JUMP_INSTR: { 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5; 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SHORT_IMMEDIATE_INSTR: { 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s rax, %s", idesc.mnem, NameOfAddress(addr)); 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NO_INSTR: 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block processed = false; 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // This type is not implemented. 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The first byte didn't match any of the simple opcodes, so we 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // need to do special processing on it. 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!processed) { 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (*data) { 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC2: 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1)); 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x69: // fall through 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6B: { 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data + 1), &mod, ®op, &rm); 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data == 0x6B ? *(data + 2) 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : *reinterpret_cast<int32_t*>(data + 2); 14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("imul%c %s,%s,0x%x", 14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block operand_size_code(), 14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfCPURegister(regop), 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm), imm); 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2 + (*data == 0x6B ? 1 : 4); 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x81: // fall through 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x83: // 0x81 with sign extension bit set 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintImmediateOp(data); 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x0F: 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += TwoByteOpcodeInstruction(data); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x8F: { 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == 0) { 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("pop "); 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFF: { 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "inc"; 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "dec"; 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "call"; 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "jmp"; 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "push"; 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem = "???"; 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "), 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mnem, 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code()); 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC7: // imm32, fall through 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC6: // imm8 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_byte = *data == 0xC6; 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 151044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 151144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movb "); 151244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 151344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *data; 151444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 151544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data++; 151644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("mov%c ", operand_size_code()); 151844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 151944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data); 152044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 152144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 4; 152244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x80: { 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("cmpb "); 152944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data; 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x88: // 8bit, fall through 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x89: // 32bit 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_byte = *data == 0x88; 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 154344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 154444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movb "); 154544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 154644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 154844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("mov%c ", operand_size_code()); 154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 155044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 155144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x90: 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x91: 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x92: 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x93: 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x94: 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x95: 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x96: 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x97: { 1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int reg = (*data & 0x7) | (rex_b() ? 8 : 0); 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (reg == 0) { 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("nop"); // Common name for xchg rax,rax. 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("xchg%c rax, %s", 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(reg)); 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block data++; 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 15748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB0: 15758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB1: 15768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB2: 15778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB3: 15788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB4: 15798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB5: 15808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB6: 15818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB7: 15828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB8: 15838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xB9: 15848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xBA: 15858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xBB: 15868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xBC: 15878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xBD: 15888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xBE: 15898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case 0xBF: { 15908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // mov reg8,imm8 or mov reg32,imm32 15918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch byte opcode = *data; 15928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch data++; 15938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool is_32bit = (opcode >= 0xB8); 15948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int reg = (opcode & 0x7) | (rex_b() ? 8 : 0); 15958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (is_32bit) { 15968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AppendToBuffer("mov%c %s, ", 15978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch operand_size_code(), 15988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch NameOfCPURegister(reg)); 15998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch data += PrintImmediate(data, DOUBLEWORD_SIZE); 16008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 16018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AppendToBuffer("movb %s, ", 16028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch NameOfByteCPURegister(reg)); 16038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch data += PrintImmediate(data, BYTE_SIZE); 16048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 16058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 16068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFE: { 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 16110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (regop == 1) { 16120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("decb "); 161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 16188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x68: 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1)); 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6A: 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA1: // Fall through. 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA3: 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (operand_size()) { 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: { 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* memory_location = NameOfAddress( 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<byte*>( 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<int32_t*>(data + 1))); 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0xA1) { // Opcode 0xA1 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movzxlq rax,(%s)", memory_location); 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Opcode 0xA3 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movzxlq (%s),rax", memory_location); 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: { 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // New x64 instruction mov rax,(imm_64). 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* memory_location = NameOfAddress( 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *reinterpret_cast<byte**>(data + 1)); 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0xA1) { // Opcode 0xA1 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movq rax,(%s)", memory_location); 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { // Opcode 0xA3 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movq (%s),rax", memory_location); 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 9; 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA8: 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1)); 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA9: { 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t value = 0; 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (operand_size()) { 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case WORD_SIZE: 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<uint16_t*>(data + 1); 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case DOUBLEWORD_SIZE: 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<uint32_t*>(data + 1); 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case QUADWORD_SIZE: 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = *reinterpret_cast<int32_t*>(data + 1); 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x", 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block operand_size_code(), 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value); 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD1: // fall through 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD3: // fall through 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC1: 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += ShiftInstruction(data); 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD0: // fall through 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD2: // fall through 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC0: 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte_size_operand_ = true; 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += ShiftInstruction(data); 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD9: // fall through 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDA: // fall through 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDB: // fall through 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDC: // fall through 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDD: // fall through 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDE: // fall through 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDF: 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += FPUInstruction(data); 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEB: 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpShort(data); 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF6: 1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte_size_operand_ = true; // fall through 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block data += F6F7Instruction(data); 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 1; 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } // !processed 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[tmp_buffer_pos_] = '\0'; 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int instr_len = static_cast<int>(data - instr); 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(instr_len > 0); // Ensure progress. 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int outp = 0; 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bytes. 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = instr; bp < data; bp++) { 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, "%02x", *bp); 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - instr_len; i >= 0; i--) { 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, " "); 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, " %s", 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_.start()); 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr_len; 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[16] = { 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[16] = { 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l" 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[16] = { 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); 177244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 16) 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return cpu_regs[reg]; 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 16) 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return byte_cpu_regs[reg]; 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 16) 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return xmm_regs[reg]; 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // X64 does not embed debug strings at the moment. 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) { } 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() { } 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE); 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(buffer, instruction); 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The X64 assembler does not use constant pools. 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p", prev_pc); 1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = prev_pc; bp < pc; bp++) { 1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%02x", *bp); 1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " %s\n", buffer.start()); 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 1853