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

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

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