Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: src/ppc/disasm-ppc.cc

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

Powered by Google App Engine
This is Rietveld 408576698