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 #if V8_TARGET_ARCH_X64
     10 
     11 #include "src/base/compiler-specific.h"
     12 #include "src/base/lazy-instance.h"
     13 #include "src/disasm.h"
     14 
     15 namespace disasm {
     16 
     17 enum OperandType {
     18   UNSET_OP_ORDER = 0,
     19   // Operand size decides between 16, 32 and 64 bit operands.
     20   REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
     21   OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
     22   // Fixed 8-bit operands.
     23   BYTE_SIZE_OPERAND_FLAG = 4,
     24   BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
     25   BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
     26 };
     27 
     28 
     29 //------------------------------------------------------------------
     30 // Tables
     31 //------------------------------------------------------------------
     32 struct ByteMnemonic {
     33   int b;  // -1 terminates, otherwise must be in range (0..255)
     34   OperandType op_order_;
     35   const char* mnem;
     36 };
     37 
     38 
     39 static const ByteMnemonic two_operands_instr[] = {
     40   { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
     41   { 0x01, OPER_REG_OP_ORDER,      "add" },
     42   { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
     43   { 0x03, REG_OPER_OP_ORDER,      "add" },
     44   { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
     45   { 0x09, OPER_REG_OP_ORDER,      "or" },
     46   { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
     47   { 0x0B, REG_OPER_OP_ORDER,      "or" },
     48   { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
     49   { 0x11, OPER_REG_OP_ORDER,      "adc" },
     50   { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
     51   { 0x13, REG_OPER_OP_ORDER,      "adc" },
     52   { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
     53   { 0x19, OPER_REG_OP_ORDER,      "sbb" },
     54   { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
     55   { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
     56   { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
     57   { 0x21, OPER_REG_OP_ORDER,      "and" },
     58   { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
     59   { 0x23, REG_OPER_OP_ORDER,      "and" },
     60   { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
     61   { 0x29, OPER_REG_OP_ORDER,      "sub" },
     62   { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
     63   { 0x2B, REG_OPER_OP_ORDER,      "sub" },
     64   { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
     65   { 0x31, OPER_REG_OP_ORDER,      "xor" },
     66   { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
     67   { 0x33, REG_OPER_OP_ORDER,      "xor" },
     68   { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
     69   { 0x39, OPER_REG_OP_ORDER,      "cmp" },
     70   { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
     71   { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
     72   { 0x63, REG_OPER_OP_ORDER,      "movsxl" },
     73   { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
     74   { 0x85, REG_OPER_OP_ORDER,      "test" },
     75   { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
     76   { 0x87, REG_OPER_OP_ORDER,      "xchg" },
     77   { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
     78   { 0x89, OPER_REG_OP_ORDER,      "mov" },
     79   { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
     80   { 0x8B, REG_OPER_OP_ORDER,      "mov" },
     81   { 0x8D, REG_OPER_OP_ORDER,      "lea" },
     82   { -1, UNSET_OP_ORDER, "" }
     83 };
     84 
     85 
     86 static const ByteMnemonic zero_operands_instr[] = {
     87   { 0xC3, UNSET_OP_ORDER, "ret" },
     88   { 0xC9, UNSET_OP_ORDER, "leave" },
     89   { 0xF4, UNSET_OP_ORDER, "hlt" },
     90   { 0xFC, UNSET_OP_ORDER, "cld" },
     91   { 0xCC, UNSET_OP_ORDER, "int3" },
     92   { 0x60, UNSET_OP_ORDER, "pushad" },
     93   { 0x61, UNSET_OP_ORDER, "popad" },
     94   { 0x9C, UNSET_OP_ORDER, "pushfd" },
     95   { 0x9D, UNSET_OP_ORDER, "popfd" },
     96   { 0x9E, UNSET_OP_ORDER, "sahf" },
     97   { 0x99, UNSET_OP_ORDER, "cdq" },
     98   { 0x9B, UNSET_OP_ORDER, "fwait" },
     99   { 0xA4, UNSET_OP_ORDER, "movs" },
    100   { 0xA5, UNSET_OP_ORDER, "movs" },
    101   { 0xA6, UNSET_OP_ORDER, "cmps" },
    102   { 0xA7, UNSET_OP_ORDER, "cmps" },
    103   { -1, UNSET_OP_ORDER, "" }
    104 };
    105 
    106 
    107 static const ByteMnemonic call_jump_instr[] = {
    108   { 0xE8, UNSET_OP_ORDER, "call" },
    109   { 0xE9, UNSET_OP_ORDER, "jmp" },
    110   { -1, UNSET_OP_ORDER, "" }
    111 };
    112 
    113 
    114 static const ByteMnemonic short_immediate_instr[] = {
    115   { 0x05, UNSET_OP_ORDER, "add" },
    116   { 0x0D, UNSET_OP_ORDER, "or" },
    117   { 0x15, UNSET_OP_ORDER, "adc" },
    118   { 0x1D, UNSET_OP_ORDER, "sbb" },
    119   { 0x25, UNSET_OP_ORDER, "and" },
    120   { 0x2D, UNSET_OP_ORDER, "sub" },
    121   { 0x35, UNSET_OP_ORDER, "xor" },
    122   { 0x3D, UNSET_OP_ORDER, "cmp" },
    123   { -1, UNSET_OP_ORDER, "" }
    124 };
    125 
    126 
    127 static const char* const conditional_code_suffix[] = {
    128   "o", "no", "c", "nc", "z", "nz", "na", "a",
    129   "s", "ns", "pe", "po", "l", "ge", "le", "g"
    130 };
    131 
    132 
    133 enum InstructionType {
    134   NO_INSTR,
    135   ZERO_OPERANDS_INSTR,
    136   TWO_OPERANDS_INSTR,
    137   JUMP_CONDITIONAL_SHORT_INSTR,
    138   REGISTER_INSTR,
    139   PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
    140   MOVE_REG_INSTR,
    141   CALL_JUMP_INSTR,
    142   SHORT_IMMEDIATE_INSTR
    143 };
    144 
    145 enum Prefixes {
    146   ESCAPE_PREFIX = 0x0F,
    147   OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
    148   ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
    149   VEX3_PREFIX = 0xC4,
    150   VEX2_PREFIX = 0xC5,
    151   LOCK_PREFIX = 0xF0,
    152   REPNE_PREFIX = 0xF2,
    153   REP_PREFIX = 0xF3,
    154   REPEQ_PREFIX = REP_PREFIX
    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 const 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_(unimplemented_action ==
    294                                 ABORT_ON_UNIMPLEMENTED_OPCODE),
    295         rex_(0),
    296         operand_size_(0),
    297         group_1_prefix_(0),
    298         vex_byte0_(0),
    299         vex_byte1_(0),
    300         vex_byte2_(0),
    301         byte_size_operand_(false),
    302         instruction_table_(instruction_table.Pointer()) {
    303     tmp_buffer_[0] = '\0';
    304   }
    305 
    306   virtual ~DisassemblerX64() {
    307   }
    308 
    309   // Writes one disassembled instruction into 'buffer' (0-terminated).
    310   // Returns the length of the disassembled machine instruction in bytes.
    311   int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
    312 
    313  private:
    314   enum OperandSize {
    315     OPERAND_BYTE_SIZE = 0,
    316     OPERAND_WORD_SIZE = 1,
    317     OPERAND_DOUBLEWORD_SIZE = 2,
    318     OPERAND_QUADWORD_SIZE = 3
    319   };
    320 
    321   const NameConverter& converter_;
    322   v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
    323   unsigned int tmp_buffer_pos_;
    324   bool abort_on_unimplemented_;
    325   // Prefixes parsed
    326   byte rex_;
    327   byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0.
    328   byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
    329   byte vex_byte0_;       // 0xc4 or 0xc5
    330   byte vex_byte1_;
    331   byte vex_byte2_;  // only for 3 bytes vex prefix
    332   // Byte size operand override.
    333   bool byte_size_operand_;
    334   const InstructionTable* const instruction_table_;
    335 
    336   void setRex(byte rex) {
    337     DCHECK_EQ(0x40, rex & 0xF0);
    338     rex_ = rex;
    339   }
    340 
    341   bool rex() { return rex_ != 0; }
    342 
    343   bool rex_b() { return (rex_ & 0x01) != 0; }
    344 
    345   // Actual number of base register given the low bits and the rex.b state.
    346   int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
    347 
    348   bool rex_x() { return (rex_ & 0x02) != 0; }
    349 
    350   bool rex_r() { return (rex_ & 0x04) != 0; }
    351 
    352   bool rex_w() { return (rex_ & 0x08) != 0; }
    353 
    354   bool vex_w() {
    355     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    356     return vex_byte0_ == VEX3_PREFIX ? (vex_byte2_ & 0x80) != 0 : false;
    357   }
    358 
    359   bool vex_128() {
    360     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    361     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
    362     return (checked & 4) == 0;
    363   }
    364 
    365   bool vex_none() {
    366     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    367     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
    368     return (checked & 3) == 0;
    369   }
    370 
    371   bool vex_66() {
    372     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    373     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
    374     return (checked & 3) == 1;
    375   }
    376 
    377   bool vex_f3() {
    378     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    379     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
    380     return (checked & 3) == 2;
    381   }
    382 
    383   bool vex_f2() {
    384     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    385     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
    386     return (checked & 3) == 3;
    387   }
    388 
    389   bool vex_0f() {
    390     if (vex_byte0_ == VEX2_PREFIX) return true;
    391     return (vex_byte1_ & 3) == 1;
    392   }
    393 
    394   bool vex_0f38() {
    395     if (vex_byte0_ == VEX2_PREFIX) return false;
    396     return (vex_byte1_ & 3) == 2;
    397   }
    398 
    399   bool vex_0f3a() {
    400     if (vex_byte0_ == VEX2_PREFIX) return false;
    401     return (vex_byte1_ & 3) == 3;
    402   }
    403 
    404   int vex_vreg() {
    405     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
    406     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
    407     return ~(checked >> 3) & 0xf;
    408   }
    409 
    410   OperandSize operand_size() {
    411     if (byte_size_operand_) return OPERAND_BYTE_SIZE;
    412     if (rex_w()) return OPERAND_QUADWORD_SIZE;
    413     if (operand_size_ != 0) return OPERAND_WORD_SIZE;
    414     return OPERAND_DOUBLEWORD_SIZE;
    415   }
    416 
    417   char operand_size_code() {
    418     return "bwlq"[operand_size()];
    419   }
    420 
    421   char float_size_code() { return "sd"[rex_w()]; }
    422 
    423   const char* NameOfCPURegister(int reg) const {
    424     return converter_.NameOfCPURegister(reg);
    425   }
    426 
    427   const char* NameOfByteCPURegister(int reg) const {
    428     return converter_.NameOfByteCPURegister(reg);
    429   }
    430 
    431   const char* NameOfXMMRegister(int reg) const {
    432     return converter_.NameOfXMMRegister(reg);
    433   }
    434 
    435   const char* NameOfAddress(byte* addr) const {
    436     return converter_.NameOfAddress(addr);
    437   }
    438 
    439   // Disassembler helper functions.
    440   void get_modrm(byte data,
    441                  int* mod,
    442                  int* regop,
    443                  int* rm) {
    444     *mod = (data >> 6) & 3;
    445     *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
    446     *rm = (data & 7) | (rex_b() ? 8 : 0);
    447   }
    448 
    449   void get_sib(byte data,
    450                int* scale,
    451                int* index,
    452                int* base) {
    453     *scale = (data >> 6) & 3;
    454     *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
    455     *base = (data & 7) | (rex_b() ? 8 : 0);
    456   }
    457 
    458   typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
    459 
    460   int PrintRightOperandHelper(byte* modrmp,
    461                               RegisterNameMapping register_name);
    462   int PrintRightOperand(byte* modrmp);
    463   int PrintRightByteOperand(byte* modrmp);
    464   int PrintRightXMMOperand(byte* modrmp);
    465   int PrintOperands(const char* mnem,
    466                     OperandType op_order,
    467                     byte* data);
    468   int PrintImmediate(byte* data, OperandSize size);
    469   int PrintImmediateOp(byte* data);
    470   const char* TwoByteMnemonic(byte opcode);
    471   int TwoByteOpcodeInstruction(byte* data);
    472   int F6F7Instruction(byte* data);
    473   int ShiftInstruction(byte* data);
    474   int JumpShort(byte* data);
    475   int JumpConditional(byte* data);
    476   int JumpConditionalShort(byte* data);
    477   int SetCC(byte* data);
    478   int FPUInstruction(byte* data);
    479   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
    480   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
    481   int AVXInstruction(byte* data);
    482   PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
    483 
    484   void UnimplementedInstruction() {
    485     if (abort_on_unimplemented_) {
    486       CHECK(false);
    487     } else {
    488       AppendToBuffer("'Unimplemented Instruction'");
    489     }
    490   }
    491 };
    492 
    493 
    494 void DisassemblerX64::AppendToBuffer(const char* format, ...) {
    495   v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
    496   va_list args;
    497   va_start(args, format);
    498   int result = v8::internal::VSNPrintF(buf, format, args);
    499   va_end(args);
    500   tmp_buffer_pos_ += result;
    501 }
    502 
    503 
    504 int DisassemblerX64::PrintRightOperandHelper(
    505     byte* modrmp,
    506     RegisterNameMapping direct_register_name) {
    507   int mod, regop, rm;
    508   get_modrm(*modrmp, &mod, &regop, &rm);
    509   RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
    510       &DisassemblerX64::NameOfCPURegister;
    511   switch (mod) {
    512     case 0:
    513       if ((rm & 7) == 5) {
    514         int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
    515         AppendToBuffer("[rip+0x%x]", disp);
    516         return 5;
    517       } else if ((rm & 7) == 4) {
    518         // Codes for SIB byte.
    519         byte sib = *(modrmp + 1);
    520         int scale, index, base;
    521         get_sib(sib, &scale, &index, &base);
    522         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
    523           // index == rsp means no index. Only use sib byte with no index for
    524           // rsp and r12 base.
    525           AppendToBuffer("[%s]", NameOfCPURegister(base));
    526           return 2;
    527         } else if (base == 5) {
    528           // base == rbp means no base register (when mod == 0).
    529           int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
    530           AppendToBuffer("[%s*%d%s0x%x]",
    531                          NameOfCPURegister(index),
    532                          1 << scale,
    533                          disp < 0 ? "-" : "+",
    534                          disp < 0 ? -disp : disp);
    535           return 6;
    536         } else if (index != 4 && base != 5) {
    537           // [base+index*scale]
    538           AppendToBuffer("[%s+%s*%d]",
    539                          NameOfCPURegister(base),
    540                          NameOfCPURegister(index),
    541                          1 << scale);
    542           return 2;
    543         } else {
    544           UnimplementedInstruction();
    545           return 1;
    546         }
    547       } else {
    548         AppendToBuffer("[%s]", NameOfCPURegister(rm));
    549         return 1;
    550       }
    551       break;
    552     case 1:  // fall through
    553     case 2:
    554       if ((rm & 7) == 4) {
    555         byte sib = *(modrmp + 1);
    556         int scale, index, base;
    557         get_sib(sib, &scale, &index, &base);
    558         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
    559                               : *reinterpret_cast<int8_t*>(modrmp + 2);
    560         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
    561           AppendToBuffer("[%s%s0x%x]",
    562                          NameOfCPURegister(base),
    563                          disp < 0 ? "-" : "+",
    564                          disp < 0 ? -disp : disp);
    565         } else {
    566           AppendToBuffer("[%s+%s*%d%s0x%x]",
    567                          NameOfCPURegister(base),
    568                          NameOfCPURegister(index),
    569                          1 << scale,
    570                          disp < 0 ? "-" : "+",
    571                          disp < 0 ? -disp : disp);
    572         }
    573         return mod == 2 ? 6 : 3;
    574       } else {
    575         // No sib.
    576         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
    577                               : *reinterpret_cast<int8_t*>(modrmp + 1);
    578         AppendToBuffer("[%s%s0x%x]",
    579                        NameOfCPURegister(rm),
    580                        disp < 0 ? "-" : "+",
    581                        disp < 0 ? -disp : disp);
    582         return (mod == 2) ? 5 : 2;
    583       }
    584       break;
    585     case 3:
    586       AppendToBuffer("%s", (this->*register_name)(rm));
    587       return 1;
    588     default:
    589       UnimplementedInstruction();
    590       return 1;
    591   }
    592   UNREACHABLE();
    593 }
    594 
    595 
    596 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
    597   int64_t value;
    598   int count;
    599   switch (size) {
    600     case OPERAND_BYTE_SIZE:
    601       value = *data;
    602       count = 1;
    603       break;
    604     case OPERAND_WORD_SIZE:
    605       value = *reinterpret_cast<int16_t*>(data);
    606       count = 2;
    607       break;
    608     case OPERAND_DOUBLEWORD_SIZE:
    609       value = *reinterpret_cast<uint32_t*>(data);
    610       count = 4;
    611       break;
    612     case OPERAND_QUADWORD_SIZE:
    613       value = *reinterpret_cast<int32_t*>(data);
    614       count = 4;
    615       break;
    616     default:
    617       UNREACHABLE();
    618       value = 0;  // Initialize variables on all paths to satisfy the compiler.
    619       count = 0;
    620   }
    621   AppendToBuffer("%" PRIx64, value);
    622   return count;
    623 }
    624 
    625 
    626 int DisassemblerX64::PrintRightOperand(byte* modrmp) {
    627   return PrintRightOperandHelper(modrmp,
    628                                  &DisassemblerX64::NameOfCPURegister);
    629 }
    630 
    631 
    632 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
    633   return PrintRightOperandHelper(modrmp,
    634                                  &DisassemblerX64::NameOfByteCPURegister);
    635 }
    636 
    637 
    638 int DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
    639   return PrintRightOperandHelper(modrmp,
    640                                  &DisassemblerX64::NameOfXMMRegister);
    641 }
    642 
    643 
    644 // Returns number of bytes used including the current *data.
    645 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
    646 int DisassemblerX64::PrintOperands(const char* mnem,
    647                                    OperandType op_order,
    648                                    byte* data) {
    649   byte modrm = *data;
    650   int mod, regop, rm;
    651   get_modrm(modrm, &mod, &regop, &rm);
    652   int advance = 0;
    653   const char* register_name =
    654       byte_size_operand_ ? NameOfByteCPURegister(regop)
    655                          : NameOfCPURegister(regop);
    656   switch (op_order) {
    657     case REG_OPER_OP_ORDER: {
    658       AppendToBuffer("%s%c %s,",
    659                      mnem,
    660                      operand_size_code(),
    661                      register_name);
    662       advance = byte_size_operand_ ? PrintRightByteOperand(data)
    663                                    : PrintRightOperand(data);
    664       break;
    665     }
    666     case OPER_REG_OP_ORDER: {
    667       AppendToBuffer("%s%c ", mnem, operand_size_code());
    668       advance = byte_size_operand_ ? PrintRightByteOperand(data)
    669                                    : PrintRightOperand(data);
    670       AppendToBuffer(",%s", register_name);
    671       break;
    672     }
    673     default:
    674       UNREACHABLE();
    675       break;
    676   }
    677   return advance;
    678 }
    679 
    680 
    681 // Returns number of bytes used by machine instruction, including *data byte.
    682 // Writes immediate instructions to 'tmp_buffer_'.
    683 int DisassemblerX64::PrintImmediateOp(byte* data) {
    684   bool byte_size_immediate = (*data & 0x02) != 0;
    685   byte modrm = *(data + 1);
    686   int mod, regop, rm;
    687   get_modrm(modrm, &mod, &regop, &rm);
    688   const char* mnem = "Imm???";
    689   switch (regop) {
    690     case 0:
    691       mnem = "add";
    692       break;
    693     case 1:
    694       mnem = "or";
    695       break;
    696     case 2:
    697       mnem = "adc";
    698       break;
    699     case 3:
    700       mnem = "sbb";
    701       break;
    702     case 4:
    703       mnem = "and";
    704       break;
    705     case 5:
    706       mnem = "sub";
    707       break;
    708     case 6:
    709       mnem = "xor";
    710       break;
    711     case 7:
    712       mnem = "cmp";
    713       break;
    714     default:
    715       UnimplementedInstruction();
    716   }
    717   AppendToBuffer("%s%c ", mnem, operand_size_code());
    718   int count = PrintRightOperand(data + 1);
    719   AppendToBuffer(",0x");
    720   OperandSize immediate_size =
    721       byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
    722   count += PrintImmediate(data + 1 + count, immediate_size);
    723   return 1 + count;
    724 }
    725 
    726 
    727 // Returns number of bytes used, including *data.
    728 int DisassemblerX64::F6F7Instruction(byte* data) {
    729   DCHECK(*data == 0xF7 || *data == 0xF6);
    730   byte modrm = *(data + 1);
    731   int mod, regop, rm;
    732   get_modrm(modrm, &mod, &regop, &rm);
    733   if (mod == 3 && regop != 0) {
    734     const char* mnem = NULL;
    735     switch (regop) {
    736       case 2:
    737         mnem = "not";
    738         break;
    739       case 3:
    740         mnem = "neg";
    741         break;
    742       case 4:
    743         mnem = "mul";
    744         break;
    745       case 5:
    746         mnem = "imul";
    747         break;
    748       case 6:
    749         mnem = "div";
    750         break;
    751       case 7:
    752         mnem = "idiv";
    753         break;
    754       default:
    755         UnimplementedInstruction();
    756     }
    757     AppendToBuffer("%s%c %s",
    758                    mnem,
    759                    operand_size_code(),
    760                    NameOfCPURegister(rm));
    761     return 2;
    762   } else if (regop == 0) {
    763     AppendToBuffer("test%c ", operand_size_code());
    764     int count = PrintRightOperand(data + 1);  // Use name of 64-bit register.
    765     AppendToBuffer(",0x");
    766     count += PrintImmediate(data + 1 + count, operand_size());
    767     return 1 + count;
    768   } else {
    769     UnimplementedInstruction();
    770     return 2;
    771   }
    772 }
    773 
    774 
    775 int DisassemblerX64::ShiftInstruction(byte* data) {
    776   byte op = *data & (~1);
    777   int count = 1;
    778   if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
    779     UnimplementedInstruction();
    780     return count;
    781   }
    782   // Print mneumonic.
    783   {
    784     byte modrm = *(data + count);
    785     int mod, regop, rm;
    786     get_modrm(modrm, &mod, &regop, &rm);
    787     regop &= 0x7;  // The REX.R bit does not affect the operation.
    788     const char* mnem = NULL;
    789     switch (regop) {
    790       case 0:
    791         mnem = "rol";
    792         break;
    793       case 1:
    794         mnem = "ror";
    795         break;
    796       case 2:
    797         mnem = "rcl";
    798         break;
    799       case 3:
    800         mnem = "rcr";
    801         break;
    802       case 4:
    803         mnem = "shl";
    804         break;
    805       case 5:
    806         mnem = "shr";
    807         break;
    808       case 7:
    809         mnem = "sar";
    810         break;
    811       default:
    812         UnimplementedInstruction();
    813         return count + 1;
    814     }
    815     DCHECK_NOT_NULL(mnem);
    816     AppendToBuffer("%s%c ", mnem, operand_size_code());
    817   }
    818   count += PrintRightOperand(data + count);
    819   if (op == 0xD2) {
    820     AppendToBuffer(", cl");
    821   } else {
    822     int imm8 = -1;
    823     if (op == 0xD0) {
    824       imm8 = 1;
    825     } else {
    826       DCHECK_EQ(0xC0, op);
    827       imm8 = *(data + count);
    828       count++;
    829     }
    830     AppendToBuffer(", %d", imm8);
    831   }
    832   return count;
    833 }
    834 
    835 
    836 // Returns number of bytes used, including *data.
    837 int DisassemblerX64::JumpShort(byte* data) {
    838   DCHECK_EQ(0xEB, *data);
    839   byte b = *(data + 1);
    840   byte* dest = data + static_cast<int8_t>(b) + 2;
    841   AppendToBuffer("jmp %s", NameOfAddress(dest));
    842   return 2;
    843 }
    844 
    845 
    846 // Returns number of bytes used, including *data.
    847 int DisassemblerX64::JumpConditional(byte* data) {
    848   DCHECK_EQ(0x0F, *data);
    849   byte cond = *(data + 1) & 0x0F;
    850   byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
    851   const char* mnem = conditional_code_suffix[cond];
    852   AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
    853   return 6;  // includes 0x0F
    854 }
    855 
    856 
    857 // Returns number of bytes used, including *data.
    858 int DisassemblerX64::JumpConditionalShort(byte* data) {
    859   byte cond = *data & 0x0F;
    860   byte b = *(data + 1);
    861   byte* dest = data + static_cast<int8_t>(b) + 2;
    862   const char* mnem = conditional_code_suffix[cond];
    863   AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
    864   return 2;
    865 }
    866 
    867 
    868 // Returns number of bytes used, including *data.
    869 int DisassemblerX64::SetCC(byte* data) {
    870   DCHECK_EQ(0x0F, *data);
    871   byte cond = *(data + 1) & 0x0F;
    872   const char* mnem = conditional_code_suffix[cond];
    873   AppendToBuffer("set%s%c ", mnem, operand_size_code());
    874   PrintRightByteOperand(data + 2);
    875   return 3;  // includes 0x0F
    876 }
    877 
    878 
    879 int DisassemblerX64::AVXInstruction(byte* data) {
    880   byte opcode = *data;
    881   byte* current = data + 1;
    882   if (vex_66() && vex_0f38()) {
    883     int mod, regop, rm, vvvv = vex_vreg();
    884     get_modrm(*current, &mod, &regop, &rm);
    885     switch (opcode) {
    886       case 0x99:
    887         AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
    888                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    889         current += PrintRightXMMOperand(current);
    890         break;
    891       case 0xa9:
    892         AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
    893                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    894         current += PrintRightXMMOperand(current);
    895         break;
    896       case 0xb9:
    897         AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
    898                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    899         current += PrintRightXMMOperand(current);
    900         break;
    901       case 0x9b:
    902         AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
    903                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    904         current += PrintRightXMMOperand(current);
    905         break;
    906       case 0xab:
    907         AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
    908                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    909         current += PrintRightXMMOperand(current);
    910         break;
    911       case 0xbb:
    912         AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
    913                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    914         current += PrintRightXMMOperand(current);
    915         break;
    916       case 0x9d:
    917         AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
    918                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    919         current += PrintRightXMMOperand(current);
    920         break;
    921       case 0xad:
    922         AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
    923                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    924         current += PrintRightXMMOperand(current);
    925         break;
    926       case 0xbd:
    927         AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
    928                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    929         current += PrintRightXMMOperand(current);
    930         break;
    931       case 0x9f:
    932         AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
    933                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    934         current += PrintRightXMMOperand(current);
    935         break;
    936       case 0xaf:
    937         AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
    938                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    939         current += PrintRightXMMOperand(current);
    940         break;
    941       case 0xbf:
    942         AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
    943                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    944         current += PrintRightXMMOperand(current);
    945         break;
    946       case 0xf7:
    947         AppendToBuffer("shlx%c %s,", operand_size_code(),
    948                        NameOfCPURegister(regop));
    949         current += PrintRightOperand(current);
    950         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
    951         break;
    952       default:
    953         UnimplementedInstruction();
    954     }
    955   } else if (vex_66() && vex_0f3a()) {
    956     int mod, regop, rm, vvvv = vex_vreg();
    957     get_modrm(*current, &mod, &regop, &rm);
    958     switch (opcode) {
    959       case 0x0a:
    960         AppendToBuffer("vroundss %s,%s,", NameOfXMMRegister(regop),
    961                        NameOfXMMRegister(vvvv));
    962         current += PrintRightXMMOperand(current);
    963         AppendToBuffer(",0x%x", *current++);
    964         break;
    965       case 0x0b:
    966         AppendToBuffer("vroundsd %s,%s,", NameOfXMMRegister(regop),
    967                        NameOfXMMRegister(vvvv));
    968         current += PrintRightXMMOperand(current);
    969         AppendToBuffer(",0x%x", *current++);
    970         break;
    971       default:
    972         UnimplementedInstruction();
    973     }
    974   } else if (vex_f3() && vex_0f()) {
    975     int mod, regop, rm, vvvv = vex_vreg();
    976     get_modrm(*current, &mod, &regop, &rm);
    977     switch (opcode) {
    978       case 0x10:
    979         AppendToBuffer("vmovss %s,", NameOfXMMRegister(regop));
    980         if (mod == 3) {
    981           AppendToBuffer("%s,", NameOfXMMRegister(vvvv));
    982         }
    983         current += PrintRightXMMOperand(current);
    984         break;
    985       case 0x11:
    986         AppendToBuffer("vmovss ");
    987         current += PrintRightXMMOperand(current);
    988         if (mod == 3) {
    989           AppendToBuffer(",%s", NameOfXMMRegister(vvvv));
    990         }
    991         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    992         break;
    993       case 0x2a:
    994         AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2ss" : "vcvtlsi2ss",
    995                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
    996         current += PrintRightOperand(current);
    997         break;
    998       case 0x2c:
    999         AppendToBuffer("vcvttss2si%s %s,", vex_w() ? "q" : "",
   1000                        NameOfCPURegister(regop));
   1001         current += PrintRightXMMOperand(current);
   1002         break;
   1003       case 0x58:
   1004         AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop),
   1005                        NameOfXMMRegister(vvvv));
   1006         current += PrintRightXMMOperand(current);
   1007         break;
   1008       case 0x59:
   1009         AppendToBuffer("vmulss %s,%s,", NameOfXMMRegister(regop),
   1010                        NameOfXMMRegister(vvvv));
   1011         current += PrintRightXMMOperand(current);
   1012         break;
   1013       case 0x5a:
   1014         AppendToBuffer("vcvtss2sd %s,%s,", NameOfXMMRegister(regop),
   1015                        NameOfXMMRegister(vvvv));
   1016         current += PrintRightXMMOperand(current);
   1017         break;
   1018       case 0x5c:
   1019         AppendToBuffer("vsubss %s,%s,", NameOfXMMRegister(regop),
   1020                        NameOfXMMRegister(vvvv));
   1021         current += PrintRightXMMOperand(current);
   1022         break;
   1023       case 0x5d:
   1024         AppendToBuffer("vminss %s,%s,", NameOfXMMRegister(regop),
   1025                        NameOfXMMRegister(vvvv));
   1026         current += PrintRightXMMOperand(current);
   1027         break;
   1028       case 0x5e:
   1029         AppendToBuffer("vdivss %s,%s,", NameOfXMMRegister(regop),
   1030                        NameOfXMMRegister(vvvv));
   1031         current += PrintRightXMMOperand(current);
   1032         break;
   1033       case 0x5f:
   1034         AppendToBuffer("vmaxss %s,%s,", NameOfXMMRegister(regop),
   1035                        NameOfXMMRegister(vvvv));
   1036         current += PrintRightXMMOperand(current);
   1037         break;
   1038       default:
   1039         UnimplementedInstruction();
   1040     }
   1041   } else if (vex_f2() && vex_0f()) {
   1042     int mod, regop, rm, vvvv = vex_vreg();
   1043     get_modrm(*current, &mod, &regop, &rm);
   1044     switch (opcode) {
   1045       case 0x10:
   1046         AppendToBuffer("vmovsd %s,", NameOfXMMRegister(regop));
   1047         if (mod == 3) {
   1048           AppendToBuffer("%s,", NameOfXMMRegister(vvvv));
   1049         }
   1050         current += PrintRightXMMOperand(current);
   1051         break;
   1052       case 0x11:
   1053         AppendToBuffer("vmovsd ");
   1054         current += PrintRightXMMOperand(current);
   1055         if (mod == 3) {
   1056           AppendToBuffer(",%s", NameOfXMMRegister(vvvv));
   1057         }
   1058         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1059         break;
   1060       case 0x2a:
   1061         AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2sd" : "vcvtlsi2sd",
   1062                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
   1063         current += PrintRightOperand(current);
   1064         break;
   1065       case 0x2c:
   1066         AppendToBuffer("vcvttsd2si%s %s,", vex_w() ? "q" : "",
   1067                        NameOfCPURegister(regop));
   1068         current += PrintRightXMMOperand(current);
   1069         break;
   1070       case 0x2d:
   1071         AppendToBuffer("vcvtsd2si%s %s,", vex_w() ? "q" : "",
   1072                        NameOfCPURegister(regop));
   1073         current += PrintRightXMMOperand(current);
   1074         break;
   1075       case 0x51:
   1076         AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop),
   1077                        NameOfXMMRegister(vvvv));
   1078         current += PrintRightXMMOperand(current);
   1079         break;
   1080       case 0x58:
   1081         AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
   1082                        NameOfXMMRegister(vvvv));
   1083         current += PrintRightXMMOperand(current);
   1084         break;
   1085       case 0x59:
   1086         AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
   1087                        NameOfXMMRegister(vvvv));
   1088         current += PrintRightXMMOperand(current);
   1089         break;
   1090       case 0x5a:
   1091         AppendToBuffer("vcvtsd2ss %s,%s,", NameOfXMMRegister(regop),
   1092                        NameOfXMMRegister(vvvv));
   1093         current += PrintRightXMMOperand(current);
   1094         break;
   1095       case 0x5c:
   1096         AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
   1097                        NameOfXMMRegister(vvvv));
   1098         current += PrintRightXMMOperand(current);
   1099         break;
   1100       case 0x5d:
   1101         AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop),
   1102                        NameOfXMMRegister(vvvv));
   1103         current += PrintRightXMMOperand(current);
   1104         break;
   1105       case 0x5e:
   1106         AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
   1107                        NameOfXMMRegister(vvvv));
   1108         current += PrintRightXMMOperand(current);
   1109         break;
   1110       case 0x5f:
   1111         AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop),
   1112                        NameOfXMMRegister(vvvv));
   1113         current += PrintRightXMMOperand(current);
   1114         break;
   1115       default:
   1116         UnimplementedInstruction();
   1117     }
   1118   } else if (vex_none() && vex_0f38()) {
   1119     int mod, regop, rm, vvvv = vex_vreg();
   1120     get_modrm(*current, &mod, &regop, &rm);
   1121     const char* mnem = "?";
   1122     switch (opcode) {
   1123       case 0xf2:
   1124         AppendToBuffer("andn%c %s,%s,", operand_size_code(),
   1125                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
   1126         current += PrintRightOperand(current);
   1127         break;
   1128       case 0xf5:
   1129         AppendToBuffer("bzhi%c %s,", operand_size_code(),
   1130                        NameOfCPURegister(regop));
   1131         current += PrintRightOperand(current);
   1132         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
   1133         break;
   1134       case 0xf7:
   1135         AppendToBuffer("bextr%c %s,", operand_size_code(),
   1136                        NameOfCPURegister(regop));
   1137         current += PrintRightOperand(current);
   1138         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
   1139         break;
   1140       case 0xf3:
   1141         switch (regop) {
   1142           case 1:
   1143             mnem = "blsr";
   1144             break;
   1145           case 2:
   1146             mnem = "blsmsk";
   1147             break;
   1148           case 3:
   1149             mnem = "blsi";
   1150             break;
   1151           default:
   1152             UnimplementedInstruction();
   1153         }
   1154         AppendToBuffer("%s%c %s,", mnem, operand_size_code(),
   1155                        NameOfCPURegister(vvvv));
   1156         current += PrintRightOperand(current);
   1157         mnem = "?";
   1158         break;
   1159       default:
   1160         UnimplementedInstruction();
   1161     }
   1162   } else if (vex_f2() && vex_0f38()) {
   1163     int mod, regop, rm, vvvv = vex_vreg();
   1164     get_modrm(*current, &mod, &regop, &rm);
   1165     switch (opcode) {
   1166       case 0xf5:
   1167         AppendToBuffer("pdep%c %s,%s,", operand_size_code(),
   1168                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
   1169         current += PrintRightOperand(current);
   1170         break;
   1171       case 0xf6:
   1172         AppendToBuffer("mulx%c %s,%s,", operand_size_code(),
   1173                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
   1174         current += PrintRightOperand(current);
   1175         break;
   1176       case 0xf7:
   1177         AppendToBuffer("shrx%c %s,", operand_size_code(),
   1178                        NameOfCPURegister(regop));
   1179         current += PrintRightOperand(current);
   1180         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
   1181         break;
   1182       default:
   1183         UnimplementedInstruction();
   1184     }
   1185   } else if (vex_f3() && vex_0f38()) {
   1186     int mod, regop, rm, vvvv = vex_vreg();
   1187     get_modrm(*current, &mod, &regop, &rm);
   1188     switch (opcode) {
   1189       case 0xf5:
   1190         AppendToBuffer("pext%c %s,%s,", operand_size_code(),
   1191                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
   1192         current += PrintRightOperand(current);
   1193         break;
   1194       case 0xf7:
   1195         AppendToBuffer("sarx%c %s,", operand_size_code(),
   1196                        NameOfCPURegister(regop));
   1197         current += PrintRightOperand(current);
   1198         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
   1199         break;
   1200       default:
   1201         UnimplementedInstruction();
   1202     }
   1203   } else if (vex_f2() && vex_0f3a()) {
   1204     int mod, regop, rm;
   1205     get_modrm(*current, &mod, &regop, &rm);
   1206     switch (opcode) {
   1207       case 0xf0:
   1208         AppendToBuffer("rorx%c %s,", operand_size_code(),
   1209                        NameOfCPURegister(regop));
   1210         current += PrintRightOperand(current);
   1211         switch (operand_size()) {
   1212           case OPERAND_DOUBLEWORD_SIZE:
   1213             AppendToBuffer(",%d", *current & 0x1f);
   1214             break;
   1215           case OPERAND_QUADWORD_SIZE:
   1216             AppendToBuffer(",%d", *current & 0x3f);
   1217             break;
   1218           default:
   1219             UnimplementedInstruction();
   1220         }
   1221         current += 1;
   1222         break;
   1223       default:
   1224         UnimplementedInstruction();
   1225     }
   1226   } else if (vex_none() && vex_0f()) {
   1227     int mod, regop, rm, vvvv = vex_vreg();
   1228     get_modrm(*current, &mod, &regop, &rm);
   1229     switch (opcode) {
   1230       case 0x28:
   1231         AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop));
   1232         current += PrintRightXMMOperand(current);
   1233         break;
   1234       case 0x29:
   1235         AppendToBuffer("vmovaps ");
   1236         current += PrintRightXMMOperand(current);
   1237         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1238         break;
   1239       case 0x2e:
   1240         AppendToBuffer("vucomiss %s,", NameOfXMMRegister(regop));
   1241         current += PrintRightXMMOperand(current);
   1242         break;
   1243       case 0x54:
   1244         AppendToBuffer("vandps %s,%s,", NameOfXMMRegister(regop),
   1245                        NameOfXMMRegister(vvvv));
   1246         current += PrintRightXMMOperand(current);
   1247         break;
   1248       case 0x57:
   1249         AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop),
   1250                        NameOfXMMRegister(vvvv));
   1251         current += PrintRightXMMOperand(current);
   1252         break;
   1253       default:
   1254         UnimplementedInstruction();
   1255     }
   1256   } else if (vex_66() && vex_0f()) {
   1257     int mod, regop, rm, vvvv = vex_vreg();
   1258     get_modrm(*current, &mod, &regop, &rm);
   1259     switch (opcode) {
   1260       case 0x28:
   1261         AppendToBuffer("vmovapd %s,", NameOfXMMRegister(regop));
   1262         current += PrintRightXMMOperand(current);
   1263         break;
   1264       case 0x29:
   1265         AppendToBuffer("vmovapd ");
   1266         current += PrintRightXMMOperand(current);
   1267         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1268         break;
   1269       case 0x2e:
   1270         AppendToBuffer("vucomisd %s,", NameOfXMMRegister(regop));
   1271         current += PrintRightXMMOperand(current);
   1272         break;
   1273       case 0x50:
   1274         AppendToBuffer("vmovmskpd %s,", NameOfCPURegister(regop));
   1275         current += PrintRightXMMOperand(current);
   1276         break;
   1277       case 0x54:
   1278         AppendToBuffer("vandpd %s,%s,", NameOfXMMRegister(regop),
   1279                        NameOfXMMRegister(vvvv));
   1280         current += PrintRightXMMOperand(current);
   1281         break;
   1282       case 0x56:
   1283         AppendToBuffer("vorpd %s,%s,", NameOfXMMRegister(regop),
   1284                        NameOfXMMRegister(vvvv));
   1285         current += PrintRightXMMOperand(current);
   1286         break;
   1287       case 0x57:
   1288         AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop),
   1289                        NameOfXMMRegister(vvvv));
   1290         current += PrintRightXMMOperand(current);
   1291         break;
   1292       case 0x6e:
   1293         AppendToBuffer("vmov%c %s,", vex_w() ? 'q' : 'd',
   1294                        NameOfXMMRegister(regop));
   1295         current += PrintRightOperand(current);
   1296         break;
   1297       case 0x73:
   1298         AppendToBuffer("%s %s,", regop == 6 ? "vpsllq" : "vpsrlq",
   1299                        NameOfXMMRegister(vvvv));
   1300         current += PrintRightXMMOperand(current);
   1301         AppendToBuffer(",%u", *current++);
   1302         break;
   1303       case 0x76:
   1304         AppendToBuffer("vpcmpeqd %s,%s,", NameOfXMMRegister(regop),
   1305                        NameOfXMMRegister(vvvv));
   1306         current += PrintRightXMMOperand(current);
   1307         break;
   1308       case 0x7e:
   1309         AppendToBuffer("vmov%c ", vex_w() ? 'q' : 'd');
   1310         current += PrintRightOperand(current);
   1311         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1312         break;
   1313       default:
   1314         UnimplementedInstruction();
   1315     }
   1316 
   1317   } else {
   1318     UnimplementedInstruction();
   1319   }
   1320 
   1321   return static_cast<int>(current - data);
   1322 }
   1323 
   1324 
   1325 // Returns number of bytes used, including *data.
   1326 int DisassemblerX64::FPUInstruction(byte* data) {
   1327   byte escape_opcode = *data;
   1328   DCHECK_EQ(0xD8, escape_opcode & 0xF8);
   1329   byte modrm_byte = *(data+1);
   1330 
   1331   if (modrm_byte >= 0xC0) {
   1332     return RegisterFPUInstruction(escape_opcode, modrm_byte);
   1333   } else {
   1334     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
   1335   }
   1336 }
   1337 
   1338 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
   1339                                            int modrm_byte,
   1340                                            byte* modrm_start) {
   1341   const char* mnem = "?";
   1342   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
   1343   switch (escape_opcode) {
   1344     case 0xD9: switch (regop) {
   1345         case 0: mnem = "fld_s"; break;
   1346         case 3: mnem = "fstp_s"; break;
   1347         case 7: mnem = "fstcw"; break;
   1348         default: UnimplementedInstruction();
   1349       }
   1350       break;
   1351 
   1352     case 0xDB: switch (regop) {
   1353         case 0: mnem = "fild_s"; break;
   1354         case 1: mnem = "fisttp_s"; break;
   1355         case 2: mnem = "fist_s"; break;
   1356         case 3: mnem = "fistp_s"; break;
   1357         default: UnimplementedInstruction();
   1358       }
   1359       break;
   1360 
   1361     case 0xDD: switch (regop) {
   1362         case 0: mnem = "fld_d"; break;
   1363         case 3: mnem = "fstp_d"; break;
   1364         default: UnimplementedInstruction();
   1365       }
   1366       break;
   1367 
   1368     case 0xDF: switch (regop) {
   1369         case 5: mnem = "fild_d"; break;
   1370         case 7: mnem = "fistp_d"; break;
   1371         default: UnimplementedInstruction();
   1372       }
   1373       break;
   1374 
   1375     default: UnimplementedInstruction();
   1376   }
   1377   AppendToBuffer("%s ", mnem);
   1378   int count = PrintRightOperand(modrm_start);
   1379   return count + 1;
   1380 }
   1381 
   1382 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
   1383                                              byte modrm_byte) {
   1384   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
   1385   const char* mnem = "?";
   1386 
   1387   switch (escape_opcode) {
   1388     case 0xD8:
   1389       UnimplementedInstruction();
   1390       break;
   1391 
   1392     case 0xD9:
   1393       switch (modrm_byte & 0xF8) {
   1394         case 0xC0:
   1395           mnem = "fld";
   1396           has_register = true;
   1397           break;
   1398         case 0xC8:
   1399           mnem = "fxch";
   1400           has_register = true;
   1401           break;
   1402         default:
   1403           switch (modrm_byte) {
   1404             case 0xE0: mnem = "fchs"; break;
   1405             case 0xE1: mnem = "fabs"; break;
   1406             case 0xE3: mnem = "fninit"; break;
   1407             case 0xE4: mnem = "ftst"; break;
   1408             case 0xE8: mnem = "fld1"; break;
   1409             case 0xEB: mnem = "fldpi"; break;
   1410             case 0xED: mnem = "fldln2"; break;
   1411             case 0xEE: mnem = "fldz"; break;
   1412             case 0xF0: mnem = "f2xm1"; break;
   1413             case 0xF1: mnem = "fyl2x"; break;
   1414             case 0xF2: mnem = "fptan"; break;
   1415             case 0xF5: mnem = "fprem1"; break;
   1416             case 0xF7: mnem = "fincstp"; break;
   1417             case 0xF8: mnem = "fprem"; break;
   1418             case 0xFC: mnem = "frndint"; break;
   1419             case 0xFD: mnem = "fscale"; break;
   1420             case 0xFE: mnem = "fsin"; break;
   1421             case 0xFF: mnem = "fcos"; break;
   1422             default: UnimplementedInstruction();
   1423           }
   1424       }
   1425       break;
   1426 
   1427     case 0xDA:
   1428       if (modrm_byte == 0xE9) {
   1429         mnem = "fucompp";
   1430       } else {
   1431         UnimplementedInstruction();
   1432       }
   1433       break;
   1434 
   1435     case 0xDB:
   1436       if ((modrm_byte & 0xF8) == 0xE8) {
   1437         mnem = "fucomi";
   1438         has_register = true;
   1439       } else if (modrm_byte  == 0xE2) {
   1440         mnem = "fclex";
   1441       } else if (modrm_byte == 0xE3) {
   1442         mnem = "fninit";
   1443       } else {
   1444         UnimplementedInstruction();
   1445       }
   1446       break;
   1447 
   1448     case 0xDC:
   1449       has_register = true;
   1450       switch (modrm_byte & 0xF8) {
   1451         case 0xC0: mnem = "fadd"; break;
   1452         case 0xE8: mnem = "fsub"; break;
   1453         case 0xC8: mnem = "fmul"; break;
   1454         case 0xF8: mnem = "fdiv"; break;
   1455         default: UnimplementedInstruction();
   1456       }
   1457       break;
   1458 
   1459     case 0xDD:
   1460       has_register = true;
   1461       switch (modrm_byte & 0xF8) {
   1462         case 0xC0: mnem = "ffree"; break;
   1463         case 0xD8: mnem = "fstp"; break;
   1464         default: UnimplementedInstruction();
   1465       }
   1466       break;
   1467 
   1468     case 0xDE:
   1469       if (modrm_byte  == 0xD9) {
   1470         mnem = "fcompp";
   1471       } else {
   1472         has_register = true;
   1473         switch (modrm_byte & 0xF8) {
   1474           case 0xC0: mnem = "faddp"; break;
   1475           case 0xE8: mnem = "fsubp"; break;
   1476           case 0xC8: mnem = "fmulp"; break;
   1477           case 0xF8: mnem = "fdivp"; break;
   1478           default: UnimplementedInstruction();
   1479         }
   1480       }
   1481       break;
   1482 
   1483     case 0xDF:
   1484       if (modrm_byte == 0xE0) {
   1485         mnem = "fnstsw_ax";
   1486       } else if ((modrm_byte & 0xF8) == 0xE8) {
   1487         mnem = "fucomip";
   1488         has_register = true;
   1489       }
   1490       break;
   1491 
   1492     default: UnimplementedInstruction();
   1493   }
   1494 
   1495   if (has_register) {
   1496     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
   1497   } else {
   1498     AppendToBuffer("%s", mnem);
   1499   }
   1500   return 2;
   1501 }
   1502 
   1503 
   1504 
   1505 // Handle all two-byte opcodes, which start with 0x0F.
   1506 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
   1507 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
   1508 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
   1509   byte opcode = *(data + 1);
   1510   byte* current = data + 2;
   1511   // At return, "current" points to the start of the next instruction.
   1512   const char* mnemonic = TwoByteMnemonic(opcode);
   1513   if (operand_size_ == 0x66) {
   1514     // 0x66 0x0F prefix.
   1515     int mod, regop, rm;
   1516     if (opcode == 0x38) {
   1517       byte third_byte = *current;
   1518       current = data + 3;
   1519       if (third_byte == 0x40) {
   1520         // pmulld xmm, xmm/m128
   1521         get_modrm(*current, &mod, &regop, &rm);
   1522         AppendToBuffer("pmulld %s,", NameOfXMMRegister(regop));
   1523         current += PrintRightXMMOperand(current);
   1524       }
   1525     } else if (opcode == 0x3A) {
   1526       byte third_byte = *current;
   1527       current = data + 3;
   1528       if (third_byte == 0x17) {
   1529         get_modrm(*current, &mod, &regop, &rm);
   1530         AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
   1531         current += PrintRightOperand(current);
   1532         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
   1533         current += 1;
   1534       } else if (third_byte == 0x0a) {
   1535         get_modrm(*current, &mod, &regop, &rm);
   1536         AppendToBuffer("roundss %s,", NameOfXMMRegister(regop));
   1537         current += PrintRightXMMOperand(current);
   1538         AppendToBuffer(",0x%x", (*current) & 3);
   1539         current += 1;
   1540       } else if (third_byte == 0x0b) {
   1541         get_modrm(*current, &mod, &regop, &rm);
   1542          // roundsd xmm, xmm/m64, imm8
   1543         AppendToBuffer("roundsd %s,", NameOfXMMRegister(regop));
   1544         current += PrintRightXMMOperand(current);
   1545         AppendToBuffer(",0x%x", (*current) & 3);
   1546         current += 1;
   1547       } else if (third_byte == 0x16) {
   1548         get_modrm(*current, &mod, &regop, &rm);
   1549         AppendToBuffer("pextrd ");  // reg/m32, xmm, imm8
   1550         current += PrintRightOperand(current);
   1551         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
   1552         current += 1;
   1553       } else if (third_byte == 0x21) {
   1554         get_modrm(*current, &mod, &regop, &rm);
   1555         // insertps xmm, xmm/m32, imm8
   1556         AppendToBuffer("insertps %s,", NameOfXMMRegister(regop));
   1557         current += PrintRightXMMOperand(current);
   1558         AppendToBuffer(",0x%x", (*current) & 3);
   1559         current += 1;
   1560       } else if (third_byte == 0x22) {
   1561         get_modrm(*current, &mod, &regop, &rm);
   1562         AppendToBuffer("pinsrd ");  // xmm, reg/m32, imm8
   1563         AppendToBuffer(" %s,", NameOfXMMRegister(regop));
   1564         current += PrintRightOperand(current);
   1565         AppendToBuffer(",%d", (*current) & 3);
   1566         current += 1;
   1567       } else {
   1568         UnimplementedInstruction();
   1569       }
   1570     } else {
   1571       get_modrm(*current, &mod, &regop, &rm);
   1572       if (opcode == 0x1f) {
   1573         current++;
   1574         if (rm == 4) {  // SIB byte present.
   1575           current++;
   1576         }
   1577         if (mod == 1) {  // Byte displacement.
   1578           current += 1;
   1579         } else if (mod == 2) {  // 32-bit displacement.
   1580           current += 4;
   1581         }  // else no immediate displacement.
   1582         AppendToBuffer("nop");
   1583       } else if (opcode == 0x28) {
   1584         AppendToBuffer("movapd %s,", NameOfXMMRegister(regop));
   1585         current += PrintRightXMMOperand(current);
   1586       } else if (opcode == 0x29) {
   1587         AppendToBuffer("movapd ");
   1588         current += PrintRightXMMOperand(current);
   1589         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1590       } else if (opcode == 0x6E) {
   1591         AppendToBuffer("mov%c %s,",
   1592                        rex_w() ? 'q' : 'd',
   1593                        NameOfXMMRegister(regop));
   1594         current += PrintRightOperand(current);
   1595       } else if (opcode == 0x6F) {
   1596         AppendToBuffer("movdqa %s,",
   1597                        NameOfXMMRegister(regop));
   1598         current += PrintRightXMMOperand(current);
   1599       } else if (opcode == 0x7E) {
   1600         AppendToBuffer("mov%c ",
   1601                        rex_w() ? 'q' : 'd');
   1602         current += PrintRightOperand(current);
   1603         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1604       } else if (opcode == 0x7F) {
   1605         AppendToBuffer("movdqa ");
   1606         current += PrintRightXMMOperand(current);
   1607         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1608       } else if (opcode == 0xD6) {
   1609         AppendToBuffer("movq ");
   1610         current += PrintRightXMMOperand(current);
   1611         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1612       } else if (opcode == 0x50) {
   1613         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
   1614         current += PrintRightXMMOperand(current);
   1615       } else if (opcode == 0x70) {
   1616         AppendToBuffer("pshufd %s,", NameOfXMMRegister(regop));
   1617         current += PrintRightXMMOperand(current);
   1618         AppendToBuffer(",0x%x", *current);
   1619         current += 1;
   1620       } else if (opcode == 0x72) {
   1621         current += 1;
   1622         AppendToBuffer("%s %s,%d", (regop == 6) ? "pslld" : "psrld",
   1623                        NameOfXMMRegister(rm), *current & 0x7f);
   1624         current += 1;
   1625       } else if (opcode == 0x73) {
   1626         current += 1;
   1627         AppendToBuffer("%s %s,%d", (regop == 6) ? "psllq" : "psrlq",
   1628                        NameOfXMMRegister(rm), *current & 0x7f);
   1629         current += 1;
   1630       } else if (opcode == 0xB1) {
   1631         current += PrintOperands("cmpxchg", OPER_REG_OP_ORDER, current);
   1632       } else {
   1633         const char* mnemonic = "?";
   1634         if (opcode == 0x54) {
   1635           mnemonic = "andpd";
   1636         } else  if (opcode == 0x56) {
   1637           mnemonic = "orpd";
   1638         } else  if (opcode == 0x57) {
   1639           mnemonic = "xorpd";
   1640         } else if (opcode == 0x5B) {
   1641           mnemonic = "cvtps2dq";
   1642         } else if (opcode == 0x2E) {
   1643           mnemonic = "ucomisd";
   1644         } else if (opcode == 0x2F) {
   1645           mnemonic = "comisd";
   1646         } else if (opcode == 0x76) {
   1647           mnemonic = "pcmpeqd";
   1648         } else if (opcode == 0x62) {
   1649           mnemonic = "punpckldq";
   1650         } else if (opcode == 0x6A) {
   1651           mnemonic = "punpckhdq";
   1652         } else if (opcode == 0xF4) {
   1653           mnemonic = "pmuludq";
   1654         } else if (opcode == 0xFA) {
   1655           mnemonic = "psubd";
   1656         } else if (opcode == 0xFE) {
   1657           mnemonic = "paddd";
   1658         } else {
   1659           UnimplementedInstruction();
   1660         }
   1661         AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1662         current += PrintRightXMMOperand(current);
   1663       }
   1664     }
   1665   } else if (group_1_prefix_ == 0xF2) {
   1666     // Beginning of instructions with prefix 0xF2.
   1667 
   1668     if (opcode == 0x11 || opcode == 0x10) {
   1669       // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
   1670       AppendToBuffer("movsd ");
   1671       int mod, regop, rm;
   1672       get_modrm(*current, &mod, &regop, &rm);
   1673       if (opcode == 0x11) {
   1674         current += PrintRightXMMOperand(current);
   1675         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1676       } else {
   1677         AppendToBuffer("%s,", NameOfXMMRegister(regop));
   1678         current += PrintRightXMMOperand(current);
   1679       }
   1680     } else if (opcode == 0x2A) {
   1681       // CVTSI2SD: integer to XMM double conversion.
   1682       int mod, regop, rm;
   1683       get_modrm(*current, &mod, &regop, &rm);
   1684       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1685       current += PrintRightOperand(current);
   1686     } else if (opcode == 0x2C) {
   1687       // CVTTSD2SI:
   1688       // Convert with truncation scalar double-precision FP to integer.
   1689       int mod, regop, rm;
   1690       get_modrm(*current, &mod, &regop, &rm);
   1691       AppendToBuffer("cvttsd2si%c %s,",
   1692           operand_size_code(), NameOfCPURegister(regop));
   1693       current += PrintRightXMMOperand(current);
   1694     } else if (opcode == 0x2D) {
   1695       // CVTSD2SI: Convert scalar double-precision FP to integer.
   1696       int mod, regop, rm;
   1697       get_modrm(*current, &mod, &regop, &rm);
   1698       AppendToBuffer("cvtsd2si%c %s,",
   1699           operand_size_code(), NameOfCPURegister(regop));
   1700       current += PrintRightXMMOperand(current);
   1701     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
   1702       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
   1703       int mod, regop, rm;
   1704       get_modrm(*current, &mod, &regop, &rm);
   1705       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1706       current += PrintRightXMMOperand(current);
   1707     } else if (opcode == 0xC2) {
   1708       // Intel manual 2A, Table 3-18.
   1709       int mod, regop, rm;
   1710       get_modrm(*current, &mod, &regop, &rm);
   1711       const char* const pseudo_op[] = {
   1712         "cmpeqsd",
   1713         "cmpltsd",
   1714         "cmplesd",
   1715         "cmpunordsd",
   1716         "cmpneqsd",
   1717         "cmpnltsd",
   1718         "cmpnlesd",
   1719         "cmpordsd"
   1720       };
   1721       AppendToBuffer("%s %s,%s",
   1722                      pseudo_op[current[1]],
   1723                      NameOfXMMRegister(regop),
   1724                      NameOfXMMRegister(rm));
   1725       current += 2;
   1726     } else {
   1727       UnimplementedInstruction();
   1728     }
   1729   } else if (group_1_prefix_ == 0xF3) {
   1730     // Instructions with prefix 0xF3.
   1731     if (opcode == 0x11 || opcode == 0x10) {
   1732       // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
   1733       AppendToBuffer("movss ");
   1734       int mod, regop, rm;
   1735       get_modrm(*current, &mod, &regop, &rm);
   1736       if (opcode == 0x11) {
   1737         current += PrintRightOperand(current);
   1738         AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1739       } else {
   1740         AppendToBuffer("%s,", NameOfXMMRegister(regop));
   1741         current += PrintRightOperand(current);
   1742       }
   1743     } else if (opcode == 0x2A) {
   1744       // CVTSI2SS: integer to XMM single conversion.
   1745       int mod, regop, rm;
   1746       get_modrm(*current, &mod, &regop, &rm);
   1747       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1748       current += PrintRightOperand(current);
   1749     } else if (opcode == 0x2C) {
   1750       // CVTTSS2SI:
   1751       // Convert with truncation scalar single-precision FP to dword integer.
   1752       int mod, regop, rm;
   1753       get_modrm(*current, &mod, &regop, &rm);
   1754       AppendToBuffer("cvttss2si%c %s,",
   1755           operand_size_code(), NameOfCPURegister(regop));
   1756       current += PrintRightXMMOperand(current);
   1757     } else if (opcode == 0x7E) {
   1758       int mod, regop, rm;
   1759       get_modrm(*current, &mod, &regop, &rm);
   1760       AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
   1761       current += PrintRightXMMOperand(current);
   1762     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
   1763       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
   1764       int mod, regop, rm;
   1765       get_modrm(*current, &mod, &regop, &rm);
   1766       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
   1767       current += PrintRightXMMOperand(current);
   1768     } else if (opcode == 0xB8) {
   1769       int mod, regop, rm;
   1770       get_modrm(*current, &mod, &regop, &rm);
   1771       AppendToBuffer("popcnt%c %s,", operand_size_code(),
   1772                      NameOfCPURegister(regop));
   1773       current += PrintRightOperand(current);
   1774     } else if (opcode == 0xBC) {
   1775       int mod, regop, rm;
   1776       get_modrm(*current, &mod, &regop, &rm);
   1777       AppendToBuffer("tzcnt%c %s,", operand_size_code(),
   1778                      NameOfCPURegister(regop));
   1779       current += PrintRightOperand(current);
   1780     } else if (opcode == 0xBD) {
   1781       int mod, regop, rm;
   1782       get_modrm(*current, &mod, &regop, &rm);
   1783       AppendToBuffer("lzcnt%c %s,", operand_size_code(),
   1784                      NameOfCPURegister(regop));
   1785       current += PrintRightOperand(current);
   1786     } else if (opcode == 0xC2) {
   1787       // Intel manual 2A, Table 3-18.
   1788       int mod, regop, rm;
   1789       get_modrm(*current, &mod, &regop, &rm);
   1790       const char* const pseudo_op[] = {"cmpeqss",    "cmpltss",  "cmpless",
   1791                                        "cmpunordss", "cmpneqss", "cmpnltss",
   1792                                        "cmpnless",   "cmpordss"};
   1793       AppendToBuffer("%s %s,%s", pseudo_op[current[1]],
   1794                      NameOfXMMRegister(regop), NameOfXMMRegister(rm));
   1795       current += 2;
   1796     } else {
   1797       UnimplementedInstruction();
   1798     }
   1799   } else if (opcode == 0x10 || opcode == 0x11) {
   1800     // movups xmm, xmm/m128
   1801     // movups xmm/m128, xmm
   1802     int mod, regop, rm;
   1803     get_modrm(*current, &mod, &regop, &rm);
   1804     AppendToBuffer("movups ");
   1805     if (opcode == 0x11) {
   1806       current += PrintRightXMMOperand(current);
   1807       AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1808     } else {
   1809       AppendToBuffer("%s,", NameOfXMMRegister(regop));
   1810       current += PrintRightXMMOperand(current);
   1811     }
   1812   } else if (opcode == 0x1F) {
   1813     // NOP
   1814     int mod, regop, rm;
   1815     get_modrm(*current, &mod, &regop, &rm);
   1816     current++;
   1817     if (rm == 4) {  // SIB byte present.
   1818       current++;
   1819     }
   1820     if (mod == 1) {  // Byte displacement.
   1821       current += 1;
   1822     } else if (mod == 2) {  // 32-bit displacement.
   1823       current += 4;
   1824     }  // else no immediate displacement.
   1825     AppendToBuffer("nop");
   1826 
   1827   } else if (opcode == 0x28) {
   1828     // movaps xmm, xmm/m128
   1829     int mod, regop, rm;
   1830     get_modrm(*current, &mod, &regop, &rm);
   1831     AppendToBuffer("movaps %s,", NameOfXMMRegister(regop));
   1832     current += PrintRightXMMOperand(current);
   1833 
   1834   } else if (opcode == 0x29) {
   1835     // movaps xmm/m128, xmm
   1836     int mod, regop, rm;
   1837     get_modrm(*current, &mod, &regop, &rm);
   1838     AppendToBuffer("movaps ");
   1839     current += PrintRightXMMOperand(current);
   1840     AppendToBuffer(",%s", NameOfXMMRegister(regop));
   1841 
   1842   } else if (opcode == 0x2e) {
   1843     int mod, regop, rm;
   1844     get_modrm(*current, &mod, &regop, &rm);
   1845     AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
   1846     current += PrintRightXMMOperand(current);
   1847   } else if (opcode == 0xA2) {
   1848     // CPUID
   1849     AppendToBuffer("%s", mnemonic);
   1850 
   1851   } else if ((opcode & 0xF0) == 0x40) {
   1852     // CMOVcc: conditional move.
   1853     int condition = opcode & 0x0F;
   1854     const InstructionDesc& idesc = cmov_instructions[condition];
   1855     byte_size_operand_ = idesc.byte_size_operation;
   1856     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
   1857 
   1858   } else if (opcode >= 0x51 && opcode <= 0x5F) {
   1859     const char* const pseudo_op[] = {
   1860         "sqrtps",   "rsqrtps", "rcpps", "andps", "andnps",
   1861         "orps",     "xorps",   "addps", "mulps", "cvtps2pd",
   1862         "cvtdq2ps", "subps",   "minps", "divps", "maxps",
   1863     };
   1864     int mod, regop, rm;
   1865     get_modrm(*current, &mod, &regop, &rm);
   1866     AppendToBuffer("%s %s,", pseudo_op[opcode - 0x51],
   1867                    NameOfXMMRegister(regop));
   1868     current += PrintRightXMMOperand(current);
   1869 
   1870   } else if (opcode == 0xC2) {
   1871     // cmpps xmm, xmm/m128, imm8
   1872     int mod, regop, rm;
   1873     get_modrm(*current, &mod, &regop, &rm);
   1874     const char* const pseudo_op[] = {"cmpeqps",    "cmpltps",  "cmpleps",
   1875                                      "cmpunordps", "cmpneqps", "cmpnltps",
   1876                                      "cmpnleps",   "cmpordps"};
   1877     AppendToBuffer("%s %s,%s", pseudo_op[current[1]], NameOfXMMRegister(regop),
   1878                    NameOfXMMRegister(rm));
   1879     current += 2;
   1880   } else if (opcode == 0xC6) {
   1881     // shufps xmm, xmm/m128, imm8
   1882     int mod, regop, rm;
   1883     get_modrm(*current, &mod, &regop, &rm);
   1884     AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
   1885     current += PrintRightXMMOperand(current);
   1886     AppendToBuffer(", %d", (*current) & 3);
   1887     current += 1;
   1888   } else if (opcode == 0x50) {
   1889     // movmskps reg, xmm
   1890     int mod, regop, rm;
   1891     get_modrm(*current, &mod, &regop, &rm);
   1892     AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
   1893     current += PrintRightXMMOperand(current);
   1894 
   1895   } else if ((opcode & 0xF0) == 0x80) {
   1896     // Jcc: Conditional jump (branch).
   1897     current = data + JumpConditional(data);
   1898 
   1899   } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
   1900              opcode == 0xB7 || opcode == 0xAF) {
   1901     // Size-extending moves, IMUL.
   1902     current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
   1903 
   1904   } else if ((opcode & 0xF0) == 0x90) {
   1905     // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
   1906     current = data + SetCC(data);
   1907 
   1908   } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
   1909     // SHLD, SHRD (double-precision shift), BTS (bit set).
   1910     AppendToBuffer("%s ", mnemonic);
   1911     int mod, regop, rm;
   1912     get_modrm(*current, &mod, &regop, &rm);
   1913     current += PrintRightOperand(current);
   1914     if (opcode == 0xAB) {
   1915       AppendToBuffer(",%s", NameOfCPURegister(regop));
   1916     } else {
   1917       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
   1918     }
   1919   } else if (opcode == 0xB8 || opcode == 0xBC || opcode == 0xBD) {
   1920     // POPCNT, CTZ, CLZ.
   1921     AppendToBuffer("%s%c ", mnemonic, operand_size_code());
   1922     int mod, regop, rm;
   1923     get_modrm(*current, &mod, &regop, &rm);
   1924     AppendToBuffer("%s,", NameOfCPURegister(regop));
   1925     current += PrintRightOperand(current);
   1926   } else if (opcode == 0x0B) {
   1927     AppendToBuffer("ud2");
   1928   } else if (opcode == 0xB0 || opcode == 0xB1) {
   1929     // CMPXCHG.
   1930     if (opcode == 0xB0) {
   1931       byte_size_operand_ = true;
   1932     }
   1933     current += PrintOperands(mnemonic, OPER_REG_OP_ORDER, current);
   1934   } else {
   1935     UnimplementedInstruction();
   1936   }
   1937   return static_cast<int>(current - data);
   1938 }
   1939 
   1940 
   1941 // Mnemonics for two-byte opcode instructions starting with 0x0F.
   1942 // The argument is the second byte of the two-byte opcode.
   1943 // Returns NULL if the instruction is not handled here.
   1944 const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
   1945   switch (opcode) {
   1946     case 0x1F:
   1947       return "nop";
   1948     case 0x2A:  // F2/F3 prefix.
   1949       return (group_1_prefix_ == 0xF2) ? "cvtsi2sd" : "cvtsi2ss";
   1950     case 0x51:  // F2/F3 prefix.
   1951       return (group_1_prefix_ == 0xF2) ? "sqrtsd" : "sqrtss";
   1952     case 0x58:  // F2/F3 prefix.
   1953       return (group_1_prefix_ == 0xF2) ? "addsd" : "addss";
   1954     case 0x59:  // F2/F3 prefix.
   1955       return (group_1_prefix_ == 0xF2) ? "mulsd" : "mulss";
   1956     case 0x5A:  // F2/F3 prefix.
   1957       return (group_1_prefix_ == 0xF2) ? "cvtsd2ss" : "cvtss2sd";
   1958     case 0x5D:  // F2/F3 prefix.
   1959       return (group_1_prefix_ == 0xF2) ? "minsd" : "minss";
   1960     case 0x5C:  // F2/F3 prefix.
   1961       return (group_1_prefix_ == 0xF2) ? "subsd" : "subss";
   1962     case 0x5E:  // F2/F3 prefix.
   1963       return (group_1_prefix_ == 0xF2) ? "divsd" : "divss";
   1964     case 0x5F:  // F2/F3 prefix.
   1965       return (group_1_prefix_ == 0xF2) ? "maxsd" : "maxss";
   1966     case 0xA2:
   1967       return "cpuid";
   1968     case 0xA5:
   1969       return "shld";
   1970     case 0xAB:
   1971       return "bts";
   1972     case 0xAD:
   1973       return "shrd";
   1974     case 0xAF:
   1975       return "imul";
   1976     case 0xB0:
   1977     case 0xB1:
   1978       return "cmpxchg";
   1979     case 0xB6:
   1980       return "movzxb";
   1981     case 0xB7:
   1982       return "movzxw";
   1983     case 0xBC:
   1984       return "bsf";
   1985     case 0xBD:
   1986       return "bsr";
   1987     case 0xBE:
   1988       return "movsxb";
   1989     case 0xBF:
   1990       return "movsxw";
   1991     default:
   1992       return NULL;
   1993   }
   1994 }
   1995 
   1996 
   1997 // Disassembles the instruction at instr, and writes it into out_buffer.
   1998 int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
   1999                                        byte* instr) {
   2000   tmp_buffer_pos_ = 0;  // starting to write as position 0
   2001   byte* data = instr;
   2002   bool processed = true;  // Will be set to false if the current instruction
   2003                           // is not in 'instructions' table.
   2004   byte current;
   2005 
   2006   // Scan for prefixes.
   2007   while (true) {
   2008     current = *data;
   2009     if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
   2010       operand_size_ = current;
   2011     } else if ((current & 0xF0) == 0x40) {  // REX prefix.
   2012       setRex(current);
   2013       if (rex_w()) AppendToBuffer("REX.W ");
   2014     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
   2015       group_1_prefix_ = current;
   2016     } else if (current == LOCK_PREFIX) {
   2017       AppendToBuffer("lock ");
   2018     } else if (current == VEX3_PREFIX) {
   2019       vex_byte0_ = current;
   2020       vex_byte1_ = *(data + 1);
   2021       vex_byte2_ = *(data + 2);
   2022       setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
   2023       data += 3;
   2024       break;  // Vex is the last prefix.
   2025     } else if (current == VEX2_PREFIX) {
   2026       vex_byte0_ = current;
   2027       vex_byte1_ = *(data + 1);
   2028       setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
   2029       data += 2;
   2030       break;  // Vex is the last prefix.
   2031     } else {  // Not a prefix - an opcode.
   2032       break;
   2033     }
   2034     data++;
   2035   }
   2036 
   2037   // Decode AVX instructions.
   2038   if (vex_byte0_ != 0) {
   2039     processed = true;
   2040     data += AVXInstruction(data);
   2041   } else {
   2042     const InstructionDesc& idesc = instruction_table_->Get(current);
   2043     byte_size_operand_ = idesc.byte_size_operation;
   2044     switch (idesc.type) {
   2045       case ZERO_OPERANDS_INSTR:
   2046         if (current >= 0xA4 && current <= 0xA7) {
   2047           // String move or compare operations.
   2048           if (group_1_prefix_ == REP_PREFIX) {
   2049             // REP.
   2050             AppendToBuffer("rep ");
   2051           }
   2052           if (rex_w()) AppendToBuffer("REX.W ");
   2053           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
   2054         } else {
   2055           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
   2056         }
   2057         data++;
   2058         break;
   2059 
   2060       case TWO_OPERANDS_INSTR:
   2061         data++;
   2062         data += PrintOperands(idesc.mnem, idesc.op_order_, data);
   2063         break;
   2064 
   2065       case JUMP_CONDITIONAL_SHORT_INSTR:
   2066         data += JumpConditionalShort(data);
   2067         break;
   2068 
   2069       case REGISTER_INSTR:
   2070         AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(),
   2071                        NameOfCPURegister(base_reg(current & 0x07)));
   2072         data++;
   2073         break;
   2074       case PUSHPOP_INSTR:
   2075         AppendToBuffer("%s %s", idesc.mnem,
   2076                        NameOfCPURegister(base_reg(current & 0x07)));
   2077         data++;
   2078         break;
   2079       case MOVE_REG_INSTR: {
   2080         byte* addr = NULL;
   2081         switch (operand_size()) {
   2082           case OPERAND_WORD_SIZE:
   2083             addr =
   2084                 reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
   2085             data += 3;
   2086             break;
   2087           case OPERAND_DOUBLEWORD_SIZE:
   2088             addr =
   2089                 reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
   2090             data += 5;
   2091             break;
   2092           case OPERAND_QUADWORD_SIZE:
   2093             addr =
   2094                 reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
   2095             data += 9;
   2096             break;
   2097           default:
   2098             UNREACHABLE();
   2099         }
   2100         AppendToBuffer("mov%c %s,%s", operand_size_code(),
   2101                        NameOfCPURegister(base_reg(current & 0x07)),
   2102                        NameOfAddress(addr));
   2103         break;
   2104       }
   2105 
   2106       case CALL_JUMP_INSTR: {
   2107         byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
   2108         AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
   2109         data += 5;
   2110         break;
   2111       }
   2112 
   2113       case SHORT_IMMEDIATE_INSTR: {
   2114         byte* addr =
   2115             reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
   2116         AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
   2117         data += 5;
   2118         break;
   2119       }
   2120 
   2121       case NO_INSTR:
   2122         processed = false;
   2123         break;
   2124 
   2125       default:
   2126         UNIMPLEMENTED();  // This type is not implemented.
   2127     }
   2128   }
   2129 
   2130   // The first byte didn't match any of the simple opcodes, so we
   2131   // need to do special processing on it.
   2132   if (!processed) {
   2133     switch (*data) {
   2134       case 0xC2:
   2135         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
   2136         data += 3;
   2137         break;
   2138 
   2139       case 0x69:  // fall through
   2140       case 0x6B: {
   2141         int count = 1;
   2142         count += PrintOperands("imul", REG_OPER_OP_ORDER, data + count);
   2143         AppendToBuffer(",0x");
   2144         if (*data == 0x69) {
   2145           count += PrintImmediate(data + count, operand_size());
   2146         } else {
   2147           count += PrintImmediate(data + count, OPERAND_BYTE_SIZE);
   2148         }
   2149         data += count;
   2150         break;
   2151       }
   2152 
   2153       case 0x81:  // fall through
   2154       case 0x83:  // 0x81 with sign extension bit set
   2155         data += PrintImmediateOp(data);
   2156         break;
   2157 
   2158       case 0x0F:
   2159         data += TwoByteOpcodeInstruction(data);
   2160         break;
   2161 
   2162       case 0x8F: {
   2163         data++;
   2164         int mod, regop, rm;
   2165         get_modrm(*data, &mod, &regop, &rm);
   2166         if (regop == 0) {
   2167           AppendToBuffer("pop ");
   2168           data += PrintRightOperand(data);
   2169         }
   2170       }
   2171         break;
   2172 
   2173       case 0xFF: {
   2174         data++;
   2175         int mod, regop, rm;
   2176         get_modrm(*data, &mod, &regop, &rm);
   2177         const char* mnem = NULL;
   2178         switch (regop) {
   2179           case 0:
   2180             mnem = "inc";
   2181             break;
   2182           case 1:
   2183             mnem = "dec";
   2184             break;
   2185           case 2:
   2186             mnem = "call";
   2187             break;
   2188           case 4:
   2189             mnem = "jmp";
   2190             break;
   2191           case 6:
   2192             mnem = "push";
   2193             break;
   2194           default:
   2195             mnem = "???";
   2196         }
   2197         if (regop <= 1) {
   2198           AppendToBuffer("%s%c ", mnem, operand_size_code());
   2199         } else {
   2200           AppendToBuffer("%s ", mnem);
   2201         }
   2202         data += PrintRightOperand(data);
   2203       }
   2204         break;
   2205 
   2206       case 0xC7:  // imm32, fall through
   2207       case 0xC6:  // imm8
   2208       {
   2209         bool is_byte = *data == 0xC6;
   2210         data++;
   2211         if (is_byte) {
   2212           AppendToBuffer("movb ");
   2213           data += PrintRightByteOperand(data);
   2214           int32_t imm = *data;
   2215           AppendToBuffer(",0x%x", imm);
   2216           data++;
   2217         } else {
   2218           AppendToBuffer("mov%c ", operand_size_code());
   2219           data += PrintRightOperand(data);
   2220           if (operand_size() == OPERAND_WORD_SIZE) {
   2221             int16_t imm = *reinterpret_cast<int16_t*>(data);
   2222             AppendToBuffer(",0x%x", imm);
   2223             data += 2;
   2224           } else {
   2225             int32_t imm = *reinterpret_cast<int32_t*>(data);
   2226             AppendToBuffer(",0x%x", imm);
   2227             data += 4;
   2228           }
   2229         }
   2230       }
   2231         break;
   2232 
   2233       case 0x80: {
   2234         data++;
   2235         AppendToBuffer("cmpb ");
   2236         data += PrintRightByteOperand(data);
   2237         int32_t imm = *data;
   2238         AppendToBuffer(",0x%x", imm);
   2239         data++;
   2240       }
   2241         break;
   2242 
   2243       case 0x88:  // 8bit, fall through
   2244       case 0x89:  // 32bit
   2245       {
   2246         bool is_byte = *data == 0x88;
   2247         int mod, regop, rm;
   2248         data++;
   2249         get_modrm(*data, &mod, &regop, &rm);
   2250         if (is_byte) {
   2251           AppendToBuffer("movb ");
   2252           data += PrintRightByteOperand(data);
   2253           AppendToBuffer(",%s", NameOfByteCPURegister(regop));
   2254         } else {
   2255           AppendToBuffer("mov%c ", operand_size_code());
   2256           data += PrintRightOperand(data);
   2257           AppendToBuffer(",%s", NameOfCPURegister(regop));
   2258         }
   2259       }
   2260         break;
   2261 
   2262       case 0x90:
   2263       case 0x91:
   2264       case 0x92:
   2265       case 0x93:
   2266       case 0x94:
   2267       case 0x95:
   2268       case 0x96:
   2269       case 0x97: {
   2270         int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
   2271         if (reg == 0) {
   2272           AppendToBuffer("nop");  // Common name for xchg rax,rax.
   2273         } else {
   2274           AppendToBuffer("xchg%c rax,%s",
   2275                          operand_size_code(),
   2276                          NameOfCPURegister(reg));
   2277         }
   2278         data++;
   2279       }
   2280         break;
   2281       case 0xB0:
   2282       case 0xB1:
   2283       case 0xB2:
   2284       case 0xB3:
   2285       case 0xB4:
   2286       case 0xB5:
   2287       case 0xB6:
   2288       case 0xB7:
   2289       case 0xB8:
   2290       case 0xB9:
   2291       case 0xBA:
   2292       case 0xBB:
   2293       case 0xBC:
   2294       case 0xBD:
   2295       case 0xBE:
   2296       case 0xBF: {
   2297         // mov reg8,imm8 or mov reg32,imm32
   2298         byte opcode = *data;
   2299         data++;
   2300         bool is_32bit = (opcode >= 0xB8);
   2301         int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
   2302         if (is_32bit) {
   2303           AppendToBuffer("mov%c %s,",
   2304                          operand_size_code(),
   2305                          NameOfCPURegister(reg));
   2306           data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
   2307         } else {
   2308           AppendToBuffer("movb %s,",
   2309                          NameOfByteCPURegister(reg));
   2310           data += PrintImmediate(data, OPERAND_BYTE_SIZE);
   2311         }
   2312         break;
   2313       }
   2314       case 0xFE: {
   2315         data++;
   2316         int mod, regop, rm;
   2317         get_modrm(*data, &mod, &regop, &rm);
   2318         if (regop == 1) {
   2319           AppendToBuffer("decb ");
   2320           data += PrintRightByteOperand(data);
   2321         } else {
   2322           UnimplementedInstruction();
   2323         }
   2324         break;
   2325       }
   2326       case 0x68:
   2327         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
   2328         data += 5;
   2329         break;
   2330 
   2331       case 0x6A:
   2332         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
   2333         data += 2;
   2334         break;
   2335 
   2336       case 0xA1:  // Fall through.
   2337       case 0xA3:
   2338         switch (operand_size()) {
   2339           case OPERAND_DOUBLEWORD_SIZE: {
   2340             const char* memory_location = NameOfAddress(
   2341                 reinterpret_cast<byte*>(
   2342                     *reinterpret_cast<int32_t*>(data + 1)));
   2343             if (*data == 0xA1) {  // Opcode 0xA1
   2344               AppendToBuffer("movzxlq rax,(%s)", memory_location);
   2345             } else {  // Opcode 0xA3
   2346               AppendToBuffer("movzxlq (%s),rax", memory_location);
   2347             }
   2348             data += 5;
   2349             break;
   2350           }
   2351           case OPERAND_QUADWORD_SIZE: {
   2352             // New x64 instruction mov rax,(imm_64).
   2353             const char* memory_location = NameOfAddress(
   2354                 *reinterpret_cast<byte**>(data + 1));
   2355             if (*data == 0xA1) {  // Opcode 0xA1
   2356               AppendToBuffer("movq rax,(%s)", memory_location);
   2357             } else {  // Opcode 0xA3
   2358               AppendToBuffer("movq (%s),rax", memory_location);
   2359             }
   2360             data += 9;
   2361             break;
   2362           }
   2363           default:
   2364             UnimplementedInstruction();
   2365             data += 2;
   2366         }
   2367         break;
   2368 
   2369       case 0xA8:
   2370         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
   2371         data += 2;
   2372         break;
   2373 
   2374       case 0xA9: {
   2375         int64_t value = 0;
   2376         switch (operand_size()) {
   2377           case OPERAND_WORD_SIZE:
   2378             value = *reinterpret_cast<uint16_t*>(data + 1);
   2379             data += 3;
   2380             break;
   2381           case OPERAND_DOUBLEWORD_SIZE:
   2382             value = *reinterpret_cast<uint32_t*>(data + 1);
   2383             data += 5;
   2384             break;
   2385           case OPERAND_QUADWORD_SIZE:
   2386             value = *reinterpret_cast<int32_t*>(data + 1);
   2387             data += 5;
   2388             break;
   2389           default:
   2390             UNREACHABLE();
   2391         }
   2392         AppendToBuffer("test%c rax,0x%" PRIx64, operand_size_code(), value);
   2393         break;
   2394       }
   2395       case 0xD1:  // fall through
   2396       case 0xD3:  // fall through
   2397       case 0xC1:
   2398         data += ShiftInstruction(data);
   2399         break;
   2400       case 0xD0:  // fall through
   2401       case 0xD2:  // fall through
   2402       case 0xC0:
   2403         byte_size_operand_ = true;
   2404         data += ShiftInstruction(data);
   2405         break;
   2406 
   2407       case 0xD9:  // fall through
   2408       case 0xDA:  // fall through
   2409       case 0xDB:  // fall through
   2410       case 0xDC:  // fall through
   2411       case 0xDD:  // fall through
   2412       case 0xDE:  // fall through
   2413       case 0xDF:
   2414         data += FPUInstruction(data);
   2415         break;
   2416 
   2417       case 0xEB:
   2418         data += JumpShort(data);
   2419         break;
   2420 
   2421       case 0xF6:
   2422         byte_size_operand_ = true;  // fall through
   2423       case 0xF7:
   2424         data += F6F7Instruction(data);
   2425         break;
   2426 
   2427       case 0x3C:
   2428         AppendToBuffer("cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
   2429         data +=2;
   2430         break;
   2431 
   2432       default:
   2433         UnimplementedInstruction();
   2434         data += 1;
   2435     }
   2436   }  // !processed
   2437 
   2438   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
   2439     tmp_buffer_[tmp_buffer_pos_] = '\0';
   2440   }
   2441 
   2442   int instr_len = static_cast<int>(data - instr);
   2443   DCHECK(instr_len > 0);  // Ensure progress.
   2444 
   2445   int outp = 0;
   2446   // Instruction bytes.
   2447   for (byte* bp = instr; bp < data; bp++) {
   2448     outp += v8::internal::SNPrintF(out_buffer + outp, "%02x", *bp);
   2449   }
   2450   for (int i = 6 - instr_len; i >= 0; i--) {
   2451     outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
   2452   }
   2453 
   2454   outp += v8::internal::SNPrintF(out_buffer + outp, " %s",
   2455                                  tmp_buffer_.start());
   2456   return instr_len;
   2457 }
   2458 
   2459 
   2460 //------------------------------------------------------------------------------
   2461 
   2462 
   2463 static const char* const cpu_regs[16] = {
   2464   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
   2465   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
   2466 };
   2467 
   2468 
   2469 static const char* const byte_cpu_regs[16] = {
   2470   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
   2471   "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
   2472 };
   2473 
   2474 
   2475 static const char* const xmm_regs[16] = {
   2476   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
   2477   "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
   2478 };
   2479 
   2480 
   2481 const char* NameConverter::NameOfAddress(byte* addr) const {
   2482   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   2483   return tmp_buffer_.start();
   2484 }
   2485 
   2486 
   2487 const char* NameConverter::NameOfConstant(byte* addr) const {
   2488   return NameOfAddress(addr);
   2489 }
   2490 
   2491 
   2492 const char* NameConverter::NameOfCPURegister(int reg) const {
   2493   if (0 <= reg && reg < 16)
   2494     return cpu_regs[reg];
   2495   return "noreg";
   2496 }
   2497 
   2498 
   2499 const char* NameConverter::NameOfByteCPURegister(int reg) const {
   2500   if (0 <= reg && reg < 16)
   2501     return byte_cpu_regs[reg];
   2502   return "noreg";
   2503 }
   2504 
   2505 
   2506 const char* NameConverter::NameOfXMMRegister(int reg) const {
   2507   if (0 <= reg && reg < 16)
   2508     return xmm_regs[reg];
   2509   return "noxmmreg";
   2510 }
   2511 
   2512 
   2513 const char* NameConverter::NameInCode(byte* addr) const {
   2514   // X64 does not embed debug strings at the moment.
   2515   UNREACHABLE();
   2516   return "";
   2517 }
   2518 
   2519 
   2520 //------------------------------------------------------------------------------
   2521 
   2522 Disassembler::Disassembler(const NameConverter& converter)
   2523     : converter_(converter) { }
   2524 
   2525 Disassembler::~Disassembler() { }
   2526 
   2527 
   2528 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
   2529                                     byte* instruction) {
   2530   DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
   2531   return d.InstructionDecode(buffer, instruction);
   2532 }
   2533 
   2534 
   2535 // The X64 assembler does not use constant pools.
   2536 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
   2537   return -1;
   2538 }
   2539 
   2540 
   2541 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
   2542   NameConverter converter;
   2543   Disassembler d(converter);
   2544   for (byte* pc = begin; pc < end;) {
   2545     v8::internal::EmbeddedVector<char, 128> buffer;
   2546     buffer[0] = '\0';
   2547     byte* prev_pc = pc;
   2548     pc += d.InstructionDecode(buffer, pc);
   2549     fprintf(f, "%p", static_cast<void*>(prev_pc));
   2550     fprintf(f, "    ");
   2551 
   2552     for (byte* bp = prev_pc; bp < pc; bp++) {
   2553       fprintf(f, "%02x", *bp);
   2554     }
   2555     for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
   2556       fprintf(f, "  ");
   2557     }
   2558     fprintf(f, "  %s\n", buffer.start());
   2559   }
   2560 }
   2561 
   2562 }  // namespace disasm
   2563 
   2564 #endif  // V8_TARGET_ARCH_X64
   2565