LCOV - code coverage report
Current view: top level - src/x64 - disasm-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 4 1444 0.3 %
Date: 2019-04-17 Functions: 2 43 4.7 %

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

Generated by: LCOV version 1.10