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