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