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