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

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