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[] = { 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x01, "add", OPER_REG_OP_ORDER}, 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x03, "add", REG_OPER_OP_ORDER}, 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x09, "or", OPER_REG_OP_ORDER}, 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x0B, "or", REG_OPER_OP_ORDER}, 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x1B, "sbb", REG_OPER_OP_ORDER}, 63d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x21, "and", OPER_REG_OP_ORDER}, 64d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x23, "and", REG_OPER_OP_ORDER}, 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x29, "sub", OPER_REG_OP_ORDER}, 66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke {0x2A, "subb", REG_OPER_OP_ORDER}, 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x2B, "sub", REG_OPER_OP_ORDER}, 68eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke {0x31, "xor", OPER_REG_OP_ORDER}, 69eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke {0x33, "xor", REG_OPER_OP_ORDER}, 70d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x38, "cmpb", OPER_REG_OP_ORDER}, 71d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x3A, "cmpb", REG_OPER_OP_ORDER}, 72d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x3B, "cmp", REG_OPER_OP_ORDER}, 73d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x84, "test_b", REG_OPER_OP_ORDER}, 74d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x85, "test", REG_OPER_OP_ORDER}, 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x87, "xchg", REG_OPER_OP_ORDER}, 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x8A, "mov_b", REG_OPER_OP_ORDER}, 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x8B, "mov", REG_OPER_OP_ORDER}, 78d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x8D, "lea", REG_OPER_OP_ORDER}, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xC3, "ret", UNSET_OP_ORDER}, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xC9, "leave", UNSET_OP_ORDER}, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x90, "nop", UNSET_OP_ORDER}, 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xF4, "hlt", UNSET_OP_ORDER}, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xCC, "int3", UNSET_OP_ORDER}, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x60, "pushad", UNSET_OP_ORDER}, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x61, "popad", UNSET_OP_ORDER}, 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9C, "pushfd", UNSET_OP_ORDER}, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9D, "popfd", UNSET_OP_ORDER}, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9E, "sahf", UNSET_OP_ORDER}, 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x99, "cdq", UNSET_OP_ORDER}, 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9B, "fwait", UNSET_OP_ORDER}, 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block {0xFC, "cld", UNSET_OP_ORDER}, 97f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke {0xAB, "stos", UNSET_OP_ORDER}, 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = { 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xE8, "call", UNSET_OP_ORDER}, 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xE9, "jmp", UNSET_OP_ORDER}, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = { 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x05, "add", UNSET_OP_ORDER}, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x0D, "or", UNSET_OP_ORDER}, 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x15, "adc", UNSET_OP_ORDER}, 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x25, "and", UNSET_OP_ORDER}, 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x2D, "sub", UNSET_OP_ORDER}, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x35, "xor", UNSET_OP_ORDER}, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x3D, "cmp", UNSET_OP_ORDER}, 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generally we don't want to generate these because they are subject to partial 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register stalls. They are included for completeness and because the cmp 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// variant is used by the RecordWrite stub. Because it does not update the 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register it is not subject to partial register stalls. 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic ByteMnemonic byte_immediate_instr[] = { 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x0c, "or", UNSET_OP_ORDER}, 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x24, "and", UNSET_OP_ORDER}, 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x34, "xor", UNSET_OP_ORDER}, 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x3c, "cmp", UNSET_OP_ORDER}, 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {-1, "", UNSET_OP_ORDER} 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const jump_conditional_mnem[] = { 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*0*/ "jo", "jno", "jc", "jnc", 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*4*/ "jz", "jnz", "jna", "ja", 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*8*/ "js", "jns", "jpe", "jpo", 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*12*/ "jl", "jnl", "jng", "jg" 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const set_conditional_mnem[] = { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*0*/ "seto", "setno", "setc", "setnc", 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*4*/ "setz", "setnz", "setna", "seta", 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*8*/ "sets", "setns", "setpe", "setpo", 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*12*/ "setl", "setnl", "setng", "setg" 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_move_mnem[] = { 1513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", 1523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", 1533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", 1543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" 1553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}; 1563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType { 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_INSTR, 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ZERO_OPERANDS_INSTR, 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TWO_OPERANDS_INSTR, 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JUMP_CONDITIONAL_SHORT_INSTR, 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REGISTER_INSTR, 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MOVE_REG_INSTR, 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_JUMP_INSTR, 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SHORT_IMMEDIATE_INSTR, 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BYTE_IMMEDIATE_INSTR 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionType type; 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order_; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable { 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionTable(); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& Get(byte x) const { return instructions_[x]; } 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static InstructionTable* get_instance() { 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static InstructionTable table; 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return &table; 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc instructions_[256]; 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Clear(); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Init(); 19169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void CopyTable(const ByteMnemonic bm[], InstructionType type); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetTableRange(InstructionType type, 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AddJumpConditionalShort(); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() { 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Init(); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < 256; i++) { 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].mnem = ""; 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].type = NO_INSTR; 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].op_order_ = UNSET_OP_ORDER; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() { 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(call_jump_instr, CALL_JUMP_INSTR); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddJumpConditionalShort(); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[], 23269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch InstructionType type) { 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; bm[i].b >= 0; i++) { 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[bm[i].b]; 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = bm[i].mnem; 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->op_order_ = bm[i].op_order_; 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type, 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem) { 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = start; b <= end; b++) { 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = mnem; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() { 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = 0x70; b <= 0x7F; b++) { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = jump_conditional_mnem[b & 0x0F]; 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = JUMP_CONDITIONAL_SHORT_INSTR; 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA32 disassembler implementation. 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerIA32 { 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32(const NameConverter& converter, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented = true) 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instruction_table_(InstructionTable::get_instance()), 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_(0), 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort_on_unimplemented_(abort_on_unimplemented) { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[0] = '\0'; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~DisassemblerIA32() {} 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const NameConverter& converter_; 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InstructionTable* instruction_table_; 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int tmp_buffer_pos_; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented_; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum { 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block eax = 0, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ecx = 1, 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx = 2, 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebx = 3, 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esp = 4, 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebp = 5, 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esi = 6, 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edi = 7 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block enum ShiftOpcodeExtension { 304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROL = 0, 305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROR = 1, 306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCL = 2, 307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCR = 3, 308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSHL = 4, 309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block KSHR = 5, 310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSAR = 7 311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfCPURegister(int reg) const { 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfCPURegister(reg); 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfByteCPURegister(int reg) const { 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfByteCPURegister(reg); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfXMMRegister(int reg) const { 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfXMMRegister(reg); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(byte* addr) const { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfAddress(addr); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Disassembler helper functions. 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_modrm(byte data, int* mod, int* regop, int* rm) { 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *mod = (data >> 6) & 3; 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *regop = (data & 0x38) >> 3; 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rm = data & 7; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_sib(byte data, int* scale, int* index, int* base) { 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *scale = (data >> 6) & 3; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *index = (data >> 3) & 7; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *base = data & 7; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperand(byte* modrmp); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightByteOperand(byte* modrmp); 35344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int PrintRightXMMOperand(byte* modrmp); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediateOp(byte* data); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int F7Instruction(byte* data); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int D1D3C1Instruction(byte* data); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpShort(byte* data); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditional(byte* data, const char* comment); 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditionalShort(byte* data, const char* comment); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SetCC(byte* data); 3623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int CMov(byte* data); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int FPUInstruction(byte* data); 364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AppendToBuffer(const char* format, ...); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UnimplementedInstruction() { 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (abort_on_unimplemented_) { 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("'Unimplemented Instruction'"); 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) { 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = v8::internal::OS::VSNPrintF(buf, format, args); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ += result; 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper( 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* modrmp, 39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping direct_register_name) { 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*modrmp, &mod, ®op, &rm); 39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfCPURegister; 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (mod) { 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == ebp) { 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[0x%x]", disp); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rm == esp) { 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == esp && base == esp && scale == 0 /*times_1*/) { 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (base == ebp) { 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s*%d+0x%x]", 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disp); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (index != esp && base != ebp) { 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base+index*scale] 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d]", 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: // fall through 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == esp) { 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) : *(modrmp + 2); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d+0x%x]", 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block disp); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 6 : 3; 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No sib. 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int disp = 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) : *(modrmp + 1); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 5 : 2; 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", (this->*register_name)(rm)); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) { 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) { 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerIA32::NameOfByteCPURegister); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) { 48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return PrintRightOperandHelper(modrmp, 48144f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfXMMRegister); 48244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 48344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 48444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data. 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem, 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order, 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data) { 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *data; 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int advance = 0; 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (op_order) { 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REG_OPER_OP_ORDER: { 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case OPER_REG_OP_ORDER: { 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return advance; 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte. 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'. 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) { 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool sign_extension_bit = (*data & 0x02) != 0; 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "Imm???"; 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: mnem = "add"; break; 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: mnem = "or"; break; 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: mnem = "adc"; break; 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: mnem = "and"; break; 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: mnem = "sub"; break; 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: mnem = "xor"; break; 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: mnem = "cmp"; break; 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data+1); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (sign_extension_bit) { 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *(data + 1 + count)); 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 1 /*int8*/; 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 4 /*int32_t*/; 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) { 546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xF7, *data); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3 && regop != 0) { 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: mnem = "not"; break; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: mnem = "neg"; break; 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: mnem = "mul"; break; 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: mnem = "idiv"; break; 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfCPURegister(rm)); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (mod == 3 && regop == eax) { 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data+2); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test %s,0x%x", NameOfCPURegister(rm), imm); 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (regop == eax) { 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test "); 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data+1); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data+1+count); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1+count+4 /*int32_t*/; 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) { 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte op = *data; 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm8 = -1; 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_bytes = 2; 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mod == 3) { 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (regop) { 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kROL: mnem = "rol"; break; 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kROR: mnem = "ror"; break; 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kRCL: mnem = "rcl"; break; 591756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick case kRCR: mnem = "rcr"; break; 592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kSHL: mnem = "shl"; break; 593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case KSHR: mnem = "shr"; break; 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case kSAR: mnem = "sar"; break; 595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (op == 0xD1) { 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = 1; 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (op == 0xC1) { 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm8 = *(data+2); 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_bytes = 3; 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (op == 0xD3) { 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Shift/rotate by cl. 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_NE(NULL, mnem); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm)); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (imm8 > 0) { 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%d", imm8); 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("cl"); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return num_bytes; 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) { 621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xEB, *data); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("jmp %s", NameOfAddress(dest)); 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) { 631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; // includes 0x0F 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *data & 0x0F; 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) { 659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = set_conditional_mnem[cond]; 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRightByteOperand(data+2); 664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 3; // Includes 0x0F. 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 6693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) { 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0x0F, *data); 6713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block byte cond = *(data + 1) & 0x0F; 6723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block const char* mnem = conditional_move_mnem[cond]; 6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); 6743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return 2 + op_size; // includes 0x0F 6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data. 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) { 680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte escape_opcode = *data; 681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT_EQ(0xD8, escape_opcode & 0xF8); 682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte = *(data+1); 683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte >= 0xC0) { 685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return RegisterFPUInstruction(escape_opcode, modrm_byte); 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, 692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int modrm_byte, 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte* modrm_start) { 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: switch (regop) { 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_s"; break; 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_s"; break; 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fstcw"; break; 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: switch (regop) { 706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fild_s"; break; 707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 1: mnem = "fisttp_s"; break; 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 2: mnem = "fist_s"; break; 709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fistp_s"; break; 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: switch (regop) { 715d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_d"; break; 7160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 1: mnem = "fisttp_d"; break; 7170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 2: mnem = "fst_d"; break; 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_d"; break; 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: switch (regop) { 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 5: mnem = "fild_d"; break; 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fistp_d"; break; 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s ", mnem); 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int count = PrintRightOperand(modrm_start); 734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return count + 1; 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, 738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte) { 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool has_register = false; // Is the FPU register encoded in modrm_byte? 740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: 748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 7490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 0xC0: 7500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mnem = "fld"; 7510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen has_register = true; 7520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: 754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fxch"; 755d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 756d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte) { 759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE0: mnem = "fchs"; break; 760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE1: mnem = "fabs"; break; 761d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE4: mnem = "ftst"; break; 762d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fld1"; break; 763402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case 0xEB: mnem = "fldpi"; break; 764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xED: mnem = "fldln2"; break; 765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xEE: mnem = "fldz"; break; 7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xF0: mnem = "f2xm1"; break; 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xF1: mnem = "fyl2x"; break; 768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF5: mnem = "fprem1"; break; 769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF7: mnem = "fincstp"; break; 770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fprem"; break; 7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFC: mnem = "frndint"; break; 7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFD: mnem = "fscale"; break; 773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFE: mnem = "fsin"; break; 774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFF: mnem = "fcos"; break; 775d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 776d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDA: 781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE9) { 782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucompp"; 783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 784d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 785d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: 789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if ((modrm_byte & 0xF8) == 0xE8) { 790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomi"; 791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (modrm_byte == 0xE2) { 793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fclex"; 7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (modrm_byte == 0xE3) { 7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mnem = "fninit"; 796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDC: 802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "fadd"; break; 805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsub"; break; 806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmul"; break; 807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdiv"; break; 808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: 813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "ffree"; break; 816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: mnem = "fstp"; break; 817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDE: 822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xD9) { 823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fcompp"; 824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "faddp"; break; 828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsubp"; break; 829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmulp"; break; 830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdivp"; break; 831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE0) { 838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fnstsw_ax"; 839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if ((modrm_byte & 0xF8) == 0xE8) { 840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomip"; 841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (has_register) { 849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte. 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here. 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) { 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (f0byte) { 8617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch case 0x18: return "prefetch"; 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA2: return "cpuid"; 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x31: return "rdtsc"; 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBE: return "movsx_b"; 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBF: return "movsx_w"; 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB6: return "movzx_b"; 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB7: return "movzx_w"; 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAF: return "imul"; 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA5: return "shld"; 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAD: return "shrd"; 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAB: return "bts"; 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: return NULL; 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'. 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instr) { 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ = 0; // starting to write as position 0 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data = instr; 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for hints. 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* branch_hint = NULL; 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We use these two prefixes only with branch prediction 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0x3E /*ds*/) { 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted taken"; 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x2E /*cs*/) { 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted not taken"; 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool processed = true; // Will be set to false if the current instruction 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is not in 'instructions' table. 8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const InstructionDesc& idesc = instruction_table_->Get(*data); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (idesc.type) { 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ZERO_OPERANDS_INSTR: 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(idesc.mnem); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TWO_OPERANDS_INSTR: 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(idesc.mnem, idesc.op_order_, data); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case JUMP_CONDITIONAL_SHORT_INSTR: 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditionalShort(data, branch_hint); 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REGISTER_INSTR: 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOVE_REG_INSTR: { 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov %s,%s", 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(*data & 0x07), 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfAddress(addr)); 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CALL_JUMP_INSTR: { 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5; 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SHORT_IMMEDIATE_INSTR: { 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s eax, %s", idesc.mnem, NameOfAddress(addr)); 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BYTE_IMMEDIATE_INSTR: { 9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("%s al, 0x%x", idesc.mnem, data[1]); 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 2; 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NO_INSTR: 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block processed = false; 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // This type is not implemented. 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block //---------------------------- 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!processed) { 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (*data) { 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC2: 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1)); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x69: // fall through 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6B: 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { int mod, regop, rm; 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*(data+1), &mod, ®op, &rm); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2); 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("imul %s,%s,0x%x", 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(regop), 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(rm), 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block imm); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2 + (*data == 0x6B ? 1 : 4); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF6: 9747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch { data++; 9757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 9767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 9777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (regop == eax) { 9787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("test_b "); 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 9807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int32_t imm = *data; 9817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer(",0x%x", imm); 9827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x81: // fall through 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x83: // 0x81 with sign extension bit set 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintImmediateOp(data); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x0F: 9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { byte f0byte = data[1]; 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* f0mnem = F0Mnem(f0byte); 9977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (f0byte == 0x18) { 9987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 9997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 10007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const char* suffix[] = {"nta", "1", "2", "3"}; 10017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]); 10027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0) { 10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 3 byte nop. 10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 3; 10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) { 10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 4 byte nop. 10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 4; 10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 && 10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0) { 10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 5 byte nop. 10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 5; 10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 && 10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0 && data[5] == 0 && data[6] == 0) { 10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 7 byte nop. 10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 7; 10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 && 10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0 && data[5] == 0 && data[6] == 0 && 10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[7] == 0) { 10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 8 byte nop. 10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 8; 10227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (f0byte == 0xA2 || f0byte == 0x31) { 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", f0mnem); 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 10250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (f0byte == 0x28) { 10260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 10270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int mod, regop, rm; 10280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen get_modrm(*data, &mod, ®op, &rm); 10290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("movaps %s,%s", 10300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 10310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 10320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data++; 1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (f0byte == 0x57) { 1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data += 2; 1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AppendToBuffer("xorps %s,%s", 1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NameOfXMMRegister(regop), 1039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NameOfXMMRegister(rm)); 1040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data++; 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x80) { 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditional(data, branch_hint); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f0byte == 0xB7 || f0byte == 0xAF) { 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x90) { 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += SetCC(data); 10493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if ((f0byte & 0xF0) == 0x40) { 10503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data += CMov(data); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) { 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // shrd, shld, bts 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", f0mnem); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f0byte == 0xAB) { 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x8F: 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == eax) { 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("pop "); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFF: 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esi: mnem = "push"; break; 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case eax: mnem = "inc"; break; 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ecx: mnem = "dec"; break; 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case edx: mnem = "call"; break; 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esp: mnem = "jmp"; break; 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: mnem = "???"; 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC7: // imm32, fall through 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC6: // imm8 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0xC6; 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 110444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 110544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 110644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 110744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *data; 110844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 110944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data++; 111044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 111144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 111244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 111344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data); 111444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 4; 111644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x80: 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1122e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1124e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* mnem = NULL; 1125e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (regop) { 1126e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 5: mnem = "subb"; break; 1127e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 7: mnem = "cmpb"; break; 1128e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke default: UnimplementedInstruction(); 1129e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("%s ", mnem); 113144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data; 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x88: // 8bit, fall through 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x89: // 32bit 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0x88; 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 114444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 114644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 114744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 114844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 114944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 115044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x66: // prefix 11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (*data == 0x66) data++; 11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*data == 0xf && data[1] == 0x1f) { 11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 0x66 prefix 11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x90) { 11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 0x66 prefix 11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x8B) { 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x89) { 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov_w "); 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 11723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (*data == 0x0F) { 11733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x38) { 11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x17) { 11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("ptest %s,%s", 11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 11847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0x2A) { 11857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // movntdqa 11867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 11877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 11887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 11897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop)); 11907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x3A) { 1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 119669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*data == 0x0B) { 119769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data++; 119869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int mod, regop, rm; 119969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 120069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 120169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AppendToBuffer("roundsd %s,%s,%d", 120269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(regop), 120369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(rm), 120469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static_cast<int>(imm8)); 120569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data += 2; 120669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (*data == 0x16) { 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pextrd %s,%s,%d", 12121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(regop), 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x17) { 12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data++; 12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mod, regop, rm; 12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch get_modrm(*data, &mod, ®op, &rm); 12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("extractps %s,%s,%d", 12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NameOfCPURegister(regop), 12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NameOfXMMRegister(rm), 12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<int>(imm8)); 12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 2; 12261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (*data == 0x22) { 12271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data++; 12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int mod, regop, rm; 12291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block get_modrm(*data, &mod, ®op, &rm); 12301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int8_t imm8 = static_cast<int8_t>(data[1]); 12311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("pinsrd %s,%s,%d", 12321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfXMMRegister(regop), 12331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(rm), 12341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<int>(imm8)); 12351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data += 2; 1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UnimplementedInstruction(); 1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x2E || *data == 0x2F) { 12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd"; 12413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 12423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int mod, regop, rm; 12433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block get_modrm(*data, &mod, ®op, &rm); 12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mod == 0x3) { 12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,%s", mnem, 12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x50) { 12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movmskpd %s,%s", 12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfCPURegister(regop), 12593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block NameOfXMMRegister(rm)); 12603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x54) { 1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("andpd %s,%s", 1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1269e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x57) { 1270e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1271e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("xorpd %s,%s", 1274e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(regop), 1275e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(rm)); 1276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x6E) { 12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movd %s,", NameOfXMMRegister(regop)); 12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 1283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x6F) { 1284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1286e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1287e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop)); 128844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x70) { 1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pshufd %s,%s,%d", 1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x90) { 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data++; 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 2 byte nop. 1302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xF3) { 1303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psllq %s,%s", 1307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x73) { 1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(regop == esi || regop == edx); 1316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("%s %s,%d", 1317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch (regop == esi) ? "psllq" : "psrlq", 1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xD3) { 1322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psrlq %s,%s", 1326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x7F) { 1330e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa "); 1331e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 133444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1335e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x7E) { 1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("movd "); 1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += PrintRightOperand(data); 1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0xDB) { 1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pand %s,%s", 1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 13517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0xE7) { 13527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 13537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 13547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (mod == 3) { 135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movntdq "); 135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 135844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block UnimplementedInstruction(); 136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0xEF) { 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pxor %s,%s", 1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1370b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xEB) { 1371b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1372b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1373b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1374b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("por %s,%s", 1375b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1376b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1377b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 13783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 13793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UnimplementedInstruction(); 13803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFE: 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 13900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (regop == ecx) { 13910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("dec_b "); 13920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += PrintRightOperand(data); 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x68: 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1)); 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6A: 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA8: 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1)); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA9: 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1)); 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD1: // fall through 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD3: // fall through 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC1: 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += D1D3C1Instruction(data); 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD9: // fall through 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDA: // fall through 1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDB: // fall through 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDC: // fall through 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDD: // fall through 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDE: // fall through 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDF: 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += FPUInstruction(data); 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEB: 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpShort(data); 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF2: 1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*(data+1) == 0x0F) { 1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b2 = *(data+2); 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x11) { 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd "); 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 144744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b2 == 0x10) { 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd %s,", NameOfXMMRegister(regop)); 145444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 145544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 145644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 145744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 145844f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 145944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop)); 146044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (b2) { 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x2A: mnem = "cvtsi2sd"; break; 14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x2C: mnem = "cvttsd2si"; break; 14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x51: mnem = "sqrtsd"; break; 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x58: mnem = "addsd"; break; 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x59: mnem = "mulsd"; break; 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5C: mnem = "subsd"; break; 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5E: mnem = "divsd"; break; 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x2A) { 147644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 147744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (b2 == 0x2C) { 147944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 148044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 14810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (b2 == 0xC2) { 14820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Intel manual 2A, Table 3-18. 14830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const char* const pseudo_op[] = { 14840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpeqsd", 14850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpltsd", 14860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmplesd", 14870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpunordsd", 14880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpneqsd", 14890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnltsd", 14900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnlesd", 14910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpordsd" 14920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen }; 14930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("%s %s,%s", 14940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen pseudo_op[data[1]], 14950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 14960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 14970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 149944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 150044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF3: 1509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (*(data+1) == 0x0F) { 151044f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte b2 = *(data+2); 151144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (b2 == 0x11) { 151244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss "); 1513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 151444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 151544f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 151644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 151844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x10) { 15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 3; 15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 152244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss %s,", NameOfXMMRegister(regop)); 152344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 152444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x2C) { 152544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 152644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 152744f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 152844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop)); 152944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 153044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 153144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 153244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 153344f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 153444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 153644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x6F) { 1537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop)); 154144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 154244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x7F) { 1543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu "); 1544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UnimplementedInstruction(); 1551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*(data+1) == 0xA5) { 1553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 2; 1554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("rep_movs"); 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*(data+1) == 0xAB) { 15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 2; 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("rep_stos"); 1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += F7Instruction(data); 1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[tmp_buffer_pos_] = '\0'; 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instr_len = data - instr; 1577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (instr_len == 0) { 1578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%02x", *data); 1579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(instr_len > 0); // Ensure progress. 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int outp = 0; 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bytes. 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = instr; bp < data; bp++) { 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%02x", 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *bp); 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - instr_len; i >= 0; i--) { 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block " "); 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block outp += v8::internal::OS::SNPrintF(out_buffer + outp, 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block " %s", 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_.start()); 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr_len; 15980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} // NOLINT (function is too long) 1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[8] = { 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[8] = { 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[8] = { 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 162044f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); 162144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return cpu_regs[reg]; 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return byte_cpu_regs[reg]; 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return xmm_regs[reg]; 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IA32 does not embed debug strings at the moment. 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(buffer, instruction); 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools. 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p", prev_pc); 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = prev_pc; bp < pc; bp++) { 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%02x", *bp); 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " %s\n", buffer.start()); 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1698f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1700