1e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h>
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdio.h>
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h>
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
33f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
34f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64)
35f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "disasm.h"
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "lazy-instance.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm {
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandType {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNSET_OP_ORDER = 0,
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Operand size decides between 16, 32 and 64 bit operands.
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fixed 8-bit operands.
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BYTE_SIZE_OPERAND_FLAG = 4,
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic {
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int b;  // -1 terminates, otherwise must be in range (0..255)
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandType op_order_;
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic two_operands_instr[] = {
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x01, OPER_REG_OP_ORDER,      "add" },
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x03, REG_OPER_OP_ORDER,      "add" },
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x09, OPER_REG_OP_ORDER,      "or" },
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x0B, REG_OPER_OP_ORDER,      "or" },
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x11, OPER_REG_OP_ORDER,      "adc" },
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x13, REG_OPER_OP_ORDER,      "adc" },
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x19, OPER_REG_OP_ORDER,      "sbb" },
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x21, OPER_REG_OP_ORDER,      "and" },
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x23, REG_OPER_OP_ORDER,      "and" },
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x29, OPER_REG_OP_ORDER,      "sub" },
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x2B, REG_OPER_OP_ORDER,      "sub" },
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x31, OPER_REG_OP_ORDER,      "xor" },
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x33, REG_OPER_OP_ORDER,      "xor" },
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x39, OPER_REG_OP_ORDER,      "cmp" },
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x63, REG_OPER_OP_ORDER,      "movsxlq" },
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x85, REG_OPER_OP_ORDER,      "test" },
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x87, REG_OPER_OP_ORDER,      "xchg" },
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x89, OPER_REG_OP_ORDER,      "mov" },
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x8B, REG_OPER_OP_ORDER,      "mov" },
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x8D, REG_OPER_OP_ORDER,      "lea" },
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = {
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xC3, UNSET_OP_ORDER, "ret" },
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xC9, UNSET_OP_ORDER, "leave" },
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xF4, UNSET_OP_ORDER, "hlt" },
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { 0xFC, UNSET_OP_ORDER, "cld" },
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xCC, UNSET_OP_ORDER, "int3" },
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x60, UNSET_OP_ORDER, "pushad" },
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x61, UNSET_OP_ORDER, "popad" },
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9C, UNSET_OP_ORDER, "pushfd" },
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9D, UNSET_OP_ORDER, "popfd" },
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9E, UNSET_OP_ORDER, "sahf" },
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x99, UNSET_OP_ORDER, "cdq" },
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x9B, UNSET_OP_ORDER, "fwait" },
122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  { 0xA4, UNSET_OP_ORDER, "movs" },
123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  { 0xA5, UNSET_OP_ORDER, "movs" },
124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  { 0xA6, UNSET_OP_ORDER, "cmps" },
125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  { 0xA7, UNSET_OP_ORDER, "cmps" },
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = {
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xE8, UNSET_OP_ORDER, "call" },
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0xE9, UNSET_OP_ORDER, "jmp" },
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = {
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x05, UNSET_OP_ORDER, "add" },
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x0D, UNSET_OP_ORDER, "or" },
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x15, UNSET_OP_ORDER, "adc" },
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x1D, UNSET_OP_ORDER, "sbb" },
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x25, UNSET_OP_ORDER, "and" },
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x2D, UNSET_OP_ORDER, "sub" },
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x35, UNSET_OP_ORDER, "xor" },
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { 0x3D, UNSET_OP_ORDER, "cmp" },
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { -1, UNSET_OP_ORDER, "" }
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_code_suffix[] = {
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "o", "no", "c", "nc", "z", "nz", "na", "a",
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "s", "ns", "pe", "po", "l", "ge", "le", "g"
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType {
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NO_INSTR,
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZERO_OPERANDS_INSTR,
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TWO_OPERANDS_INSTR,
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JUMP_CONDITIONAL_SHORT_INSTR,
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REGISTER_INSTR,
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MOVE_REG_INSTR,
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CALL_JUMP_INSTR,
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SHORT_IMMEDIATE_INSTR
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeenum Prefixes {
170d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ESCAPE_PREFIX = 0x0F,
171d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
173d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  REPNE_PREFIX = 0xF2,
174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  REP_PREFIX = 0xF3,
175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  REPEQ_PREFIX = REP_PREFIX
176d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc {
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionType type;
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandType op_order_;
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool byte_size_operation;  // Fixed 8-bit operation.
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable {
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionTable();
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const InstructionDesc& Get(byte x) const {
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return instructions_[x];
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionDesc instructions_[256];
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Clear();
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Init();
19869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void CopyTable(const ByteMnemonic bm[], InstructionType type);
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const char* mnem);
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AddJumpConditionalShort();
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() {
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Clear();
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Init();
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() {
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 256; i++) {
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].mnem = "(bad)";
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].type = NO_INSTR;
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].op_order_ = UNSET_OP_ORDER;
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].byte_size_operation = false;
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() {
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddJumpConditionalShort();
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[],
23469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                 InstructionType type) {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; bm[i].b >= 0; i++) {
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[bm[i].b];
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = bm[i].mnem;
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    OperandType op_order = bm[i].op_order_;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->op_order_ =
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type,
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte start,
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte end,
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     bool byte_size,
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     const char* mnem) {
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = start; b <= end; b++) {
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = mnem;
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->byte_size_operation = byte_size;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() {
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = 0x70; b <= 0x7F; b++) {
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = NULL;  // Computed depending on condition code.
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic v8::internal::LazyInstance<InstructionTable>::type instruction_table =
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LAZY_INSTANCE_INITIALIZER;
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic InstructionDesc cmov_instructions[16] = {
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DisassemblerX64 implementation.
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum UnimplementedOpcodeAction {
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CONTINUE_ON_UNIMPLEMENTED_OPCODE,
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ABORT_ON_UNIMPLEMENTED_OPCODE
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A new DisassemblerX64 object is created to disassemble each instruction.
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The object can only disassemble a single instruction.
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerX64 {
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerX64(const NameConverter& converter,
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  UnimplementedOpcodeAction unimplemented_action =
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      ABORT_ON_UNIMPLEMENTED_OPCODE)
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : converter_(converter),
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        tmp_buffer_pos_(0),
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        abort_on_unimplemented_(
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        rex_(0),
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        operand_size_(0),
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        group_1_prefix_(0),
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte_size_operand_(false) {
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[0] = '\0';
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~DisassemblerX64() {
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Writes one disassembled instruction into 'buffer' (0-terminated).
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the length of the disassembled machine instruction in bytes.
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum OperandSize {
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BYTE_SIZE = 0,
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    WORD_SIZE = 1,
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DOUBLEWORD_SIZE = 2,
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    QUADWORD_SIZE = 3
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const NameConverter& converter_;
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned int tmp_buffer_pos_;
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool abort_on_unimplemented_;
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prefixes parsed
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte rex_;
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0.
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Byte size operand override.
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool byte_size_operand_;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void setRex(byte rex) {
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT_EQ(0x40, rex & 0xF0);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    rex_ = rex;
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex() { return rex_ != 0; }
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_b() { return (rex_ & 0x01) != 0; }
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Actual number of base register given the low bits and the rex.b state.
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_x() { return (rex_ & 0x02) != 0; }
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_r() { return (rex_ & 0x04) != 0; }
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool rex_w() { return (rex_ & 0x08) != 0; }
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandSize operand_size() {
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (byte_size_operand_) return BYTE_SIZE;
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (rex_w()) return QUADWORD_SIZE;
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (operand_size_ != 0) return WORD_SIZE;
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return DOUBLEWORD_SIZE;
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char operand_size_code() {
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return "bwlq"[operand_size()];
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfCPURegister(int reg) const {
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfCPURegister(reg);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfByteCPURegister(int reg) const {
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfByteCPURegister(reg);
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfXMMRegister(int reg) const {
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfXMMRegister(reg);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(byte* addr) const {
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfAddress(addr);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Disassembler helper functions.
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void get_modrm(byte data,
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 int* mod,
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 int* regop,
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 int* rm) {
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *mod = (data >> 6) & 3;
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *rm = (data & 7) | (rex_b() ? 8 : 0);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void get_sib(byte data,
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               int* scale,
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               int* index,
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               int* base) {
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *scale = (data >> 6) & 3;
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *base = (data & 7) | (rex_b() ? 8 : 0);
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperandHelper(byte* modrmp,
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              RegisterNameMapping register_name);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperand(byte* modrmp);
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightByteOperand(byte* modrmp);
418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int PrintRightXMMOperand(byte* modrmp);
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintOperands(const char* mnem,
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    OperandType op_order,
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    byte* data);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediate(byte* data, OperandSize size);
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediateOp(byte* data);
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* TwoByteMnemonic(byte opcode);
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int TwoByteOpcodeInstruction(byte* data);
426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int F6F7Instruction(byte* data);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int ShiftInstruction(byte* data);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpShort(byte* data);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditional(byte* data);
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditionalShort(byte* data);
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int SetCC(byte* data);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int FPUInstruction(byte* data);
433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AppendToBuffer(const char* format, ...);
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UnimplementedInstruction() {
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (abort_on_unimplemented_) {
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(false);
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("'Unimplemented Instruction'");
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerX64::AppendToBuffer(const char* format, ...) {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_list args;
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_start(args, format);
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int result = v8::internal::OS::VSNPrintF(buf, format, args);
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_end(args);
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ += result;
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperandHelper(
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* modrmp,
45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RegisterNameMapping direct_register_name) {
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(*modrmp, &mod, &regop, &rm);
46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &DisassemblerX64::NameOfCPURegister;
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (mod) {
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((rm & 7) == 5) {
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[0x%x]", disp);
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if ((rm & 7) == 4) {
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Codes for SIB byte.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // index == rsp means no index. Only use sib byte with no index for
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // rsp and r12 base.
4788defd9ff6930b4e24729971a61cf7469daf119beSteve Block          AppendToBuffer("[%s]", NameOfCPURegister(base));
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (base == 5) {
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // base == rbp means no base register (when mod == 0).
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s*%d+0x%x]",
4848defd9ff6930b4e24729971a61cf7469daf119beSteve Block                         NameOfCPURegister(index),
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale, disp);
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 6;
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (index != 4 && base != 5) {
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // [base+index*scale]
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s+%s*%d]",
4908defd9ff6930b4e24729971a61cf7469daf119beSteve Block                         NameOfCPURegister(base),
4918defd9ff6930b4e24729971a61cf7469daf119beSteve Block                         NameOfCPURegister(index),
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale);
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
4998defd9ff6930b4e24729971a61cf7469daf119beSteve Block        AppendToBuffer("[%s]", NameOfCPURegister(rm));
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 1;
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:  // fall through
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((rm & 7) == 4) {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              : *reinterpret_cast<char*>(modrmp + 2);
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (-disp > 0) {
5138defd9ff6930b4e24729971a61cf7469daf119beSteve Block            AppendToBuffer("[%s-0x%x]", NameOfCPURegister(base), -disp);
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
5158defd9ff6930b4e24729971a61cf7469daf119beSteve Block            AppendToBuffer("[%s+0x%x]", NameOfCPURegister(base), disp);
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (-disp > 0) {
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("[%s+%s*%d-0x%x]",
5208defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           NameOfCPURegister(base),
5218defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           NameOfCPURegister(index),
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           1 << scale,
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           -disp);
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("[%s+%s*%d+0x%x]",
5268defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           NameOfCPURegister(base),
5278defd9ff6930b4e24729971a61cf7469daf119beSteve Block                           NameOfCPURegister(index),
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           1 << scale,
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           disp);
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 6 : 3;
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No sib.
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              : *reinterpret_cast<char*>(modrmp + 1);
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (-disp > 0) {
5388defd9ff6930b4e24729971a61cf7469daf119beSteve Block        AppendToBuffer("[%s-0x%x]", NameOfCPURegister(rm), -disp);
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
5408defd9ff6930b4e24729971a61cf7469daf119beSteve Block        AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp);
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return (mod == 2) ? 5 : 2;
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s", (this->*register_name)(rm));
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int64_t value;
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count;
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (size) {
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case BYTE_SIZE:
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *data;
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 1;
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case WORD_SIZE:
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *reinterpret_cast<int16_t*>(data);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 2;
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case DOUBLEWORD_SIZE:
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *reinterpret_cast<uint32_t*>(data);
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 4;
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case QUADWORD_SIZE:
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = *reinterpret_cast<int32_t*>(data);
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 4;
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = 0;  // Initialize variables on all paths to satisfy the compiler.
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      count = 0;
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%" V8_PTR_PREFIX "x", value);
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return count;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightOperand(byte* modrmp) {
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerX64::NameOfCPURegister);
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerX64::NameOfByteCPURegister);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return PrintRightOperandHelper(modrmp,
600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                 &DisassemblerX64::NameOfXMMRegister);
601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data.
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintOperands(const char* mnem,
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   OperandType op_order,
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   byte* data) {
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *data;
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int advance = 0;
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* register_name =
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte_size_operand_ ? NameOfByteCPURegister(regop)
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         : NameOfCPURegister(regop);
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (op_order) {
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REG_OPER_OP_ORDER: {
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s%c %s,",
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     mnem,
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     operand_size_code(),
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     register_name);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = byte_size_operand_ ? PrintRightByteOperand(data)
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   : PrintRightOperand(data);
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case OPER_REG_OP_ORDER: {
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s%c ", mnem, operand_size_code());
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = byte_size_operand_ ? PrintRightByteOperand(data)
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   : PrintRightOperand(data);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", register_name);
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return advance;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte.
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'.
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::PrintImmediateOp(byte* data) {
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool byte_size_immediate = (*data & 0x02) != 0;
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data + 1);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = "Imm???";
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "add";
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "or";
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "adc";
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
6598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case 3:
6608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      mnem = "sbb";
6618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      break;
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4:
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "and";
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5:
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "sub";
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 6:
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "xor";
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7:
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "cmp";
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s%c ", mnem, operand_size_code());
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = PrintRightOperand(data + 1);
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer(",0x");
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  count += PrintImmediate(data + 1 + count, immediate_size);
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 1 + count;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::F6F7Instruction(byte* data) {
688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(*data == 0xF7 || *data == 0xF6);
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data + 1);
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mod == 3 && regop != 0) {
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* mnem = NULL;
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (regop) {
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 2:
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "not";
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 3:
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "neg";
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 4:
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "mul";
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 7:
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mnem = "idiv";
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s%c %s",
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   mnem,
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   operand_size_code(),
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   NameOfCPURegister(rm));
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (regop == 0) {
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("test%c ", operand_size_code());
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int count = PrintRightOperand(data + 1);  // Use name of 64-bit register.
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AppendToBuffer(",0x");
719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    count += PrintImmediate(data + 1 + count, operand_size());
720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return 1 + count;
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 2;
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::ShiftInstruction(byte* data) {
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte op = *data & (~1);
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1;
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data + 1);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  regop &= 0x7;  // The REX.R bit does not affect the operation.
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm8 = -1;
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_bytes = 2;
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mod != 3) {
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return num_bytes;
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = NULL;
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "rol";
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "ror";
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "rcl";
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "rcr";
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4:
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "shl";
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5:
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "shr";
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7:
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mnem = "sar";
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return num_bytes;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_NE(NULL, mnem);
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op == 0xD0) {
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm8 = 1;
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (op == 0xC0) {
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    imm8 = *(data + 2);
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    num_bytes = 3;
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s%c %s,",
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 mnem,
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 operand_size_code(),
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 byte_size_operand_ ? NameOfByteCPURegister(rm)
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    : NameOfCPURegister(rm));
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op == 0xD2) {
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("cl");
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%d", imm8);
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return num_bytes;
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpShort(byte* data) {
794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_EQ(0xEB, *data);
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data + 1);
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("jmp %s", NameOfAddress(dest));
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditional(byte* data) {
804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_EQ(0x0F, *data);
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data + 1) & 0x0F;
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = conditional_code_suffix[cond];
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 6;  // includes 0x0F
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::JumpConditionalShort(byte* data) {
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *data & 0x0F;
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data + 1);
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = conditional_code_suffix[cond];
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::SetCC(byte* data) {
826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_EQ(0x0F, *data);
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data + 1) & 0x0F;
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = conditional_code_suffix[cond];
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("set%s%c ", mnem, operand_size_code());
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintRightByteOperand(data + 2);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 3;  // includes 0x0F
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::FPUInstruction(byte* data) {
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte escape_opcode = *data;
838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_EQ(0xD8, escape_opcode & 0xF8);
839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte modrm_byte = *(data+1);
840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (modrm_byte >= 0xC0) {
842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return RegisterFPUInstruction(escape_opcode, modrm_byte);
843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           int modrm_byte,
850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           byte* modrm_start) {
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9: switch (regop) {
855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_s"; break;
856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_s"; break;
857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fstcw"; break;
858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB: switch (regop) {
863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fild_s"; break;
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 1: mnem = "fisttp_s"; break;
865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 2: mnem = "fist_s"; break;
866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fistp_s"; break;
867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
8683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      }
869d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
870d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD: switch (regop) {
872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_d"; break;
873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_d"; break;
874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
878d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF: switch (regop) {
879d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 5: mnem = "fild_d"; break;
880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fistp_d"; break;
881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
884d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
885d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AppendToBuffer("%s ", mnem);
888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int count = PrintRightOperand(modrm_start);
889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return count + 1;
890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             byte modrm_byte) {
894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool has_register = false;  // Is the FPU register encoded in modrm_byte?
895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD8:
899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UnimplementedInstruction();
900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9:
903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
9040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 0xC0:
9050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          mnem = "fld";
9060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          has_register = true;
9070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8:
909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          mnem = "fxch";
910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          has_register = true;
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default:
913d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          switch (modrm_byte) {
914d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE0: mnem = "fchs"; break;
915d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE1: mnem = "fabs"; break;
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xE3: mnem = "fninit"; break;
917d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE4: mnem = "ftst"; break;
918d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE8: mnem = "fld1"; break;
9190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            case 0xEB: mnem = "fldpi"; break;
920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xED: mnem = "fldln2"; break;
921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xEE: mnem = "fldz"; break;
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xF0: mnem = "f2xm1"; break;
923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xF1: mnem = "fyl2x"; break;
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xF2: mnem = "fptan"; break;
925d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF5: mnem = "fprem1"; break;
926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF7: mnem = "fincstp"; break;
927d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF8: mnem = "fprem"; break;
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFD: mnem = "fscale"; break;
929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFE: mnem = "fsin"; break;
930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFF: mnem = "fcos"; break;
931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            default: UnimplementedInstruction();
932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          }
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDA:
937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE9) {
938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucompp";
939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
942d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB:
945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if ((modrm_byte & 0xF8) == 0xE8) {
946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomi";
947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (modrm_byte  == 0xE2) {
949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fclex";
950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDC:
956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "fadd"; break;
959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xE8: mnem = "fsub"; break;
960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8: mnem = "fmul"; break;
961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xF8: mnem = "fdiv"; break;
962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD:
967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "ffree"; break;
970d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xD8: mnem = "fstp"; break;
971d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDE:
976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte  == 0xD9) {
977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fcompp";
978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
979d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        switch (modrm_byte & 0xF8) {
981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC0: mnem = "faddp"; break;
982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xE8: mnem = "fsubp"; break;
983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC8: mnem = "fmulp"; break;
984d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xF8: mnem = "fdivp"; break;
985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          default: UnimplementedInstruction();
986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF:
991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE0) {
992d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fnstsw_ax";
993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if ((modrm_byte & 0xF8) == 0xE8) {
994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomip";
995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
998d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
999d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
1000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (has_register) {
1003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
1004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnem);
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle all two-byte opcodes, which start with 0x0F.
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte opcode = *(data + 1);
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* current = data + 2;
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // At return, "current" points to the start of the next instruction.
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnemonic = TwoByteMnemonic(opcode);
1020402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (operand_size_ == 0x66) {
1021402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // 0x66 0x0F prefix.
1022402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    int mod, regop, rm;
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (opcode == 0x3A) {
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      byte third_byte = *current;
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      current = data + 3;
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (third_byte == 0x17) {
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        get_modrm(*current, &mod, &regop, &rm);
10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current += PrintRightOperand(current);
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        AppendToBuffer(", %s, %d", NameOfCPURegister(regop), (*current) & 3);
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current += 1;
1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else if (third_byte == 0x0b) {
1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        get_modrm(*current, &mod, &regop, &rm);
1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch         // roundsd xmm, xmm/m64, imm8
1035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer("roundsd %s, ", NameOfCPURegister(regop));
1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        current += PrintRightOperand(current);
1037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer(", %d", (*current) & 3);
1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        current += 1;
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        UnimplementedInstruction();
10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1042402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else {
10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      get_modrm(*current, &mod, &regop, &rm);
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (opcode == 0x1f) {
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current++;
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (rm == 4) {  // SIB byte present.
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          current++;
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (mod == 1) {  // Byte displacement.
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          current += 1;
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (mod == 2) {  // 32-bit displacement.
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          current += 4;
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }  // else no immediate displacement.
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AppendToBuffer("nop");
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (opcode == 0x28) {
1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop));
1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        current += PrintRightXMMOperand(current);
1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else if (opcode == 0x29) {
1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer("movapd ");
1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        current += PrintRightXMMOperand(current);
1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer(", %s", NameOfXMMRegister(regop));
1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else if (opcode == 0x6E) {
10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        AppendToBuffer("mov%c %s,",
10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       rex_w() ? 'q' : 'd',
10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       NameOfXMMRegister(regop));
10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current += PrintRightOperand(current);
10671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (opcode == 0x6F) {
10681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AppendToBuffer("movdqa %s,",
10691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                       NameOfXMMRegister(regop));
107044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current += PrintRightXMMOperand(current);
10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else if (opcode == 0x7E) {
1072bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        AppendToBuffer("mov%c ",
1073bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                       rex_w() ? 'q' : 'd');
1074bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        current += PrintRightOperand(current);
1075bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        AppendToBuffer(", %s", NameOfXMMRegister(regop));
10761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else if (opcode == 0x7F) {
10771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AppendToBuffer("movdqa ");
107844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current += PrintRightXMMOperand(current);
10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        AppendToBuffer(", %s", NameOfXMMRegister(regop));
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      } else if (opcode == 0xD6) {
1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer("movq ");
1082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        current += PrintRightXMMOperand(current);
1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        AppendToBuffer(", %s", NameOfXMMRegister(regop));
10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (opcode == 0x50) {
10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
10863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        current += PrintRightXMMOperand(current);
10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        const char* mnemonic = "?";
10893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (opcode == 0x54) {
1090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          mnemonic = "andpd";
1091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else  if (opcode == 0x56) {
1092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          mnemonic = "orpd";
1093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else  if (opcode == 0x57) {
10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          mnemonic = "xorpd";
10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else if (opcode == 0x2E) {
10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          mnemonic = "ucomisd";
10978defd9ff6930b4e24729971a61cf7469daf119beSteve Block        } else if (opcode == 0x2F) {
10988defd9ff6930b4e24729971a61cf7469daf119beSteve Block          mnemonic = "comisd";
10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          UnimplementedInstruction();
11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current += PrintRightXMMOperand(current);
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
1106402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else if (group_1_prefix_ == 0xF2) {
1107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    // Beginning of instructions with prefix 0xF2.
1108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    if (opcode == 0x11 || opcode == 0x10) {
1110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
1111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      AppendToBuffer("movsd ");
1112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      int mod, regop, rm;
1113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      get_modrm(*current, &mod, &regop, &rm);
1114402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      if (opcode == 0x11) {
111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current += PrintRightXMMOperand(current);
1116402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        AppendToBuffer(",%s", NameOfXMMRegister(regop));
1117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      } else {
1118402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        AppendToBuffer("%s,", NameOfXMMRegister(regop));
111944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        current += PrintRightXMMOperand(current);
1120402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      }
1121402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else if (opcode == 0x2A) {
1122402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // CVTSI2SD: integer to XMM double conversion.
1123402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      int mod, regop, rm;
1124402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      get_modrm(*current, &mod, &regop, &rm);
11258defd9ff6930b4e24729971a61cf7469daf119beSteve Block      AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
1126402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      current += PrintRightOperand(current);
11270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else if (opcode == 0x2C) {
11280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // CVTTSD2SI:
11290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Convert with truncation scalar double-precision FP to integer.
11300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      int mod, regop, rm;
11310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      get_modrm(*current, &mod, &regop, &rm);
11320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      AppendToBuffer("cvttsd2si%c %s,",
11330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          operand_size_code(), NameOfCPURegister(regop));
11340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      current += PrintRightXMMOperand(current);
11350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else if (opcode == 0x2D) {
11360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // CVTSD2SI: Convert scalar double-precision FP to integer.
11370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      int mod, regop, rm;
11380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      get_modrm(*current, &mod, &regop, &rm);
11390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      AppendToBuffer("cvtsd2si%c %s,",
11400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          operand_size_code(), NameOfCPURegister(regop));
11410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      current += PrintRightXMMOperand(current);
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1143402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1144402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      int mod, regop, rm;
1145402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      get_modrm(*current, &mod, &regop, &rm);
1146402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1147402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      current += PrintRightXMMOperand(current);
1148402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    } else {
1149402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      UnimplementedInstruction();
1150402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (group_1_prefix_ == 0xF3) {
11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Instructions with prefix 0xF3.
11538defd9ff6930b4e24729971a61cf7469daf119beSteve Block    if (opcode == 0x11 || opcode == 0x10) {
11548defd9ff6930b4e24729971a61cf7469daf119beSteve Block      // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
11558defd9ff6930b4e24729971a61cf7469daf119beSteve Block      AppendToBuffer("movss ");
11568defd9ff6930b4e24729971a61cf7469daf119beSteve Block      int mod, regop, rm;
11578defd9ff6930b4e24729971a61cf7469daf119beSteve Block      get_modrm(*current, &mod, &regop, &rm);
11588defd9ff6930b4e24729971a61cf7469daf119beSteve Block      if (opcode == 0x11) {
11598defd9ff6930b4e24729971a61cf7469daf119beSteve Block        current += PrintRightOperand(current);
11608defd9ff6930b4e24729971a61cf7469daf119beSteve Block        AppendToBuffer(",%s", NameOfXMMRegister(regop));
11618defd9ff6930b4e24729971a61cf7469daf119beSteve Block      } else {
11628defd9ff6930b4e24729971a61cf7469daf119beSteve Block        AppendToBuffer("%s,", NameOfXMMRegister(regop));
11638defd9ff6930b4e24729971a61cf7469daf119beSteve Block        current += PrintRightOperand(current);
11648defd9ff6930b4e24729971a61cf7469daf119beSteve Block      }
11658defd9ff6930b4e24729971a61cf7469daf119beSteve Block    } else if (opcode == 0x2A) {
11668defd9ff6930b4e24729971a61cf7469daf119beSteve Block      // CVTSI2SS: integer to XMM single conversion.
11678defd9ff6930b4e24729971a61cf7469daf119beSteve Block      int mod, regop, rm;
11688defd9ff6930b4e24729971a61cf7469daf119beSteve Block      get_modrm(*current, &mod, &regop, &rm);
11698defd9ff6930b4e24729971a61cf7469daf119beSteve Block      AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
11708defd9ff6930b4e24729971a61cf7469daf119beSteve Block      current += PrintRightOperand(current);
11718defd9ff6930b4e24729971a61cf7469daf119beSteve Block    } else if (opcode == 0x2C) {
11720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // CVTTSS2SI:
11730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Convert with truncation scalar single-precision FP to dword integer.
11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      int mod, regop, rm;
11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      get_modrm(*current, &mod, &regop, &rm);
11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AppendToBuffer("cvttss2si%c %s,",
11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          operand_size_code(), NameOfCPURegister(regop));
11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      current += PrintRightXMMOperand(current);
11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if (opcode == 0x5A) {
11800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // CVTSS2SD:
11810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Convert scalar single-precision FP to scalar double-precision FP.
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int mod, regop, rm;
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      get_modrm(*current, &mod, &regop, &rm);
11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      current += PrintRightXMMOperand(current);
1186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    } else if (opcode == 0x7E) {
1187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      int mod, regop, rm;
1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      get_modrm(*current, &mod, &regop, &rm);
1189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      AppendToBuffer("movq %s, ", NameOfXMMRegister(regop));
1190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      current += PrintRightXMMOperand(current);
11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UnimplementedInstruction();
11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else if (opcode == 0x1F) {
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // NOP
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int mod, regop, rm;
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    get_modrm(*current, &mod, &regop, &rm);
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current++;
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (rm == 4) {  // SIB byte present.
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current++;
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mod == 1) {  // Byte displacement.
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += 1;
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (mod == 2) {  // 32-bit displacement.
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current += 4;
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }  // else no immediate displacement.
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("nop");
1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (opcode == 0x28) {
1210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // movaps xmm, xmm/m128
1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int mod, regop, rm;
1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AppendToBuffer("movaps %s, ", NameOfXMMRegister(regop));
1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current += PrintRightXMMOperand(current);
1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (opcode == 0x29) {
1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // movaps xmm/m128, xmm
1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int mod, regop, rm;
1219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AppendToBuffer("movaps ");
1221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current += PrintRightXMMOperand(current);
1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AppendToBuffer(", %s", NameOfXMMRegister(regop));
1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1224402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  } else if (opcode == 0xA2 || opcode == 0x31) {
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // RDTSC or CPUID
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnemonic);
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if ((opcode & 0xF0) == 0x40) {
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // CMOVcc: conditional move.
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int condition = opcode & 0x0F;
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const InstructionDesc& idesc = cmov_instructions[condition];
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte_size_operand_ = idesc.byte_size_operation;
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (opcode == 0x57) {
1236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // xorps xmm, xmm/m128
1237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int mod, regop, rm;
1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
1239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    AppendToBuffer("xorps %s, ", NameOfXMMRegister(regop));
1240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    current += PrintRightXMMOperand(current);
1241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if ((opcode & 0xF0) == 0x80) {
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Jcc: Conditional jump (branch).
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = data + JumpConditional(data);
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             opcode == 0xB7 || opcode == 0xAF) {
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Size-extending moves, IMUL.
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if ((opcode & 0xF0) == 0x90) {
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = data + SetCC(data);
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // SHLD, SHRD (double-precision shift), BTS (bit set).
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s ", mnemonic);
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int mod, regop, rm;
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    get_modrm(*current, &mod, &regop, &rm);
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current += PrintRightOperand(current);
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (opcode == 0xAB) {
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", NameOfCPURegister(regop));
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UnimplementedInstruction();
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return static_cast<int>(current - data);
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for two-byte opcode instructions starting with 0x0F.
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The argument is the second byte of the two-byte opcode.
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here.
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (opcode) {
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x1F:
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "nop";
12808defd9ff6930b4e24729971a61cf7469daf119beSteve Block    case 0x2A:  // F2/F3 prefix.
12818defd9ff6930b4e24729971a61cf7469daf119beSteve Block      return "cvtsi2s";
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x31:
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "rdtsc";
12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    case 0x51:  // F2 prefix.
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return "sqrtsd";
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x58:  // F2 prefix.
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "addsd";
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x59:  // F2 prefix.
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "mulsd";
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x5C:  // F2 prefix.
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "subsd";
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x5E:  // F2 prefix.
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "divsd";
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA2:
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "cpuid";
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA5:
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "shld";
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAB:
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "bts";
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAD:
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "shrd";
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAF:
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "imul";
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB6:
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movzxb";
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB7:
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movzxw";
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBE:
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movsxb";
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBF:
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return "movsxw";
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return NULL;
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembles the instruction at instr, and writes it into out_buffer.
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       byte* instr) {
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ = 0;  // starting to write as position 0
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* data = instr;
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool processed = true;  // Will be set to false if the current instruction
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          // is not in 'instructions' table.
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte current;
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scan for prefixes.
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current = *data;
1330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      operand_size_ = current;
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if ((current & 0xF0) == 0x40) {  // REX prefix.
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      setRex(current);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rex_w()) AppendToBuffer("REX.W ");
1335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      group_1_prefix_ = current;
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {  // Not a prefix - an opcode.
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const InstructionDesc& idesc = instruction_table.Get().Get(current);
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte_size_operand_ = idesc.byte_size_operation;
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (idesc.type) {
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case ZERO_OPERANDS_INSTR:
1347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      if (current >= 0xA4 && current <= 0xA7) {
1348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        // String move or compare operations.
1349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        if (group_1_prefix_ == REP_PREFIX) {
1350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          // REP.
1351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          AppendToBuffer("rep ");
1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        }
1353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        if (rex_w()) AppendToBuffer("REX.W ");
1354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
1355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      } else {
1356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        AppendToBuffer("%s", idesc.mnem, operand_size_code());
1357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      }
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case TWO_OPERANDS_INSTR:
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case JUMP_CONDITIONAL_SHORT_INSTR:
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += JumpConditionalShort(data);
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REGISTER_INSTR:
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s%c %s",
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     idesc.mnem,
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     operand_size_code(),
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(base_reg(current & 0x07)));
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case PUSHPOP_INSTR:
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s",
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     idesc.mnem,
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(base_reg(current & 0x07)));
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case MOVE_REG_INSTR: {
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = NULL;
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      switch (operand_size()) {
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case WORD_SIZE:
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += 3;
1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case DOUBLEWORD_SIZE:
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += 5;
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        case QUADWORD_SIZE:
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += 9;
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default:
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UNREACHABLE();
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("mov%c %s,%s",
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     operand_size_code(),
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(base_reg(current & 0x07)),
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfAddress(addr));
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case CALL_JUMP_INSTR: {
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case SHORT_IMMEDIATE_INSTR: {
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr =
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s rax, %s", idesc.mnem, NameOfAddress(addr));
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case NO_INSTR:
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      processed = false;
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // This type is not implemented.
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The first byte didn't match any of the simple opcodes, so we
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // need to do special processing on it.
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!processed) {
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (*data) {
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC2:
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 3;
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x69:  // fall through
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6B: {
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*(data + 1), &mod, &regop, &rm);
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t imm = *data == 0x6B ? *(data + 2)
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            : *reinterpret_cast<int32_t*>(data + 2);
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        AppendToBuffer("imul%c %s,%s,0x%x",
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       operand_size_code(),
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                       NameOfCPURegister(regop),
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       NameOfCPURegister(rm), imm);
1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2 + (*data == 0x6B ? 1 : 4);
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x81:  // fall through
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x83:  // 0x81 with sign extension bit set
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintImmediateOp(data);
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x0F:
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += TwoByteOpcodeInstruction(data);
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x8F: {
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (regop == 0) {
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("pop ");
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFF: {
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const char* mnem = NULL;
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (regop) {
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 0:
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "inc";
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 1:
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "dec";
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 2:
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "call";
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 4:
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "jmp";
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case 6:
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "push";
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mnem = "???";
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       mnem,
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       operand_size_code());
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintRightOperand(data);
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC7:  // imm32, fall through
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC6:  // imm8
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      {
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_byte = *data == 0xC6;
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
151044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (is_byte) {
151144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer("movb ");
151244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightByteOperand(data);
151344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          int32_t imm = *data;
151444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer(",0x%x", imm);
151544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data++;
151644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer("mov%c ", operand_size_code());
151844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightOperand(data);
151944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          int32_t imm = *reinterpret_cast<int32_t*>(data);
152044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer(",0x%x", imm);
152144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += 4;
152244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x80: {
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("cmpb ");
152944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        data += PrintRightByteOperand(data);
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t imm = *data;
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer(",0x%x", imm);
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x88:  // 8bit, fall through
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x89:  // 32bit
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      {
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_byte = *data == 0x88;
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
154344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (is_byte) {
154444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer("movb ");
154544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightByteOperand(data);
154644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer(",%s", NameOfByteCPURegister(regop));
154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        } else {
154844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer("mov%c ", operand_size_code());
154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightOperand(data);
155044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          AppendToBuffer(",%s", NameOfCPURegister(regop));
155144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x90:
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x91:
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x92:
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x93:
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x94:
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x95:
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x96:
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x97: {
1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (reg == 0) {
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("nop");  // Common name for xchg rax,rax.
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("xchg%c rax, %s",
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         operand_size_code(),
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         NameOfCPURegister(reg));
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        data++;
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
15748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB0:
15758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB1:
15768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB2:
15778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB3:
15788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB4:
15798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB5:
15808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB6:
15818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB7:
15828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB8:
15838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xB9:
15848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xBA:
15858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xBB:
15868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xBC:
15878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xBD:
15888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xBE:
15898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      case 0xBF: {
15908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // mov reg8,imm8 or mov reg32,imm32
15918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        byte opcode = *data;
15928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        data++;
15938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        bool is_32bit = (opcode >= 0xB8);
15948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
15958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        if (is_32bit) {
15968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          AppendToBuffer("mov%c %s, ",
15978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         operand_size_code(),
15988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         NameOfCPURegister(reg));
15998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          data += PrintImmediate(data, DOUBLEWORD_SIZE);
16008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        } else {
16018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          AppendToBuffer("movb %s, ",
16028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         NameOfByteCPURegister(reg));
16038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          data += PrintImmediate(data, BYTE_SIZE);
16048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        }
16058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        break;
16068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFE: {
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data++;
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int mod, regop, rm;
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_modrm(*data, &mod, &regop, &rm);
16110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        if (regop == 1) {
16120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          AppendToBuffer("decb ");
161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightByteOperand(data);
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
16188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x68:
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6A:
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA1:  // Fall through.
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA3:
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (operand_size()) {
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case DOUBLEWORD_SIZE: {
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* memory_location = NameOfAddress(
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                reinterpret_cast<byte*>(
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    *reinterpret_cast<int32_t*>(data + 1)));
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (*data == 0xA1) {  // Opcode 0xA1
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movzxlq rax,(%s)", memory_location);
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {  // Opcode 0xA3
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movzxlq (%s),rax", memory_location);
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 5;
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case QUADWORD_SIZE: {
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // New x64 instruction mov rax,(imm_64).
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* memory_location = NameOfAddress(
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                *reinterpret_cast<byte**>(data + 1));
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (*data == 0xA1) {  // Opcode 0xA1
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movq rax,(%s)", memory_location);
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {  // Opcode 0xA3
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              AppendToBuffer("movq (%s),rax", memory_location);
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 9;
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA8:
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA9: {
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int64_t value = 0;
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (operand_size()) {
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case WORD_SIZE:
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            value = *reinterpret_cast<uint16_t*>(data + 1);
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case DOUBLEWORD_SIZE:
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            value = *reinterpret_cast<uint32_t*>(data + 1);
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 5;
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case QUADWORD_SIZE:
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            value = *reinterpret_cast<int32_t*>(data + 1);
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 5;
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UNREACHABLE();
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x",
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       operand_size_code(),
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       value);
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD1:  // fall through
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD3:  // fall through
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC1:
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += ShiftInstruction(data);
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD0:  // fall through
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD2:  // fall through
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC0:
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte_size_operand_ = true;
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += ShiftInstruction(data);
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD9:  // fall through
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDA:  // fall through
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDB:  // fall through
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDC:  // fall through
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDD:  // fall through
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDE:  // fall through
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDF:
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += FPUInstruction(data);
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xEB:
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += JumpShort(data);
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      case 0xF6:
1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        byte_size_operand_ = true;  // fall through
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF7:
1719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        data += F6F7Instruction(data);
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 1;
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }  // !processed
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[tmp_buffer_pos_] = '\0';
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int instr_len = static_cast<int>(data - instr);
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(instr_len > 0);  // Ensure progress.
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int outp = 0;
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instruction bytes.
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* bp = instr; bp < data; bp++) {
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outp += v8::internal::OS::SNPrintF(out_buffer + outp, "%02x", *bp);
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 6 - instr_len; i >= 0; i--) {
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outp += v8::internal::OS::SNPrintF(out_buffer + outp, "  ");
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  outp += v8::internal::OS::SNPrintF(out_buffer + outp, " %s",
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     tmp_buffer_.start());
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return instr_len;
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[16] = {
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[16] = {
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[16] = {
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const {
177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
177244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return tmp_buffer_.start();
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const {
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NameOfAddress(addr);
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const {
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 16)
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return cpu_regs[reg];
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const {
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 16)
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return byte_cpu_regs[reg];
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const {
1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 16)
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return xmm_regs[reg];
1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noxmmreg";
1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const {
1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // X64 does not embed debug strings at the moment.
1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "";
1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter)
1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter) { }
1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() { }
1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* instruction) {
1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return d.InstructionDecode(buffer, instruction);
1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The X64 assembler does not use constant pools.
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) {
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NameConverter converter;
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Disassembler d(converter);
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* pc = begin; pc < end;) {
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::internal::EmbeddedVector<char, 128> buffer;
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[0] = '\0';
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc += d.InstructionDecode(buffer, pc);
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "%p", prev_pc);
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "    ");
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (byte* bp = prev_pc; bp < pc; bp++) {
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "%02x", *bp);
1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "  ");
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "  %s\n", buffer.start());
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace disasm
1851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_X64
1853