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