a93e57a4d2b9fefaee9dd094c765f7c0baf90f64
[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 == 0x73) {
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",
1570                            (regop == esi) ? "psllq" : "psrlq",
1571                            NameOfXMMRegister(rm),
1572                            static_cast<int>(imm8));
1573             data += 2;
1574           } else if (*data == 0xF2) {
1575             data++;
1576             int mod, regop, rm;
1577             get_modrm(*data, &mod, &regop, &rm);
1578             AppendToBuffer("pslld %s,%s",
1579                            NameOfXMMRegister(regop),
1580                            NameOfXMMRegister(rm));
1581             data++;
1582           } else if (*data == 0x72) {
1583             data++;
1584             int mod, regop, rm;
1585             get_modrm(*data, &mod, &regop, &rm);
1586             int8_t imm8 = static_cast<int8_t>(data[1]);
1587             DCHECK(regop == esi || regop == edx);
1588             AppendToBuffer("%s %s,%d",
1589                            (regop == esi) ? "pslld"
1590                            : ((regop == edx) ? "psrld" : "psrad"),
1591                            NameOfXMMRegister(rm),
1592                            static_cast<int>(imm8));
1593             data += 2;
1594           } else if (*data == 0xC6) {
1595             data++;
1596             int mod, regop, rm;
1597             get_modrm(*data, &mod, &regop, &rm);
1598             int8_t imm8 = static_cast<int8_t>(data[1]);
1599             AppendToBuffer("shufpd %s,%s,%d",
1600                            NameOfXMMRegister(regop),
1601                            NameOfXMMRegister(rm),
1602                            static_cast<int>(imm8));
1603             data += 2;
1604           } else if (*data == 0xD2) {
1605             data++;
1606             int mod, regop, rm;
1607             get_modrm(*data, &mod, &regop, &rm);
1608             AppendToBuffer("psrld %s,%s",
1609                            NameOfXMMRegister(regop),
1610                            NameOfXMMRegister(rm));
1611             data++;
1612           } else if (*data == 0xD3) {
1613             data++;
1614             int mod, regop, rm;
1615             get_modrm(*data, &mod, &regop, &rm);
1616             AppendToBuffer("psrlq %s,%s",
1617                            NameOfXMMRegister(regop),
1618                            NameOfXMMRegister(rm));
1619             data++;
1620           } else if (*data == 0xE2) {
1621             data++;
1622             int mod, regop, rm;
1623             get_modrm(*data, &mod, &regop, &rm);
1624             AppendToBuffer("psrad %s,%s",
1625                            NameOfXMMRegister(regop),
1626                            NameOfXMMRegister(rm));
1627             data++;
1628           } else if (*data == 0x7F) {
1629             AppendToBuffer("movdqa ");
1630             data++;
1631             int mod, regop, rm;
1632             get_modrm(*data, &mod, &regop, &rm);
1633             data += PrintRightXMMOperand(data);
1634             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1635           } else if (*data == 0x7E) {
1636             data++;
1637             int mod, regop, rm;
1638             get_modrm(*data, &mod, &regop, &rm);
1639             AppendToBuffer("movd ");
1640             data += PrintRightOperand(data);
1641             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1642           } else if (*data == 0xDB) {
1643             data++;
1644             int mod, regop, rm;
1645             get_modrm(*data, &mod, &regop, &rm);
1646             AppendToBuffer("pand %s,%s",
1647                            NameOfXMMRegister(regop),
1648                            NameOfXMMRegister(rm));
1649             data++;
1650           } else if (*data == 0xE7) {
1651             data++;
1652             int mod, regop, rm;
1653             get_modrm(*data, &mod, &regop, &rm);
1654             if (mod == 3) {
1655               AppendToBuffer("movntdq ");
1656               data += PrintRightOperand(data);
1657               AppendToBuffer(",%s", NameOfXMMRegister(regop));
1658             } else {
1659               UnimplementedInstruction();
1660             }
1661           } else if (*data == 0xEF) {
1662             data++;
1663             int mod, regop, rm;
1664             get_modrm(*data, &mod, &regop, &rm);
1665             AppendToBuffer("pxor %s,%s",
1666                            NameOfXMMRegister(regop),
1667                            NameOfXMMRegister(rm));
1668             data++;
1669           } else if (*data == 0xEB) {
1670             data++;
1671             int mod, regop, rm;
1672             get_modrm(*data, &mod, &regop, &rm);
1673             AppendToBuffer("por %s,%s",
1674                            NameOfXMMRegister(regop),
1675                            NameOfXMMRegister(rm));
1676             data++;
1677           } else {
1678             UnimplementedInstruction();
1679           }
1680         } else {
1681           UnimplementedInstruction();
1682         }
1683         break;
1684
1685       case 0xFE:
1686         { data++;
1687           int mod, regop, rm;
1688           get_modrm(*data, &mod, &regop, &rm);
1689           if (regop == ecx) {
1690             AppendToBuffer("dec_b ");
1691             data += PrintRightOperand(data);
1692           } else {
1693             UnimplementedInstruction();
1694           }
1695         }
1696         break;
1697
1698       case 0x68:
1699         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1700         data += 5;
1701         break;
1702
1703       case 0x6A:
1704         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1705         data += 2;
1706         break;
1707
1708       case 0xA8:
1709         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1710         data += 2;
1711         break;
1712
1713       case 0xA9:
1714         AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1715         data += 5;
1716         break;
1717
1718       case 0xD1:  // fall through
1719       case 0xD3:  // fall through
1720       case 0xC1:
1721         data += D1D3C1Instruction(data);
1722         break;
1723
1724       case 0xD8:  // fall through
1725       case 0xD9:  // fall through
1726       case 0xDA:  // fall through
1727       case 0xDB:  // fall through
1728       case 0xDC:  // fall through
1729       case 0xDD:  // fall through
1730       case 0xDE:  // fall through
1731       case 0xDF:
1732         data += FPUInstruction(data);
1733         break;
1734
1735       case 0xEB:
1736         data += JumpShort(data);
1737         break;
1738
1739       case 0xF2:
1740         if (*(data+1) == 0x0F) {
1741           byte b2 = *(data+2);
1742           if (b2 == 0x11) {
1743             AppendToBuffer("movsd ");
1744             data += 3;
1745             int mod, regop, rm;
1746             get_modrm(*data, &mod, &regop, &rm);
1747             data += PrintRightXMMOperand(data);
1748             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1749           } else if (b2 == 0x10) {
1750             data += 3;
1751             int mod, regop, rm;
1752             get_modrm(*data, &mod, &regop, &rm);
1753             AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
1754             data += PrintRightXMMOperand(data);
1755           } else  if (b2 == 0x5A) {
1756             data += 3;
1757             int mod, regop, rm;
1758             get_modrm(*data, &mod, &regop, &rm);
1759             AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
1760             data += PrintRightXMMOperand(data);
1761           } else {
1762             const char* mnem = "?";
1763             switch (b2) {
1764               case 0x2A: mnem = "cvtsi2sd"; break;
1765               case 0x2C: mnem = "cvttsd2si"; break;
1766               case 0x2D: mnem = "cvtsd2si"; break;
1767               case 0x51: mnem = "sqrtsd"; break;
1768               case 0x58: mnem = "addsd"; break;
1769               case 0x59: mnem = "mulsd"; break;
1770               case 0x5C: mnem = "subsd"; break;
1771               case 0x5E: mnem = "divsd"; break;
1772             }
1773             data += 3;
1774             int mod, regop, rm;
1775             get_modrm(*data, &mod, &regop, &rm);
1776             if (b2 == 0x2A) {
1777               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1778               data += PrintRightOperand(data);
1779             } else if (b2 == 0x2C || b2 == 0x2D) {
1780               AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
1781               data += PrintRightXMMOperand(data);
1782             } else if (b2 == 0xC2) {
1783               // Intel manual 2A, Table 3-18.
1784               const char* const pseudo_op[] = {
1785                 "cmpeqsd",
1786                 "cmpltsd",
1787                 "cmplesd",
1788                 "cmpunordsd",
1789                 "cmpneqsd",
1790                 "cmpnltsd",
1791                 "cmpnlesd",
1792                 "cmpordsd"
1793               };
1794               AppendToBuffer("%s %s,%s",
1795                              pseudo_op[data[1]],
1796                              NameOfXMMRegister(regop),
1797                              NameOfXMMRegister(rm));
1798               data += 2;
1799             } else {
1800               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1801               data += PrintRightXMMOperand(data);
1802             }
1803           }
1804         } else {
1805           UnimplementedInstruction();
1806         }
1807         break;
1808
1809       case 0xF3:
1810         if (*(data+1) == 0x0F) {
1811           byte b2 = *(data+2);
1812           if (b2 == 0x11) {
1813             AppendToBuffer("movss ");
1814             data += 3;
1815             int mod, regop, rm;
1816             get_modrm(*data, &mod, &regop, &rm);
1817             data += PrintRightXMMOperand(data);
1818             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1819           } else if (b2 == 0x10) {
1820             data += 3;
1821             int mod, regop, rm;
1822             get_modrm(*data, &mod, &regop, &rm);
1823             AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
1824             data += PrintRightXMMOperand(data);
1825           } else if (b2 == 0x2C) {
1826             data += 3;
1827             int mod, regop, rm;
1828             get_modrm(*data, &mod, &regop, &rm);
1829             AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
1830             data += PrintRightXMMOperand(data);
1831           } else if (b2 == 0x5A) {
1832             data += 3;
1833             int mod, regop, rm;
1834             get_modrm(*data, &mod, &regop, &rm);
1835             AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1836             data += PrintRightXMMOperand(data);
1837           } else if (b2 == 0x6F) {
1838             data += 3;
1839             int mod, regop, rm;
1840             get_modrm(*data, &mod, &regop, &rm);
1841             AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
1842             data += PrintRightXMMOperand(data);
1843           } else if (b2 == 0x7F) {
1844             AppendToBuffer("movdqu ");
1845             data += 3;
1846             int mod, regop, rm;
1847             get_modrm(*data, &mod, &regop, &rm);
1848             data += PrintRightXMMOperand(data);
1849             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1850           } else if (b2 == 0x7E) {
1851             data += 3;
1852             int mod, regop, rm;
1853             get_modrm(*data, &mod, &regop, &rm);
1854             AppendToBuffer("movq %s,", NameOfXMMRegister(regop));
1855             data += PrintRightXMMOperand(data);
1856           } else {
1857             UnimplementedInstruction();
1858           }
1859         } else if (*(data+1) == 0xA5) {
1860           data += 2;
1861           AppendToBuffer("rep_movs");
1862         } else if (*(data+1) == 0xAB) {
1863           data += 2;
1864           AppendToBuffer("rep_stos");
1865         } else {
1866           UnimplementedInstruction();
1867         }
1868         break;
1869
1870       case 0xF7:
1871         data += F7Instruction(data);
1872         break;
1873
1874       default:
1875         UnimplementedInstruction();
1876     }
1877   }
1878
1879   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1880     tmp_buffer_[tmp_buffer_pos_] = '\0';
1881   }
1882
1883   int instr_len = data - instr;
1884   if (instr_len == 0) {
1885     printf("%02x", *data);
1886   }
1887   DCHECK(instr_len > 0);  // Ensure progress.
1888
1889   int outp = 0;
1890   // Instruction bytes.
1891   for (byte* bp = instr; bp < data; bp++) {
1892     outp += v8::internal::SNPrintF(out_buffer + outp,
1893                                    "%02x",
1894                                    *bp);
1895   }
1896   for (int i = 6 - instr_len; i >= 0; i--) {
1897     outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
1898   }
1899
1900   outp += v8::internal::SNPrintF(out_buffer + outp,
1901                                  " %s",
1902                                  tmp_buffer_.start());
1903   return instr_len;
1904 }  // NOLINT (function is too long)
1905
1906
1907 //------------------------------------------------------------------------------
1908
1909
1910 static const char* cpu_regs[8] = {
1911   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
1912 };
1913
1914
1915 static const char* byte_cpu_regs[8] = {
1916   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
1917 };
1918
1919
1920 static const char* xmm_regs[8] = {
1921   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
1922 };
1923
1924
1925 const char* NameConverter::NameOfAddress(byte* addr) const {
1926   v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1927   return tmp_buffer_.start();
1928 }
1929
1930
1931 const char* NameConverter::NameOfConstant(byte* addr) const {
1932   return NameOfAddress(addr);
1933 }
1934
1935
1936 const char* NameConverter::NameOfCPURegister(int reg) const {
1937   if (0 <= reg && reg < 8) return cpu_regs[reg];
1938   return "noreg";
1939 }
1940
1941
1942 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1943   if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
1944   return "noreg";
1945 }
1946
1947
1948 const char* NameConverter::NameOfXMMRegister(int reg) const {
1949   if (0 <= reg && reg < 8) return xmm_regs[reg];
1950   return "noxmmreg";
1951 }
1952
1953
1954 const char* NameConverter::NameInCode(byte* addr) const {
1955   // IA32 does not embed debug strings at the moment.
1956   UNREACHABLE();
1957   return "";
1958 }
1959
1960
1961 //------------------------------------------------------------------------------
1962
1963 Disassembler::Disassembler(const NameConverter& converter)
1964     : converter_(converter) {}
1965
1966
1967 Disassembler::~Disassembler() {}
1968
1969
1970 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1971                                     byte* instruction) {
1972   DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
1973   return d.InstructionDecode(buffer, instruction);
1974 }
1975
1976
1977 // The IA-32 assembler does not currently use constant pools.
1978 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1979
1980
1981 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1982   NameConverter converter;
1983   Disassembler d(converter);
1984   for (byte* pc = begin; pc < end;) {
1985     v8::internal::EmbeddedVector<char, 128> buffer;
1986     buffer[0] = '\0';
1987     byte* prev_pc = pc;
1988     pc += d.InstructionDecode(buffer, pc);
1989     fprintf(f, "%p", prev_pc);
1990     fprintf(f, "    ");
1991
1992     for (byte* bp = prev_pc; bp < pc; bp++) {
1993       fprintf(f, "%02x",  *bp);
1994     }
1995     for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1996       fprintf(f, "  ");
1997     }
1998     fprintf(f, "  %s\n", buffer.start());
1999   }
2000 }
2001
2002
2003 }  // namespace disasm
2004
2005 #endif  // V8_TARGET_ARCH_IA32