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