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