• 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/lazy-instance.h"
12 #include "src/disasm.h"
13 
14 namespace disasm {
15 
16 enum OperandType {
17   UNSET_OP_ORDER = 0,
18   // Operand size decides between 16, 32 and 64 bit operands.
19   REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
20   OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
21   // Fixed 8-bit operands.
22   BYTE_SIZE_OPERAND_FLAG = 4,
23   BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
24   BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
25 };
26 
27 
28 //------------------------------------------------------------------
29 // Tables
30 //------------------------------------------------------------------
31 struct ByteMnemonic {
32   int b;  // -1 terminates, otherwise must be in range (0..255)
33   OperandType op_order_;
34   const char* mnem;
35 };
36 
37 
38 static const ByteMnemonic two_operands_instr[] = {
39   { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
40   { 0x01, OPER_REG_OP_ORDER,      "add" },
41   { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
42   { 0x03, REG_OPER_OP_ORDER,      "add" },
43   { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
44   { 0x09, OPER_REG_OP_ORDER,      "or" },
45   { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
46   { 0x0B, REG_OPER_OP_ORDER,      "or" },
47   { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
48   { 0x11, OPER_REG_OP_ORDER,      "adc" },
49   { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
50   { 0x13, REG_OPER_OP_ORDER,      "adc" },
51   { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
52   { 0x19, OPER_REG_OP_ORDER,      "sbb" },
53   { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
54   { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
55   { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
56   { 0x21, OPER_REG_OP_ORDER,      "and" },
57   { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
58   { 0x23, REG_OPER_OP_ORDER,      "and" },
59   { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
60   { 0x29, OPER_REG_OP_ORDER,      "sub" },
61   { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
62   { 0x2B, REG_OPER_OP_ORDER,      "sub" },
63   { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
64   { 0x31, OPER_REG_OP_ORDER,      "xor" },
65   { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
66   { 0x33, REG_OPER_OP_ORDER,      "xor" },
67   { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
68   { 0x39, OPER_REG_OP_ORDER,      "cmp" },
69   { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
70   { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
71   { 0x63, REG_OPER_OP_ORDER,      "movsxl" },
72   { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
73   { 0x85, REG_OPER_OP_ORDER,      "test" },
74   { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
75   { 0x87, REG_OPER_OP_ORDER,      "xchg" },
76   { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
77   { 0x89, OPER_REG_OP_ORDER,      "mov" },
78   { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
79   { 0x8B, REG_OPER_OP_ORDER,      "mov" },
80   { 0x8D, REG_OPER_OP_ORDER,      "lea" },
81   { -1, UNSET_OP_ORDER, "" }
82 };
83 
84 
85 static const ByteMnemonic zero_operands_instr[] = {
86   { 0xC3, UNSET_OP_ORDER, "ret" },
87   { 0xC9, UNSET_OP_ORDER, "leave" },
88   { 0xF4, UNSET_OP_ORDER, "hlt" },
89   { 0xFC, UNSET_OP_ORDER, "cld" },
90   { 0xCC, UNSET_OP_ORDER, "int3" },
91   { 0x60, UNSET_OP_ORDER, "pushad" },
92   { 0x61, UNSET_OP_ORDER, "popad" },
93   { 0x9C, UNSET_OP_ORDER, "pushfd" },
94   { 0x9D, UNSET_OP_ORDER, "popfd" },
95   { 0x9E, UNSET_OP_ORDER, "sahf" },
96   { 0x99, UNSET_OP_ORDER, "cdq" },
97   { 0x9B, UNSET_OP_ORDER, "fwait" },
98   { 0xA4, UNSET_OP_ORDER, "movs" },
99   { 0xA5, UNSET_OP_ORDER, "movs" },
100   { 0xA6, UNSET_OP_ORDER, "cmps" },
101   { 0xA7, UNSET_OP_ORDER, "cmps" },
102   { -1, UNSET_OP_ORDER, "" }
103 };
104 
105 
106 static const ByteMnemonic call_jump_instr[] = {
107   { 0xE8, UNSET_OP_ORDER, "call" },
108   { 0xE9, UNSET_OP_ORDER, "jmp" },
109   { -1, UNSET_OP_ORDER, "" }
110 };
111 
112 
113 static const ByteMnemonic short_immediate_instr[] = {
114   { 0x05, UNSET_OP_ORDER, "add" },
115   { 0x0D, UNSET_OP_ORDER, "or" },
116   { 0x15, UNSET_OP_ORDER, "adc" },
117   { 0x1D, UNSET_OP_ORDER, "sbb" },
118   { 0x25, UNSET_OP_ORDER, "and" },
119   { 0x2D, UNSET_OP_ORDER, "sub" },
120   { 0x35, UNSET_OP_ORDER, "xor" },
121   { 0x3D, UNSET_OP_ORDER, "cmp" },
122   { -1, UNSET_OP_ORDER, "" }
123 };
124 
125 
126 static const char* const conditional_code_suffix[] = {
127   "o", "no", "c", "nc", "z", "nz", "na", "a",
128   "s", "ns", "pe", "po", "l", "ge", "le", "g"
129 };
130 
131 
132 enum InstructionType {
133   NO_INSTR,
134   ZERO_OPERANDS_INSTR,
135   TWO_OPERANDS_INSTR,
136   JUMP_CONDITIONAL_SHORT_INSTR,
137   REGISTER_INSTR,
138   PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
139   MOVE_REG_INSTR,
140   CALL_JUMP_INSTR,
141   SHORT_IMMEDIATE_INSTR
142 };
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   REPNE_PREFIX = 0xF2,
152   REP_PREFIX = 0xF3,
153   REPEQ_PREFIX = REP_PREFIX
154 };
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) != 1;
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   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("%" V8_PTR_PREFIX "x", 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 0x0b:
960         AppendToBuffer("vroundsd %s,%s,", NameOfXMMRegister(regop),
961                        NameOfXMMRegister(vvvv));
962         current += PrintRightXMMOperand(current);
963         AppendToBuffer(",0x%x", *current++);
964         break;
965       default:
966         UnimplementedInstruction();
967     }
968   } else if (vex_f3() && vex_0f()) {
969     int mod, regop, rm, vvvv = vex_vreg();
970     get_modrm(*current, &mod, &regop, &rm);
971     switch (opcode) {
972       case 0x10:
973         AppendToBuffer("vmovss %s,", NameOfXMMRegister(regop));
974         if (mod == 3) {
975           AppendToBuffer("%s,", NameOfXMMRegister(vvvv));
976         }
977         current += PrintRightXMMOperand(current);
978         break;
979       case 0x11:
980         AppendToBuffer("vmovss ");
981         current += PrintRightXMMOperand(current);
982         if (mod == 3) {
983           AppendToBuffer(",%s", NameOfXMMRegister(vvvv));
984         }
985         AppendToBuffer(",%s", NameOfXMMRegister(regop));
986         break;
987       case 0x2a:
988         AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2ss" : "vcvtlsi2ss",
989                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
990         current += PrintRightOperand(current);
991         break;
992       case 0x2c:
993         AppendToBuffer("vcvttss2si%s %s,", vex_w() ? "q" : "",
994                        NameOfCPURegister(regop));
995         current += PrintRightXMMOperand(current);
996         break;
997       case 0x58:
998         AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop),
999                        NameOfXMMRegister(vvvv));
1000         current += PrintRightXMMOperand(current);
1001         break;
1002       case 0x59:
1003         AppendToBuffer("vmulss %s,%s,", NameOfXMMRegister(regop),
1004                        NameOfXMMRegister(vvvv));
1005         current += PrintRightXMMOperand(current);
1006         break;
1007       case 0x5a:
1008         AppendToBuffer("vcvtss2sd %s,%s,", NameOfXMMRegister(regop),
1009                        NameOfXMMRegister(vvvv));
1010         current += PrintRightXMMOperand(current);
1011         break;
1012       case 0x5c:
1013         AppendToBuffer("vsubss %s,%s,", NameOfXMMRegister(regop),
1014                        NameOfXMMRegister(vvvv));
1015         current += PrintRightXMMOperand(current);
1016         break;
1017       case 0x5d:
1018         AppendToBuffer("vminss %s,%s,", NameOfXMMRegister(regop),
1019                        NameOfXMMRegister(vvvv));
1020         current += PrintRightXMMOperand(current);
1021         break;
1022       case 0x5e:
1023         AppendToBuffer("vdivss %s,%s,", NameOfXMMRegister(regop),
1024                        NameOfXMMRegister(vvvv));
1025         current += PrintRightXMMOperand(current);
1026         break;
1027       case 0x5f:
1028         AppendToBuffer("vmaxss %s,%s,", NameOfXMMRegister(regop),
1029                        NameOfXMMRegister(vvvv));
1030         current += PrintRightXMMOperand(current);
1031         break;
1032       default:
1033         UnimplementedInstruction();
1034     }
1035   } else if (vex_f2() && vex_0f()) {
1036     int mod, regop, rm, vvvv = vex_vreg();
1037     get_modrm(*current, &mod, &regop, &rm);
1038     switch (opcode) {
1039       case 0x10:
1040         AppendToBuffer("vmovsd %s,", NameOfXMMRegister(regop));
1041         if (mod == 3) {
1042           AppendToBuffer("%s,", NameOfXMMRegister(vvvv));
1043         }
1044         current += PrintRightXMMOperand(current);
1045         break;
1046       case 0x11:
1047         AppendToBuffer("vmovsd ");
1048         current += PrintRightXMMOperand(current);
1049         if (mod == 3) {
1050           AppendToBuffer(",%s", NameOfXMMRegister(vvvv));
1051         }
1052         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1053         break;
1054       case 0x2a:
1055         AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2sd" : "vcvtlsi2sd",
1056                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
1057         current += PrintRightOperand(current);
1058         break;
1059       case 0x2c:
1060         AppendToBuffer("vcvttsd2si%s %s,", vex_w() ? "q" : "",
1061                        NameOfCPURegister(regop));
1062         current += PrintRightXMMOperand(current);
1063         break;
1064       case 0x2d:
1065         AppendToBuffer("vcvtsd2si%s %s,", vex_w() ? "q" : "",
1066                        NameOfCPURegister(regop));
1067         current += PrintRightXMMOperand(current);
1068         break;
1069       case 0x51:
1070         AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop),
1071                        NameOfXMMRegister(vvvv));
1072         current += PrintRightXMMOperand(current);
1073         break;
1074       case 0x58:
1075         AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
1076                        NameOfXMMRegister(vvvv));
1077         current += PrintRightXMMOperand(current);
1078         break;
1079       case 0x59:
1080         AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
1081                        NameOfXMMRegister(vvvv));
1082         current += PrintRightXMMOperand(current);
1083         break;
1084       case 0x5a:
1085         AppendToBuffer("vcvtsd2ss %s,%s,", NameOfXMMRegister(regop),
1086                        NameOfXMMRegister(vvvv));
1087         current += PrintRightXMMOperand(current);
1088         break;
1089       case 0x5c:
1090         AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
1091                        NameOfXMMRegister(vvvv));
1092         current += PrintRightXMMOperand(current);
1093         break;
1094       case 0x5d:
1095         AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop),
1096                        NameOfXMMRegister(vvvv));
1097         current += PrintRightXMMOperand(current);
1098         break;
1099       case 0x5e:
1100         AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
1101                        NameOfXMMRegister(vvvv));
1102         current += PrintRightXMMOperand(current);
1103         break;
1104       case 0x5f:
1105         AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop),
1106                        NameOfXMMRegister(vvvv));
1107         current += PrintRightXMMOperand(current);
1108         break;
1109       default:
1110         UnimplementedInstruction();
1111     }
1112   } else if (vex_none() && vex_0f38()) {
1113     int mod, regop, rm, vvvv = vex_vreg();
1114     get_modrm(*current, &mod, &regop, &rm);
1115     const char* mnem = "?";
1116     switch (opcode) {
1117       case 0xf2:
1118         AppendToBuffer("andn%c %s,%s,", operand_size_code(),
1119                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1120         current += PrintRightOperand(current);
1121         break;
1122       case 0xf5:
1123         AppendToBuffer("bzhi%c %s,", operand_size_code(),
1124                        NameOfCPURegister(regop));
1125         current += PrintRightOperand(current);
1126         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1127         break;
1128       case 0xf7:
1129         AppendToBuffer("bextr%c %s,", operand_size_code(),
1130                        NameOfCPURegister(regop));
1131         current += PrintRightOperand(current);
1132         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1133         break;
1134       case 0xf3:
1135         switch (regop) {
1136           case 1:
1137             mnem = "blsr";
1138             break;
1139           case 2:
1140             mnem = "blsmsk";
1141             break;
1142           case 3:
1143             mnem = "blsi";
1144             break;
1145           default:
1146             UnimplementedInstruction();
1147         }
1148         AppendToBuffer("%s%c %s,", mnem, operand_size_code(),
1149                        NameOfCPURegister(vvvv));
1150         current += PrintRightOperand(current);
1151         mnem = "?";
1152         break;
1153       default:
1154         UnimplementedInstruction();
1155     }
1156   } else if (vex_f2() && vex_0f38()) {
1157     int mod, regop, rm, vvvv = vex_vreg();
1158     get_modrm(*current, &mod, &regop, &rm);
1159     switch (opcode) {
1160       case 0xf5:
1161         AppendToBuffer("pdep%c %s,%s,", operand_size_code(),
1162                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1163         current += PrintRightOperand(current);
1164         break;
1165       case 0xf6:
1166         AppendToBuffer("mulx%c %s,%s,", operand_size_code(),
1167                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1168         current += PrintRightOperand(current);
1169         break;
1170       case 0xf7:
1171         AppendToBuffer("shrx%c %s,", operand_size_code(),
1172                        NameOfCPURegister(regop));
1173         current += PrintRightOperand(current);
1174         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1175         break;
1176       default:
1177         UnimplementedInstruction();
1178     }
1179   } else if (vex_f3() && vex_0f38()) {
1180     int mod, regop, rm, vvvv = vex_vreg();
1181     get_modrm(*current, &mod, &regop, &rm);
1182     switch (opcode) {
1183       case 0xf5:
1184         AppendToBuffer("pext%c %s,%s,", operand_size_code(),
1185                        NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1186         current += PrintRightOperand(current);
1187         break;
1188       case 0xf7:
1189         AppendToBuffer("sarx%c %s,", operand_size_code(),
1190                        NameOfCPURegister(regop));
1191         current += PrintRightOperand(current);
1192         AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1193         break;
1194       default:
1195         UnimplementedInstruction();
1196     }
1197   } else if (vex_f2() && vex_0f3a()) {
1198     int mod, regop, rm;
1199     get_modrm(*current, &mod, &regop, &rm);
1200     switch (opcode) {
1201       case 0xf0:
1202         AppendToBuffer("rorx%c %s,", operand_size_code(),
1203                        NameOfCPURegister(regop));
1204         current += PrintRightOperand(current);
1205         switch (operand_size()) {
1206           case OPERAND_DOUBLEWORD_SIZE:
1207             AppendToBuffer(",%d", *current & 0x1f);
1208             break;
1209           case OPERAND_QUADWORD_SIZE:
1210             AppendToBuffer(",%d", *current & 0x3f);
1211             break;
1212           default:
1213             UnimplementedInstruction();
1214         }
1215         current += 1;
1216         break;
1217       default:
1218         UnimplementedInstruction();
1219     }
1220   } else if (vex_none() && vex_0f()) {
1221     int mod, regop, rm, vvvv = vex_vreg();
1222     get_modrm(*current, &mod, &regop, &rm);
1223     switch (opcode) {
1224       case 0x28:
1225         AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop));
1226         current += PrintRightXMMOperand(current);
1227         break;
1228       case 0x29:
1229         AppendToBuffer("vmovaps ");
1230         current += PrintRightXMMOperand(current);
1231         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1232         break;
1233       case 0x2e:
1234         AppendToBuffer("vucomiss %s,", NameOfXMMRegister(regop));
1235         current += PrintRightXMMOperand(current);
1236         break;
1237       case 0x54:
1238         AppendToBuffer("vandps %s,%s,", NameOfXMMRegister(regop),
1239                        NameOfXMMRegister(vvvv));
1240         current += PrintRightXMMOperand(current);
1241         break;
1242       case 0x57:
1243         AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop),
1244                        NameOfXMMRegister(vvvv));
1245         current += PrintRightXMMOperand(current);
1246         break;
1247       default:
1248         UnimplementedInstruction();
1249     }
1250   } else if (vex_66() && vex_0f()) {
1251     int mod, regop, rm, vvvv = vex_vreg();
1252     get_modrm(*current, &mod, &regop, &rm);
1253     switch (opcode) {
1254       case 0x28:
1255         AppendToBuffer("vmovapd %s,", NameOfXMMRegister(regop));
1256         current += PrintRightXMMOperand(current);
1257         break;
1258       case 0x29:
1259         AppendToBuffer("vmovapd ");
1260         current += PrintRightXMMOperand(current);
1261         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1262         break;
1263       case 0x2e:
1264         AppendToBuffer("vucomisd %s,", NameOfXMMRegister(regop));
1265         current += PrintRightXMMOperand(current);
1266         break;
1267       case 0x50:
1268         AppendToBuffer("vmovmskpd %s,", NameOfCPURegister(regop));
1269         current += PrintRightXMMOperand(current);
1270         break;
1271       case 0x54:
1272         AppendToBuffer("vandpd %s,%s,", NameOfXMMRegister(regop),
1273                        NameOfXMMRegister(vvvv));
1274         current += PrintRightXMMOperand(current);
1275         break;
1276       case 0x56:
1277         AppendToBuffer("vorpd %s,%s,", NameOfXMMRegister(regop),
1278                        NameOfXMMRegister(vvvv));
1279         current += PrintRightXMMOperand(current);
1280         break;
1281       case 0x57:
1282         AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop),
1283                        NameOfXMMRegister(vvvv));
1284         current += PrintRightXMMOperand(current);
1285         break;
1286       case 0x6e:
1287         AppendToBuffer("vmov%c %s,", vex_w() ? 'q' : 'd',
1288                        NameOfXMMRegister(regop));
1289         current += PrintRightOperand(current);
1290         break;
1291       case 0x73:
1292         AppendToBuffer("%s %s,", regop == 6 ? "vpsllq" : "vpsrlq",
1293                        NameOfXMMRegister(vvvv));
1294         current += PrintRightXMMOperand(current);
1295         AppendToBuffer(",%u", *current++);
1296         break;
1297       case 0x76:
1298         AppendToBuffer("vpcmpeqd %s,%s,", NameOfXMMRegister(regop),
1299                        NameOfXMMRegister(vvvv));
1300         current += PrintRightXMMOperand(current);
1301         break;
1302       case 0x7e:
1303         AppendToBuffer("vmov%c ", vex_w() ? 'q' : 'd');
1304         current += PrintRightOperand(current);
1305         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1306         break;
1307       default:
1308         UnimplementedInstruction();
1309     }
1310 
1311   } else {
1312     UnimplementedInstruction();
1313   }
1314 
1315   return static_cast<int>(current - data);
1316 }
1317 
1318 
1319 // Returns number of bytes used, including *data.
FPUInstruction(byte * data)1320 int DisassemblerX64::FPUInstruction(byte* data) {
1321   byte escape_opcode = *data;
1322   DCHECK_EQ(0xD8, escape_opcode & 0xF8);
1323   byte modrm_byte = *(data+1);
1324 
1325   if (modrm_byte >= 0xC0) {
1326     return RegisterFPUInstruction(escape_opcode, modrm_byte);
1327   } else {
1328     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
1329   }
1330 }
1331 
MemoryFPUInstruction(int escape_opcode,int modrm_byte,byte * modrm_start)1332 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
1333                                            int modrm_byte,
1334                                            byte* modrm_start) {
1335   const char* mnem = "?";
1336   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
1337   switch (escape_opcode) {
1338     case 0xD9: switch (regop) {
1339         case 0: mnem = "fld_s"; break;
1340         case 3: mnem = "fstp_s"; break;
1341         case 7: mnem = "fstcw"; break;
1342         default: UnimplementedInstruction();
1343       }
1344       break;
1345 
1346     case 0xDB: switch (regop) {
1347         case 0: mnem = "fild_s"; break;
1348         case 1: mnem = "fisttp_s"; break;
1349         case 2: mnem = "fist_s"; break;
1350         case 3: mnem = "fistp_s"; break;
1351         default: UnimplementedInstruction();
1352       }
1353       break;
1354 
1355     case 0xDD: switch (regop) {
1356         case 0: mnem = "fld_d"; break;
1357         case 3: mnem = "fstp_d"; break;
1358         default: UnimplementedInstruction();
1359       }
1360       break;
1361 
1362     case 0xDF: switch (regop) {
1363         case 5: mnem = "fild_d"; break;
1364         case 7: mnem = "fistp_d"; break;
1365         default: UnimplementedInstruction();
1366       }
1367       break;
1368 
1369     default: UnimplementedInstruction();
1370   }
1371   AppendToBuffer("%s ", mnem);
1372   int count = PrintRightOperand(modrm_start);
1373   return count + 1;
1374 }
1375 
RegisterFPUInstruction(int escape_opcode,byte modrm_byte)1376 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
1377                                              byte modrm_byte) {
1378   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
1379   const char* mnem = "?";
1380 
1381   switch (escape_opcode) {
1382     case 0xD8:
1383       UnimplementedInstruction();
1384       break;
1385 
1386     case 0xD9:
1387       switch (modrm_byte & 0xF8) {
1388         case 0xC0:
1389           mnem = "fld";
1390           has_register = true;
1391           break;
1392         case 0xC8:
1393           mnem = "fxch";
1394           has_register = true;
1395           break;
1396         default:
1397           switch (modrm_byte) {
1398             case 0xE0: mnem = "fchs"; break;
1399             case 0xE1: mnem = "fabs"; break;
1400             case 0xE3: mnem = "fninit"; break;
1401             case 0xE4: mnem = "ftst"; break;
1402             case 0xE8: mnem = "fld1"; break;
1403             case 0xEB: mnem = "fldpi"; break;
1404             case 0xED: mnem = "fldln2"; break;
1405             case 0xEE: mnem = "fldz"; break;
1406             case 0xF0: mnem = "f2xm1"; break;
1407             case 0xF1: mnem = "fyl2x"; break;
1408             case 0xF2: mnem = "fptan"; break;
1409             case 0xF5: mnem = "fprem1"; break;
1410             case 0xF7: mnem = "fincstp"; break;
1411             case 0xF8: mnem = "fprem"; break;
1412             case 0xFC: mnem = "frndint"; break;
1413             case 0xFD: mnem = "fscale"; break;
1414             case 0xFE: mnem = "fsin"; break;
1415             case 0xFF: mnem = "fcos"; break;
1416             default: UnimplementedInstruction();
1417           }
1418       }
1419       break;
1420 
1421     case 0xDA:
1422       if (modrm_byte == 0xE9) {
1423         mnem = "fucompp";
1424       } else {
1425         UnimplementedInstruction();
1426       }
1427       break;
1428 
1429     case 0xDB:
1430       if ((modrm_byte & 0xF8) == 0xE8) {
1431         mnem = "fucomi";
1432         has_register = true;
1433       } else if (modrm_byte  == 0xE2) {
1434         mnem = "fclex";
1435       } else if (modrm_byte == 0xE3) {
1436         mnem = "fninit";
1437       } else {
1438         UnimplementedInstruction();
1439       }
1440       break;
1441 
1442     case 0xDC:
1443       has_register = true;
1444       switch (modrm_byte & 0xF8) {
1445         case 0xC0: mnem = "fadd"; break;
1446         case 0xE8: mnem = "fsub"; break;
1447         case 0xC8: mnem = "fmul"; break;
1448         case 0xF8: mnem = "fdiv"; break;
1449         default: UnimplementedInstruction();
1450       }
1451       break;
1452 
1453     case 0xDD:
1454       has_register = true;
1455       switch (modrm_byte & 0xF8) {
1456         case 0xC0: mnem = "ffree"; break;
1457         case 0xD8: mnem = "fstp"; break;
1458         default: UnimplementedInstruction();
1459       }
1460       break;
1461 
1462     case 0xDE:
1463       if (modrm_byte  == 0xD9) {
1464         mnem = "fcompp";
1465       } else {
1466         has_register = true;
1467         switch (modrm_byte & 0xF8) {
1468           case 0xC0: mnem = "faddp"; break;
1469           case 0xE8: mnem = "fsubp"; break;
1470           case 0xC8: mnem = "fmulp"; break;
1471           case 0xF8: mnem = "fdivp"; break;
1472           default: UnimplementedInstruction();
1473         }
1474       }
1475       break;
1476 
1477     case 0xDF:
1478       if (modrm_byte == 0xE0) {
1479         mnem = "fnstsw_ax";
1480       } else if ((modrm_byte & 0xF8) == 0xE8) {
1481         mnem = "fucomip";
1482         has_register = true;
1483       }
1484       break;
1485 
1486     default: UnimplementedInstruction();
1487   }
1488 
1489   if (has_register) {
1490     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
1491   } else {
1492     AppendToBuffer("%s", mnem);
1493   }
1494   return 2;
1495 }
1496 
1497 
1498 
1499 // Handle all two-byte opcodes, which start with 0x0F.
1500 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
1501 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
TwoByteOpcodeInstruction(byte * data)1502 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
1503   byte opcode = *(data + 1);
1504   byte* current = data + 2;
1505   // At return, "current" points to the start of the next instruction.
1506   const char* mnemonic = TwoByteMnemonic(opcode);
1507   if (operand_size_ == 0x66) {
1508     // 0x66 0x0F prefix.
1509     int mod, regop, rm;
1510     if (opcode == 0x3A) {
1511       byte third_byte = *current;
1512       current = data + 3;
1513       if (third_byte == 0x17) {
1514         get_modrm(*current, &mod, &regop, &rm);
1515         AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
1516         current += PrintRightOperand(current);
1517         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1518         current += 1;
1519       } else if (third_byte == 0x0b) {
1520         get_modrm(*current, &mod, &regop, &rm);
1521          // roundsd xmm, xmm/m64, imm8
1522         AppendToBuffer("roundsd %s,", NameOfXMMRegister(regop));
1523         current += PrintRightXMMOperand(current);
1524         AppendToBuffer(",0x%x", (*current) & 3);
1525         current += 1;
1526       } else if (third_byte == 0x16) {
1527         get_modrm(*current, &mod, &rm, &regop);
1528         AppendToBuffer("pextrd ");  // reg/m32, xmm, imm8
1529         current += PrintRightOperand(current);
1530         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1531         current += 1;
1532       } else if (third_byte == 0x22) {
1533         get_modrm(*current, &mod, &regop, &rm);
1534         AppendToBuffer("pinsrd ");  // xmm, reg/m32, imm8
1535         AppendToBuffer(" %s,", NameOfXMMRegister(regop));
1536         current += PrintRightOperand(current);
1537         AppendToBuffer(",%d", (*current) & 3);
1538         current += 1;
1539       } else {
1540         UnimplementedInstruction();
1541       }
1542     } else {
1543       get_modrm(*current, &mod, &regop, &rm);
1544       if (opcode == 0x1f) {
1545         current++;
1546         if (rm == 4) {  // SIB byte present.
1547           current++;
1548         }
1549         if (mod == 1) {  // Byte displacement.
1550           current += 1;
1551         } else if (mod == 2) {  // 32-bit displacement.
1552           current += 4;
1553         }  // else no immediate displacement.
1554         AppendToBuffer("nop");
1555       } else if (opcode == 0x28) {
1556         AppendToBuffer("movapd %s,", NameOfXMMRegister(regop));
1557         current += PrintRightXMMOperand(current);
1558       } else if (opcode == 0x29) {
1559         AppendToBuffer("movapd ");
1560         current += PrintRightXMMOperand(current);
1561         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1562       } else if (opcode == 0x6E) {
1563         AppendToBuffer("mov%c %s,",
1564                        rex_w() ? 'q' : 'd',
1565                        NameOfXMMRegister(regop));
1566         current += PrintRightOperand(current);
1567       } else if (opcode == 0x6F) {
1568         AppendToBuffer("movdqa %s,",
1569                        NameOfXMMRegister(regop));
1570         current += PrintRightXMMOperand(current);
1571       } else if (opcode == 0x7E) {
1572         AppendToBuffer("mov%c ",
1573                        rex_w() ? 'q' : 'd');
1574         current += PrintRightOperand(current);
1575         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1576       } else if (opcode == 0x7F) {
1577         AppendToBuffer("movdqa ");
1578         current += PrintRightXMMOperand(current);
1579         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1580       } else if (opcode == 0xD6) {
1581         AppendToBuffer("movq ");
1582         current += PrintRightXMMOperand(current);
1583         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1584       } else if (opcode == 0x50) {
1585         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
1586         current += PrintRightXMMOperand(current);
1587       } else if (opcode == 0x72) {
1588         current += 1;
1589         AppendToBuffer("%s %s,%d", (regop == 6) ? "pslld" : "psrld",
1590                        NameOfXMMRegister(rm), *current & 0x7f);
1591         current += 1;
1592       } else if (opcode == 0x73) {
1593         current += 1;
1594         AppendToBuffer("%s %s,%d", (regop == 6) ? "psllq" : "psrlq",
1595                        NameOfXMMRegister(rm), *current & 0x7f);
1596         current += 1;
1597       } else {
1598         const char* mnemonic = "?";
1599         if (opcode == 0x54) {
1600           mnemonic = "andpd";
1601         } else  if (opcode == 0x56) {
1602           mnemonic = "orpd";
1603         } else  if (opcode == 0x57) {
1604           mnemonic = "xorpd";
1605         } else if (opcode == 0x2E) {
1606           mnemonic = "ucomisd";
1607         } else if (opcode == 0x2F) {
1608           mnemonic = "comisd";
1609         } else if (opcode == 0x76) {
1610           mnemonic = "pcmpeqd";
1611         } else if (opcode == 0x62) {
1612           mnemonic = "punpckldq";
1613         } else if (opcode == 0x6A) {
1614           mnemonic = "punpckhdq";
1615         } else {
1616           UnimplementedInstruction();
1617         }
1618         AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1619         current += PrintRightXMMOperand(current);
1620       }
1621     }
1622   } else if (group_1_prefix_ == 0xF2) {
1623     // Beginning of instructions with prefix 0xF2.
1624 
1625     if (opcode == 0x11 || opcode == 0x10) {
1626       // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
1627       AppendToBuffer("movsd ");
1628       int mod, regop, rm;
1629       get_modrm(*current, &mod, &regop, &rm);
1630       if (opcode == 0x11) {
1631         current += PrintRightXMMOperand(current);
1632         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1633       } else {
1634         AppendToBuffer("%s,", NameOfXMMRegister(regop));
1635         current += PrintRightXMMOperand(current);
1636       }
1637     } else if (opcode == 0x2A) {
1638       // CVTSI2SD: integer to XMM double conversion.
1639       int mod, regop, rm;
1640       get_modrm(*current, &mod, &regop, &rm);
1641       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1642       current += PrintRightOperand(current);
1643     } else if (opcode == 0x2C) {
1644       // CVTTSD2SI:
1645       // Convert with truncation scalar double-precision FP to integer.
1646       int mod, regop, rm;
1647       get_modrm(*current, &mod, &regop, &rm);
1648       AppendToBuffer("cvttsd2si%c %s,",
1649           operand_size_code(), NameOfCPURegister(regop));
1650       current += PrintRightXMMOperand(current);
1651     } else if (opcode == 0x2D) {
1652       // CVTSD2SI: Convert scalar double-precision FP to integer.
1653       int mod, regop, rm;
1654       get_modrm(*current, &mod, &regop, &rm);
1655       AppendToBuffer("cvtsd2si%c %s,",
1656           operand_size_code(), NameOfCPURegister(regop));
1657       current += PrintRightXMMOperand(current);
1658     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1659       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1660       int mod, regop, rm;
1661       get_modrm(*current, &mod, &regop, &rm);
1662       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1663       current += PrintRightXMMOperand(current);
1664     } else if (opcode == 0xC2) {
1665       // Intel manual 2A, Table 3-18.
1666       int mod, regop, rm;
1667       get_modrm(*current, &mod, &regop, &rm);
1668       const char* const pseudo_op[] = {
1669         "cmpeqsd",
1670         "cmpltsd",
1671         "cmplesd",
1672         "cmpunordsd",
1673         "cmpneqsd",
1674         "cmpnltsd",
1675         "cmpnlesd",
1676         "cmpordsd"
1677       };
1678       AppendToBuffer("%s %s,%s",
1679                      pseudo_op[current[1]],
1680                      NameOfXMMRegister(regop),
1681                      NameOfXMMRegister(rm));
1682       current += 2;
1683     } else {
1684       UnimplementedInstruction();
1685     }
1686   } else if (group_1_prefix_ == 0xF3) {
1687     // Instructions with prefix 0xF3.
1688     if (opcode == 0x11 || opcode == 0x10) {
1689       // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
1690       AppendToBuffer("movss ");
1691       int mod, regop, rm;
1692       get_modrm(*current, &mod, &regop, &rm);
1693       if (opcode == 0x11) {
1694         current += PrintRightOperand(current);
1695         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1696       } else {
1697         AppendToBuffer("%s,", NameOfXMMRegister(regop));
1698         current += PrintRightOperand(current);
1699       }
1700     } else if (opcode == 0x2A) {
1701       // CVTSI2SS: integer to XMM single conversion.
1702       int mod, regop, rm;
1703       get_modrm(*current, &mod, &regop, &rm);
1704       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1705       current += PrintRightOperand(current);
1706     } else if (opcode == 0x2C) {
1707       // CVTTSS2SI:
1708       // Convert with truncation scalar single-precision FP to dword integer.
1709       int mod, regop, rm;
1710       get_modrm(*current, &mod, &regop, &rm);
1711       AppendToBuffer("cvttss2si%c %s,",
1712           operand_size_code(), NameOfCPURegister(regop));
1713       current += PrintRightXMMOperand(current);
1714     } else if (opcode == 0x7E) {
1715       int mod, regop, rm;
1716       get_modrm(*current, &mod, &regop, &rm);
1717       AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
1718       current += PrintRightXMMOperand(current);
1719     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1720       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1721       int mod, regop, rm;
1722       get_modrm(*current, &mod, &regop, &rm);
1723       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1724       current += PrintRightXMMOperand(current);
1725     } else if (opcode == 0xB8) {
1726       int mod, regop, rm;
1727       get_modrm(*current, &mod, &regop, &rm);
1728       AppendToBuffer("popcnt%c %s,", operand_size_code(),
1729                      NameOfCPURegister(regop));
1730       current += PrintRightOperand(current);
1731     } else if (opcode == 0xBC) {
1732       int mod, regop, rm;
1733       get_modrm(*current, &mod, &regop, &rm);
1734       AppendToBuffer("tzcnt%c %s,", operand_size_code(),
1735                      NameOfCPURegister(regop));
1736       current += PrintRightOperand(current);
1737     } else if (opcode == 0xBD) {
1738       int mod, regop, rm;
1739       get_modrm(*current, &mod, &regop, &rm);
1740       AppendToBuffer("lzcnt%c %s,", operand_size_code(),
1741                      NameOfCPURegister(regop));
1742       current += PrintRightOperand(current);
1743     } else if (opcode == 0xC2) {
1744       // Intel manual 2A, Table 3-18.
1745       int mod, regop, rm;
1746       get_modrm(*current, &mod, &regop, &rm);
1747       const char* const pseudo_op[] = {"cmpeqss",    "cmpltss",  "cmpless",
1748                                        "cmpunordss", "cmpneqss", "cmpnltss",
1749                                        "cmpnless",   "cmpordss"};
1750       AppendToBuffer("%s %s,%s", pseudo_op[current[1]],
1751                      NameOfXMMRegister(regop), NameOfXMMRegister(rm));
1752       current += 2;
1753     } else {
1754       UnimplementedInstruction();
1755     }
1756   } else if (opcode == 0x1F) {
1757     // NOP
1758     int mod, regop, rm;
1759     get_modrm(*current, &mod, &regop, &rm);
1760     current++;
1761     if (rm == 4) {  // SIB byte present.
1762       current++;
1763     }
1764     if (mod == 1) {  // Byte displacement.
1765       current += 1;
1766     } else if (mod == 2) {  // 32-bit displacement.
1767       current += 4;
1768     }  // else no immediate displacement.
1769     AppendToBuffer("nop");
1770 
1771   } else if (opcode == 0x28) {
1772     // movaps xmm, xmm/m128
1773     int mod, regop, rm;
1774     get_modrm(*current, &mod, &regop, &rm);
1775     AppendToBuffer("movaps %s,", NameOfXMMRegister(regop));
1776     current += PrintRightXMMOperand(current);
1777 
1778   } else if (opcode == 0x29) {
1779     // movaps xmm/m128, xmm
1780     int mod, regop, rm;
1781     get_modrm(*current, &mod, &regop, &rm);
1782     AppendToBuffer("movaps ");
1783     current += PrintRightXMMOperand(current);
1784     AppendToBuffer(",%s", NameOfXMMRegister(regop));
1785 
1786   } else if (opcode == 0x2e) {
1787     int mod, regop, rm;
1788     get_modrm(*current, &mod, &regop, &rm);
1789     AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
1790     current += PrintRightXMMOperand(current);
1791   } else if (opcode == 0xA2) {
1792     // CPUID
1793     AppendToBuffer("%s", mnemonic);
1794 
1795   } else if ((opcode & 0xF0) == 0x40) {
1796     // CMOVcc: conditional move.
1797     int condition = opcode & 0x0F;
1798     const InstructionDesc& idesc = cmov_instructions[condition];
1799     byte_size_operand_ = idesc.byte_size_operation;
1800     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1801 
1802   } else if (opcode >= 0x53 && opcode <= 0x5F) {
1803     const char* const pseudo_op[] = {
1804       "rcpps",
1805       "andps",
1806       "andnps",
1807       "orps",
1808       "xorps",
1809       "addps",
1810       "mulps",
1811       "cvtps2pd",
1812       "cvtdq2ps",
1813       "subps",
1814       "minps",
1815       "divps",
1816       "maxps",
1817     };
1818     int mod, regop, rm;
1819     get_modrm(*current, &mod, &regop, &rm);
1820     AppendToBuffer("%s %s,",
1821                    pseudo_op[opcode - 0x53],
1822                    NameOfXMMRegister(regop));
1823     current += PrintRightXMMOperand(current);
1824 
1825   } else if (opcode == 0xC6) {
1826     // shufps xmm, xmm/m128, imm8
1827     int mod, regop, rm;
1828     get_modrm(*current, &mod, &regop, &rm);
1829     AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
1830     current += PrintRightXMMOperand(current);
1831     AppendToBuffer(", %d", (*current) & 3);
1832     current += 1;
1833 
1834   } else if (opcode == 0x50) {
1835     // movmskps reg, xmm
1836     int mod, regop, rm;
1837     get_modrm(*current, &mod, &regop, &rm);
1838     AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
1839     current += PrintRightXMMOperand(current);
1840 
1841   } else if ((opcode & 0xF0) == 0x80) {
1842     // Jcc: Conditional jump (branch).
1843     current = data + JumpConditional(data);
1844 
1845   } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1846              opcode == 0xB7 || opcode == 0xAF) {
1847     // Size-extending moves, IMUL.
1848     current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1849 
1850   } else if ((opcode & 0xF0) == 0x90) {
1851     // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
1852     current = data + SetCC(data);
1853 
1854   } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1855     // SHLD, SHRD (double-precision shift), BTS (bit set).
1856     AppendToBuffer("%s ", mnemonic);
1857     int mod, regop, rm;
1858     get_modrm(*current, &mod, &regop, &rm);
1859     current += PrintRightOperand(current);
1860     if (opcode == 0xAB) {
1861       AppendToBuffer(",%s", NameOfCPURegister(regop));
1862     } else {
1863       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1864     }
1865   } else if (opcode == 0xB8 || opcode == 0xBC || opcode == 0xBD) {
1866     // POPCNT, CTZ, CLZ.
1867     AppendToBuffer("%s%c ", mnemonic, operand_size_code());
1868     int mod, regop, rm;
1869     get_modrm(*current, &mod, &regop, &rm);
1870     AppendToBuffer("%s,", NameOfCPURegister(regop));
1871     current += PrintRightOperand(current);
1872   } else if (opcode == 0x0B) {
1873     AppendToBuffer("ud2");
1874   } else {
1875     UnimplementedInstruction();
1876   }
1877   return static_cast<int>(current - data);
1878 }
1879 
1880 
1881 // Mnemonics for two-byte opcode instructions starting with 0x0F.
1882 // The argument is the second byte of the two-byte opcode.
1883 // Returns NULL if the instruction is not handled here.
TwoByteMnemonic(byte opcode)1884 const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
1885   switch (opcode) {
1886     case 0x1F:
1887       return "nop";
1888     case 0x2A:  // F2/F3 prefix.
1889       return (group_1_prefix_ == 0xF2) ? "cvtsi2sd" : "cvtsi2ss";
1890     case 0x51:  // F2/F3 prefix.
1891       return (group_1_prefix_ == 0xF2) ? "sqrtsd" : "sqrtss";
1892     case 0x58:  // F2/F3 prefix.
1893       return (group_1_prefix_ == 0xF2) ? "addsd" : "addss";
1894     case 0x59:  // F2/F3 prefix.
1895       return (group_1_prefix_ == 0xF2) ? "mulsd" : "mulss";
1896     case 0x5A:  // F2/F3 prefix.
1897       return (group_1_prefix_ == 0xF2) ? "cvtsd2ss" : "cvtss2sd";
1898     case 0x5D:  // F2/F3 prefix.
1899       return (group_1_prefix_ == 0xF2) ? "minsd" : "minss";
1900     case 0x5C:  // F2/F3 prefix.
1901       return (group_1_prefix_ == 0xF2) ? "subsd" : "subss";
1902     case 0x5E:  // F2/F3 prefix.
1903       return (group_1_prefix_ == 0xF2) ? "divsd" : "divss";
1904     case 0x5F:  // F2/F3 prefix.
1905       return (group_1_prefix_ == 0xF2) ? "maxsd" : "maxss";
1906     case 0xA2:
1907       return "cpuid";
1908     case 0xA5:
1909       return "shld";
1910     case 0xAB:
1911       return "bts";
1912     case 0xAD:
1913       return "shrd";
1914     case 0xAF:
1915       return "imul";
1916     case 0xB6:
1917       return "movzxb";
1918     case 0xB7:
1919       return "movzxw";
1920     case 0xBC:
1921       return "bsf";
1922     case 0xBD:
1923       return "bsr";
1924     case 0xBE:
1925       return "movsxb";
1926     case 0xBF:
1927       return "movsxw";
1928     default:
1929       return NULL;
1930   }
1931 }
1932 
1933 
1934 // Disassembles the instruction at instr, and writes it into out_buffer.
InstructionDecode(v8::internal::Vector<char> out_buffer,byte * instr)1935 int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
1936                                        byte* instr) {
1937   tmp_buffer_pos_ = 0;  // starting to write as position 0
1938   byte* data = instr;
1939   bool processed = true;  // Will be set to false if the current instruction
1940                           // is not in 'instructions' table.
1941   byte current;
1942 
1943   // Scan for prefixes.
1944   while (true) {
1945     current = *data;
1946     if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
1947       operand_size_ = current;
1948     } else if ((current & 0xF0) == 0x40) {  // REX prefix.
1949       setRex(current);
1950       if (rex_w()) AppendToBuffer("REX.W ");
1951     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
1952       group_1_prefix_ = current;
1953     } else if (current == VEX3_PREFIX) {
1954       vex_byte0_ = current;
1955       vex_byte1_ = *(data + 1);
1956       vex_byte2_ = *(data + 2);
1957       setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
1958       data += 3;
1959       break;  // Vex is the last prefix.
1960     } else if (current == VEX2_PREFIX) {
1961       vex_byte0_ = current;
1962       vex_byte1_ = *(data + 1);
1963       setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
1964       data += 2;
1965       break;  // Vex is the last prefix.
1966     } else {  // Not a prefix - an opcode.
1967       break;
1968     }
1969     data++;
1970   }
1971 
1972   // Decode AVX instructions.
1973   if (vex_byte0_ != 0) {
1974     processed = true;
1975     data += AVXInstruction(data);
1976   } else {
1977     const InstructionDesc& idesc = instruction_table_->Get(current);
1978     byte_size_operand_ = idesc.byte_size_operation;
1979     switch (idesc.type) {
1980       case ZERO_OPERANDS_INSTR:
1981         if (current >= 0xA4 && current <= 0xA7) {
1982           // String move or compare operations.
1983           if (group_1_prefix_ == REP_PREFIX) {
1984             // REP.
1985             AppendToBuffer("rep ");
1986           }
1987           if (rex_w()) AppendToBuffer("REX.W ");
1988           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
1989         } else {
1990           AppendToBuffer("%s", idesc.mnem, operand_size_code());
1991         }
1992         data++;
1993         break;
1994 
1995       case TWO_OPERANDS_INSTR:
1996         data++;
1997         data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1998         break;
1999 
2000       case JUMP_CONDITIONAL_SHORT_INSTR:
2001         data += JumpConditionalShort(data);
2002         break;
2003 
2004       case REGISTER_INSTR:
2005         AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(),
2006                        NameOfCPURegister(base_reg(current & 0x07)));
2007         data++;
2008         break;
2009       case PUSHPOP_INSTR:
2010         AppendToBuffer("%s %s", idesc.mnem,
2011                        NameOfCPURegister(base_reg(current & 0x07)));
2012         data++;
2013         break;
2014       case MOVE_REG_INSTR: {
2015         byte* addr = NULL;
2016         switch (operand_size()) {
2017           case OPERAND_WORD_SIZE:
2018             addr =
2019                 reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
2020             data += 3;
2021             break;
2022           case OPERAND_DOUBLEWORD_SIZE:
2023             addr =
2024                 reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
2025             data += 5;
2026             break;
2027           case OPERAND_QUADWORD_SIZE:
2028             addr =
2029                 reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
2030             data += 9;
2031             break;
2032           default:
2033             UNREACHABLE();
2034         }
2035         AppendToBuffer("mov%c %s,%s", operand_size_code(),
2036                        NameOfCPURegister(base_reg(current & 0x07)),
2037                        NameOfAddress(addr));
2038         break;
2039       }
2040 
2041       case CALL_JUMP_INSTR: {
2042         byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
2043         AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
2044         data += 5;
2045         break;
2046       }
2047 
2048       case SHORT_IMMEDIATE_INSTR: {
2049         byte* addr =
2050             reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
2051         AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
2052         data += 5;
2053         break;
2054       }
2055 
2056       case NO_INSTR:
2057         processed = false;
2058         break;
2059 
2060       default:
2061         UNIMPLEMENTED();  // This type is not implemented.
2062     }
2063   }
2064 
2065   // The first byte didn't match any of the simple opcodes, so we
2066   // need to do special processing on it.
2067   if (!processed) {
2068     switch (*data) {
2069       case 0xC2:
2070         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
2071         data += 3;
2072         break;
2073 
2074       case 0x69:  // fall through
2075       case 0x6B: {
2076         int count = 1;
2077         count += PrintOperands("imul", REG_OPER_OP_ORDER, data + count);
2078         AppendToBuffer(",0x");
2079         if (*data == 0x69) {
2080           count += PrintImmediate(data + count, operand_size());
2081         } else {
2082           count += PrintImmediate(data + count, OPERAND_BYTE_SIZE);
2083         }
2084         data += count;
2085         break;
2086       }
2087 
2088       case 0x81:  // fall through
2089       case 0x83:  // 0x81 with sign extension bit set
2090         data += PrintImmediateOp(data);
2091         break;
2092 
2093       case 0x0F:
2094         data += TwoByteOpcodeInstruction(data);
2095         break;
2096 
2097       case 0x8F: {
2098         data++;
2099         int mod, regop, rm;
2100         get_modrm(*data, &mod, &regop, &rm);
2101         if (regop == 0) {
2102           AppendToBuffer("pop ");
2103           data += PrintRightOperand(data);
2104         }
2105       }
2106         break;
2107 
2108       case 0xFF: {
2109         data++;
2110         int mod, regop, rm;
2111         get_modrm(*data, &mod, &regop, &rm);
2112         const char* mnem = NULL;
2113         switch (regop) {
2114           case 0:
2115             mnem = "inc";
2116             break;
2117           case 1:
2118             mnem = "dec";
2119             break;
2120           case 2:
2121             mnem = "call";
2122             break;
2123           case 4:
2124             mnem = "jmp";
2125             break;
2126           case 6:
2127             mnem = "push";
2128             break;
2129           default:
2130             mnem = "???";
2131         }
2132         AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
2133                        mnem,
2134                        operand_size_code());
2135         data += PrintRightOperand(data);
2136       }
2137         break;
2138 
2139       case 0xC7:  // imm32, fall through
2140       case 0xC6:  // imm8
2141       {
2142         bool is_byte = *data == 0xC6;
2143         data++;
2144         if (is_byte) {
2145           AppendToBuffer("movb ");
2146           data += PrintRightByteOperand(data);
2147           int32_t imm = *data;
2148           AppendToBuffer(",0x%x", imm);
2149           data++;
2150         } else {
2151           AppendToBuffer("mov%c ", operand_size_code());
2152           data += PrintRightOperand(data);
2153           if (operand_size() == OPERAND_WORD_SIZE) {
2154             int16_t imm = *reinterpret_cast<int16_t*>(data);
2155             AppendToBuffer(",0x%x", imm);
2156             data += 2;
2157           } else {
2158             int32_t imm = *reinterpret_cast<int32_t*>(data);
2159             AppendToBuffer(",0x%x", imm);
2160             data += 4;
2161           }
2162         }
2163       }
2164         break;
2165 
2166       case 0x80: {
2167         data++;
2168         AppendToBuffer("cmpb ");
2169         data += PrintRightByteOperand(data);
2170         int32_t imm = *data;
2171         AppendToBuffer(",0x%x", imm);
2172         data++;
2173       }
2174         break;
2175 
2176       case 0x88:  // 8bit, fall through
2177       case 0x89:  // 32bit
2178       {
2179         bool is_byte = *data == 0x88;
2180         int mod, regop, rm;
2181         data++;
2182         get_modrm(*data, &mod, &regop, &rm);
2183         if (is_byte) {
2184           AppendToBuffer("movb ");
2185           data += PrintRightByteOperand(data);
2186           AppendToBuffer(",%s", NameOfByteCPURegister(regop));
2187         } else {
2188           AppendToBuffer("mov%c ", operand_size_code());
2189           data += PrintRightOperand(data);
2190           AppendToBuffer(",%s", NameOfCPURegister(regop));
2191         }
2192       }
2193         break;
2194 
2195       case 0x90:
2196       case 0x91:
2197       case 0x92:
2198       case 0x93:
2199       case 0x94:
2200       case 0x95:
2201       case 0x96:
2202       case 0x97: {
2203         int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
2204         if (reg == 0) {
2205           AppendToBuffer("nop");  // Common name for xchg rax,rax.
2206         } else {
2207           AppendToBuffer("xchg%c rax,%s",
2208                          operand_size_code(),
2209                          NameOfCPURegister(reg));
2210         }
2211         data++;
2212       }
2213         break;
2214       case 0xB0:
2215       case 0xB1:
2216       case 0xB2:
2217       case 0xB3:
2218       case 0xB4:
2219       case 0xB5:
2220       case 0xB6:
2221       case 0xB7:
2222       case 0xB8:
2223       case 0xB9:
2224       case 0xBA:
2225       case 0xBB:
2226       case 0xBC:
2227       case 0xBD:
2228       case 0xBE:
2229       case 0xBF: {
2230         // mov reg8,imm8 or mov reg32,imm32
2231         byte opcode = *data;
2232         data++;
2233         bool is_32bit = (opcode >= 0xB8);
2234         int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
2235         if (is_32bit) {
2236           AppendToBuffer("mov%c %s,",
2237                          operand_size_code(),
2238                          NameOfCPURegister(reg));
2239           data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
2240         } else {
2241           AppendToBuffer("movb %s,",
2242                          NameOfByteCPURegister(reg));
2243           data += PrintImmediate(data, OPERAND_BYTE_SIZE);
2244         }
2245         break;
2246       }
2247       case 0xFE: {
2248         data++;
2249         int mod, regop, rm;
2250         get_modrm(*data, &mod, &regop, &rm);
2251         if (regop == 1) {
2252           AppendToBuffer("decb ");
2253           data += PrintRightByteOperand(data);
2254         } else {
2255           UnimplementedInstruction();
2256         }
2257         break;
2258       }
2259       case 0x68:
2260         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
2261         data += 5;
2262         break;
2263 
2264       case 0x6A:
2265         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
2266         data += 2;
2267         break;
2268 
2269       case 0xA1:  // Fall through.
2270       case 0xA3:
2271         switch (operand_size()) {
2272           case OPERAND_DOUBLEWORD_SIZE: {
2273             const char* memory_location = NameOfAddress(
2274                 reinterpret_cast<byte*>(
2275                     *reinterpret_cast<int32_t*>(data + 1)));
2276             if (*data == 0xA1) {  // Opcode 0xA1
2277               AppendToBuffer("movzxlq rax,(%s)", memory_location);
2278             } else {  // Opcode 0xA3
2279               AppendToBuffer("movzxlq (%s),rax", memory_location);
2280             }
2281             data += 5;
2282             break;
2283           }
2284           case OPERAND_QUADWORD_SIZE: {
2285             // New x64 instruction mov rax,(imm_64).
2286             const char* memory_location = NameOfAddress(
2287                 *reinterpret_cast<byte**>(data + 1));
2288             if (*data == 0xA1) {  // Opcode 0xA1
2289               AppendToBuffer("movq rax,(%s)", memory_location);
2290             } else {  // Opcode 0xA3
2291               AppendToBuffer("movq (%s),rax", memory_location);
2292             }
2293             data += 9;
2294             break;
2295           }
2296           default:
2297             UnimplementedInstruction();
2298             data += 2;
2299         }
2300         break;
2301 
2302       case 0xA8:
2303         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
2304         data += 2;
2305         break;
2306 
2307       case 0xA9: {
2308         int64_t value = 0;
2309         switch (operand_size()) {
2310           case OPERAND_WORD_SIZE:
2311             value = *reinterpret_cast<uint16_t*>(data + 1);
2312             data += 3;
2313             break;
2314           case OPERAND_DOUBLEWORD_SIZE:
2315             value = *reinterpret_cast<uint32_t*>(data + 1);
2316             data += 5;
2317             break;
2318           case OPERAND_QUADWORD_SIZE:
2319             value = *reinterpret_cast<int32_t*>(data + 1);
2320             data += 5;
2321             break;
2322           default:
2323             UNREACHABLE();
2324         }
2325         AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x",
2326                        operand_size_code(),
2327                        value);
2328         break;
2329       }
2330       case 0xD1:  // fall through
2331       case 0xD3:  // fall through
2332       case 0xC1:
2333         data += ShiftInstruction(data);
2334         break;
2335       case 0xD0:  // fall through
2336       case 0xD2:  // fall through
2337       case 0xC0:
2338         byte_size_operand_ = true;
2339         data += ShiftInstruction(data);
2340         break;
2341 
2342       case 0xD9:  // fall through
2343       case 0xDA:  // fall through
2344       case 0xDB:  // fall through
2345       case 0xDC:  // fall through
2346       case 0xDD:  // fall through
2347       case 0xDE:  // fall through
2348       case 0xDF:
2349         data += FPUInstruction(data);
2350         break;
2351 
2352       case 0xEB:
2353         data += JumpShort(data);
2354         break;
2355 
2356       case 0xF6:
2357         byte_size_operand_ = true;  // fall through
2358       case 0xF7:
2359         data += F6F7Instruction(data);
2360         break;
2361 
2362       case 0x3C:
2363         AppendToBuffer("cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
2364         data +=2;
2365         break;
2366 
2367       default:
2368         UnimplementedInstruction();
2369         data += 1;
2370     }
2371   }  // !processed
2372 
2373   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
2374     tmp_buffer_[tmp_buffer_pos_] = '\0';
2375   }
2376 
2377   int instr_len = static_cast<int>(data - instr);
2378   DCHECK(instr_len > 0);  // Ensure progress.
2379 
2380   int outp = 0;
2381   // Instruction bytes.
2382   for (byte* bp = instr; bp < data; bp++) {
2383     outp += v8::internal::SNPrintF(out_buffer + outp, "%02x", *bp);
2384   }
2385   for (int i = 6 - instr_len; i >= 0; i--) {
2386     outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
2387   }
2388 
2389   outp += v8::internal::SNPrintF(out_buffer + outp, " %s",
2390                                  tmp_buffer_.start());
2391   return instr_len;
2392 }
2393 
2394 
2395 //------------------------------------------------------------------------------
2396 
2397 
2398 static const char* const cpu_regs[16] = {
2399   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
2400   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
2401 };
2402 
2403 
2404 static const char* const byte_cpu_regs[16] = {
2405   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
2406   "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
2407 };
2408 
2409 
2410 static const char* const xmm_regs[16] = {
2411   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
2412   "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
2413 };
2414 
2415 
NameOfAddress(byte * addr) const2416 const char* NameConverter::NameOfAddress(byte* addr) const {
2417   v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
2418   return tmp_buffer_.start();
2419 }
2420 
2421 
NameOfConstant(byte * addr) const2422 const char* NameConverter::NameOfConstant(byte* addr) const {
2423   return NameOfAddress(addr);
2424 }
2425 
2426 
NameOfCPURegister(int reg) const2427 const char* NameConverter::NameOfCPURegister(int reg) const {
2428   if (0 <= reg && reg < 16)
2429     return cpu_regs[reg];
2430   return "noreg";
2431 }
2432 
2433 
NameOfByteCPURegister(int reg) const2434 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2435   if (0 <= reg && reg < 16)
2436     return byte_cpu_regs[reg];
2437   return "noreg";
2438 }
2439 
2440 
NameOfXMMRegister(int reg) const2441 const char* NameConverter::NameOfXMMRegister(int reg) const {
2442   if (0 <= reg && reg < 16)
2443     return xmm_regs[reg];
2444   return "noxmmreg";
2445 }
2446 
2447 
NameInCode(byte * addr) const2448 const char* NameConverter::NameInCode(byte* addr) const {
2449   // X64 does not embed debug strings at the moment.
2450   UNREACHABLE();
2451   return "";
2452 }
2453 
2454 
2455 //------------------------------------------------------------------------------
2456 
Disassembler(const NameConverter & converter)2457 Disassembler::Disassembler(const NameConverter& converter)
2458     : converter_(converter) { }
2459 
~Disassembler()2460 Disassembler::~Disassembler() { }
2461 
2462 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)2463 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2464                                     byte* instruction) {
2465   DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
2466   return d.InstructionDecode(buffer, instruction);
2467 }
2468 
2469 
2470 // The X64 assembler does not use constant pools.
ConstantPoolSizeAt(byte * instruction)2471 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2472   return -1;
2473 }
2474 
2475 
Disassemble(FILE * f,byte * begin,byte * end)2476 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
2477   NameConverter converter;
2478   Disassembler d(converter);
2479   for (byte* pc = begin; pc < end;) {
2480     v8::internal::EmbeddedVector<char, 128> buffer;
2481     buffer[0] = '\0';
2482     byte* prev_pc = pc;
2483     pc += d.InstructionDecode(buffer, pc);
2484     fprintf(f, "%p", prev_pc);
2485     fprintf(f, "    ");
2486 
2487     for (byte* bp = prev_pc; bp < pc; bp++) {
2488       fprintf(f, "%02x", *bp);
2489     }
2490     for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
2491       fprintf(f, "  ");
2492     }
2493     fprintf(f, "  %s\n", buffer.start());
2494   }
2495 }
2496 
2497 }  // namespace disasm
2498 
2499 #endif  // V8_TARGET_ARCH_X64
2500