LCOV - code coverage report
Current view: top level - src/x64 - disasm-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 0 1329 0.0 %
Date: 2017-04-26 Functions: 0 46 0.0 %

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

Generated by: LCOV version 1.10