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