15d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
25ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// Redistribution and use in source and binary forms, with or without
35ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// modification, are permitted provided that the following conditions are
45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// met:
55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Redistributions of source code must retain the above copyright
75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       notice, this list of conditions and the following disclaimer.
85ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Redistributions in binary form must reproduce the above
95ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       copyright notice, this list of conditions and the following
105ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       disclaimer in the documentation and/or other materials provided
115ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       with the distribution.
125ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//     * Neither the name of Google Inc. nor the names of its
135ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       contributors may be used to endorse or promote products derived
145ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//       from this software without specific prior written permission.
155ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org//
165ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org
2868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#include <assert.h>
2968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#include <stdio.h>
3068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#include <stdarg.h>
3168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
32b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#include "v8.h"
339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3493a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_X64
359dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org#include "disasm.h"
371456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#include "lazy-instance.h"
38b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
39b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgnamespace disasm {
40b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
41e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgenum OperandType {
42e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  UNSET_OP_ORDER = 0,
43e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Operand size decides between 16, 32 and 64 bit operands.
44e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
45e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
46e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Fixed 8-bit operands.
47e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  BYTE_SIZE_OPERAND_FLAG = 4,
48e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
49e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
5068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
5168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
52e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
5368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org//------------------------------------------------------------------
5468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Tables
5568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org//------------------------------------------------------------------
5668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgstruct ByteMnemonic {
5768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int b;  // -1 terminates, otherwise must be in range (0..255)
58e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  OperandType op_order_;
5968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* mnem;
6068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
6168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
6268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
637c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic two_operands_instr[] = {
64e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
65e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x01, OPER_REG_OP_ORDER,      "add" },
66e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
67e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x03, REG_OPER_OP_ORDER,      "add" },
68e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
69e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x09, OPER_REG_OP_ORDER,      "or" },
70e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
71e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x0B, REG_OPER_OP_ORDER,      "or" },
72e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
73e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x11, OPER_REG_OP_ORDER,      "adc" },
74e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
75e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x13, REG_OPER_OP_ORDER,      "adc" },
76e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
77e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x19, OPER_REG_OP_ORDER,      "sbb" },
78e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
79e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
80e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
81e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x21, OPER_REG_OP_ORDER,      "and" },
82e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
83e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x23, REG_OPER_OP_ORDER,      "and" },
84e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
85e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x29, OPER_REG_OP_ORDER,      "sub" },
86e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
87e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x2B, REG_OPER_OP_ORDER,      "sub" },
88e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
89e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x31, OPER_REG_OP_ORDER,      "xor" },
90e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
91e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x33, REG_OPER_OP_ORDER,      "xor" },
92e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
93e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x39, OPER_REG_OP_ORDER,      "cmp" },
94e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
95e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
96528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  { 0x63, REG_OPER_OP_ORDER,      "movsxl" },
97e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
98e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x85, REG_OPER_OP_ORDER,      "test" },
99e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
100e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x87, REG_OPER_OP_ORDER,      "xchg" },
101e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
102e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x89, OPER_REG_OP_ORDER,      "mov" },
103e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
104e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x8B, REG_OPER_OP_ORDER,      "mov" },
105b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  { 0x8D, REG_OPER_OP_ORDER,      "lea" },
10668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { -1, UNSET_OP_ORDER, "" }
10768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
10868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
10968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1107c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic zero_operands_instr[] = {
11168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0xC3, UNSET_OP_ORDER, "ret" },
11268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0xC9, UNSET_OP_ORDER, "leave" },
11368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0xF4, UNSET_OP_ORDER, "hlt" },
11464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  { 0xFC, UNSET_OP_ORDER, "cld" },
11568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0xCC, UNSET_OP_ORDER, "int3" },
11668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x60, UNSET_OP_ORDER, "pushad" },
11768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x61, UNSET_OP_ORDER, "popad" },
11868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x9C, UNSET_OP_ORDER, "pushfd" },
11968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x9D, UNSET_OP_ORDER, "popfd" },
12068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x9E, UNSET_OP_ORDER, "sahf" },
12168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x99, UNSET_OP_ORDER, "cdq" },
12268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x9B, UNSET_OP_ORDER, "fwait" },
123b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  { 0xA4, UNSET_OP_ORDER, "movs" },
124b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  { 0xA5, UNSET_OP_ORDER, "movs" },
125b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  { 0xA6, UNSET_OP_ORDER, "cmps" },
126b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  { 0xA7, UNSET_OP_ORDER, "cmps" },
12768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { -1, UNSET_OP_ORDER, "" }
12868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
12968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
13068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1317c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic call_jump_instr[] = {
13268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0xE8, UNSET_OP_ORDER, "call" },
13368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0xE9, UNSET_OP_ORDER, "jmp" },
13468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { -1, UNSET_OP_ORDER, "" }
13568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
13668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
13768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1387c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic short_immediate_instr[] = {
13968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x05, UNSET_OP_ORDER, "add" },
14068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x0D, UNSET_OP_ORDER, "or" },
14168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x15, UNSET_OP_ORDER, "adc" },
142e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  { 0x1D, UNSET_OP_ORDER, "sbb" },
14368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x25, UNSET_OP_ORDER, "and" },
14468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x2D, UNSET_OP_ORDER, "sub" },
14568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x35, UNSET_OP_ORDER, "xor" },
14668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { 0x3D, UNSET_OP_ORDER, "cmp" },
14768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  { -1, UNSET_OP_ORDER, "" }
14868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
14968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
15068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1517c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const char* const conditional_code_suffix[] = {
152b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  "o", "no", "c", "nc", "z", "nz", "na", "a",
15368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "s", "ns", "pe", "po", "l", "ge", "le", "g"
15468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
15568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
15668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
15768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgenum InstructionType {
15868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  NO_INSTR,
15968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  ZERO_OPERANDS_INSTR,
16068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  TWO_OPERANDS_INSTR,
16168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  JUMP_CONDITIONAL_SHORT_INSTR,
16268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  REGISTER_INSTR,
16368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
16468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  MOVE_REG_INSTR,
16568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  CALL_JUMP_INSTR,
16668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  SHORT_IMMEDIATE_INSTR
16768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
16868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
16968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
170b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgenum Prefixes {
171b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ESCAPE_PREFIX = 0x0F,
172b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
173b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
174b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  REPNE_PREFIX = 0xF2,
175b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  REP_PREFIX = 0xF3,
176b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  REPEQ_PREFIX = REP_PREFIX
177b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org};
178b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
179b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
18068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgstruct InstructionDesc {
18168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* mnem;
18268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  InstructionType type;
183e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  OperandType op_order_;
184e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  bool byte_size_operation;  // Fixed 8-bit operation.
18568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
18668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
18768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
18868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgclass InstructionTable {
18968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org public:
19068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  InstructionTable();
19168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const InstructionDesc& Get(byte x) const {
19268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return instructions_[x];
19368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
19468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
19568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org private:
19668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  InstructionDesc instructions_[256];
19768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void Clear();
19868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void Init();
1997c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  void CopyTable(const ByteMnemonic bm[], InstructionType type);
200e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
20168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     const char* mnem);
20268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void AddJumpConditionalShort();
20368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
20468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
20568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
20668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgInstructionTable::InstructionTable() {
20768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  Clear();
20868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  Init();
20968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
21068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
21168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
21268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgvoid InstructionTable::Clear() {
21368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (int i = 0; i < 256; i++) {
214e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    instructions_[i].mnem = "(bad)";
21568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    instructions_[i].type = NO_INSTR;
21668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    instructions_[i].op_order_ = UNSET_OP_ORDER;
217e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    instructions_[i].byte_size_operation = false;
21868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
21968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
22068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
22168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
22268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgvoid InstructionTable::Init() {
22368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
22468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
22568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
22668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
22768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  AddJumpConditionalShort();
228e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
229e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
230e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
23168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
23268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
23368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
2347c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgvoid InstructionTable::CopyTable(const ByteMnemonic bm[],
2357c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                 InstructionType type) {
23668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (int i = 0; bm[i].b >= 0; i++) {
23768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    InstructionDesc* id = &instructions_[bm[i].b];
23868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    id->mnem = bm[i].mnem;
239e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    OperandType op_order = bm[i].op_order_;
240e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    id->op_order_ =
241e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
2423811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
24368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    id->type = type;
244e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
24568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
24668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
24768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
24868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
249e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgvoid InstructionTable::SetTableRange(InstructionType type,
250e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                     byte start,
251e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                     byte end,
252e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                     bool byte_size,
253e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                     const char* mnem) {
25468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (byte b = start; b <= end; b++) {
25568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    InstructionDesc* id = &instructions_[b];
2563811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
25768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    id->mnem = mnem;
25868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    id->type = type;
259e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    id->byte_size_operation = byte_size;
26068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
26168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
26268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
26368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
26468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgvoid InstructionTable::AddJumpConditionalShort() {
26568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (byte b = 0x70; b <= 0x7F; b++) {
26668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    InstructionDesc* id = &instructions_[b];
2673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
26868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    id->mnem = NULL;  // Computed depending on condition code.
26968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
27068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
27168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
27268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
27368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
2741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgstatic v8::internal::LazyInstance<InstructionTable>::type instruction_table =
2751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    LAZY_INSTANCE_INITIALIZER;
27668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
277ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
278b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.orgstatic InstructionDesc cmov_instructions[16] = {
279b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
280b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
281b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
282b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
283b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
284b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
285b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
286b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
287b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
288b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
289b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
290b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
291b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
292b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
293b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
294b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
295b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org};
29668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
297e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
298e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org//------------------------------------------------------------------------------
299e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// DisassemblerX64 implementation.
300e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
30168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgenum UnimplementedOpcodeAction {
30268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  CONTINUE_ON_UNIMPLEMENTED_OPCODE,
30368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  ABORT_ON_UNIMPLEMENTED_OPCODE
30468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
30568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
306e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
307e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// A new DisassemblerX64 object is created to disassemble each instruction.
308e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// The object can only disassemble a single instruction.
30968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgclass DisassemblerX64 {
31068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org public:
31168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  DisassemblerX64(const NameConverter& converter,
31268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                  UnimplementedOpcodeAction unimplemented_action =
31368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                      ABORT_ON_UNIMPLEMENTED_OPCODE)
31468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      : converter_(converter),
31568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        tmp_buffer_pos_(0),
31668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        abort_on_unimplemented_(
31768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
31868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        rex_(0),
319e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        operand_size_(0),
320e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        group_1_prefix_(0),
3217d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        byte_size_operand_(false),
3227d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org        instruction_table_(instruction_table.Pointer()) {
32368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    tmp_buffer_[0] = '\0';
32468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
32568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
32668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  virtual ~DisassemblerX64() {
32768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
32868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
32968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Writes one disassembled instruction into 'buffer' (0-terminated).
33068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Returns the length of the disassembled machine instruction in bytes.
33168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
33268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
33368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org private:
334e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  enum OperandSize {
335e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    OPERAND_BYTE_SIZE = 0,
336e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    OPERAND_WORD_SIZE = 1,
337e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    OPERAND_DOUBLEWORD_SIZE = 2,
338e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    OPERAND_QUADWORD_SIZE = 3
339e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  };
34068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
34168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const NameConverter& converter_;
34268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
34368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  unsigned int tmp_buffer_pos_;
34468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool abort_on_unimplemented_;
34568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Prefixes parsed
34668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte rex_;
347e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0.
348e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
349e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // Byte size operand override.
350e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  bool byte_size_operand_;
3517d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const InstructionTable* const instruction_table_;
35268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
35368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void setRex(byte rex) {
35468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    ASSERT_EQ(0x40, rex & 0xF0);
35568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    rex_ = rex;
35668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
35768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
35868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool rex() { return rex_ != 0; }
35968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
36068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool rex_b() { return (rex_ & 0x01) != 0; }
36168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
36268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Actual number of base register given the low bits and the rex.b state.
36368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
36468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
36568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool rex_x() { return (rex_ & 0x02) != 0; }
36668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
36768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool rex_r() { return (rex_ & 0x04) != 0; }
36868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
36968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool rex_w() { return (rex_ & 0x08) != 0; }
37068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
371e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  OperandSize operand_size() {
372e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (byte_size_operand_) return OPERAND_BYTE_SIZE;
373e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (rex_w()) return OPERAND_QUADWORD_SIZE;
374e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (operand_size_ != 0) return OPERAND_WORD_SIZE;
375e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return OPERAND_DOUBLEWORD_SIZE;
37668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
37768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
37868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  char operand_size_code() {
379e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    return "bwlq"[operand_size()];
38068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
38168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
38268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* NameOfCPURegister(int reg) const {
38368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return converter_.NameOfCPURegister(reg);
38468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
38568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
38668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* NameOfByteCPURegister(int reg) const {
38768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return converter_.NameOfByteCPURegister(reg);
38868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
38968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
39068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* NameOfXMMRegister(int reg) const {
39168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return converter_.NameOfXMMRegister(reg);
39268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
39368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
39468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* NameOfAddress(byte* addr) const {
39568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return converter_.NameOfAddress(addr);
39668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
39768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
39868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Disassembler helper functions.
39968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void get_modrm(byte data,
40068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                 int* mod,
40168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                 int* regop,
40268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                 int* rm) {
40368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    *mod = (data >> 6) & 3;
40468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
40568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    *rm = (data & 7) | (rex_b() ? 8 : 0);
40668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
40768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
40868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void get_sib(byte data,
40968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org               int* scale,
41068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org               int* index,
41168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org               int* base) {
41268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    *scale = (data >> 6) & 3;
41368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
414e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    *base = (data & 7) | (rex_b() ? 8 : 0);
41568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
41668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
41768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
41868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
41968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int PrintRightOperandHelper(byte* modrmp,
42068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                              RegisterNameMapping register_name);
42168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int PrintRightOperand(byte* modrmp);
42268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int PrintRightByteOperand(byte* modrmp);
4233811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int PrintRightXMMOperand(byte* modrmp);
42468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int PrintOperands(const char* mnem,
425e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                    OperandType op_order,
42668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                    byte* data);
427e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  int PrintImmediate(byte* data, OperandSize size);
42868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int PrintImmediateOp(byte* data);
429e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  const char* TwoByteMnemonic(byte opcode);
430e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  int TwoByteOpcodeInstruction(byte* data);
4313811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int F6F7Instruction(byte* data);
432e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  int ShiftInstruction(byte* data);
43368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int JumpShort(byte* data);
43468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int JumpConditional(byte* data);
43568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int JumpConditionalShort(byte* data);
43668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int SetCC(byte* data);
43768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int FPUInstruction(byte* data);
4383811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
4393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
44068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void AppendToBuffer(const char* format, ...);
44168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
44268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  void UnimplementedInstruction() {
44368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    if (abort_on_unimplemented_) {
444e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      CHECK(false);
44568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    } else {
44668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("'Unimplemented Instruction'");
44768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
44868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
44968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
45068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
45168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
45268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgvoid DisassemblerX64::AppendToBuffer(const char* format, ...) {
45368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
45468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  va_list args;
45568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  va_start(args, format);
45668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int result = v8::internal::OS::VSNPrintF(buf, format, args);
45768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  va_end(args);
45868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  tmp_buffer_pos_ += result;
45968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
46068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
46168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
46268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::PrintRightOperandHelper(
46368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    byte* modrmp,
464badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    RegisterNameMapping direct_register_name) {
46568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int mod, regop, rm;
46668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  get_modrm(*modrmp, &mod, &regop, &rm);
467badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
468badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org      &DisassemblerX64::NameOfCPURegister;
46968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  switch (mod) {
47068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 0:
47168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      if ((rm & 7) == 5) {
47268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
47368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer("[0x%x]", disp);
47468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        return 5;
47568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      } else if ((rm & 7) == 4) {
47668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        // Codes for SIB byte.
47768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        byte sib = *(modrmp + 1);
47868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int scale, index, base;
47968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_sib(sib, &scale, &index, &base);
48068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
48168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          // index == rsp means no index. Only use sib byte with no index for
48268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          // rsp and r12 base.
48332d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org          AppendToBuffer("[%s]", NameOfCPURegister(base));
48468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          return 2;
48568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else if (base == 5) {
48668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          // base == rbp means no base register (when mod == 0).
48768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
48868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          AppendToBuffer("[%s*%d+0x%x]",
48932d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                         NameOfCPURegister(index),
49068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                         1 << scale, disp);
49168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          return 6;
49268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else if (index != 4 && base != 5) {
49368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          // [base+index*scale]
49468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          AppendToBuffer("[%s+%s*%d]",
49532d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                         NameOfCPURegister(base),
49632d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                         NameOfCPURegister(index),
49768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                         1 << scale);
49868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          return 2;
49968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else {
50068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          UnimplementedInstruction();
50168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          return 1;
50268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
50368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      } else {
50432d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org        AppendToBuffer("[%s]", NameOfCPURegister(rm));
50568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        return 1;
50668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
50768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
50868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 1:  // fall through
50968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 2:
51068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      if ((rm & 7) == 4) {
51168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        byte sib = *(modrmp + 1);
51268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int scale, index, base;
51368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_sib(sib, &scale, &index, &base);
51468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
51568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                              : *reinterpret_cast<char*>(modrmp + 2);
51668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
51768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          if (-disp > 0) {
51832d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org            AppendToBuffer("[%s-0x%x]", NameOfCPURegister(base), -disp);
51968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          } else {
52032d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org            AppendToBuffer("[%s+0x%x]", NameOfCPURegister(base), disp);
52168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          }
52268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else {
52368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          if (-disp > 0) {
52468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            AppendToBuffer("[%s+%s*%d-0x%x]",
52532d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                           NameOfCPURegister(base),
52632d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                           NameOfCPURegister(index),
52768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                           1 << scale,
52868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                           -disp);
52968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          } else {
53068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            AppendToBuffer("[%s+%s*%d+0x%x]",
53132d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                           NameOfCPURegister(base),
53232d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org                           NameOfCPURegister(index),
53368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                           1 << scale,
53468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                           disp);
53568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          }
53668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
53768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        return mod == 2 ? 6 : 3;
53868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      } else {
53968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        // No sib.
54068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
54168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                              : *reinterpret_cast<char*>(modrmp + 1);
54268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        if (-disp > 0) {
54332d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org        AppendToBuffer("[%s-0x%x]", NameOfCPURegister(rm), -disp);
54468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else {
54532d961d4454609ab4251a760fc46b19f661da90clrn@chromium.org        AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp);
54668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
54768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        return (mod == 2) ? 5 : 2;
54868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
54968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
55068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 3:
55168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("%s", (this->*register_name)(rm));
55268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return 1;
55368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    default:
55468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      UnimplementedInstruction();
55568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return 1;
55668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
55768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  UNREACHABLE();
55868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
55968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
56068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
561e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgint DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
562e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  int64_t value;
563e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  int count;
564e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  switch (size) {
565e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    case OPERAND_BYTE_SIZE:
566e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      value = *data;
567e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      count = 1;
568e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
569e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    case OPERAND_WORD_SIZE:
570e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      value = *reinterpret_cast<int16_t*>(data);
571e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      count = 2;
572e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
573e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    case OPERAND_DOUBLEWORD_SIZE:
574e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      value = *reinterpret_cast<uint32_t*>(data);
575e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      count = 4;
576e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
577e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    case OPERAND_QUADWORD_SIZE:
578e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      value = *reinterpret_cast<int32_t*>(data);
579e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      count = 4;
580e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
581e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    default:
582e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      UNREACHABLE();
583e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      value = 0;  // Initialize variables on all paths to satisfy the compiler.
584e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      count = 0;
585e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
586b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  AppendToBuffer("%" V8_PTR_PREFIX "x", value);
587e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  return count;
588e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org}
589e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
590e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
59168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::PrintRightOperand(byte* modrmp) {
59268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return PrintRightOperandHelper(modrmp,
59368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                                 &DisassemblerX64::NameOfCPURegister);
59468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
59568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
59668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
59768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
59868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return PrintRightOperandHelper(modrmp,
59968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                                 &DisassemblerX64::NameOfByteCPURegister);
600b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
601b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
602b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
6033811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgint DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
6043811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  return PrintRightOperandHelper(modrmp,
6053811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                 &DisassemblerX64::NameOfXMMRegister);
6063811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
6073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
6083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
60968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used including the current *data.
61068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
61168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::PrintOperands(const char* mnem,
612e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                   OperandType op_order,
61368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                                   byte* data) {
61468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte modrm = *data;
61568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int mod, regop, rm;
61668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  get_modrm(modrm, &mod, &regop, &rm);
61768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int advance = 0;
618e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  const char* register_name =
619e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      byte_size_operand_ ? NameOfByteCPURegister(regop)
620e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                         : NameOfCPURegister(regop);
62168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  switch (op_order) {
62268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case REG_OPER_OP_ORDER: {
62368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("%s%c %s,",
62468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     mnem,
62568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     operand_size_code(),
626e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                     register_name);
627e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      advance = byte_size_operand_ ? PrintRightByteOperand(data)
628e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                   : PrintRightOperand(data);
62968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
63068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
63168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case OPER_REG_OP_ORDER: {
63268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("%s%c ", mnem, operand_size_code());
633e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      advance = byte_size_operand_ ? PrintRightByteOperand(data)
634e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                   : PrintRightOperand(data);
635e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      AppendToBuffer(",%s", register_name);
63668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
63768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
63868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    default:
63968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      UNREACHABLE();
64068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
64168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
64268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return advance;
643b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
644b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
645b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
64668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used by machine instruction, including *data byte.
64768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Writes immediate instructions to 'tmp_buffer_'.
64868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::PrintImmediateOp(byte* data) {
649e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  bool byte_size_immediate = (*data & 0x02) != 0;
65068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte modrm = *(data + 1);
65168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int mod, regop, rm;
65268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  get_modrm(modrm, &mod, &regop, &rm);
65368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* mnem = "Imm???";
65468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  switch (regop) {
65568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 0:
65668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "add";
65768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
65868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 1:
65968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "or";
66068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
66168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 2:
66268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "adc";
66368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
664a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    case 3:
665a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      mnem = "sbb";
666a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      break;
66768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 4:
66868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "and";
66968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
67068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 5:
67168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "sub";
67268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
67368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 6:
67468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "xor";
67568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
67668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 7:
67768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      mnem = "cmp";
67868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
67968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    default:
68068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      UnimplementedInstruction();
68168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
682e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  AppendToBuffer("%s%c ", mnem, operand_size_code());
68368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int count = PrintRightOperand(data + 1);
684e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  AppendToBuffer(",0x");
685e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  OperandSize immediate_size =
686e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
687e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  count += PrintImmediate(data + 1 + count, immediate_size);
688e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  return 1 + count;
68968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
69068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
69168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
69268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used, including *data.
6933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgint DisassemblerX64::F6F7Instruction(byte* data) {
6943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT(*data == 0xF7 || *data == 0xF6);
69568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte modrm = *(data + 1);
69668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int mod, regop, rm;
69768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  get_modrm(modrm, &mod, &regop, &rm);
69868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (mod == 3 && regop != 0) {
69968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    const char* mnem = NULL;
70068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    switch (regop) {
70168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 2:
70268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        mnem = "not";
70368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
70468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 3:
70568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        mnem = "neg";
70668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
70768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 4:
70868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        mnem = "mul";
70968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
710d2899aa30a5af82205029034f7a491d49c48fc68yangguo@chromium.org      case 5:
711d2899aa30a5af82205029034f7a491d49c48fc68yangguo@chromium.org        mnem = "imul";
712d2899aa30a5af82205029034f7a491d49c48fc68yangguo@chromium.org        break;
71368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 7:
71468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        mnem = "idiv";
71568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
71668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      default:
71768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        UnimplementedInstruction();
71868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
71968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    AppendToBuffer("%s%c %s",
72068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                   mnem,
72168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                   operand_size_code(),
72268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                   NameOfCPURegister(rm));
72368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return 2;
72468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  } else if (regop == 0) {
72568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    AppendToBuffer("test%c ", operand_size_code());
7263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    int count = PrintRightOperand(data + 1);  // Use name of 64-bit register.
7273811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    AppendToBuffer(",0x");
7283811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    count += PrintImmediate(data + 1 + count, operand_size());
7293811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    return 1 + count;
73068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  } else {
73168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    UnimplementedInstruction();
73268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return 2;
73368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
73468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
73568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
73668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
737e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgint DisassemblerX64::ShiftInstruction(byte* data) {
738e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  byte op = *data & (~1);
739e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
740e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    UnimplementedInstruction();
741e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    return 1;
742e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
74368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte modrm = *(data + 1);
74468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int mod, regop, rm;
74568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  get_modrm(modrm, &mod, &regop, &rm);
746e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  regop &= 0x7;  // The REX.R bit does not affect the operation.
74768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int imm8 = -1;
74868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int num_bytes = 2;
749e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  if (mod != 3) {
75068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    UnimplementedInstruction();
751e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    return num_bytes;
752e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
753e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  const char* mnem = NULL;
754e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  switch (regop) {
755e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0:
756e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "rol";
757e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
758e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 1:
759e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "ror";
760e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
761e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 2:
762e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "rcl";
763e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
764e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 3:
765e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "rcr";
766e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
767e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 4:
768e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "shl";
769e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
770e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 5:
771e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "shr";
772e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
773e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 7:
774e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      mnem = "sar";
775e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      break;
776e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    default:
777e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      UnimplementedInstruction();
778e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return num_bytes;
779e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
7803811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_NE(NULL, mnem);
781e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  if (op == 0xD0) {
782e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    imm8 = 1;
783e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else if (op == 0xC0) {
784e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    imm8 = *(data + 2);
785e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    num_bytes = 3;
786e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
787e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  AppendToBuffer("%s%c %s,",
788e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                 mnem,
789e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                 operand_size_code(),
790e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                 byte_size_operand_ ? NameOfByteCPURegister(rm)
791e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                                    : NameOfCPURegister(rm));
792e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  if (op == 0xD2) {
793e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    AppendToBuffer("cl");
794e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else {
795e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    AppendToBuffer("%d", imm8);
79668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
79768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return num_bytes;
79868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
79968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
80068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
80168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used, including *data.
80268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::JumpShort(byte* data) {
8033811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0xEB, *data);
80468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte b = *(data + 1);
80568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte* dest = data + static_cast<int8_t>(b) + 2;
80668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  AppendToBuffer("jmp %s", NameOfAddress(dest));
80768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return 2;
80868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
80968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
81068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
81168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used, including *data.
81268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::JumpConditional(byte* data) {
8133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0x0F, *data);
81468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte cond = *(data + 1) & 0x0F;
81568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
81668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* mnem = conditional_code_suffix[cond];
81768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
81868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return 6;  // includes 0x0F
81968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
82068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
82168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
82268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used, including *data.
82368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::JumpConditionalShort(byte* data) {
82468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte cond = *data & 0x0F;
82568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte b = *(data + 1);
82668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte* dest = data + static_cast<int8_t>(b) + 2;
82768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* mnem = conditional_code_suffix[cond];
82868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
82968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return 2;
83068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
83168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
83268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
83368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used, including *data.
83468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::SetCC(byte* data) {
8353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0x0F, *data);
83668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte cond = *(data + 1) & 0x0F;
83768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  const char* mnem = conditional_code_suffix[cond];
83868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  AppendToBuffer("set%s%c ", mnem, operand_size_code());
83968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  PrintRightByteOperand(data + 2);
84068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return 3;  // includes 0x0F
84168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
84268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
84368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
84468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns number of bytes used, including *data.
84568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::FPUInstruction(byte* data) {
8463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  byte escape_opcode = *data;
8473811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0xD8, escape_opcode & 0xF8);
8483811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  byte modrm_byte = *(data+1);
8493811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8503811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  if (modrm_byte >= 0xC0) {
8513811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    return RegisterFPUInstruction(escape_opcode, modrm_byte);
8523811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  } else {
8533811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
8543811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
8553811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
8563811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgint DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
8583811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                           int modrm_byte,
8593811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                           byte* modrm_start) {
8603811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  const char* mnem = "?";
8613811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
8623811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  switch (escape_opcode) {
8633811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xD9: switch (regop) {
8643811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0: mnem = "fld_s"; break;
8653811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 3: mnem = "fstp_s"; break;
8663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 7: mnem = "fstcw"; break;
8673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
86868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
8693811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8713811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDB: switch (regop) {
8723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0: mnem = "fild_s"; break;
8733811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 1: mnem = "fisttp_s"; break;
8743811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 2: mnem = "fist_s"; break;
8753811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 3: mnem = "fistp_s"; break;
8763811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
8773811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8783811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8793811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8803811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDD: switch (regop) {
8813811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0: mnem = "fld_d"; break;
8823811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 3: mnem = "fstp_d"; break;
8833811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
8843811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8863811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8873811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDF: switch (regop) {
8883811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 5: mnem = "fild_d"; break;
8893811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 7: mnem = "fistp_d"; break;
8903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
8913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    default: UnimplementedInstruction();
8953811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
8963811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  AppendToBuffer("%s ", mnem);
8973811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int count = PrintRightOperand(modrm_start);
8983811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  return count + 1;
8993811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
9003811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9013811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgint DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
9023811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                             byte modrm_byte) {
9033811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  bool has_register = false;  // Is the FPU register encoded in modrm_byte?
9043811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  const char* mnem = "?";
9053811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9063811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  switch (escape_opcode) {
9073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xD8:
9083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      UnimplementedInstruction();
9093811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9103811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9113811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xD9:
9123811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      switch (modrm_byte & 0xF8) {
9134a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case 0xC0:
9144a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          mnem = "fld";
9154a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          has_register = true;
9164a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
9173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC8:
9183811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          mnem = "fxch";
9193811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          has_register = true;
92068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          break;
92168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        default:
9223811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          switch (modrm_byte) {
9233811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE0: mnem = "fchs"; break;
9243811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE1: mnem = "fabs"; break;
92564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xE3: mnem = "fninit"; break;
9263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE4: mnem = "ftst"; break;
9273811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE8: mnem = "fld1"; break;
9284a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org            case 0xEB: mnem = "fldpi"; break;
929a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org            case 0xED: mnem = "fldln2"; break;
9303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xEE: mnem = "fldz"; break;
93164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xF0: mnem = "f2xm1"; break;
932a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org            case 0xF1: mnem = "fyl2x"; break;
93364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xF2: mnem = "fptan"; break;
9343811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xF5: mnem = "fprem1"; break;
9353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xF7: mnem = "fincstp"; break;
9363811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xF8: mnem = "fprem"; break;
93764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xFD: mnem = "fscale"; break;
9383811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xFE: mnem = "fsin"; break;
9393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xFF: mnem = "fcos"; break;
9403811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            default: UnimplementedInstruction();
9413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          }
94268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
9433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9443811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9453811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDA:
9463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if (modrm_byte == 0xE9) {
9473811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fucompp";
9483811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else {
94968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        UnimplementedInstruction();
9503811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
9513811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9523811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9533811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDB:
9543811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if ((modrm_byte & 0xF8) == 0xE8) {
9553811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fucomi";
9563811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        has_register = true;
9573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else if (modrm_byte  == 0xE2) {
9583811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fclex";
9593811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else {
96068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        UnimplementedInstruction();
9613811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
9623811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9633811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9643811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDC:
9653811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      has_register = true;
9663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      switch (modrm_byte & 0xF8) {
9673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC0: mnem = "fadd"; break;
9683811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xE8: mnem = "fsub"; break;
9693811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC8: mnem = "fmul"; break;
9703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xF8: mnem = "fdiv"; break;
9713811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
9723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
9733811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9743811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9753811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDD:
9763811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      has_register = true;
9773811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      switch (modrm_byte & 0xF8) {
9783811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC0: mnem = "ffree"; break;
9793811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xD8: mnem = "fstp"; break;
9803811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
9813811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
9823811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9833811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9843811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDE:
9853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if (modrm_byte  == 0xD9) {
9863811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fcompp";
9873811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else {
9883811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        has_register = true;
9893811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        switch (modrm_byte & 0xF8) {
9903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xC0: mnem = "faddp"; break;
9913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xE8: mnem = "fsubp"; break;
9923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xC8: mnem = "fmulp"; break;
9933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xF8: mnem = "fdivp"; break;
9943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          default: UnimplementedInstruction();
9953811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        }
9963811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
9973811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
9983811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
9993811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDF:
10003811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if (modrm_byte == 0xE0) {
10013811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fnstsw_ax";
10023811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else if ((modrm_byte & 0xF8) == 0xE8) {
10033811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fucomip";
10043811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        has_register = true;
10053811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
10063811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
10073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
10083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    default: UnimplementedInstruction();
10093811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
10103811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
10113811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  if (has_register) {
10123811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
10133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  } else {
101468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    AppendToBuffer("%s", mnem);
101568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
101668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return 2;
101768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
101868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1019e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
10203811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
1021e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// Handle all two-byte opcodes, which start with 0x0F.
1022e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
1023e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
1024e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgint DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
1025e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  byte opcode = *(data + 1);
1026e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  byte* current = data + 2;
1027e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  // At return, "current" points to the start of the next instruction.
1028e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  const char* mnemonic = TwoByteMnemonic(opcode);
10295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (operand_size_ == 0x66) {
10305c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // 0x66 0x0F prefix.
10315c838251403b0be9a882540f1922577abba4c872ager@chromium.org    int mod, regop, rm;
1032ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    if (opcode == 0x3A) {
1033ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      byte third_byte = *current;
1034ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      current = data + 3;
1035ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      if (third_byte == 0x17) {
1036ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        get_modrm(*current, &mod, &regop, &rm);
1037ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
1038ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        current += PrintRightOperand(current);
1039b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1040ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        current += 1;
1041160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      } else if (third_byte == 0x0b) {
1042160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        get_modrm(*current, &mod, &regop, &rm);
1043160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org         // roundsd xmm, xmm/m64, imm8
1044b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer("roundsd %s,", NameOfXMMRegister(regop));
1045b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        current += PrintRightXMMOperand(current);
1046b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer(",%d", (*current) & 3);
1047160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        current += 1;
1048357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      } else {
1049357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org        UnimplementedInstruction();
1050357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      }
1051ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org    } else {
1052ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      get_modrm(*current, &mod, &regop, &rm);
105364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      if (opcode == 0x1f) {
105464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        current++;
105564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        if (rm == 4) {  // SIB byte present.
105664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          current++;
105764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        }
105864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        if (mod == 1) {  // Byte displacement.
105964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          current += 1;
106064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        } else if (mod == 2) {  // 32-bit displacement.
106164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          current += 4;
106264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        }  // else no immediate displacement.
106364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        AppendToBuffer("nop");
106464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      } else if (opcode == 0x28) {
1065b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer("movapd %s,", NameOfXMMRegister(regop));
1066160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        current += PrintRightXMMOperand(current);
1067160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      } else if (opcode == 0x29) {
1068160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        AppendToBuffer("movapd ");
1069160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        current += PrintRightXMMOperand(current);
1070b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer(",%s", NameOfXMMRegister(regop));
1071160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      } else if (opcode == 0x6E) {
1072ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        AppendToBuffer("mov%c %s,",
1073ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org                       rex_w() ? 'q' : 'd',
1074ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org                       NameOfXMMRegister(regop));
1075ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        current += PrintRightOperand(current);
10760ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      } else if (opcode == 0x6F) {
10770ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org        AppendToBuffer("movdqa %s,",
10780ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org                       NameOfXMMRegister(regop));
1079badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        current += PrintRightXMMOperand(current);
1080ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      } else if (opcode == 0x7E) {
1081e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org        AppendToBuffer("mov%c ",
1082e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org                       rex_w() ? 'q' : 'd');
1083e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org        current += PrintRightOperand(current);
1084b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer(",%s", NameOfXMMRegister(regop));
10850ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org      } else if (opcode == 0x7F) {
10860ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org        AppendToBuffer("movdqa ");
1087badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        current += PrintRightXMMOperand(current);
1088b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer(",%s", NameOfXMMRegister(regop));
1089160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      } else if (opcode == 0xD6) {
1090160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        AppendToBuffer("movq ");
1091160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        current += PrintRightXMMOperand(current);
1092b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer(",%s", NameOfXMMRegister(regop));
1093ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org      } else if (opcode == 0x50) {
1094ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org        AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
1095ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org        current += PrintRightXMMOperand(current);
1096ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      } else {
1097ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        const char* mnemonic = "?";
1098ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org        if (opcode == 0x54) {
10995d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org          mnemonic = "andpd";
11005d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org        } else  if (opcode == 0x56) {
11015d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org          mnemonic = "orpd";
11025d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org        } else  if (opcode == 0x57) {
1103ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org          mnemonic = "xorpd";
1104ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        } else if (opcode == 0x2E) {
1105ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org          mnemonic = "ucomisd";
110640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org        } else if (opcode == 0x2F) {
110740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org          mnemonic = "comisd";
1108ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        } else {
1109ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org          UnimplementedInstruction();
1110ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        }
1111ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1112ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org        current += PrintRightXMMOperand(current);
1113ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org      }
11145c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
11155c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else if (group_1_prefix_ == 0xF2) {
11165c838251403b0be9a882540f1922577abba4c872ager@chromium.org    // Beginning of instructions with prefix 0xF2.
11175c838251403b0be9a882540f1922577abba4c872ager@chromium.org
11185c838251403b0be9a882540f1922577abba4c872ager@chromium.org    if (opcode == 0x11 || opcode == 0x10) {
11195c838251403b0be9a882540f1922577abba4c872ager@chromium.org      // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
11205c838251403b0be9a882540f1922577abba4c872ager@chromium.org      AppendToBuffer("movsd ");
11215c838251403b0be9a882540f1922577abba4c872ager@chromium.org      int mod, regop, rm;
11225c838251403b0be9a882540f1922577abba4c872ager@chromium.org      get_modrm(*current, &mod, &regop, &rm);
11235c838251403b0be9a882540f1922577abba4c872ager@chromium.org      if (opcode == 0x11) {
1124badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        current += PrintRightXMMOperand(current);
11255c838251403b0be9a882540f1922577abba4c872ager@chromium.org        AppendToBuffer(",%s", NameOfXMMRegister(regop));
11265c838251403b0be9a882540f1922577abba4c872ager@chromium.org      } else {
11275c838251403b0be9a882540f1922577abba4c872ager@chromium.org        AppendToBuffer("%s,", NameOfXMMRegister(regop));
1128badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        current += PrintRightXMMOperand(current);
11295c838251403b0be9a882540f1922577abba4c872ager@chromium.org      }
11305c838251403b0be9a882540f1922577abba4c872ager@chromium.org    } else if (opcode == 0x2A) {
11315c838251403b0be9a882540f1922577abba4c872ager@chromium.org      // CVTSI2SD: integer to XMM double conversion.
11325c838251403b0be9a882540f1922577abba4c872ager@chromium.org      int mod, regop, rm;
11335c838251403b0be9a882540f1922577abba4c872ager@chromium.org      get_modrm(*current, &mod, &regop, &rm);
113440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
11355c838251403b0be9a882540f1922577abba4c872ager@chromium.org      current += PrintRightOperand(current);
11364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    } else if (opcode == 0x2C) {
11374a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // CVTTSD2SI:
11384a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // Convert with truncation scalar double-precision FP to integer.
11394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      int mod, regop, rm;
11404a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      get_modrm(*current, &mod, &regop, &rm);
11414a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      AppendToBuffer("cvttsd2si%c %s,",
11424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          operand_size_code(), NameOfCPURegister(regop));
11434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      current += PrintRightXMMOperand(current);
11444a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    } else if (opcode == 0x2D) {
11454a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // CVTSD2SI: Convert scalar double-precision FP to integer.
11464a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      int mod, regop, rm;
11474a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      get_modrm(*current, &mod, &regop, &rm);
11484a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      AppendToBuffer("cvtsd2si%c %s,",
11494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          operand_size_code(), NameOfCPURegister(regop));
11504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      current += PrintRightXMMOperand(current);
11514111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
11525c838251403b0be9a882540f1922577abba4c872ager@chromium.org      // XMM arithmetic. Mnemonic was retrieved at the start of this function.
11535c838251403b0be9a882540f1922577abba4c872ager@chromium.org      int mod, regop, rm;
11545c838251403b0be9a882540f1922577abba4c872ager@chromium.org      get_modrm(*current, &mod, &regop, &rm);
11555c838251403b0be9a882540f1922577abba4c872ager@chromium.org      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
11565c838251403b0be9a882540f1922577abba4c872ager@chromium.org      current += PrintRightXMMOperand(current);
11571e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    } else if (opcode == 0xC2) {
11581e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      // Intel manual 2A, Table 3-18.
11591e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      int mod, regop, rm;
11601e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      get_modrm(*current, &mod, &regop, &rm);
11611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      const char* const pseudo_op[] = {
11621e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpeqsd",
11631e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpltsd",
11641e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmplesd",
11651e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpunordsd",
11661e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpneqsd",
11671e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpnltsd",
11681e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpnlesd",
11691e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        "cmpordsd"
11701e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      };
11711e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      AppendToBuffer("%s %s,%s",
11721e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                     pseudo_op[current[1]],
11731e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                     NameOfXMMRegister(regop),
11741e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                     NameOfXMMRegister(rm));
11751e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      current += 2;
11765c838251403b0be9a882540f1922577abba4c872ager@chromium.org    } else {
11775c838251403b0be9a882540f1922577abba4c872ager@chromium.org      UnimplementedInstruction();
11785c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
1179357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  } else if (group_1_prefix_ == 0xF3) {
1180357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    // Instructions with prefix 0xF3.
118140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    if (opcode == 0x11 || opcode == 0x10) {
118240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
118340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      AppendToBuffer("movss ");
118440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      int mod, regop, rm;
118540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      get_modrm(*current, &mod, &regop, &rm);
118640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      if (opcode == 0x11) {
118740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org        current += PrintRightOperand(current);
118840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org        AppendToBuffer(",%s", NameOfXMMRegister(regop));
118940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      } else {
119040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org        AppendToBuffer("%s,", NameOfXMMRegister(regop));
119140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org        current += PrintRightOperand(current);
119240b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      }
119340b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    } else if (opcode == 0x2A) {
119440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      // CVTSI2SS: integer to XMM single conversion.
119540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      int mod, regop, rm;
119640b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      get_modrm(*current, &mod, &regop, &rm);
119740b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
119840b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      current += PrintRightOperand(current);
119940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    } else if (opcode == 0x2C) {
12004a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // CVTTSS2SI:
12014a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // Convert with truncation scalar single-precision FP to dword integer.
12020a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      int mod, regop, rm;
12030a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      get_modrm(*current, &mod, &regop, &rm);
12040a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      AppendToBuffer("cvttss2si%c %s,",
12050a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          operand_size_code(), NameOfCPURegister(regop));
12060a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      current += PrintRightXMMOperand(current);
1207357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    } else if (opcode == 0x5A) {
12084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // CVTSS2SD:
12094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // Convert scalar single-precision FP to scalar double-precision FP.
1210357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      int mod, regop, rm;
1211357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      get_modrm(*current, &mod, &regop, &rm);
1212357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1213357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      current += PrintRightXMMOperand(current);
1214160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    } else if (opcode == 0x7E) {
1215160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      int mod, regop, rm;
1216160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      get_modrm(*current, &mod, &regop, &rm);
1217b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org      AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
1218160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      current += PrintRightXMMOperand(current);
1219357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    } else {
1220357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org      UnimplementedInstruction();
1221357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    }
12225c838251403b0be9a882540f1922577abba4c872ager@chromium.org  } else if (opcode == 0x1F) {
1223e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    // NOP
1224e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    int mod, regop, rm;
1225e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    get_modrm(*current, &mod, &regop, &rm);
1226e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    current++;
122764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    if (rm == 4) {  // SIB byte present.
1228e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      current++;
1229e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    }
1230e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    if (mod == 1) {  // Byte displacement.
1231e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      current += 1;
1232e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    } else if (mod == 2) {  // 32-bit displacement.
1233e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      current += 4;
1234e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    }  // else no immediate displacement.
1235e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    AppendToBuffer("nop");
1236160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
12378e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  } else if (opcode == 0x28) {
1238160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    // movaps xmm, xmm/m128
1239160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    int mod, regop, rm;
1240160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    get_modrm(*current, &mod, &regop, &rm);
1241b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    AppendToBuffer("movaps %s,", NameOfXMMRegister(regop));
1242160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    current += PrintRightXMMOperand(current);
1243160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
12448e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  } else if (opcode == 0x29) {
1245160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    // movaps xmm/m128, xmm
1246160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    int mod, regop, rm;
1247160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    get_modrm(*current, &mod, &regop, &rm);
12488e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    AppendToBuffer("movaps ");
1249160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    current += PrintRightXMMOperand(current);
1250b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    AppendToBuffer(",%s", NameOfXMMRegister(regop));
1251160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1252ec6855e761a7474a580d750a45d748323dd3b7c7verwaest@chromium.org  } else if (opcode == 0xA2) {
1253ec6855e761a7474a580d750a45d748323dd3b7c7verwaest@chromium.org    // CPUID
1254e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    AppendToBuffer("%s", mnemonic);
1255e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1256b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org  } else if ((opcode & 0xF0) == 0x40) {
1257b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org    // CMOVcc: conditional move.
1258b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org    int condition = opcode & 0x0F;
1259b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org    const InstructionDesc& idesc = cmov_instructions[condition];
1260b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org    byte_size_operand_ = idesc.byte_size_operation;
1261b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org    current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1262b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org
1263af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  } else if (opcode >= 0x53 && opcode <= 0x5F) {
1264af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    const char* const pseudo_op[] = {
1265af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "rcpps",
1266af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "andps",
1267af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "andnps",
1268af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "orps",
1269af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "xorps",
1270af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "addps",
1271af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "mulps",
1272af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "cvtps2pd",
1273af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "cvtdq2ps",
1274af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "subps",
1275af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "minps",
1276af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "divps",
1277af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org      "maxps",
1278af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    };
1279ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org    int mod, regop, rm;
1280ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org    get_modrm(*current, &mod, &regop, &rm);
1281af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    AppendToBuffer("%s %s,",
1282af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org                   pseudo_op[opcode - 0x53],
1283af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org                   NameOfXMMRegister(regop));
1284ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org    current += PrintRightXMMOperand(current);
1285ef33a5482a35a9a25f702f8e3f02bb6b49f3854cjkummerow@chromium.org
1286af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org  } else if (opcode == 0xC6) {
1287af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    // shufps xmm, xmm/m128, imm8
1288057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    int mod, regop, rm;
1289057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org    get_modrm(*current, &mod, &regop, &rm);
1290af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
1291160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    current += PrintRightXMMOperand(current);
1292af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    AppendToBuffer(", %d", (*current) & 3);
1293af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org    current += 1;
1294160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
12954121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org  } else if (opcode == 0x50) {
12964121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org    // movmskps reg, xmm
12974121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org    int mod, regop, rm;
12984121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org    get_modrm(*current, &mod, &regop, &rm);
1299b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org    AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
13004121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org    current += PrintRightXMMOperand(current);
13014121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org
1302e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else if ((opcode & 0xF0) == 0x80) {
1303e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    // Jcc: Conditional jump (branch).
1304e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    current = data + JumpConditional(data);
1305e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1306e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1307e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org             opcode == 0xB7 || opcode == 0xAF) {
1308e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    // Size-extending moves, IMUL.
1309e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1310e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1311e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else if ((opcode & 0xF0) == 0x90) {
1312e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
1313e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    current = data + SetCC(data);
1314e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1315e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1316e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    // SHLD, SHRD (double-precision shift), BTS (bit set).
1317e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    AppendToBuffer("%s ", mnemonic);
1318e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    int mod, regop, rm;
1319e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    get_modrm(*current, &mod, &regop, &rm);
1320e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    current += PrintRightOperand(current);
1321e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    if (opcode == 0xAB) {
1322e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      AppendToBuffer(",%s", NameOfCPURegister(regop));
1323e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    } else {
1324e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1325e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    }
1326e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  } else {
1327e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    UnimplementedInstruction();
1328e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  }
1329c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  return static_cast<int>(current - data);
1330e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org}
1331e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1332e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1333e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// Mnemonics for two-byte opcode instructions starting with 0x0F.
1334e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// The argument is the second byte of the two-byte opcode.
133568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// Returns NULL if the instruction is not handled here.
1336e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.orgconst char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
1337e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  switch (opcode) {
133868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 0x1F:
133968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return "nop";
134040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org    case 0x2A:  // F2/F3 prefix.
134140b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org      return "cvtsi2s";
13424111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org    case 0x51:  // F2 prefix.
13434111b80e5083e1ec54273d3275875ccc24cdbbafkmillikin@chromium.org      return "sqrtsd";
1344e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0x58:  // F2 prefix.
1345e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "addsd";
1346e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0x59:  // F2 prefix.
1347e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "mulsd";
13483d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org    case 0x5A:  // F2 prefix.
13493d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org      return "cvtsd2ss";
1350e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0x5C:  // F2 prefix.
1351e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "subsd";
1352e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0x5E:  // F2 prefix.
1353e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "divsd";
135468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 0xA2:
135568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return "cpuid";
135668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 0xA5:
135768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return "shld";
135868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case 0xAB:
135968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return "bts";
1360e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0xAD:
1361e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "shrd";
1362e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0xAF:
1363e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "imul";
1364e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0xB6:
1365e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "movzxb";
1366e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0xB7:
1367e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "movzxw";
1368e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0xBE:
1369e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "movsxb";
1370e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    case 0xBF:
1371e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return "movsxw";
137268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    default:
137368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      return NULL;
137468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
137568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
137668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1377e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org
1378e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org// Disassembles the instruction at instr, and writes it into out_buffer.
137968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
138068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                                       byte* instr) {
138168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  tmp_buffer_pos_ = 0;  // starting to write as position 0
138268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte* data = instr;
138368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  bool processed = true;  // Will be set to false if the current instruction
138468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                          // is not in 'instructions' table.
138568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  byte current;
138668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
138768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Scan for prefixes.
138868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  while (true) {
138968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    current = *data;
1390b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
1391e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      operand_size_ = current;
1392e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    } else if ((current & 0xF0) == 0x40) {  // REX prefix.
139368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      setRex(current);
139468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      if (rex_w()) AppendToBuffer("REX.W ");
1395b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
1396e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      group_1_prefix_ = current;
1397e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    } else {  // Not a prefix - an opcode.
139868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
139968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
1400e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org    data++;
140168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
140268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
14037d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  const InstructionDesc& idesc = instruction_table_->Get(current);
1404e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org  byte_size_operand_ = idesc.byte_size_operation;
140568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  switch (idesc.type) {
140668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case ZERO_OPERANDS_INSTR:
1407b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      if (current >= 0xA4 && current <= 0xA7) {
1408b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        // String move or compare operations.
1409b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        if (group_1_prefix_ == REP_PREFIX) {
1410b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org          // REP.
1411b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org          AppendToBuffer("rep ");
1412b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        }
1413b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        if (rex_w()) AppendToBuffer("REX.W ");
1414b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
1415b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      } else {
1416b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        AppendToBuffer("%s", idesc.mnem, operand_size_code());
1417b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
141868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data++;
141968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
142068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
142168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case TWO_OPERANDS_INSTR:
142268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data++;
142368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
142468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
142568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
142668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case JUMP_CONDITIONAL_SHORT_INSTR:
142768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data += JumpConditionalShort(data);
142868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
142968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
143068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case REGISTER_INSTR:
143168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("%s%c %s",
143268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     idesc.mnem,
143368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     operand_size_code(),
143468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     NameOfCPURegister(base_reg(current & 0x07)));
143568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data++;
143668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
143768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case PUSHPOP_INSTR:
143868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("%s %s",
143968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     idesc.mnem,
144068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     NameOfCPURegister(base_reg(current & 0x07)));
144168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data++;
144268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
144368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case MOVE_REG_INSTR: {
144468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      byte* addr = NULL;
144568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      switch (operand_size()) {
1446e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org        case OPERAND_WORD_SIZE:
144768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
144868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          data += 3;
144968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          break;
1450e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org        case OPERAND_DOUBLEWORD_SIZE:
145168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
145268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          data += 5;
145368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          break;
1454e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org        case OPERAND_QUADWORD_SIZE:
145568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
145668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          data += 9;
145768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          break;
145868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        default:
145968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          UNREACHABLE();
146068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
146168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("mov%c %s,%s",
146268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     operand_size_code(),
146368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     NameOfCPURegister(base_reg(current & 0x07)),
146468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                     NameOfAddress(addr));
146568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
146668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
146768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
146868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case CALL_JUMP_INSTR: {
146968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
147068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
147168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data += 5;
147268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
147368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
147468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
147568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case SHORT_IMMEDIATE_INSTR: {
147668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      byte* addr =
147768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1478b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org      AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
147968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      data += 5;
148068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
148168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
148268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
148368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    case NO_INSTR:
148468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      processed = false;
148568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      break;
148668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
148768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    default:
148868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      UNIMPLEMENTED();  // This type is not implemented.
148968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
149068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
149168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // The first byte didn't match any of the simple opcodes, so we
149268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // need to do special processing on it.
149368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (!processed) {
149468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    switch (*data) {
149568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xC2:
149668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
149768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += 3;
149868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
149968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
150068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x69:  // fall through
150168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x6B: {
150268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int mod, regop, rm;
150368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_modrm(*(data + 1), &mod, &regop, &rm);
150468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int32_t imm = *data == 0x6B ? *(data + 2)
150568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            : *reinterpret_cast<int32_t*>(data + 2);
1506cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        AppendToBuffer("imul%c %s,%s,0x%x",
1507cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                       operand_size_code(),
1508cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org                       NameOfCPURegister(regop),
150968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                       NameOfCPURegister(rm), imm);
151068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += 2 + (*data == 0x6B ? 1 : 4);
151168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
1512e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      }
151368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
151468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x81:  // fall through
151568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x83:  // 0x81 with sign extension bit set
151668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += PrintImmediateOp(data);
151768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
151868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1519e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      case 0x0F:
1520e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        data += TwoByteOpcodeInstruction(data);
152168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
152268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
152368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x8F: {
152468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
152568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int mod, regop, rm;
152668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_modrm(*data, &mod, &regop, &rm);
152768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        if (regop == 0) {
152868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          AppendToBuffer("pop ");
152968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          data += PrintRightOperand(data);
153068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
153168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
153268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
153368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
153468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xFF: {
153568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
153668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int mod, regop, rm;
153768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_modrm(*data, &mod, &regop, &rm);
153868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        const char* mnem = NULL;
153968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        switch (regop) {
154068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          case 0:
154168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            mnem = "inc";
154268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            break;
154368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          case 1:
154468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            mnem = "dec";
154568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            break;
154668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          case 2:
154768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            mnem = "call";
154868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            break;
154968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          case 4:
155068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            mnem = "jmp";
155168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            break;
155268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          case 6:
155368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            mnem = "push";
155468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            break;
155568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          default:
155668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org            mnem = "???";
155768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
155868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
155968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                       mnem,
156068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                       operand_size_code());
156168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += PrintRightOperand(data);
156268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
156368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
156468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
156568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xC7:  // imm32, fall through
156668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xC6:  // imm8
156768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      {
156868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        bool is_byte = *data == 0xC6;
156968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
1570badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        if (is_byte) {
1571badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer("movb ");
1572badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data += PrintRightByteOperand(data);
1573badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          int32_t imm = *data;
1574badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer(",0x%x", imm);
1575badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data++;
1576badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        } else {
1577badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer("mov%c ", operand_size_code());
1578badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data += PrintRightOperand(data);
1579e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          if (operand_size() == OPERAND_WORD_SIZE) {
1580e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            int16_t imm = *reinterpret_cast<int16_t*>(data);
1581e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            AppendToBuffer(",0x%x", imm);
1582e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            data += 2;
1583e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          } else {
1584e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            int32_t imm = *reinterpret_cast<int32_t*>(data);
1585e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            AppendToBuffer(",0x%x", imm);
1586e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            data += 4;
1587e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          }
1588badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        }
158968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
159068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
159168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
159268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x80: {
159368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
159468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer("cmpb ");
1595badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        data += PrintRightByteOperand(data);
159668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int32_t imm = *data;
159768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer(",0x%x", imm);
159868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
159968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
160068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
160168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
160268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x88:  // 8bit, fall through
160368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x89:  // 32bit
160468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      {
160568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        bool is_byte = *data == 0x88;
160668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int mod, regop, rm;
160768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
160868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_modrm(*data, &mod, &regop, &rm);
1609badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        if (is_byte) {
1610badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer("movb ");
1611badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data += PrintRightByteOperand(data);
1612badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1613badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        } else {
1614badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer("mov%c ", operand_size_code());
1615badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data += PrintRightOperand(data);
1616badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          AppendToBuffer(",%s", NameOfCPURegister(regop));
1617badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org        }
161868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
161968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
162068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
162168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x90:
162268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x91:
162368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x92:
162468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x93:
162568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x94:
162668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x95:
162768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x96:
162868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x97: {
16293811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
163068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        if (reg == 0) {
163168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          AppendToBuffer("nop");  // Common name for xchg rax,rax.
163268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else {
1633b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org          AppendToBuffer("xchg%c rax,%s",
163468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                         operand_size_code(),
1635e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                         NameOfCPURegister(reg));
163668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
16373811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        data++;
163868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      }
16393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        break;
1640a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB0:
1641a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB1:
1642a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB2:
1643a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB3:
1644a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB4:
1645a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB5:
1646a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB6:
1647a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB7:
1648a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB8:
1649a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xB9:
1650a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xBA:
1651a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xBB:
1652a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xBC:
1653a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xBD:
1654a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xBE:
1655a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      case 0xBF: {
1656a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        // mov reg8,imm8 or mov reg32,imm32
1657a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        byte opcode = *data;
1658a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        data++;
1659a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        bool is_32bit = (opcode >= 0xB8);
1660a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
1661a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        if (is_32bit) {
1662b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org          AppendToBuffer("mov%c %s,",
1663a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org                         operand_size_code(),
1664a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org                         NameOfCPURegister(reg));
1665e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
1666a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        } else {
1667b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org          AppendToBuffer("movb %s,",
1668a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org                         NameOfByteCPURegister(reg));
1669e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          data += PrintImmediate(data, OPERAND_BYTE_SIZE);
1670a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        }
1671a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org        break;
1672a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      }
167368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xFE: {
167468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data++;
167568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        int mod, regop, rm;
167668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        get_modrm(*data, &mod, &regop, &rm);
16774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        if (regop == 1) {
16784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          AppendToBuffer("decb ");
1679badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data += PrintRightByteOperand(data);
168068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        } else {
168168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org          UnimplementedInstruction();
168268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        }
168368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
1684a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      }
168568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x68:
168668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
168768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += 5;
168868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
168968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
169068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0x6A:
169168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
169268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += 2;
169368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
169468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
16950b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org      case 0xA1:  // Fall through.
16960b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org      case 0xA3:
16970b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org        switch (operand_size()) {
1698e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          case OPERAND_DOUBLEWORD_SIZE: {
16990b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            const char* memory_location = NameOfAddress(
17000b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                reinterpret_cast<byte*>(
17010b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                    *reinterpret_cast<int32_t*>(data + 1)));
1702b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org            if (*data == 0xA1) {  // Opcode 0xA1
17030b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org              AppendToBuffer("movzxlq rax,(%s)", memory_location);
1704b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org            } else {  // Opcode 0xA3
17050b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org              AppendToBuffer("movzxlq (%s),rax", memory_location);
17060b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            }
17070b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            data += 5;
17080b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            break;
17090b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org          }
1710e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          case OPERAND_QUADWORD_SIZE: {
17110b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            // New x64 instruction mov rax,(imm_64).
17120b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            const char* memory_location = NameOfAddress(
17130b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org                *reinterpret_cast<byte**>(data + 1));
1714b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org            if (*data == 0xA1) {  // Opcode 0xA1
17150b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org              AppendToBuffer("movq rax,(%s)", memory_location);
1716b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org            } else {  // Opcode 0xA3
17170b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org              AppendToBuffer("movq (%s),rax", memory_location);
17180b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            }
17190b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            data += 9;
17200b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            break;
17210b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org          }
17220b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org          default:
17230b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            UnimplementedInstruction();
17240b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org            data += 2;
17250b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org        }
17260b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org        break;
17270b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org
172868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xA8:
172968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
173068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += 2;
173168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
173268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1733e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      case 0xA9: {
1734e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        int64_t value = 0;
1735e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        switch (operand_size()) {
1736e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          case OPERAND_WORD_SIZE:
1737e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            value = *reinterpret_cast<uint16_t*>(data + 1);
1738e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            data += 3;
1739e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            break;
1740e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          case OPERAND_DOUBLEWORD_SIZE:
1741e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            value = *reinterpret_cast<uint32_t*>(data + 1);
1742e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            data += 5;
1743e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            break;
1744e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org          case OPERAND_QUADWORD_SIZE:
1745e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            value = *reinterpret_cast<int32_t*>(data + 1);
1746e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            data += 5;
1747e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            break;
1748e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org          default:
1749e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org            UNREACHABLE();
1750e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        }
17510e3f88bd850f46930aa95684377fab02a394ae41ulan@chromium.org        AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x",
175268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                       operand_size_code(),
1753e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org                       value);
175468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
1755e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      }
175668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xD1:  // fall through
175768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xD3:  // fall through
175868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xC1:
1759e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        data += ShiftInstruction(data);
1760e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        break;
1761e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      case 0xD0:  // fall through
1762e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      case 0xD2:  // fall through
1763e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      case 0xC0:
1764e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        byte_size_operand_ = true;
1765e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        data += ShiftInstruction(data);
176668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
176768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
176868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xD9:  // fall through
176968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xDA:  // fall through
177068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xDB:  // fall through
177168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xDC:  // fall through
177268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xDD:  // fall through
177368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xDE:  // fall through
177468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xDF:
177568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += FPUInstruction(data);
177668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
177768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
177868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xEB:
177968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        data += JumpShort(data);
178068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
178168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
17823811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      case 0xF6:
17833811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        byte_size_operand_ = true;  // fall through
178468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      case 0xF7:
17853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        data += F6F7Instruction(data);
178668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        break;
178768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
17884121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org      case 0x3C:
1789b4968bea48ba224f54110f626278e2c04649dd5bmstarzinger@chromium.org        AppendToBuffer("cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
17904121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org        data +=2;
17914121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org        break;
17924121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org
179368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      default:
179468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        UnimplementedInstruction();
1795e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        data += 1;
179668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
179768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }  // !processed
179868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
179968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
180068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    tmp_buffer_[tmp_buffer_pos_] = '\0';
180168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
180268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1803c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  int instr_len = static_cast<int>(data - instr);
180468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  ASSERT(instr_len > 0);  // Ensure progress.
180568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
180668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  int outp = 0;
180768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // Instruction bytes.
180868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (byte* bp = instr; bp < data; bp++) {
180968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    outp += v8::internal::OS::SNPrintF(out_buffer + outp, "%02x", *bp);
181068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
181168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (int i = 6 - instr_len; i >= 0; i--) {
181268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    outp += v8::internal::OS::SNPrintF(out_buffer + outp, "  ");
181368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
181468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
181568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  outp += v8::internal::OS::SNPrintF(out_buffer + outp, " %s",
181668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                                     tmp_buffer_.start());
181768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return instr_len;
181868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
181968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
1820e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
182168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org//------------------------------------------------------------------------------
182268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
182368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
182468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgstatic const char* cpu_regs[16] = {
182568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
182668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
182768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
182868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
182968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
183068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgstatic const char* byte_cpu_regs[16] = {
183168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
183268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
183368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
183468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
183568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
183668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgstatic const char* xmm_regs[16] = {
183768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
183868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
183968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org};
184068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
184168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
184268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgconst char* NameConverter::NameOfAddress(byte* addr) const {
1843ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
1844ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return tmp_buffer_.start();
184568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org}
184668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
184768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
184868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgconst char* NameConverter::NameOfConstant(byte* addr) const {
184968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return NameOfAddress(addr);
1850b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1851b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
1852b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
1853b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.orgconst char* NameConverter::NameOfCPURegister(int reg) const {
185468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (0 <= reg && reg < 16)
185568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return cpu_regs[reg];
185668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return "noreg";
1857b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1858b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
1859b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
186068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgconst char* NameConverter::NameOfByteCPURegister(int reg) const {
186168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (0 <= reg && reg < 16)
186268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return byte_cpu_regs[reg];
186368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return "noreg";
1864b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1865b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
1866b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
186768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgconst char* NameConverter::NameOfXMMRegister(int reg) const {
186868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  if (0 <= reg && reg < 16)
186968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    return xmm_regs[reg];
187068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return "noxmmreg";
1871b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1872b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
187368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
187468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgconst char* NameConverter::NameInCode(byte* addr) const {
187568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  // X64 does not embed debug strings at the moment.
187668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  UNREACHABLE();
187768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return "";
1878b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1879b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
1880e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
188168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org//------------------------------------------------------------------------------
188268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
188368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgDisassembler::Disassembler(const NameConverter& converter)
188468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    : converter_(converter) { }
188568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
188668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgDisassembler::~Disassembler() { }
188768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
188868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
188968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
189068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org                                    byte* instruction) {
189168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
189268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return d.InstructionDecode(buffer, instruction);
1893b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1894b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
189568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
189668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org// The X64 assembler does not use constant pools.
189768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint Disassembler::ConstantPoolSizeAt(byte* instruction) {
189868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  return -1;
1899b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1900b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
190168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
190268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgvoid Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
190368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  NameConverter converter;
190468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  Disassembler d(converter);
190568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  for (byte* pc = begin; pc < end;) {
190668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    v8::internal::EmbeddedVector<char, 128> buffer;
190768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    buffer[0] = '\0';
190868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    byte* prev_pc = pc;
190968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    pc += d.InstructionDecode(buffer, pc);
191068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    fprintf(f, "%p", prev_pc);
191168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    fprintf(f, "    ");
191268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
191368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    for (byte* bp = prev_pc; bp < pc; bp++) {
191468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      fprintf(f, "%02x", *bp);
191568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
1916c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
191768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org      fprintf(f, "  ");
191868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
191968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    fprintf(f, "  %s\n", buffer.start());
192068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org  }
1921b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}
1922b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
1923b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org}  // namespace disasm
19249dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
19259dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_X64
1926