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