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
16namespace disasm {
17
18enum 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//------------------------------------------------------------------
33struct ByteMnemonic {
34  int b;  // -1 terminates, otherwise must be in range (0..255)
35  OperandType op_order_;
36  const char* mnem;
37};
38
39
40static 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
87static 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
108static 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
115static 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
128static 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
134enum 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
146enum 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
158struct InstructionDesc {
159  const char* mnem;
160  InstructionType type;
161  OperandType op_order_;
162  bool byte_size_operation;  // Fixed 8-bit operation.
163};
164
165
166class InstructionTable {
167 public:
168  InstructionTable();
169  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
184InstructionTable::InstructionTable() {
185  Clear();
186  Init();
187}
188
189
190void 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
200void 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
212void 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
227void 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
242void 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
252static v8::base::LazyInstance<InstructionTable>::type instruction_table =
253    LAZY_INSTANCE_INITIALIZER;
254
255
256static 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
279enum 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.
287class DisassemblerX64 {
288 public:
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
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
337  void setRex(byte rex) {
338    DCHECK_EQ(0x40, rex & 0xF0);
339    rex_ = rex;
340  }
341
342  bool rex() { return rex_ != 0; }
343
344  bool rex_b() { return (rex_ & 0x01) != 0; }
345
346  // Actual number of base register given the low bits and the rex.b state.
347  int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
348
349  bool rex_x() { return (rex_ & 0x02) != 0; }
350
351  bool rex_r() { return (rex_ & 0x04) != 0; }
352
353  bool rex_w() { return (rex_ & 0x08) != 0; }
354
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
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
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
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
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
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
390  bool vex_0f() {
391    if (vex_byte0_ == VEX2_PREFIX) return true;
392    return (vex_byte1_ & 3) == 1;
393  }
394
395  bool vex_0f38() {
396    if (vex_byte0_ == VEX2_PREFIX) return false;
397    return (vex_byte1_ & 3) == 2;
398  }
399
400  bool vex_0f3a() {
401    if (vex_byte0_ == VEX2_PREFIX) return false;
402    return (vex_byte1_ & 3) == 3;
403  }
404
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
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
418  char operand_size_code() {
419    return "bwlq"[operand_size()];
420  }
421
422  char float_size_code() { return "sd"[rex_w()]; }
423
424  const char* NameOfCPURegister(int reg) const {
425    return converter_.NameOfCPURegister(reg);
426  }
427
428  const char* NameOfByteCPURegister(int reg) const {
429    return converter_.NameOfByteCPURegister(reg);
430  }
431
432  const char* NameOfXMMRegister(int reg) const {
433    return converter_.NameOfXMMRegister(reg);
434  }
435
436  const char* NameOfAddress(byte* addr) const {
437    return converter_.NameOfAddress(addr);
438  }
439
440  // Disassembler helper functions.
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
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
485  void UnimplementedInstruction() {
486    if (abort_on_unimplemented_) {
487      CHECK(false);
488    } else {
489      AppendToBuffer("'Unimplemented Instruction'");
490    }
491  }
492};
493
494
495void 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
505int 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
597int 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
627int DisassemblerX64::PrintRightOperand(byte* modrmp) {
628  return PrintRightOperandHelper(modrmp,
629                                 &DisassemblerX64::NameOfCPURegister);
630}
631
632
633int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
634  return PrintRightOperandHelper(modrmp,
635                                 &DisassemblerX64::NameOfByteCPURegister);
636}
637
638
639int 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_'.
647int 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_'.
684int 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.
729int 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
776int 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.
838int 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.
848int 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.
859int 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.
870int 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
879const char* sf_str[4] = {"", "rl", "ra", "ll"};
880
881int 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.
1445int 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
1457int 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
1501int 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.
1627int 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.
2186const 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.
2240int 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
2705static 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
2711static 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
2717static 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
2723const 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
2729const char* NameConverter::NameOfConstant(byte* addr) const {
2730  return NameOfAddress(addr);
2731}
2732
2733
2734const char* NameConverter::NameOfCPURegister(int reg) const {
2735  if (0 <= reg && reg < 16)
2736    return cpu_regs[reg];
2737  return "noreg";
2738}
2739
2740
2741const char* NameConverter::NameOfByteCPURegister(int reg) const {
2742  if (0 <= reg && reg < 16)
2743    return byte_cpu_regs[reg];
2744  return "noreg";
2745}
2746
2747
2748const char* NameConverter::NameOfXMMRegister(int reg) const {
2749  if (0 <= reg && reg < 16)
2750    return xmm_regs[reg];
2751  return "noxmmreg";
2752}
2753
2754
2755const 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
2764Disassembler::Disassembler(const NameConverter& converter)
2765    : converter_(converter) { }
2766
2767Disassembler::~Disassembler() { }
2768
2769
2770int 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.
2778int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2779  return -1;
2780}
2781
2782
2783void 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