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