disasm-ia32.cc revision 69a99ed0b2b2ef69d393c371b03db3a98aaf880e
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben 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_IA32) 35f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandOrder { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNSET_OP_ORDER = 0, 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REG_OPER_OP_ORDER, 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OPER_REG_OP_ORDER 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic { 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int b; // -1 terminates, otherwise must be in range (0..255) 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order_; 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic two_operands_instr[] = { 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x03, "add", REG_OPER_OP_ORDER}, 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x09, "or", OPER_REG_OP_ORDER}, 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x0B, "or", REG_OPER_OP_ORDER}, 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x1B, "sbb", REG_OPER_OP_ORDER}, 62d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x21, "and", OPER_REG_OP_ORDER}, 63d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x23, "and", REG_OPER_OP_ORDER}, 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x29, "sub", OPER_REG_OP_ORDER}, 65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke {0x2A, "subb", REG_OPER_OP_ORDER}, 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x2B, "sub", REG_OPER_OP_ORDER}, 67eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke {0x31, "xor", OPER_REG_OP_ORDER}, 68eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke {0x33, "xor", REG_OPER_OP_ORDER}, 69d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x38, "cmpb", OPER_REG_OP_ORDER}, 70d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x3A, "cmpb", REG_OPER_OP_ORDER}, 71d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x3B, "cmp", REG_OPER_OP_ORDER}, 72d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x84, "test_b", REG_OPER_OP_ORDER}, 73d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x85, "test", REG_OPER_OP_ORDER}, 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x87, "xchg", REG_OPER_OP_ORDER}, 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x8A, "mov_b", REG_OPER_OP_ORDER}, 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x8B, "mov", REG_OPER_OP_ORDER}, 77d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x8D, "lea", REG_OPER_OP_ORDER}, 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = { 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xC3, "ret", UNSET_OP_ORDER}, 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xC9, "leave", UNSET_OP_ORDER}, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x90, "nop", UNSET_OP_ORDER}, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xF4, "hlt", UNSET_OP_ORDER}, 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xCC, "int3", UNSET_OP_ORDER}, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x60, "pushad", UNSET_OP_ORDER}, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x61, "popad", UNSET_OP_ORDER}, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9C, "pushfd", UNSET_OP_ORDER}, 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9D, "popfd", UNSET_OP_ORDER}, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9E, "sahf", UNSET_OP_ORDER}, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x99, "cdq", UNSET_OP_ORDER}, 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9B, "fwait", UNSET_OP_ORDER}, 956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block {0xFC, "cld", UNSET_OP_ORDER}, 96f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke {0xAB, "stos", UNSET_OP_ORDER}, 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = { 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xE8, "call", UNSET_OP_ORDER}, 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xE9, "jmp", UNSET_OP_ORDER}, 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = { 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x05, "add", UNSET_OP_ORDER}, 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x0D, "or", UNSET_OP_ORDER}, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x15, "adc", UNSET_OP_ORDER}, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x25, "and", UNSET_OP_ORDER}, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x2D, "sub", UNSET_OP_ORDER}, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x35, "xor", UNSET_OP_ORDER}, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x3D, "cmp", UNSET_OP_ORDER}, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const jump_conditional_mnem[] = { 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*0*/ "jo", "jno", "jc", "jnc", 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*4*/ "jz", "jnz", "jna", "ja", 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*8*/ "js", "jns", "jpe", "jpo", 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*12*/ "jl", "jnl", "jng", "jg" 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const set_conditional_mnem[] = { 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*0*/ "seto", "setno", "setc", "setnc", 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*4*/ "setz", "setnz", "setna", "seta", 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*8*/ "sets", "setns", "setpe", "setpo", 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*12*/ "setl", "setnl", "setng", "setg" 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_move_mnem[] = { 1373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", 1383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", 1393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", 1403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" 1413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}; 1423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType { 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_INSTR, 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ZERO_OPERANDS_INSTR, 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TWO_OPERANDS_INSTR, 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JUMP_CONDITIONAL_SHORT_INSTR, 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REGISTER_INSTR, 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MOVE_REG_INSTR, 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_JUMP_INSTR, 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SHORT_IMMEDIATE_INSTR 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionType type; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order_; 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable { 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionTable(); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& Get(byte x) const { return instructions_[x]; } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc instructions_[256]; 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Clear(); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Init(); 17269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void CopyTable(const ByteMnemonic bm[], InstructionType type); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetTableRange(InstructionType type, 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AddJumpConditionalShort(); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() { 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Init(); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() { 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < 256; i++) { 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].mnem = ""; 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].type = NO_INSTR; 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].op_order_ = UNSET_OP_ORDER; 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() { 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(call_jump_instr, CALL_JUMP_INSTR); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddJumpConditionalShort(); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[], 21269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch InstructionType type) { 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; bm[i].b >= 0; i++) { 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[bm[i].b]; 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = bm[i].mnem; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->op_order_ = bm[i].op_order_; 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type, 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem) { 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = start; b <= end; b++) { 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = mnem; 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() { 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = 0x70; b <= 0x7F; b++) { 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = jump_conditional_mnem[b & 0x0F]; 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = JUMP_CONDITIONAL_SHORT_INSTR; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionTable instruction_table; 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA32 disassembler implementation. 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerIA32 { 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32(const NameConverter& converter, 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented = true) 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_(0), 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort_on_unimplemented_(abort_on_unimplemented) { 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[0] = '\0'; 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~DisassemblerIA32() {} 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const NameConverter& converter_; 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int tmp_buffer_pos_; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented_; 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum { 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block eax = 0, 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ecx = 1, 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx = 2, 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebx = 3, 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esp = 4, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebp = 5, 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esi = 6, 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edi = 7 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block enum ShiftOpcodeExtension { 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROL = 0, 287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROR = 1, 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCL = 2, 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCR = 3, 290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSHL = 4, 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block KSHR = 5, 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSAR = 7 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfCPURegister(int reg) const { 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfCPURegister(reg); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfByteCPURegister(int reg) const { 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfByteCPURegister(reg); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfXMMRegister(int reg) const { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfXMMRegister(reg); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(byte* addr) const { 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfAddress(addr); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Disassembler helper functions. 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_modrm(byte data, int* mod, int* regop, int* rm) { 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *mod = (data >> 6) & 3; 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *regop = (data & 0x38) >> 3; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rm = data & 7; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_sib(byte data, int* scale, int* index, int* base) { 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *scale = (data >> 6) & 3; 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *index = (data >> 3) & 7; 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *base = data & 7; 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const; 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperand(byte* modrmp); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightByteOperand(byte* modrmp); 33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int PrintRightXMMOperand(byte* modrmp); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediateOp(byte* data); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int F7Instruction(byte* data); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int D1D3C1Instruction(byte* data); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpShort(byte* data); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditional(byte* data, const char* comment); 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditionalShort(byte* data, const char* comment); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SetCC(byte* data); 3443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int CMov(byte* data); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int FPUInstruction(byte* data); 346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AppendToBuffer(const char* format, ...); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UnimplementedInstruction() { 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (abort_on_unimplemented_) { 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("'Unimplemented Instruction'"); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) { 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = v8::internal::OS::VSNPrintF(buf, format, args); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ += result; 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper( 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* modrmp, 37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping direct_register_name) { 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*modrmp, &mod, ®op, &rm); 37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 37644f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfCPURegister; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (mod) { 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == ebp) { 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[0x%x]", disp); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rm == esp) { 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == esp && base == esp && scale == 0 /*times_1*/) { 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (base == ebp) { 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s*%d+0x%x]", 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disp); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (index != esp && base != ebp) { 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base+index*scale] 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d]", 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: // fall through 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == esp) { 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) : *(modrmp + 2); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d+0x%x]", 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disp); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 6 : 3; 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No sib. 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) : *(modrmp + 1); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 5 : 2; 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", (this->*register_name)(rm)); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) { 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) { 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerIA32::NameOfByteCPURegister); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) { 46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return PrintRightOperandHelper(modrmp, 46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfXMMRegister); 46444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data. 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem, 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order, 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data) { 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *data; 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int advance = 0; 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (op_order) { 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REG_OPER_OP_ORDER: { 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case OPER_REG_OP_ORDER: { 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return advance; 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte. 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'. 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) { 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool sign_extension_bit = (*data & 0x02) != 0; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "Imm???"; 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: mnem = "add"; break; 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: mnem = "or"; break; 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: mnem = "adc"; break; 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: mnem = "and"; break; 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: mnem = "sub"; break; 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: mnem = "xor"; break; 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: mnem = "cmp"; break; 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data+1); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (sign_extension_bit) { 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *(data + 1 + count)); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 1 /*int8*/; 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 4 /*int32_t*/; 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) { 528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xF7, *data); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3 && regop != 0) { 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: mnem = "not"; break; 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: mnem = "neg"; break; 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: mnem = "mul"; break; 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: mnem = "idiv"; break; 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfCPURegister(rm)); 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (mod == 3 && regop == eax) { 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data+2); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test %s,0x%x", NameOfCPURegister(rm), imm); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (regop == eax) { 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test "); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data+1); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data+1+count); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1+count+4 /*int32_t*/; 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) { 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte op = *data; 561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm8 = -1; 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_bytes = 2; 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3) { 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (regop) { 570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kROL: mnem = "rol"; break; 571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kROR: mnem = "ror"; break; 572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kRCL: mnem = "rcl"; break; 573756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick case kRCR: mnem = "rcr"; break; 574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kSHL: mnem = "shl"; break; 575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case KSHR: mnem = "shr"; break; 576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kSAR: mnem = "sar"; break; 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op == 0xD1) { 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = 1; 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (op == 0xC1) { 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = *(data+2); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_bytes = 3; 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (op == 0xD3) { 585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Shift/rotate by cl. 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NE(NULL, mnem); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm)); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (imm8 > 0) { 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%d", imm8); 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("cl"); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) { 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xEB, *data); 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("jmp %s", NameOfAddress(dest)); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) { 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; // includes 0x0F 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *data & 0x0F; 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) { 641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = set_conditional_mnem[cond]; 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRightByteOperand(data+2); 646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 3; // Includes 0x0F. 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 6513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) { 652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 6533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block byte cond = *(data + 1) & 0x0F; 6543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block const char* mnem = conditional_move_mnem[cond]; 6553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); 6563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return 2 + op_size; // includes 0x0F 6573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data. 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) { 662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte escape_opcode = *data; 663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xD8, escape_opcode & 0xF8); 664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte = *(data+1); 665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte >= 0xC0) { 667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return RegisterFPUInstruction(escape_opcode, modrm_byte); 668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, 674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int modrm_byte, 675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte* modrm_start) { 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: switch (regop) { 680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_s"; break; 681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_s"; break; 682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fstcw"; break; 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: switch (regop) { 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fild_s"; break; 689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 1: mnem = "fisttp_s"; break; 690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 2: mnem = "fist_s"; break; 691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fistp_s"; break; 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: switch (regop) { 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_d"; break; 6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 1: mnem = "fisttp_d"; break; 6990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 2: mnem = "fst_d"; break; 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_d"; break; 701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: switch (regop) { 706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 5: mnem = "fild_d"; break; 707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fistp_d"; break; 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s ", mnem); 715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int count = PrintRightOperand(modrm_start); 716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return count + 1; 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte) { 721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool has_register = false; // Is the FPU register encoded in modrm_byte? 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 7310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 0xC0: 7320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mnem = "fld"; 7330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen has_register = true; 7340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fxch"; 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte) { 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE0: mnem = "fchs"; break; 742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE1: mnem = "fabs"; break; 743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE4: mnem = "ftst"; break; 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fld1"; break; 745402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case 0xEB: mnem = "fldpi"; break; 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xED: mnem = "fldln2"; break; 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xEE: mnem = "fldz"; break; 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xF1: mnem = "fyl2x"; break; 749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF5: mnem = "fprem1"; break; 750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF7: mnem = "fincstp"; break; 751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fprem"; break; 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFE: mnem = "fsin"; break; 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFF: mnem = "fcos"; break; 754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDA: 760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE9) { 761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucompp"; 762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 764d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: 768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if ((modrm_byte & 0xF8) == 0xE8) { 769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomi"; 770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (modrm_byte == 0xE2) { 772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fclex"; 773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDC: 779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "fadd"; break; 782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsub"; break; 783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmul"; break; 784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdiv"; break; 785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: 790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "ffree"; break; 793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: mnem = "fstp"; break; 794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDE: 799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xD9) { 800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fcompp"; 801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "faddp"; break; 805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsubp"; break; 806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmulp"; break; 807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdivp"; break; 808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: 814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE0) { 815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fnstsw_ax"; 816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if ((modrm_byte & 0xF8) == 0xE8) { 817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomip"; 818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (has_register) { 826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte. 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here. 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) { 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (f0byte) { 8387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch case 0x18: return "prefetch"; 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA2: return "cpuid"; 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x31: return "rdtsc"; 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBE: return "movsx_b"; 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBF: return "movsx_w"; 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB6: return "movzx_b"; 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB7: return "movzx_w"; 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAF: return "imul"; 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA5: return "shld"; 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAD: return "shrd"; 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAB: return "bts"; 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: return NULL; 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'. 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instr) { 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ = 0; // starting to write as position 0 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data = instr; 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for hints. 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* branch_hint = NULL; 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We use these two prefixes only with branch prediction 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0x3E /*ds*/) { 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted taken"; 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x2E /*cs*/) { 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted not taken"; 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool processed = true; // Will be set to false if the current instruction 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is not in 'instructions' table. 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& idesc = instruction_table.Get(*data); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (idesc.type) { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ZERO_OPERANDS_INSTR: 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(idesc.mnem); 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TWO_OPERANDS_INSTR: 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(idesc.mnem, idesc.op_order_, data); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case JUMP_CONDITIONAL_SHORT_INSTR: 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditionalShort(data, branch_hint); 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REGISTER_INSTR: 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOVE_REG_INSTR: { 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov %s,%s", 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(*data & 0x07), 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfAddress(addr)); 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CALL_JUMP_INSTR: { 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5; 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SHORT_IMMEDIATE_INSTR: { 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s eax, %s", idesc.mnem, NameOfAddress(addr)); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NO_INSTR: 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block processed = false; 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // This type is not implemented. 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block //---------------------------- 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!processed) { 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (*data) { 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC2: 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1)); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x69: // fall through 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6B: 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { int mod, regop, rm; 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data+1), &mod, ®op, &rm); 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2); 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("imul %s,%s,0x%x", 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(regop), 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm), 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm); 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2 + (*data == 0x6B ? 1 : 4); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF6: 9457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch { data++; 9467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 9477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 9487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (regop == eax) { 9497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("test_b "); 95044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 9517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int32_t imm = *data; 9527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer(",0x%x", imm); 9537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x81: // fall through 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x83: // 0x81 with sign extension bit set 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintImmediateOp(data); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x0F: 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { byte f0byte = *(data+1); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* f0mnem = F0Mnem(f0byte); 9687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (f0byte == 0x18) { 9697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 9707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 9717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const char* suffix[] = {"nta", "1", "2", "3"}; 9727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]); 9737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 9747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (f0byte == 0xA2 || f0byte == 0x31) { 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", f0mnem); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 9770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (f0byte == 0x28) { 9780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 9790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int mod, regop, rm; 9800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen get_modrm(*data, &mod, ®op, &rm); 9810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("movaps %s,%s", 9820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 9830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 9840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data++; 985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (f0byte == 0x57) { 986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data += 2; 987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("xorps %s,%s", 990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NameOfXMMRegister(regop), 991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NameOfXMMRegister(rm)); 992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data++; 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x80) { 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditional(data, branch_hint); 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f0byte == 0xB7 || f0byte == 0xAF) { 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x90) { 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += SetCC(data); 10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if ((f0byte & 0xF0) == 0x40) { 10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data += CMov(data); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) { 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // shrd, shld, bts 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", f0mnem); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f0byte == 0xAB) { 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x8F: 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == eax) { 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("pop "); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFF: 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esi: mnem = "push"; break; 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case eax: mnem = "inc"; break; 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ecx: mnem = "dec"; break; 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case edx: mnem = "call"; break; 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esp: mnem = "jmp"; break; 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: mnem = "???"; 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC7: // imm32, fall through 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC6: // imm8 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0xC6; 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 105644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 105844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *data; 106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 106144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data++; 106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 106444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 106544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data); 106644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 106744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 4; 106844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x80: 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1075e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1076e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* mnem = NULL; 1077e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (regop) { 1078e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 5: mnem = "subb"; break; 1079e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 7: mnem = "cmpb"; break; 1080e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke default: UnimplementedInstruction(); 1081e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1082e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("%s ", mnem); 108344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data; 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x88: // 8bit, fall through 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x89: // 32bit 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0x88; 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 109644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 109744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 109844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 109944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 110044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 110144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 110244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 110344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 110444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x66: // prefix 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0x8B) { 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x89) { 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov_w "); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 11203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (*data == 0x0F) { 11213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x38) { 11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x17) { 11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("ptest %s,%s", 11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0x2A) { 11337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // movntdqa 11347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 11357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 11367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 11377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop)); 11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x3A) { 1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 114469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*data == 0x0B) { 114569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data++; 114669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int mod, regop, rm; 114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 114869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 114969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AppendToBuffer("roundsd %s,%s,%d", 115069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(regop), 115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(rm), 115269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static_cast<int>(imm8)); 115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data += 2; 115469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (*data == 0x16) { 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pextrd %s,%s,%d", 11601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(regop), 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 11641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (*data == 0x22) { 11651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data++; 11661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int mod, regop, rm; 11671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block get_modrm(*data, &mod, ®op, &rm); 11681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int8_t imm8 = static_cast<int8_t>(data[1]); 11691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("pinsrd %s,%s,%d", 11701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfXMMRegister(regop), 11711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(rm), 11721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<int>(imm8)); 11731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data += 2; 1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UnimplementedInstruction(); 1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x2E || *data == 0x2F) { 11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd"; 11793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 11803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int mod, regop, rm; 11813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block get_modrm(*data, &mod, ®op, &rm); 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mod == 0x3) { 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,%s", mnem, 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x50) { 11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movmskpd %s,%s", 11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfCPURegister(regop), 11973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block NameOfXMMRegister(rm)); 11983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x54) { 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("andpd %s,%s", 1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x57) { 1208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1209e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1210e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1211e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("xorpd %s,%s", 1212e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(regop), 1213e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(rm)); 1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x6E) { 12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movd %s,", NameOfXMMRegister(regop)); 12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 1221e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x6F) { 1222e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop)); 122644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x70) { 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pshufd %s,%s,%d", 1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1237b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xF3) { 1238b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1239b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1240b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1241b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psllq %s,%s", 1242b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1243b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1244b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x73) { 1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1250b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(regop == esi || regop == edx); 1251b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("%s %s,%d", 1252b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch (regop == esi) ? "psllq" : "psrlq", 1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1256b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xD3) { 1257b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1258b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1259b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1260b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psrlq %s,%s", 1261b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1263b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x7F) { 1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa "); 1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x7E) { 1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("movd "); 1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += PrintRightOperand(data); 1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0xDB) { 1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pand %s,%s", 1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 12867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0xE7) { 12877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 12887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 12897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 129044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (mod == 3) { 129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movntdq "); 129244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 129444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 129544f0eee88ff00398ff7f715fab053374d808c90dSteve Block UnimplementedInstruction(); 129644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0xEF) { 1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pxor %s,%s", 1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xEB) { 1306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("por %s,%s", 1310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 13133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UnimplementedInstruction(); 13153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFE: 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 13250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (regop == ecx) { 13260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("dec_b "); 13270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += PrintRightOperand(data); 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x68: 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1)); 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6A: 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA8: 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1)); 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1349e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 0x2C: 1350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("subb eax,0x%x", *reinterpret_cast<uint8_t*>(data+1)); 1351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 2; 1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 1353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA9: 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1)); 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD1: // fall through 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD3: // fall through 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC1: 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += D1D3C1Instruction(data); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD9: // fall through 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDA: // fall through 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDB: // fall through 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDC: // fall through 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDD: // fall through 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDE: // fall through 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDF: 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += FPUInstruction(data); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEB: 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpShort(data); 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF2: 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*(data+1) == 0x0F) { 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b2 = *(data+2); 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x11) { 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd "); 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b2 == 0x10) { 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd %s,", NameOfXMMRegister(regop)); 139444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 139544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 139644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 139844f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 139944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop)); 140044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (b2) { 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x2A: mnem = "cvtsi2sd"; break; 14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x2C: mnem = "cvttsd2si"; break; 14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x51: mnem = "sqrtsd"; break; 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x58: mnem = "addsd"; break; 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x59: mnem = "mulsd"; break; 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5C: mnem = "subsd"; break; 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5E: mnem = "divsd"; break; 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x2A) { 141644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 141744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (b2 == 0x2C) { 141944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 14210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (b2 == 0xC2) { 14220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Intel manual 2A, Table 3-18. 14230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const char* const pseudo_op[] = { 14240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpeqsd", 14250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpltsd", 14260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmplesd", 14270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpunordsd", 14280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpneqsd", 14290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnltsd", 14300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnlesd", 14310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpordsd" 14320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen }; 14330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("%s %s,%s", 14340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen pseudo_op[data[1]], 14350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 14360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 14370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 143944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 144044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF3: 1449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (*(data+1) == 0x0F) { 145044f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte b2 = *(data+2); 145144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (b2 == 0x11) { 145244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss "); 1453e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 145444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 145544f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 145644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 145744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 145844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x10) { 14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 3; 14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 146244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss %s,", NameOfXMMRegister(regop)); 146344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 146444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x2C) { 146544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 146644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 146744f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 146844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop)); 146944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 147044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 147144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 147244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 147344f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 147444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 147544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 147644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x6F) { 1477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1478e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop)); 148144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 148244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x7F) { 1483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu "); 1484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1485e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1490e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UnimplementedInstruction(); 1491e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1492e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*(data+1) == 0xA5) { 1493e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 2; 1494e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("rep_movs"); 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*(data+1) == 0xAB) { 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 2; 14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("rep_stos"); 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += F7Instruction(data); 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[tmp_buffer_pos_] = '\0'; 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instr_len = data - instr; 1517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (instr_len == 0) { 1518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%02x", *data); 1519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(instr_len > 0); // Ensure progress. 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int outp = 0; 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bytes. 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = instr; bp < data; bp++) { 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%02x", 1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *bp); 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - instr_len; i >= 0; i--) { 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block " "); 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, 1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block " %s", 1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_.start()); 1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr_len; 15380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} // NOLINT (function is too long) 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[8] = { 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[8] = { 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[8] = { 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); 156144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return cpu_regs[reg]; 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return byte_cpu_regs[reg]; 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return xmm_regs[reg]; 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IA32 does not embed debug strings at the moment. 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(buffer, instruction); 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools. 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p", prev_pc); 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = prev_pc; bp < pc; bp++) { 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%02x", *bp); 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " %s\n", buffer.start()); 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1638f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1639f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1640