disasm-x64.cc revision 3ce2e2076e8e3e60cf1810eec160ea2d8557e9e7
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 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"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandType {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNSET_OP_ORDER = 0,
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operand size decides between 16, 32 and 64 bit operands.
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fixed 8-bit operands.
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BYTE_SIZE_OPERAND_FLAG = 4,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic {
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int b;  // -1 terminates, otherwise must be in range (0..255)
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandType op_order_;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic two_operands_instr[] = {
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x01, OPER_REG_OP_ORDER,      "add" },
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x03, REG_OPER_OP_ORDER,      "add" },
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x09, OPER_REG_OP_ORDER,      "or" },
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x0B, REG_OPER_OP_ORDER,      "or" },
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x11, OPER_REG_OP_ORDER,      "adc" },
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x13, REG_OPER_OP_ORDER,      "adc" },
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x19, OPER_REG_OP_ORDER,      "sbb" },
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x21, OPER_REG_OP_ORDER,      "and" },
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x23, REG_OPER_OP_ORDER,      "and" },
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x29, OPER_REG_OP_ORDER,      "sub" },
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x2B, REG_OPER_OP_ORDER,      "sub" },
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x31, OPER_REG_OP_ORDER,      "xor" },
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x33, REG_OPER_OP_ORDER,      "xor" },
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x39, OPER_REG_OP_ORDER,      "cmp" },
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x63, REG_OPER_OP_ORDER,      "movsxlq" },
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x85, REG_OPER_OP_ORDER,      "test" },
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x87, REG_OPER_OP_ORDER,      "xchg" },
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x89, OPER_REG_OP_ORDER,      "mov" },
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x8B, REG_OPER_OP_ORDER,      "mov" },
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x8D, REG_OPER_OP_ORDER,      "lea" },
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic zero_operands_instr[] = {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xC3, UNSET_OP_ORDER, "ret" },
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xC9, UNSET_OP_ORDER, "leave" },
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xF4, UNSET_OP_ORDER, "hlt" },
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xCC, UNSET_OP_ORDER, "int3" },
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x60, UNSET_OP_ORDER, "pushad" },
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x61, UNSET_OP_ORDER, "popad" },
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9C, UNSET_OP_ORDER, "pushfd" },
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9D, UNSET_OP_ORDER, "popfd" },
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9E, UNSET_OP_ORDER, "sahf" },
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x99, UNSET_OP_ORDER, "cdq" },
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9B, UNSET_OP_ORDER, "fwait" },
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic call_jump_instr[] = {
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xE8, UNSET_OP_ORDER, "call" },
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xE9, UNSET_OP_ORDER, "jmp" },
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ByteMnemonic short_immediate_instr[] = {
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x05, UNSET_OP_ORDER, "add" },
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x0D, UNSET_OP_ORDER, "or" },
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x15, UNSET_OP_ORDER, "adc" },
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x1D, UNSET_OP_ORDER, "sbb" },
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x25, UNSET_OP_ORDER, "and" },
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x2D, UNSET_OP_ORDER, "sub" },
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x35, UNSET_OP_ORDER, "xor" },
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x3D, UNSET_OP_ORDER, "cmp" },
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* conditional_code_suffix[] = {
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "o", "no", "c", "nc", "z", "nz", "na", "a",
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "s", "ns", "pe", "po", "l", "ge", "le", "g"
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType {
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NO_INSTR,
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZERO_OPERANDS_INSTR,
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TWO_OPERANDS_INSTR,
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JUMP_CONDITIONAL_SHORT_INSTR,
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REGISTER_INSTR,
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MOVE_REG_INSTR,
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CALL_JUMP_INSTR,
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SHORT_IMMEDIATE_INSTR
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionType type;
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandType op_order_;
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool byte_size_operation;  // Fixed 8-bit operation.
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable {
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionTable();
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const InstructionDesc& Get(byte x) const {
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return instructions_[x];
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionDesc instructions_[256];
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Clear();
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Init();
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CopyTable(ByteMnemonic bm[], InstructionType type);
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const char* mnem);
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AddJumpConditionalShort();
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() {
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Clear();
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Init();
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() {
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 256; i++) {
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].mnem = "(bad)";
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].type = NO_INSTR;
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].op_order_ = UNSET_OP_ORDER;
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].byte_size_operation = false;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() {
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddJumpConditionalShort();
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::CopyTable(ByteMnemonic bm[], InstructionType type) {
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; bm[i].b >= 0; i++) {
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[bm[i].b];
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = bm[i].mnem;
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    OperandType op_order = bm[i].op_order_;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->op_order_ =
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assert(id->type == NO_INSTR);  // Information not already entered
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type,
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte start,
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte end,
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     bool byte_size,
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     const char* mnem) {
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = start; b <= end; b++) {
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assert(id->type == NO_INSTR);  // Information already entered
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = mnem;
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->byte_size_operation = byte_size;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() {
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = 0x70; b <= 0x7F; b++) {
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    assert(id->type == NO_INSTR);  // Information already entered
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = NULL;  // Computed depending on condition code.
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionTable instruction_table;
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionDesc cmov_instructions[16] = {
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DisassemblerX64 implementation.
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum UnimplementedOpcodeAction {
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CONTINUE_ON_UNIMPLEMENTED_OPCODE,
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ABORT_ON_UNIMPLEMENTED_OPCODE
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A new DisassemblerX64 object is created to disassemble each instruction.
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The object can only disassemble a single instruction.
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerX64 {
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerX64(const NameConverter& converter,
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  UnimplementedOpcodeAction unimplemented_action =
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      ABORT_ON_UNIMPLEMENTED_OPCODE)
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : converter_(converter),
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        tmp_buffer_pos_(0),
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        abort_on_unimplemented_(
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        rex_(0),
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        operand_size_(0),
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        group_1_prefix_(0),
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte_size_operand_(false) {
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[0] = '\0';
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~DisassemblerX64() {
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Writes one disassembled instruction into 'buffer' (0-terminated).
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the length of the disassembled machine instruction in bytes.
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum OperandSize {
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BYTE_SIZE = 0,
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    WORD_SIZE = 1,
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DOUBLEWORD_SIZE = 2,
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    QUADWORD_SIZE = 3
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const NameConverter& converter_;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned int tmp_buffer_pos_;
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool abort_on_unimplemented_;
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prefixes parsed
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_;
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0.
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Byte size operand override.
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool byte_size_operand_;
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void setRex(byte rex) {
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0x40, rex & 0xF0);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rex_ = rex;
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex() { return rex_ != 0; }
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_b() { return (rex_ & 0x01) != 0; }
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Actual number of base register given the low bits and the rex.b state.
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_x() { return (rex_ & 0x02) != 0; }
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_r() { return (rex_ & 0x04) != 0; }
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_w() { return (rex_ & 0x08) != 0; }
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandSize operand_size() {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (byte_size_operand_) return BYTE_SIZE;
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rex_w()) return QUADWORD_SIZE;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (operand_size_ != 0) return WORD_SIZE;
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return DOUBLEWORD_SIZE;
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char operand_size_code() {
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return "bwlq"[operand_size()];
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfCPURegister(int reg) const {
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfCPURegister(reg);
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfByteCPURegister(int reg) const {
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfByteCPURegister(reg);
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfXMMRegister(int reg) const {
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfXMMRegister(reg);
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(byte* addr) const {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfAddress(addr);
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Disassembler helper functions.
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void get_modrm(byte data,
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 int* mod,
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 int* regop,
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 int* rm) {
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *mod = (data >> 6) & 3;
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *rm = (data & 7) | (rex_b() ? 8 : 0);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void get_sib(byte data,
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               int* scale,
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               int* index,
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               int* base) {
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *scale = (data >> 6) & 3;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *base = (data & 7) | (rex_b() ? 8 : 0);
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperandHelper(byte* modrmp,
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              RegisterNameMapping register_name);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperand(byte* modrmp);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightByteOperand(byte* modrmp);
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintOperands(const char* mnem,
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    OperandType op_order,
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    byte* data);
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediate(byte* data, OperandSize size);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediateOp(byte* data);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* TwoByteMnemonic(byte opcode);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int TwoByteOpcodeInstruction(byte* data);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int F7Instruction(byte* data);
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int ShiftInstruction(byte* data);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpShort(byte* data);
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditional(byte* data);
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditionalShort(byte* data);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int SetCC(byte* data);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int FPUInstruction(byte* data);
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AppendToBuffer(const char* format, ...);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UnimplementedInstruction() {
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (abort_on_unimplemented_) {
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(false);
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("'Unimplemented Instruction'");
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerX64::AppendToBuffer(const char* format, ...) {
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_list args;
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_start(args, format);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int result = v8::internal::OS::VSNPrintF(buf, format, args);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_end(args);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ += result;
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperandHelper(
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* modrmp,
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegisterNameMapping register_name) {
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(*modrmp, &mod, &regop, &rm);
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (mod) {
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((rm & 7) == 5) {
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[0x%x]", disp);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if ((rm & 7) == 4) {
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Codes for SIB byte.
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // index == rsp means no index. Only use sib byte with no index for
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // rsp and r12 base.
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s]", (this->*register_name)(base));
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (base == 5) {
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // base == rbp means no base register (when mod == 0).
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s*%d+0x%x]",
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale, disp);
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 6;
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (index != 4 && base != 5) {
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // [base+index*scale]
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s+%s*%d]",
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale);
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[%s]", (this->*register_name)(rm));
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 1;
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:  // fall through
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((rm & 7) == 4) {
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              : *reinterpret_cast<char*>(modrmp + 2);
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (-disp > 0) {
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("[%s-0x%x]", (this->*register_name)(base), -disp);
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("[%s+0x%x]", (this->*register_name)(base), disp);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (-disp > 0) {
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("[%s+%s*%d-0x%x]",
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           (this->*register_name)(base),
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           (this->*register_name)(index),
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           1 << scale,
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           -disp);
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("[%s+%s*%d+0x%x]",
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           (this->*register_name)(base),
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           (this->*register_name)(index),
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           1 << scale,
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           disp);
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 6 : 3;
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No sib.
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              : *reinterpret_cast<char*>(modrmp + 1);
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (-disp > 0) {
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[%s-0x%x]", (this->*register_name)(rm), -disp);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return (mod == 2) ? 5 : 2;
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s", (this->*register_name)(rm));
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int64_t value;
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count;
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (size) {
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case BYTE_SIZE:
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *data;
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 1;
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case WORD_SIZE:
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *reinterpret_cast<int16_t*>(data);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 2;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case DOUBLEWORD_SIZE:
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *reinterpret_cast<uint32_t*>(data);
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 4;
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case QUADWORD_SIZE:
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *reinterpret_cast<int32_t*>(data);
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 4;
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = 0;  // Initialize variables on all paths to satisfy the compiler.
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 0;
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%" V8_PTR_PREFIX "x", value);
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return count;
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperand(byte* modrmp) {
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerX64::NameOfCPURegister);
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerX64::NameOfByteCPURegister);
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data.
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintOperands(const char* mnem,
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   OperandType op_order,
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   byte* data) {
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *data;
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int advance = 0;
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* register_name =
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte_size_operand_ ? NameOfByteCPURegister(regop)
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         : NameOfCPURegister(regop);
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (op_order) {
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REG_OPER_OP_ORDER: {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s%c %s,",
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     mnem,
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     operand_size_code(),
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     register_name);
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = byte_size_operand_ ? PrintRightByteOperand(data)
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   : PrintRightOperand(data);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case OPER_REG_OP_ORDER: {
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s%c ", mnem, operand_size_code());
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = byte_size_operand_ ? PrintRightByteOperand(data)
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   : PrintRightOperand(data);
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", register_name);
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return advance;
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte.
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'.
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediateOp(byte* data) {
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool byte_size_immediate = (*data & 0x02) != 0;
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data + 1);
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = "Imm???";
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "add";
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "or";
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "adc";
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4:
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "and";
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5:
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "sub";
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 6:
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "xor";
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7:
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "cmp";
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s%c ", mnem, operand_size_code());
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = PrintRightOperand(data + 1);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer(",0x");
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  count += PrintImmediate(data + 1 + count, immediate_size);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 1 + count;
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::F7Instruction(byte* data) {
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assert(*data == 0xF7);
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data + 1);
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mod == 3 && regop != 0) {
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = NULL;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (regop) {
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 2:
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "not";
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 3:
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "neg";
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 4:
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "mul";
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 7:
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "idiv";
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s%c %s",
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   mnem,
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   operand_size_code(),
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   NameOfCPURegister(rm));
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (mod == 3 && regop == 0) {
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int32_t imm = *reinterpret_cast<int32_t*>(data + 2);
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("test%c %s,0x%x",
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   operand_size_code(),
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   NameOfCPURegister(rm),
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   imm);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 6;
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (regop == 0) {
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("test%c ", operand_size_code());
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int count = PrintRightOperand(data + 1);
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count);
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", imm);
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 4 /*int32_t*/;
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::ShiftInstruction(byte* data) {
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte op = *data & (~1);
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1;
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data + 1);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  regop &= 0x7;  // The REX.R bit does not affect the operation.
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm8 = -1;
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_bytes = 2;
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mod != 3) {
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return num_bytes;
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = NULL;
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "rol";
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "ror";
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "rcl";
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "rcr";
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4:
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "shl";
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5:
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "shr";
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7:
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "sar";
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return num_bytes;
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assert(mnem != NULL);
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op == 0xD0) {
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm8 = 1;
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (op == 0xC0) {
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm8 = *(data + 2);
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    num_bytes = 3;
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s%c %s,",
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 mnem,
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 operand_size_code(),
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 byte_size_operand_ ? NameOfByteCPURegister(rm)
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    : NameOfCPURegister(rm));
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op == 0xD2) {
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("cl");
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%d", imm8);
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return num_bytes;
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpShort(byte* data) {
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assert(*data == 0xEB);
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data + 1);
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("jmp %s", NameOfAddress(dest));
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditional(byte* data) {
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assert(*data == 0x0F);
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data + 1) & 0x0F;
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = conditional_code_suffix[cond];
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 6;  // includes 0x0F
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditionalShort(byte* data) {
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *data & 0x0F;
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data + 1);
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = conditional_code_suffix[cond];
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::SetCC(byte* data) {
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assert(*data == 0x0F);
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data + 1) & 0x0F;
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = conditional_code_suffix[cond];
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("set%s%c ", mnem, operand_size_code());
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintRightByteOperand(data + 2);
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 3;  // includes 0x0F
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::FPUInstruction(byte* data) {
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b1 = *data;
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b2 = *(data + 1);
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (b1 == 0xD9) {
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = NULL;
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (b2) {
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xE0:
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fchs";
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xE1:
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fabs";
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xE4:
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "ftst";
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF5:
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fprem1";
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF7:
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fincstp";
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xE8:
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fld1";
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xEE:
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fldz";
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF8:
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fprem";
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mnem != NULL) {
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s", mnem);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 2;
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if ((b2 & 0xF8) == 0xC8) {
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("fxch st%d", b2 & 0x7);
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 2;
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int mod, regop, rm;
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      get_modrm(*(data + 1), &mod, &regop, &rm);
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const char* mnem = "?";
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      switch (regop) {
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case 0:
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          mnem = "fld_s";
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case 3:
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          mnem = "fstp_s";
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default:
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s ", mnem);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int count = PrintRightOperand(data + 1);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return count + 1;
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (b1 == 0xDD) {
8633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    int mod, regop, rm;
8643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    get_modrm(*(data + 1), &mod, &regop, &rm);
8653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    if (mod == 3) {
8663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      switch (regop) {
8673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        case 0:
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          AppendToBuffer("ffree st%d", rm & 7);
8693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          break;
8703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        case 2:
8713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          AppendToBuffer("fstp st%d", rm & 7);
8723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          break;
8733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        default:
8743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          UnimplementedInstruction();
8753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          break;
8763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 2;
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const char* mnem = "?";
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      switch (regop) {
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case 0:
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          mnem = "fld_d";
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case 3:
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          mnem = "fstp_d";
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default:
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s ", mnem);
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int count = PrintRightOperand(data + 1);
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return count + 1;
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (b1 == 0xDB) {
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int mod, regop, rm;
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    get_modrm(*(data + 1), &mod, &regop, &rm);
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = "?";
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (regop) {
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0:
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fild_s";
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 2:
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fist_s";
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 3:
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fistp_s";
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s ", mnem);
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int count = PrintRightOperand(data + 1);
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return count + 1;
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (b1 == 0xDF) {
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (b2 == 0xE0) {
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("fnstsw_ax");
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 2;
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int mod, regop, rm;
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    get_modrm(*(data + 1), &mod, &regop, &rm);
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = "?";
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (regop) {
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 5:
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fild_d";
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 7:
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fistp_d";
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s ", mnem);
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int count = PrintRightOperand(data + 1);
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return count + 1;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (b1 == 0xDC || b1 == 0xDE) {
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool is_pop = (b1 == 0xDE);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (is_pop && b2 == 0xD9) {
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("fcompp");
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 2;
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = "FP0xDC";
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (b2 & 0xF8) {
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC0:
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fadd";
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xE8:
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fsub";
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC8:
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fmul";
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF8:
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "fdiv";
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s%s st%d", mnem, is_pop ? "p" : "", b2 & 0x7);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (b1 == 0xDA && b2 == 0xE9) {
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = "fucompp";
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnem);
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("Unknown FP instruction");
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all two-byte opcodes, which start with 0x0F.
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte opcode = *(data + 1);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* current = data + 2;
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // At return, "current" points to the start of the next instruction.
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnemonic = TwoByteMnemonic(opcode);
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (opcode == 0x1F) {
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // NOP
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int mod, regop, rm;
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    get_modrm(*current, &mod, &regop, &rm);
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current++;
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (regop == 4) {  // SIB byte present.
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current++;
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mod == 1) {  // Byte displacement.
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += 1;
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (mod == 2) {  // 32-bit displacement.
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += 4;
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }  // else no immediate displacement.
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("nop");
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else  if (opcode == 0xA2 || opcode == 0x31) {
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // RDTSC or CPUID
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnemonic);
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if ((opcode & 0xF0) == 0x40) {
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // CMOVcc: conditional move.
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int condition = opcode & 0x0F;
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const InstructionDesc& idesc = cmov_instructions[condition];
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte_size_operand_ = idesc.byte_size_operation;
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if ((opcode & 0xF0) == 0x80) {
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Jcc: Conditional jump (branch).
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = data + JumpConditional(data);
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             opcode == 0xB7 || opcode == 0xAF) {
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Size-extending moves, IMUL.
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if ((opcode & 0xF0) == 0x90) {
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = data + SetCC(data);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // SHLD, SHRD (double-precision shift), BTS (bit set).
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s ", mnemonic);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int mod, regop, rm;
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    get_modrm(*current, &mod, &regop, &rm);
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintRightOperand(current);
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (opcode == 0xAB) {
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", NameOfCPURegister(regop));
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (group_1_prefix_ == 0xF2) {
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Beginning of instructions with prefix 0xF2.
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (opcode == 0x11 || opcode == 0x10) {
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("movsd ");
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int mod, regop, rm;
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      get_modrm(*current, &mod, &regop, &rm);
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (opcode == 0x11) {
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        current += PrintRightOperand(current);
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(",%s", NameOfXMMRegister(regop));
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("%s,", NameOfXMMRegister(regop));
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        current += PrintRightOperand(current);
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (opcode == 0x2A) {
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // CVTSI2SD: integer to XMM double conversion.
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int mod, regop, rm;
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      get_modrm(*current, &mod, &regop, &rm);
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += PrintRightOperand(data);
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if ((opcode & 0xF8) == 0x58) {
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int mod, regop, rm;
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      get_modrm(*current, &mod, &regop, &rm);
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s,%s", mnemonic, NameOfXMMRegister(regop),
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfXMMRegister(rm));
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) {
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Instruction with prefix 0xF3.
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // CVTTSS2SI: Convert scalar single-precision FP to dword integer.
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Assert that mod is not 3, so source is memory, not an XMM register.
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT((*current & 0xC0) != 0xC0);
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return current - data;
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for two-byte opcode instructions starting with 0x0F.
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The argument is the second byte of the two-byte opcode.
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here.
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (opcode) {
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x1F:
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "nop";
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x2A:  // F2 prefix.
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "cvtsi2sd";
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x31:
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "rdtsc";
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x58:  // F2 prefix.
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "addsd";
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x59:  // F2 prefix.
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "mulsd";
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x5C:  // F2 prefix.
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "subsd";
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x5E:  // F2 prefix.
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "divsd";
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA2:
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "cpuid";
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA5:
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "shld";
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAB:
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "bts";
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAD:
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "shrd";
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAF:
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "imul";
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB6:
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movzxb";
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB7:
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movzxw";
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBE:
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movsxb";
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBF:
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movsxw";
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return NULL;
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembles the instruction at instr, and writes it into out_buffer.
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       byte* instr) {
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ = 0;  // starting to write as position 0
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* data = instr;
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool processed = true;  // Will be set to false if the current instruction
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          // is not in 'instructions' table.
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte current;
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan for prefixes.
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = *data;
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current == 0x66) {  // Group 3 prefix.
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      operand_size_ = current;
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if ((current & 0xF0) == 0x40) {  // REX prefix.
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      setRex(current);
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rex_w()) AppendToBuffer("REX.W ");
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix.
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      group_1_prefix_ = current;
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {  // Not a prefix - an opcode.
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const InstructionDesc& idesc = instruction_table.Get(current);
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte_size_operand_ = idesc.byte_size_operation;
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (idesc.type) {
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case ZERO_OPERANDS_INSTR:
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(idesc.mnem);
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case TWO_OPERANDS_INSTR:
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case JUMP_CONDITIONAL_SHORT_INSTR:
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += JumpConditionalShort(data);
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REGISTER_INSTR:
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s%c %s",
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     idesc.mnem,
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     operand_size_code(),
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(base_reg(current & 0x07)));
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case PUSHPOP_INSTR:
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s",
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     idesc.mnem,
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(base_reg(current & 0x07)));
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case MOVE_REG_INSTR: {
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = NULL;
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      switch (operand_size()) {
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case WORD_SIZE:
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += 3;
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case DOUBLEWORD_SIZE:
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += 5;
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case QUADWORD_SIZE:
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += 9;
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default:
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UNREACHABLE();
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("mov%c %s,%s",
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     operand_size_code(),
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(base_reg(current & 0x07)),
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfAddress(addr));
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case CALL_JUMP_INSTR: {
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case SHORT_IMMEDIATE_INSTR: {
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr =
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s rax, %s", idesc.mnem, NameOfAddress(addr));
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case NO_INSTR:
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      processed = false;
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // This type is not implemented.
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The first byte didn't match any of the simple opcodes, so we
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // need to do special processing on it.
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!processed) {
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (*data) {
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC2:
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 3;
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x69:  // fall through
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6B: {
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*(data + 1), &mod, &regop, &rm);
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t imm = *data == 0x6B ? *(data + 2)
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            : *reinterpret_cast<int32_t*>(data + 2);
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("imul %s,%s,0x%x", NameOfCPURegister(regop),
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       NameOfCPURegister(rm), imm);
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2 + (*data == 0x6B ? 1 : 4);
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF6: {
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*(data + 1), &mod, &regop, &rm);
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mod == 3 && regop == 0) {
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("testb %s,%d", NameOfCPURegister(rm), *(data + 2));
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 3;
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x81:  // fall through
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x83:  // 0x81 with sign extension bit set
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintImmediateOp(data);
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x0F:
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += TwoByteOpcodeInstruction(data);
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x8F: {
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (regop == 0) {
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("pop ");
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFF: {
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* mnem = NULL;
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (regop) {
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 0:
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "inc";
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 1:
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "dec";
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 2:
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "call";
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 4:
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "jmp";
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 6:
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "push";
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "???";
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       mnem,
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       operand_size_code());
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintRightOperand(data);
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC7:  // imm32, fall through
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC6:  // imm8
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      {
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_byte = *data == 0xC6;
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("mov%c ", is_byte ? 'b' : operand_size_code());
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintRightOperand(data);
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t imm = is_byte ? *data : *reinterpret_cast<int32_t*>(data);
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(",0x%x", imm);
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += is_byte ? 1 : 4;
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x80: {
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("cmpb ");
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintRightOperand(data);
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t imm = *data;
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(",0x%x", imm);
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x88:  // 8bit, fall through
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x89:  // 32bit
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      {
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_byte = *data == 0x88;
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("mov%c ", is_byte ? 'b' : operand_size_code());
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintRightOperand(data);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(",%s", NameOfCPURegister(regop));
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x90:
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x91:
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x92:
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x93:
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x94:
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x95:
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x96:
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x97: {
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int reg = (current & 0x7) | (rex_b() ? 8 : 0);
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (reg == 0) {
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("nop");  // Common name for xchg rax,rax.
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("xchg%c rax, %s",
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         operand_size_code(),
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         NameOfCPURegister(reg));
1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFE: {
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mod == 3 && regop == 1) {
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("decb %s", NameOfCPURegister(rm));
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x68:
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6A:
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA1:  // Fall through.
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA3:
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (operand_size()) {
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case DOUBLEWORD_SIZE: {
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* memory_location = NameOfAddress(
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                reinterpret_cast<byte*>(
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    *reinterpret_cast<int32_t*>(data + 1)));
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (*data == 0xA1) {  // Opcode 0xA1
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movzxlq rax,(%s)", memory_location);
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {  // Opcode 0xA3
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movzxlq (%s),rax", memory_location);
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 5;
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case QUADWORD_SIZE: {
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // New x64 instruction mov rax,(imm_64).
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* memory_location = NameOfAddress(
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                *reinterpret_cast<byte**>(data + 1));
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (*data == 0xA1) {  // Opcode 0xA1
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movq rax,(%s)", memory_location);
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {  // Opcode 0xA3
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movq (%s),rax", memory_location);
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 9;
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA8:
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA9: {
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int64_t value = 0;
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (operand_size()) {
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case WORD_SIZE:
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            value = *reinterpret_cast<uint16_t*>(data + 1);
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case DOUBLEWORD_SIZE:
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            value = *reinterpret_cast<uint32_t*>(data + 1);
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 5;
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case QUADWORD_SIZE:
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            value = *reinterpret_cast<int32_t*>(data + 1);
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 5;
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UNREACHABLE();
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x",
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       operand_size_code(),
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       value);
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD1:  // fall through
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD3:  // fall through
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC1:
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += ShiftInstruction(data);
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD0:  // fall through
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD2:  // fall through
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC0:
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte_size_operand_ = true;
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += ShiftInstruction(data);
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD9:  // fall through
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDA:  // fall through
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDB:  // fall through
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDC:  // fall through
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDD:  // fall through
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDE:  // fall through
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDF:
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += FPUInstruction(data);
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xEB:
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += JumpShort(data);
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF7:
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += F7Instruction(data);
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 1;
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }  // !processed
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[tmp_buffer_pos_] = '\0';
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int instr_len = data - instr;
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(instr_len > 0);  // Ensure progress.
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int outp = 0;
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instruction bytes.
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* bp = instr; bp < data; bp++) {
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outp += v8::internal::OS::SNPrintF(out_buffer + outp, "%02x", *bp);
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 6 - instr_len; i >= 0; i--) {
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outp += v8::internal::OS::SNPrintF(out_buffer + outp, "  ");
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  outp += v8::internal::OS::SNPrintF(out_buffer + outp, " %s",
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     tmp_buffer_.start());
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return instr_len;
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[16] = {
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[16] = {
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[16] = {
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const {
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return tmp_buffer.start();
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const {
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NameOfAddress(addr);
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const {
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 16)
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return cpu_regs[reg];
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const {
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 16)
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return byte_cpu_regs[reg];
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const {
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 16)
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return xmm_regs[reg];
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noxmmreg";
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const {
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // X64 does not embed debug strings at the moment.
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "";
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter)
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter) { }
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() { }
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* instruction) {
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return d.InstructionDecode(buffer, instruction);
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The X64 assembler does not use constant pools.
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) {
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NameConverter converter;
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Disassembler d(converter);
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* pc = begin; pc < end;) {
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::internal::EmbeddedVector<char, 128> buffer;
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[0] = '\0';
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc += d.InstructionDecode(buffer, pc);
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "%p", prev_pc);
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "    ");
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (byte* bp = prev_pc; bp < pc; bp++) {
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "%02x", *bp);
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "  ");
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "  %s\n", buffer.start());
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace disasm
1602