disasm-ia32.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
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), 249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte0_(0), 250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte1_(0), 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte2_(0), 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instruction_table_(InstructionTable::get_instance()), 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_(0), 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort_on_unimplemented_(abort_on_unimplemented) { 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[0] = '\0'; 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~DisassemblerIA32() {} 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Writes one disassembled instruction into 'buffer' (0-terminated). 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the length of the disassembled machine instruction in bytes. 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const NameConverter& converter_; 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte vex_byte0_; // 0xc4 or 0xc5 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte vex_byte1_; 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte vex_byte2_; // only for 3 bytes vex prefix 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InstructionTable* instruction_table_; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> tmp_buffer_; 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int tmp_buffer_pos_; 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool abort_on_unimplemented_; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block eax = 0, 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ecx = 1, 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edx = 2, 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebx = 3, 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esp = 4, 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ebp = 5, 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block esi = 6, 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block edi = 7 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block enum ShiftOpcodeExtension { 287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROL = 0, 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kROR = 1, 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCL = 2, 290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kRCR = 3, 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSHL = 4, 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block KSHR = 5, 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kSAR = 7 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_128() { 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5); 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_; 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (checked & 4) != 1; 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_66() { 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5); 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_; 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (checked & 3) == 1; 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_f3() { 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5); 310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_; 311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (checked & 3) == 2; 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_f2() { 315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5); 316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_; 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (checked & 3) == 3; 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_w() { 321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (vex_byte0_ == 0xc5) return false; 322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (vex_byte2_ & 0x80) != 0; 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_0f() { 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (vex_byte0_ == 0xc5) return true; 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (vex_byte1_ & 3) == 1; 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_0f38() { 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (vex_byte0_ == 0xc5) return false; 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (vex_byte1_ & 3) == 2; 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool vex_0f3a() { 336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (vex_byte0_ == 0xc5) return false; 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return (vex_byte1_ & 3) == 3; 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int vex_vreg() { 341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5); 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_; 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return ~(checked >> 3) & 0xf; 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier char float_size_code() { return "sd"[vex_w()]; } 347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfCPURegister(int reg) const { 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfCPURegister(reg); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfByteCPURegister(int reg) const { 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfByteCPURegister(reg); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfXMMRegister(int reg) const { 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfXMMRegister(reg); 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(byte* addr) const { 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return converter_.NameOfAddress(addr); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Disassembler helper functions. 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_modrm(byte data, int* mod, int* regop, int* rm) { 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *mod = (data >> 6) & 3; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *regop = (data & 0x38) >> 3; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *rm = data & 7; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void get_sib(byte data, int* scale, int* index, int* base) { 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *scale = (data >> 6) & 3; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *index = (data >> 3) & 7; 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *base = data & 7; 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const; 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightOperand(byte* modrmp); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintRightByteOperand(byte* modrmp); 38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int PrintRightXMMOperand(byte* modrmp); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int PrintImmediateOp(byte* data); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int F7Instruction(byte* data); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int D1D3C1Instruction(byte* data); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpShort(byte* data); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditional(byte* data, const char* comment); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int JumpConditionalShort(byte* data, const char* comment); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int SetCC(byte* data); 3963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int CMov(byte* data); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int FPUInstruction(byte* data); 398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start); 399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int RegisterFPUInstruction(int escape_opcode, byte modrm_byte); 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int AVXInstruction(byte* data); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AppendToBuffer(const char* format, ...); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void UnimplementedInstruction() { 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (abort_on_unimplemented_) { 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("'Unimplemented Instruction'"); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) { 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = v8::internal::VSNPrintF(buf, format, args); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ += result; 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper( 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* modrmp, 42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping direct_register_name) { 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*modrmp, &mod, ®op, &rm); 42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block RegisterNameMapping register_name = (mod == 3) ? direct_register_name : 42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfCPURegister; 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (mod) { 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == ebp) { 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[0x%x]", disp); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 5; 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (rm == esp) { 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == esp && base == esp && scale == 0 /*times_1*/) { 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (base == ebp) { 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s*%d%s0x%x]", 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (index != esp && base != ebp) { 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [base+index*scale] 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s+%s*%d]", 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("[%s]", (this->*register_name)(rm)); 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: // fall through 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (rm == esp) { 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte sib = *(modrmp + 1); 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int scale, index, base; 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_sib(sib, &scale, &index, &base); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : *reinterpret_cast<int8_t*>(modrmp + 2); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s%s0x%x]", 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (this->*register_name)(rm), 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s+%s*%d%s0x%x]", 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(base), 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block (this->*register_name)(index), 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1 << scale, 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 6 : 3; 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No sib. 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : *reinterpret_cast<int8_t*>(modrmp + 1); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("[%s%s0x%x]", 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (this->*register_name)(rm), 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? "-" : "+", 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disp < 0 ? -disp : disp); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mod == 2 ? 5 : 2; 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 3: 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", (this->*register_name)(rm)); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1; 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) { 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) { 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return PrintRightOperandHelper(modrmp, 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &DisassemblerIA32::NameOfByteCPURegister); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) { 52344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return PrintRightOperandHelper(modrmp, 52444f0eee88ff00398ff7f715fab053374d808c90dSteve Block &DisassemblerIA32::NameOfXMMRegister); 52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data. 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem, 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OperandOrder op_order, 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data) { 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *data; 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int advance = 0; 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (op_order) { 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case REG_OPER_OP_ORDER: { 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case OPER_REG_OP_ORDER: { 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block advance = PrintRightOperand(data); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return advance; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte. 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'. 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) { 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool sign_extension_bit = (*data & 0x02) != 0; 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte modrm = *(data+1); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "Imm???"; 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0: mnem = "add"; break; 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 1: mnem = "or"; break; 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 2: mnem = "adc"; break; 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 4: mnem = "and"; break; 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 5: mnem = "sub"; break; 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 6: mnem = "xor"; break; 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 7: mnem = "cmp"; break; 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int count = PrintRightOperand(data+1); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (sign_extension_bit) { 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *(data + 1 + count)); 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 1 /*int8*/; 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 1 + count + 4 /*int32_t*/; 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) { 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0xF7, *data); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte modrm = *++data; 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* mnem = NULL; 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (regop) { 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0: 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "test"; 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "not"; 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 3: 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "neg"; 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 4: 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "mul"; 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 5: 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "imul"; 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 6: 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "div"; 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 7: 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "idiv"; 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UnimplementedInstruction(); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", mnem); 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count = PrintRightOperand(data); 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (regop == 0) { 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count)); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count += 4; 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 + count; 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) { 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte op = *data; 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1); 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte modrm = *++data; 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(modrm, &mod, ®op, &rm); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int imm8 = -1; 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* mnem = NULL; 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (regop) { 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kROL: 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "rol"; 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kROR: 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "ror"; 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRCL: 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "rcl"; 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRCR: 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "rcr"; 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSHL: 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "shl"; 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KSHR: 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "shr"; 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSAR: 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mnem = "sar"; 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UnimplementedInstruction(); 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", mnem); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count = PrintRightOperand(data); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (op == 0xD1) { 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm8 = 1; 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == 0xC1) { 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm8 = *(data + 1); 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count++; 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == 0xD3) { 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shift/rotate by cl. 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (imm8 >= 0) { 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%d", imm8); 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",cl"); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 + count; 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) { 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0xEB, *data); 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("jmp %s", NameOfAddress(dest)); 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) { 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0x0F, *data); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 6; // includes 0x0F 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *data & 0x0F; 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b = *(data+1); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* dest = data + static_cast<int8_t>(b) + 2; 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = jump_conditional_mnem[cond]; 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (comment != NULL) { 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(", %s", comment); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) { 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0x0F, *data); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte cond = *(data+1) & 0x0F; 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = set_conditional_mnem[cond]; 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintRightByteOperand(data+2); 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 3; // Includes 0x0F. 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data. 7313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) { 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0x0F, *data); 7333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block byte cond = *(data + 1) & 0x0F; 7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block const char* mnem = conditional_move_mnem[cond]; 7353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); 7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return 2 + op_size; // includes 0x0F 7373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 7383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint DisassemblerIA32::AVXInstruction(byte* data) { 741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte opcode = *data; 742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte* current = data + 1; 743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (vex_66() && vex_0f38()) { 744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm, vvvv = vex_vreg(); 745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*current, &mod, ®op, &rm); 746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (opcode) { 747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x99: 748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(), 749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xa9: 753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(), 754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xb9: 758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(), 759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x9b: 763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(), 764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xab: 768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(), 769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xbb: 773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(), 774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x9d: 778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(), 779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xad: 783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(), 784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xbd: 788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(), 789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x9f: 793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(), 794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xaf: 798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(), 799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0xbf: 803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(), 804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); 805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier default: 808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UnimplementedInstruction(); 809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (vex_f2() && vex_0f()) { 811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm, vvvv = vex_vreg(); 812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*current, &mod, ®op, &rm); 813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (opcode) { 814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x58: 815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop), 816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(vvvv)); 817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x59: 820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop), 821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(vvvv)); 822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x5c: 825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop), 826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(vvvv)); 827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case 0x5e: 830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop), 831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(vvvv)); 832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier current += PrintRightXMMOperand(current); 833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier default: 835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UnimplementedInstruction(); 836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UnimplementedInstruction(); 839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return static_cast<int>(current - data); 842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data. 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) { 847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte escape_opcode = *data; 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0xD8, escape_opcode & 0xF8); 849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte = *(data+1); 850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte >= 0xC0) { 852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return RegisterFPUInstruction(escape_opcode, modrm_byte); 853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); 855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, 859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int modrm_byte, 860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte* modrm_start) { 861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. 863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: switch (regop) { 865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_s"; break; 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 2: mnem = "fst_s"; break; 867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_s"; break; 868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fstcw"; break; 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: switch (regop) { 874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fild_s"; break; 875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 1: mnem = "fisttp_s"; break; 876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 2: mnem = "fist_s"; break; 877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fistp_s"; break; 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: UnimplementedInstruction(); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: switch (regop) { 883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0: mnem = "fld_d"; break; 8840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 1: mnem = "fisttp_d"; break; 8850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 2: mnem = "fst_d"; break; 886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 3: mnem = "fstp_d"; break; 887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: switch (regop) { 892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 5: mnem = "fild_d"; break; 893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 7: mnem = "fistp_d"; break; 894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s ", mnem); 901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int count = PrintRightOperand(modrm_start); 902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return count + 1; 903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, 906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block byte modrm_byte) { 907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool has_register = false; // Is the FPU register encoded in modrm_byte? 908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const char* mnem = "?"; 909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (escape_opcode) { 911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch has_register = true; 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (modrm_byte & 0xF8) { 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xC0: mnem = "fadd_i"; break; 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xE0: mnem = "fsub_i"; break; 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xC8: mnem = "fmul_i"; break; 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xF0: mnem = "fdiv_i"; break; 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: UnimplementedInstruction(); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD9: 923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 9240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case 0xC0: 9250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen mnem = "fld"; 9260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen has_register = true; 9270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: 929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fxch"; 930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte) { 934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE0: mnem = "fchs"; break; 935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE1: mnem = "fabs"; break; 936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE4: mnem = "ftst"; break; 937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fld1"; break; 938402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case 0xEB: mnem = "fldpi"; break; 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xED: mnem = "fldln2"; break; 940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xEE: mnem = "fldz"; break; 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xF0: mnem = "f2xm1"; break; 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case 0xF1: mnem = "fyl2x"; break; 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xF4: mnem = "fxtract"; break; 944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF5: mnem = "fprem1"; break; 945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF7: mnem = "fincstp"; break; 946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fprem"; break; 9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFC: mnem = "frndint"; break; 9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case 0xFD: mnem = "fscale"; break; 949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFE: mnem = "fsin"; break; 950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xFF: mnem = "fcos"; break; 951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDA: 957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE9) { 958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucompp"; 959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDB: 965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if ((modrm_byte & 0xF8) == 0xE8) { 966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomi"; 967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if (modrm_byte == 0xE2) { 969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fclex"; 9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (modrm_byte == 0xE3) { 9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mnem = "fninit"; 972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UnimplementedInstruction(); 974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDC: 978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 979d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "fadd"; break; 981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsub"; break; 982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmul"; break; 983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdiv"; break; 984d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDD: 989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "ffree"; break; 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xD0: mnem = "fst"; break; 993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xD8: mnem = "fstp"; break; 994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 998d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDE: 999d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xD9) { 1000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fcompp"; 1001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 1003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (modrm_byte & 0xF8) { 1004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC0: mnem = "faddp"; break; 1005d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xE8: mnem = "fsubp"; break; 1006d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xC8: mnem = "fmulp"; break; 1007d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xF8: mnem = "fdivp"; break; 1008d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 1009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case 0xDF: 1014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (modrm_byte == 0xE0) { 1015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fnstsw_ax"; 1016d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else if ((modrm_byte & 0xF8) == 0xE8) { 1017d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mnem = "fucomip"; 1018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block has_register = true; 1019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1020d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: UnimplementedInstruction(); 1023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (has_register) { 1026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); 1027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", mnem); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 2; 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte. 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here. 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) { 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (f0byte) { 10387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch case 0x18: return "prefetch"; 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA2: return "cpuid"; 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBE: return "movsx_b"; 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xBF: return "movsx_w"; 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB6: return "movzx_b"; 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xB7: return "movzx_w"; 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAF: return "imul"; 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA5: return "shld"; 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAD: return "shrd"; 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xAC: return "shrd"; // 3-operand version. 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xAB: return "bts"; 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xBD: return "bsr"; 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: return NULL; 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'. 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instr) { 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_pos_ = 0; // starting to write as position 0 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* data = instr; 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for hints. 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* branch_hint = NULL; 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We use these two prefixes only with branch prediction 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*data == 0x3E /*ds*/) { 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted taken"; 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x2E /*cs*/) { 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block branch_hint = "predicted not taken"; 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (*data == 0xC4 && *(data + 1) >= 0xc0) { 1070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte0_ = *data; 1071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte1_ = *(data + 1); 1072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte2_ = *(data + 2); 1073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 3; 1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (*data == 0xC5 && *(data + 1) >= 0xc0) { 1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte0_ = *data; 1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier vex_byte1_ = *(data + 1); 1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 2; 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool processed = true; // Will be set to false if the current instruction 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is not in 'instructions' table. 1082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Decode AVX instructions. 1083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (vex_byte0_ != 0) { 1084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += AVXInstruction(data); 1085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier const InstructionDesc& idesc = instruction_table_->Get(*data); 1087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (idesc.type) { 1088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case ZERO_OPERANDS_INSTR: 1089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer(idesc.mnem); 1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data++; 1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case TWO_OPERANDS_INSTR: 1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data++; 1095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += PrintOperands(idesc.mnem, idesc.op_order_, data); 1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case JUMP_CONDITIONAL_SHORT_INSTR: 1099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += JumpConditionalShort(data, branch_hint); 1100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case REGISTER_INSTR: 1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07)); 1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data++; 1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case MOVE_REG_INSTR: { 1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte* addr = 1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07), 1111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfAddress(addr)); 1112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 5; 1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case CALL_JUMP_INSTR: { 1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5; 1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr)); 1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 5; 1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case SHORT_IMMEDIATE_INSTR: { 1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier byte* addr = 1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); 1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr)); 1127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 5; 1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case BYTE_IMMEDIATE_INSTR: { 1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]); 1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 2; 1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NO_INSTR: 1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier processed = false; 1139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier default: 1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNIMPLEMENTED(); // This type is not implemented. 1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block //---------------------------- 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!processed) { 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (*data) { 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC2: 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1)); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x6B: { 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintOperands("imul", REG_OPER_OP_ORDER, data); 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%d", *data); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } break; 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x69: { 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintOperands("imul", REG_OPER_OP_ORDER, data); 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data)); 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 4; 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF6: 11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch { data++; 11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (regop == eax) { 11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("test_b "); 117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int32_t imm = *data; 11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer(",0x%x", imm); 11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x81: // fall through 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x83: // 0x81 with sign extension bit set 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintImmediateOp(data); 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x0F: 11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { byte f0byte = data[1]; 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* f0mnem = F0Mnem(f0byte); 11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch if (f0byte == 0x18) { 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch const char* suffix[] = {"nta", "1", "2", "3"}; 11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]); 11987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0) { 12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 3 byte nop. 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 3; 12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) { 12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 4 byte nop. 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 4; 12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 && 12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0) { 12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 5 byte nop. 12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 5; 12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 && 12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0 && data[5] == 0 && data[6] == 0) { 12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 7 byte nop. 12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 7; 12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 && 12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[4] == 0 && data[5] == 0 && data[6] == 0 && 12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data[7] == 0) { 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 8 byte nop. 12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 8; 12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (f0byte == 0xA2 || f0byte == 0x31) { 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s", f0mnem); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 12210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (f0byte == 0x28) { 12220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 12230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int mod, regop, rm; 12240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen get_modrm(*data, &mod, ®op, &rm); 12250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("movaps %s,%s", 12260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 12270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 12280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data++; 1229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (f0byte == 0x2e) { 1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 2; 1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm; 1232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*data, &mod, ®op, &rm); 1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop)); 1234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += PrintRightXMMOperand(data); 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte >= 0x53 && f0byte <= 0x5F) { 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const pseudo_op[] = { 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "rcpps", 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "andps", 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "andnps", 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "orps", 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "xorps", 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "addps", 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "mulps", 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "cvtps2pd", 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "cvtdq2ps", 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "subps", 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "minps", 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "divps", 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "maxps", 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data += 2; 1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int mod, regop, rm; 1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s %s,", 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pseudo_op[f0byte - 0x53], 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop)); 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightXMMOperand(data); 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte == 0x50) { 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("movmskps %s,%s", 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfCPURegister(regop), 1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NameOfXMMRegister(rm)); 1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch data++; 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte== 0xC6) { 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // shufps xmm, xmm/m128, imm8 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("shufps %s,%s,%d", 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(rm), 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(imm8)); 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x80) { 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpConditional(data, branch_hint); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f0byte == 0xB7 || f0byte == 0xAF) { 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if ((f0byte & 0xF0) == 0x90) { 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += SetCC(data); 12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if ((f0byte & 0xF0) == 0x40) { 12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data += CMov(data); 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) { 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // shrd, shld, bts 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", f0mnem); 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightOperand(data); 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (f0byte == 0xAB) { 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%s", NameOfCPURegister(regop)); 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",%s,cl", NameOfCPURegister(regop)); 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (f0byte == 0xBD) { 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop)); 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightOperand(data); 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UnimplementedInstruction(); 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x8F: 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (regop == eax) { 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("pop "); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFF: 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = NULL; 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (regop) { 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esi: mnem = "push"; break; 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case eax: mnem = "inc"; break; 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case ecx: mnem = "dec"; break; 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case edx: mnem = "call"; break; 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case esp: mnem = "jmp"; break; 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: mnem = "???"; 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("%s ", mnem); 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC7: // imm32, fall through 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC6: // imm8 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0xC6; 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *data; 134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data++; 135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t imm = *reinterpret_cast<int32_t*>(data); 135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",0x%x", imm); 135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 4; 135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x80: 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke const char* mnem = NULL; 1366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (regop) { 1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 5: mnem = "subb"; break; 1368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 7: mnem = "cmpb"; break; 1369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke default: UnimplementedInstruction(); 1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("%s ", mnem); 137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int32_t imm = *data; 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",0x%x", imm); 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x88: // 8bit, fall through 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x89: // 32bit 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { bool is_byte = *data == 0x88; 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (is_byte) { 138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov_b"); 138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightByteOperand(data); 138844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfByteCPURegister(regop)); 138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s ", "mov"); 139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x66: // prefix 13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (*data == 0x66) data++; 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*data == 0xf && data[1] == 0x1f) { 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 0x66 prefix 14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x90) { 14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 0x66 prefix 14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x8B) { 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (*data == 0x89) { 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data++; 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("mov_w "); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += PrintRightOperand(data); 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfCPURegister(regop)); 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*data == 0xC7) { 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("%s ", "mov_w"); 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += PrintRightOperand(data); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm = *reinterpret_cast<int16_t*>(data); 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer(",0x%x", imm); 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data += 2; 14203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else if (*data == 0x0F) { 14213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x38) { 14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*data == 0x17) { 14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("ptest %s,%s", 14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0x2A) { 14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // movntdqa 14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 14367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 14377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop)); 14387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data += PrintRightOperand(data); 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UnimplementedInstruction(); 14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x3A) { 1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 144469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*data == 0x0B) { 144569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data++; 144669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int mod, regop, rm; 144769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 144869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 144969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AppendToBuffer("roundsd %s,%s,%d", 145069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(regop), 145169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch NameOfXMMRegister(rm), 145269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static_cast<int>(imm8)); 145369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch data += 2; 145469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (*data == 0x16) { 1455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pextrd %s,%s,%d", 14601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(regop), 1461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x17) { 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data++; 14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int mod, regop, rm; 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch get_modrm(*data, &mod, ®op, &rm); 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("extractps %s,%s,%d", 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfCPURegister(rm), 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<int>(imm8)); 14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data += 2; 14741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (*data == 0x22) { 14751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data++; 14761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int mod, regop, rm; 14771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block get_modrm(*data, &mod, ®op, &rm); 14781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int8_t imm8 = static_cast<int8_t>(data[1]); 14791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AppendToBuffer("pinsrd %s,%s,%d", 14801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfXMMRegister(regop), 14811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NameOfCPURegister(rm), 14821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<int>(imm8)); 14831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block data += 2; 1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UnimplementedInstruction(); 1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x2E || *data == 0x2F) { 14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd"; 14893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 14903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int mod, regop, rm; 14913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block get_modrm(*data, &mod, ®op, &rm); 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mod == 0x3) { 14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,%s", mnem, 14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(regop), 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfXMMRegister(rm)); 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x50) { 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movmskpd %s,%s", 15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block NameOfCPURegister(regop), 15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block NameOfXMMRegister(rm)); 15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block data++; 1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x54) { 1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("andpd %s,%s", 1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*data == 0x56) { 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("orpd %s,%s", 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(rm)); 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x57) { 1526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("xorpd %s,%s", 1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(regop), 1531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke NameOfXMMRegister(rm)); 1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0x6E) { 15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data++; 15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("movd %s,", NameOfXMMRegister(regop)); 15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += PrintRightOperand(data); 1539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x6F) { 1540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop)); 154444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x70) { 1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pshufd %s,%s,%d", 1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*data == 0x76) { 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mod, regop, rm; 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch get_modrm(*data, &mod, ®op, &rm); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AppendToBuffer("pcmpeqd %s,%s", 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(regop), 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameOfXMMRegister(rm)); 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data++; 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (*data == 0x90) { 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch data++; 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AppendToBuffer("nop"); // 2 byte nop. 1566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xF3) { 1567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psllq %s,%s", 1571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (*data == 0x72) { 1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data++; 1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm; 1577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*data, &mod, ®op, &rm); 1578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int8_t imm8 = static_cast<int8_t>(data[1]); 1579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(regop == esi || regop == edx); 1580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld", 1581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier NameOfXMMRegister(rm), static_cast<int>(imm8)); 1582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 2; 1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x73) { 1584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int8_t imm8 = static_cast<int8_t>(data[1]); 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(regop == esi || regop == edx); 1589b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("%s %s,%d", 1590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch (regop == esi) ? "psllq" : "psrlq", 1591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm), 1592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(imm8)); 1593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += 2; 1594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xD3) { 1595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("psrlq %s,%s", 1599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*data == 0x7F) { 1603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqa "); 1604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data++; 1605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0x7E) { 1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("movd "); 1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data += PrintRightOperand(data); 1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (*data == 0xDB) { 1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pand %s,%s", 1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 16247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else if (*data == 0xE7) { 16257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch data++; 16267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch int mod, regop, rm; 16277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch get_modrm(*data, &mod, ®op, &rm); 162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (mod == 3) { 162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movntdq "); 163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 163344f0eee88ff00398ff7f715fab053374d808c90dSteve Block UnimplementedInstruction(); 163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 16356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*data == 0xEF) { 1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int mod, regop, rm; 1638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendToBuffer("pxor %s,%s", 1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(regop), 1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NameOfXMMRegister(rm)); 1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data++; 1643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (*data == 0xEB) { 1644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 1645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int mod, regop, rm; 1646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch get_modrm(*data, &mod, ®op, &rm); 1647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AppendToBuffer("por %s,%s", 1648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(regop), 1649b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch NameOfXMMRegister(rm)); 1650b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data++; 16513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block UnimplementedInstruction(); 16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xFE: 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { data++; 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 16630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (regop == ecx) { 16640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("dec_b "); 16650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += PrintRightOperand(data); 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x68: 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1)); 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x6A: 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA8: 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1)); 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 2; 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xA9: 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1)); 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 5; 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD1: // fall through 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD3: // fall through 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xC1: 1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += D1D3C1Instruction(data); 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0xD8: // fall through 1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xD9: // fall through 1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDA: // fall through 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDB: // fall through 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDC: // fall through 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDD: // fall through 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDE: // fall through 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xDF: 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += FPUInstruction(data); 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xEB: 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += JumpShort(data); 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF2: 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*(data+1) == 0x0F) { 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte b2 = *(data+2); 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x11) { 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd "); 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 172144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (b2 == 0x10) { 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AppendToBuffer("movsd %s,", NameOfXMMRegister(regop)); 172844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 172944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 173044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 173144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 173244f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 173344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop)); 173444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* mnem = "?"; 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (b2) { 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x2A: mnem = "cvtsi2sd"; break; 17396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x2C: mnem = "cvttsd2si"; break; 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0x2D: mnem = "cvtsd2si"; break; 17416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case 0x51: mnem = "sqrtsd"; break; 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x58: mnem = "addsd"; break; 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x59: mnem = "mulsd"; break; 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5C: mnem = "subsd"; break; 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0x5E: mnem = "divsd"; break; 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += 3; 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mod, regop, rm; 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block get_modrm(*data, &mod, ®op, &rm); 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (b2 == 0x2A) { 175144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 175244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightOperand(data); 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (b2 == 0x2C || b2 == 0x2D) { 175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); 175544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 17560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (b2 == 0xC2) { 17570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Intel manual 2A, Table 3-18. 17580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const char* const pseudo_op[] = { 17590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpeqsd", 17600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpltsd", 17610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmplesd", 17620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpunordsd", 17630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpneqsd", 17640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnltsd", 17650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpnlesd", 17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "cmpordsd" 17670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen }; 17680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AppendToBuffer("%s %s,%s", 17690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen pseudo_op[data[1]], 17700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(regop), 17710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen NameOfXMMRegister(rm)); 17720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen data += 2; 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 177444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop)); 177544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF3: 1784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (*(data+1) == 0x0F) { 178544f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte b2 = *(data+2); 178644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (b2 == 0x11) { 178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss "); 1788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 178944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 179144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 179244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer(",%s", NameOfXMMRegister(regop)); 179344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x10) { 17946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 3; 17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int mod, regop, rm; 17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_modrm(*data, &mod, ®op, &rm); 179744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("movss %s,", NameOfXMMRegister(regop)); 179844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 179944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x2C) { 180044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 180144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 180244f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 180344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop)); 180444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (b2 == 0x58) { 1806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 3; 1807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm; 1808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*data, &mod, ®op, &rm); 1809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("addss %s,", NameOfXMMRegister(regop)); 1810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += PrintRightXMMOperand(data); 1811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (b2 == 0x59) { 1812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 3; 1813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm; 1814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*data, &mod, ®op, &rm); 1815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("mulss %s,", NameOfXMMRegister(regop)); 1816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += PrintRightXMMOperand(data); 181744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (b2 == 0x5A) { 181844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += 3; 181944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int mod, regop, rm; 182044f0eee88ff00398ff7f715fab053374d808c90dSteve Block get_modrm(*data, &mod, ®op, &rm); 182144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop)); 182244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (b2 == 0x5c) { 1824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 3; 1825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm; 1826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*data, &mod, ®op, &rm); 1827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("subss %s,", NameOfXMMRegister(regop)); 1828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += PrintRightXMMOperand(data); 1829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (b2 == 0x5e) { 1830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += 3; 1831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int mod, regop, rm; 1832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier get_modrm(*data, &mod, ®op, &rm); 1833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AppendToBuffer("divss %s,", NameOfXMMRegister(regop)); 1834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier data += PrintRightXMMOperand(data); 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (b2 == 0x6F) { 1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 1839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop)); 184044f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (b2 == 0x7F) { 1842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("movdqu "); 1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 3; 1844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int mod, regop, rm; 1845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke get_modrm(*data, &mod, ®op, &rm); 184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data += PrintRightXMMOperand(data); 1847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer(",%s", NameOfXMMRegister(regop)); 1848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 1849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UnimplementedInstruction(); 1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else if (*(data+1) == 0xA5) { 1852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke data += 2; 1853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke AppendToBuffer("rep_movs"); 18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (*(data+1) == 0xAB) { 18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += 2; 18566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AppendToBuffer("rep_stos"); 1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0xF7: 1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data += F7Instruction(data); 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnimplementedInstruction(); 1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tmp_buffer_pos_ < sizeof tmp_buffer_) { 1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tmp_buffer_[tmp_buffer_pos_] = '\0'; 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instr_len = data - instr; 1876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (instr_len == 0) { 1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke printf("%02x", *data); 1878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr_len > 0); // Ensure progress. 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int outp = 0; 1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instruction bytes. 1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = instr; bp < data; bp++) { 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outp += v8::internal::SNPrintF(out_buffer + outp, 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%02x", 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *bp); 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - instr_len; i >= 0; i--) { 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outp += v8::internal::SNPrintF(out_buffer + outp, " "); 1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outp += v8::internal::SNPrintF(out_buffer + outp, 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " %s", 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tmp_buffer_.start()); 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return instr_len; 18960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} // NOLINT (function is too long) 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const cpu_regs[8] = { 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const byte_cpu_regs[8] = { 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" 1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const xmm_regs[8] = { 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const { 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 191944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return tmp_buffer_.start(); 1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const { 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NameOfAddress(addr); 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const { 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return cpu_regs[reg]; 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const { 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return byte_cpu_regs[reg]; 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noreg"; 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const { 1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 <= reg && reg < 8) return xmm_regs[reg]; 1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "noxmmreg"; 1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const { 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // IA32 does not embed debug strings at the moment. 1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ""; 1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------ 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter) 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : converter_(converter) {} 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {} 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* instruction) { 1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); 1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d.InstructionDecode(buffer, instruction); 1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools. 1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } 1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NameConverter converter; 1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Disassembler d(converter); 1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* pc = begin; pc < end;) { 1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::internal::EmbeddedVector<char, 128> buffer; 1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[0] = '\0'; 1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* prev_pc = pc; 1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pc += d.InstructionDecode(buffer, pc); 1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%p", prev_pc); 1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (byte* bp = prev_pc; bp < pc; bp++) { 1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, "%02x", *bp); 1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 6 - (pc - prev_pc); i >= 0; i--) { 1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " "); 1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fprintf(f, " %s\n", buffer.start()); 1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace disasm 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1998