• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 // A Disassembler object is used to disassemble a block of code instruction by
6 // instruction. The default implementation of the NameConverter object can be
7 // overriden to modify register names or to do symbol lookup on addresses.
8 //
9 // The example below will disassemble a block of code and print it to stdout.
10 //
11 //   NameConverter converter;
12 //   Disassembler d(converter);
13 //   for (byte* pc = begin; pc < end;) {
14 //     v8::internal::EmbeddedVector<char, 256> buffer;
15 //     byte* prev_pc = pc;
16 //     pc += d.InstructionDecode(buffer, pc);
17 //     printf("%p    %08x      %s\n",
18 //            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
19 //   }
20 //
21 // The Disassembler class also has a convenience method to disassemble a block
22 // of code into a FILE*, meaning that the above functionality could also be
23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
24 
25 
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #if V8_TARGET_ARCH_PPC
32 
33 #include "src/base/platform/platform.h"
34 #include "src/disasm.h"
35 #include "src/macro-assembler.h"
36 #include "src/ppc/constants-ppc.h"
37 
38 
39 namespace v8 {
40 namespace internal {
41 
42 const auto GetRegConfig = RegisterConfiguration::Default;
43 
44 //------------------------------------------------------------------------------
45 
46 // Decoder decodes and disassembles instructions into an output buffer.
47 // It uses the converter to convert register names and call destinations into
48 // more informative description.
49 class Decoder {
50  public:
Decoder(const disasm::NameConverter & converter,Vector<char> out_buffer)51   Decoder(const disasm::NameConverter& converter, Vector<char> out_buffer)
52       : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) {
53     out_buffer_[out_buffer_pos_] = '\0';
54   }
55 
~Decoder()56   ~Decoder() {}
57 
58   // Writes one disassembled instruction into 'buffer' (0-terminated).
59   // Returns the length of the disassembled machine instruction in bytes.
60   int InstructionDecode(byte* instruction);
61 
62  private:
63   // Bottleneck functions to print into the out_buffer.
64   void PrintChar(const char ch);
65   void Print(const char* str);
66 
67   // Printing of common values.
68   void PrintRegister(int reg);
69   void PrintDRegister(int reg);
70   int FormatFPRegister(Instruction* instr, const char* format);
71   void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
72 
73   // Handle formatting of instructions and their options.
74   int FormatRegister(Instruction* instr, const char* option);
75   int FormatOption(Instruction* instr, const char* option);
76   void Format(Instruction* instr, const char* format);
77   void Unknown(Instruction* instr);
78   void UnknownFormat(Instruction* instr, const char* opcname);
79 
80   void DecodeExt1(Instruction* instr);
81   void DecodeExt2(Instruction* instr);
82   void DecodeExt3(Instruction* instr);
83   void DecodeExt4(Instruction* instr);
84   void DecodeExt5(Instruction* instr);
85   void DecodeExt6(Instruction* instr);
86 
87   const disasm::NameConverter& converter_;
88   Vector<char> out_buffer_;
89   int out_buffer_pos_;
90 
91   DISALLOW_COPY_AND_ASSIGN(Decoder);
92 };
93 
94 
95 // Support for assertions in the Decoder formatting functions.
96 #define STRING_STARTS_WITH(string, compare_string) \
97   (strncmp(string, compare_string, strlen(compare_string)) == 0)
98 
99 
100 // Append the ch to the output buffer.
PrintChar(const char ch)101 void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
102 
103 
104 // Append the str to the output buffer.
Print(const char * str)105 void Decoder::Print(const char* str) {
106   char cur = *str++;
107   while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
108     PrintChar(cur);
109     cur = *str++;
110   }
111   out_buffer_[out_buffer_pos_] = 0;
112 }
113 
114 
115 // Print the register name according to the active name converter.
PrintRegister(int reg)116 void Decoder::PrintRegister(int reg) {
117   Print(converter_.NameOfCPURegister(reg));
118 }
119 
120 
121 // Print the double FP register name according to the active name converter.
PrintDRegister(int reg)122 void Decoder::PrintDRegister(int reg) {
123   Print(GetRegConfig()->GetDoubleRegisterName(reg));
124 }
125 
126 
127 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
128 // the FormatOption method.
PrintSoftwareInterrupt(SoftwareInterruptCodes svc)129 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
130   switch (svc) {
131     case kCallRtRedirected:
132       Print("call rt redirected");
133       return;
134     case kBreakpoint:
135       Print("breakpoint");
136       return;
137     default:
138       if (svc >= kStopCode) {
139         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x",
140                                     svc & kStopCodeMask, svc & kStopCodeMask);
141       } else {
142         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc);
143       }
144       return;
145   }
146 }
147 
148 
149 // Handle all register based formatting in this function to reduce the
150 // complexity of FormatOption.
FormatRegister(Instruction * instr,const char * format)151 int Decoder::FormatRegister(Instruction* instr, const char* format) {
152   DCHECK_EQ(format[0], 'r');
153 
154   if ((format[1] == 't') || (format[1] == 's')) {  // 'rt & 'rs register
155     int reg = instr->RTValue();
156     PrintRegister(reg);
157     return 2;
158   } else if (format[1] == 'a') {  // 'ra: RA register
159     int reg = instr->RAValue();
160     PrintRegister(reg);
161     return 2;
162   } else if (format[1] == 'b') {  // 'rb: RB register
163     int reg = instr->RBValue();
164     PrintRegister(reg);
165     return 2;
166   }
167 
168   UNREACHABLE();
169 }
170 
171 
172 // Handle all FP register based formatting in this function to reduce the
173 // complexity of FormatOption.
FormatFPRegister(Instruction * instr,const char * format)174 int Decoder::FormatFPRegister(Instruction* instr, const char* format) {
175   DCHECK_EQ(format[0], 'D');
176 
177   int retval = 2;
178   int reg = -1;
179   if (format[1] == 't') {
180     reg = instr->RTValue();
181   } else if (format[1] == 'a') {
182     reg = instr->RAValue();
183   } else if (format[1] == 'b') {
184     reg = instr->RBValue();
185   } else if (format[1] == 'c') {
186     reg = instr->RCValue();
187   } else {
188     UNREACHABLE();
189   }
190 
191   PrintDRegister(reg);
192 
193   return retval;
194 }
195 
196 
197 // FormatOption takes a formatting string and interprets it based on
198 // the current instructions. The format string points to the first
199 // character of the option string (the option escape has already been
200 // consumed by the caller.)  FormatOption returns the number of
201 // characters that were consumed from the formatting string.
FormatOption(Instruction * instr,const char * format)202 int Decoder::FormatOption(Instruction* instr, const char* format) {
203   switch (format[0]) {
204     case 'o': {
205       if (instr->Bit(10) == 1) {
206         Print("o");
207       }
208       return 1;
209     }
210     case '.': {
211       if (instr->Bit(0) == 1) {
212         Print(".");
213       } else {
214         Print(" ");  // ensure consistent spacing
215       }
216       return 1;
217     }
218     case 'r': {
219       return FormatRegister(instr, format);
220     }
221     case 'D': {
222       return FormatFPRegister(instr, format);
223     }
224     case 'i': {  // int16
225       int32_t value = (instr->Bits(15, 0) << 16) >> 16;
226       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
227       return 5;
228     }
229     case 'u': {  // uint16
230       int32_t value = instr->Bits(15, 0);
231       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
232       return 6;
233     }
234     case 'l': {
235       // Link (LK) Bit 0
236       if (instr->Bit(0) == 1) {
237         Print("l");
238       }
239       return 1;
240     }
241     case 'a': {
242       // Absolute Address Bit 1
243       if (instr->Bit(1) == 1) {
244         Print("a");
245       }
246       return 1;
247     }
248     case 'c': {  // 'cr: condition register of branch instruction
249       int code = instr->Bits(20, 18);
250       if (code != 7) {
251         out_buffer_pos_ +=
252             SNPrintF(out_buffer_ + out_buffer_pos_, " cr%d", code);
253       }
254       return 2;
255     }
256     case 't': {  // 'target: target of branch instructions
257       // target26 or target16
258       DCHECK(STRING_STARTS_WITH(format, "target"));
259       if ((format[6] == '2') && (format[7] == '6')) {
260         int off = ((instr->Bits(25, 2)) << 8) >> 6;
261         out_buffer_pos_ += SNPrintF(
262             out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
263             converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
264         return 8;
265       } else if ((format[6] == '1') && (format[7] == '6')) {
266         int off = ((instr->Bits(15, 2)) << 18) >> 16;
267         out_buffer_pos_ += SNPrintF(
268             out_buffer_ + out_buffer_pos_, "%+d -> %s", off,
269             converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
270         return 8;
271       }
272       break;
273       case 's': {
274         DCHECK_EQ(format[1], 'h');
275         int32_t value = 0;
276         int32_t opcode = instr->OpcodeValue() << 26;
277         int32_t sh = instr->Bits(15, 11);
278         if (opcode == EXT5 ||
279             (opcode == EXT2 && instr->Bits(10, 2) << 2 == SRADIX)) {
280           // SH Bits 1 and 15-11 (split field)
281           value = (sh | (instr->Bit(1) << 5));
282         } else {
283           // SH Bits 15-11
284           value = (sh << 26) >> 26;
285         }
286         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
287         return 2;
288       }
289       case 'm': {
290         int32_t value = 0;
291         if (format[1] == 'e') {
292           if (instr->OpcodeValue() << 26 != EXT5) {
293             // ME Bits 10-6
294             value = (instr->Bits(10, 6) << 26) >> 26;
295           } else {
296             // ME Bits 5 and 10-6 (split field)
297             value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
298           }
299         } else if (format[1] == 'b') {
300           if (instr->OpcodeValue() << 26 != EXT5) {
301             // MB Bits 5-1
302             value = (instr->Bits(5, 1) << 26) >> 26;
303           } else {
304             // MB Bits 5 and 10-6 (split field)
305             value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
306           }
307         } else {
308           UNREACHABLE();  // bad format
309         }
310         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
311         return 2;
312       }
313     }
314 #if V8_TARGET_ARCH_PPC64
315     case 'd': {  // ds value for offset
316       int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
317       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
318       return 1;
319     }
320 #endif
321     default: {
322       UNREACHABLE();
323       break;
324     }
325   }
326 
327   UNREACHABLE();
328 }
329 
330 
331 // Format takes a formatting string for a whole instruction and prints it into
332 // the output buffer. All escaped options are handed to FormatOption to be
333 // parsed further.
Format(Instruction * instr,const char * format)334 void Decoder::Format(Instruction* instr, const char* format) {
335   char cur = *format++;
336   while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
337     if (cur == '\'') {  // Single quote is used as the formatting escape.
338       format += FormatOption(instr, format);
339     } else {
340       out_buffer_[out_buffer_pos_++] = cur;
341     }
342     cur = *format++;
343   }
344   out_buffer_[out_buffer_pos_] = '\0';
345 }
346 
347 
348 // The disassembler may end up decoding data inlined in the code. We do not want
349 // it to crash if the data does not resemble any known instruction.
350 #define VERIFY(condition) \
351   if (!(condition)) {     \
352     Unknown(instr);       \
353     return;               \
354   }
355 
356 
357 // For currently unimplemented decodings the disassembler calls Unknown(instr)
358 // which will just print "unknown" of the instruction bits.
Unknown(Instruction * instr)359 void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); }
360 
361 
362 // For currently unimplemented decodings the disassembler calls
363 // UnknownFormat(instr) which will just print opcode name of the
364 // instruction bits.
UnknownFormat(Instruction * instr,const char * name)365 void Decoder::UnknownFormat(Instruction* instr, const char* name) {
366   char buffer[100];
367   snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name);
368   Format(instr, buffer);
369 }
370 
371 
DecodeExt1(Instruction * instr)372 void Decoder::DecodeExt1(Instruction* instr) {
373   switch (EXT1 | (instr->BitField(10, 1))) {
374     case MCRF: {
375       UnknownFormat(instr, "mcrf");  // not used by V8
376       break;
377     }
378     case BCLRX: {
379       int bo = instr->BitField(25, 21);
380       int bi = instr->Bits(20, 16);
381       CRBit cond = static_cast<CRBit>(bi & (CRWIDTH - 1));
382       switch (bo) {
383         case DCBNZF: {
384           UnknownFormat(instr, "bclrx-dcbnzf");
385           break;
386         }
387         case DCBEZF: {
388           UnknownFormat(instr, "bclrx-dcbezf");
389           break;
390         }
391         case BF: {
392           switch (cond) {
393             case CR_EQ:
394               Format(instr, "bnelr'l'cr");
395               break;
396             case CR_GT:
397               Format(instr, "blelr'l'cr");
398               break;
399             case CR_LT:
400               Format(instr, "bgelr'l'cr");
401               break;
402             case CR_SO:
403               Format(instr, "bnsolr'l'cr");
404               break;
405           }
406           break;
407         }
408         case DCBNZT: {
409           UnknownFormat(instr, "bclrx-dcbbzt");
410           break;
411         }
412         case DCBEZT: {
413           UnknownFormat(instr, "bclrx-dcbnezt");
414           break;
415         }
416         case BT: {
417           switch (cond) {
418             case CR_EQ:
419               Format(instr, "beqlr'l'cr");
420               break;
421             case CR_GT:
422               Format(instr, "bgtlr'l'cr");
423               break;
424             case CR_LT:
425               Format(instr, "bltlr'l'cr");
426               break;
427             case CR_SO:
428               Format(instr, "bsolr'l'cr");
429               break;
430           }
431           break;
432         }
433         case DCBNZ: {
434           UnknownFormat(instr, "bclrx-dcbnz");
435           break;
436         }
437         case DCBEZ: {
438           UnknownFormat(instr, "bclrx-dcbez");  // not used by V8
439           break;
440         }
441         case BA: {
442           Format(instr, "blr'l");
443           break;
444         }
445       }
446       break;
447     }
448     case BCCTRX: {
449       switch (instr->BitField(25, 21)) {
450         case DCBNZF: {
451           UnknownFormat(instr, "bcctrx-dcbnzf");
452           break;
453         }
454         case DCBEZF: {
455           UnknownFormat(instr, "bcctrx-dcbezf");
456           break;
457         }
458         case BF: {
459           UnknownFormat(instr, "bcctrx-bf");
460           break;
461         }
462         case DCBNZT: {
463           UnknownFormat(instr, "bcctrx-dcbnzt");
464           break;
465         }
466         case DCBEZT: {
467           UnknownFormat(instr, "bcctrx-dcbezf");
468           break;
469         }
470         case BT: {
471           UnknownFormat(instr, "bcctrx-bt");
472           break;
473         }
474         case DCBNZ: {
475           UnknownFormat(instr, "bcctrx-dcbnz");
476           break;
477         }
478         case DCBEZ: {
479           UnknownFormat(instr, "bcctrx-dcbez");
480           break;
481         }
482         case BA: {
483           if (instr->Bit(0) == 1) {
484             Format(instr, "bctrl");
485           } else {
486             Format(instr, "bctr");
487           }
488           break;
489         }
490         default: { UNREACHABLE(); }
491       }
492       break;
493     }
494     case CRNOR: {
495       Format(instr, "crnor (stuff)");
496       break;
497     }
498     case RFI: {
499       Format(instr, "rfi (stuff)");
500       break;
501     }
502     case CRANDC: {
503       Format(instr, "crandc (stuff)");
504       break;
505     }
506     case ISYNC: {
507       Format(instr, "isync (stuff)");
508       break;
509     }
510     case CRXOR: {
511       Format(instr, "crxor (stuff)");
512       break;
513     }
514     case CRNAND: {
515       UnknownFormat(instr, "crnand");
516       break;
517     }
518     case CRAND: {
519       UnknownFormat(instr, "crand");
520       break;
521     }
522     case CREQV: {
523       UnknownFormat(instr, "creqv");
524       break;
525     }
526     case CRORC: {
527       UnknownFormat(instr, "crorc");
528       break;
529     }
530     case CROR: {
531       UnknownFormat(instr, "cror");
532       break;
533     }
534     default: {
535       Unknown(instr);  // not used by V8
536     }
537   }
538 }
539 
540 
DecodeExt2(Instruction * instr)541 void Decoder::DecodeExt2(Instruction* instr) {
542   // Some encodings are 10-1 bits, handle those first
543   switch (EXT2 | (instr->BitField(10, 1))) {
544     case SRWX: {
545       Format(instr, "srw'.    'ra, 'rs, 'rb");
546       return;
547     }
548 #if V8_TARGET_ARCH_PPC64
549     case SRDX: {
550       Format(instr, "srd'.    'ra, 'rs, 'rb");
551       return;
552     }
553 #endif
554     case SRAW: {
555       Format(instr, "sraw'.   'ra, 'rs, 'rb");
556       return;
557     }
558 #if V8_TARGET_ARCH_PPC64
559     case SRAD: {
560       Format(instr, "srad'.   'ra, 'rs, 'rb");
561       return;
562     }
563 #endif
564     case SYNC: {
565       Format(instr, "sync");
566       return;
567     }
568     case MODSW: {
569       Format(instr, "modsw  'rt, 'ra, 'rb");
570       return;
571     }
572     case MODUW: {
573       Format(instr, "moduw  'rt, 'ra, 'rb");
574       return;
575     }
576 #if V8_TARGET_ARCH_PPC64
577     case MODSD: {
578       Format(instr, "modsd  'rt, 'ra, 'rb");
579       return;
580     }
581     case MODUD: {
582       Format(instr, "modud  'rt, 'ra, 'rb");
583       return;
584     }
585 #endif
586     case SRAWIX: {
587       Format(instr, "srawi'.  'ra,'rs,'sh");
588       return;
589     }
590     case EXTSH: {
591       Format(instr, "extsh'.  'ra, 'rs");
592       return;
593     }
594 #if V8_TARGET_ARCH_PPC64
595     case EXTSW: {
596       Format(instr, "extsw'.  'ra, 'rs");
597       return;
598     }
599 #endif
600     case EXTSB: {
601       Format(instr, "extsb'.  'ra, 'rs");
602       return;
603     }
604     case LFSX: {
605       Format(instr, "lfsx    'Dt, 'ra, 'rb");
606       return;
607     }
608     case LFSUX: {
609       Format(instr, "lfsux   'Dt, 'ra, 'rb");
610       return;
611     }
612     case LFDX: {
613       Format(instr, "lfdx    'Dt, 'ra, 'rb");
614       return;
615     }
616     case LFDUX: {
617       Format(instr, "lfdux   'Dt, 'ra, 'rb");
618       return;
619     }
620     case STFSX: {
621       Format(instr, "stfsx    'rs, 'ra, 'rb");
622       return;
623     }
624     case STFSUX: {
625       Format(instr, "stfsux   'rs, 'ra, 'rb");
626       return;
627     }
628     case STFDX: {
629       Format(instr, "stfdx    'rs, 'ra, 'rb");
630       return;
631     }
632     case STFDUX: {
633       Format(instr, "stfdux   'rs, 'ra, 'rb");
634       return;
635     }
636     case POPCNTW: {
637       Format(instr, "popcntw  'ra, 'rs");
638       return;
639     }
640 #if V8_TARGET_ARCH_PPC64
641     case POPCNTD: {
642       Format(instr, "popcntd  'ra, 'rs");
643       return;
644     }
645 #endif
646   }
647 
648   switch (EXT2 | (instr->BitField(10, 2))) {
649     case SRADIX: {
650       Format(instr, "sradi'.  'ra,'rs,'sh");
651       return;
652     }
653   }
654 
655   switch (EXT2 | (instr->BitField(10, 0))) {
656     case STBCX: {
657       Format(instr, "stbcx   'rs, 'ra, 'rb");
658       return;
659     }
660     case STHCX: {
661       Format(instr, "sthcx   'rs, 'ra, 'rb");
662       return;
663     }
664     case STWCX: {
665       Format(instr, "stwcx   'rs, 'ra, 'rb");
666       return;
667     }
668   }
669 
670   // ?? are all of these xo_form?
671   switch (EXT2 | (instr->BitField(9, 1))) {
672     case CMP: {
673 #if V8_TARGET_ARCH_PPC64
674       if (instr->Bit(21)) {
675 #endif
676         Format(instr, "cmp     'ra, 'rb");
677 #if V8_TARGET_ARCH_PPC64
678       } else {
679         Format(instr, "cmpw    'ra, 'rb");
680       }
681 #endif
682       return;
683     }
684     case SLWX: {
685       Format(instr, "slw'.   'ra, 'rs, 'rb");
686       return;
687     }
688 #if V8_TARGET_ARCH_PPC64
689     case SLDX: {
690       Format(instr, "sld'.   'ra, 'rs, 'rb");
691       return;
692     }
693 #endif
694     case SUBFCX: {
695       Format(instr, "subfc'. 'rt, 'ra, 'rb");
696       return;
697     }
698     case SUBFEX: {
699       Format(instr, "subfe'. 'rt, 'ra, 'rb");
700       return;
701     }
702     case ADDCX: {
703       Format(instr, "addc'.   'rt, 'ra, 'rb");
704       return;
705     }
706     case ADDEX: {
707       Format(instr, "adde'.   'rt, 'ra, 'rb");
708       return;
709     }
710     case CNTLZWX: {
711       Format(instr, "cntlzw'. 'ra, 'rs");
712       return;
713     }
714 #if V8_TARGET_ARCH_PPC64
715     case CNTLZDX: {
716       Format(instr, "cntlzd'. 'ra, 'rs");
717       return;
718     }
719 #endif
720     case ANDX: {
721       Format(instr, "and'.    'ra, 'rs, 'rb");
722       return;
723     }
724     case ANDCX: {
725       Format(instr, "andc'.   'ra, 'rs, 'rb");
726       return;
727     }
728     case CMPL: {
729 #if V8_TARGET_ARCH_PPC64
730       if (instr->Bit(21)) {
731 #endif
732         Format(instr, "cmpl    'ra, 'rb");
733 #if V8_TARGET_ARCH_PPC64
734       } else {
735         Format(instr, "cmplw   'ra, 'rb");
736       }
737 #endif
738       return;
739     }
740     case NEGX: {
741       Format(instr, "neg'.    'rt, 'ra");
742       return;
743     }
744     case NORX: {
745       Format(instr, "nor'.    'rt, 'ra, 'rb");
746       return;
747     }
748     case SUBFX: {
749       Format(instr, "subf'.   'rt, 'ra, 'rb");
750       return;
751     }
752     case MULHWX: {
753       Format(instr, "mulhw'o'.  'rt, 'ra, 'rb");
754       return;
755     }
756     case ADDZEX: {
757       Format(instr, "addze'.   'rt, 'ra");
758       return;
759     }
760     case MULLW: {
761       Format(instr, "mullw'o'.  'rt, 'ra, 'rb");
762       return;
763     }
764 #if V8_TARGET_ARCH_PPC64
765     case MULLD: {
766       Format(instr, "mulld'o'.  'rt, 'ra, 'rb");
767       return;
768     }
769 #endif
770     case DIVW: {
771       Format(instr, "divw'o'.   'rt, 'ra, 'rb");
772       return;
773     }
774     case DIVWU: {
775       Format(instr, "divwu'o'.  'rt, 'ra, 'rb");
776       return;
777     }
778 #if V8_TARGET_ARCH_PPC64
779     case DIVD: {
780       Format(instr, "divd'o'.   'rt, 'ra, 'rb");
781       return;
782     }
783 #endif
784     case ADDX: {
785       Format(instr, "add'o     'rt, 'ra, 'rb");
786       return;
787     }
788     case XORX: {
789       Format(instr, "xor'.    'ra, 'rs, 'rb");
790       return;
791     }
792     case ORX: {
793       if (instr->RTValue() == instr->RBValue()) {
794         Format(instr, "mr      'ra, 'rb");
795       } else {
796         Format(instr, "or      'ra, 'rs, 'rb");
797       }
798       return;
799     }
800     case MFSPR: {
801       int spr = instr->Bits(20, 11);
802       if (256 == spr) {
803         Format(instr, "mflr    'rt");
804       } else {
805         Format(instr, "mfspr   'rt ??");
806       }
807       return;
808     }
809     case MTSPR: {
810       int spr = instr->Bits(20, 11);
811       if (256 == spr) {
812         Format(instr, "mtlr    'rt");
813       } else if (288 == spr) {
814         Format(instr, "mtctr   'rt");
815       } else {
816         Format(instr, "mtspr   'rt ??");
817       }
818       return;
819     }
820     case MFCR: {
821       Format(instr, "mfcr    'rt");
822       return;
823     }
824     case STWX: {
825       Format(instr, "stwx    'rs, 'ra, 'rb");
826       return;
827     }
828     case STWUX: {
829       Format(instr, "stwux   'rs, 'ra, 'rb");
830       return;
831     }
832     case STBX: {
833       Format(instr, "stbx    'rs, 'ra, 'rb");
834       return;
835     }
836     case STBUX: {
837       Format(instr, "stbux   'rs, 'ra, 'rb");
838       return;
839     }
840     case STHX: {
841       Format(instr, "sthx    'rs, 'ra, 'rb");
842       return;
843     }
844     case STHUX: {
845       Format(instr, "sthux   'rs, 'ra, 'rb");
846       return;
847     }
848     case LWZX: {
849       Format(instr, "lwzx    'rt, 'ra, 'rb");
850       return;
851     }
852     case LWZUX: {
853       Format(instr, "lwzux   'rt, 'ra, 'rb");
854       return;
855     }
856     case LWAX: {
857       Format(instr, "lwax    'rt, 'ra, 'rb");
858       return;
859     }
860     case LBZX: {
861       Format(instr, "lbzx    'rt, 'ra, 'rb");
862       return;
863     }
864     case LBZUX: {
865       Format(instr, "lbzux   'rt, 'ra, 'rb");
866       return;
867     }
868     case LHZX: {
869       Format(instr, "lhzx    'rt, 'ra, 'rb");
870       return;
871     }
872     case LHZUX: {
873       Format(instr, "lhzux   'rt, 'ra, 'rb");
874       return;
875     }
876     case LHAX: {
877       Format(instr, "lhax    'rt, 'ra, 'rb");
878       return;
879     }
880     case LBARX: {
881       Format(instr, "lbarx   'rt, 'ra, 'rb");
882       return;
883     }
884     case LHARX: {
885       Format(instr, "lharx   'rt, 'ra, 'rb");
886       return;
887     }
888     case LWARX: {
889       Format(instr, "lwarx   'rt, 'ra, 'rb");
890       return;
891     }
892 #if V8_TARGET_ARCH_PPC64
893     case LDX: {
894       Format(instr, "ldx     'rt, 'ra, 'rb");
895       return;
896     }
897     case LDUX: {
898       Format(instr, "ldux    'rt, 'ra, 'rb");
899       return;
900     }
901     case STDX: {
902       Format(instr, "stdx    'rt, 'ra, 'rb");
903       return;
904     }
905     case STDUX: {
906       Format(instr, "stdux   'rt, 'ra, 'rb");
907       return;
908     }
909     case MFVSRD: {
910       Format(instr, "mffprd  'ra, 'Dt");
911       return;
912     }
913     case MFVSRWZ: {
914       Format(instr, "mffprwz 'ra, 'Dt");
915       return;
916     }
917     case MTVSRD: {
918       Format(instr, "mtfprd  'Dt, 'ra");
919       return;
920     }
921     case MTVSRWA: {
922       Format(instr, "mtfprwa 'Dt, 'ra");
923       return;
924     }
925     case MTVSRWZ: {
926       Format(instr, "mtfprwz 'Dt, 'ra");
927       return;
928     }
929 #endif
930   }
931 
932   switch (EXT2 | (instr->BitField(5, 1))) {
933     case ISEL: {
934       Format(instr, "isel    'rt, 'ra, 'rb");
935       return;
936     }
937     default: {
938       Unknown(instr);  // not used by V8
939     }
940   }
941 }
942 
943 
DecodeExt3(Instruction * instr)944 void Decoder::DecodeExt3(Instruction* instr) {
945   switch (EXT3 | (instr->BitField(10, 1))) {
946     case FCFID: {
947       Format(instr, "fcfids'. 'Dt, 'Db");
948       break;
949     }
950     case FCFIDU: {
951       Format(instr, "fcfidus'.'Dt, 'Db");
952       break;
953     }
954     default: {
955       Unknown(instr);  // not used by V8
956     }
957   }
958 }
959 
960 
DecodeExt4(Instruction * instr)961 void Decoder::DecodeExt4(Instruction* instr) {
962   switch (EXT4 | (instr->BitField(5, 1))) {
963     case FDIV: {
964       Format(instr, "fdiv'.   'Dt, 'Da, 'Db");
965       return;
966     }
967     case FSUB: {
968       Format(instr, "fsub'.   'Dt, 'Da, 'Db");
969       return;
970     }
971     case FADD: {
972       Format(instr, "fadd'.   'Dt, 'Da, 'Db");
973       return;
974     }
975     case FSQRT: {
976       Format(instr, "fsqrt'.  'Dt, 'Db");
977       return;
978     }
979     case FSEL: {
980       Format(instr, "fsel'.   'Dt, 'Da, 'Dc, 'Db");
981       return;
982     }
983     case FMUL: {
984       Format(instr, "fmul'.   'Dt, 'Da, 'Dc");
985       return;
986     }
987     case FMSUB: {
988       Format(instr, "fmsub'.  'Dt, 'Da, 'Dc, 'Db");
989       return;
990     }
991     case FMADD: {
992       Format(instr, "fmadd'.  'Dt, 'Da, 'Dc, 'Db");
993       return;
994     }
995   }
996 
997   switch (EXT4 | (instr->BitField(10, 1))) {
998     case FCMPU: {
999       Format(instr, "fcmpu   'Da, 'Db");
1000       break;
1001     }
1002     case FRSP: {
1003       Format(instr, "frsp'.   'Dt, 'Db");
1004       break;
1005     }
1006     case FCFID: {
1007       Format(instr, "fcfid'.  'Dt, 'Db");
1008       break;
1009     }
1010     case FCFIDU: {
1011       Format(instr, "fcfidu'. 'Dt, 'Db");
1012       break;
1013     }
1014     case FCTID: {
1015       Format(instr, "fctid   'Dt, 'Db");
1016       break;
1017     }
1018     case FCTIDZ: {
1019       Format(instr, "fctidz  'Dt, 'Db");
1020       break;
1021     }
1022     case FCTIDU: {
1023       Format(instr, "fctidu  'Dt, 'Db");
1024       break;
1025     }
1026     case FCTIDUZ: {
1027       Format(instr, "fctiduz 'Dt, 'Db");
1028       break;
1029     }
1030     case FCTIW: {
1031       Format(instr, "fctiw'. 'Dt, 'Db");
1032       break;
1033     }
1034     case FCTIWZ: {
1035       Format(instr, "fctiwz'. 'Dt, 'Db");
1036       break;
1037     }
1038     case FMR: {
1039       Format(instr, "fmr'.    'Dt, 'Db");
1040       break;
1041     }
1042     case MTFSFI: {
1043       Format(instr, "mtfsfi'.  ?,?");
1044       break;
1045     }
1046     case MFFS: {
1047       Format(instr, "mffs'.   'Dt");
1048       break;
1049     }
1050     case MTFSF: {
1051       Format(instr, "mtfsf'.  'Db ?,?,?");
1052       break;
1053     }
1054     case FABS: {
1055       Format(instr, "fabs'.   'Dt, 'Db");
1056       break;
1057     }
1058     case FRIN: {
1059       Format(instr, "frin.   'Dt, 'Db");
1060       break;
1061     }
1062     case FRIZ: {
1063       Format(instr, "friz.   'Dt, 'Db");
1064       break;
1065     }
1066     case FRIP: {
1067       Format(instr, "frip.   'Dt, 'Db");
1068       break;
1069     }
1070     case FRIM: {
1071       Format(instr, "frim.   'Dt, 'Db");
1072       break;
1073     }
1074     case FNEG: {
1075       Format(instr, "fneg'.   'Dt, 'Db");
1076       break;
1077     }
1078     case MCRFS: {
1079       Format(instr, "mcrfs   ?,?");
1080       break;
1081     }
1082     case MTFSB0: {
1083       Format(instr, "mtfsb0'. ?");
1084       break;
1085     }
1086     case MTFSB1: {
1087       Format(instr, "mtfsb1'. ?");
1088       break;
1089     }
1090     default: {
1091       Unknown(instr);  // not used by V8
1092     }
1093   }
1094 }
1095 
1096 
DecodeExt5(Instruction * instr)1097 void Decoder::DecodeExt5(Instruction* instr) {
1098   switch (EXT5 | (instr->BitField(4, 2))) {
1099     case RLDICL: {
1100       Format(instr, "rldicl'. 'ra, 'rs, 'sh, 'mb");
1101       return;
1102     }
1103     case RLDICR: {
1104       Format(instr, "rldicr'. 'ra, 'rs, 'sh, 'me");
1105       return;
1106     }
1107     case RLDIC: {
1108       Format(instr, "rldic'.  'ra, 'rs, 'sh, 'mb");
1109       return;
1110     }
1111     case RLDIMI: {
1112       Format(instr, "rldimi'. 'ra, 'rs, 'sh, 'mb");
1113       return;
1114     }
1115   }
1116   switch (EXT5 | (instr->BitField(4, 1))) {
1117     case RLDCL: {
1118       Format(instr, "rldcl'.  'ra, 'rs, 'sb, 'mb");
1119       return;
1120     }
1121   }
1122   Unknown(instr);  // not used by V8
1123 }
1124 
DecodeExt6(Instruction * instr)1125 void Decoder::DecodeExt6(Instruction* instr) {
1126   switch (EXT6 | (instr->BitField(10, 3))) {
1127 #define DECODE_XX3_INSTRUCTIONS(name, opcode_name, opcode_value) \
1128   case opcode_name: {                                            \
1129     Format(instr, #name" 'Dt, 'Da, 'Db");                        \
1130     return;                                                      \
1131   }
1132     PPC_XX3_OPCODE_LIST(DECODE_XX3_INSTRUCTIONS)
1133 #undef DECODE_XX3_INSTRUCTIONS
1134   }
1135   switch (EXT6 | (instr->BitField(10, 2))) {
1136 #define DECODE_XX2_INSTRUCTIONS(name, opcode_name, opcode_value) \
1137   case opcode_name: {                                            \
1138     Format(instr, #name" 'Dt, 'Db");                             \
1139     return;                                                      \
1140   }
1141     PPC_XX2_OPCODE_LIST(DECODE_XX2_INSTRUCTIONS)
1142   }
1143 #undef DECODE_XX3_INSTRUCTIONS
1144   Unknown(instr);  // not used by V8
1145 }
1146 
1147 #undef VERIFIY
1148 
1149 // Disassemble the instruction at *instr_ptr into the output buffer.
InstructionDecode(byte * instr_ptr)1150 int Decoder::InstructionDecode(byte* instr_ptr) {
1151   Instruction* instr = Instruction::At(instr_ptr);
1152   // Print raw instruction bytes.
1153   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x       ",
1154                               instr->InstructionBits());
1155 
1156   if (ABI_USES_FUNCTION_DESCRIPTORS && instr->InstructionBits() == 0) {
1157     // The first field will be identified as a jump table entry.  We
1158     // emit the rest of the structure as zero, so just skip past them.
1159     Format(instr, "constant");
1160     return kInstrSize;
1161   }
1162 
1163   uint32_t opcode = instr->OpcodeValue() << 26;
1164   switch (opcode) {
1165     case TWI: {
1166       PrintSoftwareInterrupt(instr->SvcValue());
1167       break;
1168     }
1169     case MULLI: {
1170       UnknownFormat(instr, "mulli");
1171       break;
1172     }
1173     case SUBFIC: {
1174       Format(instr, "subfic  'rt, 'ra, 'int16");
1175       break;
1176     }
1177     case CMPLI: {
1178 #if V8_TARGET_ARCH_PPC64
1179       if (instr->Bit(21)) {
1180 #endif
1181         Format(instr, "cmpli   'ra, 'uint16");
1182 #if V8_TARGET_ARCH_PPC64
1183       } else {
1184         Format(instr, "cmplwi  'ra, 'uint16");
1185       }
1186 #endif
1187       break;
1188     }
1189     case CMPI: {
1190 #if V8_TARGET_ARCH_PPC64
1191       if (instr->Bit(21)) {
1192 #endif
1193         Format(instr, "cmpi    'ra, 'int16");
1194 #if V8_TARGET_ARCH_PPC64
1195       } else {
1196         Format(instr, "cmpwi   'ra, 'int16");
1197       }
1198 #endif
1199       break;
1200     }
1201     case ADDIC: {
1202       Format(instr, "addic   'rt, 'ra, 'int16");
1203       break;
1204     }
1205     case ADDICx: {
1206       UnknownFormat(instr, "addicx");
1207       break;
1208     }
1209     case ADDI: {
1210       if (instr->RAValue() == 0) {
1211         // this is load immediate
1212         Format(instr, "li      'rt, 'int16");
1213       } else {
1214         Format(instr, "addi    'rt, 'ra, 'int16");
1215       }
1216       break;
1217     }
1218     case ADDIS: {
1219       if (instr->RAValue() == 0) {
1220         Format(instr, "lis     'rt, 'int16");
1221       } else {
1222         Format(instr, "addis   'rt, 'ra, 'int16");
1223       }
1224       break;
1225     }
1226     case BCX: {
1227       int bo = instr->Bits(25, 21) << 21;
1228       int bi = instr->Bits(20, 16);
1229       CRBit cond = static_cast<CRBit>(bi & (CRWIDTH - 1));
1230       switch (bo) {
1231         case BT: {  // Branch if condition true
1232           switch (cond) {
1233             case CR_EQ:
1234               Format(instr, "beq'l'a'cr 'target16");
1235               break;
1236             case CR_GT:
1237               Format(instr, "bgt'l'a'cr 'target16");
1238               break;
1239             case CR_LT:
1240               Format(instr, "blt'l'a'cr 'target16");
1241               break;
1242             case CR_SO:
1243               Format(instr, "bso'l'a'cr 'target16");
1244               break;
1245           }
1246           break;
1247         }
1248         case BF: {  // Branch if condition false
1249           switch (cond) {
1250             case CR_EQ:
1251               Format(instr, "bne'l'a'cr 'target16");
1252               break;
1253             case CR_GT:
1254               Format(instr, "ble'l'a'cr 'target16");
1255               break;
1256             case CR_LT:
1257               Format(instr, "bge'l'a'cr 'target16");
1258               break;
1259             case CR_SO:
1260               Format(instr, "bnso'l'a'cr 'target16");
1261               break;
1262           }
1263           break;
1264         }
1265         case DCBNZ: {  // Decrement CTR; branch if CTR != 0
1266           Format(instr, "bdnz'l'a 'target16");
1267           break;
1268         }
1269         default:
1270           Format(instr, "bc'l'a'cr 'target16");
1271           break;
1272       }
1273       break;
1274     }
1275     case SC: {
1276       UnknownFormat(instr, "sc");
1277       break;
1278     }
1279     case BX: {
1280       Format(instr, "b'l'a 'target26");
1281       break;
1282     }
1283     case EXT1: {
1284       DecodeExt1(instr);
1285       break;
1286     }
1287     case RLWIMIX: {
1288       Format(instr, "rlwimi'. 'ra, 'rs, 'sh, 'me, 'mb");
1289       break;
1290     }
1291     case RLWINMX: {
1292       Format(instr, "rlwinm'. 'ra, 'rs, 'sh, 'me, 'mb");
1293       break;
1294     }
1295     case RLWNMX: {
1296       Format(instr, "rlwnm'.  'ra, 'rs, 'rb, 'me, 'mb");
1297       break;
1298     }
1299     case ORI: {
1300       Format(instr, "ori     'ra, 'rs, 'uint16");
1301       break;
1302     }
1303     case ORIS: {
1304       Format(instr, "oris    'ra, 'rs, 'uint16");
1305       break;
1306     }
1307     case XORI: {
1308       Format(instr, "xori    'ra, 'rs, 'uint16");
1309       break;
1310     }
1311     case XORIS: {
1312       Format(instr, "xoris   'ra, 'rs, 'uint16");
1313       break;
1314     }
1315     case ANDIx: {
1316       Format(instr, "andi.   'ra, 'rs, 'uint16");
1317       break;
1318     }
1319     case ANDISx: {
1320       Format(instr, "andis.  'ra, 'rs, 'uint16");
1321       break;
1322     }
1323     case EXT2: {
1324       DecodeExt2(instr);
1325       break;
1326     }
1327     case LWZ: {
1328       Format(instr, "lwz     'rt, 'int16('ra)");
1329       break;
1330     }
1331     case LWZU: {
1332       Format(instr, "lwzu    'rt, 'int16('ra)");
1333       break;
1334     }
1335     case LBZ: {
1336       Format(instr, "lbz     'rt, 'int16('ra)");
1337       break;
1338     }
1339     case LBZU: {
1340       Format(instr, "lbzu    'rt, 'int16('ra)");
1341       break;
1342     }
1343     case STW: {
1344       Format(instr, "stw     'rs, 'int16('ra)");
1345       break;
1346     }
1347     case STWU: {
1348       Format(instr, "stwu    'rs, 'int16('ra)");
1349       break;
1350     }
1351     case STB: {
1352       Format(instr, "stb     'rs, 'int16('ra)");
1353       break;
1354     }
1355     case STBU: {
1356       Format(instr, "stbu    'rs, 'int16('ra)");
1357       break;
1358     }
1359     case LHZ: {
1360       Format(instr, "lhz     'rt, 'int16('ra)");
1361       break;
1362     }
1363     case LHZU: {
1364       Format(instr, "lhzu    'rt, 'int16('ra)");
1365       break;
1366     }
1367     case LHA: {
1368       Format(instr, "lha     'rt, 'int16('ra)");
1369       break;
1370     }
1371     case LHAU: {
1372       Format(instr, "lhau    'rt, 'int16('ra)");
1373       break;
1374     }
1375     case STH: {
1376       Format(instr, "sth 'rs, 'int16('ra)");
1377       break;
1378     }
1379     case STHU: {
1380       Format(instr, "sthu 'rs, 'int16('ra)");
1381       break;
1382     }
1383     case LMW: {
1384       UnknownFormat(instr, "lmw");
1385       break;
1386     }
1387     case STMW: {
1388       UnknownFormat(instr, "stmw");
1389       break;
1390     }
1391     case LFS: {
1392       Format(instr, "lfs     'Dt, 'int16('ra)");
1393       break;
1394     }
1395     case LFSU: {
1396       Format(instr, "lfsu    'Dt, 'int16('ra)");
1397       break;
1398     }
1399     case LFD: {
1400       Format(instr, "lfd     'Dt, 'int16('ra)");
1401       break;
1402     }
1403     case LFDU: {
1404       Format(instr, "lfdu    'Dt, 'int16('ra)");
1405       break;
1406     }
1407     case STFS: {
1408       Format(instr, "stfs    'Dt, 'int16('ra)");
1409       break;
1410     }
1411     case STFSU: {
1412       Format(instr, "stfsu   'Dt, 'int16('ra)");
1413       break;
1414     }
1415     case STFD: {
1416       Format(instr, "stfd    'Dt, 'int16('ra)");
1417       break;
1418     }
1419     case STFDU: {
1420       Format(instr, "stfdu   'Dt, 'int16('ra)");
1421       break;
1422     }
1423     case EXT3: {
1424       DecodeExt3(instr);
1425       break;
1426     }
1427     case EXT4: {
1428       DecodeExt4(instr);
1429       break;
1430     }
1431     case EXT5: {
1432       DecodeExt5(instr);
1433       break;
1434     }
1435     case EXT6: {
1436       DecodeExt6(instr);
1437       break;
1438     }
1439 #if V8_TARGET_ARCH_PPC64
1440     case LD: {
1441       switch (instr->Bits(1, 0)) {
1442         case 0:
1443           Format(instr, "ld      'rt, 'd('ra)");
1444           break;
1445         case 1:
1446           Format(instr, "ldu     'rt, 'd('ra)");
1447           break;
1448         case 2:
1449           Format(instr, "lwa     'rt, 'd('ra)");
1450           break;
1451       }
1452       break;
1453     }
1454     case STD: {  // could be STD or STDU
1455       if (instr->Bit(0) == 0) {
1456         Format(instr, "std     'rs, 'd('ra)");
1457       } else {
1458         Format(instr, "stdu    'rs, 'd('ra)");
1459       }
1460       break;
1461     }
1462 #endif
1463     default: {
1464       Unknown(instr);
1465       break;
1466     }
1467   }
1468 
1469   return kInstrSize;
1470 }
1471 }  // namespace internal
1472 }  // namespace v8
1473 
1474 
1475 //------------------------------------------------------------------------------
1476 
1477 namespace disasm {
1478 
1479 
NameOfAddress(byte * addr) const1480 const char* NameConverter::NameOfAddress(byte* addr) const {
1481   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
1482   return tmp_buffer_.start();
1483 }
1484 
1485 
NameOfConstant(byte * addr) const1486 const char* NameConverter::NameOfConstant(byte* addr) const {
1487   return NameOfAddress(addr);
1488 }
1489 
1490 
NameOfCPURegister(int reg) const1491 const char* NameConverter::NameOfCPURegister(int reg) const {
1492   return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
1493 }
1494 
NameOfByteCPURegister(int reg) const1495 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1496   UNREACHABLE();  // PPC does not have the concept of a byte register
1497   return "nobytereg";
1498 }
1499 
1500 
NameOfXMMRegister(int reg) const1501 const char* NameConverter::NameOfXMMRegister(int reg) const {
1502   UNREACHABLE();  // PPC does not have any XMM registers
1503   return "noxmmreg";
1504 }
1505 
NameInCode(byte * addr) const1506 const char* NameConverter::NameInCode(byte* addr) const {
1507   // The default name converter is called for unknown code. So we will not try
1508   // to access any memory.
1509   return "";
1510 }
1511 
1512 
1513 //------------------------------------------------------------------------------
1514 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)1515 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1516                                     byte* instruction) {
1517   v8::internal::Decoder d(converter_, buffer);
1518   return d.InstructionDecode(instruction);
1519 }
1520 
1521 
1522 // The PPC assembler does not currently use constant pools.
ConstantPoolSizeAt(byte * instruction)1523 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1524 
Disassemble(FILE * f,byte * begin,byte * end,UnimplementedOpcodeAction unimplemented_action)1525 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
1526                                UnimplementedOpcodeAction unimplemented_action) {
1527   NameConverter converter;
1528   Disassembler d(converter, unimplemented_action);
1529   for (byte* pc = begin; pc < end;) {
1530     v8::internal::EmbeddedVector<char, 128> buffer;
1531     buffer[0] = '\0';
1532     byte* prev_pc = pc;
1533     pc += d.InstructionDecode(buffer, pc);
1534     v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
1535                          *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1536   }
1537 }
1538 
1539 
1540 }  // namespace disasm
1541 
1542 #endif  // V8_TARGET_ARCH_PPC
1543