Upstream version 7.36.149.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 <stdio.h>
7 #include <stdarg.h>
8
9 #include "v8.h"
10
11 #if V8_TARGET_ARCH_IA32
12
13 #include "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     ASSERT_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     ASSERT_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     ASSERT_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::OS::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   ASSERT_EQ(0xF7, *data);
532   byte modrm = *(data+1);
533   int mod, regop, rm;
534   get_modrm(modrm, &mod, &regop, &rm);
535   if (mod == 3 && regop != 0) {
536     const char* mnem = NULL;
537     switch (regop) {
538       case 2: mnem = "not"; break;
539       case 3: mnem = "neg"; break;
540       case 4: mnem = "mul"; break;
541       case 5: mnem = "imul"; break;
542       case 7: mnem = "idiv"; break;
543       default: UnimplementedInstruction();
544     }
545     AppendToBuffer("%s %s", mnem, NameOfCPURegister(rm));
546     return 2;
547   } else if (mod == 3 && regop == eax) {
548     int32_t imm = *reinterpret_cast<int32_t*>(data+2);
549     AppendToBuffer("test %s,0x%x", NameOfCPURegister(rm), imm);
550     return 6;
551   } else if (regop == eax) {
552     AppendToBuffer("test ");
553     int count = PrintRightOperand(data+1);
554     int32_t imm = *reinterpret_cast<int32_t*>(data+1+count);
555     AppendToBuffer(",0x%x", imm);
556     return 1+count+4 /*int32_t*/;
557   } else {
558     UnimplementedInstruction();
559     return 2;
560   }
561 }
562
563
564 int DisassemblerIA32::D1D3C1Instruction(byte* data) {
565   byte op = *data;
566   ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1);
567   byte modrm = *(data+1);
568   int mod, regop, rm;
569   get_modrm(modrm, &mod, &regop, &rm);
570   int imm8 = -1;
571   int num_bytes = 2;
572   if (mod == 3) {
573     const char* mnem = NULL;
574     switch (regop) {
575       case kROL: mnem = "rol"; break;
576       case kROR: mnem = "ror"; break;
577       case kRCL: mnem = "rcl"; break;
578       case kRCR: mnem = "rcr"; break;
579       case kSHL: mnem = "shl"; break;
580       case KSHR: mnem = "shr"; break;
581       case kSAR: mnem = "sar"; break;
582       default: UnimplementedInstruction();
583     }
584     if (op == 0xD1) {
585       imm8 = 1;
586     } else if (op == 0xC1) {
587       imm8 = *(data+2);
588       num_bytes = 3;
589     } else if (op == 0xD3) {
590       // Shift/rotate by cl.
591     }
592     ASSERT_NE(NULL, mnem);
593     AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm));
594     if (imm8 >= 0) {
595       AppendToBuffer("%d", imm8);
596     } else {
597       AppendToBuffer("cl");
598     }
599   } else {
600     UnimplementedInstruction();
601   }
602   return num_bytes;
603 }
604
605
606 // Returns number of bytes used, including *data.
607 int DisassemblerIA32::JumpShort(byte* data) {
608   ASSERT_EQ(0xEB, *data);
609   byte b = *(data+1);
610   byte* dest = data + static_cast<int8_t>(b) + 2;
611   AppendToBuffer("jmp %s", NameOfAddress(dest));
612   return 2;
613 }
614
615
616 // Returns number of bytes used, including *data.
617 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
618   ASSERT_EQ(0x0F, *data);
619   byte cond = *(data+1) & 0x0F;
620   byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
621   const char* mnem = jump_conditional_mnem[cond];
622   AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
623   if (comment != NULL) {
624     AppendToBuffer(", %s", comment);
625   }
626   return 6;  // includes 0x0F
627 }
628
629
630 // Returns number of bytes used, including *data.
631 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
632   byte cond = *data & 0x0F;
633   byte b = *(data+1);
634   byte* dest = data + static_cast<int8_t>(b) + 2;
635   const char* mnem = jump_conditional_mnem[cond];
636   AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
637   if (comment != NULL) {
638     AppendToBuffer(", %s", comment);
639   }
640   return 2;
641 }
642
643
644 // Returns number of bytes used, including *data.
645 int DisassemblerIA32::SetCC(byte* data) {
646   ASSERT_EQ(0x0F, *data);
647   byte cond = *(data+1) & 0x0F;
648   const char* mnem = set_conditional_mnem[cond];
649   AppendToBuffer("%s ", mnem);
650   PrintRightByteOperand(data+2);
651   return 3;  // Includes 0x0F.
652 }
653
654
655 // Returns number of bytes used, including *data.
656 int DisassemblerIA32::CMov(byte* data) {
657   ASSERT_EQ(0x0F, *data);
658   byte cond = *(data + 1) & 0x0F;
659   const char* mnem = conditional_move_mnem[cond];
660   int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
661   return 2 + op_size;  // includes 0x0F
662 }
663
664
665 // Returns number of bytes used, including *data.
666 int DisassemblerIA32::FPUInstruction(byte* data) {
667   byte escape_opcode = *data;
668   ASSERT_EQ(0xD8, escape_opcode & 0xF8);
669   byte modrm_byte = *(data+1);
670
671   if (modrm_byte >= 0xC0) {
672     return RegisterFPUInstruction(escape_opcode, modrm_byte);
673   } else {
674     return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
675   }
676 }
677
678 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
679                                            int modrm_byte,
680                                            byte* modrm_start) {
681   const char* mnem = "?";
682   int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
683   switch (escape_opcode) {
684     case 0xD9: switch (regop) {
685         case 0: mnem = "fld_s"; break;
686         case 2: mnem = "fst_s"; break;
687         case 3: mnem = "fstp_s"; break;
688         case 7: mnem = "fstcw"; break;
689         default: UnimplementedInstruction();
690       }
691       break;
692
693     case 0xDB: switch (regop) {
694         case 0: mnem = "fild_s"; break;
695         case 1: mnem = "fisttp_s"; break;
696         case 2: mnem = "fist_s"; break;
697         case 3: mnem = "fistp_s"; break;
698         default: UnimplementedInstruction();
699       }
700       break;
701
702     case 0xDD: switch (regop) {
703         case 0: mnem = "fld_d"; break;
704         case 1: mnem = "fisttp_d"; break;
705         case 2: mnem = "fst_d"; break;
706         case 3: mnem = "fstp_d"; break;
707         default: UnimplementedInstruction();
708       }
709       break;
710
711     case 0xDF: switch (regop) {
712         case 5: mnem = "fild_d"; break;
713         case 7: mnem = "fistp_d"; break;
714         default: UnimplementedInstruction();
715       }
716       break;
717
718     default: UnimplementedInstruction();
719   }
720   AppendToBuffer("%s ", mnem);
721   int count = PrintRightOperand(modrm_start);
722   return count + 1;
723 }
724
725 int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
726                                              byte modrm_byte) {
727   bool has_register = false;  // Is the FPU register encoded in modrm_byte?
728   const char* mnem = "?";
729
730   switch (escape_opcode) {
731     case 0xD8:
732       has_register = true;
733       switch (modrm_byte & 0xF8) {
734         case 0xC0: mnem = "fadd_i"; break;
735         case 0xE0: mnem = "fsub_i"; break;
736         case 0xC8: mnem = "fmul_i"; break;
737         case 0xF0: mnem = "fdiv_i"; break;
738         default: UnimplementedInstruction();
739       }
740       break;
741
742     case 0xD9:
743       switch (modrm_byte & 0xF8) {
744         case 0xC0:
745           mnem = "fld";
746           has_register = true;
747           break;
748         case 0xC8:
749           mnem = "fxch";
750           has_register = true;
751           break;
752         default:
753           switch (modrm_byte) {
754             case 0xE0: mnem = "fchs"; break;
755             case 0xE1: mnem = "fabs"; break;
756             case 0xE4: mnem = "ftst"; break;
757             case 0xE8: mnem = "fld1"; break;
758             case 0xEB: mnem = "fldpi"; break;
759             case 0xED: mnem = "fldln2"; break;
760             case 0xEE: mnem = "fldz"; break;
761             case 0xF0: mnem = "f2xm1"; break;
762             case 0xF1: mnem = "fyl2x"; break;
763             case 0xF4: mnem = "fxtract"; break;
764             case 0xF5: mnem = "fprem1"; break;
765             case 0xF7: mnem = "fincstp"; break;
766             case 0xF8: mnem = "fprem"; break;
767             case 0xFC: mnem = "frndint"; break;
768             case 0xFD: mnem = "fscale"; break;
769             case 0xFE: mnem = "fsin"; break;
770             case 0xFF: mnem = "fcos"; break;
771             default: UnimplementedInstruction();
772           }
773       }
774       break;
775
776     case 0xDA:
777       if (modrm_byte == 0xE9) {
778         mnem = "fucompp";
779       } else {
780         UnimplementedInstruction();
781       }
782       break;
783
784     case 0xDB:
785       if ((modrm_byte & 0xF8) == 0xE8) {
786         mnem = "fucomi";
787         has_register = true;
788       } else if (modrm_byte  == 0xE2) {
789         mnem = "fclex";
790       } else if (modrm_byte == 0xE3) {
791         mnem = "fninit";
792       } else {
793         UnimplementedInstruction();
794       }
795       break;
796
797     case 0xDC:
798       has_register = true;
799       switch (modrm_byte & 0xF8) {
800         case 0xC0: mnem = "fadd"; break;
801         case 0xE8: mnem = "fsub"; break;
802         case 0xC8: mnem = "fmul"; break;
803         case 0xF8: mnem = "fdiv"; break;
804         default: UnimplementedInstruction();
805       }
806       break;
807
808     case 0xDD:
809       has_register = true;
810       switch (modrm_byte & 0xF8) {
811         case 0xC0: mnem = "ffree"; break;
812         case 0xD0: mnem = "fst"; break;
813         case 0xD8: mnem = "fstp"; break;
814         default: UnimplementedInstruction();
815       }
816       break;
817
818     case 0xDE:
819       if (modrm_byte  == 0xD9) {
820         mnem = "fcompp";
821       } else {
822         has_register = true;
823         switch (modrm_byte & 0xF8) {
824           case 0xC0: mnem = "faddp"; break;
825           case 0xE8: mnem = "fsubp"; break;
826           case 0xC8: mnem = "fmulp"; break;
827           case 0xF8: mnem = "fdivp"; break;
828           default: UnimplementedInstruction();
829         }
830       }
831       break;
832
833     case 0xDF:
834       if (modrm_byte == 0xE0) {
835         mnem = "fnstsw_ax";
836       } else if ((modrm_byte & 0xF8) == 0xE8) {
837         mnem = "fucomip";
838         has_register = true;
839       }
840       break;
841
842     default: UnimplementedInstruction();
843   }
844
845   if (has_register) {
846     AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
847   } else {
848     AppendToBuffer("%s", mnem);
849   }
850   return 2;
851 }
852
853
854 // Mnemonics for instructions 0xF0 byte.
855 // Returns NULL if the instruction is not handled here.
856 static const char* F0Mnem(byte f0byte) {
857   switch (f0byte) {
858     case 0x18: return "prefetch";
859     case 0xA2: return "cpuid";
860     case 0xBE: return "movsx_b";
861     case 0xBF: return "movsx_w";
862     case 0xB6: return "movzx_b";
863     case 0xB7: return "movzx_w";
864     case 0xAF: return "imul";
865     case 0xA5: return "shld";
866     case 0xAD: return "shrd";
867     case 0xAC: return "shrd";  // 3-operand version.
868     case 0xAB: return "bts";
869     case 0xBD: return "bsr";
870     default: return NULL;
871   }
872 }
873
874
875 // Disassembled instruction '*instr' and writes it into 'out_buffer'.
876 int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
877                                         byte* instr) {
878   tmp_buffer_pos_ = 0;  // starting to write as position 0
879   byte* data = instr;
880   // Check for hints.
881   const char* branch_hint = NULL;
882   // We use these two prefixes only with branch prediction
883   if (*data == 0x3E /*ds*/) {
884     branch_hint = "predicted taken";
885     data++;
886   } else if (*data == 0x2E /*cs*/) {
887     branch_hint = "predicted not taken";
888     data++;
889   }
890   bool processed = true;  // Will be set to false if the current instruction
891                           // is not in 'instructions' table.
892   const InstructionDesc& idesc = instruction_table_->Get(*data);
893   switch (idesc.type) {
894     case ZERO_OPERANDS_INSTR:
895       AppendToBuffer(idesc.mnem);
896       data++;
897       break;
898
899     case TWO_OPERANDS_INSTR:
900       data++;
901       data += PrintOperands(idesc.mnem, idesc.op_order_, data);
902       break;
903
904     case JUMP_CONDITIONAL_SHORT_INSTR:
905       data += JumpConditionalShort(data, branch_hint);
906       break;
907
908     case REGISTER_INSTR:
909       AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
910       data++;
911       break;
912
913     case MOVE_REG_INSTR: {
914       byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
915       AppendToBuffer("mov %s,%s",
916                      NameOfCPURegister(*data & 0x07),
917                      NameOfAddress(addr));
918       data += 5;
919       break;
920     }
921
922     case CALL_JUMP_INSTR: {
923       byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
924       AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
925       data += 5;
926       break;
927     }
928
929     case SHORT_IMMEDIATE_INSTR: {
930       byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
931       AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
932       data += 5;
933       break;
934     }
935
936     case BYTE_IMMEDIATE_INSTR: {
937       AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
938       data += 2;
939       break;
940     }
941
942     case NO_INSTR:
943       processed = false;
944       break;
945
946     default:
947       UNIMPLEMENTED();  // This type is not implemented.
948   }
949   //----------------------------
950   if (!processed) {
951     switch (*data) {
952       case 0xC2:
953         AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
954         data += 3;
955         break;
956
957       case 0x69:  // fall through
958       case 0x6B:
959         { int mod, regop, rm;
960           get_modrm(*(data+1), &mod, &regop, &rm);
961           int32_t imm =
962               *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2);
963           AppendToBuffer("imul %s,%s,0x%x",
964                          NameOfCPURegister(regop),
965                          NameOfCPURegister(rm),
966                          imm);
967           data += 2 + (*data == 0x6B ? 1 : 4);
968         }
969         break;
970
971       case 0xF6:
972         { data++;
973           int mod, regop, rm;
974           get_modrm(*data, &mod, &regop, &rm);
975           if (regop == eax) {
976             AppendToBuffer("test_b ");
977             data += PrintRightByteOperand(data);
978             int32_t imm = *data;
979             AppendToBuffer(",0x%x", imm);
980             data++;
981           } else {
982             UnimplementedInstruction();
983           }
984         }
985         break;
986
987       case 0x81:  // fall through
988       case 0x83:  // 0x81 with sign extension bit set
989         data += PrintImmediateOp(data);
990         break;
991
992       case 0x0F:
993         { byte f0byte = data[1];
994           const char* f0mnem = F0Mnem(f0byte);
995           if (f0byte == 0x18) {
996             data += 2;
997             int mod, regop, rm;
998             get_modrm(*data, &mod, &regop, &rm);
999             const char* suffix[] = {"nta", "1", "2", "3"};
1000             AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
1001             data += PrintRightOperand(data);
1002           } else if (f0byte == 0x1F && data[2] == 0) {
1003             AppendToBuffer("nop");  // 3 byte nop.
1004             data += 3;
1005           } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
1006             AppendToBuffer("nop");  // 4 byte nop.
1007             data += 4;
1008           } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
1009                      data[4] == 0) {
1010             AppendToBuffer("nop");  // 5 byte nop.
1011             data += 5;
1012           } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
1013                      data[4] == 0 && data[5] == 0 && data[6] == 0) {
1014             AppendToBuffer("nop");  // 7 byte nop.
1015             data += 7;
1016           } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
1017                      data[4] == 0 && data[5] == 0 && data[6] == 0 &&
1018                      data[7] == 0) {
1019             AppendToBuffer("nop");  // 8 byte nop.
1020             data += 8;
1021           } else if (f0byte == 0xA2 || f0byte == 0x31) {
1022             AppendToBuffer("%s", f0mnem);
1023             data += 2;
1024           } else if (f0byte == 0x28) {
1025             data += 2;
1026             int mod, regop, rm;
1027             get_modrm(*data, &mod, &regop, &rm);
1028             AppendToBuffer("movaps %s,%s",
1029                            NameOfXMMRegister(regop),
1030                            NameOfXMMRegister(rm));
1031             data++;
1032           } else if (f0byte == 0x10) {
1033             data += 2;
1034             int mod, regop, rm;
1035             get_modrm(*data, &mod, &regop, &rm);
1036             AppendToBuffer("movups %s,", NameOfXMMRegister(regop));
1037             data += PrintRightXMMOperand(data);
1038           } else if (f0byte == 0x11) {
1039             AppendToBuffer("movups ");
1040             data += 2;
1041             int mod, regop, rm;
1042             get_modrm(*data, &mod, &regop, &rm);
1043             data += PrintRightXMMOperand(data);
1044             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1045           } else if (f0byte >= 0x51 && f0byte <= 0x5F) {
1046             const char* const pseudo_op[] = {
1047               "sqrtps",
1048               "rsqrtps",
1049               "rcpps",
1050               "andps",
1051               "andnps",
1052               "orps",
1053               "xorps",
1054               "addps",
1055               "mulps",
1056               "cvtps2pd",
1057               "cvtdq2ps",
1058               "subps",
1059               "minps",
1060               "divps",
1061               "maxps"
1062             };
1063
1064             data += 2;
1065             int mod, regop, rm;
1066             get_modrm(*data, &mod, &regop, &rm);
1067             AppendToBuffer("%s %s,",
1068                            pseudo_op[f0byte - 0x51],
1069                            NameOfXMMRegister(regop));
1070             data += PrintRightXMMOperand(data);
1071           } else if (f0byte == 0x50) {
1072             data += 2;
1073             int mod, regop, rm;
1074             get_modrm(*data, &mod, &regop, &rm);
1075             AppendToBuffer("movmskps %s,%s",
1076                            NameOfCPURegister(regop),
1077                            NameOfXMMRegister(rm));
1078             data++;
1079           } else if (f0byte == 0xC2) {
1080             // Intel manual 2A, Table 3-11.
1081             data += 2;
1082             int mod, regop, rm;
1083             get_modrm(*data, &mod, &regop, &rm);
1084             const char* const pseudo_op[] = {
1085               "cmpeqps",
1086               "cmpltps",
1087               "cmpleps",
1088               "cmpunordps",
1089               "cmpneqps",
1090               "cmpnltps",
1091               "cmpnleps",
1092               "cmpordps"
1093             };
1094             AppendToBuffer("%s %s,%s",
1095                            pseudo_op[data[1]],
1096                            NameOfXMMRegister(regop),
1097                            NameOfXMMRegister(rm));
1098             data += 2;
1099           } else if (f0byte== 0xC6) {
1100             // shufps xmm, xmm/m128, imm8
1101             data += 2;
1102             int mod, regop, rm;
1103             get_modrm(*data, &mod, &regop, &rm);
1104             int8_t imm8 = static_cast<int8_t>(data[1]);
1105             AppendToBuffer("shufps %s,%s,%d",
1106                             NameOfXMMRegister(rm),
1107                             NameOfXMMRegister(regop),
1108                             static_cast<int>(imm8));
1109             data += 2;
1110           } else if (f0byte== 0x5B) {
1111             data += 2;
1112             int mod, regop, rm;
1113             get_modrm(*data, &mod, &regop, &rm);
1114             AppendToBuffer("cvtdq2ps %s,",
1115                             NameOfXMMRegister(rm));
1116             data += PrintRightXMMOperand(data);
1117           } else if ((f0byte & 0xF0) == 0x80) {
1118             data += JumpConditional(data, branch_hint);
1119           } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1120                      f0byte == 0xB7 || f0byte == 0xAF) {
1121             data += 2;
1122             data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1123           } else if ((f0byte & 0xF0) == 0x90) {
1124             data += SetCC(data);
1125           } else if ((f0byte & 0xF0) == 0x40) {
1126             data += CMov(data);
1127           } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1128             // shrd, shld, bts
1129             data += 2;
1130             AppendToBuffer("%s ", f0mnem);
1131             int mod, regop, rm;
1132             get_modrm(*data, &mod, &regop, &rm);
1133             data += PrintRightOperand(data);
1134             if (f0byte == 0xAB) {
1135               AppendToBuffer(",%s", NameOfCPURegister(regop));
1136             } else {
1137               AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1138             }
1139           } else if (f0byte == 0xBD) {
1140             data += 2;
1141             int mod, regop, rm;
1142             get_modrm(*data, &mod, &regop, &rm);
1143             AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1144             data += PrintRightOperand(data);
1145           } else {
1146             UnimplementedInstruction();
1147           }
1148         }
1149         break;
1150
1151       case 0x8F:
1152         { data++;
1153           int mod, regop, rm;
1154           get_modrm(*data, &mod, &regop, &rm);
1155           if (regop == eax) {
1156             AppendToBuffer("pop ");
1157             data += PrintRightOperand(data);
1158           }
1159         }
1160         break;
1161
1162       case 0xFF:
1163         { data++;
1164           int mod, regop, rm;
1165           get_modrm(*data, &mod, &regop, &rm);
1166           const char* mnem = NULL;
1167           switch (regop) {
1168             case esi: mnem = "push"; break;
1169             case eax: mnem = "inc"; break;
1170             case ecx: mnem = "dec"; break;
1171             case edx: mnem = "call"; break;
1172             case esp: mnem = "jmp"; break;
1173             default: mnem = "???";
1174           }
1175           AppendToBuffer("%s ", mnem);
1176           data += PrintRightOperand(data);
1177         }
1178         break;
1179
1180       case 0xC7:  // imm32, fall through
1181       case 0xC6:  // imm8
1182         { bool is_byte = *data == 0xC6;
1183           data++;
1184           if (is_byte) {
1185             AppendToBuffer("%s ", "mov_b");
1186             data += PrintRightByteOperand(data);
1187             int32_t imm = *data;
1188             AppendToBuffer(",0x%x", imm);
1189             data++;
1190           } else {
1191             AppendToBuffer("%s ", "mov");
1192             data += PrintRightOperand(data);
1193             int32_t imm = *reinterpret_cast<int32_t*>(data);
1194             AppendToBuffer(",0x%x", imm);
1195             data += 4;
1196           }
1197         }
1198         break;
1199
1200       case 0x80:
1201         { data++;
1202           int mod, regop, rm;
1203           get_modrm(*data, &mod, &regop, &rm);
1204           const char* mnem = NULL;
1205           switch (regop) {
1206             case 5:  mnem = "subb"; break;
1207             case 7:  mnem = "cmpb"; break;
1208             default: UnimplementedInstruction();
1209           }
1210           AppendToBuffer("%s ", mnem);
1211           data += PrintRightByteOperand(data);
1212           int32_t imm = *data;
1213           AppendToBuffer(",0x%x", imm);
1214           data++;
1215         }
1216         break;
1217
1218       case 0x88:  // 8bit, fall through
1219       case 0x89:  // 32bit
1220         { bool is_byte = *data == 0x88;
1221           int mod, regop, rm;
1222           data++;
1223           get_modrm(*data, &mod, &regop, &rm);
1224           if (is_byte) {
1225             AppendToBuffer("%s ", "mov_b");
1226             data += PrintRightByteOperand(data);
1227             AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1228           } else {
1229             AppendToBuffer("%s ", "mov");
1230             data += PrintRightOperand(data);
1231             AppendToBuffer(",%s", NameOfCPURegister(regop));
1232           }
1233         }
1234         break;
1235
1236       case 0x66:  // prefix
1237         while (*data == 0x66) data++;
1238         if (*data == 0xf && data[1] == 0x1f) {
1239           AppendToBuffer("nop");  // 0x66 prefix
1240         } else if (*data == 0x90) {
1241           AppendToBuffer("nop");  // 0x66 prefix
1242         } else if (*data == 0x8B) {
1243           data++;
1244           data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1245         } else if (*data == 0x89) {
1246           data++;
1247           int mod, regop, rm;
1248           get_modrm(*data, &mod, &regop, &rm);
1249           AppendToBuffer("mov_w ");
1250           data += PrintRightOperand(data);
1251           AppendToBuffer(",%s", NameOfCPURegister(regop));
1252         } else if (*data == 0xC7) {
1253           data++;
1254           AppendToBuffer("%s ", "mov_w");
1255           data += PrintRightOperand(data);
1256           int imm = *reinterpret_cast<int16_t*>(data);
1257           AppendToBuffer(",0x%x", imm);
1258           data += 2;
1259         } else if (*data == 0x0F) {
1260           data++;
1261           if (*data == 0x38) {
1262             data++;
1263             if (*data == 0x17) {
1264               data++;
1265               int mod, regop, rm;
1266               get_modrm(*data, &mod, &regop, &rm);
1267               AppendToBuffer("ptest %s,%s",
1268                              NameOfXMMRegister(regop),
1269                              NameOfXMMRegister(rm));
1270               data++;
1271             } else if (*data == 0x40) {
1272               data++;
1273               int mod, regop, rm;
1274               get_modrm(*data, &mod, &regop, &rm);
1275               AppendToBuffer("pmulld %s,%s",
1276                              NameOfXMMRegister(regop));
1277               data += PrintRightXMMOperand(data);
1278             } else if (*data == 0x2A) {
1279               // movntdqa
1280               data++;
1281               int mod, regop, rm;
1282               get_modrm(*data, &mod, &regop, &rm);
1283               AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop));
1284               data += PrintRightOperand(data);
1285             } else {
1286               UnimplementedInstruction();
1287             }
1288           } else if (*data == 0x3A) {
1289             data++;
1290             if (*data == 0x0B) {
1291               data++;
1292               int mod, regop, rm;
1293               get_modrm(*data, &mod, &regop, &rm);
1294               int8_t imm8 = static_cast<int8_t>(data[1]);
1295               AppendToBuffer("roundsd %s,%s,%d",
1296                              NameOfXMMRegister(regop),
1297                              NameOfXMMRegister(rm),
1298                              static_cast<int>(imm8));
1299               data += 2;
1300             } else if (*data == 0x16) {
1301               data++;
1302               int mod, regop, rm;
1303               get_modrm(*data, &mod, &regop, &rm);
1304               int8_t imm8 = static_cast<int8_t>(data[1]);
1305               AppendToBuffer("pextrd %s,%s,%d",
1306                              NameOfCPURegister(regop),
1307                              NameOfXMMRegister(rm),
1308                              static_cast<int>(imm8));
1309               data += 2;
1310             } else if (*data == 0x21) {
1311               data++;
1312               int mod, regop, rm;
1313               get_modrm(*data, &mod, &regop, &rm);
1314               int8_t imm8 = static_cast<int8_t>(data[1]);
1315               AppendToBuffer("insertps %s,%s,%d",
1316                              NameOfXMMRegister(regop),
1317                              NameOfXMMRegister(rm),
1318                              static_cast<int>(imm8));
1319               data += 2;
1320             } else if (*data == 0x17) {
1321               data++;
1322               int mod, regop, rm;
1323               get_modrm(*data, &mod, &regop, &rm);
1324               int8_t imm8 = static_cast<int8_t>(data[1]);
1325               AppendToBuffer("extractps %s,%s,%d",
1326                              NameOfCPURegister(rm),
1327                              NameOfXMMRegister(regop),
1328                              static_cast<int>(imm8));
1329               data += 2;
1330             } else if (*data == 0x22) {
1331               data++;
1332               int mod, regop, rm;
1333               get_modrm(*data, &mod, &regop, &rm);
1334               int8_t imm8 = static_cast<int8_t>(data[1]);
1335               AppendToBuffer("pinsrd %s,%s,%d",
1336                              NameOfXMMRegister(regop),
1337                              NameOfCPURegister(rm),
1338                              static_cast<int>(imm8));
1339               data += 2;
1340             } else {
1341               UnimplementedInstruction();
1342             }
1343           } else if (*data == 0x2E || *data == 0x2F) {
1344             const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
1345             data++;
1346             int mod, regop, rm;
1347             get_modrm(*data, &mod, &regop, &rm);
1348             if (mod == 0x3) {
1349               AppendToBuffer("%s %s,%s", mnem,
1350                              NameOfXMMRegister(regop),
1351                              NameOfXMMRegister(rm));
1352               data++;
1353             } else {
1354               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1355               data += PrintRightOperand(data);
1356             }
1357           } else if (*data == 0x50) {
1358             data++;
1359             int mod, regop, rm;
1360             get_modrm(*data, &mod, &regop, &rm);
1361             AppendToBuffer("movmskpd %s,%s",
1362                            NameOfCPURegister(regop),
1363                            NameOfXMMRegister(rm));
1364             data++;
1365           } else if (*data == 0x51) {
1366             data++;
1367             int mod, regop, rm;
1368             get_modrm(*data, &mod, &regop, &rm);
1369             AppendToBuffer("sqrtpd %s,%s",
1370                            NameOfXMMRegister(regop),
1371                            NameOfXMMRegister(rm));
1372             data++;
1373           } else if (*data == 0x54) {
1374             data++;
1375             int mod, regop, rm;
1376             get_modrm(*data, &mod, &regop, &rm);
1377             AppendToBuffer("andpd %s,%s",
1378                            NameOfXMMRegister(regop),
1379                            NameOfXMMRegister(rm));
1380             data++;
1381           } else if (*data == 0x56) {
1382             data++;
1383             int mod, regop, rm;
1384             get_modrm(*data, &mod, &regop, &rm);
1385             AppendToBuffer("orpd %s,%s",
1386                            NameOfXMMRegister(regop),
1387                            NameOfXMMRegister(rm));
1388             data++;
1389           } else if (*data == 0x57) {
1390             data++;
1391             int mod, regop, rm;
1392             get_modrm(*data, &mod, &regop, &rm);
1393             AppendToBuffer("xorpd %s,",
1394                            NameOfXMMRegister(regop));
1395             data += PrintRightXMMOperand(data);
1396           } else if (*data == 0x58) {
1397             data++;
1398             int mod, regop, rm;
1399             get_modrm(*data, &mod, &regop, &rm);
1400             AppendToBuffer("addpd %s,",
1401                            NameOfXMMRegister(regop));
1402             data += PrintRightXMMOperand(data);
1403           } else if (*data == 0x59) {
1404             data++;
1405             int mod, regop, rm;
1406             get_modrm(*data, &mod, &regop, &rm);
1407             AppendToBuffer("mulpd %s,",
1408                            NameOfXMMRegister(regop));
1409             data += PrintRightXMMOperand(data);
1410           } else if (*data == 0x5B) {
1411             data++;
1412             int mod, regop, rm;
1413             get_modrm(*data, &mod, &regop, &rm);
1414             AppendToBuffer("cvtps2dq %s,",
1415                            NameOfXMMRegister(regop));
1416             data += PrintRightXMMOperand(data);
1417           } else if (*data == 0x5C) {
1418             data++;
1419             int mod, regop, rm;
1420             get_modrm(*data, &mod, &regop, &rm);
1421             AppendToBuffer("subpd %s,",
1422                            NameOfXMMRegister(regop));
1423             data += PrintRightXMMOperand(data);
1424           } else if (*data == 0x5D) {
1425             data++;
1426             int mod, regop, rm;
1427             get_modrm(*data, &mod, &regop, &rm);
1428             AppendToBuffer("minpd %s,",
1429                            NameOfXMMRegister(regop));
1430             data += PrintRightXMMOperand(data);
1431           } else if (*data == 0x5E) {
1432             data++;
1433             int mod, regop, rm;
1434             get_modrm(*data, &mod, &regop, &rm);
1435             AppendToBuffer("divpd %s,",
1436                            NameOfXMMRegister(regop));
1437             data += PrintRightXMMOperand(data);
1438           } else if (*data == 0x5F) {
1439             data++;
1440             int mod, regop, rm;
1441             get_modrm(*data, &mod, &regop, &rm);
1442             AppendToBuffer("maxpd %s,",
1443                            NameOfXMMRegister(regop));
1444             data += PrintRightXMMOperand(data);
1445           } else if (*data == 0x62) {
1446             data++;
1447             int mod, regop, rm;
1448             get_modrm(*data, &mod, &regop, &rm);
1449             AppendToBuffer("punpackldq %s,",
1450                             NameOfXMMRegister(regop));
1451             data += PrintRightXMMOperand(data);
1452           } else if (*data == 0xF4) {
1453             data++;
1454             int mod, regop, rm;
1455             get_modrm(*data, &mod, &regop, &rm);
1456             AppendToBuffer("pmuludq %s,",
1457                             NameOfXMMRegister(regop));
1458             data += PrintRightXMMOperand(data);
1459           } else if (*data == 0xFA) {
1460             data++;
1461             int mod, regop, rm;
1462             get_modrm(*data, &mod, &regop, &rm);
1463             AppendToBuffer("psubd %s,",
1464                             NameOfXMMRegister(regop));
1465             data += PrintRightXMMOperand(data);
1466           } else if (*data == 0xFE) {
1467             data++;
1468             int mod, regop, rm;
1469             get_modrm(*data, &mod, &regop, &rm);
1470             AppendToBuffer("paddd %s,",
1471                             NameOfXMMRegister(regop));
1472             data += PrintRightXMMOperand(data);
1473           } else if (*data == 0x6E) {
1474             data++;
1475             int mod, regop, rm;
1476             get_modrm(*data, &mod, &regop, &rm);
1477             AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
1478             data += PrintRightOperand(data);
1479           } else if (*data == 0x6F) {
1480             data++;
1481             int mod, regop, rm;
1482             get_modrm(*data, &mod, &regop, &rm);
1483             AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
1484             data += PrintRightXMMOperand(data);
1485           } else if (*data == 0x70) {
1486             data++;
1487             int mod, regop, rm;
1488             get_modrm(*data, &mod, &regop, &rm);
1489             int8_t imm8 = static_cast<int8_t>(data[1]);
1490             AppendToBuffer("pshufd %s,%s,%d",
1491                            NameOfXMMRegister(regop),
1492                            NameOfXMMRegister(rm),
1493                            static_cast<int>(imm8));
1494             data += 2;
1495           } else if (*data == 0x66) {
1496             data++;
1497             int mod, regop, rm;
1498             get_modrm(*data, &mod, &regop, &rm);
1499             AppendToBuffer("pcmpgtd %s,%s",
1500                            NameOfXMMRegister(regop),
1501                            NameOfXMMRegister(rm));
1502             data++;
1503           } else if (*data == 0x76) {
1504             data++;
1505             int mod, regop, rm;
1506             get_modrm(*data, &mod, &regop, &rm);
1507             AppendToBuffer("pcmpeqd %s,%s",
1508                            NameOfXMMRegister(regop),
1509                            NameOfXMMRegister(rm));
1510             data++;
1511           } else if (*data == 0x90) {
1512             data++;
1513             AppendToBuffer("nop");  // 2 byte nop.
1514           } else if (*data == 0xF3) {
1515             data++;
1516             int mod, regop, rm;
1517             get_modrm(*data, &mod, &regop, &rm);
1518             AppendToBuffer("psllq %s,%s",
1519                            NameOfXMMRegister(regop),
1520                            NameOfXMMRegister(rm));
1521             data++;
1522           } else if (*data == 0x73) {
1523             data++;
1524             int mod, regop, rm;
1525             get_modrm(*data, &mod, &regop, &rm);
1526             int8_t imm8 = static_cast<int8_t>(data[1]);
1527             ASSERT(regop == esi || regop == edx);
1528             AppendToBuffer("%s %s,%d",
1529                            (regop == esi) ? "psllq" : "psrlq",
1530                            NameOfXMMRegister(rm),
1531                            static_cast<int>(imm8));
1532             data += 2;
1533           } else if (*data == 0xF2) {
1534             data++;
1535             int mod, regop, rm;
1536             get_modrm(*data, &mod, &regop, &rm);
1537             AppendToBuffer("pslld %s,%s",
1538                            NameOfXMMRegister(regop),
1539                            NameOfXMMRegister(rm));
1540             data++;
1541           } else if (*data == 0x72) {
1542             data++;
1543             int mod, regop, rm;
1544             get_modrm(*data, &mod, &regop, &rm);
1545             int8_t imm8 = static_cast<int8_t>(data[1]);
1546             ASSERT(regop == esi || regop == edx);
1547             AppendToBuffer("%s %s,%d",
1548                            (regop == esi) ? "pslld"
1549                            : ((regop == edx) ? "psrld" : "psrad"),
1550                            NameOfXMMRegister(rm),
1551                            static_cast<int>(imm8));
1552             data += 2;
1553           } else if (*data == 0xC6) {
1554             data++;
1555             int mod, regop, rm;
1556             get_modrm(*data, &mod, &regop, &rm);
1557             int8_t imm8 = static_cast<int8_t>(data[1]);
1558             AppendToBuffer("shufpd %s,%s,%d",
1559                            NameOfXMMRegister(regop),
1560                            NameOfXMMRegister(rm),
1561                            static_cast<int>(imm8));
1562             data += 2;
1563           } else if (*data == 0xD2) {
1564             data++;
1565             int mod, regop, rm;
1566             get_modrm(*data, &mod, &regop, &rm);
1567             AppendToBuffer("psrld %s,%s",
1568                            NameOfXMMRegister(regop),
1569                            NameOfXMMRegister(rm));
1570             data++;
1571           } else if (*data == 0xD3) {
1572             data++;
1573             int mod, regop, rm;
1574             get_modrm(*data, &mod, &regop, &rm);
1575             AppendToBuffer("psrlq %s,%s",
1576                            NameOfXMMRegister(regop),
1577                            NameOfXMMRegister(rm));
1578             data++;
1579           } else if (*data == 0xE2) {
1580             data++;
1581             int mod, regop, rm;
1582             get_modrm(*data, &mod, &regop, &rm);
1583             AppendToBuffer("psrad %s,%s",
1584                            NameOfXMMRegister(regop),
1585                            NameOfXMMRegister(rm));
1586             data++;
1587           } else if (*data == 0x7F) {
1588             AppendToBuffer("movdqa ");
1589             data++;
1590             int mod, regop, rm;
1591             get_modrm(*data, &mod, &regop, &rm);
1592             data += PrintRightXMMOperand(data);
1593             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1594           } else if (*data == 0x7E) {
1595             data++;
1596             int mod, regop, rm;
1597             get_modrm(*data, &mod, &regop, &rm);
1598             AppendToBuffer("movd ");
1599             data += PrintRightOperand(data);
1600             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1601           } else if (*data == 0xDB) {
1602             data++;
1603             int mod, regop, rm;
1604             get_modrm(*data, &mod, &regop, &rm);
1605             AppendToBuffer("pand %s,%s",
1606                            NameOfXMMRegister(regop),
1607                            NameOfXMMRegister(rm));
1608             data++;
1609           } else if (*data == 0xE7) {
1610             data++;
1611             int mod, regop, rm;
1612             get_modrm(*data, &mod, &regop, &rm);
1613             if (mod == 3) {
1614               AppendToBuffer("movntdq ");
1615               data += PrintRightOperand(data);
1616               AppendToBuffer(",%s", NameOfXMMRegister(regop));
1617             } else {
1618               UnimplementedInstruction();
1619             }
1620           } else if (*data == 0xEF) {
1621             data++;
1622             int mod, regop, rm;
1623             get_modrm(*data, &mod, &regop, &rm);
1624             AppendToBuffer("pxor %s,%s",
1625                            NameOfXMMRegister(regop),
1626                            NameOfXMMRegister(rm));
1627             data++;
1628           } else if (*data == 0xEB) {
1629             data++;
1630             int mod, regop, rm;
1631             get_modrm(*data, &mod, &regop, &rm);
1632             AppendToBuffer("por %s,%s",
1633                            NameOfXMMRegister(regop),
1634                            NameOfXMMRegister(rm));
1635             data++;
1636           } else {
1637             UnimplementedInstruction();
1638           }
1639         } else {
1640           UnimplementedInstruction();
1641         }
1642         break;
1643
1644       case 0xFE:
1645         { data++;
1646           int mod, regop, rm;
1647           get_modrm(*data, &mod, &regop, &rm);
1648           if (regop == ecx) {
1649             AppendToBuffer("dec_b ");
1650             data += PrintRightOperand(data);
1651           } else {
1652             UnimplementedInstruction();
1653           }
1654         }
1655         break;
1656
1657       case 0x68:
1658         AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1659         data += 5;
1660         break;
1661
1662       case 0x6A:
1663         AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1664         data += 2;
1665         break;
1666
1667       case 0xA8:
1668         AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1669         data += 2;
1670         break;
1671
1672       case 0xA9:
1673         AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1674         data += 5;
1675         break;
1676
1677       case 0xD1:  // fall through
1678       case 0xD3:  // fall through
1679       case 0xC1:
1680         data += D1D3C1Instruction(data);
1681         break;
1682
1683       case 0xD8:  // fall through
1684       case 0xD9:  // fall through
1685       case 0xDA:  // fall through
1686       case 0xDB:  // fall through
1687       case 0xDC:  // fall through
1688       case 0xDD:  // fall through
1689       case 0xDE:  // fall through
1690       case 0xDF:
1691         data += FPUInstruction(data);
1692         break;
1693
1694       case 0xEB:
1695         data += JumpShort(data);
1696         break;
1697
1698       case 0xF2:
1699         if (*(data+1) == 0x0F) {
1700           byte b2 = *(data+2);
1701           if (b2 == 0x11) {
1702             AppendToBuffer("movsd ");
1703             data += 3;
1704             int mod, regop, rm;
1705             get_modrm(*data, &mod, &regop, &rm);
1706             data += PrintRightXMMOperand(data);
1707             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1708           } else if (b2 == 0x10) {
1709             data += 3;
1710             int mod, regop, rm;
1711             get_modrm(*data, &mod, &regop, &rm);
1712             AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
1713             data += PrintRightXMMOperand(data);
1714           } else  if (b2 == 0x5A) {
1715             data += 3;
1716             int mod, regop, rm;
1717             get_modrm(*data, &mod, &regop, &rm);
1718             AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
1719             data += PrintRightXMMOperand(data);
1720           } else {
1721             const char* mnem = "?";
1722             switch (b2) {
1723               case 0x2A: mnem = "cvtsi2sd"; break;
1724               case 0x2C: mnem = "cvttsd2si"; break;
1725               case 0x2D: mnem = "cvtsd2si"; break;
1726               case 0x51: mnem = "sqrtsd"; break;
1727               case 0x58: mnem = "addsd"; break;
1728               case 0x59: mnem = "mulsd"; break;
1729               case 0x5C: mnem = "subsd"; break;
1730               case 0x5E: mnem = "divsd"; break;
1731             }
1732             data += 3;
1733             int mod, regop, rm;
1734             get_modrm(*data, &mod, &regop, &rm);
1735             if (b2 == 0x2A) {
1736               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1737               data += PrintRightOperand(data);
1738             } else if (b2 == 0x2C || b2 == 0x2D) {
1739               AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
1740               data += PrintRightXMMOperand(data);
1741             } else if (b2 == 0xC2) {
1742               // Intel manual 2A, Table 3-18.
1743               const char* const pseudo_op[] = {
1744                 "cmpeqsd",
1745                 "cmpltsd",
1746                 "cmplesd",
1747                 "cmpunordsd",
1748                 "cmpneqsd",
1749                 "cmpnltsd",
1750                 "cmpnlesd",
1751                 "cmpordsd"
1752               };
1753               AppendToBuffer("%s %s,%s",
1754                              pseudo_op[data[1]],
1755                              NameOfXMMRegister(regop),
1756                              NameOfXMMRegister(rm));
1757               data += 2;
1758             } else {
1759               AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1760               data += PrintRightXMMOperand(data);
1761             }
1762           }
1763         } else {
1764           UnimplementedInstruction();
1765         }
1766         break;
1767
1768       case 0xF3:
1769         if (*(data+1) == 0x0F) {
1770           byte b2 = *(data+2);
1771           if (b2 == 0x11) {
1772             AppendToBuffer("movss ");
1773             data += 3;
1774             int mod, regop, rm;
1775             get_modrm(*data, &mod, &regop, &rm);
1776             data += PrintRightXMMOperand(data);
1777             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1778           } else if (b2 == 0x10) {
1779             data += 3;
1780             int mod, regop, rm;
1781             get_modrm(*data, &mod, &regop, &rm);
1782             AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
1783             data += PrintRightXMMOperand(data);
1784           } else if (b2 == 0x2C) {
1785             data += 3;
1786             int mod, regop, rm;
1787             get_modrm(*data, &mod, &regop, &rm);
1788             AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
1789             data += PrintRightXMMOperand(data);
1790           } else if (b2 == 0x5A) {
1791             data += 3;
1792             int mod, regop, rm;
1793             get_modrm(*data, &mod, &regop, &rm);
1794             AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1795             data += PrintRightXMMOperand(data);
1796           } else if (b2 == 0x6F) {
1797             data += 3;
1798             int mod, regop, rm;
1799             get_modrm(*data, &mod, &regop, &rm);
1800             AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
1801             data += PrintRightXMMOperand(data);
1802           } else if (b2 == 0x7F) {
1803             AppendToBuffer("movdqu ");
1804             data += 3;
1805             int mod, regop, rm;
1806             get_modrm(*data, &mod, &regop, &rm);
1807             data += PrintRightXMMOperand(data);
1808             AppendToBuffer(",%s", NameOfXMMRegister(regop));
1809           } else {
1810             UnimplementedInstruction();
1811           }
1812         } else if (*(data+1) == 0xA5) {
1813           data += 2;
1814           AppendToBuffer("rep_movs");
1815         } else if (*(data+1) == 0xAB) {
1816           data += 2;
1817           AppendToBuffer("rep_stos");
1818         } else {
1819           UnimplementedInstruction();
1820         }
1821         break;
1822
1823       case 0xF7:
1824         data += F7Instruction(data);
1825         break;
1826
1827       default:
1828         UnimplementedInstruction();
1829     }
1830   }
1831
1832   if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1833     tmp_buffer_[tmp_buffer_pos_] = '\0';
1834   }
1835
1836   int instr_len = data - instr;
1837   if (instr_len == 0) {
1838     printf("%02x", *data);
1839   }
1840   ASSERT(instr_len > 0);  // Ensure progress.
1841
1842   int outp = 0;
1843   // Instruction bytes.
1844   for (byte* bp = instr; bp < data; bp++) {
1845     outp += v8::internal::OS::SNPrintF(out_buffer + outp,
1846                                        "%02x",
1847                                        *bp);
1848   }
1849   for (int i = 6 - instr_len; i >= 0; i--) {
1850     outp += v8::internal::OS::SNPrintF(out_buffer + outp,
1851                                        "  ");
1852   }
1853
1854   outp += v8::internal::OS::SNPrintF(out_buffer + outp,
1855                                      " %s",
1856                                      tmp_buffer_.start());
1857   return instr_len;
1858 }  // NOLINT (function is too long)
1859
1860
1861 //------------------------------------------------------------------------------
1862
1863
1864 static const char* cpu_regs[8] = {
1865   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
1866 };
1867
1868
1869 static const char* byte_cpu_regs[8] = {
1870   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
1871 };
1872
1873
1874 static const char* xmm_regs[8] = {
1875   "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
1876 };
1877
1878
1879 const char* NameConverter::NameOfAddress(byte* addr) const {
1880   v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
1881   return tmp_buffer_.start();
1882 }
1883
1884
1885 const char* NameConverter::NameOfConstant(byte* addr) const {
1886   return NameOfAddress(addr);
1887 }
1888
1889
1890 const char* NameConverter::NameOfCPURegister(int reg) const {
1891   if (0 <= reg && reg < 8) return cpu_regs[reg];
1892   return "noreg";
1893 }
1894
1895
1896 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1897   if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
1898   return "noreg";
1899 }
1900
1901
1902 const char* NameConverter::NameOfXMMRegister(int reg) const {
1903   if (0 <= reg && reg < 8) return xmm_regs[reg];
1904   return "noxmmreg";
1905 }
1906
1907
1908 const char* NameConverter::NameInCode(byte* addr) const {
1909   // IA32 does not embed debug strings at the moment.
1910   UNREACHABLE();
1911   return "";
1912 }
1913
1914
1915 //------------------------------------------------------------------------------
1916
1917 Disassembler::Disassembler(const NameConverter& converter)
1918     : converter_(converter) {}
1919
1920
1921 Disassembler::~Disassembler() {}
1922
1923
1924 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1925                                     byte* instruction) {
1926   DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
1927   return d.InstructionDecode(buffer, instruction);
1928 }
1929
1930
1931 // The IA-32 assembler does not currently use constant pools.
1932 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1933
1934
1935 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1936   NameConverter converter;
1937   Disassembler d(converter);
1938   for (byte* pc = begin; pc < end;) {
1939     v8::internal::EmbeddedVector<char, 128> buffer;
1940     buffer[0] = '\0';
1941     byte* prev_pc = pc;
1942     pc += d.InstructionDecode(buffer, pc);
1943     fprintf(f, "%p", prev_pc);
1944     fprintf(f, "    ");
1945
1946     for (byte* bp = prev_pc; bp < pc; bp++) {
1947       fprintf(f, "%02x",  *bp);
1948     }
1949     for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1950       fprintf(f, "  ");
1951     }
1952     fprintf(f, "  %s\n", buffer.start());
1953   }
1954 }
1955
1956
1957 }  // namespace disasm
1958
1959 #endif  // V8_TARGET_ARCH_IA32