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