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