deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / x64 / disasm-x64.cc
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8
9 #include "src/v8.h"
10
11 #if V8_TARGET_ARCH_X64
12
13 #include "src/base/lazy-instance.h"
14 #include "src/disasm.h"
15
16 namespace disasm {
17
18 enum OperandType {
19   UNSET_OP_ORDER = 0,
20   // Operand size decides between 16, 32 and 64 bit operands.
21   REG_OPER_OP_ORDER = 1,  // Register destination, operand source.
22   OPER_REG_OP_ORDER = 2,  // Operand destination, register source.
23   // Fixed 8-bit operands.
24   BYTE_SIZE_OPERAND_FLAG = 4,
25   BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
26   BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
27 };
28
29
30 //------------------------------------------------------------------
31 // Tables
32 //------------------------------------------------------------------
33 struct ByteMnemonic {
34   int b;  // -1 terminates, otherwise must be in range (0..255)
35   OperandType op_order_;
36   const char* mnem;
37 };
38
39
40 static const ByteMnemonic two_operands_instr[] = {
41   { 0x00, BYTE_OPER_REG_OP_ORDER, "add" },
42   { 0x01, OPER_REG_OP_ORDER,      "add" },
43   { 0x02, BYTE_REG_OPER_OP_ORDER, "add" },
44   { 0x03, REG_OPER_OP_ORDER,      "add" },
45   { 0x08, BYTE_OPER_REG_OP_ORDER, "or" },
46   { 0x09, OPER_REG_OP_ORDER,      "or" },
47   { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" },
48   { 0x0B, REG_OPER_OP_ORDER,      "or" },
49   { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" },
50   { 0x11, OPER_REG_OP_ORDER,      "adc" },
51   { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" },
52   { 0x13, REG_OPER_OP_ORDER,      "adc" },
53   { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" },
54   { 0x19, OPER_REG_OP_ORDER,      "sbb" },
55   { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" },
56   { 0x1B, REG_OPER_OP_ORDER,      "sbb" },
57   { 0x20, BYTE_OPER_REG_OP_ORDER, "and" },
58   { 0x21, OPER_REG_OP_ORDER,      "and" },
59   { 0x22, BYTE_REG_OPER_OP_ORDER, "and" },
60   { 0x23, REG_OPER_OP_ORDER,      "and" },
61   { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" },
62   { 0x29, OPER_REG_OP_ORDER,      "sub" },
63   { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" },
64   { 0x2B, REG_OPER_OP_ORDER,      "sub" },
65   { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" },
66   { 0x31, OPER_REG_OP_ORDER,      "xor" },
67   { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" },
68   { 0x33, REG_OPER_OP_ORDER,      "xor" },
69   { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" },
70   { 0x39, OPER_REG_OP_ORDER,      "cmp" },
71   { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" },
72   { 0x3B, REG_OPER_OP_ORDER,      "cmp" },
73   { 0x63, REG_OPER_OP_ORDER,      "movsxl" },
74   { 0x84, BYTE_REG_OPER_OP_ORDER, "test" },
75   { 0x85, REG_OPER_OP_ORDER,      "test" },
76   { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" },
77   { 0x87, REG_OPER_OP_ORDER,      "xchg" },
78   { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" },
79   { 0x89, OPER_REG_OP_ORDER,      "mov" },
80   { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" },
81   { 0x8B, REG_OPER_OP_ORDER,      "mov" },
82   { 0x8D, REG_OPER_OP_ORDER,      "lea" },
83   { -1, UNSET_OP_ORDER, "" }
84 };
85
86
87 static const ByteMnemonic zero_operands_instr[] = {
88   { 0xC3, UNSET_OP_ORDER, "ret" },
89   { 0xC9, UNSET_OP_ORDER, "leave" },
90   { 0xF4, UNSET_OP_ORDER, "hlt" },
91   { 0xFC, UNSET_OP_ORDER, "cld" },
92   { 0xCC, UNSET_OP_ORDER, "int3" },
93   { 0x60, UNSET_OP_ORDER, "pushad" },
94   { 0x61, UNSET_OP_ORDER, "popad" },
95   { 0x9C, UNSET_OP_ORDER, "pushfd" },
96   { 0x9D, UNSET_OP_ORDER, "popfd" },
97   { 0x9E, UNSET_OP_ORDER, "sahf" },
98   { 0x99, UNSET_OP_ORDER, "cdq" },
99   { 0x9B, UNSET_OP_ORDER, "fwait" },
100   { 0xA4, UNSET_OP_ORDER, "movs" },
101   { 0xA5, UNSET_OP_ORDER, "movs" },
102   { 0xA6, UNSET_OP_ORDER, "cmps" },
103   { 0xA7, UNSET_OP_ORDER, "cmps" },
104   { -1, UNSET_OP_ORDER, "" }
105 };
106
107
108 static const ByteMnemonic call_jump_instr[] = {
109   { 0xE8, UNSET_OP_ORDER, "call" },
110   { 0xE9, UNSET_OP_ORDER, "jmp" },
111   { -1, UNSET_OP_ORDER, "" }
112 };
113
114
115 static const ByteMnemonic short_immediate_instr[] = {
116   { 0x05, UNSET_OP_ORDER, "add" },
117   { 0x0D, UNSET_OP_ORDER, "or" },
118   { 0x15, UNSET_OP_ORDER, "adc" },
119   { 0x1D, UNSET_OP_ORDER, "sbb" },
120   { 0x25, UNSET_OP_ORDER, "and" },
121   { 0x2D, UNSET_OP_ORDER, "sub" },
122   { 0x35, UNSET_OP_ORDER, "xor" },
123   { 0x3D, UNSET_OP_ORDER, "cmp" },
124   { -1, UNSET_OP_ORDER, "" }
125 };
126
127
128 static const char* const conditional_code_suffix[] = {
129   "o", "no", "c", "nc", "z", "nz", "na", "a",
130   "s", "ns", "pe", "po", "l", "ge", "le", "g"
131 };
132
133
134 enum InstructionType {
135   NO_INSTR,
136   ZERO_OPERANDS_INSTR,
137   TWO_OPERANDS_INSTR,
138   JUMP_CONDITIONAL_SHORT_INSTR,
139   REGISTER_INSTR,
140   PUSHPOP_INSTR,  // Has implicit 64-bit operand size.
141   MOVE_REG_INSTR,
142   CALL_JUMP_INSTR,
143   SHORT_IMMEDIATE_INSTR
144 };
145
146
147 enum Prefixes {
148   ESCAPE_PREFIX = 0x0F,
149   OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
150   ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
151   VEX3_PREFIX = 0xC4,
152   VEX2_PREFIX = 0xC5,
153   REPNE_PREFIX = 0xF2,
154   REP_PREFIX = 0xF3,
155   REPEQ_PREFIX = REP_PREFIX
156 };
157
158
159 struct InstructionDesc {
160   const char* mnem;
161   InstructionType type;
162   OperandType op_order_;
163   bool byte_size_operation;  // Fixed 8-bit operation.
164 };
165
166
167 class InstructionTable {
168  public:
169   InstructionTable();
170   const InstructionDesc& Get(byte x) const {
171     return instructions_[x];
172   }
173
174  private:
175   InstructionDesc instructions_[256];
176   void Clear();
177   void Init();
178   void CopyTable(const ByteMnemonic bm[], InstructionType type);
179   void SetTableRange(InstructionType type, byte start, byte end, bool byte_size,
180                      const char* mnem);
181   void AddJumpConditionalShort();
182 };
183
184
185 InstructionTable::InstructionTable() {
186   Clear();
187   Init();
188 }
189
190
191 void InstructionTable::Clear() {
192   for (int i = 0; i < 256; i++) {
193     instructions_[i].mnem = "(bad)";
194     instructions_[i].type = NO_INSTR;
195     instructions_[i].op_order_ = UNSET_OP_ORDER;
196     instructions_[i].byte_size_operation = false;
197   }
198 }
199
200
201 void InstructionTable::Init() {
202   CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
203   CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
204   CopyTable(call_jump_instr, CALL_JUMP_INSTR);
205   CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
206   AddJumpConditionalShort();
207   SetTableRange(PUSHPOP_INSTR, 0x50, 0x57, false, "push");
208   SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F, false, "pop");
209   SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, false, "mov");
210 }
211
212
213 void InstructionTable::CopyTable(const ByteMnemonic bm[],
214                                  InstructionType type) {
215   for (int i = 0; bm[i].b >= 0; i++) {
216     InstructionDesc* id = &instructions_[bm[i].b];
217     id->mnem = bm[i].mnem;
218     OperandType op_order = bm[i].op_order_;
219     id->op_order_ =
220         static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
221     DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered
222     id->type = type;
223     id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
224   }
225 }
226
227
228 void InstructionTable::SetTableRange(InstructionType type,
229                                      byte start,
230                                      byte end,
231                                      bool byte_size,
232                                      const char* mnem) {
233   for (byte b = start; b <= end; b++) {
234     InstructionDesc* id = &instructions_[b];
235     DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered
236     id->mnem = mnem;
237     id->type = type;
238     id->byte_size_operation = byte_size;
239   }
240 }
241
242
243 void InstructionTable::AddJumpConditionalShort() {
244   for (byte b = 0x70; b <= 0x7F; b++) {
245     InstructionDesc* id = &instructions_[b];
246     DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered
247     id->mnem = NULL;  // Computed depending on condition code.
248     id->type = JUMP_CONDITIONAL_SHORT_INSTR;
249   }
250 }
251
252
253 static v8::base::LazyInstance<InstructionTable>::type instruction_table =
254     LAZY_INSTANCE_INITIALIZER;
255
256
257 static const InstructionDesc cmov_instructions[16] = {
258   {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
259   {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
260   {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
261   {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
262   {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
263   {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
264   {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
265   {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
266   {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
267   {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
268   {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
269   {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
270   {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
271   {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
272   {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
273   {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
274 };
275
276
277 //------------------------------------------------------------------------------
278 // DisassemblerX64 implementation.
279
280 enum UnimplementedOpcodeAction {
281   CONTINUE_ON_UNIMPLEMENTED_OPCODE,
282   ABORT_ON_UNIMPLEMENTED_OPCODE
283 };
284
285
286 // A new DisassemblerX64 object is created to disassemble each instruction.
287 // The object can only disassemble a single instruction.
288 class DisassemblerX64 {
289  public:
290   DisassemblerX64(const NameConverter& converter,
291                   UnimplementedOpcodeAction unimplemented_action =
292                       ABORT_ON_UNIMPLEMENTED_OPCODE)
293       : converter_(converter),
294         tmp_buffer_pos_(0),
295         abort_on_unimplemented_(unimplemented_action ==
296                                 ABORT_ON_UNIMPLEMENTED_OPCODE),
297         rex_(0),
298         operand_size_(0),
299         group_1_prefix_(0),
300         vex_byte0_(0),
301         vex_byte1_(0),
302         vex_byte2_(0),
303         byte_size_operand_(false),
304         instruction_table_(instruction_table.Pointer()) {
305     tmp_buffer_[0] = '\0';
306   }
307
308   virtual ~DisassemblerX64() {
309   }
310
311   // Writes one disassembled instruction into 'buffer' (0-terminated).
312   // Returns the length of the disassembled machine instruction in bytes.
313   int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
314
315  private:
316   enum OperandSize {
317     OPERAND_BYTE_SIZE = 0,
318     OPERAND_WORD_SIZE = 1,
319     OPERAND_DOUBLEWORD_SIZE = 2,
320     OPERAND_QUADWORD_SIZE = 3
321   };
322
323   const NameConverter& converter_;
324   v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
325   unsigned int tmp_buffer_pos_;
326   bool abort_on_unimplemented_;
327   // Prefixes parsed
328   byte rex_;
329   byte operand_size_;  // 0x66 or (if no group 3 prefix is present) 0x0.
330   byte group_1_prefix_;  // 0xF2, 0xF3, or (if no group 1 prefix is present) 0.
331   byte vex_byte0_;       // 0xc4 or 0xc5
332   byte vex_byte1_;
333   byte vex_byte2_;  // only for 3 bytes vex prefix
334   // Byte size operand override.
335   bool byte_size_operand_;
336   const InstructionTable* const instruction_table_;
337
338   void setRex(byte rex) {
339     DCHECK_EQ(0x40, rex & 0xF0);
340     rex_ = rex;
341   }
342
343   bool rex() { return rex_ != 0; }
344
345   bool rex_b() { return (rex_ & 0x01) != 0; }
346
347   // Actual number of base register given the low bits and the rex.b state.
348   int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); }
349
350   bool rex_x() { return (rex_ & 0x02) != 0; }
351
352   bool rex_r() { return (rex_ & 0x04) != 0; }
353
354   bool rex_w() { return (rex_ & 0x08) != 0; }
355
356   bool vex_128() {
357     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
358     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
359     return (checked & 4) != 1;
360   }
361
362   bool vex_66() {
363     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
364     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
365     return (checked & 3) == 1;
366   }
367
368   bool vex_f3() {
369     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
370     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
371     return (checked & 3) == 2;
372   }
373
374   bool vex_f2() {
375     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
376     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
377     return (checked & 3) == 3;
378   }
379
380   bool vex_0f() {
381     if (vex_byte0_ == VEX2_PREFIX) return true;
382     return (vex_byte1_ & 3) == 1;
383   }
384
385   bool vex_0f38() {
386     if (vex_byte0_ == VEX2_PREFIX) return false;
387     return (vex_byte1_ & 3) == 2;
388   }
389
390   bool vex_0f3a() {
391     if (vex_byte0_ == VEX2_PREFIX) return false;
392     return (vex_byte1_ & 3) == 3;
393   }
394
395   int vex_vreg() {
396     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
397     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
398     return ~(checked >> 3) & 0xf;
399   }
400
401   OperandSize operand_size() {
402     if (byte_size_operand_) return OPERAND_BYTE_SIZE;
403     if (rex_w()) return OPERAND_QUADWORD_SIZE;
404     if (operand_size_ != 0) return OPERAND_WORD_SIZE;
405     return OPERAND_DOUBLEWORD_SIZE;
406   }
407
408   char operand_size_code() {
409     return "bwlq"[operand_size()];
410   }
411
412   char float_size_code() { return "sd"[rex_w()]; }
413
414   const char* NameOfCPURegister(int reg) const {
415     return converter_.NameOfCPURegister(reg);
416   }
417
418   const char* NameOfByteCPURegister(int reg) const {
419     return converter_.NameOfByteCPURegister(reg);
420   }
421
422   const char* NameOfXMMRegister(int reg) const {
423     return converter_.NameOfXMMRegister(reg);
424   }
425
426   const char* NameOfAddress(byte* addr) const {
427     return converter_.NameOfAddress(addr);
428   }
429
430   // Disassembler helper functions.
431   void get_modrm(byte data,
432                  int* mod,
433                  int* regop,
434                  int* rm) {
435     *mod = (data >> 6) & 3;
436     *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
437     *rm = (data & 7) | (rex_b() ? 8 : 0);
438   }
439
440   void get_sib(byte data,
441                int* scale,
442                int* index,
443                int* base) {
444     *scale = (data >> 6) & 3;
445     *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
446     *base = (data & 7) | (rex_b() ? 8 : 0);
447   }
448
449   typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const;
450
451   int PrintRightOperandHelper(byte* modrmp,
452                               RegisterNameMapping register_name);
453   int PrintRightOperand(byte* modrmp);
454   int PrintRightByteOperand(byte* modrmp);
455   int PrintRightXMMOperand(byte* modrmp);
456   int PrintOperands(const char* mnem,
457                     OperandType op_order,
458                     byte* data);
459   int PrintImmediate(byte* data, OperandSize size);
460   int PrintImmediateOp(byte* data);
461   const char* TwoByteMnemonic(byte opcode);
462   int TwoByteOpcodeInstruction(byte* data);
463   int F6F7Instruction(byte* data);
464   int ShiftInstruction(byte* data);
465   int JumpShort(byte* data);
466   int JumpConditional(byte* data);
467   int JumpConditionalShort(byte* data);
468   int SetCC(byte* data);
469   int FPUInstruction(byte* data);
470   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
471   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
472   int AVXInstruction(byte* data);
473   void AppendToBuffer(const char* format, ...);
474
475   void UnimplementedInstruction() {
476     if (abort_on_unimplemented_) {
477       CHECK(false);
478     } else {
479       AppendToBuffer("'Unimplemented Instruction'");
480     }
481   }
482 };
483
484
485 void DisassemblerX64::AppendToBuffer(const char* format, ...) {
486   v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
487   va_list args;
488   va_start(args, format);
489   int result = v8::internal::VSNPrintF(buf, format, args);
490   va_end(args);
491   tmp_buffer_pos_ += result;
492 }
493
494
495 int DisassemblerX64::PrintRightOperandHelper(
496     byte* modrmp,
497     RegisterNameMapping direct_register_name) {
498   int mod, regop, rm;
499   get_modrm(*modrmp, &mod, &regop, &rm);
500   RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
501       &DisassemblerX64::NameOfCPURegister;
502   switch (mod) {
503     case 0:
504       if ((rm & 7) == 5) {
505         int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1);
506         AppendToBuffer("[rip+0x%x]", disp);
507         return 5;
508       } else if ((rm & 7) == 4) {
509         // Codes for SIB byte.
510         byte sib = *(modrmp + 1);
511         int scale, index, base;
512         get_sib(sib, &scale, &index, &base);
513         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
514           // index == rsp means no index. Only use sib byte with no index for
515           // rsp and r12 base.
516           AppendToBuffer("[%s]", NameOfCPURegister(base));
517           return 2;
518         } else if (base == 5) {
519           // base == rbp means no base register (when mod == 0).
520           int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
521           AppendToBuffer("[%s*%d%s0x%x]",
522                          NameOfCPURegister(index),
523                          1 << scale,
524                          disp < 0 ? "-" : "+",
525                          disp < 0 ? -disp : disp);
526           return 6;
527         } else if (index != 4 && base != 5) {
528           // [base+index*scale]
529           AppendToBuffer("[%s+%s*%d]",
530                          NameOfCPURegister(base),
531                          NameOfCPURegister(index),
532                          1 << scale);
533           return 2;
534         } else {
535           UnimplementedInstruction();
536           return 1;
537         }
538       } else {
539         AppendToBuffer("[%s]", NameOfCPURegister(rm));
540         return 1;
541       }
542       break;
543     case 1:  // fall through
544     case 2:
545       if ((rm & 7) == 4) {
546         byte sib = *(modrmp + 1);
547         int scale, index, base;
548         get_sib(sib, &scale, &index, &base);
549         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
550                               : *reinterpret_cast<int8_t*>(modrmp + 2);
551         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
552           AppendToBuffer("[%s%s0x%x]",
553                          NameOfCPURegister(base),
554                          disp < 0 ? "-" : "+",
555                          disp < 0 ? -disp : disp);
556         } else {
557           AppendToBuffer("[%s+%s*%d%s0x%x]",
558                          NameOfCPURegister(base),
559                          NameOfCPURegister(index),
560                          1 << scale,
561                          disp < 0 ? "-" : "+",
562                          disp < 0 ? -disp : disp);
563         }
564         return mod == 2 ? 6 : 3;
565       } else {
566         // No sib.
567         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
568                               : *reinterpret_cast<int8_t*>(modrmp + 1);
569         AppendToBuffer("[%s%s0x%x]",
570                        NameOfCPURegister(rm),
571                        disp < 0 ? "-" : "+",
572                        disp < 0 ? -disp : disp);
573         return (mod == 2) ? 5 : 2;
574       }
575       break;
576     case 3:
577       AppendToBuffer("%s", (this->*register_name)(rm));
578       return 1;
579     default:
580       UnimplementedInstruction();
581       return 1;
582   }
583   UNREACHABLE();
584 }
585
586
587 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
588   int64_t value;
589   int count;
590   switch (size) {
591     case OPERAND_BYTE_SIZE:
592       value = *data;
593       count = 1;
594       break;
595     case OPERAND_WORD_SIZE:
596       value = *reinterpret_cast<int16_t*>(data);
597       count = 2;
598       break;
599     case OPERAND_DOUBLEWORD_SIZE:
600       value = *reinterpret_cast<uint32_t*>(data);
601       count = 4;
602       break;
603     case OPERAND_QUADWORD_SIZE:
604       value = *reinterpret_cast<int32_t*>(data);
605       count = 4;
606       break;
607     default:
608       UNREACHABLE();
609       value = 0;  // Initialize variables on all paths to satisfy the compiler.
610       count = 0;
611   }
612   AppendToBuffer("%" V8_PTR_PREFIX "x", value);
613   return count;
614 }
615
616
617 int DisassemblerX64::PrintRightOperand(byte* modrmp) {
618   return PrintRightOperandHelper(modrmp,
619                                  &DisassemblerX64::NameOfCPURegister);
620 }
621
622
623 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
624   return PrintRightOperandHelper(modrmp,
625                                  &DisassemblerX64::NameOfByteCPURegister);
626 }
627
628
629 int DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
630   return PrintRightOperandHelper(modrmp,
631                                  &DisassemblerX64::NameOfXMMRegister);
632 }
633
634
635 // Returns number of bytes used including the current *data.
636 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
637 int DisassemblerX64::PrintOperands(const char* mnem,
638                                    OperandType op_order,
639                                    byte* data) {
640   byte modrm = *data;
641   int mod, regop, rm;
642   get_modrm(modrm, &mod, &regop, &rm);
643   int advance = 0;
644   const char* register_name =
645       byte_size_operand_ ? NameOfByteCPURegister(regop)
646                          : NameOfCPURegister(regop);
647   switch (op_order) {
648     case REG_OPER_OP_ORDER: {
649       AppendToBuffer("%s%c %s,",
650                      mnem,
651                      operand_size_code(),
652                      register_name);
653       advance = byte_size_operand_ ? PrintRightByteOperand(data)
654                                    : PrintRightOperand(data);
655       break;
656     }
657     case OPER_REG_OP_ORDER: {
658       AppendToBuffer("%s%c ", mnem, operand_size_code());
659       advance = byte_size_operand_ ? PrintRightByteOperand(data)
660                                    : PrintRightOperand(data);
661       AppendToBuffer(",%s", register_name);
662       break;
663     }
664     default:
665       UNREACHABLE();
666       break;
667   }
668   return advance;
669 }
670
671
672 // Returns number of bytes used by machine instruction, including *data byte.
673 // Writes immediate instructions to 'tmp_buffer_'.
674 int DisassemblerX64::PrintImmediateOp(byte* data) {
675   bool byte_size_immediate = (*data & 0x02) != 0;
676   byte modrm = *(data + 1);
677   int mod, regop, rm;
678   get_modrm(modrm, &mod, &regop, &rm);
679   const char* mnem = "Imm???";
680   switch (regop) {
681     case 0:
682       mnem = "add";
683       break;
684     case 1:
685       mnem = "or";
686       break;
687     case 2:
688       mnem = "adc";
689       break;
690     case 3:
691       mnem = "sbb";
692       break;
693     case 4:
694       mnem = "and";
695       break;
696     case 5:
697       mnem = "sub";
698       break;
699     case 6:
700       mnem = "xor";
701       break;
702     case 7:
703       mnem = "cmp";
704       break;
705     default:
706       UnimplementedInstruction();
707   }
708   AppendToBuffer("%s%c ", mnem, operand_size_code());
709   int count = PrintRightOperand(data + 1);
710   AppendToBuffer(",0x");
711   OperandSize immediate_size =
712       byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
713   count += PrintImmediate(data + 1 + count, immediate_size);
714   return 1 + count;
715 }
716
717
718 // Returns number of bytes used, including *data.
719 int DisassemblerX64::F6F7Instruction(byte* data) {
720   DCHECK(*data == 0xF7 || *data == 0xF6);
721   byte modrm = *(data + 1);
722   int mod, regop, rm;
723   get_modrm(modrm, &mod, &regop, &rm);
724   if (mod == 3 && regop != 0) {
725     const char* mnem = NULL;
726     switch (regop) {
727       case 2:
728         mnem = "not";
729         break;
730       case 3:
731         mnem = "neg";
732         break;
733       case 4:
734         mnem = "mul";
735         break;
736       case 5:
737         mnem = "imul";
738         break;
739       case 6:
740         mnem = "div";
741         break;
742       case 7:
743         mnem = "idiv";
744         break;
745       default:
746         UnimplementedInstruction();
747     }
748     AppendToBuffer("%s%c %s",
749                    mnem,
750                    operand_size_code(),
751                    NameOfCPURegister(rm));
752     return 2;
753   } else if (regop == 0) {
754     AppendToBuffer("test%c ", operand_size_code());
755     int count = PrintRightOperand(data + 1);  // Use name of 64-bit register.
756     AppendToBuffer(",0x");
757     count += PrintImmediate(data + 1 + count, operand_size());
758     return 1 + count;
759   } else {
760     UnimplementedInstruction();
761     return 2;
762   }
763 }
764
765
766 int DisassemblerX64::ShiftInstruction(byte* data) {
767   byte op = *data & (~1);
768   int count = 1;
769   if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
770     UnimplementedInstruction();
771     return count;
772   }
773   // Print mneumonic.
774   {
775     byte modrm = *(data + count);
776     int mod, regop, rm;
777     get_modrm(modrm, &mod, &regop, &rm);
778     regop &= 0x7;  // The REX.R bit does not affect the operation.
779     const char* mnem = NULL;
780     switch (regop) {
781       case 0:
782         mnem = "rol";
783         break;
784       case 1:
785         mnem = "ror";
786         break;
787       case 2:
788         mnem = "rcl";
789         break;
790       case 3:
791         mnem = "rcr";
792         break;
793       case 4:
794         mnem = "shl";
795         break;
796       case 5:
797         mnem = "shr";
798         break;
799       case 7:
800         mnem = "sar";
801         break;
802       default:
803         UnimplementedInstruction();
804         return count + 1;
805     }
806     DCHECK_NOT_NULL(mnem);
807     AppendToBuffer("%s%c ", mnem, operand_size_code());
808   }
809   count += PrintRightOperand(data + count);
810   if (op == 0xD2) {
811     AppendToBuffer(", cl");
812   } else {
813     int imm8 = -1;
814     if (op == 0xD0) {
815       imm8 = 1;
816     } else {
817       DCHECK_EQ(0xC0, op);
818       imm8 = *(data + count);
819       count++;
820     }
821     AppendToBuffer(", %d", imm8);
822   }
823   return count;
824 }
825
826
827 // Returns number of bytes used, including *data.
828 int DisassemblerX64::JumpShort(byte* data) {
829   DCHECK_EQ(0xEB, *data);
830   byte b = *(data + 1);
831   byte* dest = data + static_cast<int8_t>(b) + 2;
832   AppendToBuffer("jmp %s", NameOfAddress(dest));
833   return 2;
834 }
835
836
837 // Returns number of bytes used, including *data.
838 int DisassemblerX64::JumpConditional(byte* data) {
839   DCHECK_EQ(0x0F, *data);
840   byte cond = *(data + 1) & 0x0F;
841   byte* dest = data + *reinterpret_cast<int32_t*>(data + 2) + 6;
842   const char* mnem = conditional_code_suffix[cond];
843   AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
844   return 6;  // includes 0x0F
845 }
846
847
848 // Returns number of bytes used, including *data.
849 int DisassemblerX64::JumpConditionalShort(byte* data) {
850   byte cond = *data & 0x0F;
851   byte b = *(data + 1);
852   byte* dest = data + static_cast<int8_t>(b) + 2;
853   const char* mnem = conditional_code_suffix[cond];
854   AppendToBuffer("j%s %s", mnem, NameOfAddress(dest));
855   return 2;
856 }
857
858
859 // Returns number of bytes used, including *data.
860 int DisassemblerX64::SetCC(byte* data) {
861   DCHECK_EQ(0x0F, *data);
862   byte cond = *(data + 1) & 0x0F;
863   const char* mnem = conditional_code_suffix[cond];
864   AppendToBuffer("set%s%c ", mnem, operand_size_code());
865   PrintRightByteOperand(data + 2);
866   return 3;  // includes 0x0F
867 }
868
869
870 int DisassemblerX64::AVXInstruction(byte* data) {
871   byte opcode = *data;
872   byte* current = data + 1;
873   if (vex_66() && vex_0f38()) {
874     int mod, regop, rm, vvvv = vex_vreg();
875     get_modrm(*current, &mod, &regop, &rm);
876     switch (opcode) {
877       case 0x99:
878         AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
879                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
880         current += PrintRightXMMOperand(current);
881         break;
882       case 0xa9:
883         AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
884                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
885         current += PrintRightXMMOperand(current);
886         break;
887       case 0xb9:
888         AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
889                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
890         current += PrintRightXMMOperand(current);
891         break;
892       case 0x9b:
893         AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
894                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
895         current += PrintRightXMMOperand(current);
896         break;
897       case 0xab:
898         AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
899                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
900         current += PrintRightXMMOperand(current);
901         break;
902       case 0xbb:
903         AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
904                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
905         current += PrintRightXMMOperand(current);
906         break;
907       case 0x9d:
908         AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
909                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
910         current += PrintRightXMMOperand(current);
911         break;
912       case 0xad:
913         AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
914                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
915         current += PrintRightXMMOperand(current);
916         break;
917       case 0xbd:
918         AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
919                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
920         current += PrintRightXMMOperand(current);
921         break;
922       case 0x9f:
923         AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
924                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
925         current += PrintRightXMMOperand(current);
926         break;
927       case 0xaf:
928         AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
929                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
930         current += PrintRightXMMOperand(current);
931         break;
932       case 0xbf:
933         AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
934                        NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
935         current += PrintRightXMMOperand(current);
936         break;
937       default:
938         UnimplementedInstruction();
939     }
940   } else if (vex_f2() && vex_0f()) {
941     int mod, regop, rm, vvvv = vex_vreg();
942     get_modrm(*current, &mod, &regop, &rm);
943     switch (opcode) {
944       case 0x58:
945         AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
946                        NameOfXMMRegister(vvvv));
947         current += PrintRightXMMOperand(current);
948         break;
949       case 0x59:
950         AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
951                        NameOfXMMRegister(vvvv));
952         current += PrintRightXMMOperand(current);
953         break;
954       case 0x5c:
955         AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
956                        NameOfXMMRegister(vvvv));
957         current += PrintRightXMMOperand(current);
958         break;
959       case 0x5d:
960         AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop),
961                        NameOfXMMRegister(vvvv));
962         current += PrintRightXMMOperand(current);
963         break;
964       case 0x5e:
965         AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
966                        NameOfXMMRegister(vvvv));
967         current += PrintRightXMMOperand(current);
968         break;
969       case 0x5f:
970         AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop),
971                        NameOfXMMRegister(vvvv));
972         current += PrintRightXMMOperand(current);
973         break;
974       default:
975         UnimplementedInstruction();
976     }
977   } else {
978     UnimplementedInstruction();
979   }
980
981   return static_cast<int>(current - data);
982 }
983
984
985 // Returns number of bytes used, including *data.
986 int DisassemblerX64::FPUInstruction(byte* data) {
987   byte escape_opcode = *data;
988   DCHECK_EQ(0xD8, escape_opcode & 0xF8);
989   byte modrm_byte = *(data+1);
990
991   if (modrm_byte >= 0xC0) {
992     return RegisterFPUInstruction(escape_opcode, modrm_byte);
993   } else {
994     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
995   }
996 }
997
998 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode,
999                                            int modrm_byte,
1000                                            byte* modrm_start) {
1001   const char* mnem = "?";
1002   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
1003   switch (escape_opcode) {
1004     case 0xD9: switch (regop) {
1005         case 0: mnem = "fld_s"; break;
1006         case 3: mnem = "fstp_s"; break;
1007         case 7: mnem = "fstcw"; break;
1008         default: UnimplementedInstruction();
1009       }
1010       break;
1011
1012     case 0xDB: switch (regop) {
1013         case 0: mnem = "fild_s"; break;
1014         case 1: mnem = "fisttp_s"; break;
1015         case 2: mnem = "fist_s"; break;
1016         case 3: mnem = "fistp_s"; break;
1017         default: UnimplementedInstruction();
1018       }
1019       break;
1020
1021     case 0xDD: switch (regop) {
1022         case 0: mnem = "fld_d"; break;
1023         case 3: mnem = "fstp_d"; break;
1024         default: UnimplementedInstruction();
1025       }
1026       break;
1027
1028     case 0xDF: switch (regop) {
1029         case 5: mnem = "fild_d"; break;
1030         case 7: mnem = "fistp_d"; break;
1031         default: UnimplementedInstruction();
1032       }
1033       break;
1034
1035     default: UnimplementedInstruction();
1036   }
1037   AppendToBuffer("%s ", mnem);
1038   int count = PrintRightOperand(modrm_start);
1039   return count + 1;
1040 }
1041
1042 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode,
1043                                              byte modrm_byte) {
1044   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
1045   const char* mnem = "?";
1046
1047   switch (escape_opcode) {
1048     case 0xD8:
1049       UnimplementedInstruction();
1050       break;
1051
1052     case 0xD9:
1053       switch (modrm_byte & 0xF8) {
1054         case 0xC0:
1055           mnem = "fld";
1056           has_register = true;
1057           break;
1058         case 0xC8:
1059           mnem = "fxch";
1060           has_register = true;
1061           break;
1062         default:
1063           switch (modrm_byte) {
1064             case 0xE0: mnem = "fchs"; break;
1065             case 0xE1: mnem = "fabs"; break;
1066             case 0xE3: mnem = "fninit"; break;
1067             case 0xE4: mnem = "ftst"; break;
1068             case 0xE8: mnem = "fld1"; break;
1069             case 0xEB: mnem = "fldpi"; break;
1070             case 0xED: mnem = "fldln2"; break;
1071             case 0xEE: mnem = "fldz"; break;
1072             case 0xF0: mnem = "f2xm1"; break;
1073             case 0xF1: mnem = "fyl2x"; break;
1074             case 0xF2: mnem = "fptan"; break;
1075             case 0xF5: mnem = "fprem1"; break;
1076             case 0xF7: mnem = "fincstp"; break;
1077             case 0xF8: mnem = "fprem"; break;
1078             case 0xFC: mnem = "frndint"; break;
1079             case 0xFD: mnem = "fscale"; break;
1080             case 0xFE: mnem = "fsin"; break;
1081             case 0xFF: mnem = "fcos"; break;
1082             default: UnimplementedInstruction();
1083           }
1084       }
1085       break;
1086
1087     case 0xDA:
1088       if (modrm_byte == 0xE9) {
1089         mnem = "fucompp";
1090       } else {
1091         UnimplementedInstruction();
1092       }
1093       break;
1094
1095     case 0xDB:
1096       if ((modrm_byte & 0xF8) == 0xE8) {
1097         mnem = "fucomi";
1098         has_register = true;
1099       } else if (modrm_byte  == 0xE2) {
1100         mnem = "fclex";
1101       } else if (modrm_byte == 0xE3) {
1102         mnem = "fninit";
1103       } else {
1104         UnimplementedInstruction();
1105       }
1106       break;
1107
1108     case 0xDC:
1109       has_register = true;
1110       switch (modrm_byte & 0xF8) {
1111         case 0xC0: mnem = "fadd"; break;
1112         case 0xE8: mnem = "fsub"; break;
1113         case 0xC8: mnem = "fmul"; break;
1114         case 0xF8: mnem = "fdiv"; break;
1115         default: UnimplementedInstruction();
1116       }
1117       break;
1118
1119     case 0xDD:
1120       has_register = true;
1121       switch (modrm_byte & 0xF8) {
1122         case 0xC0: mnem = "ffree"; break;
1123         case 0xD8: mnem = "fstp"; break;
1124         default: UnimplementedInstruction();
1125       }
1126       break;
1127
1128     case 0xDE:
1129       if (modrm_byte  == 0xD9) {
1130         mnem = "fcompp";
1131       } else {
1132         has_register = true;
1133         switch (modrm_byte & 0xF8) {
1134           case 0xC0: mnem = "faddp"; break;
1135           case 0xE8: mnem = "fsubp"; break;
1136           case 0xC8: mnem = "fmulp"; break;
1137           case 0xF8: mnem = "fdivp"; break;
1138           default: UnimplementedInstruction();
1139         }
1140       }
1141       break;
1142
1143     case 0xDF:
1144       if (modrm_byte == 0xE0) {
1145         mnem = "fnstsw_ax";
1146       } else if ((modrm_byte & 0xF8) == 0xE8) {
1147         mnem = "fucomip";
1148         has_register = true;
1149       }
1150       break;
1151
1152     default: UnimplementedInstruction();
1153   }
1154
1155   if (has_register) {
1156     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
1157   } else {
1158     AppendToBuffer("%s", mnem);
1159   }
1160   return 2;
1161 }
1162
1163
1164
1165 // Handle all two-byte opcodes, which start with 0x0F.
1166 // These instructions may be affected by an 0x66, 0xF2, or 0xF3 prefix.
1167 // We do not use any three-byte opcodes, which start with 0x0F38 or 0x0F3A.
1168 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
1169   byte opcode = *(data + 1);
1170   byte* current = data + 2;
1171   // At return, "current" points to the start of the next instruction.
1172   const char* mnemonic = TwoByteMnemonic(opcode);
1173   if (operand_size_ == 0x66) {
1174     // 0x66 0x0F prefix.
1175     int mod, regop, rm;
1176     if (opcode == 0x3A) {
1177       byte third_byte = *current;
1178       current = data + 3;
1179       if (third_byte == 0x17) {
1180         get_modrm(*current, &mod, &regop, &rm);
1181         AppendToBuffer("extractps ");  // reg/m32, xmm, imm8
1182         current += PrintRightOperand(current);
1183         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1184         current += 1;
1185       } else if (third_byte == 0x0b) {
1186         get_modrm(*current, &mod, &regop, &rm);
1187          // roundsd xmm, xmm/m64, imm8
1188         AppendToBuffer("roundsd %s,", NameOfXMMRegister(regop));
1189         current += PrintRightXMMOperand(current);
1190         AppendToBuffer(",%d", (*current) & 3);
1191         current += 1;
1192       } else if (third_byte == 0x16) {
1193         get_modrm(*current, &mod, &regop, &rm);
1194         AppendToBuffer("pextrd ");  // reg/m32, xmm, imm8
1195         current += PrintRightOperand(current);
1196         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1197         current += 1;
1198       } else if (third_byte == 0x22) {
1199         get_modrm(*current, &mod, &regop, &rm);
1200         AppendToBuffer("pinsrd ");  // xmm, reg/m32, imm8
1201         AppendToBuffer(" %s,", NameOfXMMRegister(regop));
1202         current += PrintRightOperand(current);
1203         AppendToBuffer(",%d", (*current) & 3);
1204         current += 1;
1205       } else {
1206         UnimplementedInstruction();
1207       }
1208     } else {
1209       get_modrm(*current, &mod, &regop, &rm);
1210       if (opcode == 0x1f) {
1211         current++;
1212         if (rm == 4) {  // SIB byte present.
1213           current++;
1214         }
1215         if (mod == 1) {  // Byte displacement.
1216           current += 1;
1217         } else if (mod == 2) {  // 32-bit displacement.
1218           current += 4;
1219         }  // else no immediate displacement.
1220         AppendToBuffer("nop");
1221       } else if (opcode == 0x28) {
1222         AppendToBuffer("movapd %s,", NameOfXMMRegister(regop));
1223         current += PrintRightXMMOperand(current);
1224       } else if (opcode == 0x29) {
1225         AppendToBuffer("movapd ");
1226         current += PrintRightXMMOperand(current);
1227         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1228       } else if (opcode == 0x6E) {
1229         AppendToBuffer("mov%c %s,",
1230                        rex_w() ? 'q' : 'd',
1231                        NameOfXMMRegister(regop));
1232         current += PrintRightOperand(current);
1233       } else if (opcode == 0x6F) {
1234         AppendToBuffer("movdqa %s,",
1235                        NameOfXMMRegister(regop));
1236         current += PrintRightXMMOperand(current);
1237       } else if (opcode == 0x7E) {
1238         AppendToBuffer("mov%c ",
1239                        rex_w() ? 'q' : 'd');
1240         current += PrintRightOperand(current);
1241         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1242       } else if (opcode == 0x7F) {
1243         AppendToBuffer("movdqa ");
1244         current += PrintRightXMMOperand(current);
1245         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1246       } else if (opcode == 0xD6) {
1247         AppendToBuffer("movq ");
1248         current += PrintRightXMMOperand(current);
1249         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1250       } else if (opcode == 0x50) {
1251         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
1252         current += PrintRightXMMOperand(current);
1253       } else if (opcode == 0x72) {
1254         current += 1;
1255         AppendToBuffer("%s %s,%d", (regop == 6) ? "pslld" : "psrld",
1256                        NameOfXMMRegister(rm), *current & 0x7f);
1257         current += 1;
1258       } else if (opcode == 0x73) {
1259         current += 1;
1260         AppendToBuffer("%s %s,%d", (regop == 6) ? "psllq" : "psrlq",
1261                        NameOfXMMRegister(rm), *current & 0x7f);
1262         current += 1;
1263       } else {
1264         const char* mnemonic = "?";
1265         if (opcode == 0x54) {
1266           mnemonic = "andpd";
1267         } else  if (opcode == 0x56) {
1268           mnemonic = "orpd";
1269         } else  if (opcode == 0x57) {
1270           mnemonic = "xorpd";
1271         } else if (opcode == 0x2E) {
1272           mnemonic = "ucomisd";
1273         } else if (opcode == 0x2F) {
1274           mnemonic = "comisd";
1275         } else if (opcode == 0x76) {
1276           mnemonic = "pcmpeqd";
1277         } else if (opcode == 0x62) {
1278           mnemonic = "punpckldq";
1279         } else if (opcode == 0x6A) {
1280           mnemonic = "punpckhdq";
1281         } else {
1282           UnimplementedInstruction();
1283         }
1284         AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1285         current += PrintRightXMMOperand(current);
1286       }
1287     }
1288   } else if (group_1_prefix_ == 0xF2) {
1289     // Beginning of instructions with prefix 0xF2.
1290
1291     if (opcode == 0x11 || opcode == 0x10) {
1292       // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
1293       AppendToBuffer("movsd ");
1294       int mod, regop, rm;
1295       get_modrm(*current, &mod, &regop, &rm);
1296       if (opcode == 0x11) {
1297         current += PrintRightXMMOperand(current);
1298         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1299       } else {
1300         AppendToBuffer("%s,", NameOfXMMRegister(regop));
1301         current += PrintRightXMMOperand(current);
1302       }
1303     } else if (opcode == 0x2A) {
1304       // CVTSI2SD: integer to XMM double conversion.
1305       int mod, regop, rm;
1306       get_modrm(*current, &mod, &regop, &rm);
1307       AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
1308       current += PrintRightOperand(current);
1309     } else if (opcode == 0x2C) {
1310       // CVTTSD2SI:
1311       // Convert with truncation scalar double-precision FP to integer.
1312       int mod, regop, rm;
1313       get_modrm(*current, &mod, &regop, &rm);
1314       AppendToBuffer("cvttsd2si%c %s,",
1315           operand_size_code(), NameOfCPURegister(regop));
1316       current += PrintRightXMMOperand(current);
1317     } else if (opcode == 0x2D) {
1318       // CVTSD2SI: Convert scalar double-precision FP to integer.
1319       int mod, regop, rm;
1320       get_modrm(*current, &mod, &regop, &rm);
1321       AppendToBuffer("cvtsd2si%c %s,",
1322           operand_size_code(), NameOfCPURegister(regop));
1323       current += PrintRightXMMOperand(current);
1324     } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1325       // XMM arithmetic. Mnemonic was retrieved at the start of this function.
1326       int mod, regop, rm;
1327       get_modrm(*current, &mod, &regop, &rm);
1328       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
1329       current += PrintRightXMMOperand(current);
1330     } else if (opcode == 0xC2) {
1331       // Intel manual 2A, Table 3-18.
1332       int mod, regop, rm;
1333       get_modrm(*current, &mod, &regop, &rm);
1334       const char* const pseudo_op[] = {
1335         "cmpeqsd",
1336         "cmpltsd",
1337         "cmplesd",
1338         "cmpunordsd",
1339         "cmpneqsd",
1340         "cmpnltsd",
1341         "cmpnlesd",
1342         "cmpordsd"
1343       };
1344       AppendToBuffer("%s %s,%s",
1345                      pseudo_op[current[1]],
1346                      NameOfXMMRegister(regop),
1347                      NameOfXMMRegister(rm));
1348       current += 2;
1349     } else {
1350       UnimplementedInstruction();
1351     }
1352   } else if (group_1_prefix_ == 0xF3) {
1353     // Instructions with prefix 0xF3.
1354     if (opcode == 0x11 || opcode == 0x10) {
1355       // MOVSS: Move scalar double-precision fp to/from/between XMM registers.
1356       AppendToBuffer("movss ");
1357       int mod, regop, rm;
1358       get_modrm(*current, &mod, &regop, &rm);
1359       if (opcode == 0x11) {
1360         current += PrintRightOperand(current);
1361         AppendToBuffer(",%s", NameOfXMMRegister(regop));
1362       } else {
1363         AppendToBuffer("%s,", NameOfXMMRegister(regop));
1364         current += PrintRightOperand(current);
1365       }
1366     } else if (opcode == 0x2A) {
1367       // CVTSI2SS: integer to XMM single conversion.
1368       int mod, regop, rm;
1369       get_modrm(*current, &mod, &regop, &rm);
1370       AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
1371       current += PrintRightOperand(current);
1372     } else if (opcode == 0x2C) {
1373       // CVTTSS2SI:
1374       // Convert with truncation scalar single-precision FP to dword integer.
1375       int mod, regop, rm;
1376       get_modrm(*current, &mod, &regop, &rm);
1377       AppendToBuffer("cvttss2si%c %s,",
1378           operand_size_code(), NameOfCPURegister(regop));
1379       current += PrintRightXMMOperand(current);
1380     } else if (opcode == 0x58) {
1381       int mod, regop, rm;
1382       get_modrm(*current, &mod, &regop, &rm);
1383       AppendToBuffer("addss %s,", NameOfXMMRegister(regop));
1384       current += PrintRightXMMOperand(current);
1385     } else if (opcode == 0x59) {
1386       int mod, regop, rm;
1387       get_modrm(*current, &mod, &regop, &rm);
1388       AppendToBuffer("mulss %s,", NameOfXMMRegister(regop));
1389       current += PrintRightXMMOperand(current);
1390     } else if (opcode == 0x5A) {
1391       // CVTSS2SD:
1392       // Convert scalar single-precision FP to scalar double-precision FP.
1393       int mod, regop, rm;
1394       get_modrm(*current, &mod, &regop, &rm);
1395       AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1396       current += PrintRightXMMOperand(current);
1397     } else if (opcode == 0x5c) {
1398       int mod, regop, rm;
1399       get_modrm(*current, &mod, &regop, &rm);
1400       AppendToBuffer("subss %s,", NameOfXMMRegister(regop));
1401       current += PrintRightXMMOperand(current);
1402     } else if (opcode == 0x5e) {
1403       int mod, regop, rm;
1404       get_modrm(*current, &mod, &regop, &rm);
1405       AppendToBuffer("divss %s,", NameOfXMMRegister(regop));
1406       current += PrintRightXMMOperand(current);
1407     } else if (opcode == 0x7E) {
1408       int mod, regop, rm;
1409       get_modrm(*current, &mod, &regop, &rm);
1410       AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
1411       current += PrintRightXMMOperand(current);
1412     } else {
1413       UnimplementedInstruction();
1414     }
1415   } else if (opcode == 0x1F) {
1416     // NOP
1417     int mod, regop, rm;
1418     get_modrm(*current, &mod, &regop, &rm);
1419     current++;
1420     if (rm == 4) {  // SIB byte present.
1421       current++;
1422     }
1423     if (mod == 1) {  // Byte displacement.
1424       current += 1;
1425     } else if (mod == 2) {  // 32-bit displacement.
1426       current += 4;
1427     }  // else no immediate displacement.
1428     AppendToBuffer("nop");
1429
1430   } else if (opcode == 0x28) {
1431     // movaps xmm, xmm/m128
1432     int mod, regop, rm;
1433     get_modrm(*current, &mod, &regop, &rm);
1434     AppendToBuffer("movaps %s,", NameOfXMMRegister(regop));
1435     current += PrintRightXMMOperand(current);
1436
1437   } else if (opcode == 0x29) {
1438     // movaps xmm/m128, xmm
1439     int mod, regop, rm;
1440     get_modrm(*current, &mod, &regop, &rm);
1441     AppendToBuffer("movaps ");
1442     current += PrintRightXMMOperand(current);
1443     AppendToBuffer(",%s", NameOfXMMRegister(regop));
1444
1445   } else if (opcode == 0x2e) {
1446     int mod, regop, rm;
1447     get_modrm(*current, &mod, &regop, &rm);
1448     AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
1449     current += PrintRightXMMOperand(current);
1450   } else if (opcode == 0xA2) {
1451     // CPUID
1452     AppendToBuffer("%s", mnemonic);
1453
1454   } else if ((opcode & 0xF0) == 0x40) {
1455     // CMOVcc: conditional move.
1456     int condition = opcode & 0x0F;
1457     const InstructionDesc& idesc = cmov_instructions[condition];
1458     byte_size_operand_ = idesc.byte_size_operation;
1459     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1460
1461   } else if (opcode >= 0x53 && opcode <= 0x5F) {
1462     const char* const pseudo_op[] = {
1463       "rcpps",
1464       "andps",
1465       "andnps",
1466       "orps",
1467       "xorps",
1468       "addps",
1469       "mulps",
1470       "cvtps2pd",
1471       "cvtdq2ps",
1472       "subps",
1473       "minps",
1474       "divps",
1475       "maxps",
1476     };
1477     int mod, regop, rm;
1478     get_modrm(*current, &mod, &regop, &rm);
1479     AppendToBuffer("%s %s,",
1480                    pseudo_op[opcode - 0x53],
1481                    NameOfXMMRegister(regop));
1482     current += PrintRightXMMOperand(current);
1483
1484   } else if (opcode == 0xC6) {
1485     // shufps xmm, xmm/m128, imm8
1486     int mod, regop, rm;
1487     get_modrm(*current, &mod, &regop, &rm);
1488     AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
1489     current += PrintRightXMMOperand(current);
1490     AppendToBuffer(", %d", (*current) & 3);
1491     current += 1;
1492
1493   } else if (opcode == 0x50) {
1494     // movmskps reg, xmm
1495     int mod, regop, rm;
1496     get_modrm(*current, &mod, &regop, &rm);
1497     AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
1498     current += PrintRightXMMOperand(current);
1499
1500   } else if ((opcode & 0xF0) == 0x80) {
1501     // Jcc: Conditional jump (branch).
1502     current = data + JumpConditional(data);
1503
1504   } else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1505              opcode == 0xB7 || opcode == 0xAF) {
1506     // Size-extending moves, IMUL.
1507     current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1508
1509   } else if ((opcode & 0xF0) == 0x90) {
1510     // SETcc: Set byte on condition. Needs pointer to beginning of instruction.
1511     current = data + SetCC(data);
1512
1513   } else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1514     // SHLD, SHRD (double-precision shift), BTS (bit set).
1515     AppendToBuffer("%s ", mnemonic);
1516     int mod, regop, rm;
1517     get_modrm(*current, &mod, &regop, &rm);
1518     current += PrintRightOperand(current);
1519     if (opcode == 0xAB) {
1520       AppendToBuffer(",%s", NameOfCPURegister(regop));
1521     } else {
1522       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1523     }
1524   } else if (opcode == 0xBD) {
1525     AppendToBuffer("%s%c ", mnemonic, operand_size_code());
1526     int mod, regop, rm;
1527     get_modrm(*current, &mod, &regop, &rm);
1528     AppendToBuffer("%s,", NameOfCPURegister(regop));
1529     current += PrintRightOperand(current);
1530   } else if (opcode == 0x0B) {
1531     AppendToBuffer("ud2");
1532   } else {
1533     UnimplementedInstruction();
1534   }
1535   return static_cast<int>(current - data);
1536 }
1537
1538
1539 // Mnemonics for two-byte opcode instructions starting with 0x0F.
1540 // The argument is the second byte of the two-byte opcode.
1541 // Returns NULL if the instruction is not handled here.
1542 const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
1543   switch (opcode) {
1544     case 0x1F:
1545       return "nop";
1546     case 0x2A:  // F2/F3 prefix.
1547       return "cvtsi2s";
1548     case 0x51:  // F2 prefix.
1549       return "sqrtsd";
1550     case 0x58:  // F2 prefix.
1551       return "addsd";
1552     case 0x59:  // F2 prefix.
1553       return "mulsd";
1554     case 0x5A:  // F2 prefix.
1555       return "cvtsd2ss";
1556     case 0x5D:  // F2 prefix.
1557       return "minsd";
1558     case 0x5C:  // F2 prefix.
1559       return "subsd";
1560     case 0x5E:  // F2 prefix.
1561       return "divsd";
1562     case 0x5F:  // F2 prefix.
1563       return "maxsd";
1564     case 0xA2:
1565       return "cpuid";
1566     case 0xA5:
1567       return "shld";
1568     case 0xAB:
1569       return "bts";
1570     case 0xAD:
1571       return "shrd";
1572     case 0xAF:
1573       return "imul";
1574     case 0xB6:
1575       return "movzxb";
1576     case 0xB7:
1577       return "movzxw";
1578     case 0xBD:
1579       return "bsr";
1580     case 0xBE:
1581       return "movsxb";
1582     case 0xBF:
1583       return "movsxw";
1584     default:
1585       return NULL;
1586   }
1587 }
1588
1589
1590 // Disassembles the instruction at instr, and writes it into out_buffer.
1591 int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
1592                                        byte* instr) {
1593   tmp_buffer_pos_ = 0;  // starting to write as position 0
1594   byte* data = instr;
1595   bool processed = true;  // Will be set to false if the current instruction
1596                           // is not in 'instructions' table.
1597   byte current;
1598
1599   // Scan for prefixes.
1600   while (true) {
1601     current = *data;
1602     if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {  // Group 3 prefix.
1603       operand_size_ = current;
1604     } else if ((current & 0xF0) == 0x40) {  // REX prefix.
1605       setRex(current);
1606       if (rex_w()) AppendToBuffer("REX.W ");
1607     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
1608       group_1_prefix_ = current;
1609     } else if (current == VEX3_PREFIX) {
1610       vex_byte0_ = current;
1611       vex_byte1_ = *(data + 1);
1612       vex_byte2_ = *(data + 2);
1613       setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
1614       data += 2;
1615     } else if (current == VEX2_PREFIX) {
1616       vex_byte0_ = current;
1617       vex_byte1_ = *(data + 1);
1618       setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
1619       data++;
1620     } else {  // Not a prefix - an opcode.
1621       break;
1622     }
1623     data++;
1624   }
1625
1626   // Decode AVX instructions.
1627   if (vex_byte0_ != 0) {
1628     processed = true;
1629     data += AVXInstruction(data);
1630   } else {
1631     const InstructionDesc& idesc = instruction_table_->Get(current);
1632     byte_size_operand_ = idesc.byte_size_operation;
1633     switch (idesc.type) {
1634       case ZERO_OPERANDS_INSTR:
1635         if (current >= 0xA4 && current <= 0xA7) {
1636           // String move or compare operations.
1637           if (group_1_prefix_ == REP_PREFIX) {
1638             // REP.
1639             AppendToBuffer("rep ");
1640           }
1641           if (rex_w()) AppendToBuffer("REX.W ");
1642           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
1643         } else {
1644           AppendToBuffer("%s", idesc.mnem, operand_size_code());
1645         }
1646         data++;
1647         break;
1648
1649       case TWO_OPERANDS_INSTR:
1650         data++;
1651         data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1652         break;
1653
1654       case JUMP_CONDITIONAL_SHORT_INSTR:
1655         data += JumpConditionalShort(data);
1656         break;
1657
1658       case REGISTER_INSTR:
1659         AppendToBuffer("%s%c %s", idesc.mnem, operand_size_code(),
1660                        NameOfCPURegister(base_reg(current & 0x07)));
1661         data++;
1662         break;
1663       case PUSHPOP_INSTR:
1664         AppendToBuffer("%s %s", idesc.mnem,
1665                        NameOfCPURegister(base_reg(current & 0x07)));
1666         data++;
1667         break;
1668       case MOVE_REG_INSTR: {
1669         byte* addr = NULL;
1670         switch (operand_size()) {
1671           case OPERAND_WORD_SIZE:
1672             addr =
1673                 reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1));
1674             data += 3;
1675             break;
1676           case OPERAND_DOUBLEWORD_SIZE:
1677             addr =
1678                 reinterpret_cast<byte*>(*reinterpret_cast<uint32_t*>(data + 1));
1679             data += 5;
1680             break;
1681           case OPERAND_QUADWORD_SIZE:
1682             addr =
1683                 reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1));
1684             data += 9;
1685             break;
1686           default:
1687             UNREACHABLE();
1688         }
1689         AppendToBuffer("mov%c %s,%s", operand_size_code(),
1690                        NameOfCPURegister(base_reg(current & 0x07)),
1691                        NameOfAddress(addr));
1692         break;
1693       }
1694
1695       case CALL_JUMP_INSTR: {
1696         byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1697         AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1698         data += 5;
1699         break;
1700       }
1701
1702       case SHORT_IMMEDIATE_INSTR: {
1703         byte* addr =
1704             reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1705         AppendToBuffer("%s rax,%s", idesc.mnem, NameOfAddress(addr));
1706         data += 5;
1707         break;
1708       }
1709
1710       case NO_INSTR:
1711         processed = false;
1712         break;
1713
1714       default:
1715         UNIMPLEMENTED();  // This type is not implemented.
1716     }
1717   }
1718
1719   // The first byte didn't match any of the simple opcodes, so we
1720   // need to do special processing on it.
1721   if (!processed) {
1722     switch (*data) {
1723       case 0xC2:
1724         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
1725         data += 3;
1726         break;
1727
1728       case 0x69:  // fall through
1729       case 0x6B: {
1730         int count = 1;
1731         count += PrintOperands("imul", REG_OPER_OP_ORDER, data + count);
1732         AppendToBuffer(",0x");
1733         if (*data == 0x69) {
1734           count += PrintImmediate(data + count, operand_size());
1735         } else {
1736           count += PrintImmediate(data + count, OPERAND_BYTE_SIZE);
1737         }
1738         data += count;
1739         break;
1740       }
1741
1742       case 0x81:  // fall through
1743       case 0x83:  // 0x81 with sign extension bit set
1744         data += PrintImmediateOp(data);
1745         break;
1746
1747       case 0x0F:
1748         data += TwoByteOpcodeInstruction(data);
1749         break;
1750
1751       case 0x8F: {
1752         data++;
1753         int mod, regop, rm;
1754         get_modrm(*data, &mod, &regop, &rm);
1755         if (regop == 0) {
1756           AppendToBuffer("pop ");
1757           data += PrintRightOperand(data);
1758         }
1759       }
1760         break;
1761
1762       case 0xFF: {
1763         data++;
1764         int mod, regop, rm;
1765         get_modrm(*data, &mod, &regop, &rm);
1766         const char* mnem = NULL;
1767         switch (regop) {
1768           case 0:
1769             mnem = "inc";
1770             break;
1771           case 1:
1772             mnem = "dec";
1773             break;
1774           case 2:
1775             mnem = "call";
1776             break;
1777           case 4:
1778             mnem = "jmp";
1779             break;
1780           case 6:
1781             mnem = "push";
1782             break;
1783           default:
1784             mnem = "???";
1785         }
1786         AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
1787                        mnem,
1788                        operand_size_code());
1789         data += PrintRightOperand(data);
1790       }
1791         break;
1792
1793       case 0xC7:  // imm32, fall through
1794       case 0xC6:  // imm8
1795       {
1796         bool is_byte = *data == 0xC6;
1797         data++;
1798         if (is_byte) {
1799           AppendToBuffer("movb ");
1800           data += PrintRightByteOperand(data);
1801           int32_t imm = *data;
1802           AppendToBuffer(",0x%x", imm);
1803           data++;
1804         } else {
1805           AppendToBuffer("mov%c ", operand_size_code());
1806           data += PrintRightOperand(data);
1807           if (operand_size() == OPERAND_WORD_SIZE) {
1808             int16_t imm = *reinterpret_cast<int16_t*>(data);
1809             AppendToBuffer(",0x%x", imm);
1810             data += 2;
1811           } else {
1812             int32_t imm = *reinterpret_cast<int32_t*>(data);
1813             AppendToBuffer(",0x%x", imm);
1814             data += 4;
1815           }
1816         }
1817       }
1818         break;
1819
1820       case 0x80: {
1821         data++;
1822         AppendToBuffer("cmpb ");
1823         data += PrintRightByteOperand(data);
1824         int32_t imm = *data;
1825         AppendToBuffer(",0x%x", imm);
1826         data++;
1827       }
1828         break;
1829
1830       case 0x88:  // 8bit, fall through
1831       case 0x89:  // 32bit
1832       {
1833         bool is_byte = *data == 0x88;
1834         int mod, regop, rm;
1835         data++;
1836         get_modrm(*data, &mod, &regop, &rm);
1837         if (is_byte) {
1838           AppendToBuffer("movb ");
1839           data += PrintRightByteOperand(data);
1840           AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1841         } else {
1842           AppendToBuffer("mov%c ", operand_size_code());
1843           data += PrintRightOperand(data);
1844           AppendToBuffer(",%s", NameOfCPURegister(regop));
1845         }
1846       }
1847         break;
1848
1849       case 0x90:
1850       case 0x91:
1851       case 0x92:
1852       case 0x93:
1853       case 0x94:
1854       case 0x95:
1855       case 0x96:
1856       case 0x97: {
1857         int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
1858         if (reg == 0) {
1859           AppendToBuffer("nop");  // Common name for xchg rax,rax.
1860         } else {
1861           AppendToBuffer("xchg%c rax,%s",
1862                          operand_size_code(),
1863                          NameOfCPURegister(reg));
1864         }
1865         data++;
1866       }
1867         break;
1868       case 0xB0:
1869       case 0xB1:
1870       case 0xB2:
1871       case 0xB3:
1872       case 0xB4:
1873       case 0xB5:
1874       case 0xB6:
1875       case 0xB7:
1876       case 0xB8:
1877       case 0xB9:
1878       case 0xBA:
1879       case 0xBB:
1880       case 0xBC:
1881       case 0xBD:
1882       case 0xBE:
1883       case 0xBF: {
1884         // mov reg8,imm8 or mov reg32,imm32
1885         byte opcode = *data;
1886         data++;
1887         bool is_32bit = (opcode >= 0xB8);
1888         int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
1889         if (is_32bit) {
1890           AppendToBuffer("mov%c %s,",
1891                          operand_size_code(),
1892                          NameOfCPURegister(reg));
1893           data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
1894         } else {
1895           AppendToBuffer("movb %s,",
1896                          NameOfByteCPURegister(reg));
1897           data += PrintImmediate(data, OPERAND_BYTE_SIZE);
1898         }
1899         break;
1900       }
1901       case 0xFE: {
1902         data++;
1903         int mod, regop, rm;
1904         get_modrm(*data, &mod, &regop, &rm);
1905         if (regop == 1) {
1906           AppendToBuffer("decb ");
1907           data += PrintRightByteOperand(data);
1908         } else {
1909           UnimplementedInstruction();
1910         }
1911         break;
1912       }
1913       case 0x68:
1914         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
1915         data += 5;
1916         break;
1917
1918       case 0x6A:
1919         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1920         data += 2;
1921         break;
1922
1923       case 0xA1:  // Fall through.
1924       case 0xA3:
1925         switch (operand_size()) {
1926           case OPERAND_DOUBLEWORD_SIZE: {
1927             const char* memory_location = NameOfAddress(
1928                 reinterpret_cast<byte*>(
1929                     *reinterpret_cast<int32_t*>(data + 1)));
1930             if (*data == 0xA1) {  // Opcode 0xA1
1931               AppendToBuffer("movzxlq rax,(%s)", memory_location);
1932             } else {  // Opcode 0xA3
1933               AppendToBuffer("movzxlq (%s),rax", memory_location);
1934             }
1935             data += 5;
1936             break;
1937           }
1938           case OPERAND_QUADWORD_SIZE: {
1939             // New x64 instruction mov rax,(imm_64).
1940             const char* memory_location = NameOfAddress(
1941                 *reinterpret_cast<byte**>(data + 1));
1942             if (*data == 0xA1) {  // Opcode 0xA1
1943               AppendToBuffer("movq rax,(%s)", memory_location);
1944             } else {  // Opcode 0xA3
1945               AppendToBuffer("movq (%s),rax", memory_location);
1946             }
1947             data += 9;
1948             break;
1949           }
1950           default:
1951             UnimplementedInstruction();
1952             data += 2;
1953         }
1954         break;
1955
1956       case 0xA8:
1957         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
1958         data += 2;
1959         break;
1960
1961       case 0xA9: {
1962         int64_t value = 0;
1963         switch (operand_size()) {
1964           case OPERAND_WORD_SIZE:
1965             value = *reinterpret_cast<uint16_t*>(data + 1);
1966             data += 3;
1967             break;
1968           case OPERAND_DOUBLEWORD_SIZE:
1969             value = *reinterpret_cast<uint32_t*>(data + 1);
1970             data += 5;
1971             break;
1972           case OPERAND_QUADWORD_SIZE:
1973             value = *reinterpret_cast<int32_t*>(data + 1);
1974             data += 5;
1975             break;
1976           default:
1977             UNREACHABLE();
1978         }
1979         AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x",
1980                        operand_size_code(),
1981                        value);
1982         break;
1983       }
1984       case 0xD1:  // fall through
1985       case 0xD3:  // fall through
1986       case 0xC1:
1987         data += ShiftInstruction(data);
1988         break;
1989       case 0xD0:  // fall through
1990       case 0xD2:  // fall through
1991       case 0xC0:
1992         byte_size_operand_ = true;
1993         data += ShiftInstruction(data);
1994         break;
1995
1996       case 0xD9:  // fall through
1997       case 0xDA:  // fall through
1998       case 0xDB:  // fall through
1999       case 0xDC:  // fall through
2000       case 0xDD:  // fall through
2001       case 0xDE:  // fall through
2002       case 0xDF:
2003         data += FPUInstruction(data);
2004         break;
2005
2006       case 0xEB:
2007         data += JumpShort(data);
2008         break;
2009
2010       case 0xF6:
2011         byte_size_operand_ = true;  // fall through
2012       case 0xF7:
2013         data += F6F7Instruction(data);
2014         break;
2015
2016       case 0x3C:
2017         AppendToBuffer("cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
2018         data +=2;
2019         break;
2020
2021       default:
2022         UnimplementedInstruction();
2023         data += 1;
2024     }
2025   }  // !processed
2026
2027   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
2028     tmp_buffer_[tmp_buffer_pos_] = '\0';
2029   }
2030
2031   int instr_len = static_cast<int>(data - instr);
2032   DCHECK(instr_len > 0);  // Ensure progress.
2033
2034   int outp = 0;
2035   // Instruction bytes.
2036   for (byte* bp = instr; bp < data; bp++) {
2037     outp += v8::internal::SNPrintF(out_buffer + outp, "%02x", *bp);
2038   }
2039   for (int i = 6 - instr_len; i >= 0; i--) {
2040     outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
2041   }
2042
2043   outp += v8::internal::SNPrintF(out_buffer + outp, " %s",
2044                                  tmp_buffer_.start());
2045   return instr_len;
2046 }
2047
2048
2049 //------------------------------------------------------------------------------
2050
2051
2052 static const char* const cpu_regs[16] = {
2053   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
2054   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
2055 };
2056
2057
2058 static const char* const byte_cpu_regs[16] = {
2059   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
2060   "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"
2061 };
2062
2063
2064 static const char* const xmm_regs[16] = {
2065   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
2066   "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
2067 };
2068
2069
2070 const char* NameConverter::NameOfAddress(byte* addr) const {
2071   v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
2072   return tmp_buffer_.start();
2073 }
2074
2075
2076 const char* NameConverter::NameOfConstant(byte* addr) const {
2077   return NameOfAddress(addr);
2078 }
2079
2080
2081 const char* NameConverter::NameOfCPURegister(int reg) const {
2082   if (0 <= reg && reg < 16)
2083     return cpu_regs[reg];
2084   return "noreg";
2085 }
2086
2087
2088 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2089   if (0 <= reg && reg < 16)
2090     return byte_cpu_regs[reg];
2091   return "noreg";
2092 }
2093
2094
2095 const char* NameConverter::NameOfXMMRegister(int reg) const {
2096   if (0 <= reg && reg < 16)
2097     return xmm_regs[reg];
2098   return "noxmmreg";
2099 }
2100
2101
2102 const char* NameConverter::NameInCode(byte* addr) const {
2103   // X64 does not embed debug strings at the moment.
2104   UNREACHABLE();
2105   return "";
2106 }
2107
2108
2109 //------------------------------------------------------------------------------
2110
2111 Disassembler::Disassembler(const NameConverter& converter)
2112     : converter_(converter) { }
2113
2114 Disassembler::~Disassembler() { }
2115
2116
2117 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2118                                     byte* instruction) {
2119   DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
2120   return d.InstructionDecode(buffer, instruction);
2121 }
2122
2123
2124 // The X64 assembler does not use constant pools.
2125 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2126   return -1;
2127 }
2128
2129
2130 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
2131   NameConverter converter;
2132   Disassembler d(converter);
2133   for (byte* pc = begin; pc < end;) {
2134     v8::internal::EmbeddedVector<char, 128> buffer;
2135     buffer[0] = '\0';
2136     byte* prev_pc = pc;
2137     pc += d.InstructionDecode(buffer, pc);
2138     fprintf(f, "%p", prev_pc);
2139     fprintf(f, "    ");
2140
2141     for (byte* bp = prev_pc; bp < pc; bp++) {
2142       fprintf(f, "%02x", *bp);
2143     }
2144     for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
2145       fprintf(f, "  ");
2146     }
2147     fprintf(f, "  %s\n", buffer.start());
2148   }
2149 }
2150
2151 }  // namespace disasm
2152
2153 #endif  // V8_TARGET_ARCH_X64