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