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