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