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();
Get(byte x) const143   const InstructionDesc& Get(byte x) const { return instructions_[x]; }
get_instance()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 
InstructionTable()162 InstructionTable::InstructionTable() {
163   Clear();
164   Init();
165 }
166 
167 
Clear()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 
Init()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 
CopyTable(const ByteMnemonic bm[],InstructionType type)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 
SetTableRange(InstructionType type,byte start,byte end,const char * mnem)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 
AddJumpConditionalShort()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:
DisassemblerIA32(const NameConverter & converter,Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action)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 
~DisassemblerIA32()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 
vex_128()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 
vex_none()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 
vex_66()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 
vex_f3()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 
vex_f2()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 
vex_w()312   bool vex_w() {
313     if (vex_byte0_ == 0xC5) return false;
314     return (vex_byte2_ & 0x80) != 0;
315   }
316 
vex_0f()317   bool vex_0f() {
318     if (vex_byte0_ == 0xC5) return true;
319     return (vex_byte1_ & 3) == 1;
320   }
321 
vex_0f38()322   bool vex_0f38() {
323     if (vex_byte0_ == 0xC5) return false;
324     return (vex_byte1_ & 3) == 2;
325   }
326 
vex_0f3a()327   bool vex_0f3a() {
328     if (vex_byte0_ == 0xC5) return false;
329     return (vex_byte1_ & 3) == 3;
330   }
331 
vex_vreg()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 
float_size_code()338   char float_size_code() { return "sd"[vex_w()]; }
339 
NameOfCPURegister(int reg) const340   const char* NameOfCPURegister(int reg) const {
341     return converter_.NameOfCPURegister(reg);
342   }
343 
344 
NameOfByteCPURegister(int reg) const345   const char* NameOfByteCPURegister(int reg) const {
346     return converter_.NameOfByteCPURegister(reg);
347   }
348 
349 
NameOfXMMRegister(int reg) const350   const char* NameOfXMMRegister(int reg) const {
351     return converter_.NameOfXMMRegister(reg);
352   }
353 
354 
NameOfAddress(byte * addr) const355   const char* NameOfAddress(byte* addr) const {
356     return converter_.NameOfAddress(addr);
357   }
358 
359 
360   // Disassembler helper functions.
get_modrm(byte data,int * mod,int * regop,int * rm)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 
get_sib(byte data,int * scale,int * index,int * base)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 
UnimplementedInstruction()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 
AppendToBuffer(const char * format,...)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 
PrintRightOperandHelper(byte * modrmp,RegisterNameMapping direct_register_name)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 
PrintRightOperand(byte * modrmp)503 int DisassemblerIA32::PrintRightOperand(byte* modrmp) {
504   return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
505 }
506 
507 
PrintRightByteOperand(byte * modrmp)508 int DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
509   return PrintRightOperandHelper(modrmp,
510                                  &DisassemblerIA32::NameOfByteCPURegister);
511 }
512 
513 
PrintRightXMMOperand(byte * modrmp)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_'.
PrintOperands(const char * mnem,OperandOrder op_order,byte * data)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_'.
PrintImmediateOp(byte * data)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.
F7Instruction(byte * 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 
D1D3C1Instruction(byte * data)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.
JumpShort(byte * 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.
JumpConditional(byte * data,const char * comment)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.
JumpConditionalShort(byte * data,const char * comment)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.
SetCC(byte * 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.
CMov(byte * 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 
AVXInstruction(byte * data)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.
FPUInstruction(byte * 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 
MemoryFPUInstruction(int escape_opcode,int modrm_byte,byte * modrm_start)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 
RegisterFPUInstruction(int escape_opcode,byte modrm_byte)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.
F0Mnem(byte f0byte)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'.
InstructionDecode(v8::internal::Vector<char> out_buffer,byte * instr)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 
NameOfAddress(byte * addr) const2604 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 
NameOfConstant(byte * addr) const2610 const char* NameConverter::NameOfConstant(byte* addr) const {
2611   return NameOfAddress(addr);
2612 }
2613 
2614 
NameOfCPURegister(int reg) const2615 const char* NameConverter::NameOfCPURegister(int reg) const {
2616   if (0 <= reg && reg < 8) return cpu_regs[reg];
2617   return "noreg";
2618 }
2619 
2620 
NameOfByteCPURegister(int reg) const2621 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2622   if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
2623   return "noreg";
2624 }
2625 
2626 
NameOfXMMRegister(int reg) const2627 const char* NameConverter::NameOfXMMRegister(int reg) const {
2628   if (0 <= reg && reg < 8) return xmm_regs[reg];
2629   return "noxmmreg";
2630 }
2631 
2632 
NameInCode(byte * addr) const2633 const char* NameConverter::NameInCode(byte* addr) const {
2634   // IA32 does not embed debug strings at the moment.
2635   UNREACHABLE();
2636 }
2637 
2638 
2639 //------------------------------------------------------------------------------
2640 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)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.
ConstantPoolSizeAt(byte * instruction)2648 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
2649 
2650 // static
Disassemble(FILE * f,byte * begin,byte * end,UnimplementedOpcodeAction unimplemented_action)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