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