LCOV - code coverage report
Current view: top level - src/x64 - disasm-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 4 1441 0.3 %
Date: 2019-03-21 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 0x57:
    1317             :         AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop),
    1318           0 :                        NameOfXMMRegister(vvvv));
    1319           0 :         current += PrintRightXMMOperand(current);
    1320           0 :         break;
    1321             :       case 0xC2: {
    1322             :         AppendToBuffer("vcmpps %s,%s,", NameOfXMMRegister(regop),
    1323           0 :                        NameOfXMMRegister(vvvv));
    1324           0 :         current += PrintRightXMMOperand(current);
    1325             :         const char* const pseudo_op[] = {"eq",  "lt",  "le",  "unord",
    1326           0 :                                          "neq", "nlt", "nle", "ord"};
    1327           0 :         AppendToBuffer(", (%s)", pseudo_op[*current]);
    1328           0 :         current += 1;
    1329             :         break;
    1330             :       }
    1331             :       default:
    1332           0 :         UnimplementedInstruction();
    1333             :     }
    1334           0 :   } else if (vex_66() && vex_0f()) {
    1335             :     int mod, regop, rm, vvvv = vex_vreg();
    1336           0 :     get_modrm(*current, &mod, &regop, &rm);
    1337           0 :     switch (opcode) {
    1338             :       case 0x10:
    1339           0 :         AppendToBuffer("vmovupd %s,", NameOfXMMRegister(regop));
    1340           0 :         current += PrintRightXMMOperand(current);
    1341           0 :         break;
    1342             :       case 0x11:
    1343           0 :         AppendToBuffer("vmovupd ");
    1344           0 :         current += PrintRightXMMOperand(current);
    1345           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1346           0 :         break;
    1347             :       case 0x28:
    1348           0 :         AppendToBuffer("vmovapd %s,", NameOfXMMRegister(regop));
    1349           0 :         current += PrintRightXMMOperand(current);
    1350           0 :         break;
    1351             :       case 0x29:
    1352           0 :         AppendToBuffer("vmovapd ");
    1353           0 :         current += PrintRightXMMOperand(current);
    1354           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1355           0 :         break;
    1356             :       case 0x2E:
    1357           0 :         AppendToBuffer("vucomisd %s,", NameOfXMMRegister(regop));
    1358           0 :         current += PrintRightXMMOperand(current);
    1359           0 :         break;
    1360             :       case 0x50:
    1361           0 :         AppendToBuffer("vmovmskpd %s,", NameOfCPURegister(regop));
    1362           0 :         current += PrintRightXMMOperand(current);
    1363           0 :         break;
    1364             :       case 0x54:
    1365             :         AppendToBuffer("vandpd %s,%s,", NameOfXMMRegister(regop),
    1366           0 :                        NameOfXMMRegister(vvvv));
    1367           0 :         current += PrintRightXMMOperand(current);
    1368           0 :         break;
    1369             :       case 0x56:
    1370             :         AppendToBuffer("vorpd %s,%s,", NameOfXMMRegister(regop),
    1371           0 :                        NameOfXMMRegister(vvvv));
    1372           0 :         current += PrintRightXMMOperand(current);
    1373           0 :         break;
    1374             :       case 0x57:
    1375             :         AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop),
    1376           0 :                        NameOfXMMRegister(vvvv));
    1377           0 :         current += PrintRightXMMOperand(current);
    1378           0 :         break;
    1379             :       case 0x6E:
    1380           0 :         AppendToBuffer("vmov%c %s,", vex_w() ? 'q' : 'd',
    1381           0 :                        NameOfXMMRegister(regop));
    1382           0 :         current += PrintRightOperand(current);
    1383           0 :         break;
    1384             :       case 0x70:
    1385           0 :         AppendToBuffer("vpshufd %s,", NameOfXMMRegister(regop));
    1386           0 :         current += PrintRightXMMOperand(current);
    1387           0 :         AppendToBuffer(",0x%x", *current++);
    1388           0 :         break;
    1389             :       case 0x71:
    1390           0 :         AppendToBuffer("vps%sw %s,", sf_str[regop / 2],
    1391           0 :                        NameOfXMMRegister(vvvv));
    1392           0 :         current += PrintRightXMMOperand(current);
    1393           0 :         AppendToBuffer(",%u", *current++);
    1394           0 :         break;
    1395             :       case 0x72:
    1396           0 :         AppendToBuffer("vps%sd %s,", sf_str[regop / 2],
    1397           0 :                        NameOfXMMRegister(vvvv));
    1398           0 :         current += PrintRightXMMOperand(current);
    1399           0 :         AppendToBuffer(",%u", *current++);
    1400           0 :         break;
    1401             :       case 0x73:
    1402           0 :         AppendToBuffer("vps%sq %s,", sf_str[regop / 2],
    1403           0 :                        NameOfXMMRegister(vvvv));
    1404           0 :         current += PrintRightXMMOperand(current);
    1405           0 :         AppendToBuffer(",%u", *current++);
    1406           0 :         break;
    1407             :       case 0x7E:
    1408           0 :         AppendToBuffer("vmov%c ", vex_w() ? 'q' : 'd');
    1409           0 :         current += PrintRightOperand(current);
    1410           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1411           0 :         break;
    1412             :       case 0xC2: {
    1413             :         AppendToBuffer("vcmppd %s,%s,", NameOfXMMRegister(regop),
    1414           0 :                        NameOfXMMRegister(vvvv));
    1415           0 :         current += PrintRightXMMOperand(current);
    1416             :         const char* const pseudo_op[] = {"eq",  "lt",  "le",  "unord",
    1417           0 :                                          "neq", "nlt", "nle", "ord"};
    1418           0 :         AppendToBuffer(", (%s)", pseudo_op[*current]);
    1419           0 :         current += 1;
    1420             :         break;
    1421             :       }
    1422             :       case 0xC4:
    1423             :         AppendToBuffer("vpinsrw %s,%s,", NameOfXMMRegister(regop),
    1424           0 :                        NameOfXMMRegister(vvvv));
    1425           0 :         current += PrintRightOperand(current);
    1426           0 :         AppendToBuffer(",0x%x", *current++);
    1427           0 :         break;
    1428             :       case 0xC5:
    1429           0 :         AppendToBuffer("vpextrw %s,", NameOfCPURegister(regop));
    1430           0 :         current += PrintRightXMMOperand(current);
    1431           0 :         AppendToBuffer(",0x%x", *current++);
    1432           0 :         break;
    1433             : #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \
    1434             :   case 0x##opcode: {                                                      \
    1435             :     AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop),  \
    1436             :                    NameOfXMMRegister(vvvv));                              \
    1437             :     current += PrintRightXMMOperand(current);                             \
    1438             :     break;                                                                \
    1439             :   }
    1440             : 
    1441           0 :         SSE2_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
    1442             : #undef DECLARE_SSE_AVX_DIS_CASE
    1443             :       default:
    1444           0 :         UnimplementedInstruction();
    1445             :     }
    1446             : 
    1447             :   } else {
    1448           0 :     UnimplementedInstruction();
    1449             :   }
    1450             : 
    1451           0 :   return static_cast<int>(current - data);
    1452             : }
    1453             : 
    1454             : // Returns number of bytes used, including *data.
    1455           0 : int DisassemblerX64::FPUInstruction(byte* data) {
    1456           0 :   byte escape_opcode = *data;
    1457             :   DCHECK_EQ(0xD8, escape_opcode & 0xF8);
    1458           0 :   byte modrm_byte = *(data+1);
    1459             : 
    1460           0 :   if (modrm_byte >= 0xC0) {
    1461           0 :     return RegisterFPUInstruction(escape_opcode, modrm_byte);
    1462             :   } else {
    1463           0 :     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
    1464             :   }
    1465             : }
    1466             : 
    1467           0 : int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
    1468             :                                            int modrm_byte,
    1469             :                                            byte* modrm_start) {
    1470             :   const char* mnem = "?";
    1471           0 :   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
    1472           0 :   switch (escape_opcode) {
    1473           0 :     case 0xD9: switch (regop) {
    1474             :         case 0: mnem = "fld_s"; break;
    1475           0 :         case 3: mnem = "fstp_s"; break;
    1476           0 :         case 7: mnem = "fstcw"; break;
    1477           0 :         default: UnimplementedInstruction();
    1478             :       }
    1479             :       break;
    1480             : 
    1481           0 :     case 0xDB: switch (regop) {
    1482             :         case 0: mnem = "fild_s"; break;
    1483           0 :         case 1: mnem = "fisttp_s"; break;
    1484           0 :         case 2: mnem = "fist_s"; break;
    1485           0 :         case 3: mnem = "fistp_s"; break;
    1486           0 :         default: UnimplementedInstruction();
    1487             :       }
    1488             :       break;
    1489             : 
    1490           0 :     case 0xDD: switch (regop) {
    1491             :         case 0: mnem = "fld_d"; break;
    1492           0 :         case 3: mnem = "fstp_d"; break;
    1493           0 :         default: UnimplementedInstruction();
    1494             :       }
    1495             :       break;
    1496             : 
    1497           0 :     case 0xDF: switch (regop) {
    1498             :         case 5: mnem = "fild_d"; break;
    1499           0 :         case 7: mnem = "fistp_d"; break;
    1500           0 :         default: UnimplementedInstruction();
    1501             :       }
    1502             :       break;
    1503             : 
    1504           0 :     default: UnimplementedInstruction();
    1505             :   }
    1506           0 :   AppendToBuffer("%s ", mnem);
    1507             :   int count = PrintRightOperand(modrm_start);
    1508           0 :   return count + 1;
    1509             : }
    1510             : 
    1511           0 : int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
    1512             :                                              byte modrm_byte) {
    1513             :   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
    1514             :   const char* mnem = "?";
    1515             : 
    1516           0 :   switch (escape_opcode) {
    1517             :     case 0xD8:
    1518           0 :       UnimplementedInstruction();
    1519           0 :       break;
    1520             : 
    1521             :     case 0xD9:
    1522           0 :       switch (modrm_byte & 0xF8) {
    1523             :         case 0xC0:
    1524             :           mnem = "fld";
    1525             :           has_register = true;
    1526             :           break;
    1527             :         case 0xC8:
    1528             :           mnem = "fxch";
    1529             :           has_register = true;
    1530           0 :           break;
    1531             :         default:
    1532           0 :           switch (modrm_byte) {
    1533             :             case 0xE0: mnem = "fchs"; break;
    1534           0 :             case 0xE1: mnem = "fabs"; break;
    1535           0 :             case 0xE3: mnem = "fninit"; break;
    1536           0 :             case 0xE4: mnem = "ftst"; break;
    1537           0 :             case 0xE8: mnem = "fld1"; break;
    1538           0 :             case 0xEB: mnem = "fldpi"; break;
    1539           0 :             case 0xED: mnem = "fldln2"; break;
    1540           0 :             case 0xEE: mnem = "fldz"; break;
    1541           0 :             case 0xF0: mnem = "f2xm1"; break;
    1542           0 :             case 0xF1: mnem = "fyl2x"; break;
    1543           0 :             case 0xF2: mnem = "fptan"; break;
    1544           0 :             case 0xF5: mnem = "fprem1"; break;
    1545           0 :             case 0xF7: mnem = "fincstp"; break;
    1546           0 :             case 0xF8: mnem = "fprem"; break;
    1547           0 :             case 0xFC: mnem = "frndint"; break;
    1548           0 :             case 0xFD: mnem = "fscale"; break;
    1549           0 :             case 0xFE: mnem = "fsin"; break;
    1550           0 :             case 0xFF: mnem = "fcos"; break;
    1551           0 :             default: UnimplementedInstruction();
    1552             :           }
    1553             :       }
    1554             :       break;
    1555             : 
    1556             :     case 0xDA:
    1557           0 :       if (modrm_byte == 0xE9) {
    1558             :         mnem = "fucompp";
    1559             :       } else {
    1560           0 :         UnimplementedInstruction();
    1561             :       }
    1562             :       break;
    1563             : 
    1564             :     case 0xDB:
    1565           0 :       if ((modrm_byte & 0xF8) == 0xE8) {
    1566             :         mnem = "fucomi";
    1567             :         has_register = true;
    1568           0 :       } else if (modrm_byte  == 0xE2) {
    1569             :         mnem = "fclex";
    1570           0 :       } else if (modrm_byte == 0xE3) {
    1571             :         mnem = "fninit";
    1572             :       } else {
    1573           0 :         UnimplementedInstruction();
    1574             :       }
    1575             :       break;
    1576             : 
    1577             :     case 0xDC:
    1578             :       has_register = true;
    1579           0 :       switch (modrm_byte & 0xF8) {
    1580             :         case 0xC0: mnem = "fadd"; break;
    1581           0 :         case 0xE8: mnem = "fsub"; break;
    1582           0 :         case 0xC8: mnem = "fmul"; break;
    1583           0 :         case 0xF8: mnem = "fdiv"; break;
    1584           0 :         default: UnimplementedInstruction();
    1585             :       }
    1586             :       break;
    1587             : 
    1588             :     case 0xDD:
    1589             :       has_register = true;
    1590           0 :       switch (modrm_byte & 0xF8) {
    1591             :         case 0xC0: mnem = "ffree"; break;
    1592           0 :         case 0xD8: mnem = "fstp"; break;
    1593           0 :         default: UnimplementedInstruction();
    1594             :       }
    1595             :       break;
    1596             : 
    1597             :     case 0xDE:
    1598           0 :       if (modrm_byte  == 0xD9) {
    1599             :         mnem = "fcompp";
    1600             :       } else {
    1601             :         has_register = true;
    1602           0 :         switch (modrm_byte & 0xF8) {
    1603             :           case 0xC0: mnem = "faddp"; break;
    1604           0 :           case 0xE8: mnem = "fsubp"; break;
    1605           0 :           case 0xC8: mnem = "fmulp"; break;
    1606           0 :           case 0xF8: mnem = "fdivp"; break;
    1607           0 :           default: UnimplementedInstruction();
    1608             :         }
    1609             :       }
    1610             :       break;
    1611             : 
    1612             :     case 0xDF:
    1613           0 :       if (modrm_byte == 0xE0) {
    1614             :         mnem = "fnstsw_ax";
    1615           0 :       } else if ((modrm_byte & 0xF8) == 0xE8) {
    1616             :         mnem = "fucomip";
    1617             :         has_register = true;
    1618             :       }
    1619             :       break;
    1620             : 
    1621           0 :     default: UnimplementedInstruction();
    1622             :   }
    1623             : 
    1624           0 :   if (has_register) {
    1625           0 :     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
    1626             :   } else {
    1627           0 :     AppendToBuffer("%s", mnem);
    1628             :   }
    1629           0 :   return 2;
    1630             : }
    1631             : 
    1632             : 
    1633             : 
    1634             : // Handle all two-byte opcodes, which start with 0x0F.
    1635             : // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
    1636             : // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
    1637           0 : int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
    1638           0 :   byte opcode = *(data + 1);
    1639           0 :   byte* current = data + 2;
    1640             :   // At return, "current" points to the start of the next instruction.
    1641           0 :   const char* mnemonic = TwoByteMnemonic(opcode);
    1642           0 :   if (operand_size_ == 0x66) {
    1643             :     // 0x66 0x0F prefix.
    1644             :     int mod, regop, rm;
    1645           0 :     if (opcode == 0x38) {
    1646           0 :       byte third_byte = *current;
    1647           0 :       current = data + 3;
    1648           0 :       get_modrm(*current, &mod, &regop, &rm);
    1649           0 :       switch (third_byte) {
    1650             : #define SSE34_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, opcode) \
    1651             :   case 0x##opcode: {                                                      \
    1652             :     AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop));        \
    1653             :     current += PrintRightXMMOperand(current);                             \
    1654             :     break;                                                                \
    1655             :   }
    1656             : 
    1657           0 :         SSSE3_INSTRUCTION_LIST(SSE34_DIS_CASE)
    1658           0 :         SSE4_INSTRUCTION_LIST(SSE34_DIS_CASE)
    1659             : #undef SSE34_DIS_CASE
    1660             :         default:
    1661           0 :           UnimplementedInstruction();
    1662             :       }
    1663           0 :     } else if (opcode == 0x3A) {
    1664           0 :       byte third_byte = *current;
    1665           0 :       current = data + 3;
    1666           0 :       if (third_byte == 0x17) {
    1667           0 :         get_modrm(*current, &mod, &regop, &rm);
    1668           0 :         AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
    1669           0 :         current += PrintRightOperand(current);
    1670           0 :         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
    1671           0 :         current += 1;
    1672           0 :       } else if (third_byte == 0x0A) {
    1673           0 :         get_modrm(*current, &mod, &regop, &rm);
    1674           0 :         AppendToBuffer("roundss %s,", NameOfXMMRegister(regop));
    1675           0 :         current += PrintRightXMMOperand(current);
    1676           0 :         AppendToBuffer(",0x%x", (*current) & 3);
    1677           0 :         current += 1;
    1678           0 :       } else if (third_byte == 0x0B) {
    1679           0 :         get_modrm(*current, &mod, &regop, &rm);
    1680             :          // roundsd xmm, xmm/m64, imm8
    1681           0 :         AppendToBuffer("roundsd %s,", NameOfXMMRegister(regop));
    1682           0 :         current += PrintRightXMMOperand(current);
    1683           0 :         AppendToBuffer(",0x%x", (*current) & 3);
    1684           0 :         current += 1;
    1685           0 :       } else if (third_byte == 0x0E) {
    1686           0 :         get_modrm(*current, &mod, &regop, &rm);
    1687           0 :         AppendToBuffer("pblendw %s,", NameOfXMMRegister(regop));
    1688           0 :         current += PrintRightXMMOperand(data);
    1689           0 :         AppendToBuffer(",0x%x", (*current) & 3);
    1690           0 :         current += 1;
    1691           0 :       } else if (third_byte == 0x0F) {
    1692           0 :         get_modrm(*data, &mod, &regop, &rm);
    1693           0 :         AppendToBuffer("palignr %s,", NameOfXMMRegister(regop));
    1694           0 :         current += PrintRightXMMOperand(data);
    1695           0 :         AppendToBuffer(",0x%x", (*current) & 3);
    1696           0 :         current += 1;
    1697           0 :       } else if (third_byte == 0x14) {
    1698           0 :         get_modrm(*current, &mod, &regop, &rm);
    1699           0 :         AppendToBuffer("pextrb ");  // reg/m32, xmm, imm8
    1700           0 :         current += PrintRightOperand(current);
    1701           0 :         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
    1702           0 :         current += 1;
    1703           0 :       } else if (third_byte == 0x15) {
    1704           0 :         get_modrm(*current, &mod, &regop, &rm);
    1705           0 :         AppendToBuffer("pextrw ");  // reg/m32, xmm, imm8
    1706           0 :         current += PrintRightOperand(current);
    1707           0 :         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 7);
    1708           0 :         current += 1;
    1709           0 :       } else if (third_byte == 0x16) {
    1710           0 :         get_modrm(*current, &mod, &regop, &rm);
    1711           0 :         AppendToBuffer("pextrd ");  // reg/m32, xmm, imm8
    1712           0 :         current += PrintRightOperand(current);
    1713           0 :         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
    1714           0 :         current += 1;
    1715           0 :       } else if (third_byte == 0x20) {
    1716           0 :         get_modrm(*current, &mod, &regop, &rm);
    1717           0 :         AppendToBuffer("pinsrd ");  // xmm, reg/m32, imm8
    1718           0 :         AppendToBuffer(" %s,", NameOfXMMRegister(regop));
    1719           0 :         current += PrintRightOperand(current);
    1720           0 :         AppendToBuffer(",%d", (*current) & 3);
    1721           0 :         current += 1;
    1722           0 :       } else if (third_byte == 0x21) {
    1723           0 :         get_modrm(*current, &mod, &regop, &rm);
    1724             :         // insertps xmm, xmm/m32, imm8
    1725           0 :         AppendToBuffer("insertps %s,", NameOfXMMRegister(regop));
    1726           0 :         current += PrintRightXMMOperand(current);
    1727           0 :         AppendToBuffer(",0x%x", (*current) & 3);
    1728           0 :         current += 1;
    1729           0 :       } else if (third_byte == 0x22) {
    1730           0 :         get_modrm(*current, &mod, &regop, &rm);
    1731           0 :         AppendToBuffer("pinsrd ");  // xmm, reg/m32, imm8
    1732           0 :         AppendToBuffer(" %s,", NameOfXMMRegister(regop));
    1733           0 :         current += PrintRightOperand(current);
    1734           0 :         AppendToBuffer(",%d", (*current) & 3);
    1735           0 :         current += 1;
    1736             :       } else {
    1737           0 :         UnimplementedInstruction();
    1738             :       }
    1739             :     } else {
    1740           0 :       get_modrm(*current, &mod, &regop, &rm);
    1741           0 :       if (opcode == 0x1F) {
    1742           0 :         current++;
    1743           0 :         if (rm == 4) {  // SIB byte present.
    1744           0 :           current++;
    1745             :         }
    1746           0 :         if (mod == 1) {  // Byte displacement.
    1747           0 :           current += 1;
    1748           0 :         } else if (mod == 2) {  // 32-bit displacement.
    1749           0 :           current += 4;
    1750             :         }  // else no immediate displacement.
    1751           0 :         AppendToBuffer("nop");
    1752           0 :       } else if (opcode == 0x10) {
    1753           0 :         AppendToBuffer("movupd %s,", NameOfXMMRegister(regop));
    1754           0 :         current += PrintRightXMMOperand(current);
    1755           0 :       } else if (opcode == 0x11) {
    1756           0 :         AppendToBuffer("movupd ");
    1757           0 :         current += PrintRightXMMOperand(current);
    1758           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1759           0 :       } else if (opcode == 0x28) {
    1760           0 :         AppendToBuffer("movapd %s,", NameOfXMMRegister(regop));
    1761           0 :         current += PrintRightXMMOperand(current);
    1762           0 :       } else if (opcode == 0x29) {
    1763           0 :         AppendToBuffer("movapd ");
    1764           0 :         current += PrintRightXMMOperand(current);
    1765           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1766           0 :       } else if (opcode == 0x6E) {
    1767           0 :         AppendToBuffer("mov%c %s,",
    1768             :                        rex_w() ? 'q' : 'd',
    1769           0 :                        NameOfXMMRegister(regop));
    1770           0 :         current += PrintRightOperand(current);
    1771           0 :       } else if (opcode == 0x6F) {
    1772             :         AppendToBuffer("movdqa %s,",
    1773           0 :                        NameOfXMMRegister(regop));
    1774           0 :         current += PrintRightXMMOperand(current);
    1775           0 :       } else if (opcode == 0x7E) {
    1776           0 :         AppendToBuffer("mov%c ",
    1777           0 :                        rex_w() ? 'q' : 'd');
    1778           0 :         current += PrintRightOperand(current);
    1779           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1780           0 :       } else if (opcode == 0x7F) {
    1781           0 :         AppendToBuffer("movdqa ");
    1782           0 :         current += PrintRightXMMOperand(current);
    1783           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1784           0 :       } else if (opcode == 0xD6) {
    1785           0 :         AppendToBuffer("movq ");
    1786           0 :         current += PrintRightXMMOperand(current);
    1787           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1788           0 :       } else if (opcode == 0x50) {
    1789           0 :         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
    1790           0 :         current += PrintRightXMMOperand(current);
    1791           0 :       } else if (opcode == 0x70) {
    1792           0 :         AppendToBuffer("pshufd %s,", NameOfXMMRegister(regop));
    1793           0 :         current += PrintRightXMMOperand(current);
    1794           0 :         AppendToBuffer(",0x%x", *current);
    1795           0 :         current += 1;
    1796           0 :       } else if (opcode == 0x71) {
    1797             :         current += 1;
    1798           0 :         AppendToBuffer("ps%sw %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
    1799           0 :                        *current & 0x7F);
    1800           0 :         current += 1;
    1801           0 :       } else if (opcode == 0x72) {
    1802             :         current += 1;
    1803           0 :         AppendToBuffer("ps%sd %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
    1804           0 :                        *current & 0x7F);
    1805           0 :         current += 1;
    1806           0 :       } else if (opcode == 0x73) {
    1807             :         current += 1;
    1808           0 :         AppendToBuffer("ps%sq %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
    1809           0 :                        *current & 0x7F);
    1810           0 :         current += 1;
    1811           0 :       } else if (opcode == 0xB1) {
    1812           0 :         current += PrintOperands("cmpxchg", OPER_REG_OP_ORDER, current);
    1813           0 :       } else if (opcode == 0xC4) {
    1814           0 :         AppendToBuffer("pinsrw %s,", NameOfXMMRegister(regop));
    1815           0 :         current += PrintRightOperand(current);
    1816           0 :         AppendToBuffer(",0x%x", (*current) & 7);
    1817           0 :         current += 1;
    1818             :       } else {
    1819             :         const char* mnemonic;
    1820           0 :         if (opcode == 0x54) {
    1821             :           mnemonic = "andpd";
    1822           0 :         } else  if (opcode == 0x56) {
    1823             :           mnemonic = "orpd";
    1824           0 :         } else  if (opcode == 0x57) {
    1825             :           mnemonic = "xorpd";
    1826           0 :         } else if (opcode == 0x5B) {
    1827             :           mnemonic = "cvtps2dq";
    1828           0 :         } else if (opcode == 0x60) {
    1829             :           mnemonic = "punpcklbw";
    1830           0 :         } else if (opcode == 0x61) {
    1831             :           mnemonic = "punpcklwd";
    1832           0 :         } else if (opcode == 0x62) {
    1833             :           mnemonic = "punpckldq";
    1834           0 :         } else if (opcode == 0x63) {
    1835             :           mnemonic = "packsswb";
    1836           0 :         } else if (opcode == 0x64) {
    1837             :           mnemonic = "pcmpgtb";
    1838           0 :         } else if (opcode == 0x65) {
    1839             :           mnemonic = "pcmpgtw";
    1840           0 :         } else if (opcode == 0x66) {
    1841             :           mnemonic = "pcmpgtd";
    1842           0 :         } else if (opcode == 0x67) {
    1843             :           mnemonic = "packuswb";
    1844           0 :         } else if (opcode == 0x68) {
    1845             :           mnemonic = "punpckhbw";
    1846           0 :         } else if (opcode == 0x69) {
    1847             :           mnemonic = "punpckhwd";
    1848           0 :         } else if (opcode == 0x6A) {
    1849             :           mnemonic = "punpckhdq";
    1850           0 :         } else if (opcode == 0x6B) {
    1851             :           mnemonic = "packssdw";
    1852           0 :         } else if (opcode == 0x6C) {
    1853             :           mnemonic = "punpcklqdq";
    1854           0 :         } else if (opcode == 0x6D) {
    1855             :           mnemonic = "punpckhqdq";
    1856           0 :         } else if (opcode == 0x2E) {
    1857             :           mnemonic = "ucomisd";
    1858           0 :         } else if (opcode == 0x2F) {
    1859             :           mnemonic = "comisd";
    1860           0 :         } else if (opcode == 0x74) {
    1861             :           mnemonic = "pcmpeqb";
    1862           0 :         } else if (opcode == 0x75) {
    1863             :           mnemonic = "pcmpeqw";
    1864           0 :         } else if (opcode == 0x76) {
    1865             :           mnemonic = "pcmpeqd";
    1866           0 :         } else if (opcode == 0xD1) {
    1867             :           mnemonic = "psrlw";
    1868           0 :         } else if (opcode == 0xD2) {
    1869             :           mnemonic = "psrld";
    1870           0 :         } else if (opcode == 0xD5) {
    1871             :           mnemonic = "pmullw";
    1872           0 :         } else if (opcode == 0xD7) {
    1873             :           mnemonic = "pmovmskb";
    1874           0 :         } else if (opcode == 0xD8) {
    1875             :           mnemonic = "psubusb";
    1876           0 :         } else if (opcode == 0xD9) {
    1877             :           mnemonic = "psubusw";
    1878           0 :         } else if (opcode == 0xDA) {
    1879             :           mnemonic = "pand";
    1880           0 :         } else if (opcode == 0xDB) {
    1881             :           mnemonic = "pminub";
    1882           0 :         } else if (opcode == 0xDC) {
    1883             :           mnemonic = "paddusb";
    1884           0 :         } else if (opcode == 0xDD) {
    1885             :           mnemonic = "paddusw";
    1886           0 :         } else if (opcode == 0xDE) {
    1887             :           mnemonic = "pmaxub";
    1888           0 :         } else if (opcode == 0xE1) {
    1889             :           mnemonic = "psraw";
    1890           0 :         } else if (opcode == 0xE2) {
    1891             :           mnemonic = "psrad";
    1892           0 :         } else if (opcode == 0xE8) {
    1893             :           mnemonic = "psubsb";
    1894           0 :         } else if (opcode == 0xE9) {
    1895             :           mnemonic = "psubsw";
    1896           0 :         } else if (opcode == 0xEA) {
    1897             :           mnemonic = "pminsw";
    1898           0 :         } else if (opcode == 0xEB) {
    1899             :           mnemonic = "por";
    1900           0 :         } else if (opcode == 0xEC) {
    1901             :           mnemonic = "paddsb";
    1902           0 :         } else if (opcode == 0xED) {
    1903             :           mnemonic = "paddsw";
    1904           0 :         } else if (opcode == 0xEE) {
    1905             :           mnemonic = "pmaxsw";
    1906           0 :         } else if (opcode == 0xEF) {
    1907             :           mnemonic = "pxor";
    1908           0 :         } else if (opcode == 0xF1) {
    1909             :           mnemonic = "psllw";
    1910           0 :         } else if (opcode == 0xF2) {
    1911             :           mnemonic = "pslld";
    1912           0 :         } else if (opcode == 0xF4) {
    1913             :           mnemonic = "pmuludq";
    1914           0 :         } else if (opcode == 0xF8) {
    1915             :           mnemonic = "psubb";
    1916           0 :         } else if (opcode == 0xF9) {
    1917             :           mnemonic = "psubw";
    1918           0 :         } else if (opcode == 0xFA) {
    1919             :           mnemonic = "psubd";
    1920           0 :         } else if (opcode == 0xFC) {
    1921             :           mnemonic = "paddb";
    1922           0 :         } else if (opcode == 0xFD) {
    1923             :           mnemonic = "paddw";
    1924           0 :         } else if (opcode == 0xFE) {
    1925             :           mnemonic = "paddd";
    1926           0 :         } else if (opcode == 0xC2) {
    1927             :           mnemonic = "cmppd";
    1928             :         } else {
    1929           0 :           UnimplementedInstruction();
    1930             :         }
    1931           0 :         AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
    1932           0 :         current += PrintRightXMMOperand(current);
    1933           0 :         if (opcode == 0xC2) {
    1934             :           const char* const pseudo_op[] = {"eq",  "lt",  "le",  "unord",
    1935           0 :                                            "neq", "nlt", "nle", "ord"};
    1936           0 :           AppendToBuffer(", (%s)", pseudo_op[*current]);
    1937           0 :           current += 1;
    1938             :         }
    1939             :       }
    1940             :     }
    1941           0 :   } else if (group_1_prefix_ == 0xF2) {
    1942             :     // Beginning of instructions with prefix 0xF2.
    1943             : 
    1944           0 :     if (opcode == 0x11 || opcode == 0x10) {
    1945             :       // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
    1946           0 :       AppendToBuffer("movsd ");
    1947             :       int mod, regop, rm;
    1948           0 :       get_modrm(*current, &mod, &regop, &rm);
    1949           0 :       if (opcode == 0x11) {
    1950           0 :         current += PrintRightXMMOperand(current);
    1951           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    1952             :       } else {
    1953           0 :         AppendToBuffer("%s,", NameOfXMMRegister(regop));
    1954           0 :         current += PrintRightXMMOperand(current);
    1955             :       }
    1956           0 :     } else if (opcode == 0x2A) {
    1957             :       // CVTSI2SD: integer to XMM double conversion.
    1958             :       int mod, regop, rm;
    1959           0 :       get_modrm(*current, &mod, &regop, &rm);
    1960           0 :       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
    1961           0 :       current += PrintRightOperand(current);
    1962           0 :     } else if (opcode == 0x2C) {
    1963             :       // CVTTSD2SI:
    1964             :       // Convert with truncation scalar double-precision FP to integer.
    1965             :       int mod, regop, rm;
    1966           0 :       get_modrm(*current, &mod, &regop, &rm);
    1967           0 :       AppendToBuffer("cvttsd2si%c %s,",
    1968           0 :           operand_size_code(), NameOfCPURegister(regop));
    1969           0 :       current += PrintRightXMMOperand(current);
    1970           0 :     } else if (opcode == 0x2D) {
    1971             :       // CVTSD2SI: Convert scalar double-precision FP to integer.
    1972             :       int mod, regop, rm;
    1973           0 :       get_modrm(*current, &mod, &regop, &rm);
    1974           0 :       AppendToBuffer("cvtsd2si%c %s,",
    1975           0 :           operand_size_code(), NameOfCPURegister(regop));
    1976           0 :       current += PrintRightXMMOperand(current);
    1977           0 :     } else if (opcode == 0x5B) {
    1978             :       // CVTTPS2DQ: Convert packed single-precision FP values to packed signed
    1979             :       // doubleword integer values
    1980             :       int mod, regop, rm;
    1981           0 :       get_modrm(*current, &mod, &regop, &rm);
    1982           0 :       AppendToBuffer("cvttps2dq%c %s,", operand_size_code(),
    1983           0 :                      NameOfCPURegister(regop));
    1984           0 :       current += PrintRightXMMOperand(current);
    1985           0 :     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
    1986             :       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
    1987             :       int mod, regop, rm;
    1988           0 :       get_modrm(*current, &mod, &regop, &rm);
    1989           0 :       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
    1990           0 :       current += PrintRightXMMOperand(current);
    1991           0 :     } else if (opcode == 0x70) {
    1992             :       int mod, regop, rm;
    1993           0 :       get_modrm(*current, &mod, &regop, &rm);
    1994           0 :       AppendToBuffer("pshuflw %s, ", NameOfXMMRegister(regop));
    1995           0 :       current += PrintRightXMMOperand(current);
    1996           0 :       AppendToBuffer(", %d", (*current) & 7);
    1997           0 :       current += 1;
    1998           0 :     } else if (opcode == 0xC2) {
    1999             :       // Intel manual 2A, Table 3-18.
    2000             :       int mod, regop, rm;
    2001           0 :       get_modrm(*current, &mod, &regop, &rm);
    2002             :       const char* const pseudo_op[] = {
    2003             :         "cmpeqsd",
    2004             :         "cmpltsd",
    2005             :         "cmplesd",
    2006             :         "cmpunordsd",
    2007             :         "cmpneqsd",
    2008             :         "cmpnltsd",
    2009             :         "cmpnlesd",
    2010             :         "cmpordsd"
    2011           0 :       };
    2012           0 :       AppendToBuffer("%s %s,%s",
    2013           0 :                      pseudo_op[current[1]],
    2014             :                      NameOfXMMRegister(regop),
    2015           0 :                      NameOfXMMRegister(rm));
    2016           0 :       current += 2;
    2017           0 :     } else if (opcode == 0xF0) {
    2018             :       int mod, regop, rm;
    2019           0 :       get_modrm(*current, &mod, &regop, &rm);
    2020           0 :       AppendToBuffer("lddqu %s,", NameOfXMMRegister(regop));
    2021           0 :       current += PrintRightOperand(current);
    2022           0 :     } else if (opcode == 0x7C) {
    2023             :       int mod, regop, rm;
    2024           0 :       get_modrm(*current, &mod, &regop, &rm);
    2025           0 :       AppendToBuffer("haddps %s,", NameOfXMMRegister(regop));
    2026           0 :       current += PrintRightXMMOperand(current);
    2027             :     } else {
    2028           0 :       UnimplementedInstruction();
    2029             :     }
    2030           0 :   } else if (group_1_prefix_ == 0xF3) {
    2031             :     // Instructions with prefix 0xF3.
    2032           0 :     if (opcode == 0x11 || opcode == 0x10) {
    2033             :       // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
    2034           0 :       AppendToBuffer("movss ");
    2035             :       int mod, regop, rm;
    2036           0 :       get_modrm(*current, &mod, &regop, &rm);
    2037           0 :       if (opcode == 0x11) {
    2038           0 :         current += PrintRightOperand(current);
    2039           0 :         AppendToBuffer(",%s", NameOfXMMRegister(regop));
    2040             :       } else {
    2041           0 :         AppendToBuffer("%s,", NameOfXMMRegister(regop));
    2042           0 :         current += PrintRightOperand(current);
    2043             :       }
    2044           0 :     } else if (opcode == 0x2A) {
    2045             :       // CVTSI2SS: integer to XMM single conversion.
    2046             :       int mod, regop, rm;
    2047           0 :       get_modrm(*current, &mod, &regop, &rm);
    2048           0 :       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
    2049           0 :       current += PrintRightOperand(current);
    2050           0 :     } else if (opcode == 0x2C) {
    2051             :       // CVTTSS2SI:
    2052             :       // Convert with truncation scalar single-precision FP to dword integer.
    2053             :       int mod, regop, rm;
    2054           0 :       get_modrm(*current, &mod, &regop, &rm);
    2055           0 :       AppendToBuffer("cvttss2si%c %s,",
    2056           0 :           operand_size_code(), NameOfCPURegister(regop));
    2057           0 :       current += PrintRightXMMOperand(current);
    2058           0 :     } else if (opcode == 0x70) {
    2059             :       int mod, regop, rm;
    2060           0 :       get_modrm(*current, &mod, &regop, &rm);
    2061           0 :       AppendToBuffer("pshufhw %s, ", NameOfXMMRegister(regop));
    2062           0 :       current += PrintRightXMMOperand(current);
    2063           0 :       AppendToBuffer(", %d", (*current) & 7);
    2064           0 :       current += 1;
    2065           0 :     } else if (opcode == 0x6F) {
    2066             :       int mod, regop, rm;
    2067           0 :       get_modrm(*current, &mod, &regop, &rm);
    2068           0 :       AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
    2069           0 :       current += PrintRightXMMOperand(current);
    2070           0 :     } else if (opcode == 0x7E) {
    2071             :       int mod, regop, rm;
    2072           0 :       get_modrm(*current, &mod, &regop, &rm);
    2073           0 :       AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
    2074           0 :       current += PrintRightXMMOperand(current);
    2075           0 :     } else if (opcode == 0x7F) {
    2076             :       int mod, regop, rm;
    2077           0 :       get_modrm(*current, &mod, &regop, &rm);
    2078           0 :       AppendToBuffer("movdqu ");
    2079           0 :       current += PrintRightXMMOperand(current);
    2080           0 :       AppendToBuffer(",%s", NameOfXMMRegister(regop));
    2081           0 :     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
    2082             :       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
    2083             :       int mod, regop, rm;
    2084           0 :       get_modrm(*current, &mod, &regop, &rm);
    2085           0 :       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
    2086           0 :       current += PrintRightXMMOperand(current);
    2087           0 :     } else if (opcode == 0xB8) {
    2088             :       int mod, regop, rm;
    2089           0 :       get_modrm(*current, &mod, &regop, &rm);
    2090           0 :       AppendToBuffer("popcnt%c %s,", operand_size_code(),
    2091           0 :                      NameOfCPURegister(regop));
    2092           0 :       current += PrintRightOperand(current);
    2093           0 :     } else if (opcode == 0xBC) {
    2094             :       int mod, regop, rm;
    2095           0 :       get_modrm(*current, &mod, &regop, &rm);
    2096           0 :       AppendToBuffer("tzcnt%c %s,", operand_size_code(),
    2097           0 :                      NameOfCPURegister(regop));
    2098           0 :       current += PrintRightOperand(current);
    2099           0 :     } else if (opcode == 0xBD) {
    2100             :       int mod, regop, rm;
    2101           0 :       get_modrm(*current, &mod, &regop, &rm);
    2102           0 :       AppendToBuffer("lzcnt%c %s,", operand_size_code(),
    2103           0 :                      NameOfCPURegister(regop));
    2104           0 :       current += PrintRightOperand(current);
    2105           0 :     } else if (opcode == 0xC2) {
    2106             :       // Intel manual 2A, Table 3-18.
    2107             :       int mod, regop, rm;
    2108           0 :       get_modrm(*current, &mod, &regop, &rm);
    2109             :       const char* const pseudo_op[] = {"cmpeqss",    "cmpltss",  "cmpless",
    2110             :                                        "cmpunordss", "cmpneqss", "cmpnltss",
    2111           0 :                                        "cmpnless",   "cmpordss"};
    2112           0 :       AppendToBuffer("%s %s,%s", pseudo_op[current[1]],
    2113           0 :                      NameOfXMMRegister(regop), NameOfXMMRegister(rm));
    2114           0 :       current += 2;
    2115             :     } else {
    2116           0 :       UnimplementedInstruction();
    2117             :     }
    2118           0 :   } else if (opcode == 0x10 || opcode == 0x11) {
    2119             :     // movups xmm, xmm/m128
    2120             :     // movups xmm/m128, xmm
    2121             :     int mod, regop, rm;
    2122           0 :     get_modrm(*current, &mod, &regop, &rm);
    2123           0 :     AppendToBuffer("movups ");
    2124           0 :     if (opcode == 0x11) {
    2125           0 :       current += PrintRightXMMOperand(current);
    2126           0 :       AppendToBuffer(",%s", NameOfXMMRegister(regop));
    2127             :     } else {
    2128           0 :       AppendToBuffer("%s,", NameOfXMMRegister(regop));
    2129           0 :       current += PrintRightXMMOperand(current);
    2130             :     }
    2131           0 :   } else if (opcode == 0x1F) {
    2132             :     // NOP
    2133             :     int mod, regop, rm;
    2134           0 :     get_modrm(*current, &mod, &regop, &rm);
    2135           0 :     current++;
    2136           0 :     if (rm == 4) {  // SIB byte present.
    2137           0 :       current++;
    2138             :     }
    2139           0 :     if (mod == 1) {  // Byte displacement.
    2140           0 :       current += 1;
    2141           0 :     } else if (mod == 2) {  // 32-bit displacement.
    2142           0 :       current += 4;
    2143             :     }  // else no immediate displacement.
    2144           0 :     AppendToBuffer("nop");
    2145             : 
    2146           0 :   } else if (opcode == 0x28) {
    2147             :     // movaps xmm, xmm/m128
    2148             :     int mod, regop, rm;
    2149           0 :     get_modrm(*current, &mod, &regop, &rm);
    2150           0 :     AppendToBuffer("movaps %s,", NameOfXMMRegister(regop));
    2151           0 :     current += PrintRightXMMOperand(current);
    2152             : 
    2153           0 :   } else if (opcode == 0x29) {
    2154             :     // movaps xmm/m128, xmm
    2155             :     int mod, regop, rm;
    2156           0 :     get_modrm(*current, &mod, &regop, &rm);
    2157           0 :     AppendToBuffer("movaps ");
    2158           0 :     current += PrintRightXMMOperand(current);
    2159           0 :     AppendToBuffer(",%s", NameOfXMMRegister(regop));
    2160             : 
    2161           0 :   } else if (opcode == 0x2E) {
    2162             :     int mod, regop, rm;
    2163           0 :     get_modrm(*current, &mod, &regop, &rm);
    2164           0 :     AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
    2165           0 :     current += PrintRightXMMOperand(current);
    2166           0 :   } else if (opcode == 0xA2) {
    2167             :     // CPUID
    2168           0 :     AppendToBuffer("%s", mnemonic);
    2169           0 :   } else if ((opcode & 0xF0) == 0x40) {
    2170             :     // CMOVcc: conditional move.
    2171           0 :     int condition = opcode & 0x0F;
    2172             :     const InstructionDesc& idesc = cmov_instructions[condition];
    2173           0 :     byte_size_operand_ = idesc.byte_size_operation;
    2174           0 :     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
    2175             : 
    2176           0 :   } else if (opcode >= 0x51 && opcode <= 0x5F) {
    2177             :     const char* const pseudo_op[] = {
    2178             :         "sqrtps",   "rsqrtps", "rcpps", "andps", "andnps",
    2179             :         "orps",     "xorps",   "addps", "mulps", "cvtps2pd",
    2180             :         "cvtdq2ps", "subps",   "minps", "divps", "maxps",
    2181           0 :     };
    2182             :     int mod, regop, rm;
    2183           0 :     get_modrm(*current, &mod, &regop, &rm);
    2184           0 :     AppendToBuffer("%s %s,", pseudo_op[opcode - 0x51],
    2185           0 :                    NameOfXMMRegister(regop));
    2186           0 :     current += PrintRightXMMOperand(current);
    2187             : 
    2188           0 :   } else if (opcode == 0xC2) {
    2189             :     // cmpps xmm, xmm/m128, imm8
    2190             :     int mod, regop, rm;
    2191           0 :     get_modrm(*current, &mod, &regop, &rm);
    2192             :     const char* const pseudo_op[] = {"eq",  "lt",  "le",  "unord",
    2193           0 :                                      "neq", "nlt", "nle", "ord"};
    2194           0 :     AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop));
    2195           0 :     current += PrintRightXMMOperand(current);
    2196           0 :     AppendToBuffer(", %s", pseudo_op[*current]);
    2197           0 :     current += 1;
    2198           0 :   } else if (opcode == 0xC6) {
    2199             :     // shufps xmm, xmm/m128, imm8
    2200             :     int mod, regop, rm;
    2201           0 :     get_modrm(*current, &mod, &regop, &rm);
    2202           0 :     AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
    2203           0 :     current += PrintRightXMMOperand(current);
    2204           0 :     AppendToBuffer(", %d", (*current) & 3);
    2205           0 :     current += 1;
    2206           0 :   } else if (opcode >= 0xC8 && opcode <= 0xCF) {
    2207             :     // bswap
    2208           0 :     int reg = (opcode - 0xC8) | (rex_r() ? 8 : 0);
    2209           0 :     AppendToBuffer("bswap%c %s", operand_size_code(), NameOfCPURegister(reg));
    2210           0 :   } else if (opcode == 0x50) {
    2211             :     // movmskps reg, xmm
    2212             :     int mod, regop, rm;
    2213           0 :     get_modrm(*current, &mod, &regop, &rm);
    2214           0 :     AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
    2215           0 :     current += PrintRightXMMOperand(current);
    2216           0 :   } else if (opcode == 0x70) {
    2217             :     int mod, regop, rm;
    2218           0 :     get_modrm(*current, &mod, &regop, &rm);
    2219           0 :     AppendToBuffer("pshufw %s, ", NameOfXMMRegister(regop));
    2220           0 :     current += PrintRightXMMOperand(current);
    2221           0 :     AppendToBuffer(", %d", (*current) & 3);
    2222           0 :     current += 1;
    2223           0 :   } else if ((opcode & 0xF0) == 0x80) {
    2224             :     // Jcc: Conditional jump (branch).
    2225           0 :     current = data + JumpConditional(data);
    2226             : 
    2227           0 :   } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
    2228           0 :              opcode == 0xB7 || opcode == 0xAF) {
    2229             :     // Size-extending moves, IMUL.
    2230           0 :     current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
    2231           0 :   } else if ((opcode & 0xF0) == 0x90) {
    2232             :     // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
    2233           0 :     current = data + SetCC(data);
    2234           0 :   } else if (opcode == 0xA3 || opcode == 0xA5 || opcode == 0xAB ||
    2235           0 :              opcode == 0xAD) {
    2236             :     // BT (bit test), SHLD, BTS (bit test and set),
    2237             :     // SHRD (double-precision shift)
    2238           0 :     AppendToBuffer("%s ", mnemonic);
    2239             :     int mod, regop, rm;
    2240           0 :     get_modrm(*current, &mod, &regop, &rm);
    2241           0 :     current += PrintRightOperand(current);
    2242           0 :     if (opcode == 0xAB) {
    2243           0 :       AppendToBuffer(",%s", NameOfCPURegister(regop));
    2244             :     } else {
    2245           0 :       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
    2246             :     }
    2247           0 :   } else if (opcode == 0xBA) {
    2248             :     // BTS / BTR (bit test and set/reset) with immediate
    2249             :     int mod, regop, rm;
    2250           0 :     get_modrm(*current, &mod, &regop, &rm);
    2251           0 :     mnemonic = regop == 5 ? "bts" : regop == 6 ? "btr" : "?";
    2252           0 :     AppendToBuffer("%s ", mnemonic);
    2253           0 :     current += PrintRightOperand(current);
    2254           0 :     AppendToBuffer(",%d", *current++);
    2255           0 :   } else if (opcode == 0xB8 || opcode == 0xBC || opcode == 0xBD) {
    2256             :     // POPCNT, CTZ, CLZ.
    2257           0 :     AppendToBuffer("%s%c ", mnemonic, operand_size_code());
    2258             :     int mod, regop, rm;
    2259           0 :     get_modrm(*current, &mod, &regop, &rm);
    2260           0 :     AppendToBuffer("%s,", NameOfCPURegister(regop));
    2261           0 :     current += PrintRightOperand(current);
    2262           0 :   } else if (opcode == 0x0B) {
    2263           0 :     AppendToBuffer("ud2");
    2264           0 :   } else if (opcode == 0xB0 || opcode == 0xB1) {
    2265             :     // CMPXCHG.
    2266           0 :     if (opcode == 0xB0) {
    2267           0 :       byte_size_operand_ = true;
    2268             :     }
    2269           0 :     current += PrintOperands(mnemonic, OPER_REG_OP_ORDER, current);
    2270           0 :   } else if (opcode == 0xAE && (*(data + 2) & 0xF8) == 0xE8) {
    2271           0 :     AppendToBuffer("lfence");
    2272           0 :     current = data + 3;
    2273             :   } else {
    2274           0 :     UnimplementedInstruction();
    2275             :   }
    2276           0 :   return static_cast<int>(current - data);
    2277             : }
    2278             : 
    2279             : // Mnemonics for two-byte opcode instructions starting with 0x0F.
    2280             : // The argument is the second byte of the two-byte opcode.
    2281             : // Returns nullptr if the instruction is not handled here.
    2282           0 : const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
    2283           0 :   if (opcode >= 0xC8 && opcode <= 0xCF) return "bswap";
    2284           0 :   switch (opcode) {
    2285             :     case 0x1F:
    2286             :       return "nop";
    2287             :     case 0x2A:  // F2/F3 prefix.
    2288           0 :       return (group_1_prefix_ == 0xF2) ? "cvtsi2sd" : "cvtsi2ss";
    2289             :     case 0x51:  // F2/F3 prefix.
    2290           0 :       return (group_1_prefix_ == 0xF2) ? "sqrtsd" : "sqrtss";
    2291             :     case 0x58:  // F2/F3 prefix.
    2292           0 :       return (group_1_prefix_ == 0xF2) ? "addsd" : "addss";
    2293             :     case 0x59:  // F2/F3 prefix.
    2294           0 :       return (group_1_prefix_ == 0xF2) ? "mulsd" : "mulss";
    2295             :     case 0x5A:  // F2/F3 prefix.
    2296           0 :       return (group_1_prefix_ == 0xF2) ? "cvtsd2ss" : "cvtss2sd";
    2297             :     case 0x5D:  // F2/F3 prefix.
    2298           0 :       return (group_1_prefix_ == 0xF2) ? "minsd" : "minss";
    2299             :     case 0x5C:  // F2/F3 prefix.
    2300           0 :       return (group_1_prefix_ == 0xF2) ? "subsd" : "subss";
    2301             :     case 0x5E:  // F2/F3 prefix.
    2302           0 :       return (group_1_prefix_ == 0xF2) ? "divsd" : "divss";
    2303             :     case 0x5F:  // F2/F3 prefix.
    2304           0 :       return (group_1_prefix_ == 0xF2) ? "maxsd" : "maxss";
    2305             :     case 0xA2:
    2306           0 :       return "cpuid";
    2307             :     case 0xA3:
    2308           0 :       return "bt";
    2309             :     case 0xA5:
    2310           0 :       return "shld";
    2311             :     case 0xAB:
    2312           0 :       return "bts";
    2313             :     case 0xAD:
    2314           0 :       return "shrd";
    2315             :     case 0xAF:
    2316           0 :       return "imul";
    2317             :     case 0xB0:
    2318             :     case 0xB1:
    2319           0 :       return "cmpxchg";
    2320             :     case 0xB6:
    2321           0 :       return "movzxb";
    2322             :     case 0xB7:
    2323           0 :       return "movzxw";
    2324             :     case 0xBC:
    2325           0 :       return "bsf";
    2326             :     case 0xBD:
    2327           0 :       return "bsr";
    2328             :     case 0xBE:
    2329           0 :       return "movsxb";
    2330             :     case 0xBF:
    2331           0 :       return "movsxw";
    2332             :     default:
    2333           0 :       return nullptr;
    2334             :   }
    2335             : }
    2336             : 
    2337             : 
    2338             : // Disassembles the instruction at instr, and writes it into out_buffer.
    2339           0 : int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
    2340             :                                        byte* instr) {
    2341           0 :   tmp_buffer_pos_ = 0;  // starting to write as position 0
    2342             :   byte* data = instr;
    2343             :   bool processed = true;  // Will be set to false if the current instruction
    2344             :                           // is not in 'instructions' table.
    2345             :   byte current;
    2346             : 
    2347             :   // Scan for prefixes.
    2348           0 :   while (true) {
    2349           0 :     current = *data;
    2350           0 :     if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
    2351           0 :       operand_size_ = current;
    2352           0 :     } else if ((current & 0xF0) == 0x40) {  // REX prefix.
    2353             :       setRex(current);
    2354           0 :       if (rex_w()) AppendToBuffer("REX.W ");
    2355           0 :     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
    2356           0 :       group_1_prefix_ = current;
    2357           0 :     } else if (current == LOCK_PREFIX) {
    2358           0 :       AppendToBuffer("lock ");
    2359           0 :     } else if (current == VEX3_PREFIX) {
    2360           0 :       vex_byte0_ = current;
    2361           0 :       vex_byte1_ = *(data + 1);
    2362           0 :       vex_byte2_ = *(data + 2);
    2363           0 :       setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
    2364           0 :       data += 3;
    2365           0 :       break;  // Vex is the last prefix.
    2366           0 :     } else if (current == VEX2_PREFIX) {
    2367           0 :       vex_byte0_ = current;
    2368           0 :       vex_byte1_ = *(data + 1);
    2369           0 :       setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
    2370           0 :       data += 2;
    2371           0 :       break;  // Vex is the last prefix.
    2372             :     } else {  // Not a prefix - an opcode.
    2373             :       break;
    2374             :     }
    2375           0 :     data++;
    2376             :   }
    2377             : 
    2378             :   // Decode AVX instructions.
    2379           0 :   if (vex_byte0_ != 0) {
    2380             :     processed = true;
    2381           0 :     data += AVXInstruction(data);
    2382             :   } else {
    2383           0 :     const InstructionDesc& idesc = instruction_table_->Get(current);
    2384           0 :     byte_size_operand_ = idesc.byte_size_operation;
    2385           0 :     switch (idesc.type) {
    2386             :       case ZERO_OPERANDS_INSTR:
    2387           0 :         if (current >= 0xA4 && current <= 0xA7) {
    2388             :           // String move or compare operations.
    2389           0 :           if (group_1_prefix_ == REP_PREFIX) {
    2390             :             // REP.
    2391           0 :             AppendToBuffer("rep ");
    2392             :           }
    2393           0 :           if (rex_w()) AppendToBuffer("REX.W ");
    2394           0 :           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
    2395             :         } else {
    2396           0 :           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
    2397             :         }
    2398           0 :         data++;
    2399           0 :         break;
    2400             : 
    2401             :       case TWO_OPERANDS_INSTR:
    2402           0 :         data++;
    2403           0 :         data += PrintOperands(idesc.mnem, idesc.op_order_, data);
    2404           0 :         break;
    2405             : 
    2406             :       case JUMP_CONDITIONAL_SHORT_INSTR:
    2407           0 :         data += JumpConditionalShort(data);
    2408           0 :         break;
    2409             : 
    2410             :       case REGISTER_INSTR:
    2411           0 :         AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(),
    2412           0 :                        NameOfCPURegister(base_reg(current & 0x07)));
    2413           0 :         data++;
    2414           0 :         break;
    2415             :       case PUSHPOP_INSTR:
    2416           0 :         AppendToBuffer("%s %s", idesc.mnem,
    2417           0 :                        NameOfCPURegister(base_reg(current & 0x07)));
    2418           0 :         data++;
    2419           0 :         break;
    2420             :       case MOVE_REG_INSTR: {
    2421             :         byte* addr = nullptr;
    2422           0 :         switch (operand_size()) {
    2423             :           case OPERAND_WORD_SIZE:
    2424             :             addr =
    2425           0 :                 reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
    2426           0 :             data += 3;
    2427           0 :             break;
    2428             :           case OPERAND_DOUBLEWORD_SIZE:
    2429             :             addr =
    2430           0 :                 reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
    2431           0 :             data += 5;
    2432           0 :             break;
    2433             :           case OPERAND_QUADWORD_SIZE:
    2434             :             addr =
    2435           0 :                 reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
    2436           0 :             data += 9;
    2437           0 :             break;
    2438             :           default:
    2439           0 :             UNREACHABLE();
    2440             :         }
    2441           0 :         AppendToBuffer("mov%c %s,%s", operand_size_code(),
    2442             :                        NameOfCPURegister(base_reg(current & 0x07)),
    2443           0 :                        NameOfAddress(addr));
    2444           0 :         break;
    2445             :       }
    2446             : 
    2447             :       case CALL_JUMP_INSTR: {
    2448           0 :         byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
    2449           0 :         AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
    2450           0 :         data += 5;
    2451           0 :         break;
    2452             :       }
    2453             : 
    2454             :       case SHORT_IMMEDIATE_INSTR: {
    2455             :         int32_t imm;
    2456           0 :         if (operand_size() == OPERAND_WORD_SIZE) {
    2457           0 :           imm = *reinterpret_cast<int16_t*>(data + 1);
    2458           0 :           data += 3;
    2459             :         } else {
    2460           0 :           imm = *reinterpret_cast<int32_t*>(data + 1);
    2461           0 :           data += 5;
    2462             :         }
    2463           0 :         AppendToBuffer("%s rax,0x%x", idesc.mnem, imm);
    2464           0 :         break;
    2465             :       }
    2466             : 
    2467             :       case NO_INSTR:
    2468             :         processed = false;
    2469             :         break;
    2470             : 
    2471             :       default:
    2472           0 :         UNIMPLEMENTED();  // This type is not implemented.
    2473             :     }
    2474             :   }
    2475             : 
    2476             :   // The first byte didn't match any of the simple opcodes, so we
    2477             :   // need to do special processing on it.
    2478           0 :   if (!processed) {
    2479           0 :     switch (*data) {
    2480             :       case 0xC2:
    2481           0 :         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
    2482           0 :         data += 3;
    2483           0 :         break;
    2484             : 
    2485             :       case 0x69:  // fall through
    2486             :       case 0x6B: {
    2487             :         int count = 1;
    2488           0 :         count += PrintOperands("imul", REG_OPER_OP_ORDER, data + count);
    2489           0 :         AppendToBuffer(",0x");
    2490           0 :         if (*data == 0x69) {
    2491           0 :           count += PrintImmediate(data + count, operand_size());
    2492             :         } else {
    2493           0 :           count += PrintImmediate(data + count, OPERAND_BYTE_SIZE);
    2494             :         }
    2495           0 :         data += count;
    2496           0 :         break;
    2497             :       }
    2498             : 
    2499             :       case 0x81:  // fall through
    2500             :       case 0x83:  // 0x81 with sign extension bit set
    2501           0 :         data += PrintImmediateOp(data);
    2502           0 :         break;
    2503             : 
    2504             :       case 0x0F:
    2505           0 :         data += TwoByteOpcodeInstruction(data);
    2506           0 :         break;
    2507             : 
    2508             :       case 0x8F: {
    2509           0 :         data++;
    2510             :         int mod, regop, rm;
    2511           0 :         get_modrm(*data, &mod, &regop, &rm);
    2512           0 :         if (regop == 0) {
    2513           0 :           AppendToBuffer("pop ");
    2514           0 :           data += PrintRightOperand(data);
    2515             :         }
    2516             :       }
    2517             :         break;
    2518             : 
    2519             :       case 0xFF: {
    2520           0 :         data++;
    2521             :         int mod, regop, rm;
    2522           0 :         get_modrm(*data, &mod, &regop, &rm);
    2523             :         const char* mnem = nullptr;
    2524           0 :         switch (regop) {
    2525             :           case 0:
    2526             :             mnem = "inc";
    2527             :             break;
    2528             :           case 1:
    2529             :             mnem = "dec";
    2530           0 :             break;
    2531             :           case 2:
    2532             :             mnem = "call";
    2533           0 :             break;
    2534             :           case 4:
    2535             :             mnem = "jmp";
    2536           0 :             break;
    2537             :           case 6:
    2538             :             mnem = "push";
    2539           0 :             break;
    2540             :           default:
    2541             :             mnem = "???";
    2542             :         }
    2543           0 :         if (regop <= 1) {
    2544           0 :           AppendToBuffer("%s%c ", mnem, operand_size_code());
    2545             :         } else {
    2546           0 :           AppendToBuffer("%s ", mnem);
    2547             :         }
    2548           0 :         data += PrintRightOperand(data);
    2549             :       }
    2550           0 :         break;
    2551             : 
    2552             :       case 0xC7:  // imm32, fall through
    2553             :       case 0xC6:  // imm8
    2554             :       {
    2555             :         bool is_byte = *data == 0xC6;
    2556           0 :         data++;
    2557           0 :         if (is_byte) {
    2558           0 :           AppendToBuffer("movb ");
    2559           0 :           data += PrintRightByteOperand(data);
    2560           0 :           int32_t imm = *data;
    2561           0 :           AppendToBuffer(",0x%x", imm);
    2562           0 :           data++;
    2563             :         } else {
    2564           0 :           AppendToBuffer("mov%c ", operand_size_code());
    2565           0 :           data += PrintRightOperand(data);
    2566           0 :           if (operand_size() == OPERAND_WORD_SIZE) {
    2567           0 :             int16_t imm = *reinterpret_cast<int16_t*>(data);
    2568           0 :             AppendToBuffer(",0x%x", imm);
    2569           0 :             data += 2;
    2570             :           } else {
    2571           0 :             int32_t imm = *reinterpret_cast<int32_t*>(data);
    2572           0 :             AppendToBuffer(",0x%x", imm);
    2573           0 :             data += 4;
    2574             :           }
    2575             :         }
    2576             :       }
    2577             :         break;
    2578             : 
    2579             :       case 0x80: {
    2580           0 :         data++;
    2581           0 :         AppendToBuffer("cmpb ");
    2582           0 :         data += PrintRightByteOperand(data);
    2583           0 :         int32_t imm = *data;
    2584           0 :         AppendToBuffer(",0x%x", imm);
    2585           0 :         data++;
    2586             :       }
    2587           0 :         break;
    2588             : 
    2589             :       case 0x88:  // 8bit, fall through
    2590             :       case 0x89:  // 32bit
    2591             :       {
    2592             :         bool is_byte = *data == 0x88;
    2593             :         int mod, regop, rm;
    2594           0 :         data++;
    2595           0 :         get_modrm(*data, &mod, &regop, &rm);
    2596           0 :         if (is_byte) {
    2597           0 :           AppendToBuffer("movb ");
    2598           0 :           data += PrintRightByteOperand(data);
    2599           0 :           AppendToBuffer(",%s", NameOfByteCPURegister(regop));
    2600             :         } else {
    2601           0 :           AppendToBuffer("mov%c ", operand_size_code());
    2602           0 :           data += PrintRightOperand(data);
    2603           0 :           AppendToBuffer(",%s", NameOfCPURegister(regop));
    2604             :         }
    2605             :       }
    2606             :         break;
    2607             : 
    2608             :       case 0x90:
    2609             :       case 0x91:
    2610             :       case 0x92:
    2611             :       case 0x93:
    2612             :       case 0x94:
    2613             :       case 0x95:
    2614             :       case 0x96:
    2615             :       case 0x97: {
    2616           0 :         int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
    2617           0 :         if (group_1_prefix_ == 0xF3 && *data == 0x90) {
    2618           0 :           AppendToBuffer("pause");
    2619           0 :         } else if (reg == 0) {
    2620           0 :           AppendToBuffer("nop");  // Common name for xchg rax,rax.
    2621             :         } else {
    2622           0 :           AppendToBuffer("xchg%c rax,%s",
    2623             :                          operand_size_code(),
    2624           0 :                          NameOfCPURegister(reg));
    2625             :         }
    2626           0 :         data++;
    2627             :       }
    2628           0 :         break;
    2629             :       case 0xB0:
    2630             :       case 0xB1:
    2631             :       case 0xB2:
    2632             :       case 0xB3:
    2633             :       case 0xB4:
    2634             :       case 0xB5:
    2635             :       case 0xB6:
    2636             :       case 0xB7:
    2637             :       case 0xB8:
    2638             :       case 0xB9:
    2639             :       case 0xBA:
    2640             :       case 0xBB:
    2641             :       case 0xBC:
    2642             :       case 0xBD:
    2643             :       case 0xBE:
    2644             :       case 0xBF: {
    2645             :         // mov reg8,imm8 or mov reg32,imm32
    2646             :         byte opcode = *data;
    2647             :         data++;
    2648             :         bool is_32bit = (opcode >= 0xB8);
    2649           0 :         int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
    2650           0 :         if (is_32bit) {
    2651           0 :           AppendToBuffer("mov%c %s,",
    2652             :                          operand_size_code(),
    2653           0 :                          NameOfCPURegister(reg));
    2654           0 :           data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
    2655             :         } else {
    2656             :           AppendToBuffer("movb %s,",
    2657           0 :                          NameOfByteCPURegister(reg));
    2658           0 :           data += PrintImmediate(data, OPERAND_BYTE_SIZE);
    2659             :         }
    2660             :         break;
    2661             :       }
    2662             :       case 0xFE: {
    2663           0 :         data++;
    2664             :         int mod, regop, rm;
    2665           0 :         get_modrm(*data, &mod, &regop, &rm);
    2666           0 :         if (regop == 1) {
    2667           0 :           AppendToBuffer("decb ");
    2668           0 :           data += PrintRightByteOperand(data);
    2669             :         } else {
    2670           0 :           UnimplementedInstruction();
    2671             :         }
    2672             :         break;
    2673             :       }
    2674             :       case 0x68:
    2675           0 :         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
    2676           0 :         data += 5;
    2677           0 :         break;
    2678             : 
    2679             :       case 0x6A:
    2680           0 :         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
    2681           0 :         data += 2;
    2682           0 :         break;
    2683             : 
    2684             :       case 0xA1:  // Fall through.
    2685             :       case 0xA3:
    2686           0 :         switch (operand_size()) {
    2687             :           case OPERAND_DOUBLEWORD_SIZE: {
    2688           0 :             const char* memory_location = NameOfAddress(
    2689             :                 reinterpret_cast<byte*>(
    2690             :                     *reinterpret_cast<int32_t*>(data + 1)));
    2691           0 :             if (*data == 0xA1) {  // Opcode 0xA1
    2692           0 :               AppendToBuffer("movzxlq rax,(%s)", memory_location);
    2693             :             } else {  // Opcode 0xA3
    2694           0 :               AppendToBuffer("movzxlq (%s),rax", memory_location);
    2695             :             }
    2696           0 :             data += 5;
    2697           0 :             break;
    2698             :           }
    2699             :           case OPERAND_QUADWORD_SIZE: {
    2700             :             // New x64 instruction mov rax,(imm_64).
    2701           0 :             const char* memory_location = NameOfAddress(
    2702             :                 *reinterpret_cast<byte**>(data + 1));
    2703           0 :             if (*data == 0xA1) {  // Opcode 0xA1
    2704           0 :               AppendToBuffer("movq rax,(%s)", memory_location);
    2705             :             } else {  // Opcode 0xA3
    2706           0 :               AppendToBuffer("movq (%s),rax", memory_location);
    2707             :             }
    2708           0 :             data += 9;
    2709           0 :             break;
    2710             :           }
    2711             :           default:
    2712           0 :             UnimplementedInstruction();
    2713           0 :             data += 2;
    2714             :         }
    2715             :         break;
    2716             : 
    2717             :       case 0xA8:
    2718           0 :         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
    2719           0 :         data += 2;
    2720           0 :         break;
    2721             : 
    2722             :       case 0xA9: {
    2723             :         int64_t value = 0;
    2724           0 :         switch (operand_size()) {
    2725             :           case OPERAND_WORD_SIZE:
    2726           0 :             value = *reinterpret_cast<uint16_t*>(data + 1);
    2727           0 :             data += 3;
    2728           0 :             break;
    2729             :           case OPERAND_DOUBLEWORD_SIZE:
    2730           0 :             value = *reinterpret_cast<uint32_t*>(data + 1);
    2731           0 :             data += 5;
    2732           0 :             break;
    2733             :           case OPERAND_QUADWORD_SIZE:
    2734           0 :             value = *reinterpret_cast<int32_t*>(data + 1);
    2735           0 :             data += 5;
    2736           0 :             break;
    2737             :           default:
    2738           0 :             UNREACHABLE();
    2739             :         }
    2740           0 :         AppendToBuffer("test%c rax,0x%" PRIx64, operand_size_code(), value);
    2741           0 :         break;
    2742             :       }
    2743             :       case 0xD1:  // fall through
    2744             :       case 0xD3:  // fall through
    2745             :       case 0xC1:
    2746           0 :         data += ShiftInstruction(data);
    2747           0 :         break;
    2748             :       case 0xD0:  // fall through
    2749             :       case 0xD2:  // fall through
    2750             :       case 0xC0:
    2751           0 :         byte_size_operand_ = true;
    2752           0 :         data += ShiftInstruction(data);
    2753           0 :         break;
    2754             : 
    2755             :       case 0xD9:  // fall through
    2756             :       case 0xDA:  // fall through
    2757             :       case 0xDB:  // fall through
    2758             :       case 0xDC:  // fall through
    2759             :       case 0xDD:  // fall through
    2760             :       case 0xDE:  // fall through
    2761             :       case 0xDF:
    2762           0 :         data += FPUInstruction(data);
    2763           0 :         break;
    2764             : 
    2765             :       case 0xEB:
    2766           0 :         data += JumpShort(data);
    2767           0 :         break;
    2768             : 
    2769             :       case 0xF6:
    2770           0 :         byte_size_operand_ = true;
    2771             :         V8_FALLTHROUGH;
    2772             :       case 0xF7:
    2773           0 :         data += F6F7Instruction(data);
    2774           0 :         break;
    2775             : 
    2776             :       case 0x3C:
    2777           0 :         AppendToBuffer("cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
    2778           0 :         data +=2;
    2779           0 :         break;
    2780             : 
    2781             :       default:
    2782           0 :         UnimplementedInstruction();
    2783           0 :         data += 1;
    2784             :     }
    2785             :   }  // !processed
    2786             : 
    2787           0 :   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
    2788           0 :     tmp_buffer_[tmp_buffer_pos_] = '\0';
    2789             :   }
    2790             : 
    2791           0 :   int instr_len = static_cast<int>(data - instr);
    2792             :   DCHECK_GT(instr_len, 0);  // Ensure progress.
    2793             : 
    2794             :   int outp = 0;
    2795             :   // Instruction bytes.
    2796           0 :   for (byte* bp = instr; bp < data; bp++) {
    2797           0 :     outp += v8::internal::SNPrintF(out_buffer + outp, "%02x", *bp);
    2798             :   }
    2799           0 :   for (int i = 6 - instr_len; i >= 0; i--) {
    2800           0 :     outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
    2801             :   }
    2802             : 
    2803           0 :   outp += v8::internal::SNPrintF(out_buffer + outp, " %s",
    2804           0 :                                  tmp_buffer_.start());
    2805           0 :   return instr_len;
    2806             : }
    2807             : 
    2808             : 
    2809             : //------------------------------------------------------------------------------
    2810             : 
    2811             : 
    2812             : static const char* const cpu_regs[16] = {
    2813             :   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
    2814             :   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
    2815             : };
    2816             : 
    2817             : 
    2818             : static const char* const byte_cpu_regs[16] = {
    2819             :   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
    2820             :   "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
    2821             : };
    2822             : 
    2823             : 
    2824             : static const char* const xmm_regs[16] = {
    2825             :   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
    2826             :   "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
    2827             : };
    2828             : 
    2829             : 
    2830           0 : const char* NameConverter::NameOfAddress(byte* addr) const {
    2831           0 :   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
    2832           0 :   return tmp_buffer_.start();
    2833             : }
    2834             : 
    2835             : 
    2836           0 : const char* NameConverter::NameOfConstant(byte* addr) const {
    2837           0 :   return NameOfAddress(addr);
    2838             : }
    2839             : 
    2840             : 
    2841         360 : const char* NameConverter::NameOfCPURegister(int reg) const {
    2842         360 :   if (0 <= reg && reg < 16)
    2843         360 :     return cpu_regs[reg];
    2844             :   return "noreg";
    2845             : }
    2846             : 
    2847             : 
    2848           0 : const char* NameConverter::NameOfByteCPURegister(int reg) const {
    2849           0 :   if (0 <= reg && reg < 16)
    2850           0 :     return byte_cpu_regs[reg];
    2851             :   return "noreg";
    2852             : }
    2853             : 
    2854             : 
    2855           0 : const char* NameConverter::NameOfXMMRegister(int reg) const {
    2856           0 :   if (0 <= reg && reg < 16)
    2857           0 :     return xmm_regs[reg];
    2858             :   return "noxmmreg";
    2859             : }
    2860             : 
    2861             : 
    2862           0 : const char* NameConverter::NameInCode(byte* addr) const {
    2863             :   // X64 does not embed debug strings at the moment.
    2864           0 :   UNREACHABLE();
    2865             : }
    2866             : 
    2867             : 
    2868             : //------------------------------------------------------------------------------
    2869             : 
    2870           0 : int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
    2871             :                                     byte* instruction) {
    2872           0 :   DisassemblerX64 d(converter_, unimplemented_opcode_action());
    2873           0 :   return d.InstructionDecode(buffer, instruction);
    2874             : }
    2875             : 
    2876             : // The X64 assembler does not use constant pools.
    2877           0 : int Disassembler::ConstantPoolSizeAt(byte* instruction) {
    2878           0 :   return -1;
    2879             : }
    2880             : 
    2881           0 : void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
    2882             :                                UnimplementedOpcodeAction unimplemented_action) {
    2883             :   NameConverter converter;
    2884             :   Disassembler d(converter, unimplemented_action);
    2885           0 :   for (byte* pc = begin; pc < end;) {
    2886             :     v8::internal::EmbeddedVector<char, 128> buffer;
    2887           0 :     buffer[0] = '\0';
    2888             :     byte* prev_pc = pc;
    2889           0 :     pc += d.InstructionDecode(buffer, pc);
    2890             :     fprintf(f, "%p", static_cast<void*>(prev_pc));
    2891             :     fprintf(f, "    ");
    2892             : 
    2893           0 :     for (byte* bp = prev_pc; bp < pc; bp++) {
    2894           0 :       fprintf(f, "%02x", *bp);
    2895             :     }
    2896           0 :     for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
    2897             :       fprintf(f, "  ");
    2898             :     }
    2899             :     fprintf(f, "  %s\n", buffer.start());
    2900             :   }
    2901           0 : }
    2902             : 
    2903      120216 : }  // namespace disasm
    2904             : 
    2905             : #endif  // V8_TARGET_ARCH_X64

Generated by: LCOV version 1.10