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