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