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