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

Generated by: LCOV version 1.10