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