disasm-ia32.cc revision b8a8cc1952d61a2f3a2568848933943a543b5d3e
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h> 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdio.h> 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 10f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 12f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disasm.h" 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm { 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandOrder { 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNSET_OP_ORDER = 0, 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REG_OPER_OP_ORDER, 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OPER_REG_OP_ORDER 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------ 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic { 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int b; // -1 terminates, otherwise must be in range (0..255) 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order_; 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic two_operands_instr[] = { 353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x01, "add", OPER_REG_OP_ORDER}, 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x03, "add", REG_OPER_OP_ORDER}, 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x09, "or", OPER_REG_OP_ORDER}, 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x0B, "or", REG_OPER_OP_ORDER}, 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x1B, "sbb", REG_OPER_OP_ORDER}, 40d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x21, "and", OPER_REG_OP_ORDER}, 41d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x23, "and", REG_OPER_OP_ORDER}, 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x29, "sub", OPER_REG_OP_ORDER}, 43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke {0x2A, "subb", REG_OPER_OP_ORDER}, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x2B, "sub", REG_OPER_OP_ORDER}, 45eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke {0x31, "xor", OPER_REG_OP_ORDER}, 46eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke {0x33, "xor", REG_OPER_OP_ORDER}, 47d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x38, "cmpb", OPER_REG_OP_ORDER}, 48d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x3A, "cmpb", REG_OPER_OP_ORDER}, 49d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x3B, "cmp", REG_OPER_OP_ORDER}, 50d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x84, "test_b", REG_OPER_OP_ORDER}, 51d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x85, "test", REG_OPER_OP_ORDER}, 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x87, "xchg", REG_OPER_OP_ORDER}, 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x8A, "mov_b", REG_OPER_OP_ORDER}, 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x8B, "mov", REG_OPER_OP_ORDER}, 55d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke {0x8D, "lea", REG_OPER_OP_ORDER}, 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xC3, "ret", UNSET_OP_ORDER}, 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xC9, "leave", UNSET_OP_ORDER}, 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x90, "nop", UNSET_OP_ORDER}, 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xF4, "hlt", UNSET_OP_ORDER}, 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xCC, "int3", UNSET_OP_ORDER}, 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x60, "pushad", UNSET_OP_ORDER}, 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x61, "popad", UNSET_OP_ORDER}, 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9C, "pushfd", UNSET_OP_ORDER}, 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9D, "popfd", UNSET_OP_ORDER}, 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9E, "sahf", UNSET_OP_ORDER}, 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x99, "cdq", UNSET_OP_ORDER}, 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x9B, "fwait", UNSET_OP_ORDER}, 736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block {0xFC, "cld", UNSET_OP_ORDER}, 74f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke {0xAB, "stos", UNSET_OP_ORDER}, 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = { 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xE8, "call", UNSET_OP_ORDER}, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0xE9, "jmp", UNSET_OP_ORDER}, 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = { 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x05, "add", UNSET_OP_ORDER}, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x0D, "or", UNSET_OP_ORDER}, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x15, "adc", UNSET_OP_ORDER}, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x25, "and", UNSET_OP_ORDER}, 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x2D, "sub", UNSET_OP_ORDER}, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x35, "xor", UNSET_OP_ORDER}, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {0x3D, "cmp", UNSET_OP_ORDER}, 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {-1, "", UNSET_OP_ORDER} 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generally we don't want to generate these because they are subject to partial 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register stalls. They are included for completeness and because the cmp 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// variant is used by the RecordWrite stub. Because it does not update the 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register it is not subject to partial register stalls. 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic ByteMnemonic byte_immediate_instr[] = { 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x0c, "or", UNSET_OP_ORDER}, 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x24, "and", UNSET_OP_ORDER}, 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x34, "xor", UNSET_OP_ORDER}, 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {0x3c, "cmp", UNSET_OP_ORDER}, 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {-1, "", UNSET_OP_ORDER} 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const jump_conditional_mnem[] = { 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*0*/ "jo", "jno", "jc", "jnc", 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*4*/ "jz", "jnz", "jna", "ja", 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*8*/ "js", "jns", "jpe", "jpo", 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*12*/ "jl", "jnl", "jng", "jg" 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const set_conditional_mnem[] = { 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*0*/ "seto", "setno", "setc", "setnc", 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*4*/ "setz", "setnz", "setna", "seta", 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*8*/ "sets", "setns", "setpe", "setpo", 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /*12*/ "setl", "setnl", "setng", "setg" 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_move_mnem[] = { 1283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", 1293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", 1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", 1313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" 1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}; 1333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NO_INSTR, 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ZERO_OPERANDS_INSTR, 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TWO_OPERANDS_INSTR, 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JUMP_CONDITIONAL_SHORT_INSTR, 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block REGISTER_INSTR, 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MOVE_REG_INSTR, 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_JUMP_INSTR, 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SHORT_IMMEDIATE_INSTR, 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BYTE_IMMEDIATE_INSTR 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc { 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionType type; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order_; 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable { 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionTable(); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const InstructionDesc& Get(byte x) const { return instructions_[x]; } 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static InstructionTable* get_instance() { 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static InstructionTable table; 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return &table; 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc instructions_[256]; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Clear(); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Init(); 16869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void CopyTable(const ByteMnemonic bm[], InstructionType type); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetTableRange(InstructionType type, 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AddJumpConditionalShort(); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Init(); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < 256; i++) { 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].mnem = ""; 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].type = NO_INSTR; 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block instructions_[i].op_order_ = UNSET_OP_ORDER; 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() { 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(two_operands_instr, TWO_OPERANDS_INSTR); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(call_jump_instr, CALL_JUMP_INSTR); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR); 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddJumpConditionalShort(); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc"); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec"); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push"); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop"); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop. 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[], 20969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch InstructionType type) { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; bm[i].b >= 0; i++) { 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[bm[i].b]; 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = bm[i].mnem; 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->op_order_ = bm[i].op_order_; 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type, 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte start, 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte end, 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem) { 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = start; b <= end; b++) { 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = mnem; 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = type; 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() { 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte b = 0x70; b <= 0x7F; b++) { 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block InstructionDesc* id = &instructions_[b]; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->mnem = jump_conditional_mnem[b & 0x0F]; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block id->type = JUMP_CONDITIONAL_SHORT_INSTR; 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA32 disassembler implementation. 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerIA32 { 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32(const NameConverter& converter, 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented = true) 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter), 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instruction_table_(InstructionTable::get_instance()), 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_(0), 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort_on_unimplemented_(abort_on_unimplemented) { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[0] = '\0'; 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~DisassemblerIA32() {} 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const NameConverter& converter_; 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InstructionTable* instruction_table_; 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int tmp_buffer_pos_; 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented_; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum { 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block eax = 0, 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ecx = 1, 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx = 2, 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebx = 3, 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esp = 4, 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebp = 5, 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esi = 6, 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edi = 7 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block enum ShiftOpcodeExtension { 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROL = 0, 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROR = 1, 283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCL = 2, 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCR = 3, 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSHL = 4, 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block KSHR = 5, 287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSAR = 7 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfCPURegister(int reg) const { 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfCPURegister(reg); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfByteCPURegister(int reg) const { 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfByteCPURegister(reg); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfXMMRegister(int reg) const { 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfXMMRegister(reg); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(byte* addr) const { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfAddress(addr); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Disassembler helper functions. 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_modrm(byte data, int* mod, int* regop, int* rm) { 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *mod = (data >> 6) & 3; 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *regop = (data & 0x38) >> 3; 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rm = data & 7; 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_sib(byte data, int* scale, int* index, int* base) { 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *scale = (data >> 6) & 3; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *index = (data >> 3) & 7; 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *base = data & 7; 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const; 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperand(byte* modrmp); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightByteOperand(byte* modrmp); 33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int PrintRightXMMOperand(byte* modrmp); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediateOp(byte* data); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int F7Instruction(byte* data); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int D1D3C1Instruction(byte* data); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpShort(byte* data); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditional(byte* data, const char* comment); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditionalShort(byte* data, const char* comment); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SetCC(byte* data); 3393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int CMov(byte* data); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int FPUInstruction(byte* data); 341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AppendToBuffer(const char* format, ...); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UnimplementedInstruction() { 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (abort_on_unimplemented_) { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("'Unimplemented Instruction'"); 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) { 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = v8::internal::VSNPrintF(buf, format, args); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ += result; 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper( 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* modrmp, 36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping direct_register_name) { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*modrmp, &mod, ®op, &rm); 37044f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfCPURegister; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (mod) { 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == ebp) { 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[0x%x]", disp); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rm == esp) { 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == esp && base == esp && scale == 0 /*times_1*/) { 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (base == ebp) { 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s*%d%s0x%x]", 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (index != esp && base != ebp) { 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base+index*scale] 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d]", 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: // fall through 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == esp) { 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : *reinterpret_cast<int8_t*>(modrmp + 2); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s%s0x%x]", 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (this->*register_name)(rm), 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s+%s*%d%s0x%x]", 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 6 : 3; 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No sib. 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : *reinterpret_cast<int8_t*>(modrmp + 1); 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s%s0x%x]", 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (this->*register_name)(rm), 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 5 : 2; 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", (this->*register_name)(rm)); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) { 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) { 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerIA32::NameOfByteCPURegister); 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) { 46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return PrintRightOperandHelper(modrmp, 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfXMMRegister); 46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data. 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem, 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order, 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data) { 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *data; 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int advance = 0; 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (op_order) { 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REG_OPER_OP_ORDER: { 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case OPER_REG_OP_ORDER: { 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return advance; 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte. 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'. 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) { 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool sign_extension_bit = (*data & 0x02) != 0; 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "Imm???"; 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: mnem = "add"; break; 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: mnem = "or"; break; 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: mnem = "adc"; break; 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: mnem = "and"; break; 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: mnem = "sub"; break; 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: mnem = "xor"; break; 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: mnem = "cmp"; break; 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data+1); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (sign_extension_bit) { 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *(data + 1 + count)); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 1 /*int8*/; 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 4 /*int32_t*/; 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) { 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0xF7, *data); 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte modrm = *++data; 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* mnem = NULL; 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (regop) { 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0: 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "test"; 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "not"; 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 3: 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "neg"; 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 4: 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "mul"; 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 5: 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "imul"; 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 6: 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "div"; 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 7: 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "idiv"; 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UnimplementedInstruction(); 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", mnem); 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count = PrintRightOperand(data); 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (regop == 0) { 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count)); 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count += 4; 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 + count; 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) { 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte op = *data; 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte modrm = *++data; 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm8 = -1; 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* mnem = NULL; 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (regop) { 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kROL: 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "rol"; 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kROR: 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "ror"; 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRCL: 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "rcl"; 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRCR: 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "rcr"; 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSHL: 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "shl"; 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KSHR: 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "shr"; 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSAR: 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "sar"; 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UnimplementedInstruction(); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", mnem); 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count = PrintRightOperand(data); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (op == 0xD1) { 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm8 = 1; 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == 0xC1) { 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm8 = *(data + 1); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count++; 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == 0xD3) { 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shift/rotate by cl. 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (imm8 >= 0) { 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%d", imm8); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",cl"); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 + count; 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) { 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0xEB, *data); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("jmp %s", NameOfAddress(dest)); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) { 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0x0F, *data); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; // includes 0x0F 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *data & 0x0F; 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) { 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0x0F, *data); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = set_conditional_mnem[cond]; 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRightByteOperand(data+2); 668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 3; // Includes 0x0F. 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) { 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0x0F, *data); 6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block byte cond = *(data + 1) & 0x0F; 6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block const char* mnem = conditional_move_mnem[cond]; 6773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); 6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return 2 + op_size; // includes 0x0F 6793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 6803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 6823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data. 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) { 684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte escape_opcode = *data; 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0xD8, escape_opcode & 0xF8); 686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte = *(data+1); 687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte >= 0xC0) { 689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return RegisterFPUInstruction(escape_opcode, modrm_byte); 690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int modrm_byte, 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte* modrm_start) { 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: switch (regop) { 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_s"; break; 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: mnem = "fst_s"; break; 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_s"; break; 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fstcw"; break; 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: switch (regop) { 711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fild_s"; break; 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 1: mnem = "fisttp_s"; break; 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 2: mnem = "fist_s"; break; 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fistp_s"; break; 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: switch (regop) { 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_d"; break; 7210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 1: mnem = "fisttp_d"; break; 7220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 2: mnem = "fst_d"; break; 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_d"; break; 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: switch (regop) { 729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 5: mnem = "fild_d"; break; 730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fistp_d"; break; 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s ", mnem); 738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int count = PrintRightOperand(modrm_start); 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return count + 1; 740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, 743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte) { 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool has_register = false; // Is the FPU register encoded in modrm_byte? 745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch has_register = true; 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (modrm_byte & 0xF8) { 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xC0: mnem = "fadd_i"; break; 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xE0: mnem = "fsub_i"; break; 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xC8: mnem = "fmul_i"; break; 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xF0: mnem = "fdiv_i"; break; 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: UnimplementedInstruction(); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: 760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 7610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 0xC0: 7620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mnem = "fld"; 7630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen has_register = true; 7640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: 766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fxch"; 767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte) { 771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE0: mnem = "fchs"; break; 772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE1: mnem = "fabs"; break; 773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE4: mnem = "ftst"; break; 774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fld1"; break; 775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case 0xEB: mnem = "fldpi"; break; 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xED: mnem = "fldln2"; break; 777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xEE: mnem = "fldz"; break; 7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xF0: mnem = "f2xm1"; break; 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xF1: mnem = "fyl2x"; break; 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xF4: mnem = "fxtract"; break; 781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF5: mnem = "fprem1"; break; 782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF7: mnem = "fincstp"; break; 783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fprem"; break; 7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFC: mnem = "frndint"; break; 7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFD: mnem = "fscale"; break; 786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFE: mnem = "fsin"; break; 787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFF: mnem = "fcos"; break; 788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDA: 794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE9) { 795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucompp"; 796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: 802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if ((modrm_byte & 0xF8) == 0xE8) { 803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomi"; 804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (modrm_byte == 0xE2) { 806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fclex"; 8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (modrm_byte == 0xE3) { 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mnem = "fninit"; 809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDC: 815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "fadd"; break; 818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsub"; break; 819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmul"; break; 820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdiv"; break; 821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: 826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "ffree"; break; 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xD0: mnem = "fst"; break; 830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: mnem = "fstp"; break; 831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDE: 836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xD9) { 837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fcompp"; 838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "faddp"; break; 842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsubp"; break; 843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmulp"; break; 844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdivp"; break; 845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: 851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE0) { 852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fnstsw_ax"; 853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if ((modrm_byte & 0xF8) == 0xE8) { 854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomip"; 855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (has_register) { 863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte. 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here. 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) { 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (f0byte) { 8757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch case 0x18: return "prefetch"; 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA2: return "cpuid"; 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBE: return "movsx_b"; 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBF: return "movsx_w"; 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB6: return "movzx_b"; 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB7: return "movzx_w"; 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAF: return "imul"; 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA5: return "shld"; 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAD: return "shrd"; 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xAC: return "shrd"; // 3-operand version. 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAB: return "bts"; 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xBD: return "bsr"; 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: return NULL; 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'. 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instr) { 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ = 0; // starting to write as position 0 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data = instr; 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for hints. 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* branch_hint = NULL; 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We use these two prefixes only with branch prediction 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0x3E /*ds*/) { 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted taken"; 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x2E /*cs*/) { 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted not taken"; 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool processed = true; // Will be set to false if the current instruction 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is not in 'instructions' table. 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const InstructionDesc& idesc = instruction_table_->Get(*data); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (idesc.type) { 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ZERO_OPERANDS_INSTR: 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(idesc.mnem); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case TWO_OPERANDS_INSTR: 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(idesc.mnem, idesc.op_order_, data); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case JUMP_CONDITIONAL_SHORT_INSTR: 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditionalShort(data, branch_hint); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REGISTER_INSTR: 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case MOVE_REG_INSTR: { 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov %s,%s", 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfCPURegister(*data & 0x07), 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameOfAddress(addr)); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case CALL_JUMP_INSTR: { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5; 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case SHORT_IMMEDIATE_INSTR: { 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1)); 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr)); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BYTE_IMMEDIATE_INSTR: { 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]); 9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 2; 9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case NO_INSTR: 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block processed = false; 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); // This type is not implemented. 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block //---------------------------- 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!processed) { 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (*data) { 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC2: 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1)); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x6B: { 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintOperands("imul", REG_OPER_OP_ORDER, data); 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%d", *data); 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } break; 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x69: { 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintOperands("imul", REG_OPER_OP_ORDER, data); 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data)); 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 4; 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF6: 9907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch { data++; 9917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 9927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 9937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (regop == eax) { 9947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("test_b "); 99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 9967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int32_t imm = *data; 9977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer(",0x%x", imm); 9987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x81: // fall through 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x83: // 0x81 with sign extension bit set 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintImmediateOp(data); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x0F: 10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { byte f0byte = data[1]; 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* f0mnem = F0Mnem(f0byte); 10137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (f0byte == 0x18) { 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 10157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 10167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 10177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const char* suffix[] = {"nta", "1", "2", "3"}; 10187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]); 10197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0) { 10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 3 byte nop. 10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 3; 10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) { 10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 4 byte nop. 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 4; 10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 && 10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0) { 10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 5 byte nop. 10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 5; 10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 && 10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0 && data[5] == 0 && data[6] == 0) { 10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 7 byte nop. 10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 7; 10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 && 10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0 && data[5] == 0 && data[6] == 0 && 10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[7] == 0) { 10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 8 byte nop. 10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 8; 10397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (f0byte == 0xA2 || f0byte == 0x31) { 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", f0mnem); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 10420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (f0byte == 0x28) { 10430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 10440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int mod, regop, rm; 10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen get_modrm(*data, &mod, ®op, &rm); 10460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("movaps %s,%s", 10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 10480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 10490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data++; 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte >= 0x53 && f0byte <= 0x5F) { 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const pseudo_op[] = { 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "rcpps", 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "andps", 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "andnps", 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "orps", 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "xorps", 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "addps", 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "mulps", 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "cvtps2pd", 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "cvtdq2ps", 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "subps", 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "minps", 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "divps", 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "maxps", 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data += 2; 1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s %s,", 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pseudo_op[f0byte - 0x53], 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop)); 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightXMMOperand(data); 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte == 0x50) { 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("movmskps %s,%s", 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfCPURegister(regop), 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NameOfXMMRegister(rm)); 1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data++; 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte== 0xC6) { 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // shufps xmm, xmm/m128, imm8 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("shufps %s,%s,%d", 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(rm), 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(imm8)); 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x80) { 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditional(data, branch_hint); 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f0byte == 0xB7 || f0byte == 0xAF) { 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x90) { 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += SetCC(data); 11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if ((f0byte & 0xF0) == 0x40) { 11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data += CMov(data); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) { 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // shrd, shld, bts 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", f0mnem); 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightOperand(data); 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (f0byte == 0xAB) { 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%s", NameOfCPURegister(regop)); 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte == 0xBD) { 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop)); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightOperand(data); 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UnimplementedInstruction(); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x8F: 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == eax) { 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("pop "); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFF: 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esi: mnem = "push"; break; 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case eax: mnem = "inc"; break; 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ecx: mnem = "dec"; break; 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case edx: mnem = "call"; break; 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esp: mnem = "jmp"; break; 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: mnem = "???"; 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC7: // imm32, fall through 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC6: // imm8 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0xC6; 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *data; 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data++; 116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data); 117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 4; 117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x80: 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* mnem = NULL; 1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (regop) { 1182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 5: mnem = "subb"; break; 1183e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 7: mnem = "cmpb"; break; 1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke default: UnimplementedInstruction(); 1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("%s ", mnem); 118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data; 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x88: // 8bit, fall through 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x89: // 32bit 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0x88; 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 120044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 120144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 120244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x66: // prefix 12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (*data == 0x66) data++; 12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*data == 0xf && data[1] == 0x1f) { 12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 0x66 prefix 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x90) { 12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 0x66 prefix 12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x8B) { 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x89) { 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov_w "); 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*data == 0xC7) { 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", "mov_w"); 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightOperand(data); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm = *reinterpret_cast<int16_t*>(data); 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",0x%x", imm); 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (*data == 0x0F) { 12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x38) { 12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x17) { 12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("ptest %s,%s", 12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 12477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0x2A) { 12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // movntdqa 12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 12507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop)); 12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x3A) { 1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 125969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*data == 0x0B) { 126069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data++; 126169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int mod, regop, rm; 126269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 126369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AppendToBuffer("roundsd %s,%s,%d", 126569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(regop), 126669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(rm), 126769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static_cast<int>(imm8)); 126869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data += 2; 126969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (*data == 0x16) { 1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pextrd %s,%s,%d", 12751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(regop), 1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x17) { 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data++; 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mod, regop, rm; 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch get_modrm(*data, &mod, ®op, &rm); 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("extractps %s,%s,%d", 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfCPURegister(rm), 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<int>(imm8)); 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 2; 12891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (*data == 0x22) { 12901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data++; 12911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int mod, regop, rm; 12921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block get_modrm(*data, &mod, ®op, &rm); 12931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int8_t imm8 = static_cast<int8_t>(data[1]); 12941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("pinsrd %s,%s,%d", 12951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfXMMRegister(regop), 12961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(rm), 12971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<int>(imm8)); 12981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data += 2; 1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UnimplementedInstruction(); 1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x2E || *data == 0x2F) { 13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd"; 13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int mod, regop, rm; 13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block get_modrm(*data, &mod, ®op, &rm); 13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mod == 0x3) { 13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,%s", mnem, 13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 13156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x50) { 13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 13196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 13206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movmskpd %s,%s", 13216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfCPURegister(regop), 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block NameOfXMMRegister(rm)); 13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x54) { 1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("andpd %s,%s", 1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*data == 0x56) { 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("orpd %s,%s", 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(rm)); 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x57) { 1341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("xorpd %s,%s", 1345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(regop), 1346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(rm)); 1347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x6E) { 13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movd %s,", NameOfXMMRegister(regop)); 13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 1354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x6F) { 1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop)); 135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x70) { 1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pshufd %s,%s,%d", 1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*data == 0x76) { 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("pcmpeqd %s,%s", 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(rm)); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x90) { 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data++; 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 2 byte nop. 1381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xF3) { 1382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1383b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psllq %s,%s", 1386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x73) { 1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(regop == esi || regop == edx); 1395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("%s %s,%d", 1396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch (regop == esi) ? "psllq" : "psrlq", 1397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xD3) { 1401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psrlq %s,%s", 1405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x7F) { 1409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa "); 1410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 141344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x7E) { 1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("movd "); 1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += PrintRightOperand(data); 1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0xDB) { 1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pand %s,%s", 1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 14307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0xE7) { 14317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 143444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (mod == 3) { 143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movntdq "); 143644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 143744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 143844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 143944f0eee88ff00398ff7f715fab053374d808c90dSteve Block UnimplementedInstruction(); 144044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0xEF) { 1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pxor %s,%s", 1446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xEB) { 1450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("por %s,%s", 1454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UnimplementedInstruction(); 14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFE: 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 14690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (regop == ecx) { 14700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("dec_b "); 14710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += PrintRightOperand(data); 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x68: 1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1)); 1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6A: 1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA8: 1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1)); 1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA9: 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1)); 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD1: // fall through 1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD3: // fall through 1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC1: 1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += D1D3C1Instruction(data); 1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xD8: // fall through 1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD9: // fall through 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDA: // fall through 1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDB: // fall through 1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDC: // fall through 1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDD: // fall through 1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDE: // fall through 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDF: 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += FPUInstruction(data); 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEB: 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpShort(data); 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF2: 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*(data+1) == 0x0F) { 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b2 = *(data+2); 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x11) { 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd "); 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 152744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b2 == 0x10) { 1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd %s,", NameOfXMMRegister(regop)); 153444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 153644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 153744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 153844f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 153944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop)); 154044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (b2) { 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x2A: mnem = "cvtsi2sd"; break; 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x2C: mnem = "cvttsd2si"; break; 1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x2D: mnem = "cvtsd2si"; break; 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x51: mnem = "sqrtsd"; break; 1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x58: mnem = "addsd"; break; 1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x59: mnem = "mulsd"; break; 1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5C: mnem = "subsd"; break; 1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5E: mnem = "divsd"; break; 1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x2A) { 155744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 155844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (b2 == 0x2C || b2 == 0x2D) { 156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 156144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 15620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (b2 == 0xC2) { 15630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Intel manual 2A, Table 3-18. 15640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const char* const pseudo_op[] = { 15650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpeqsd", 15660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpltsd", 15670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmplesd", 15680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpunordsd", 15690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpneqsd", 15700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnltsd", 15710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnlesd", 15720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpordsd" 15730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen }; 15740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("%s %s,%s", 15750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen pseudo_op[data[1]], 15760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 15770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 15780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 158044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 158144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF3: 1590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (*(data+1) == 0x0F) { 159144f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte b2 = *(data+2); 159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (b2 == 0x11) { 159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss "); 1594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 159544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 159644f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x10) { 16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 3; 16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 16026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 160344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss %s,", NameOfXMMRegister(regop)); 160444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 160544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x2C) { 160644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 160944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop)); 161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 161144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 161244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 161444f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 161544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 161644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (b2 == 0x6F) { 1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop)); 162244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (b2 == 0x7F) { 1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu "); 1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UnimplementedInstruction(); 1632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*(data+1) == 0xA5) { 1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 2; 1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("rep_movs"); 16366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*(data+1) == 0xAB) { 16376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 2; 16386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("rep_stos"); 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += F7Instruction(data); 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[tmp_buffer_pos_] = '\0'; 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instr_len = data - instr; 1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (instr_len == 0) { 1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%02x", *data); 1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr_len > 0); // Ensure progress. 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int outp = 0; 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bytes. 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = instr; bp < data; bp++) { 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outp += v8::internal::SNPrintF(out_buffer + outp, 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%02x", 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *bp); 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - instr_len; i >= 0; i--) { 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outp += v8::internal::SNPrintF(out_buffer + outp, " "); 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outp += v8::internal::SNPrintF(out_buffer + outp, 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " %s", 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tmp_buffer_.start()); 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr_len; 16780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} // NOLINT (function is too long) 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[8] = { 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[8] = { 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[8] = { 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 170144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return cpu_regs[reg]; 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return byte_cpu_regs[reg]; 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return xmm_regs[reg]; 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IA32 does not embed debug strings at the moment. 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(buffer, instruction); 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools. 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p", prev_pc); 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = prev_pc; bp < pc; bp++) { 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%02x", *bp); 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " %s\n", buffer.start()); 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1780