• 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::Crankshaft;
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 
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.
PrintChar(const char ch)100 void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; }
101 
102 
103 // Append the str to the output buffer.
Print(const char * str)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.
PrintRegister(int reg)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.
PrintDRegister(int reg)121 void Decoder::PrintDRegister(int reg) {
122   Print(GetRegConfig()->GetDoubleRegisterName(reg));
123 }
124 
125 
126 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
127 // the FormatOption method.
PrintSoftwareInterrupt(SoftwareInterruptCodes svc)128 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
129   switch (svc) {
130     case kCallRtRedirected:
131       Print("call rt redirected");
132       return;
133     case kBreakpoint:
134       Print("breakpoint");
135       return;
136     default:
137       if (svc >= kStopCode) {
138         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d - 0x%x",
139                                     svc & kStopCodeMask, svc & kStopCodeMask);
140       } else {
141         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", svc);
142       }
143       return;
144   }
145 }
146 
147 
148 // Handle all register based formatting in this function to reduce the
149 // complexity of FormatOption.
FormatRegister(Instruction * instr,const char * format)150 int Decoder::FormatRegister(Instruction* instr, const char* format) {
151   DCHECK(format[0] == 'r');
152 
153   if ((format[1] == 't') || (format[1] == 's')) {  // 'rt & 'rs register
154     int reg = instr->RTValue();
155     PrintRegister(reg);
156     return 2;
157   } else if (format[1] == 'a') {  // 'ra: RA register
158     int reg = instr->RAValue();
159     PrintRegister(reg);
160     return 2;
161   } else if (format[1] == 'b') {  // 'rb: RB register
162     int reg = instr->RBValue();
163     PrintRegister(reg);
164     return 2;
165   }
166 
167   UNREACHABLE();
168   return -1;
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(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       case 's': {
273         DCHECK(format[1] == 'h');
274         int32_t value = 0;
275         int32_t opcode = instr->OpcodeValue() << 26;
276         int32_t sh = instr->Bits(15, 11);
277         if (opcode == EXT5 ||
278             (opcode == EXT2 && instr->Bits(10, 2) << 2 == SRADIX)) {
279           // SH Bits 1 and 15-11 (split field)
280           value = (sh | (instr->Bit(1) << 5));
281         } else {
282           // SH Bits 15-11
283           value = (sh << 26) >> 26;
284         }
285         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
286         return 2;
287       }
288       case 'm': {
289         int32_t value = 0;
290         if (format[1] == 'e') {
291           if (instr->OpcodeValue() << 26 != EXT5) {
292             // ME Bits 10-6
293             value = (instr->Bits(10, 6) << 26) >> 26;
294           } else {
295             // ME Bits 5 and 10-6 (split field)
296             value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
297           }
298         } else if (format[1] == 'b') {
299           if (instr->OpcodeValue() << 26 != EXT5) {
300             // MB Bits 5-1
301             value = (instr->Bits(5, 1) << 26) >> 26;
302           } else {
303             // MB Bits 5 and 10-6 (split field)
304             value = (instr->Bits(10, 6) | (instr->Bit(5) << 5));
305           }
306         } else {
307           UNREACHABLE();  // bad format
308         }
309         out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
310         return 2;
311       }
312     }
313 #if V8_TARGET_ARCH_PPC64
314     case 'd': {  // ds value for offset
315       int32_t value = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
316       out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
317       return 1;
318     }
319 #endif
320     default: {
321       UNREACHABLE();
322       break;
323     }
324   }
325 
326   UNREACHABLE();
327   return -1;
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 ressemble 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 (instr->Bits(10, 1) << 1) {
374     case MCRF: {
375       UnknownFormat(instr, "mcrf");  // not used by V8
376       break;
377     }
378     case BCLRX: {
379       int bo = instr->Bits(25, 21) << 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->Bits(25, 21) << 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 (instr->Bits(10, 1) << 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 SRAWIX: {
565       Format(instr, "srawi'.  'ra,'rs,'sh");
566       return;
567     }
568     case EXTSH: {
569       Format(instr, "extsh'.  'ra, 'rs");
570       return;
571     }
572 #if V8_TARGET_ARCH_PPC64
573     case EXTSW: {
574       Format(instr, "extsw'.  'ra, 'rs");
575       return;
576     }
577 #endif
578     case EXTSB: {
579       Format(instr, "extsb'.  'ra, 'rs");
580       return;
581     }
582     case LFSX: {
583       Format(instr, "lfsx    'rt, 'ra, 'rb");
584       return;
585     }
586     case LFSUX: {
587       Format(instr, "lfsux   'rt, 'ra, 'rb");
588       return;
589     }
590     case LFDX: {
591       Format(instr, "lfdx    'rt, 'ra, 'rb");
592       return;
593     }
594     case LFDUX: {
595       Format(instr, "lfdux   'rt, 'ra, 'rb");
596       return;
597     }
598     case STFSX: {
599       Format(instr, "stfsx    'rs, 'ra, 'rb");
600       return;
601     }
602     case STFSUX: {
603       Format(instr, "stfsux   'rs, 'ra, 'rb");
604       return;
605     }
606     case STFDX: {
607       Format(instr, "stfdx    'rs, 'ra, 'rb");
608       return;
609     }
610     case STFDUX: {
611       Format(instr, "stfdux   'rs, 'ra, 'rb");
612       return;
613     }
614     case POPCNTW: {
615       Format(instr, "popcntw  'ra, 'rs");
616       return;
617     }
618 #if V8_TARGET_ARCH_PPC64
619     case POPCNTD: {
620       Format(instr, "popcntd  'ra, 'rs");
621       return;
622     }
623 #endif
624   }
625 
626   switch (instr->Bits(10, 2) << 2) {
627     case SRADIX: {
628       Format(instr, "sradi'.  'ra,'rs,'sh");
629       return;
630     }
631   }
632 
633   // ?? are all of these xo_form?
634   switch (instr->Bits(9, 1) << 1) {
635     case CMP: {
636 #if V8_TARGET_ARCH_PPC64
637       if (instr->Bit(21)) {
638 #endif
639         Format(instr, "cmp     'ra, 'rb");
640 #if V8_TARGET_ARCH_PPC64
641       } else {
642         Format(instr, "cmpw    'ra, 'rb");
643       }
644 #endif
645       return;
646     }
647     case SLWX: {
648       Format(instr, "slw'.   'ra, 'rs, 'rb");
649       return;
650     }
651 #if V8_TARGET_ARCH_PPC64
652     case SLDX: {
653       Format(instr, "sld'.   'ra, 'rs, 'rb");
654       return;
655     }
656 #endif
657     case SUBFCX: {
658       Format(instr, "subfc'. 'rt, 'ra, 'rb");
659       return;
660     }
661     case SUBFEX: {
662       Format(instr, "subfe'. 'rt, 'ra, 'rb");
663       return;
664     }
665     case ADDCX: {
666       Format(instr, "addc'.   'rt, 'ra, 'rb");
667       return;
668     }
669     case ADDEX: {
670       Format(instr, "adde'.   'rt, 'ra, 'rb");
671       return;
672     }
673     case CNTLZWX: {
674       Format(instr, "cntlzw'. 'ra, 'rs");
675       return;
676     }
677 #if V8_TARGET_ARCH_PPC64
678     case CNTLZDX: {
679       Format(instr, "cntlzd'. 'ra, 'rs");
680       return;
681     }
682 #endif
683     case ANDX: {
684       Format(instr, "and'.    'ra, 'rs, 'rb");
685       return;
686     }
687     case ANDCX: {
688       Format(instr, "andc'.   'ra, 'rs, 'rb");
689       return;
690     }
691     case CMPL: {
692 #if V8_TARGET_ARCH_PPC64
693       if (instr->Bit(21)) {
694 #endif
695         Format(instr, "cmpl    'ra, 'rb");
696 #if V8_TARGET_ARCH_PPC64
697       } else {
698         Format(instr, "cmplw   'ra, 'rb");
699       }
700 #endif
701       return;
702     }
703     case NEGX: {
704       Format(instr, "neg'.    'rt, 'ra");
705       return;
706     }
707     case NORX: {
708       Format(instr, "nor'.    'rt, 'ra, 'rb");
709       return;
710     }
711     case SUBFX: {
712       Format(instr, "subf'.   'rt, 'ra, 'rb");
713       return;
714     }
715     case MULHWX: {
716       Format(instr, "mulhw'o'.  'rt, 'ra, 'rb");
717       return;
718     }
719     case ADDZEX: {
720       Format(instr, "addze'.   'rt, 'ra");
721       return;
722     }
723     case MULLW: {
724       Format(instr, "mullw'o'.  'rt, 'ra, 'rb");
725       return;
726     }
727 #if V8_TARGET_ARCH_PPC64
728     case MULLD: {
729       Format(instr, "mulld'o'.  'rt, 'ra, 'rb");
730       return;
731     }
732 #endif
733     case DIVW: {
734       Format(instr, "divw'o'.   'rt, 'ra, 'rb");
735       return;
736     }
737     case DIVWU: {
738       Format(instr, "divwu'o'.  'rt, 'ra, 'rb");
739       return;
740     }
741 #if V8_TARGET_ARCH_PPC64
742     case DIVD: {
743       Format(instr, "divd'o'.   'rt, 'ra, 'rb");
744       return;
745     }
746 #endif
747     case ADDX: {
748       Format(instr, "add'o     'rt, 'ra, 'rb");
749       return;
750     }
751     case XORX: {
752       Format(instr, "xor'.    'ra, 'rs, 'rb");
753       return;
754     }
755     case ORX: {
756       if (instr->RTValue() == instr->RBValue()) {
757         Format(instr, "mr      'ra, 'rb");
758       } else {
759         Format(instr, "or      'ra, 'rs, 'rb");
760       }
761       return;
762     }
763     case MFSPR: {
764       int spr = instr->Bits(20, 11);
765       if (256 == spr) {
766         Format(instr, "mflr    'rt");
767       } else {
768         Format(instr, "mfspr   'rt ??");
769       }
770       return;
771     }
772     case MTSPR: {
773       int spr = instr->Bits(20, 11);
774       if (256 == spr) {
775         Format(instr, "mtlr    'rt");
776       } else if (288 == spr) {
777         Format(instr, "mtctr   'rt");
778       } else {
779         Format(instr, "mtspr   'rt ??");
780       }
781       return;
782     }
783     case MFCR: {
784       Format(instr, "mfcr    'rt");
785       return;
786     }
787     case STWX: {
788       Format(instr, "stwx    'rs, 'ra, 'rb");
789       return;
790     }
791     case STWUX: {
792       Format(instr, "stwux   'rs, 'ra, 'rb");
793       return;
794     }
795     case STBX: {
796       Format(instr, "stbx    'rs, 'ra, 'rb");
797       return;
798     }
799     case STBUX: {
800       Format(instr, "stbux   'rs, 'ra, 'rb");
801       return;
802     }
803     case STHX: {
804       Format(instr, "sthx    'rs, 'ra, 'rb");
805       return;
806     }
807     case STHUX: {
808       Format(instr, "sthux   'rs, 'ra, 'rb");
809       return;
810     }
811     case LWZX: {
812       Format(instr, "lwzx    'rt, 'ra, 'rb");
813       return;
814     }
815     case LWZUX: {
816       Format(instr, "lwzux   'rt, 'ra, 'rb");
817       return;
818     }
819     case LWAX: {
820       Format(instr, "lwax    'rt, 'ra, 'rb");
821       return;
822     }
823     case LBZX: {
824       Format(instr, "lbzx    'rt, 'ra, 'rb");
825       return;
826     }
827     case LBZUX: {
828       Format(instr, "lbzux   'rt, 'ra, 'rb");
829       return;
830     }
831     case LHZX: {
832       Format(instr, "lhzx    'rt, 'ra, 'rb");
833       return;
834     }
835     case LHZUX: {
836       Format(instr, "lhzux   'rt, 'ra, 'rb");
837       return;
838     }
839     case LHAX: {
840       Format(instr, "lhax    'rt, 'ra, 'rb");
841       return;
842     }
843 #if V8_TARGET_ARCH_PPC64
844     case LDX: {
845       Format(instr, "ldx     'rt, 'ra, 'rb");
846       return;
847     }
848     case LDUX: {
849       Format(instr, "ldux    'rt, 'ra, 'rb");
850       return;
851     }
852     case STDX: {
853       Format(instr, "stdx    'rt, 'ra, 'rb");
854       return;
855     }
856     case STDUX: {
857       Format(instr, "stdux   'rt, 'ra, 'rb");
858       return;
859     }
860     case MFVSRD: {
861       Format(instr, "mffprd  'ra, 'Dt");
862       return;
863     }
864     case MFVSRWZ: {
865       Format(instr, "mffprwz 'ra, 'Dt");
866       return;
867     }
868     case MTVSRD: {
869       Format(instr, "mtfprd  'Dt, 'ra");
870       return;
871     }
872     case MTVSRWA: {
873       Format(instr, "mtfprwa 'Dt, 'ra");
874       return;
875     }
876     case MTVSRWZ: {
877       Format(instr, "mtfprwz 'Dt, 'ra");
878       return;
879     }
880 #endif
881   }
882 
883   switch (instr->Bits(5, 1) << 1) {
884     case ISEL: {
885       Format(instr, "isel    'rt, 'ra, 'rb");
886       return;
887     }
888     default: {
889       Unknown(instr);  // not used by V8
890     }
891   }
892 }
893 
894 
DecodeExt3(Instruction * instr)895 void Decoder::DecodeExt3(Instruction* instr) {
896   switch (instr->Bits(10, 1) << 1) {
897     case FCFID: {
898       Format(instr, "fcfids'. 'Dt, 'Db");
899       break;
900     }
901     case FCFIDU: {
902       Format(instr, "fcfidus'.'Dt, 'Db");
903       break;
904     }
905     default: {
906       Unknown(instr);  // not used by V8
907     }
908   }
909 }
910 
911 
DecodeExt4(Instruction * instr)912 void Decoder::DecodeExt4(Instruction* instr) {
913   switch (instr->Bits(5, 1) << 1) {
914     case FDIV: {
915       Format(instr, "fdiv'.   'Dt, 'Da, 'Db");
916       return;
917     }
918     case FSUB: {
919       Format(instr, "fsub'.   'Dt, 'Da, 'Db");
920       return;
921     }
922     case FADD: {
923       Format(instr, "fadd'.   'Dt, 'Da, 'Db");
924       return;
925     }
926     case FSQRT: {
927       Format(instr, "fsqrt'.  'Dt, 'Db");
928       return;
929     }
930     case FSEL: {
931       Format(instr, "fsel'.   'Dt, 'Da, 'Dc, 'Db");
932       return;
933     }
934     case FMUL: {
935       Format(instr, "fmul'.   'Dt, 'Da, 'Dc");
936       return;
937     }
938     case FMSUB: {
939       Format(instr, "fmsub'.  'Dt, 'Da, 'Dc, 'Db");
940       return;
941     }
942     case FMADD: {
943       Format(instr, "fmadd'.  'Dt, 'Da, 'Dc, 'Db");
944       return;
945     }
946   }
947 
948   switch (instr->Bits(10, 1) << 1) {
949     case FCMPU: {
950       Format(instr, "fcmpu   'Da, 'Db");
951       break;
952     }
953     case FRSP: {
954       Format(instr, "frsp'.   'Dt, 'Db");
955       break;
956     }
957     case FCFID: {
958       Format(instr, "fcfid'.  'Dt, 'Db");
959       break;
960     }
961     case FCFIDU: {
962       Format(instr, "fcfidu'. 'Dt, 'Db");
963       break;
964     }
965     case FCTID: {
966       Format(instr, "fctid   'Dt, 'Db");
967       break;
968     }
969     case FCTIDZ: {
970       Format(instr, "fctidz  'Dt, 'Db");
971       break;
972     }
973     case FCTIDU: {
974       Format(instr, "fctidu  'Dt, 'Db");
975       break;
976     }
977     case FCTIDUZ: {
978       Format(instr, "fctiduz 'Dt, 'Db");
979       break;
980     }
981     case FCTIW: {
982       Format(instr, "fctiw'. 'Dt, 'Db");
983       break;
984     }
985     case FCTIWZ: {
986       Format(instr, "fctiwz'. 'Dt, 'Db");
987       break;
988     }
989     case FMR: {
990       Format(instr, "fmr'.    'Dt, 'Db");
991       break;
992     }
993     case MTFSFI: {
994       Format(instr, "mtfsfi'.  ?,?");
995       break;
996     }
997     case MFFS: {
998       Format(instr, "mffs'.   'Dt");
999       break;
1000     }
1001     case MTFSF: {
1002       Format(instr, "mtfsf'.  'Db ?,?,?");
1003       break;
1004     }
1005     case FABS: {
1006       Format(instr, "fabs'.   'Dt, 'Db");
1007       break;
1008     }
1009     case FRIN: {
1010       Format(instr, "frin.   'Dt, 'Db");
1011       break;
1012     }
1013     case FRIZ: {
1014       Format(instr, "friz.   'Dt, 'Db");
1015       break;
1016     }
1017     case FRIP: {
1018       Format(instr, "frip.   'Dt, 'Db");
1019       break;
1020     }
1021     case FRIM: {
1022       Format(instr, "frim.   'Dt, 'Db");
1023       break;
1024     }
1025     case FNEG: {
1026       Format(instr, "fneg'.   'Dt, 'Db");
1027       break;
1028     }
1029     case MCRFS: {
1030       Format(instr, "mcrfs   ?,?");
1031       break;
1032     }
1033     case MTFSB0: {
1034       Format(instr, "mtfsb0'. ?");
1035       break;
1036     }
1037     case MTFSB1: {
1038       Format(instr, "mtfsb1'. ?");
1039       break;
1040     }
1041     default: {
1042       Unknown(instr);  // not used by V8
1043     }
1044   }
1045 }
1046 
1047 
DecodeExt5(Instruction * instr)1048 void Decoder::DecodeExt5(Instruction* instr) {
1049   switch (instr->Bits(4, 2) << 2) {
1050     case RLDICL: {
1051       Format(instr, "rldicl'. 'ra, 'rs, 'sh, 'mb");
1052       return;
1053     }
1054     case RLDICR: {
1055       Format(instr, "rldicr'. 'ra, 'rs, 'sh, 'me");
1056       return;
1057     }
1058     case RLDIC: {
1059       Format(instr, "rldic'.  'ra, 'rs, 'sh, 'mb");
1060       return;
1061     }
1062     case RLDIMI: {
1063       Format(instr, "rldimi'. 'ra, 'rs, 'sh, 'mb");
1064       return;
1065     }
1066   }
1067   switch (instr->Bits(4, 1) << 1) {
1068     case RLDCL: {
1069       Format(instr, "rldcl'.  'ra, 'rs, 'sb, 'mb");
1070       return;
1071     }
1072   }
1073   Unknown(instr);  // not used by V8
1074 }
1075 
1076 #undef VERIFIY
1077 
1078 // Disassemble the instruction at *instr_ptr into the output buffer.
InstructionDecode(byte * instr_ptr)1079 int Decoder::InstructionDecode(byte* instr_ptr) {
1080   Instruction* instr = Instruction::At(instr_ptr);
1081   // Print raw instruction bytes.
1082   out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x       ",
1083                               instr->InstructionBits());
1084 
1085   if (ABI_USES_FUNCTION_DESCRIPTORS && instr->InstructionBits() == 0) {
1086     // The first field will be identified as a jump table entry.  We
1087     // emit the rest of the structure as zero, so just skip past them.
1088     Format(instr, "constant");
1089     return Instruction::kInstrSize;
1090   }
1091 
1092   switch (instr->OpcodeValue() << 26) {
1093     case TWI: {
1094       PrintSoftwareInterrupt(instr->SvcValue());
1095       break;
1096     }
1097     case MULLI: {
1098       UnknownFormat(instr, "mulli");
1099       break;
1100     }
1101     case SUBFIC: {
1102       Format(instr, "subfic  'rt, 'ra, 'int16");
1103       break;
1104     }
1105     case CMPLI: {
1106 #if V8_TARGET_ARCH_PPC64
1107       if (instr->Bit(21)) {
1108 #endif
1109         Format(instr, "cmpli   'ra, 'uint16");
1110 #if V8_TARGET_ARCH_PPC64
1111       } else {
1112         Format(instr, "cmplwi  'ra, 'uint16");
1113       }
1114 #endif
1115       break;
1116     }
1117     case CMPI: {
1118 #if V8_TARGET_ARCH_PPC64
1119       if (instr->Bit(21)) {
1120 #endif
1121         Format(instr, "cmpi    'ra, 'int16");
1122 #if V8_TARGET_ARCH_PPC64
1123       } else {
1124         Format(instr, "cmpwi   'ra, 'int16");
1125       }
1126 #endif
1127       break;
1128     }
1129     case ADDIC: {
1130       Format(instr, "addic   'rt, 'ra, 'int16");
1131       break;
1132     }
1133     case ADDICx: {
1134       UnknownFormat(instr, "addicx");
1135       break;
1136     }
1137     case ADDI: {
1138       if (instr->RAValue() == 0) {
1139         // this is load immediate
1140         Format(instr, "li      'rt, 'int16");
1141       } else {
1142         Format(instr, "addi    'rt, 'ra, 'int16");
1143       }
1144       break;
1145     }
1146     case ADDIS: {
1147       if (instr->RAValue() == 0) {
1148         Format(instr, "lis     'rt, 'int16");
1149       } else {
1150         Format(instr, "addis   'rt, 'ra, 'int16");
1151       }
1152       break;
1153     }
1154     case BCX: {
1155       int bo = instr->Bits(25, 21) << 21;
1156       int bi = instr->Bits(20, 16);
1157       CRBit cond = static_cast<CRBit>(bi & (CRWIDTH - 1));
1158       switch (bo) {
1159         case BT: {  // Branch if condition true
1160           switch (cond) {
1161             case CR_EQ:
1162               Format(instr, "beq'l'a'cr 'target16");
1163               break;
1164             case CR_GT:
1165               Format(instr, "bgt'l'a'cr 'target16");
1166               break;
1167             case CR_LT:
1168               Format(instr, "blt'l'a'cr 'target16");
1169               break;
1170             case CR_SO:
1171               Format(instr, "bso'l'a'cr 'target16");
1172               break;
1173           }
1174           break;
1175         }
1176         case BF: {  // Branch if condition false
1177           switch (cond) {
1178             case CR_EQ:
1179               Format(instr, "bne'l'a'cr 'target16");
1180               break;
1181             case CR_GT:
1182               Format(instr, "ble'l'a'cr 'target16");
1183               break;
1184             case CR_LT:
1185               Format(instr, "bge'l'a'cr 'target16");
1186               break;
1187             case CR_SO:
1188               Format(instr, "bnso'l'a'cr 'target16");
1189               break;
1190           }
1191           break;
1192         }
1193         case DCBNZ: {  // Decrement CTR; branch if CTR != 0
1194           Format(instr, "bdnz'l'a 'target16");
1195           break;
1196         }
1197         default:
1198           Format(instr, "bc'l'a'cr 'target16");
1199           break;
1200       }
1201       break;
1202     }
1203     case SC: {
1204       UnknownFormat(instr, "sc");
1205       break;
1206     }
1207     case BX: {
1208       Format(instr, "b'l'a 'target26");
1209       break;
1210     }
1211     case EXT1: {
1212       DecodeExt1(instr);
1213       break;
1214     }
1215     case RLWIMIX: {
1216       Format(instr, "rlwimi'. 'ra, 'rs, 'sh, 'me, 'mb");
1217       break;
1218     }
1219     case RLWINMX: {
1220       Format(instr, "rlwinm'. 'ra, 'rs, 'sh, 'me, 'mb");
1221       break;
1222     }
1223     case RLWNMX: {
1224       Format(instr, "rlwnm'.  'ra, 'rs, 'rb, 'me, 'mb");
1225       break;
1226     }
1227     case ORI: {
1228       Format(instr, "ori     'ra, 'rs, 'uint16");
1229       break;
1230     }
1231     case ORIS: {
1232       Format(instr, "oris    'ra, 'rs, 'uint16");
1233       break;
1234     }
1235     case XORI: {
1236       Format(instr, "xori    'ra, 'rs, 'uint16");
1237       break;
1238     }
1239     case XORIS: {
1240       Format(instr, "xoris   'ra, 'rs, 'uint16");
1241       break;
1242     }
1243     case ANDIx: {
1244       Format(instr, "andi.   'ra, 'rs, 'uint16");
1245       break;
1246     }
1247     case ANDISx: {
1248       Format(instr, "andis.  'ra, 'rs, 'uint16");
1249       break;
1250     }
1251     case EXT2: {
1252       DecodeExt2(instr);
1253       break;
1254     }
1255     case LWZ: {
1256       Format(instr, "lwz     'rt, 'int16('ra)");
1257       break;
1258     }
1259     case LWZU: {
1260       Format(instr, "lwzu    'rt, 'int16('ra)");
1261       break;
1262     }
1263     case LBZ: {
1264       Format(instr, "lbz     'rt, 'int16('ra)");
1265       break;
1266     }
1267     case LBZU: {
1268       Format(instr, "lbzu    'rt, 'int16('ra)");
1269       break;
1270     }
1271     case STW: {
1272       Format(instr, "stw     'rs, 'int16('ra)");
1273       break;
1274     }
1275     case STWU: {
1276       Format(instr, "stwu    'rs, 'int16('ra)");
1277       break;
1278     }
1279     case STB: {
1280       Format(instr, "stb     'rs, 'int16('ra)");
1281       break;
1282     }
1283     case STBU: {
1284       Format(instr, "stbu    'rs, 'int16('ra)");
1285       break;
1286     }
1287     case LHZ: {
1288       Format(instr, "lhz     'rt, 'int16('ra)");
1289       break;
1290     }
1291     case LHZU: {
1292       Format(instr, "lhzu    'rt, 'int16('ra)");
1293       break;
1294     }
1295     case LHA: {
1296       Format(instr, "lha     'rt, 'int16('ra)");
1297       break;
1298     }
1299     case LHAU: {
1300       Format(instr, "lhau    'rt, 'int16('ra)");
1301       break;
1302     }
1303     case STH: {
1304       Format(instr, "sth 'rs, 'int16('ra)");
1305       break;
1306     }
1307     case STHU: {
1308       Format(instr, "sthu 'rs, 'int16('ra)");
1309       break;
1310     }
1311     case LMW: {
1312       UnknownFormat(instr, "lmw");
1313       break;
1314     }
1315     case STMW: {
1316       UnknownFormat(instr, "stmw");
1317       break;
1318     }
1319     case LFS: {
1320       Format(instr, "lfs     'Dt, 'int16('ra)");
1321       break;
1322     }
1323     case LFSU: {
1324       Format(instr, "lfsu    'Dt, 'int16('ra)");
1325       break;
1326     }
1327     case LFD: {
1328       Format(instr, "lfd     'Dt, 'int16('ra)");
1329       break;
1330     }
1331     case LFDU: {
1332       Format(instr, "lfdu    'Dt, 'int16('ra)");
1333       break;
1334     }
1335     case STFS: {
1336       Format(instr, "stfs    'Dt, 'int16('ra)");
1337       break;
1338     }
1339     case STFSU: {
1340       Format(instr, "stfsu   'Dt, 'int16('ra)");
1341       break;
1342     }
1343     case STFD: {
1344       Format(instr, "stfd    'Dt, 'int16('ra)");
1345       break;
1346     }
1347     case STFDU: {
1348       Format(instr, "stfdu   'Dt, 'int16('ra)");
1349       break;
1350     }
1351     case EXT3: {
1352       DecodeExt3(instr);
1353       break;
1354     }
1355     case EXT4: {
1356       DecodeExt4(instr);
1357       break;
1358     }
1359     case EXT5: {
1360       DecodeExt5(instr);
1361       break;
1362     }
1363 #if V8_TARGET_ARCH_PPC64
1364     case LD: {
1365       switch (instr->Bits(1, 0)) {
1366         case 0:
1367           Format(instr, "ld      'rt, 'd('ra)");
1368           break;
1369         case 1:
1370           Format(instr, "ldu     'rt, 'd('ra)");
1371           break;
1372         case 2:
1373           Format(instr, "lwa     'rt, 'd('ra)");
1374           break;
1375       }
1376       break;
1377     }
1378     case STD: {  // could be STD or STDU
1379       if (instr->Bit(0) == 0) {
1380         Format(instr, "std     'rs, 'd('ra)");
1381       } else {
1382         Format(instr, "stdu    'rs, 'd('ra)");
1383       }
1384       break;
1385     }
1386 #endif
1387     default: {
1388       Unknown(instr);
1389       break;
1390     }
1391   }
1392 
1393   return Instruction::kInstrSize;
1394 }
1395 }  // namespace internal
1396 }  // namespace v8
1397 
1398 
1399 //------------------------------------------------------------------------------
1400 
1401 namespace disasm {
1402 
1403 
NameOfAddress(byte * addr) const1404 const char* NameConverter::NameOfAddress(byte* addr) const {
1405   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
1406   return tmp_buffer_.start();
1407 }
1408 
1409 
NameOfConstant(byte * addr) const1410 const char* NameConverter::NameOfConstant(byte* addr) const {
1411   return NameOfAddress(addr);
1412 }
1413 
1414 
NameOfCPURegister(int reg) const1415 const char* NameConverter::NameOfCPURegister(int reg) const {
1416   return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
1417 }
1418 
NameOfByteCPURegister(int reg) const1419 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1420   UNREACHABLE();  // PPC does not have the concept of a byte register
1421   return "nobytereg";
1422 }
1423 
1424 
NameOfXMMRegister(int reg) const1425 const char* NameConverter::NameOfXMMRegister(int reg) const {
1426   UNREACHABLE();  // PPC does not have any XMM registers
1427   return "noxmmreg";
1428 }
1429 
NameInCode(byte * addr) const1430 const char* NameConverter::NameInCode(byte* addr) const {
1431   // The default name converter is called for unknown code. So we will not try
1432   // to access any memory.
1433   return "";
1434 }
1435 
1436 
1437 //------------------------------------------------------------------------------
1438 
Disassembler(const NameConverter & converter)1439 Disassembler::Disassembler(const NameConverter& converter)
1440     : converter_(converter) {}
1441 
1442 
~Disassembler()1443 Disassembler::~Disassembler() {}
1444 
1445 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)1446 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1447                                     byte* instruction) {
1448   v8::internal::Decoder d(converter_, buffer);
1449   return d.InstructionDecode(instruction);
1450 }
1451 
1452 
1453 // The PPC assembler does not currently use constant pools.
ConstantPoolSizeAt(byte * instruction)1454 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1455 
1456 
Disassemble(FILE * f,byte * begin,byte * end)1457 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1458   NameConverter converter;
1459   Disassembler d(converter);
1460   for (byte* pc = begin; pc < end;) {
1461     v8::internal::EmbeddedVector<char, 128> buffer;
1462     buffer[0] = '\0';
1463     byte* prev_pc = pc;
1464     pc += d.InstructionDecode(buffer, pc);
1465     v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
1466                          *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1467   }
1468 }
1469 
1470 
1471 }  // namespace disasm
1472 
1473 #endif  // V8_TARGET_ARCH_PPC
1474