Home | History | Annotate | Download | only in x64
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <assert.h>
     29 #include <stdio.h>
     30 #include <stdarg.h>
     31 
     32 #include "v8.h"
     33 
     34 #if V8_TARGET_ARCH_X64
     35 
     36 #include "disasm.h"
     37 #include "lazy-instance.h"
     38 
     39 namespace disasm {
     40 
     41 enum OperandType {
     42   UNSET_OP_ORDER = 0,
     43   // Operand size decides between 16, 32 and 64 bit operands.
     44   REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
     45   OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
     46   // Fixed 8-bit operands.
     47   BYTE_SIZE_OPERAND_FLAG = 4,
     48   BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
     49   BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
     50 };
     51 
     52 
     53 //------------------------------------------------------------------
     54 // Tables
     55 //------------------------------------------------------------------
     56 struct ByteMnemonic {
     57   int b;  // -1 terminates, otherwise must be in range (0..255)
     58   OperandType op_order_;
     59   const char* mnem;
     60 };
     61 
     62 
     63 static const ByteMnemonic two_operands_instr[] = {
     64   { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
     65   { 0x01, OPER_REG_OP_ORDER,      "add" },
     66   { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
     67   { 0x03, REG_OPER_OP_ORDER,      "add" },
     68   { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
     69   { 0x09, OPER_REG_OP_ORDER,      "or" },
     70   { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
     71   { 0x0B, REG_OPER_OP_ORDER,      "or" },
     72   { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
     73   { 0x11, OPER_REG_OP_ORDER,      "adc" },
     74   { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
     75   { 0x13, REG_OPER_OP_ORDER,      "adc" },
     76   { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
     77   { 0x19, OPER_REG_OP_ORDER,      "sbb" },
     78   { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
     79   { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
     80   { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
     81   { 0x21, OPER_REG_OP_ORDER,      "and" },
     82   { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
     83   { 0x23, REG_OPER_OP_ORDER,      "and" },
     84   { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
     85   { 0x29, OPER_REG_OP_ORDER,      "sub" },
     86   { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
     87   { 0x2B, REG_OPER_OP_ORDER,      "sub" },
     88   { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
     89   { 0x31, OPER_REG_OP_ORDER,      "xor" },
     90   { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
     91   { 0x33, REG_OPER_OP_ORDER,      "xor" },
     92   { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
     93   { 0x39, OPER_REG_OP_ORDER,      "cmp" },
     94   { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
     95   { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
     96   { 0x63, REG_OPER_OP_ORDER,      "movsxlq" },
     97   { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
     98   { 0x85, REG_OPER_OP_ORDER,      "test" },
     99   { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
    100   { 0x87, REG_OPER_OP_ORDER,      "xchg" },
    101   { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
    102   { 0x89, OPER_REG_OP_ORDER,      "mov" },
    103   { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
    104   { 0x8B, REG_OPER_OP_ORDER,      "mov" },
    105   { 0x8D, REG_OPER_OP_ORDER,      "lea" },
    106   { -1, UNSET_OP_ORDER, "" }
    107 };
    108 
    109 
    110 static const ByteMnemonic zero_operands_instr[] = {
    111   { 0xC3, UNSET_OP_ORDER, "ret" },
    112   { 0xC9, UNSET_OP_ORDER, "leave" },
    113   { 0xF4, UNSET_OP_ORDER, "hlt" },
    114   { 0xFC, UNSET_OP_ORDER, "cld" },
    115   { 0xCC, UNSET_OP_ORDER, "int3" },
    116   { 0x60, UNSET_OP_ORDER, "pushad" },
    117   { 0x61, UNSET_OP_ORDER, "popad" },
    118   { 0x9C, UNSET_OP_ORDER, "pushfd" },
    119   { 0x9D, UNSET_OP_ORDER, "popfd" },
    120   { 0x9E, UNSET_OP_ORDER, "sahf" },
    121   { 0x99, UNSET_OP_ORDER, "cdq" },
    122   { 0x9B, UNSET_OP_ORDER, "fwait" },
    123   { 0xA4, UNSET_OP_ORDER, "movs" },
    124   { 0xA5, UNSET_OP_ORDER, "movs" },
    125   { 0xA6, UNSET_OP_ORDER, "cmps" },
    126   { 0xA7, UNSET_OP_ORDER, "cmps" },
    127   { -1, UNSET_OP_ORDER, "" }
    128 };
    129 
    130 
    131 static const ByteMnemonic call_jump_instr[] = {
    132   { 0xE8, UNSET_OP_ORDER, "call" },
    133   { 0xE9, UNSET_OP_ORDER, "jmp" },
    134   { -1, UNSET_OP_ORDER, "" }
    135 };
    136 
    137 
    138 static const ByteMnemonic short_immediate_instr[] = {
    139   { 0x05, UNSET_OP_ORDER, "add" },
    140   { 0x0D, UNSET_OP_ORDER, "or" },
    141   { 0x15, UNSET_OP_ORDER, "adc" },
    142   { 0x1D, UNSET_OP_ORDER, "sbb" },
    143   { 0x25, UNSET_OP_ORDER, "and" },
    144   { 0x2D, UNSET_OP_ORDER, "sub" },
    145   { 0x35, UNSET_OP_ORDER, "xor" },
    146   { 0x3D, UNSET_OP_ORDER, "cmp" },
    147   { -1, UNSET_OP_ORDER, "" }
    148 };
    149 
    150 
    151 static const char* const conditional_code_suffix[] = {
    152   "o", "no", "c", "nc", "z", "nz", "na", "a",
    153   "s", "ns", "pe", "po", "l", "ge", "le", "g"
    154 };
    155 
    156 
    157 enum InstructionType {
    158   NO_INSTR,
    159   ZERO_OPERANDS_INSTR,
    160   TWO_OPERANDS_INSTR,
    161   JUMP_CONDITIONAL_SHORT_INSTR,
    162   REGISTER_INSTR,
    163   PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
    164   MOVE_REG_INSTR,
    165   CALL_JUMP_INSTR,
    166   SHORT_IMMEDIATE_INSTR
    167 };
    168 
    169 
    170 enum Prefixes {
    171   ESCAPE_PREFIX = 0x0F,
    172   OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
    173   ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
    174   REPNE_PREFIX = 0xF2,
    175   REP_PREFIX = 0xF3,
    176   REPEQ_PREFIX = REP_PREFIX
    177 };
    178 
    179 
    180 struct InstructionDesc {
    181   const char* mnem;
    182   InstructionType type;
    183   OperandType op_order_;
    184   bool byte_size_operation;  // Fixed 8-bit operation.
    185 };
    186 
    187 
    188 class InstructionTable {
    189  public:
    190   InstructionTable();
    191   const InstructionDesc& Get(byte x) const {
    192     return instructions_[x];
    193   }
    194 
    195  private:
    196   InstructionDesc instructions_[256];
    197   void Clear();
    198   void Init();
    199   void CopyTable(const ByteMnemonic bm[], InstructionType type);
    200   void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
    201                      const char* mnem);
    202   void AddJumpConditionalShort();
    203 };
    204 
    205 
    206 InstructionTable::InstructionTable() {
    207   Clear();
    208   Init();
    209 }
    210 
    211 
    212 void InstructionTable::Clear() {
    213   for (int i = 0; i < 256; i++) {
    214     instructions_[i].mnem = "(bad)";
    215     instructions_[i].type = NO_INSTR;
    216     instructions_[i].op_order_ = UNSET_OP_ORDER;
    217     instructions_[i].byte_size_operation = false;
    218   }
    219 }
    220 
    221 
    222 void InstructionTable::Init() {
    223   CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
    224   CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
    225   CopyTable(call_jump_instr, CALL_JUMP_INSTR);
    226   CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
    227   AddJumpConditionalShort();
    228   SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
    229   SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
    230   SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
    231 }
    232 
    233 
    234 void InstructionTable::CopyTable(const ByteMnemonic bm[],
    235                                  InstructionType type) {
    236   for (int i = 0; bm[i].b >= 0; i++) {
    237     InstructionDesc* id = &instructions_[bm[i].b];
    238     id->mnem = bm[i].mnem;
    239     OperandType op_order = bm[i].op_order_;
    240     id->op_order_ =
    241         static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
    242     ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
    243     id->type = type;
    244     id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
    245   }
    246 }
    247 
    248 
    249 void InstructionTable::SetTableRange(InstructionType type,
    250                                      byte start,
    251                                      byte end,
    252                                      bool byte_size,
    253                                      const char* mnem) {
    254   for (byte b = start; b <= end; b++) {
    255     InstructionDesc* id = &instructions_[b];
    256     ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
    257     id->mnem = mnem;
    258     id->type = type;
    259     id->byte_size_operation = byte_size;
    260   }
    261 }
    262 
    263 
    264 void InstructionTable::AddJumpConditionalShort() {
    265   for (byte b = 0x70; b <= 0x7F; b++) {
    266     InstructionDesc* id = &instructions_[b];
    267     ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered
    268     id->mnem = NULL;  // Computed depending on condition code.
    269     id->type = JUMP_CONDITIONAL_SHORT_INSTR;
    270   }
    271 }
    272 
    273 
    274 static v8::internal::LazyInstance<InstructionTable>::type instruction_table =
    275     LAZY_INSTANCE_INITIALIZER;
    276 
    277 
    278 static InstructionDesc cmov_instructions[16] = {
    279   {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    280   {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    281   {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    282   {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    283   {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    284   {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    285   {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    286   {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    287   {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    288   {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    289   {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    290   {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    291   {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    292   {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    293   {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
    294   {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
    295 };
    296 
    297 
    298 //------------------------------------------------------------------------------
    299 // DisassemblerX64 implementation.
    300 
    301 enum UnimplementedOpcodeAction {
    302   CONTINUE_ON_UNIMPLEMENTED_OPCODE,
    303   ABORT_ON_UNIMPLEMENTED_OPCODE
    304 };
    305 
    306 
    307 // A new DisassemblerX64 object is created to disassemble each instruction.
    308 // The object can only disassemble a single instruction.
    309 class DisassemblerX64 {
    310  public:
    311   DisassemblerX64(const NameConverter& converter,
    312                   UnimplementedOpcodeAction unimplemented_action =
    313                       ABORT_ON_UNIMPLEMENTED_OPCODE)
    314       : converter_(converter),
    315         tmp_buffer_pos_(0),
    316         abort_on_unimplemented_(
    317             unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
    318         rex_(0),
    319         operand_size_(0),
    320         group_1_prefix_(0),
    321         byte_size_operand_(false),
    322         instruction_table_(instruction_table.Pointer()) {
    323     tmp_buffer_[0] = '\0';
    324   }
    325 
    326   virtual ~DisassemblerX64() {
    327   }
    328 
    329   // Writes one disassembled instruction into 'buffer' (0-terminated).
    330   // Returns the length of the disassembled machine instruction in bytes.
    331   int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
    332 
    333  private:
    334   enum OperandSize {
    335     BYTE_SIZE = 0,
    336     WORD_SIZE = 1,
    337     DOUBLEWORD_SIZE = 2,
    338     QUADWORD_SIZE = 3
    339   };
    340 
    341   const NameConverter& converter_;
    342   v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
    343   unsigned int tmp_buffer_pos_;
    344   bool abort_on_unimplemented_;
    345   // Prefixes parsed
    346   byte rex_;
    347   byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0.
    348   byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
    349   // Byte size operand override.
    350   bool byte_size_operand_;
    351   const InstructionTable* const instruction_table_;
    352 
    353   void setRex(byte rex) {
    354     ASSERT_EQ(0x40, rex & 0xF0);
    355     rex_ = rex;
    356   }
    357 
    358   bool rex() { return rex_ != 0; }
    359 
    360   bool rex_b() { return (rex_ & 0x01) != 0; }
    361 
    362   // Actual number of base register given the low bits and the rex.b state.
    363   int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
    364 
    365   bool rex_x() { return (rex_ & 0x02) != 0; }
    366 
    367   bool rex_r() { return (rex_ & 0x04) != 0; }
    368 
    369   bool rex_w() { return (rex_ & 0x08) != 0; }
    370 
    371   OperandSize operand_size() {
    372     if (byte_size_operand_) return BYTE_SIZE;
    373     if (rex_w()) return QUADWORD_SIZE;
    374     if (operand_size_ != 0) return WORD_SIZE;
    375     return DOUBLEWORD_SIZE;
    376   }
    377 
    378   char operand_size_code() {
    379     return "bwlq"[operand_size()];
    380   }
    381 
    382   const char* NameOfCPURegister(int reg) const {
    383     return converter_.NameOfCPURegister(reg);
    384   }
    385 
    386   const char* NameOfByteCPURegister(int reg) const {
    387     return converter_.NameOfByteCPURegister(reg);
    388   }
    389 
    390   const char* NameOfXMMRegister(int reg) const {
    391     return converter_.NameOfXMMRegister(reg);
    392   }
    393 
    394   const char* NameOfAddress(byte* addr) const {
    395     return converter_.NameOfAddress(addr);
    396   }
    397 
    398   // Disassembler helper functions.
    399   void get_modrm(byte data,
    400                  int* mod,
    401                  int* regop,
    402                  int* rm) {
    403     *mod = (data >> 6) & 3;
    404     *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
    405     *rm = (data & 7) | (rex_b() ? 8 : 0);
    406   }
    407 
    408   void get_sib(byte data,
    409                int* scale,
    410                int* index,
    411                int* base) {
    412     *scale = (data >> 6) & 3;
    413     *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
    414     *base = (data & 7) | (rex_b() ? 8 : 0);
    415   }
    416 
    417   typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
    418 
    419   int PrintRightOperandHelper(byte* modrmp,
    420                               RegisterNameMapping register_name);
    421   int PrintRightOperand(byte* modrmp);
    422   int PrintRightByteOperand(byte* modrmp);
    423   int PrintRightXMMOperand(byte* modrmp);
    424   int PrintOperands(const char* mnem,
    425                     OperandType op_order,
    426                     byte* data);
    427   int PrintImmediate(byte* data, OperandSize size);
    428   int PrintImmediateOp(byte* data);
    429   const char* TwoByteMnemonic(byte opcode);
    430   int TwoByteOpcodeInstruction(byte* data);
    431   int F6F7Instruction(byte* data);
    432   int ShiftInstruction(byte* data);
    433   int JumpShort(byte* data);
    434   int JumpConditional(byte* data);
    435   int JumpConditionalShort(byte* data);
    436   int SetCC(byte* data);
    437   int FPUInstruction(byte* data);
    438   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
    439   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
    440   void AppendToBuffer(const char* format, ...);
    441 
    442   void UnimplementedInstruction() {
    443     if (abort_on_unimplemented_) {
    444       CHECK(false);
    445     } else {
    446       AppendToBuffer("'Unimplemented Instruction'");
    447     }
    448   }
    449 };
    450 
    451 
    452 void DisassemblerX64::AppendToBuffer(const char* format, ...) {
    453   v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
    454   va_list args;
    455   va_start(args, format);
    456   int result = v8::internal::OS::VSNPrintF(buf, format, args);
    457   va_end(args);
    458   tmp_buffer_pos_ += result;
    459 }
    460 
    461 
    462 int DisassemblerX64::PrintRightOperandHelper(
    463     byte* modrmp,
    464     RegisterNameMapping direct_register_name) {
    465   int mod, regop, rm;
    466   get_modrm(*modrmp, &mod, &regop, &rm);
    467   RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
    468       &DisassemblerX64::NameOfCPURegister;
    469   switch (mod) {
    470     case 0:
    471       if ((rm & 7) == 5) {
    472         int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
    473         AppendToBuffer("[0x%x]", disp);
    474         return 5;
    475       } else if ((rm & 7) == 4) {
    476         // Codes for SIB byte.
    477         byte sib = *(modrmp + 1);
    478         int scale, index, base;
    479         get_sib(sib, &scale, &index, &base);
    480         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
    481           // index == rsp means no index. Only use sib byte with no index for
    482           // rsp and r12 base.
    483           AppendToBuffer("[%s]", NameOfCPURegister(base));
    484           return 2;
    485         } else if (base == 5) {
    486           // base == rbp means no base register (when mod == 0).
    487           int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
    488           AppendToBuffer("[%s*%d+0x%x]",
    489                          NameOfCPURegister(index),
    490                          1 << scale, disp);
    491           return 6;
    492         } else if (index != 4 && base != 5) {
    493           // [base+index*scale]
    494           AppendToBuffer("[%s+%s*%d]",
    495                          NameOfCPURegister(base),
    496                          NameOfCPURegister(index),
    497                          1 << scale);
    498           return 2;
    499         } else {
    500           UnimplementedInstruction();
    501           return 1;
    502         }
    503       } else {
    504         AppendToBuffer("[%s]", NameOfCPURegister(rm));
    505         return 1;
    506       }
    507       break;
    508     case 1:  // fall through
    509     case 2:
    510       if ((rm & 7) == 4) {
    511         byte sib = *(modrmp + 1);
    512         int scale, index, base;
    513         get_sib(sib, &scale, &index, &base);
    514         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
    515                               : *reinterpret_cast<char*>(modrmp + 2);
    516         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
    517           if (-disp > 0) {
    518             AppendToBuffer("[%s-0x%x]", NameOfCPURegister(base), -disp);
    519           } else {
    520             AppendToBuffer("[%s+0x%x]", NameOfCPURegister(base), disp);
    521           }
    522         } else {
    523           if (-disp > 0) {
    524             AppendToBuffer("[%s+%s*%d-0x%x]",
    525                            NameOfCPURegister(base),
    526                            NameOfCPURegister(index),
    527                            1 << scale,
    528                            -disp);
    529           } else {
    530             AppendToBuffer("[%s+%s*%d+0x%x]",
    531                            NameOfCPURegister(base),
    532                            NameOfCPURegister(index),
    533                            1 << scale,
    534                            disp);
    535           }
    536         }
    537         return mod == 2 ? 6 : 3;
    538       } else {
    539         // No sib.
    540         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
    541                               : *reinterpret_cast<char*>(modrmp + 1);
    542         if (-disp > 0) {
    543         AppendToBuffer("[%s-0x%x]", NameOfCPURegister(rm), -disp);
    544         } else {
    545         AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp);
    546         }
    547         return (mod == 2) ? 5 : 2;
    548       }
    549       break;
    550     case 3:
    551       AppendToBuffer("%s", (this->*register_name)(rm));
    552       return 1;
    553     default:
    554       UnimplementedInstruction();
    555       return 1;
    556   }
    557   UNREACHABLE();
    558 }
    559 
    560 
    561 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
    562   int64_t value;
    563   int count;
    564   switch (size) {
    565     case BYTE_SIZE:
    566       value = *data;
    567       count = 1;
    568       break;
    569     case WORD_SIZE:
    570       value = *reinterpret_cast<int16_t*>(data);
    571       count = 2;
    572       break;
    573     case DOUBLEWORD_SIZE:
    574       value = *reinterpret_cast<uint32_t*>(data);
    575       count = 4;
    576       break;
    577     case QUADWORD_SIZE:
    578       value = *reinterpret_cast<int32_t*>(data);
    579       count = 4;
    580       break;
    581     default:
    582       UNREACHABLE();
    583       value = 0;  // Initialize variables on all paths to satisfy the compiler.
    584       count = 0;
    585   }
    586   AppendToBuffer("%" V8_PTR_PREFIX "x", value);
    587   return count;
    588 }
    589 
    590 
    591 int DisassemblerX64::PrintRightOperand(byte* modrmp) {
    592   return PrintRightOperandHelper(modrmp,
    593                                  &DisassemblerX64::NameOfCPURegister);
    594 }
    595 
    596 
    597 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
    598   return PrintRightOperandHelper(modrmp,
    599                                  &DisassemblerX64::NameOfByteCPURegister);
    600 }
    601 
    602 
    603 int DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
    604   return PrintRightOperandHelper(modrmp,
    605                                  &DisassemblerX64::NameOfXMMRegister);
    606 }
    607 
    608 
    609 // Returns number of bytes used including the current *data.
    610 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
    611 int DisassemblerX64::PrintOperands(const char* mnem,
    612                                    OperandType op_order,
    613                                    byte* data) {
    614   byte modrm = *data;
    615   int mod, regop, rm;
    616   get_modrm(modrm, &mod, &regop, &rm);
    617   int advance = 0;
    618   const char* register_name =
    619       byte_size_operand_ ? NameOfByteCPURegister(regop)
    620                          : NameOfCPURegister(regop);
    621   switch (op_order) {
    622     case REG_OPER_OP_ORDER: {
    623       AppendToBuffer("%s%c %s,",
    624                      mnem,
    625                      operand_size_code(),
    626                      register_name);
    627       advance = byte_size_operand_ ? PrintRightByteOperand(data)
    628                                    : PrintRightOperand(data);
    629       break;
    630     }
    631     case OPER_REG_OP_ORDER: {
    632       AppendToBuffer("%s%c ", mnem, operand_size_code());
    633       advance = byte_size_operand_ ? PrintRightByteOperand(data)
    634                                    : PrintRightOperand(data);
    635       AppendToBuffer(",%s", register_name);
    636       break;
    637     }
    638     default:
    639       UNREACHABLE();
    640       break;
    641   }
    642   return advance;
    643 }
    644 
    645 
    646 // Returns number of bytes used by machine instruction, including *data byte.
    647 // Writes immediate instructions to 'tmp_buffer_'.
    648 int DisassemblerX64::PrintImmediateOp(byte* data) {
    649   bool byte_size_immediate = (*data & 0x02) != 0;
    650   byte modrm = *(data + 1);
    651   int mod, regop, rm;
    652   get_modrm(modrm, &mod, &regop, &rm);
    653   const char* mnem = "Imm???";
    654   switch (regop) {
    655     case 0:
    656       mnem = "add";
    657       break;
    658     case 1:
    659       mnem = "or";
    660       break;
    661     case 2:
    662       mnem = "adc";
    663       break;
    664     case 3:
    665       mnem = "sbb";
    666       break;
    667     case 4:
    668       mnem = "and";
    669       break;
    670     case 5:
    671       mnem = "sub";
    672       break;
    673     case 6:
    674       mnem = "xor";
    675       break;
    676     case 7:
    677       mnem = "cmp";
    678       break;
    679     default:
    680       UnimplementedInstruction();
    681   }
    682   AppendToBuffer("%s%c ", mnem, operand_size_code());
    683   int count = PrintRightOperand(data + 1);
    684   AppendToBuffer(",0x");
    685   OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size();
    686   count += PrintImmediate(data + 1 + count, immediate_size);
    687   return 1 + count;
    688 }
    689 
    690 
    691 // Returns number of bytes used, including *data.
    692 int DisassemblerX64::F6F7Instruction(byte* data) {
    693   ASSERT(*data == 0xF7 || *data == 0xF6);
    694   byte modrm = *(data + 1);
    695   int mod, regop, rm;
    696   get_modrm(modrm, &mod, &regop, &rm);
    697   if (mod == 3 && regop != 0) {
    698     const char* mnem = NULL;
    699     switch (regop) {
    700       case 2:
    701         mnem = "not";
    702         break;
    703       case 3:
    704         mnem = "neg";
    705         break;
    706       case 4:
    707         mnem = "mul";
    708         break;
    709       case 5:
    710         mnem = "imul";
    711         break;
    712       case 7:
    713         mnem = "idiv";
    714         break;
    715       default:
    716         UnimplementedInstruction();
    717     }
    718     AppendToBuffer("%s%c %s",
    719                    mnem,
    720                    operand_size_code(),
    721                    NameOfCPURegister(rm));
    722     return 2;
    723   } else if (regop == 0) {
    724     AppendToBuffer("test%c ", operand_size_code());
    725     int count = PrintRightOperand(data + 1);  // Use name of 64-bit register.
    726     AppendToBuffer(",0x");
    727     count += PrintImmediate(data + 1 + count, operand_size());
    728     return 1 + count;
    729   } else {
    730     UnimplementedInstruction();
    731     return 2;
    732   }
    733 }
    734 
    735 
    736 int DisassemblerX64::ShiftInstruction(byte* data) {
    737   byte op = *data & (~1);
    738   if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
    739     UnimplementedInstruction();
    740     return 1;
    741   }
    742   byte modrm = *(data + 1);
    743   int mod, regop, rm;
    744   get_modrm(modrm, &mod, &regop, &rm);
    745   regop &= 0x7;  // The REX.R bit does not affect the operation.
    746   int imm8 = -1;
    747   int num_bytes = 2;
    748   if (mod != 3) {
    749     UnimplementedInstruction();
    750     return num_bytes;
    751   }
    752   const char* mnem = NULL;
    753   switch (regop) {
    754     case 0:
    755       mnem = "rol";
    756       break;
    757     case 1:
    758       mnem = "ror";
    759       break;
    760     case 2:
    761       mnem = "rcl";
    762       break;
    763     case 3:
    764       mnem = "rcr";
    765       break;
    766     case 4:
    767       mnem = "shl";
    768       break;
    769     case 5:
    770       mnem = "shr";
    771       break;
    772     case 7:
    773       mnem = "sar";
    774       break;
    775     default:
    776       UnimplementedInstruction();
    777       return num_bytes;
    778   }
    779   ASSERT_NE(NULL, mnem);
    780   if (op == 0xD0) {
    781     imm8 = 1;
    782   } else if (op == 0xC0) {
    783     imm8 = *(data + 2);
    784     num_bytes = 3;
    785   }
    786   AppendToBuffer("%s%c %s,",
    787                  mnem,
    788                  operand_size_code(),
    789                  byte_size_operand_ ? NameOfByteCPURegister(rm)
    790                                     : NameOfCPURegister(rm));
    791   if (op == 0xD2) {
    792     AppendToBuffer("cl");
    793   } else {
    794     AppendToBuffer("%d", imm8);
    795   }
    796   return num_bytes;
    797 }
    798 
    799 
    800 // Returns number of bytes used, including *data.
    801 int DisassemblerX64::JumpShort(byte* data) {
    802   ASSERT_EQ(0xEB, *data);
    803   byte b = *(data + 1);
    804   byte* dest = data + static_cast<int8_t>(b) + 2;
    805   AppendToBuffer("jmp %s", NameOfAddress(dest));
    806   return 2;
    807 }
    808 
    809 
    810 // Returns number of bytes used, including *data.
    811 int DisassemblerX64::JumpConditional(byte* data) {
    812   ASSERT_EQ(0x0F, *data);
    813   byte cond = *(data + 1) & 0x0F;
    814   byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
    815   const char* mnem = conditional_code_suffix[cond];
    816   AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
    817   return 6;  // includes 0x0F
    818 }
    819 
    820 
    821 // Returns number of bytes used, including *data.
    822 int DisassemblerX64::JumpConditionalShort(byte* data) {
    823   byte cond = *data & 0x0F;
    824   byte b = *(data + 1);
    825   byte* dest = data + static_cast<int8_t>(b) + 2;
    826   const char* mnem = conditional_code_suffix[cond];
    827   AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
    828   return 2;
    829 }
    830 
    831 
    832 // Returns number of bytes used, including *data.
    833 int DisassemblerX64::SetCC(byte* data) {
    834   ASSERT_EQ(0x0F, *data);
    835   byte cond = *(data + 1) & 0x0F;
    836   const char* mnem = conditional_code_suffix[cond];
    837   AppendToBuffer("set%s%c ", mnem, operand_size_code());
    838   PrintRightByteOperand(data + 2);
    839   return 3;  // includes 0x0F
    840 }
    841 
    842 
    843 // Returns number of bytes used, including *data.
    844 int DisassemblerX64::FPUInstruction(byte* data) {
    845   byte escape_opcode = *data;
    846   ASSERT_EQ(0xD8, escape_opcode & 0xF8);
    847   byte modrm_byte = *(data+1);
    848 
    849   if (modrm_byte >= 0xC0) {
    850     return RegisterFPUInstruction(escape_opcode, modrm_byte);
    851   } else {
    852     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
    853   }
    854 }
    855 
    856 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
    857                                            int modrm_byte,
    858                                            byte* modrm_start) {
    859   const char* mnem = "?";
    860   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
    861   switch (escape_opcode) {
    862     case 0xD9: switch (regop) {
    863         case 0: mnem = "fld_s"; break;
    864         case 3: mnem = "fstp_s"; break;
    865         case 7: mnem = "fstcw"; break;
    866         default: UnimplementedInstruction();
    867       }
    868       break;
    869 
    870     case 0xDB: switch (regop) {
    871         case 0: mnem = "fild_s"; break;
    872         case 1: mnem = "fisttp_s"; break;
    873         case 2: mnem = "fist_s"; break;
    874         case 3: mnem = "fistp_s"; break;
    875         default: UnimplementedInstruction();
    876       }
    877       break;
    878 
    879     case 0xDD: switch (regop) {
    880         case 0: mnem = "fld_d"; break;
    881         case 3: mnem = "fstp_d"; break;
    882         default: UnimplementedInstruction();
    883       }
    884       break;
    885 
    886     case 0xDF: switch (regop) {
    887         case 5: mnem = "fild_d"; break;
    888         case 7: mnem = "fistp_d"; break;
    889         default: UnimplementedInstruction();
    890       }
    891       break;
    892 
    893     default: UnimplementedInstruction();
    894   }
    895   AppendToBuffer("%s ", mnem);
    896   int count = PrintRightOperand(modrm_start);
    897   return count + 1;
    898 }
    899 
    900 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
    901                                              byte modrm_byte) {
    902   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
    903   const char* mnem = "?";
    904 
    905   switch (escape_opcode) {
    906     case 0xD8:
    907       UnimplementedInstruction();
    908       break;
    909 
    910     case 0xD9:
    911       switch (modrm_byte & 0xF8) {
    912         case 0xC0:
    913           mnem = "fld";
    914           has_register = true;
    915           break;
    916         case 0xC8:
    917           mnem = "fxch";
    918           has_register = true;
    919           break;
    920         default:
    921           switch (modrm_byte) {
    922             case 0xE0: mnem = "fchs"; break;
    923             case 0xE1: mnem = "fabs"; break;
    924             case 0xE3: mnem = "fninit"; break;
    925             case 0xE4: mnem = "ftst"; break;
    926             case 0xE8: mnem = "fld1"; break;
    927             case 0xEB: mnem = "fldpi"; break;
    928             case 0xED: mnem = "fldln2"; break;
    929             case 0xEE: mnem = "fldz"; break;
    930             case 0xF0: mnem = "f2xm1"; break;
    931             case 0xF1: mnem = "fyl2x"; break;
    932             case 0xF2: mnem = "fptan"; break;
    933             case 0xF5: mnem = "fprem1"; break;
    934             case 0xF7: mnem = "fincstp"; break;
    935             case 0xF8: mnem = "fprem"; break;
    936             case 0xFD: mnem = "fscale"; break;
    937             case 0xFE: mnem = "fsin"; break;
    938             case 0xFF: mnem = "fcos"; break;
    939             default: UnimplementedInstruction();
    940           }
    941       }
    942       break;
    943 
    944     case 0xDA:
    945       if (modrm_byte == 0xE9) {
    946         mnem = "fucompp";
    947       } else {
    948         UnimplementedInstruction();
    949       }
    950       break;
    951 
    952     case 0xDB:
    953       if ((modrm_byte & 0xF8) == 0xE8) {
    954         mnem = "fucomi";
    955         has_register = true;
    956       } else if (modrm_byte  == 0xE2) {
    957         mnem = "fclex";
    958       } else {
    959         UnimplementedInstruction();
    960       }
    961       break;
    962 
    963     case 0xDC:
    964       has_register = true;
    965       switch (modrm_byte & 0xF8) {
    966         case 0xC0: mnem = "fadd"; break;
    967         case 0xE8: mnem = "fsub"; break;
    968         case 0xC8: mnem = "fmul"; break;
    969         case 0xF8: mnem = "fdiv"; break;
    970         default: UnimplementedInstruction();
    971       }
    972       break;
    973 
    974     case 0xDD:
    975       has_register = true;
    976       switch (modrm_byte & 0xF8) {
    977         case 0xC0: mnem = "ffree"; break;
    978         case 0xD8: mnem = "fstp"; break;
    979         default: UnimplementedInstruction();
    980       }
    981       break;
    982 
    983     case 0xDE:
    984       if (modrm_byte  == 0xD9) {
    985         mnem = "fcompp";
    986       } else {
    987         has_register = true;
    988         switch (modrm_byte & 0xF8) {
    989           case 0xC0: mnem = "faddp"; break;
    990           case 0xE8: mnem = "fsubp"; break;
    991           case 0xC8: mnem = "fmulp"; break;
    992           case 0xF8: mnem = "fdivp"; break;
    993           default: UnimplementedInstruction();
    994         }
    995       }
    996       break;
    997 
    998     case 0xDF:
    999       if (modrm_byte == 0xE0) {
   1000         mnem = "fnstsw_ax";
   1001       } else if ((modrm_byte & 0xF8) == 0xE8) {
   1002         mnem = "fucomip";
   1003         has_register = true;
   1004       }
   1005       break;
   1006 
   1007     default: UnimplementedInstruction();
   1008   }
   1009 
   1010   if (has_register) {
   1011     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
   1012   } else {
   1013     AppendToBuffer("%s", mnem);
   1014   }
   1015   return 2;
   1016 }
   1017 
   1018 
   1019 
   1020 // Handle all two-byte opcodes, which start with 0x0F.
   1021 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
   1022 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
   1023 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
   1024   byte opcode = *(data + 1);
   1025   byte* current = data + 2;
   1026   // At return, "current" points to the start of the next instruction.
   1027   const char* mnemonic = TwoByteMnemonic(opcode);
   1028   if (operand_size_ == 0x66) {
   1029     // 0x66 0x0F prefix.
   1030     int mod, regop, rm;
   1031     if (opcode == 0x3A) {
   1032       byte third_byte = *current;
   1033       current = data + 3;
   1034       if (third_byte == 0x17) {
   1035         get_modrm(*current, &mod, &regop, &rm);
   1036         AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
   1037         current += PrintRightOperand(current);
   1038         AppendToBuffer(", %s, %d", NameOfCPURegister(regop), (*current) & 3);
   1039         current += 1;
   1040       } else if (third_byte == 0x0b) {
   1041         get_modrm(*current, &mod, &regop, &rm);
   1042          // roundsd xmm, xmm/m64, imm8
   1043         AppendToBuffer("roundsd %s, ", NameOfCPURegister(regop));
   1044         current += PrintRightOperand(current);
   1045         AppendToBuffer(", %d", (*current) & 3);
   1046         current += 1;
   1047       } else {
   1048         UnimplementedInstruction();
   1049       }
   1050     } else {
   1051       get_modrm(*current, &mod, &regop, &rm);
   1052       if (opcode == 0x1f) {
   1053         current++;
   1054         if (rm == 4) {  // SIB byte present.
   1055           current++;
   1056         }
   1057         if (mod == 1) {  // Byte displacement.
   1058           current += 1;
   1059         } else if (mod == 2) {  // 32-bit displacement.
   1060           current += 4;
   1061         }  // else no immediate displacement.
   1062         AppendToBuffer("nop");
   1063       } else if (opcode == 0x28) {
   1064         AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop));
   1065         current += PrintRightXMMOperand(current);
   1066       } else if (opcode == 0x29) {
   1067         AppendToBuffer("movapd ");
   1068         current += PrintRightXMMOperand(current);
   1069         AppendToBuffer(", %s", NameOfXMMRegister(regop));
   1070       } else if (opcode == 0x6E) {
   1071         AppendToBuffer("mov%c %s,",
   1072                        rex_w() ? 'q' : 'd',
   1073                        NameOfXMMRegister(regop));
   1074         current += PrintRightOperand(current);
   1075       } else if (opcode == 0x6F) {
   1076         AppendToBuffer("movdqa %s,",
   1077                        NameOfXMMRegister(regop));
   1078         current += PrintRightXMMOperand(current);
   1079       } else if (opcode == 0x7E) {
   1080         AppendToBuffer("mov%c ",
   1081                        rex_w() ? 'q' : 'd');
   1082         current += PrintRightOperand(current);
   1083         AppendToBuffer(", %s", NameOfXMMRegister(regop));
   1084       } else if (opcode == 0x7F) {
   1085         AppendToBuffer("movdqa ");
   1086         current += PrintRightXMMOperand(current);
   1087         AppendToBuffer(", %s", NameOfXMMRegister(regop));
   1088       } else if (opcode == 0xD6) {
   1089         AppendToBuffer("movq ");
   1090         current += PrintRightXMMOperand(current);
   1091         AppendToBuffer(", %s", NameOfXMMRegister(regop));
   1092       } else if (opcode == 0x50) {
   1093         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
   1094         current += PrintRightXMMOperand(current);
   1095       } else {
   1096         const char* mnemonic = "?";
   1097         if (opcode == 0x54) {
   1098           mnemonic = "andpd";
   1099         } else  if (opcode == 0x56) {
   1100           mnemonic = "orpd";
   1101         } else  if (opcode == 0x57) {
   1102           mnemonic = "xorpd";
   1103         } else if (opcode == 0x2E) {
   1104           mnemonic = "ucomisd";
   1105         } else if (opcode == 0x2F) {
   1106           mnemonic = "comisd";
   1107         } else {
   1108           UnimplementedInstruction();
   1109         }
   1110         AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1111         current += PrintRightXMMOperand(current);
   1112       }
   1113     }
   1114   } else if (group_1_prefix_ == 0xF2) {
   1115     // Beginning of instructions with prefix 0xF2.
   1116 
   1117     if (opcode == 0x11 || opcode == 0x10) {
   1118       // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
   1119       AppendToBuffer("movsd ");
   1120       int mod, regop, rm;
   1121       get_modrm(*current, &mod, &regop, &rm);
   1122       if (opcode == 0x11) {
   1123         current += PrintRightXMMOperand(current);
   1124         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1125       } else {
   1126         AppendToBuffer("%s,", NameOfXMMRegister(regop));
   1127         current += PrintRightXMMOperand(current);
   1128       }
   1129     } else if (opcode == 0x2A) {
   1130       // CVTSI2SD: integer to XMM double conversion.
   1131       int mod, regop, rm;
   1132       get_modrm(*current, &mod, &regop, &rm);
   1133       AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
   1134       current += PrintRightOperand(current);
   1135     } else if (opcode == 0x2C) {
   1136       // CVTTSD2SI:
   1137       // Convert with truncation scalar double-precision FP to integer.
   1138       int mod, regop, rm;
   1139       get_modrm(*current, &mod, &regop, &rm);
   1140       AppendToBuffer("cvttsd2si%c %s,",
   1141           operand_size_code(), NameOfCPURegister(regop));
   1142       current += PrintRightXMMOperand(current);
   1143     } else if (opcode == 0x2D) {
   1144       // CVTSD2SI: Convert scalar double-precision FP to integer.
   1145       int mod, regop, rm;
   1146       get_modrm(*current, &mod, &regop, &rm);
   1147       AppendToBuffer("cvtsd2si%c %s,",
   1148           operand_size_code(), NameOfCPURegister(regop));
   1149       current += PrintRightXMMOperand(current);
   1150     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
   1151       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
   1152       int mod, regop, rm;
   1153       get_modrm(*current, &mod, &regop, &rm);
   1154       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1155       current += PrintRightXMMOperand(current);
   1156     } else {
   1157       UnimplementedInstruction();
   1158     }
   1159   } else if (group_1_prefix_ == 0xF3) {
   1160     // Instructions with prefix 0xF3.
   1161     if (opcode == 0x11 || opcode == 0x10) {
   1162       // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
   1163       AppendToBuffer("movss ");
   1164       int mod, regop, rm;
   1165       get_modrm(*current, &mod, &regop, &rm);
   1166       if (opcode == 0x11) {
   1167         current += PrintRightOperand(current);
   1168         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1169       } else {
   1170         AppendToBuffer("%s,", NameOfXMMRegister(regop));
   1171         current += PrintRightOperand(current);
   1172       }
   1173     } else if (opcode == 0x2A) {
   1174       // CVTSI2SS: integer to XMM single conversion.
   1175       int mod, regop, rm;
   1176       get_modrm(*current, &mod, &regop, &rm);
   1177       AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
   1178       current += PrintRightOperand(current);
   1179     } else if (opcode == 0x2C) {
   1180       // CVTTSS2SI:
   1181       // Convert with truncation scalar single-precision FP to dword integer.
   1182       int mod, regop, rm;
   1183       get_modrm(*current, &mod, &regop, &rm);
   1184       AppendToBuffer("cvttss2si%c %s,",
   1185           operand_size_code(), NameOfCPURegister(regop));
   1186       current += PrintRightXMMOperand(current);
   1187     } else if (opcode == 0x5A) {
   1188       // CVTSS2SD:
   1189       // Convert scalar single-precision FP to scalar double-precision FP.
   1190       int mod, regop, rm;
   1191       get_modrm(*current, &mod, &regop, &rm);
   1192       AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
   1193       current += PrintRightXMMOperand(current);
   1194     } else if (opcode == 0x7E) {
   1195       int mod, regop, rm;
   1196       get_modrm(*current, &mod, &regop, &rm);
   1197       AppendToBuffer("movq %s, ", NameOfXMMRegister(regop));
   1198       current += PrintRightXMMOperand(current);
   1199     } else {
   1200       UnimplementedInstruction();
   1201     }
   1202   } else if (opcode == 0x1F) {
   1203     // NOP
   1204     int mod, regop, rm;
   1205     get_modrm(*current, &mod, &regop, &rm);
   1206     current++;
   1207     if (rm == 4) {  // SIB byte present.
   1208       current++;
   1209     }
   1210     if (mod == 1) {  // Byte displacement.
   1211       current += 1;
   1212     } else if (mod == 2) {  // 32-bit displacement.
   1213       current += 4;
   1214     }  // else no immediate displacement.
   1215     AppendToBuffer("nop");
   1216 
   1217   } else if (opcode == 0x28) {
   1218     // movaps xmm, xmm/m128
   1219     int mod, regop, rm;
   1220     get_modrm(*current, &mod, &regop, &rm);
   1221     AppendToBuffer("movaps %s, ", NameOfXMMRegister(regop));
   1222     current += PrintRightXMMOperand(current);
   1223 
   1224   } else if (opcode == 0x29) {
   1225     // movaps xmm/m128, xmm
   1226     int mod, regop, rm;
   1227     get_modrm(*current, &mod, &regop, &rm);
   1228     AppendToBuffer("movaps ");
   1229     current += PrintRightXMMOperand(current);
   1230     AppendToBuffer(", %s", NameOfXMMRegister(regop));
   1231 
   1232   } else if (opcode == 0xA2 || opcode == 0x31) {
   1233     // RDTSC or CPUID
   1234     AppendToBuffer("%s", mnemonic);
   1235 
   1236   } else if ((opcode & 0xF0) == 0x40) {
   1237     // CMOVcc: conditional move.
   1238     int condition = opcode & 0x0F;
   1239     const InstructionDesc& idesc = cmov_instructions[condition];
   1240     byte_size_operand_ = idesc.byte_size_operation;
   1241     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
   1242 
   1243   } else if (opcode == 0x57) {
   1244     // xorps xmm, xmm/m128
   1245     int mod, regop, rm;
   1246     get_modrm(*current, &mod, &regop, &rm);
   1247     AppendToBuffer("xorps %s, ", NameOfXMMRegister(regop));
   1248     current += PrintRightXMMOperand(current);
   1249 
   1250   } else if (opcode == 0x50) {
   1251     // movmskps reg, xmm
   1252     int mod, regop, rm;
   1253     get_modrm(*current, &mod, &regop, &rm);
   1254     AppendToBuffer("movmskps %s, ", NameOfCPURegister(regop));
   1255     current += PrintRightXMMOperand(current);
   1256 
   1257   } else if ((opcode & 0xF0) == 0x80) {
   1258     // Jcc: Conditional jump (branch).
   1259     current = data + JumpConditional(data);
   1260 
   1261   } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
   1262              opcode == 0xB7 || opcode == 0xAF) {
   1263     // Size-extending moves, IMUL.
   1264     current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
   1265 
   1266   } else if ((opcode & 0xF0) == 0x90) {
   1267     // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
   1268     current = data + SetCC(data);
   1269 
   1270   } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
   1271     // SHLD, SHRD (double-precision shift), BTS (bit set).
   1272     AppendToBuffer("%s ", mnemonic);
   1273     int mod, regop, rm;
   1274     get_modrm(*current, &mod, &regop, &rm);
   1275     current += PrintRightOperand(current);
   1276     if (opcode == 0xAB) {
   1277       AppendToBuffer(",%s", NameOfCPURegister(regop));
   1278     } else {
   1279       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
   1280     }
   1281   } else {
   1282     UnimplementedInstruction();
   1283   }
   1284   return static_cast<int>(current - data);
   1285 }
   1286 
   1287 
   1288 // Mnemonics for two-byte opcode instructions starting with 0x0F.
   1289 // The argument is the second byte of the two-byte opcode.
   1290 // Returns NULL if the instruction is not handled here.
   1291 const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
   1292   switch (opcode) {
   1293     case 0x1F:
   1294       return "nop";
   1295     case 0x2A:  // F2/F3 prefix.
   1296       return "cvtsi2s";
   1297     case 0x31:
   1298       return "rdtsc";
   1299     case 0x51:  // F2 prefix.
   1300       return "sqrtsd";
   1301     case 0x58:  // F2 prefix.
   1302       return "addsd";
   1303     case 0x59:  // F2 prefix.
   1304       return "mulsd";
   1305     case 0x5C:  // F2 prefix.
   1306       return "subsd";
   1307     case 0x5E:  // F2 prefix.
   1308       return "divsd";
   1309     case 0xA2:
   1310       return "cpuid";
   1311     case 0xA5:
   1312       return "shld";
   1313     case 0xAB:
   1314       return "bts";
   1315     case 0xAD:
   1316       return "shrd";
   1317     case 0xAF:
   1318       return "imul";
   1319     case 0xB6:
   1320       return "movzxb";
   1321     case 0xB7:
   1322       return "movzxw";
   1323     case 0xBE:
   1324       return "movsxb";
   1325     case 0xBF:
   1326       return "movsxw";
   1327     default:
   1328       return NULL;
   1329   }
   1330 }
   1331 
   1332 
   1333 // Disassembles the instruction at instr, and writes it into out_buffer.
   1334 int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
   1335                                        byte* instr) {
   1336   tmp_buffer_pos_ = 0;  // starting to write as position 0
   1337   byte* data = instr;
   1338   bool processed = true;  // Will be set to false if the current instruction
   1339                           // is not in 'instructions' table.
   1340   byte current;
   1341 
   1342   // Scan for prefixes.
   1343   while (true) {
   1344     current = *data;
   1345     if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
   1346       operand_size_ = current;
   1347     } else if ((current & 0xF0) == 0x40) {  // REX prefix.
   1348       setRex(current);
   1349       if (rex_w()) AppendToBuffer("REX.W ");
   1350     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
   1351       group_1_prefix_ = current;
   1352     } else {  // Not a prefix - an opcode.
   1353       break;
   1354     }
   1355     data++;
   1356   }
   1357 
   1358   const InstructionDesc& idesc = instruction_table_->Get(current);
   1359   byte_size_operand_ = idesc.byte_size_operation;
   1360   switch (idesc.type) {
   1361     case ZERO_OPERANDS_INSTR:
   1362       if (current >= 0xA4 && current <= 0xA7) {
   1363         // String move or compare operations.
   1364         if (group_1_prefix_ == REP_PREFIX) {
   1365           // REP.
   1366           AppendToBuffer("rep ");
   1367         }
   1368         if (rex_w()) AppendToBuffer("REX.W ");
   1369         AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
   1370       } else {
   1371         AppendToBuffer("%s", idesc.mnem, operand_size_code());
   1372       }
   1373       data++;
   1374       break;
   1375 
   1376     case TWO_OPERANDS_INSTR:
   1377       data++;
   1378       data += PrintOperands(idesc.mnem, idesc.op_order_, data);
   1379       break;
   1380 
   1381     case JUMP_CONDITIONAL_SHORT_INSTR:
   1382       data += JumpConditionalShort(data);
   1383       break;
   1384 
   1385     case REGISTER_INSTR:
   1386       AppendToBuffer("%s%c %s",
   1387                      idesc.mnem,
   1388                      operand_size_code(),
   1389                      NameOfCPURegister(base_reg(current & 0x07)));
   1390       data++;
   1391       break;
   1392     case PUSHPOP_INSTR:
   1393       AppendToBuffer("%s %s",
   1394                      idesc.mnem,
   1395                      NameOfCPURegister(base_reg(current & 0x07)));
   1396       data++;
   1397       break;
   1398     case MOVE_REG_INSTR: {
   1399       byte* addr = NULL;
   1400       switch (operand_size()) {
   1401         case WORD_SIZE:
   1402           addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
   1403           data += 3;
   1404           break;
   1405         case DOUBLEWORD_SIZE:
   1406           addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
   1407           data += 5;
   1408           break;
   1409         case QUADWORD_SIZE:
   1410           addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
   1411           data += 9;
   1412           break;
   1413         default:
   1414           UNREACHABLE();
   1415       }
   1416       AppendToBuffer("mov%c %s,%s",
   1417                      operand_size_code(),
   1418                      NameOfCPURegister(base_reg(current & 0x07)),
   1419                      NameOfAddress(addr));
   1420       break;
   1421     }
   1422 
   1423     case CALL_JUMP_INSTR: {
   1424       byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
   1425       AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
   1426       data += 5;
   1427       break;
   1428     }
   1429 
   1430     case SHORT_IMMEDIATE_INSTR: {
   1431       byte* addr =
   1432           reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
   1433       AppendToBuffer("%s rax, %s", idesc.mnem, NameOfAddress(addr));
   1434       data += 5;
   1435       break;
   1436     }
   1437 
   1438     case NO_INSTR:
   1439       processed = false;
   1440       break;
   1441 
   1442     default:
   1443       UNIMPLEMENTED();  // This type is not implemented.
   1444   }
   1445 
   1446   // The first byte didn't match any of the simple opcodes, so we
   1447   // need to do special processing on it.
   1448   if (!processed) {
   1449     switch (*data) {
   1450       case 0xC2:
   1451         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
   1452         data += 3;
   1453         break;
   1454 
   1455       case 0x69:  // fall through
   1456       case 0x6B: {
   1457         int mod, regop, rm;
   1458         get_modrm(*(data + 1), &mod, &regop, &rm);
   1459         int32_t imm = *data == 0x6B ? *(data + 2)
   1460             : *reinterpret_cast<int32_t*>(data + 2);
   1461         AppendToBuffer("imul%c %s,%s,0x%x",
   1462                        operand_size_code(),
   1463                        NameOfCPURegister(regop),
   1464                        NameOfCPURegister(rm), imm);
   1465         data += 2 + (*data == 0x6B ? 1 : 4);
   1466         break;
   1467       }
   1468 
   1469       case 0x81:  // fall through
   1470       case 0x83:  // 0x81 with sign extension bit set
   1471         data += PrintImmediateOp(data);
   1472         break;
   1473 
   1474       case 0x0F:
   1475         data += TwoByteOpcodeInstruction(data);
   1476         break;
   1477 
   1478       case 0x8F: {
   1479         data++;
   1480         int mod, regop, rm;
   1481         get_modrm(*data, &mod, &regop, &rm);
   1482         if (regop == 0) {
   1483           AppendToBuffer("pop ");
   1484           data += PrintRightOperand(data);
   1485         }
   1486       }
   1487         break;
   1488 
   1489       case 0xFF: {
   1490         data++;
   1491         int mod, regop, rm;
   1492         get_modrm(*data, &mod, &regop, &rm);
   1493         const char* mnem = NULL;
   1494         switch (regop) {
   1495           case 0:
   1496             mnem = "inc";
   1497             break;
   1498           case 1:
   1499             mnem = "dec";
   1500             break;
   1501           case 2:
   1502             mnem = "call";
   1503             break;
   1504           case 4:
   1505             mnem = "jmp";
   1506             break;
   1507           case 6:
   1508             mnem = "push";
   1509             break;
   1510           default:
   1511             mnem = "???";
   1512         }
   1513         AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
   1514                        mnem,
   1515                        operand_size_code());
   1516         data += PrintRightOperand(data);
   1517       }
   1518         break;
   1519 
   1520       case 0xC7:  // imm32, fall through
   1521       case 0xC6:  // imm8
   1522       {
   1523         bool is_byte = *data == 0xC6;
   1524         data++;
   1525         if (is_byte) {
   1526           AppendToBuffer("movb ");
   1527           data += PrintRightByteOperand(data);
   1528           int32_t imm = *data;
   1529           AppendToBuffer(",0x%x", imm);
   1530           data++;
   1531         } else {
   1532           AppendToBuffer("mov%c ", operand_size_code());
   1533           data += PrintRightOperand(data);
   1534           int32_t imm = *reinterpret_cast<int32_t*>(data);
   1535           AppendToBuffer(",0x%x", imm);
   1536           data += 4;
   1537         }
   1538       }
   1539         break;
   1540 
   1541       case 0x80: {
   1542         data++;
   1543         AppendToBuffer("cmpb ");
   1544         data += PrintRightByteOperand(data);
   1545         int32_t imm = *data;
   1546         AppendToBuffer(",0x%x", imm);
   1547         data++;
   1548       }
   1549         break;
   1550 
   1551       case 0x88:  // 8bit, fall through
   1552       case 0x89:  // 32bit
   1553       {
   1554         bool is_byte = *data == 0x88;
   1555         int mod, regop, rm;
   1556         data++;
   1557         get_modrm(*data, &mod, &regop, &rm);
   1558         if (is_byte) {
   1559           AppendToBuffer("movb ");
   1560           data += PrintRightByteOperand(data);
   1561           AppendToBuffer(",%s", NameOfByteCPURegister(regop));
   1562         } else {
   1563           AppendToBuffer("mov%c ", operand_size_code());
   1564           data += PrintRightOperand(data);
   1565           AppendToBuffer(",%s", NameOfCPURegister(regop));
   1566         }
   1567       }
   1568         break;
   1569 
   1570       case 0x90:
   1571       case 0x91:
   1572       case 0x92:
   1573       case 0x93:
   1574       case 0x94:
   1575       case 0x95:
   1576       case 0x96:
   1577       case 0x97: {
   1578         int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
   1579         if (reg == 0) {
   1580           AppendToBuffer("nop");  // Common name for xchg rax,rax.
   1581         } else {
   1582           AppendToBuffer("xchg%c rax, %s",
   1583                          operand_size_code(),
   1584                          NameOfCPURegister(reg));
   1585         }
   1586         data++;
   1587       }
   1588         break;
   1589       case 0xB0:
   1590       case 0xB1:
   1591       case 0xB2:
   1592       case 0xB3:
   1593       case 0xB4:
   1594       case 0xB5:
   1595       case 0xB6:
   1596       case 0xB7:
   1597       case 0xB8:
   1598       case 0xB9:
   1599       case 0xBA:
   1600       case 0xBB:
   1601       case 0xBC:
   1602       case 0xBD:
   1603       case 0xBE:
   1604       case 0xBF: {
   1605         // mov reg8,imm8 or mov reg32,imm32
   1606         byte opcode = *data;
   1607         data++;
   1608         bool is_32bit = (opcode >= 0xB8);
   1609         int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
   1610         if (is_32bit) {
   1611           AppendToBuffer("mov%c %s, ",
   1612                          operand_size_code(),
   1613                          NameOfCPURegister(reg));
   1614           data += PrintImmediate(data, DOUBLEWORD_SIZE);
   1615         } else {
   1616           AppendToBuffer("movb %s, ",
   1617                          NameOfByteCPURegister(reg));
   1618           data += PrintImmediate(data, BYTE_SIZE);
   1619         }
   1620         break;
   1621       }
   1622       case 0xFE: {
   1623         data++;
   1624         int mod, regop, rm;
   1625         get_modrm(*data, &mod, &regop, &rm);
   1626         if (regop == 1) {
   1627           AppendToBuffer("decb ");
   1628           data += PrintRightByteOperand(data);
   1629         } else {
   1630           UnimplementedInstruction();
   1631         }
   1632         break;
   1633       }
   1634       case 0x68:
   1635         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
   1636         data += 5;
   1637         break;
   1638 
   1639       case 0x6A:
   1640         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
   1641         data += 2;
   1642         break;
   1643 
   1644       case 0xA1:  // Fall through.
   1645       case 0xA3:
   1646         switch (operand_size()) {
   1647           case DOUBLEWORD_SIZE: {
   1648             const char* memory_location = NameOfAddress(
   1649                 reinterpret_cast<byte*>(
   1650                     *reinterpret_cast<int32_t*>(data + 1)));
   1651             if (*data == 0xA1) {  // Opcode 0xA1
   1652               AppendToBuffer("movzxlq rax,(%s)", memory_location);
   1653             } else {  // Opcode 0xA3
   1654               AppendToBuffer("movzxlq (%s),rax", memory_location);
   1655             }
   1656             data += 5;
   1657             break;
   1658           }
   1659           case QUADWORD_SIZE: {
   1660             // New x64 instruction mov rax,(imm_64).
   1661             const char* memory_location = NameOfAddress(
   1662                 *reinterpret_cast<byte**>(data + 1));
   1663             if (*data == 0xA1) {  // Opcode 0xA1
   1664               AppendToBuffer("movq rax,(%s)", memory_location);
   1665             } else {  // Opcode 0xA3
   1666               AppendToBuffer("movq (%s),rax", memory_location);
   1667             }
   1668             data += 9;
   1669             break;
   1670           }
   1671           default:
   1672             UnimplementedInstruction();
   1673             data += 2;
   1674         }
   1675         break;
   1676 
   1677       case 0xA8:
   1678         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
   1679         data += 2;
   1680         break;
   1681 
   1682       case 0xA9: {
   1683         int64_t value = 0;
   1684         switch (operand_size()) {
   1685           case WORD_SIZE:
   1686             value = *reinterpret_cast<uint16_t*>(data + 1);
   1687             data += 3;
   1688             break;
   1689           case DOUBLEWORD_SIZE:
   1690             value = *reinterpret_cast<uint32_t*>(data + 1);
   1691             data += 5;
   1692             break;
   1693           case QUADWORD_SIZE:
   1694             value = *reinterpret_cast<int32_t*>(data + 1);
   1695             data += 5;
   1696             break;
   1697           default:
   1698             UNREACHABLE();
   1699         }
   1700         AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x",
   1701                        operand_size_code(),
   1702                        value);
   1703         break;
   1704       }
   1705       case 0xD1:  // fall through
   1706       case 0xD3:  // fall through
   1707       case 0xC1:
   1708         data += ShiftInstruction(data);
   1709         break;
   1710       case 0xD0:  // fall through
   1711       case 0xD2:  // fall through
   1712       case 0xC0:
   1713         byte_size_operand_ = true;
   1714         data += ShiftInstruction(data);
   1715         break;
   1716 
   1717       case 0xD9:  // fall through
   1718       case 0xDA:  // fall through
   1719       case 0xDB:  // fall through
   1720       case 0xDC:  // fall through
   1721       case 0xDD:  // fall through
   1722       case 0xDE:  // fall through
   1723       case 0xDF:
   1724         data += FPUInstruction(data);
   1725         break;
   1726 
   1727       case 0xEB:
   1728         data += JumpShort(data);
   1729         break;
   1730 
   1731       case 0xF6:
   1732         byte_size_operand_ = true;  // fall through
   1733       case 0xF7:
   1734         data += F6F7Instruction(data);
   1735         break;
   1736 
   1737       case 0x3C:
   1738         AppendToBuffer("cmp al, 0x%x", *reinterpret_cast<int8_t*>(data + 1));
   1739         data +=2;
   1740         break;
   1741 
   1742       default:
   1743         UnimplementedInstruction();
   1744         data += 1;
   1745     }
   1746   }  // !processed
   1747 
   1748   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
   1749     tmp_buffer_[tmp_buffer_pos_] = '\0';
   1750   }
   1751 
   1752   int instr_len = static_cast<int>(data - instr);
   1753   ASSERT(instr_len > 0);  // Ensure progress.
   1754 
   1755   int outp = 0;
   1756   // Instruction bytes.
   1757   for (byte* bp = instr; bp < data; bp++) {
   1758     outp += v8::internal::OS::SNPrintF(out_buffer + outp, "%02x", *bp);
   1759   }
   1760   for (int i = 6 - instr_len; i >= 0; i--) {
   1761     outp += v8::internal::OS::SNPrintF(out_buffer + outp, "  ");
   1762   }
   1763 
   1764   outp += v8::internal::OS::SNPrintF(out_buffer + outp, " %s",
   1765                                      tmp_buffer_.start());
   1766   return instr_len;
   1767 }
   1768 
   1769 
   1770 //------------------------------------------------------------------------------
   1771 
   1772 
   1773 static const char* cpu_regs[16] = {
   1774   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
   1775   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
   1776 };
   1777 
   1778 
   1779 static const char* byte_cpu_regs[16] = {
   1780   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
   1781   "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
   1782 };
   1783 
   1784 
   1785 static const char* xmm_regs[16] = {
   1786   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
   1787   "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
   1788 };
   1789 
   1790 
   1791 const char* NameConverter::NameOfAddress(byte* addr) const {
   1792   v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
   1793   return tmp_buffer_.start();
   1794 }
   1795 
   1796 
   1797 const char* NameConverter::NameOfConstant(byte* addr) const {
   1798   return NameOfAddress(addr);
   1799 }
   1800 
   1801 
   1802 const char* NameConverter::NameOfCPURegister(int reg) const {
   1803   if (0 <= reg && reg < 16)
   1804     return cpu_regs[reg];
   1805   return "noreg";
   1806 }
   1807 
   1808 
   1809 const char* NameConverter::NameOfByteCPURegister(int reg) const {
   1810   if (0 <= reg && reg < 16)
   1811     return byte_cpu_regs[reg];
   1812   return "noreg";
   1813 }
   1814 
   1815 
   1816 const char* NameConverter::NameOfXMMRegister(int reg) const {
   1817   if (0 <= reg && reg < 16)
   1818     return xmm_regs[reg];
   1819   return "noxmmreg";
   1820 }
   1821 
   1822 
   1823 const char* NameConverter::NameInCode(byte* addr) const {
   1824   // X64 does not embed debug strings at the moment.
   1825   UNREACHABLE();
   1826   return "";
   1827 }
   1828 
   1829 
   1830 //------------------------------------------------------------------------------
   1831 
   1832 Disassembler::Disassembler(const NameConverter& converter)
   1833     : converter_(converter) { }
   1834 
   1835 Disassembler::~Disassembler() { }
   1836 
   1837 
   1838 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
   1839                                     byte* instruction) {
   1840   DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
   1841   return d.InstructionDecode(buffer, instruction);
   1842 }
   1843 
   1844 
   1845 // The X64 assembler does not use constant pools.
   1846 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
   1847   return -1;
   1848 }
   1849 
   1850 
   1851 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
   1852   NameConverter converter;
   1853   Disassembler d(converter);
   1854   for (byte* pc = begin; pc < end;) {
   1855     v8::internal::EmbeddedVector<char, 128> buffer;
   1856     buffer[0] = '\0';
   1857     byte* prev_pc = pc;
   1858     pc += d.InstructionDecode(buffer, pc);
   1859     fprintf(f, "%p", prev_pc);
   1860     fprintf(f, "    ");
   1861 
   1862     for (byte* bp = prev_pc; bp < pc; bp++) {
   1863       fprintf(f, "%02x", *bp);
   1864     }
   1865     for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
   1866       fprintf(f, "  ");
   1867     }
   1868     fprintf(f, "  %s\n", buffer.start());
   1869   }
   1870 }
   1871 
   1872 }  // namespace disasm
   1873 
   1874 #endif  // V8_TARGET_ARCH_X64
   1875