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