Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / v8 / src / ia32 / disasm-ia32.cc
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8
9 #include "src/v8.h"
10
11 #if V8_TARGET_ARCH_IA32
12
13 #include "src/disasm.h"
14
15 namespace disasm {
16
17 enum OperandOrder {
18   UNSET_OP_ORDER = 0,
19   REG_OPER_OP_ORDER,
20   OPER_REG_OP_ORDER
21 };
22
23
24 //------------------------------------------------------------------
25 // Tables
26 //------------------------------------------------------------------
27 struct ByteMnemonic {
28   int b;  // -1 terminates, otherwise must be in range (0..255)
29   const char* mnem;
30   OperandOrder op_order_;
31 };
32
33
34 static const ByteMnemonic two_operands_instr[] = {
35   {0x01, "add", OPER_REG_OP_ORDER},
36   {0x03, "add", REG_OPER_OP_ORDER},
37   {0x09, "or", OPER_REG_OP_ORDER},
38   {0x0B, "or", REG_OPER_OP_ORDER},
39   {0x1B, "sbb", REG_OPER_OP_ORDER},
40   {0x21, "and", OPER_REG_OP_ORDER},
41   {0x23, "and", REG_OPER_OP_ORDER},
42   {0x29, "sub", OPER_REG_OP_ORDER},
43   {0x2A, "subb", REG_OPER_OP_ORDER},
44   {0x2B, "sub", REG_OPER_OP_ORDER},
45   {0x31, "xor", OPER_REG_OP_ORDER},
46   {0x33, "xor", REG_OPER_OP_ORDER},
47   {0x38, "cmpb", OPER_REG_OP_ORDER},
48   {0x3A, "cmpb", REG_OPER_OP_ORDER},
49   {0x3B, "cmp", REG_OPER_OP_ORDER},
50   {0x84, "test_b", REG_OPER_OP_ORDER},
51   {0x85, "test", REG_OPER_OP_ORDER},
52   {0x87, "xchg", REG_OPER_OP_ORDER},
53   {0x8A, "mov_b", REG_OPER_OP_ORDER},
54   {0x8B, "mov", REG_OPER_OP_ORDER},
55   {0x8D, "lea", REG_OPER_OP_ORDER},
56   {-1, "", UNSET_OP_ORDER}
57 };
58
59
60 static const ByteMnemonic zero_operands_instr[] = {
61   {0xC3, "ret", UNSET_OP_ORDER},
62   {0xC9, "leave", UNSET_OP_ORDER},
63   {0x90, "nop", UNSET_OP_ORDER},
64   {0xF4, "hlt", UNSET_OP_ORDER},
65   {0xCC, "int3", UNSET_OP_ORDER},
66   {0x60, "pushad", UNSET_OP_ORDER},
67   {0x61, "popad", UNSET_OP_ORDER},
68   {0x9C, "pushfd", UNSET_OP_ORDER},
69   {0x9D, "popfd", UNSET_OP_ORDER},
70   {0x9E, "sahf", UNSET_OP_ORDER},
71   {0x99, "cdq", UNSET_OP_ORDER},
72   {0x9B, "fwait", UNSET_OP_ORDER},
73   {0xFC, "cld", UNSET_OP_ORDER},
74   {0xAB, "stos", UNSET_OP_ORDER},
75   {-1, "", UNSET_OP_ORDER}
76 };
77
78
79 static const ByteMnemonic call_jump_instr[] = {
80   {0xE8, "call", UNSET_OP_ORDER},
81   {0xE9, "jmp", UNSET_OP_ORDER},
82   {-1, "", UNSET_OP_ORDER}
83 };
84
85
86 static const ByteMnemonic short_immediate_instr[] = {
87   {0x05, "add", UNSET_OP_ORDER},
88   {0x0D, "or", UNSET_OP_ORDER},
89   {0x15, "adc", UNSET_OP_ORDER},
90   {0x25, "and", UNSET_OP_ORDER},
91   {0x2D, "sub", UNSET_OP_ORDER},
92   {0x35, "xor", UNSET_OP_ORDER},
93   {0x3D, "cmp", UNSET_OP_ORDER},
94   {-1, "", UNSET_OP_ORDER}
95 };
96
97
98 // Generally we don't want to generate these because they are subject to partial
99 // register stalls.  They are included for completeness and because the cmp
100 // variant is used by the RecordWrite stub.  Because it does not update the
101 // register it is not subject to partial register stalls.
102 static ByteMnemonic byte_immediate_instr[] = {
103   {0x0c, "or", UNSET_OP_ORDER},
104   {0x24, "and", UNSET_OP_ORDER},
105   {0x34, "xor", UNSET_OP_ORDER},
106   {0x3c, "cmp", UNSET_OP_ORDER},
107   {-1, "", UNSET_OP_ORDER}
108 };
109
110
111 static const char* const jump_conditional_mnem[] = {
112   /*0*/ "jo", "jno", "jc", "jnc",
113   /*4*/ "jz", "jnz", "jna", "ja",
114   /*8*/ "js", "jns", "jpe", "jpo",
115   /*12*/ "jl", "jnl", "jng", "jg"
116 };
117
118
119 static const char* const set_conditional_mnem[] = {
120   /*0*/ "seto", "setno", "setc", "setnc",
121   /*4*/ "setz", "setnz", "setna", "seta",
122   /*8*/ "sets", "setns", "setpe", "setpo",
123   /*12*/ "setl", "setnl", "setng", "setg"
124 };
125
126
127 static const char* const conditional_move_mnem[] = {
128   /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
129   /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
130   /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
131   /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"
132 };
133
134
135 enum InstructionType {
136   NO_INSTR,
137   ZERO_OPERANDS_INSTR,
138   TWO_OPERANDS_INSTR,
139   JUMP_CONDITIONAL_SHORT_INSTR,
140   REGISTER_INSTR,
141   MOVE_REG_INSTR,
142   CALL_JUMP_INSTR,
143   SHORT_IMMEDIATE_INSTR,
144   BYTE_IMMEDIATE_INSTR
145 };
146
147
148 struct InstructionDesc {
149   const char* mnem;
150   InstructionType type;
151   OperandOrder op_order_;
152 };
153
154
155 class InstructionTable {
156  public:
157   InstructionTable();
158   const InstructionDesc& Get(byte x) const { return instructions_[x]; }
159   static InstructionTable* get_instance() {
160     static InstructionTable table;
161     return &table;
162   }
163
164  private:
165   InstructionDesc instructions_[256];
166   void Clear();
167   void Init();
168   void CopyTable(const ByteMnemonic bm[], InstructionType type);
169   void SetTableRange(InstructionType type,
170                      byte start,
171                      byte end,
172                      const char* mnem);
173   void AddJumpConditionalShort();
174 };
175
176
177 InstructionTable::InstructionTable() {
178   Clear();
179   Init();
180 }
181
182
183 void InstructionTable::Clear() {
184   for (int i = 0; i < 256; i++) {
185     instructions_[i].mnem = "";
186     instructions_[i].type = NO_INSTR;
187     instructions_[i].op_order_ = UNSET_OP_ORDER;
188   }
189 }
190
191
192 void InstructionTable::Init() {
193   CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
194   CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
195   CopyTable(call_jump_instr, CALL_JUMP_INSTR);
196   CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
197   CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
198   AddJumpConditionalShort();
199   SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
200   SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
201   SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
202   SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
203   SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,");  // 0x90 is nop.
204   SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
205 }
206
207
208 void InstructionTable::CopyTable(const ByteMnemonic bm[],
209                                  InstructionType type) {
210   for (int i = 0; bm[i].b >= 0; i++) {
211     InstructionDesc* id = &instructions_[bm[i].b];
212     id->mnem = bm[i].mnem;
213     id->op_order_ = bm[i].op_order_;
214     DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
215     id->type = type;
216   }
217 }
218
219
220 void InstructionTable::SetTableRange(InstructionType type,
221                                      byte start,
222                                      byte end,
223                                      const char* mnem) {
224   for (byte b = start; b <= end; b++) {
225     InstructionDesc* id = &instructions_[b];
226     DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
227     id->mnem = mnem;
228     id->type = type;
229   }
230 }
231
232
233 void InstructionTable::AddJumpConditionalShort() {
234   for (byte b = 0x70; b <= 0x7F; b++) {
235     InstructionDesc* id = &instructions_[b];
236     DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
237     id->mnem = jump_conditional_mnem[b & 0x0F];
238     id->type = JUMP_CONDITIONAL_SHORT_INSTR;
239   }
240 }
241
242
243 // The IA32 disassembler implementation.
244 class DisassemblerIA32 {
245  public:
246   DisassemblerIA32(const NameConverter& converter,
247                    bool abort_on_unimplemented = true)
248       : converter_(converter),
249         instruction_table_(InstructionTable::get_instance()),
250         tmp_buffer_pos_(0),
251         abort_on_unimplemented_(abort_on_unimplemented) {
252     tmp_buffer_[0] = '\0';
253   }
254
255   virtual ~DisassemblerIA32() {}
256
257   // Writes one disassembled instruction into 'buffer' (0-terminated).
258   // Returns the length of the disassembled machine instruction in bytes.
259   int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
260
261  private:
262   const NameConverter& converter_;
263   InstructionTable* instruction_table_;
264   v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
265   unsigned int tmp_buffer_pos_;
266   bool abort_on_unimplemented_;
267
268   enum {
269     eax = 0,
270     ecx = 1,
271     edx = 2,
272     ebx = 3,
273     esp = 4,
274     ebp = 5,
275     esi = 6,
276     edi = 7
277   };
278
279
280   enum ShiftOpcodeExtension {
281     kROL = 0,
282     kROR = 1,
283     kRCL = 2,
284     kRCR = 3,
285     kSHL = 4,
286     KSHR = 5,
287     kSAR = 7
288   };
289
290
291   const char* NameOfCPURegister(int reg) const {
292     return converter_.NameOfCPURegister(reg);
293   }
294
295
296   const char* NameOfByteCPURegister(int reg) const {
297     return converter_.NameOfByteCPURegister(reg);
298   }
299
300
301   const char* NameOfXMMRegister(int reg) const {
302     return converter_.NameOfXMMRegister(reg);
303   }
304
305
306   const char* NameOfAddress(byte* addr) const {
307     return converter_.NameOfAddress(addr);
308   }
309
310
311   // Disassembler helper functions.
312   static void get_modrm(byte data, int* mod, int* regop, int* rm) {
313     *mod = (data >> 6) & 3;
314     *regop = (data & 0x38) >> 3;
315     *rm = data & 7;
316   }
317
318
319   static void get_sib(byte data, int* scale, int* index, int* base) {
320     *scale = (data >> 6) & 3;
321     *index = (data >> 3) & 7;
322     *base = data & 7;
323   }
324
325   typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
326
327   int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
328   int PrintRightOperand(byte* modrmp);
329   int PrintRightByteOperand(byte* modrmp);
330   int PrintRightXMMOperand(byte* modrmp);
331   int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
332   int PrintImmediateOp(byte* data);
333   int F7Instruction(byte* data);
334   int D1D3C1Instruction(byte* data);
335   int JumpShort(byte* data);
336   int JumpConditional(byte* data, const char* comment);
337   int JumpConditionalShort(byte* data, const char* comment);
338   int SetCC(byte* data);
339   int CMov(byte* data);
340   int FPUInstruction(byte* data);
341   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
342   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
343   void AppendToBuffer(const char* format, ...);
344
345
346   void UnimplementedInstruction() {
347     if (abort_on_unimplemented_) {
348       UNIMPLEMENTED();
349     } else {
350       AppendToBuffer("'Unimplemented Instruction'");
351     }
352   }
353 };
354
355
356 void DisassemblerIA32::AppendToBuffer(const char* format, ...) {
357   v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
358   va_list args;
359   va_start(args, format);
360   int result = v8::internal::VSNPrintF(buf, format, args);
361   va_end(args);
362   tmp_buffer_pos_ += result;
363 }
364
365 int DisassemblerIA32::PrintRightOperandHelper(
366     byte* modrmp,
367     RegisterNameMapping direct_register_name) {
368   int mod, regop, rm;
369   get_modrm(*modrmp, &mod, &regop, &rm);
370   RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
371       &DisassemblerIA32::NameOfCPURegister;
372   switch (mod) {
373     case 0:
374       if (rm == ebp) {
375         int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
376         AppendToBuffer("[0x%x]", disp);
377         return 5;
378       } else if (rm == esp) {
379         byte sib = *(modrmp + 1);
380         int scale, index, base;
381         get_sib(sib, &scale, &index, &base);
382         if (index == esp && base == esp && scale == 0 /*times_1*/) {
383           AppendToBuffer("[%s]", (this->*register_name)(rm));
384           return 2;
385         } else if (base == ebp) {
386           int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
387           AppendToBuffer("[%s*%d%s0x%x]",
388                          (this->*register_name)(index),
389                          1 << scale,
390                          disp < 0 ? "-" : "+",
391                          disp < 0 ? -disp : disp);
392           return 6;
393         } else if (index != esp && base != ebp) {
394           // [base+index*scale]
395           AppendToBuffer("[%s+%s*%d]",
396                          (this->*register_name)(base),
397                          (this->*register_name)(index),
398                          1 << scale);
399           return 2;
400         } else {
401           UnimplementedInstruction();
402           return 1;
403         }
404       } else {
405         AppendToBuffer("[%s]", (this->*register_name)(rm));
406         return 1;
407       }
408       break;
409     case 1:  // fall through
410     case 2:
411       if (rm == esp) {
412         byte sib = *(modrmp + 1);
413         int scale, index, base;
414         get_sib(sib, &scale, &index, &base);
415         int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2)
416                             : *reinterpret_cast<int8_t*>(modrmp + 2);
417         if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
418           AppendToBuffer("[%s%s0x%x]",
419                          (this->*register_name)(rm),
420                          disp < 0 ? "-" : "+",
421                          disp < 0 ? -disp : disp);
422         } else {
423           AppendToBuffer("[%s+%s*%d%s0x%x]",
424                          (this->*register_name)(base),
425                          (this->*register_name)(index),
426                          1 << scale,
427                          disp < 0 ? "-" : "+",
428                          disp < 0 ? -disp : disp);
429         }
430         return mod == 2 ? 6 : 3;
431       } else {
432         // No sib.
433         int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1)
434                             : *reinterpret_cast<int8_t*>(modrmp + 1);
435         AppendToBuffer("[%s%s0x%x]",
436                        (this->*register_name)(rm),
437                        disp < 0 ? "-" : "+",
438                        disp < 0 ? -disp : disp);
439         return mod == 2 ? 5 : 2;
440       }
441       break;
442     case 3:
443       AppendToBuffer("%s", (this->*register_name)(rm));
444       return 1;
445     default:
446       UnimplementedInstruction();
447       return 1;
448   }
449   UNREACHABLE();
450 }
451
452
453 int DisassemblerIA32::PrintRightOperand(byte* modrmp) {
454   return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
455 }
456
457
458 int DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
459   return PrintRightOperandHelper(modrmp,
460                                  &DisassemblerIA32::NameOfByteCPURegister);
461 }
462
463
464 int DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
465   return PrintRightOperandHelper(modrmp,
466                                  &DisassemblerIA32::NameOfXMMRegister);
467 }
468
469
470 // Returns number of bytes used including the current *data.
471 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
472 int DisassemblerIA32::PrintOperands(const char* mnem,
473                                     OperandOrder op_order,
474                                     byte* data) {
475   byte modrm = *data;
476   int mod, regop, rm;
477   get_modrm(modrm, &mod, &regop, &rm);
478   int advance = 0;
479   switch (op_order) {
480     case REG_OPER_OP_ORDER: {
481       AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
482       advance = PrintRightOperand(data);
483       break;
484     }
485     case OPER_REG_OP_ORDER: {
486       AppendToBuffer("%s ", mnem);
487       advance = PrintRightOperand(data);
488       AppendToBuffer(",%s", NameOfCPURegister(regop));
489       break;
490     }
491     default:
492       UNREACHABLE();
493       break;
494   }
495   return advance;
496 }
497
498
499 // Returns number of bytes used by machine instruction, including *data byte.
500 // Writes immediate instructions to 'tmp_buffer_'.
501 int DisassemblerIA32::PrintImmediateOp(byte* data) {
502   bool sign_extension_bit = (*data & 0x02) != 0;
503   byte modrm = *(data+1);
504   int mod, regop, rm;
505   get_modrm(modrm, &mod, &regop, &rm);
506   const char* mnem = "Imm???";
507   switch (regop) {
508     case 0: mnem = "add"; break;
509     case 1: mnem = "or"; break;
510     case 2: mnem = "adc"; break;
511     case 4: mnem = "and"; break;
512     case 5: mnem = "sub"; break;
513     case 6: mnem = "xor"; break;
514     case 7: mnem = "cmp"; break;
515     default: UnimplementedInstruction();
516   }
517   AppendToBuffer("%s ", mnem);
518   int count = PrintRightOperand(data+1);
519   if (sign_extension_bit) {
520     AppendToBuffer(",0x%x", *(data + 1 + count));
521     return 1 + count + 1 /*int8*/;
522   } else {
523     AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
524     return 1 + count + 4 /*int32_t*/;
525   }
526 }
527
528
529 // Returns number of bytes used, including *data.
530 int DisassemblerIA32::F7Instruction(byte* data) {
531   DCHECK_EQ(0xF7, *data);
532   byte modrm = *++data;
533   int mod, regop, rm;
534   get_modrm(modrm, &mod, &regop, &rm);
535   const char* mnem = NULL;
536   switch (regop) {
537     case 0:
538       mnem = "test";
539       break;
540     case 2:
541       mnem = "not";
542       break;
543     case 3:
544       mnem = "neg";
545       break;
546     case 4:
547       mnem = "mul";
548       break;
549     case 5:
550       mnem = "imul";
551       break;
552     case 6:
553       mnem = "div";
554       break;
555     case 7:
556       mnem = "idiv";
557       break;
558     default:
559       UnimplementedInstruction();
560   }
561   AppendToBuffer("%s ", mnem);
562   int count = PrintRightOperand(data);
563   if (regop == 0) {
564     AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count));
565     count += 4;
566   }
567   return 1 + count;
568 }
569
570
571 int DisassemblerIA32::D1D3C1Instruction(byte* data) {
572   byte op = *data;
573   DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1);
574   byte modrm = *++data;
575   int mod, regop, rm;
576   get_modrm(modrm, &mod, &regop, &rm);
577   int imm8 = -1;
578   const char* mnem = NULL;
579   switch (regop) {
580     case kROL:
581       mnem = "rol";
582       break;
583     case kROR:
584       mnem = "ror";
585       break;
586     case kRCL:
587       mnem = "rcl";
588       break;
589     case kRCR:
590       mnem = "rcr";
591       break;
592     case kSHL:
593       mnem = "shl";
594       break;
595     case KSHR:
596       mnem = "shr";
597       break;
598     case kSAR:
599       mnem = "sar";
600       break;
601     default:
602       UnimplementedInstruction();
603   }
604   AppendToBuffer("%s ", mnem);
605   int count = PrintRightOperand(data);
606   if (op == 0xD1) {
607     imm8 = 1;
608   } else if (op == 0xC1) {
609     imm8 = *(data + 1);
610     count++;
611   } else if (op == 0xD3) {
612     // Shift/rotate by cl.
613   }
614   if (imm8 >= 0) {
615     AppendToBuffer(",%d", imm8);
616   } else {
617     AppendToBuffer(",cl");
618   }
619   return 1 + count;
620 }
621
622
623 // Returns number of bytes used, including *data.
624 int DisassemblerIA32::JumpShort(byte* data) {
625   DCHECK_EQ(0xEB, *data);
626   byte b = *(data+1);
627   byte* dest = data + static_cast<int8_t>(b) + 2;
628   AppendToBuffer("jmp %s", NameOfAddress(dest));
629   return 2;
630 }
631
632
633 // Returns number of bytes used, including *data.
634 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
635   DCHECK_EQ(0x0F, *data);
636   byte cond = *(data+1) & 0x0F;
637   byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
638   const char* mnem = jump_conditional_mnem[cond];
639   AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
640   if (comment != NULL) {
641     AppendToBuffer(", %s", comment);
642   }
643   return 6;  // includes 0x0F
644 }
645
646
647 // Returns number of bytes used, including *data.
648 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
649   byte cond = *data & 0x0F;
650   byte b = *(data+1);
651   byte* dest = data + static_cast<int8_t>(b) + 2;
652   const char* mnem = jump_conditional_mnem[cond];
653   AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
654   if (comment != NULL) {
655     AppendToBuffer(", %s", comment);
656   }
657   return 2;
658 }
659
660
661 // Returns number of bytes used, including *data.
662 int DisassemblerIA32::SetCC(byte* data) {
663   DCHECK_EQ(0x0F, *data);
664   byte cond = *(data+1) & 0x0F;
665   const char* mnem = set_conditional_mnem[cond];
666   AppendToBuffer("%s ", mnem);
667   PrintRightByteOperand(data+2);
668   return 3;  // Includes 0x0F.
669 }
670
671
672 // Returns number of bytes used, including *data.
673 int DisassemblerIA32::CMov(byte* data) {
674   DCHECK_EQ(0x0F, *data);
675   byte cond = *(data + 1) & 0x0F;
676   const char* mnem = conditional_move_mnem[cond];
677   int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
678   return 2 + op_size;  // includes 0x0F
679 }
680
681
682 // Returns number of bytes used, including *data.
683 int DisassemblerIA32::FPUInstruction(byte* data) {
684   byte escape_opcode = *data;
685   DCHECK_EQ(0xD8, escape_opcode & 0xF8);
686   byte modrm_byte = *(data+1);
687
688   if (modrm_byte >= 0xC0) {
689     return RegisterFPUInstruction(escape_opcode, modrm_byte);
690   } else {
691     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
692   }
693 }
694
695 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
696                                            int modrm_byte,
697                                            byte* modrm_start) {
698   const char* mnem = "?";
699   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
700   switch (escape_opcode) {
701     case 0xD9: switch (regop) {
702         case 0: mnem = "fld_s"; break;
703         case 2: mnem = "fst_s"; break;
704         case 3: mnem = "fstp_s"; break;
705         case 7: mnem = "fstcw"; break;
706         default: UnimplementedInstruction();
707       }
708       break;
709
710     case 0xDB: switch (regop) {
711         case 0: mnem = "fild_s"; break;
712         case 1: mnem = "fisttp_s"; break;
713         case 2: mnem = "fist_s"; break;
714         case 3: mnem = "fistp_s"; break;
715         default: UnimplementedInstruction();
716       }
717       break;
718
719     case 0xDD: switch (regop) {
720         case 0: mnem = "fld_d"; break;
721         case 1: mnem = "fisttp_d"; break;
722         case 2: mnem = "fst_d"; break;
723         case 3: mnem = "fstp_d"; break;
724         default: UnimplementedInstruction();
725       }
726       break;
727
728     case 0xDF: switch (regop) {
729         case 5: mnem = "fild_d"; break;
730         case 7: mnem = "fistp_d"; break;
731         default: UnimplementedInstruction();
732       }
733       break;
734
735     default: UnimplementedInstruction();
736   }
737   AppendToBuffer("%s ", mnem);
738   int count = PrintRightOperand(modrm_start);
739   return count + 1;
740 }
741
742 int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
743                                              byte modrm_byte) {
744   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
745   const char* mnem = "?";
746
747   switch (escape_opcode) {
748     case 0xD8:
749       has_register = true;
750       switch (modrm_byte & 0xF8) {
751         case 0xC0: mnem = "fadd_i"; break;
752         case 0xE0: mnem = "fsub_i"; break;
753         case 0xC8: mnem = "fmul_i"; break;
754         case 0xF0: mnem = "fdiv_i"; break;
755         default: UnimplementedInstruction();
756       }
757       break;
758
759     case 0xD9:
760       switch (modrm_byte & 0xF8) {
761         case 0xC0:
762           mnem = "fld";
763           has_register = true;
764           break;
765         case 0xC8:
766           mnem = "fxch";
767           has_register = true;
768           break;
769         default:
770           switch (modrm_byte) {
771             case 0xE0: mnem = "fchs"; break;
772             case 0xE1: mnem = "fabs"; break;
773             case 0xE4: mnem = "ftst"; break;
774             case 0xE8: mnem = "fld1"; break;
775             case 0xEB: mnem = "fldpi"; break;
776             case 0xED: mnem = "fldln2"; break;
777             case 0xEE: mnem = "fldz"; break;
778             case 0xF0: mnem = "f2xm1"; break;
779             case 0xF1: mnem = "fyl2x"; break;
780             case 0xF4: mnem = "fxtract"; break;
781             case 0xF5: mnem = "fprem1"; break;
782             case 0xF7: mnem = "fincstp"; break;
783             case 0xF8: mnem = "fprem"; break;
784             case 0xFC: mnem = "frndint"; break;
785             case 0xFD: mnem = "fscale"; break;
786             case 0xFE: mnem = "fsin"; break;
787             case 0xFF: mnem = "fcos"; break;
788             default: UnimplementedInstruction();
789           }
790       }
791       break;
792
793     case 0xDA:
794       if (modrm_byte == 0xE9) {
795         mnem = "fucompp";
796       } else {
797         UnimplementedInstruction();
798       }
799       break;
800
801     case 0xDB:
802       if ((modrm_byte & 0xF8) == 0xE8) {
803         mnem = "fucomi";
804         has_register = true;
805       } else if (modrm_byte  == 0xE2) {
806         mnem = "fclex";
807       } else if (modrm_byte == 0xE3) {
808         mnem = "fninit";
809       } else {
810         UnimplementedInstruction();
811       }
812       break;
813
814     case 0xDC:
815       has_register = true;
816       switch (modrm_byte & 0xF8) {
817         case 0xC0: mnem = "fadd"; break;
818         case 0xE8: mnem = "fsub"; break;
819         case 0xC8: mnem = "fmul"; break;
820         case 0xF8: mnem = "fdiv"; break;
821         default: UnimplementedInstruction();
822       }
823       break;
824
825     case 0xDD:
826       has_register = true;
827       switch (modrm_byte & 0xF8) {
828         case 0xC0: mnem = "ffree"; break;
829         case 0xD0: mnem = "fst"; break;
830         case 0xD8: mnem = "fstp"; break;
831         default: UnimplementedInstruction();
832       }
833       break;
834
835     case 0xDE:
836       if (modrm_byte  == 0xD9) {
837         mnem = "fcompp";
838       } else {
839         has_register = true;
840         switch (modrm_byte & 0xF8) {
841           case 0xC0: mnem = "faddp"; break;
842           case 0xE8: mnem = "fsubp"; break;
843           case 0xC8: mnem = "fmulp"; break;
844           case 0xF8: mnem = "fdivp"; break;
845           default: UnimplementedInstruction();
846         }
847       }
848       break;
849
850     case 0xDF:
851       if (modrm_byte == 0xE0) {
852         mnem = "fnstsw_ax";
853       } else if ((modrm_byte & 0xF8) == 0xE8) {
854         mnem = "fucomip";
855         has_register = true;
856       }
857       break;
858
859     default: UnimplementedInstruction();
860   }
861
862   if (has_register) {
863     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
864   } else {
865     AppendToBuffer("%s", mnem);
866   }
867   return 2;
868 }
869
870
871 // Mnemonics for instructions 0xF0 byte.
872 // Returns NULL if the instruction is not handled here.
873 static const char* F0Mnem(byte f0byte) {
874   switch (f0byte) {
875     case 0x18: return "prefetch";
876     case 0xA2: return "cpuid";
877     case 0xBE: return "movsx_b";
878     case 0xBF: return "movsx_w";
879     case 0xB6: return "movzx_b";
880     case 0xB7: return "movzx_w";
881     case 0xAF: return "imul";
882     case 0xA5: return "shld";
883     case 0xAD: return "shrd";
884     case 0xAC: return "shrd";  // 3-operand version.
885     case 0xAB: return "bts";
886     case 0xBD: return "bsr";
887     default: return NULL;
888   }
889 }
890
891
892 // Disassembled instruction '*instr' and writes it into 'out_buffer'.
893 int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
894                                         byte* instr) {
895   tmp_buffer_pos_ = 0;  // starting to write as position 0
896   byte* data = instr;
897   // Check for hints.
898   const char* branch_hint = NULL;
899   // We use these two prefixes only with branch prediction
900   if (*data == 0x3E /*ds*/) {
901     branch_hint = "predicted taken";
902     data++;
903   } else if (*data == 0x2E /*cs*/) {
904     branch_hint = "predicted not taken";
905     data++;
906   }
907   bool processed = true;  // Will be set to false if the current instruction
908                           // is not in 'instructions' table.
909   const InstructionDesc& idesc = instruction_table_->Get(*data);
910   switch (idesc.type) {
911     case ZERO_OPERANDS_INSTR:
912       AppendToBuffer(idesc.mnem);
913       data++;
914       break;
915
916     case TWO_OPERANDS_INSTR:
917       data++;
918       data += PrintOperands(idesc.mnem, idesc.op_order_, data);
919       break;
920
921     case JUMP_CONDITIONAL_SHORT_INSTR:
922       data += JumpConditionalShort(data, branch_hint);
923       break;
924
925     case REGISTER_INSTR:
926       AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
927       data++;
928       break;
929
930     case MOVE_REG_INSTR: {
931       byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
932       AppendToBuffer("mov %s,%s",
933                      NameOfCPURegister(*data & 0x07),
934                      NameOfAddress(addr));
935       data += 5;
936       break;
937     }
938
939     case CALL_JUMP_INSTR: {
940       byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
941       AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
942       data += 5;
943       break;
944     }
945
946     case SHORT_IMMEDIATE_INSTR: {
947       byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
948       AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
949       data += 5;
950       break;
951     }
952
953     case BYTE_IMMEDIATE_INSTR: {
954       AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
955       data += 2;
956       break;
957     }
958
959     case NO_INSTR:
960       processed = false;
961       break;
962
963     default:
964       UNIMPLEMENTED();  // This type is not implemented.
965   }
966   //----------------------------
967   if (!processed) {
968     switch (*data) {
969       case 0xC2:
970         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
971         data += 3;
972         break;
973
974       case 0x6B: {
975         data++;
976         data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
977         AppendToBuffer(",%d", *data);
978         data++;
979       } break;
980
981       case 0x69: {
982         data++;
983         data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
984         AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data));
985         data += 4;
986         }
987         break;
988
989       case 0xF6:
990         { data++;
991           int mod, regop, rm;
992           get_modrm(*data, &mod, &regop, &rm);
993           if (regop == eax) {
994             AppendToBuffer("test_b ");
995             data += PrintRightByteOperand(data);
996             int32_t imm = *data;
997             AppendToBuffer(",0x%x", imm);
998             data++;
999           } else {
1000             UnimplementedInstruction();
1001           }
1002         }
1003         break;
1004
1005       case 0x81:  // fall through
1006       case 0x83:  // 0x81 with sign extension bit set
1007         data += PrintImmediateOp(data);
1008         break;
1009
1010       case 0x0F:
1011         { byte f0byte = data[1];
1012           const char* f0mnem = F0Mnem(f0byte);
1013           if (f0byte == 0x18) {
1014             data += 2;
1015             int mod, regop, rm;
1016             get_modrm(*data, &mod, &regop, &rm);
1017             const char* suffix[] = {"nta", "1", "2", "3"};
1018             AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
1019             data += PrintRightOperand(data);
1020           } else if (f0byte == 0x1F && data[2] == 0) {
1021             AppendToBuffer("nop");  // 3 byte nop.
1022             data += 3;
1023           } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
1024             AppendToBuffer("nop");  // 4 byte nop.
1025             data += 4;
1026           } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
1027                      data[4] == 0) {
1028             AppendToBuffer("nop");  // 5 byte nop.
1029             data += 5;
1030           } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
1031                      data[4] == 0 && data[5] == 0 && data[6] == 0) {
1032             AppendToBuffer("nop");  // 7 byte nop.
1033             data += 7;
1034           } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
1035                      data[4] == 0 && data[5] == 0 && data[6] == 0 &&
1036                      data[7] == 0) {
1037             AppendToBuffer("nop");  // 8 byte nop.
1038             data += 8;
1039           } else if (f0byte == 0xA2 || f0byte == 0x31) {
1040             AppendToBuffer("%s", f0mnem);
1041             data += 2;
1042           } else if (f0byte == 0x28) {
1043             data += 2;
1044             int mod, regop, rm;
1045             get_modrm(*data, &mod, &regop, &rm);
1046             AppendToBuffer("movaps %s,%s",
1047                            NameOfXMMRegister(regop),
1048                            NameOfXMMRegister(rm));
1049             data++;
1050            } else if (f0byte == 0x12) {
1051             data += 2;
1052             int mod, regop, rm;
1053             get_modrm(*data, &mod, &regop, &rm);
1054             AppendToBuffer("movhlps %s,%s",
1055                            NameOfXMMRegister(regop),
1056                            NameOfXMMRegister(rm));
1057             data++;
1058           } else if (f0byte == 0x16) {
1059             data += 2;
1060             int mod, regop, rm;
1061             get_modrm(*data, &mod, &regop, &rm);
1062             AppendToBuffer("movlhps %s,%s",
1063                            NameOfXMMRegister(regop),
1064                            NameOfXMMRegister(rm));
1065             data++;
1066           } else if (f0byte == 0x10) {
1067             data += 2;
1068             int mod, regop, rm;
1069             get_modrm(*data, &mod, &regop, &rm);
1070             AppendToBuffer("movups %s,", NameOfXMMRegister(regop));
1071             data += PrintRightXMMOperand(data);
1072           } else if (f0byte == 0x11) {
1073             AppendToBuffer("movups ");
1074             data += 2;
1075             int mod, regop, rm;
1076             get_modrm(*data, &mod, &regop, &rm);
1077             data += PrintRightXMMOperand(data);
1078             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1079           } else if (f0byte >= 0x51 && f0byte <= 0x5F) {
1080             const char* const pseudo_op[] = {
1081               "sqrtps",
1082               "rsqrtps",
1083               "rcpps",
1084               "andps",
1085               "andnps",
1086               "orps",
1087               "xorps",
1088               "addps",
1089               "mulps",
1090               "cvtps2pd",
1091               "cvtdq2ps",
1092               "subps",
1093               "minps",
1094               "divps",
1095               "maxps"
1096             };
1097
1098             data += 2;
1099             int mod, regop, rm;
1100             get_modrm(*data, &mod, &regop, &rm);
1101             AppendToBuffer("%s %s,",
1102                            pseudo_op[f0byte - 0x51],
1103                            NameOfXMMRegister(regop));
1104             data += PrintRightXMMOperand(data);
1105           } else if (f0byte == 0x50) {
1106             data += 2;
1107             int mod, regop, rm;
1108             get_modrm(*data, &mod, &regop, &rm);
1109             AppendToBuffer("movmskps %s,%s",
1110                            NameOfCPURegister(regop),
1111                            NameOfXMMRegister(rm));
1112             data++;
1113           } else if (f0byte == 0xC2) {
1114             // Intel manual 2A, Table 3-11.
1115             data += 2;
1116             int mod, regop, rm;
1117             get_modrm(*data, &mod, &regop, &rm);
1118             const char* const pseudo_op[] = {
1119               "cmpeqps",
1120               "cmpltps",
1121               "cmpleps",
1122               "cmpunordps",
1123               "cmpneqps",
1124               "cmpnltps",
1125               "cmpnleps",
1126               "cmpordps"
1127             };
1128             AppendToBuffer("%s %s,%s",
1129                            pseudo_op[data[1]],
1130                            NameOfXMMRegister(regop),
1131                            NameOfXMMRegister(rm));
1132             data += 2;
1133           } else if (f0byte== 0xC6) {
1134             // shufps xmm, xmm/m128, imm8
1135             data += 2;
1136             int mod, regop, rm;
1137             get_modrm(*data, &mod, &regop, &rm);
1138             int8_t imm8 = static_cast<int8_t>(data[1]);
1139             AppendToBuffer("shufps %s,%s,%d",
1140                             NameOfXMMRegister(rm),
1141                             NameOfXMMRegister(regop),
1142                             static_cast<int>(imm8));
1143             data += 2;
1144           } else if (f0byte== 0x5B) {
1145             data += 2;
1146             int mod, regop, rm;
1147             get_modrm(*data, &mod, &regop, &rm);
1148             AppendToBuffer("cvtdq2ps %s,",
1149                             NameOfXMMRegister(rm));
1150             data += PrintRightXMMOperand(data);
1151           } else if ((f0byte & 0xF0) == 0x80) {
1152             data += JumpConditional(data, branch_hint);
1153           } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1154                      f0byte == 0xB7 || f0byte == 0xAF) {
1155             data += 2;
1156             data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1157           } else if ((f0byte & 0xF0) == 0x90) {
1158             data += SetCC(data);
1159           } else if ((f0byte & 0xF0) == 0x40) {
1160             data += CMov(data);
1161           } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1162             // shrd, shld, bts
1163             data += 2;
1164             AppendToBuffer("%s ", f0mnem);
1165             int mod, regop, rm;
1166             get_modrm(*data, &mod, &regop, &rm);
1167             data += PrintRightOperand(data);
1168             if (f0byte == 0xAB) {
1169               AppendToBuffer(",%s", NameOfCPURegister(regop));
1170             } else {
1171               AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1172             }
1173           } else if (f0byte == 0xBD) {
1174             data += 2;
1175             int mod, regop, rm;
1176             get_modrm(*data, &mod, &regop, &rm);
1177             AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1178             data += PrintRightOperand(data);
1179           } else {
1180             UnimplementedInstruction();
1181           }
1182         }
1183         break;
1184
1185       case 0x8F:
1186         { data++;
1187           int mod, regop, rm;
1188           get_modrm(*data, &mod, &regop, &rm);
1189           if (regop == eax) {
1190             AppendToBuffer("pop ");
1191             data += PrintRightOperand(data);
1192           }
1193         }
1194         break;
1195
1196       case 0xFF:
1197         { data++;
1198           int mod, regop, rm;
1199           get_modrm(*data, &mod, &regop, &rm);
1200           const char* mnem = NULL;
1201           switch (regop) {
1202             case esi: mnem = "push"; break;
1203             case eax: mnem = "inc"; break;
1204             case ecx: mnem = "dec"; break;
1205             case edx: mnem = "call"; break;
1206             case esp: mnem = "jmp"; break;
1207             default: mnem = "???";
1208           }
1209           AppendToBuffer("%s ", mnem);
1210           data += PrintRightOperand(data);
1211         }
1212         break;
1213
1214       case 0xC7:  // imm32, fall through
1215       case 0xC6:  // imm8
1216         { bool is_byte = *data == 0xC6;
1217           data++;
1218           if (is_byte) {
1219             AppendToBuffer("%s ", "mov_b");
1220             data += PrintRightByteOperand(data);
1221             int32_t imm = *data;
1222             AppendToBuffer(",0x%x", imm);
1223             data++;
1224           } else {
1225             AppendToBuffer("%s ", "mov");
1226             data += PrintRightOperand(data);
1227             int32_t imm = *reinterpret_cast<int32_t*>(data);
1228             AppendToBuffer(",0x%x", imm);
1229             data += 4;
1230           }
1231         }
1232         break;
1233
1234       case 0x80:
1235         { data++;
1236           int mod, regop, rm;
1237           get_modrm(*data, &mod, &regop, &rm);
1238           const char* mnem = NULL;
1239           switch (regop) {
1240             case 5:  mnem = "subb"; break;
1241             case 7:  mnem = "cmpb"; break;
1242             default: UnimplementedInstruction();
1243           }
1244           AppendToBuffer("%s ", mnem);
1245           data += PrintRightByteOperand(data);
1246           int32_t imm = *data;
1247           AppendToBuffer(",0x%x", imm);
1248           data++;
1249         }
1250         break;
1251
1252       case 0x88:  // 8bit, fall through
1253       case 0x89:  // 32bit
1254         { bool is_byte = *data == 0x88;
1255           int mod, regop, rm;
1256           data++;
1257           get_modrm(*data, &mod, &regop, &rm);
1258           if (is_byte) {
1259             AppendToBuffer("%s ", "mov_b");
1260             data += PrintRightByteOperand(data);
1261             AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1262           } else {
1263             AppendToBuffer("%s ", "mov");
1264             data += PrintRightOperand(data);
1265             AppendToBuffer(",%s", NameOfCPURegister(regop));
1266           }
1267         }
1268         break;
1269
1270       case 0x66:  // prefix
1271         while (*data == 0x66) data++;
1272         if (*data == 0xf && data[1] == 0x1f) {
1273           AppendToBuffer("nop");  // 0x66 prefix
1274         } else if (*data == 0x90) {
1275           AppendToBuffer("nop");  // 0x66 prefix
1276         } else if (*data == 0x8B) {
1277           data++;
1278           data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1279         } else if (*data == 0x89) {
1280           data++;
1281           int mod, regop, rm;
1282           get_modrm(*data, &mod, &regop, &rm);
1283           AppendToBuffer("mov_w ");
1284           data += PrintRightOperand(data);
1285           AppendToBuffer(",%s", NameOfCPURegister(regop));
1286         } else if (*data == 0xC7) {
1287           data++;
1288           AppendToBuffer("%s ", "mov_w");
1289           data += PrintRightOperand(data);
1290           int imm = *reinterpret_cast<int16_t*>(data);
1291           AppendToBuffer(",0x%x", imm);
1292           data += 2;
1293         } else if (*data == 0x0F) {
1294           data++;
1295           if (*data == 0x38) {
1296             data++;
1297             if (*data == 0x17) {
1298               data++;
1299               int mod, regop, rm;
1300               get_modrm(*data, &mod, &regop, &rm);
1301               AppendToBuffer("ptest %s,%s",
1302                              NameOfXMMRegister(regop),
1303                              NameOfXMMRegister(rm));
1304               data++;
1305             } else if (*data == 0x40) {
1306               data++;
1307               int mod, regop, rm;
1308               get_modrm(*data, &mod, &regop, &rm);
1309               AppendToBuffer("pmulld %s,%s",
1310                              NameOfXMMRegister(regop));
1311               data += PrintRightXMMOperand(data);
1312             } else if (*data == 0x2A) {
1313               // movntdqa
1314               data++;
1315               int mod, regop, rm;
1316               get_modrm(*data, &mod, &regop, &rm);
1317               AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop));
1318               data += PrintRightOperand(data);
1319             } else {
1320               UnimplementedInstruction();
1321             }
1322           } else if (*data == 0x3A) {
1323             data++;
1324             if (*data == 0x0B) {
1325               data++;
1326               int mod, regop, rm;
1327               get_modrm(*data, &mod, &regop, &rm);
1328               int8_t imm8 = static_cast<int8_t>(data[1]);
1329               AppendToBuffer("roundsd %s,%s,%d",
1330                              NameOfXMMRegister(regop),
1331                              NameOfXMMRegister(rm),
1332                              static_cast<int>(imm8));
1333               data += 2;
1334             } else if (*data == 0x16) {
1335               data++;
1336               int mod, regop, rm;
1337               get_modrm(*data, &mod, &regop, &rm);
1338               int8_t imm8 = static_cast<int8_t>(data[1]);
1339               AppendToBuffer("pextrd %s,%s,%d",
1340                              NameOfCPURegister(regop),
1341                              NameOfXMMRegister(rm),
1342                              static_cast<int>(imm8));
1343               data += 2;
1344             } else if (*data == 0x21) {
1345               data++;
1346               int mod, regop, rm;
1347               get_modrm(*data, &mod, &regop, &rm);
1348               int8_t imm8 = static_cast<int8_t>(data[1]);
1349               AppendToBuffer("insertps %s,%s,%d",
1350                              NameOfXMMRegister(regop),
1351                              NameOfXMMRegister(rm),
1352                              static_cast<int>(imm8));
1353               data += 2;
1354             } else if (*data == 0x17) {
1355               data++;
1356               int mod, regop, rm;
1357               get_modrm(*data, &mod, &regop, &rm);
1358               int8_t imm8 = static_cast<int8_t>(data[1]);
1359               AppendToBuffer("extractps %s,%s,%d",
1360                              NameOfCPURegister(rm),
1361                              NameOfXMMRegister(regop),
1362                              static_cast<int>(imm8));
1363               data += 2;
1364             } else if (*data == 0x22) {
1365               data++;
1366               int mod, regop, rm;
1367               get_modrm(*data, &mod, &regop, &rm);
1368               int8_t imm8 = static_cast<int8_t>(data[1]);
1369               AppendToBuffer("pinsrd %s,%s,%d",
1370                              NameOfXMMRegister(regop),
1371                              NameOfCPURegister(rm),
1372                              static_cast<int>(imm8));
1373               data += 2;
1374             } else {
1375               UnimplementedInstruction();
1376             }
1377           } else if (*data == 0x2E || *data == 0x2F) {
1378             const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
1379             data++;
1380             int mod, regop, rm;
1381             get_modrm(*data, &mod, &regop, &rm);
1382             if (mod == 0x3) {
1383               AppendToBuffer("%s %s,%s", mnem,
1384                              NameOfXMMRegister(regop),
1385                              NameOfXMMRegister(rm));
1386               data++;
1387             } else {
1388               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1389               data += PrintRightOperand(data);
1390             }
1391           } else if (*data == 0x50) {
1392             data++;
1393             int mod, regop, rm;
1394             get_modrm(*data, &mod, &regop, &rm);
1395             AppendToBuffer("movmskpd %s,%s",
1396                            NameOfCPURegister(regop),
1397                            NameOfXMMRegister(rm));
1398             data++;
1399           } else if (*data == 0x51) {
1400             data++;
1401             int mod, regop, rm;
1402             get_modrm(*data, &mod, &regop, &rm);
1403             AppendToBuffer("sqrtpd %s,%s",
1404                            NameOfXMMRegister(regop),
1405                            NameOfXMMRegister(rm));
1406             data++;
1407           } else if (*data == 0x54) {
1408             data++;
1409             int mod, regop, rm;
1410             get_modrm(*data, &mod, &regop, &rm);
1411             AppendToBuffer("andpd %s,%s",
1412                            NameOfXMMRegister(regop),
1413                            NameOfXMMRegister(rm));
1414             data++;
1415           } else if (*data == 0x56) {
1416             data++;
1417             int mod, regop, rm;
1418             get_modrm(*data, &mod, &regop, &rm);
1419             AppendToBuffer("orpd %s,%s",
1420                            NameOfXMMRegister(regop),
1421                            NameOfXMMRegister(rm));
1422             data++;
1423           } else if (*data == 0x57) {
1424             data++;
1425             int mod, regop, rm;
1426             get_modrm(*data, &mod, &regop, &rm);
1427             AppendToBuffer("xorpd %s,",
1428                            NameOfXMMRegister(regop));
1429             data += PrintRightXMMOperand(data);
1430           } else if (*data == 0x58) {
1431             data++;
1432             int mod, regop, rm;
1433             get_modrm(*data, &mod, &regop, &rm);
1434             AppendToBuffer("addpd %s,",
1435                            NameOfXMMRegister(regop));
1436             data += PrintRightXMMOperand(data);
1437           } else if (*data == 0x59) {
1438             data++;
1439             int mod, regop, rm;
1440             get_modrm(*data, &mod, &regop, &rm);
1441             AppendToBuffer("mulpd %s,",
1442                            NameOfXMMRegister(regop));
1443             data += PrintRightXMMOperand(data);
1444           } else if (*data == 0x5B) {
1445             data++;
1446             int mod, regop, rm;
1447             get_modrm(*data, &mod, &regop, &rm);
1448             AppendToBuffer("cvtps2dq %s,",
1449                            NameOfXMMRegister(regop));
1450             data += PrintRightXMMOperand(data);
1451           } else if (*data == 0x5C) {
1452             data++;
1453             int mod, regop, rm;
1454             get_modrm(*data, &mod, &regop, &rm);
1455             AppendToBuffer("subpd %s,",
1456                            NameOfXMMRegister(regop));
1457             data += PrintRightXMMOperand(data);
1458           } else if (*data == 0x5D) {
1459             data++;
1460             int mod, regop, rm;
1461             get_modrm(*data, &mod, &regop, &rm);
1462             AppendToBuffer("minpd %s,",
1463                            NameOfXMMRegister(regop));
1464             data += PrintRightXMMOperand(data);
1465           } else if (*data == 0x5E) {
1466             data++;
1467             int mod, regop, rm;
1468             get_modrm(*data, &mod, &regop, &rm);
1469             AppendToBuffer("divpd %s,",
1470                            NameOfXMMRegister(regop));
1471             data += PrintRightXMMOperand(data);
1472           } else if (*data == 0x5F) {
1473             data++;
1474             int mod, regop, rm;
1475             get_modrm(*data, &mod, &regop, &rm);
1476             AppendToBuffer("maxpd %s,",
1477                            NameOfXMMRegister(regop));
1478             data += PrintRightXMMOperand(data);
1479           } else if (*data == 0x62) {
1480             data++;
1481             int mod, regop, rm;
1482             get_modrm(*data, &mod, &regop, &rm);
1483             AppendToBuffer("punpackldq %s,",
1484                             NameOfXMMRegister(regop));
1485             data += PrintRightXMMOperand(data);
1486           } else if (*data == 0xD6) {
1487             AppendToBuffer("movq ");
1488             data += 3;
1489             int mod, regop, rm;
1490             get_modrm(*data, &mod, &regop, &rm);
1491             data += PrintRightXMMOperand(data);
1492             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1493           } else if (*data == 0xF4) {
1494             data++;
1495             int mod, regop, rm;
1496             get_modrm(*data, &mod, &regop, &rm);
1497             AppendToBuffer("pmuludq %s,",
1498                             NameOfXMMRegister(regop));
1499             data += PrintRightXMMOperand(data);
1500           } else if (*data == 0xFA) {
1501             data++;
1502             int mod, regop, rm;
1503             get_modrm(*data, &mod, &regop, &rm);
1504             AppendToBuffer("psubd %s,",
1505                             NameOfXMMRegister(regop));
1506             data += PrintRightXMMOperand(data);
1507           } else if (*data == 0xFE) {
1508             data++;
1509             int mod, regop, rm;
1510             get_modrm(*data, &mod, &regop, &rm);
1511             AppendToBuffer("paddd %s,",
1512                             NameOfXMMRegister(regop));
1513             data += PrintRightXMMOperand(data);
1514           } else if (*data == 0x6E) {
1515             data++;
1516             int mod, regop, rm;
1517             get_modrm(*data, &mod, &regop, &rm);
1518             AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
1519             data += PrintRightOperand(data);
1520           } else if (*data == 0x6F) {
1521             data++;
1522             int mod, regop, rm;
1523             get_modrm(*data, &mod, &regop, &rm);
1524             AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
1525             data += PrintRightXMMOperand(data);
1526           } else if (*data == 0x70) {
1527             data++;
1528             int mod, regop, rm;
1529             get_modrm(*data, &mod, &regop, &rm);
1530             int8_t imm8 = static_cast<int8_t>(data[1]);
1531             AppendToBuffer("pshufd %s,%s,%d",
1532                            NameOfXMMRegister(regop),
1533                            NameOfXMMRegister(rm),
1534                            static_cast<int>(imm8));
1535             data += 2;
1536           } else if (*data == 0x66) {
1537             data++;
1538             int mod, regop, rm;
1539             get_modrm(*data, &mod, &regop, &rm);
1540             AppendToBuffer("pcmpgtd %s,%s",
1541                            NameOfXMMRegister(regop),
1542                            NameOfXMMRegister(rm));
1543             data++;
1544           } else if (*data == 0x76) {
1545             data++;
1546             int mod, regop, rm;
1547             get_modrm(*data, &mod, &regop, &rm);
1548             AppendToBuffer("pcmpeqd %s,%s",
1549                            NameOfXMMRegister(regop),
1550                            NameOfXMMRegister(rm));
1551             data++;
1552           } else if (*data == 0x90) {
1553             data++;
1554             AppendToBuffer("nop");  // 2 byte nop.
1555           } else if (*data == 0xF3) {
1556             data++;
1557             int mod, regop, rm;
1558             get_modrm(*data, &mod, &regop, &rm);
1559             AppendToBuffer("psllq %s,%s",
1560                            NameOfXMMRegister(regop),
1561                            NameOfXMMRegister(rm));
1562             data++;
1563           } else if (*data == 0x72) {
1564             data++;
1565             int mod, regop, rm;
1566             get_modrm(*data, &mod, &regop, &rm);
1567             int8_t imm8 = static_cast<int8_t>(data[1]);
1568             DCHECK(regop == esi || regop == edx);
1569             AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld",
1570                            NameOfXMMRegister(rm), static_cast<int>(imm8));
1571             data += 2;
1572           } else if (*data == 0x73) {
1573             data++;
1574             int mod, regop, rm;
1575             get_modrm(*data, &mod, &regop, &rm);
1576             int8_t imm8 = static_cast<int8_t>(data[1]);
1577             DCHECK(regop == esi || regop == edx);
1578             AppendToBuffer("%s %s,%d",
1579                            (regop == esi) ? "psllq" : "psrlq",
1580                            NameOfXMMRegister(rm),
1581                            static_cast<int>(imm8));
1582             data += 2;
1583           } else if (*data == 0xF2) {
1584             data++;
1585             int mod, regop, rm;
1586             get_modrm(*data, &mod, &regop, &rm);
1587             AppendToBuffer("pslld %s,%s",
1588                            NameOfXMMRegister(regop),
1589                            NameOfXMMRegister(rm));
1590             data++;
1591           } else if (*data == 0x72) {
1592             data++;
1593             int mod, regop, rm;
1594             get_modrm(*data, &mod, &regop, &rm);
1595             int8_t imm8 = static_cast<int8_t>(data[1]);
1596             DCHECK(regop == esi || regop == edx);
1597             AppendToBuffer("%s %s,%d",
1598                            (regop == esi) ? "pslld"
1599                            : ((regop == edx) ? "psrld" : "psrad"),
1600                            NameOfXMMRegister(rm),
1601                            static_cast<int>(imm8));
1602             data += 2;
1603           } else if (*data == 0xC6) {
1604             data++;
1605             int mod, regop, rm;
1606             get_modrm(*data, &mod, &regop, &rm);
1607             int8_t imm8 = static_cast<int8_t>(data[1]);
1608             AppendToBuffer("shufpd %s,%s,%d",
1609                            NameOfXMMRegister(regop),
1610                            NameOfXMMRegister(rm),
1611                            static_cast<int>(imm8));
1612             data += 2;
1613           } else if (*data == 0xD2) {
1614             data++;
1615             int mod, regop, rm;
1616             get_modrm(*data, &mod, &regop, &rm);
1617             AppendToBuffer("psrld %s,%s",
1618                            NameOfXMMRegister(regop),
1619                            NameOfXMMRegister(rm));
1620             data++;
1621           } else if (*data == 0xD3) {
1622             data++;
1623             int mod, regop, rm;
1624             get_modrm(*data, &mod, &regop, &rm);
1625             AppendToBuffer("psrlq %s,%s",
1626                            NameOfXMMRegister(regop),
1627                            NameOfXMMRegister(rm));
1628             data++;
1629           } else if (*data == 0xE2) {
1630             data++;
1631             int mod, regop, rm;
1632             get_modrm(*data, &mod, &regop, &rm);
1633             AppendToBuffer("psrad %s,%s",
1634                            NameOfXMMRegister(regop),
1635                            NameOfXMMRegister(rm));
1636             data++;
1637           } else if (*data == 0x7F) {
1638             AppendToBuffer("movdqa ");
1639             data++;
1640             int mod, regop, rm;
1641             get_modrm(*data, &mod, &regop, &rm);
1642             data += PrintRightXMMOperand(data);
1643             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1644           } else if (*data == 0x7E) {
1645             data++;
1646             int mod, regop, rm;
1647             get_modrm(*data, &mod, &regop, &rm);
1648             AppendToBuffer("movd ");
1649             data += PrintRightOperand(data);
1650             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1651           } else if (*data == 0xDB) {
1652             data++;
1653             int mod, regop, rm;
1654             get_modrm(*data, &mod, &regop, &rm);
1655             AppendToBuffer("pand %s,%s",
1656                            NameOfXMMRegister(regop),
1657                            NameOfXMMRegister(rm));
1658             data++;
1659           } else if (*data == 0xE7) {
1660             data++;
1661             int mod, regop, rm;
1662             get_modrm(*data, &mod, &regop, &rm);
1663             if (mod == 3) {
1664               AppendToBuffer("movntdq ");
1665               data += PrintRightOperand(data);
1666               AppendToBuffer(",%s", NameOfXMMRegister(regop));
1667             } else {
1668               UnimplementedInstruction();
1669             }
1670           } else if (*data == 0xEF) {
1671             data++;
1672             int mod, regop, rm;
1673             get_modrm(*data, &mod, &regop, &rm);
1674             AppendToBuffer("pxor %s,%s",
1675                            NameOfXMMRegister(regop),
1676                            NameOfXMMRegister(rm));
1677             data++;
1678           } else if (*data == 0xEB) {
1679             data++;
1680             int mod, regop, rm;
1681             get_modrm(*data, &mod, &regop, &rm);
1682             AppendToBuffer("por %s,%s",
1683                            NameOfXMMRegister(regop),
1684                            NameOfXMMRegister(rm));
1685             data++;
1686           } else {
1687             UnimplementedInstruction();
1688           }
1689         } else {
1690           UnimplementedInstruction();
1691         }
1692         break;
1693
1694       case 0xFE:
1695         { data++;
1696           int mod, regop, rm;
1697           get_modrm(*data, &mod, &regop, &rm);
1698           if (regop == ecx) {
1699             AppendToBuffer("dec_b ");
1700             data += PrintRightOperand(data);
1701           } else {
1702             UnimplementedInstruction();
1703           }
1704         }
1705         break;
1706
1707       case 0x68:
1708         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1709         data += 5;
1710         break;
1711
1712       case 0x6A:
1713         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1714         data += 2;
1715         break;
1716
1717       case 0xA8:
1718         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1719         data += 2;
1720         break;
1721
1722       case 0xA9:
1723         AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1724         data += 5;
1725         break;
1726
1727       case 0xD1:  // fall through
1728       case 0xD3:  // fall through
1729       case 0xC1:
1730         data += D1D3C1Instruction(data);
1731         break;
1732
1733       case 0xD8:  // fall through
1734       case 0xD9:  // fall through
1735       case 0xDA:  // fall through
1736       case 0xDB:  // fall through
1737       case 0xDC:  // fall through
1738       case 0xDD:  // fall through
1739       case 0xDE:  // fall through
1740       case 0xDF:
1741         data += FPUInstruction(data);
1742         break;
1743
1744       case 0xEB:
1745         data += JumpShort(data);
1746         break;
1747
1748       case 0xF2:
1749         if (*(data+1) == 0x0F) {
1750           byte b2 = *(data+2);
1751           if (b2 == 0x11) {
1752             AppendToBuffer("movsd ");
1753             data += 3;
1754             int mod, regop, rm;
1755             get_modrm(*data, &mod, &regop, &rm);
1756             data += PrintRightXMMOperand(data);
1757             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1758           } else if (b2 == 0x10) {
1759             data += 3;
1760             int mod, regop, rm;
1761             get_modrm(*data, &mod, &regop, &rm);
1762             AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
1763             data += PrintRightXMMOperand(data);
1764           } else  if (b2 == 0x5A) {
1765             data += 3;
1766             int mod, regop, rm;
1767             get_modrm(*data, &mod, &regop, &rm);
1768             AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
1769             data += PrintRightXMMOperand(data);
1770           } else {
1771             const char* mnem = "?";
1772             switch (b2) {
1773               case 0x2A: mnem = "cvtsi2sd"; break;
1774               case 0x2C: mnem = "cvttsd2si"; break;
1775               case 0x2D: mnem = "cvtsd2si"; break;
1776               case 0x51: mnem = "sqrtsd"; break;
1777               case 0x58: mnem = "addsd"; break;
1778               case 0x59: mnem = "mulsd"; break;
1779               case 0x5C: mnem = "subsd"; break;
1780               case 0x5E: mnem = "divsd"; break;
1781             }
1782             data += 3;
1783             int mod, regop, rm;
1784             get_modrm(*data, &mod, &regop, &rm);
1785             if (b2 == 0x2A) {
1786               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1787               data += PrintRightOperand(data);
1788             } else if (b2 == 0x2C || b2 == 0x2D) {
1789               AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
1790               data += PrintRightXMMOperand(data);
1791             } else if (b2 == 0xC2) {
1792               // Intel manual 2A, Table 3-18.
1793               const char* const pseudo_op[] = {
1794                 "cmpeqsd",
1795                 "cmpltsd",
1796                 "cmplesd",
1797                 "cmpunordsd",
1798                 "cmpneqsd",
1799                 "cmpnltsd",
1800                 "cmpnlesd",
1801                 "cmpordsd"
1802               };
1803               AppendToBuffer("%s %s,%s",
1804                              pseudo_op[data[1]],
1805                              NameOfXMMRegister(regop),
1806                              NameOfXMMRegister(rm));
1807               data += 2;
1808             } else {
1809               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1810               data += PrintRightXMMOperand(data);
1811             }
1812           }
1813         } else {
1814           UnimplementedInstruction();
1815         }
1816         break;
1817
1818       case 0xF3:
1819         if (*(data+1) == 0x0F) {
1820           byte b2 = *(data+2);
1821           if (b2 == 0x11) {
1822             AppendToBuffer("movss ");
1823             data += 3;
1824             int mod, regop, rm;
1825             get_modrm(*data, &mod, &regop, &rm);
1826             data += PrintRightXMMOperand(data);
1827             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1828           } else if (b2 == 0x10) {
1829             data += 3;
1830             int mod, regop, rm;
1831             get_modrm(*data, &mod, &regop, &rm);
1832             AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
1833             data += PrintRightXMMOperand(data);
1834           } else if (b2 == 0x2C) {
1835             data += 3;
1836             int mod, regop, rm;
1837             get_modrm(*data, &mod, &regop, &rm);
1838             AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
1839             data += PrintRightXMMOperand(data);
1840           } else if (b2 == 0x5A) {
1841             data += 3;
1842             int mod, regop, rm;
1843             get_modrm(*data, &mod, &regop, &rm);
1844             AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1845             data += PrintRightXMMOperand(data);
1846           } else if (b2 == 0x6F) {
1847             data += 3;
1848             int mod, regop, rm;
1849             get_modrm(*data, &mod, &regop, &rm);
1850             AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
1851             data += PrintRightXMMOperand(data);
1852           } else if (b2 == 0x7F) {
1853             AppendToBuffer("movdqu ");
1854             data += 3;
1855             int mod, regop, rm;
1856             get_modrm(*data, &mod, &regop, &rm);
1857             data += PrintRightXMMOperand(data);
1858             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1859           } else if (b2 == 0x7E) {
1860             data += 3;
1861             int mod, regop, rm;
1862             get_modrm(*data, &mod, &regop, &rm);
1863             AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
1864             data += PrintRightXMMOperand(data);
1865           } else {
1866             UnimplementedInstruction();
1867           }
1868         } else if (*(data+1) == 0xA5) {
1869           data += 2;
1870           AppendToBuffer("rep_movs");
1871         } else if (*(data+1) == 0xAB) {
1872           data += 2;
1873           AppendToBuffer("rep_stos");
1874         } else {
1875           UnimplementedInstruction();
1876         }
1877         break;
1878
1879       case 0xF7:
1880         data += F7Instruction(data);
1881         break;
1882
1883       default:
1884         UnimplementedInstruction();
1885     }
1886   }
1887
1888   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1889     tmp_buffer_[tmp_buffer_pos_] = '\0';
1890   }
1891
1892   int instr_len = data - instr;
1893   if (instr_len == 0) {
1894     printf("%02x", *data);
1895   }
1896   DCHECK(instr_len > 0);  // Ensure progress.
1897
1898   int outp = 0;
1899   // Instruction bytes.
1900   for (byte* bp = instr; bp < data; bp++) {
1901     outp += v8::internal::SNPrintF(out_buffer + outp,
1902                                    "%02x",
1903                                    *bp);
1904   }
1905   for (int i = 6 - instr_len; i >= 0; i--) {
1906     outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
1907   }
1908
1909   outp += v8::internal::SNPrintF(out_buffer + outp,
1910                                  " %s",
1911                                  tmp_buffer_.start());
1912   return instr_len;
1913 }  // NOLINT (function is too long)
1914
1915
1916 //------------------------------------------------------------------------------
1917
1918
1919 static const char* const cpu_regs[8] = {
1920   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
1921 };
1922
1923
1924 static const char* const byte_cpu_regs[8] = {
1925   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
1926 };
1927
1928
1929 static const char* const xmm_regs[8] = {
1930   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
1931 };
1932
1933
1934 const char* NameConverter::NameOfAddress(byte* addr) const {
1935   v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1936   return tmp_buffer_.start();
1937 }
1938
1939
1940 const char* NameConverter::NameOfConstant(byte* addr) const {
1941   return NameOfAddress(addr);
1942 }
1943
1944
1945 const char* NameConverter::NameOfCPURegister(int reg) const {
1946   if (0 <= reg && reg < 8) return cpu_regs[reg];
1947   return "noreg";
1948 }
1949
1950
1951 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1952   if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
1953   return "noreg";
1954 }
1955
1956
1957 const char* NameConverter::NameOfXMMRegister(int reg) const {
1958   if (0 <= reg && reg < 8) return xmm_regs[reg];
1959   return "noxmmreg";
1960 }
1961
1962
1963 const char* NameConverter::NameInCode(byte* addr) const {
1964   // IA32 does not embed debug strings at the moment.
1965   UNREACHABLE();
1966   return "";
1967 }
1968
1969
1970 //------------------------------------------------------------------------------
1971
1972 Disassembler::Disassembler(const NameConverter& converter)
1973     : converter_(converter) {}
1974
1975
1976 Disassembler::~Disassembler() {}
1977
1978
1979 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1980                                     byte* instruction) {
1981   DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
1982   return d.InstructionDecode(buffer, instruction);
1983 }
1984
1985
1986 // The IA-32 assembler does not currently use constant pools.
1987 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1988
1989
1990 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1991   NameConverter converter;
1992   Disassembler d(converter);
1993   for (byte* pc = begin; pc < end;) {
1994     v8::internal::EmbeddedVector<char, 128> buffer;
1995     buffer[0] = '\0';
1996     byte* prev_pc = pc;
1997     pc += d.InstructionDecode(buffer, pc);
1998     fprintf(f, "%p", prev_pc);
1999     fprintf(f, "    ");
2000
2001     for (byte* bp = prev_pc; bp < pc; bp++) {
2002       fprintf(f, "%02x",  *bp);
2003     }
2004     for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
2005       fprintf(f, "  ");
2006     }
2007     fprintf(f, "  %s\n", buffer.start());
2008   }
2009 }
2010
2011
2012 }  // namespace disasm
2013
2014 #endif  // V8_TARGET_ARCH_IA32