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