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