1// Copyright 2012 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 <stdio.h> 28#include <stdarg.h> 29#include <string.h> 30 31#include "src/v8.h" 32 33#if V8_TARGET_ARCH_MIPS 34 35#include "src/mips/constants-mips.h" 36#include "src/disasm.h" 37#include "src/macro-assembler.h" 38#include "src/platform.h" 39 40namespace v8 { 41namespace internal { 42 43//------------------------------------------------------------------------------ 44 45// Decoder decodes and disassembles instructions into an output buffer. 46// It uses the converter to convert register names and call destinations into 47// more informative description. 48class Decoder { 49 public: 50 Decoder(const disasm::NameConverter& converter, 51 v8::internal::Vector<char> out_buffer) 52 : converter_(converter), 53 out_buffer_(out_buffer), 54 out_buffer_pos_(0) { 55 out_buffer_[out_buffer_pos_] = '\0'; 56 } 57 58 ~Decoder() {} 59 60 // Writes one disassembled instruction into 'buffer' (0-terminated). 61 // Returns the length of the disassembled machine instruction in bytes. 62 int InstructionDecode(byte* instruction); 63 64 private: 65 // Bottleneck functions to print into the out_buffer. 66 void PrintChar(const char ch); 67 void Print(const char* str); 68 69 // Printing of common values. 70 void PrintRegister(int reg); 71 void PrintFPURegister(int freg); 72 void PrintRs(Instruction* instr); 73 void PrintRt(Instruction* instr); 74 void PrintRd(Instruction* instr); 75 void PrintFs(Instruction* instr); 76 void PrintFt(Instruction* instr); 77 void PrintFd(Instruction* instr); 78 void PrintSa(Instruction* instr); 79 void PrintSd(Instruction* instr); 80 void PrintSs1(Instruction* instr); 81 void PrintSs2(Instruction* instr); 82 void PrintBc(Instruction* instr); 83 void PrintCc(Instruction* instr); 84 void PrintFunction(Instruction* instr); 85 void PrintSecondaryField(Instruction* instr); 86 void PrintUImm16(Instruction* instr); 87 void PrintSImm16(Instruction* instr); 88 void PrintXImm16(Instruction* instr); 89 void PrintXImm26(Instruction* instr); 90 void PrintCode(Instruction* instr); // For break and trap instructions. 91 // Printing of instruction name. 92 void PrintInstructionName(Instruction* instr); 93 94 // Handle formatting of instructions and their options. 95 int FormatRegister(Instruction* instr, const char* option); 96 int FormatFPURegister(Instruction* instr, const char* option); 97 int FormatOption(Instruction* instr, const char* option); 98 void Format(Instruction* instr, const char* format); 99 void Unknown(Instruction* instr); 100 101 // Each of these functions decodes one particular instruction type. 102 void DecodeTypeRegister(Instruction* instr); 103 void DecodeTypeImmediate(Instruction* instr); 104 void DecodeTypeJump(Instruction* instr); 105 106 const disasm::NameConverter& converter_; 107 v8::internal::Vector<char> out_buffer_; 108 int out_buffer_pos_; 109 110 DISALLOW_COPY_AND_ASSIGN(Decoder); 111}; 112 113 114// Support for assertions in the Decoder formatting functions. 115#define STRING_STARTS_WITH(string, compare_string) \ 116 (strncmp(string, compare_string, strlen(compare_string)) == 0) 117 118 119// Append the ch to the output buffer. 120void Decoder::PrintChar(const char ch) { 121 out_buffer_[out_buffer_pos_++] = ch; 122} 123 124 125// Append the str to the output buffer. 126void Decoder::Print(const char* str) { 127 char cur = *str++; 128 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 129 PrintChar(cur); 130 cur = *str++; 131 } 132 out_buffer_[out_buffer_pos_] = 0; 133} 134 135 136// Print the register name according to the active name converter. 137void Decoder::PrintRegister(int reg) { 138 Print(converter_.NameOfCPURegister(reg)); 139} 140 141 142void Decoder::PrintRs(Instruction* instr) { 143 int reg = instr->RsValue(); 144 PrintRegister(reg); 145} 146 147 148void Decoder::PrintRt(Instruction* instr) { 149 int reg = instr->RtValue(); 150 PrintRegister(reg); 151} 152 153 154void Decoder::PrintRd(Instruction* instr) { 155 int reg = instr->RdValue(); 156 PrintRegister(reg); 157} 158 159 160// Print the FPUregister name according to the active name converter. 161void Decoder::PrintFPURegister(int freg) { 162 Print(converter_.NameOfXMMRegister(freg)); 163} 164 165 166void Decoder::PrintFs(Instruction* instr) { 167 int freg = instr->RsValue(); 168 PrintFPURegister(freg); 169} 170 171 172void Decoder::PrintFt(Instruction* instr) { 173 int freg = instr->RtValue(); 174 PrintFPURegister(freg); 175} 176 177 178void Decoder::PrintFd(Instruction* instr) { 179 int freg = instr->RdValue(); 180 PrintFPURegister(freg); 181} 182 183 184// Print the integer value of the sa field. 185void Decoder::PrintSa(Instruction* instr) { 186 int sa = instr->SaValue(); 187 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa); 188} 189 190 191// Print the integer value of the rd field, when it is not used as reg. 192void Decoder::PrintSd(Instruction* instr) { 193 int sd = instr->RdValue(); 194 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd); 195} 196 197 198// Print the integer value of the rd field, when used as 'ext' size. 199void Decoder::PrintSs1(Instruction* instr) { 200 int ss = instr->RdValue(); 201 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1); 202} 203 204 205// Print the integer value of the rd field, when used as 'ins' size. 206void Decoder::PrintSs2(Instruction* instr) { 207 int ss = instr->RdValue(); 208 int pos = instr->SaValue(); 209 out_buffer_pos_ += 210 SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1); 211} 212 213 214// Print the integer value of the cc field for the bc1t/f instructions. 215void Decoder::PrintBc(Instruction* instr) { 216 int cc = instr->FBccValue(); 217 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc); 218} 219 220 221// Print the integer value of the cc field for the FP compare instructions. 222void Decoder::PrintCc(Instruction* instr) { 223 int cc = instr->FCccValue(); 224 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc); 225} 226 227 228// Print 16-bit unsigned immediate value. 229void Decoder::PrintUImm16(Instruction* instr) { 230 int32_t imm = instr->Imm16Value(); 231 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm); 232} 233 234 235// Print 16-bit signed immediate value. 236void Decoder::PrintSImm16(Instruction* instr) { 237 int32_t imm = ((instr->Imm16Value()) << 16) >> 16; 238 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 239} 240 241 242// Print 16-bit hexa immediate value. 243void Decoder::PrintXImm16(Instruction* instr) { 244 int32_t imm = instr->Imm16Value(); 245 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 246} 247 248 249// Print 26-bit immediate value. 250void Decoder::PrintXImm26(Instruction* instr) { 251 uint32_t imm = instr->Imm26Value() << kImmFieldShift; 252 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 253} 254 255 256// Print 26-bit immediate value. 257void Decoder::PrintCode(Instruction* instr) { 258 if (instr->OpcodeFieldRaw() != SPECIAL) 259 return; // Not a break or trap instruction. 260 switch (instr->FunctionFieldRaw()) { 261 case BREAK: { 262 int32_t code = instr->Bits(25, 6); 263 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 264 "0x%05x (%d)", code, code); 265 break; 266 } 267 case TGE: 268 case TGEU: 269 case TLT: 270 case TLTU: 271 case TEQ: 272 case TNE: { 273 int32_t code = instr->Bits(15, 6); 274 out_buffer_pos_ += 275 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code); 276 break; 277 } 278 default: // Not a break or trap instruction. 279 break; 280 } 281} 282 283 284// Printing of instruction name. 285void Decoder::PrintInstructionName(Instruction* instr) { 286} 287 288 289// Handle all register based formatting in this function to reduce the 290// complexity of FormatOption. 291int Decoder::FormatRegister(Instruction* instr, const char* format) { 292 ASSERT(format[0] == 'r'); 293 if (format[1] == 's') { // 'rs: Rs register. 294 int reg = instr->RsValue(); 295 PrintRegister(reg); 296 return 2; 297 } else if (format[1] == 't') { // 'rt: rt register. 298 int reg = instr->RtValue(); 299 PrintRegister(reg); 300 return 2; 301 } else if (format[1] == 'd') { // 'rd: rd register. 302 int reg = instr->RdValue(); 303 PrintRegister(reg); 304 return 2; 305 } 306 UNREACHABLE(); 307 return -1; 308} 309 310 311// Handle all FPUregister based formatting in this function to reduce the 312// complexity of FormatOption. 313int Decoder::FormatFPURegister(Instruction* instr, const char* format) { 314 ASSERT(format[0] == 'f'); 315 if (format[1] == 's') { // 'fs: fs register. 316 int reg = instr->FsValue(); 317 PrintFPURegister(reg); 318 return 2; 319 } else if (format[1] == 't') { // 'ft: ft register. 320 int reg = instr->FtValue(); 321 PrintFPURegister(reg); 322 return 2; 323 } else if (format[1] == 'd') { // 'fd: fd register. 324 int reg = instr->FdValue(); 325 PrintFPURegister(reg); 326 return 2; 327 } else if (format[1] == 'r') { // 'fr: fr register. 328 int reg = instr->FrValue(); 329 PrintFPURegister(reg); 330 return 2; 331 } 332 UNREACHABLE(); 333 return -1; 334} 335 336 337// FormatOption takes a formatting string and interprets it based on 338// the current instructions. The format string points to the first 339// character of the option string (the option escape has already been 340// consumed by the caller.) FormatOption returns the number of 341// characters that were consumed from the formatting string. 342int Decoder::FormatOption(Instruction* instr, const char* format) { 343 switch (format[0]) { 344 case 'c': { // 'code for break or trap instructions. 345 ASSERT(STRING_STARTS_WITH(format, "code")); 346 PrintCode(instr); 347 return 4; 348 } 349 case 'i': { // 'imm16u or 'imm26. 350 if (format[3] == '1') { 351 ASSERT(STRING_STARTS_WITH(format, "imm16")); 352 if (format[5] == 's') { 353 ASSERT(STRING_STARTS_WITH(format, "imm16s")); 354 PrintSImm16(instr); 355 } else if (format[5] == 'u') { 356 ASSERT(STRING_STARTS_WITH(format, "imm16u")); 357 PrintSImm16(instr); 358 } else { 359 ASSERT(STRING_STARTS_WITH(format, "imm16x")); 360 PrintXImm16(instr); 361 } 362 return 6; 363 } else { 364 ASSERT(STRING_STARTS_WITH(format, "imm26x")); 365 PrintXImm26(instr); 366 return 6; 367 } 368 } 369 case 'r': { // 'r: registers. 370 return FormatRegister(instr, format); 371 } 372 case 'f': { // 'f: FPUregisters. 373 return FormatFPURegister(instr, format); 374 } 375 case 's': { // 'sa. 376 switch (format[1]) { 377 case 'a': { 378 ASSERT(STRING_STARTS_WITH(format, "sa")); 379 PrintSa(instr); 380 return 2; 381 } 382 case 'd': { 383 ASSERT(STRING_STARTS_WITH(format, "sd")); 384 PrintSd(instr); 385 return 2; 386 } 387 case 's': { 388 if (format[2] == '1') { 389 ASSERT(STRING_STARTS_WITH(format, "ss1")); /* ext size */ 390 PrintSs1(instr); 391 return 3; 392 } else { 393 ASSERT(STRING_STARTS_WITH(format, "ss2")); /* ins size */ 394 PrintSs2(instr); 395 return 3; 396 } 397 } 398 } 399 } 400 case 'b': { // 'bc - Special for bc1 cc field. 401 ASSERT(STRING_STARTS_WITH(format, "bc")); 402 PrintBc(instr); 403 return 2; 404 } 405 case 'C': { // 'Cc - Special for c.xx.d cc field. 406 ASSERT(STRING_STARTS_WITH(format, "Cc")); 407 PrintCc(instr); 408 return 2; 409 } 410 } 411 UNREACHABLE(); 412 return -1; 413} 414 415 416// Format takes a formatting string for a whole instruction and prints it into 417// the output buffer. All escaped options are handed to FormatOption to be 418// parsed further. 419void Decoder::Format(Instruction* instr, const char* format) { 420 char cur = *format++; 421 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 422 if (cur == '\'') { // Single quote is used as the formatting escape. 423 format += FormatOption(instr, format); 424 } else { 425 out_buffer_[out_buffer_pos_++] = cur; 426 } 427 cur = *format++; 428 } 429 out_buffer_[out_buffer_pos_] = '\0'; 430} 431 432 433// For currently unimplemented decodings the disassembler calls Unknown(instr) 434// which will just print "unknown" of the instruction bits. 435void Decoder::Unknown(Instruction* instr) { 436 Format(instr, "unknown"); 437} 438 439 440void Decoder::DecodeTypeRegister(Instruction* instr) { 441 switch (instr->OpcodeFieldRaw()) { 442 case COP1: // Coprocessor instructions. 443 switch (instr->RsFieldRaw()) { 444 case BC1: // bc1 handled in DecodeTypeImmediate. 445 UNREACHABLE(); 446 break; 447 case MFC1: 448 Format(instr, "mfc1 'rt, 'fs"); 449 break; 450 case MFHC1: 451 Format(instr, "mfhc1 'rt, 'fs"); 452 break; 453 case MTC1: 454 Format(instr, "mtc1 'rt, 'fs"); 455 break; 456 // These are called "fs" too, although they are not FPU registers. 457 case CTC1: 458 Format(instr, "ctc1 'rt, 'fs"); 459 break; 460 case CFC1: 461 Format(instr, "cfc1 'rt, 'fs"); 462 break; 463 case MTHC1: 464 Format(instr, "mthc1 'rt, 'fs"); 465 break; 466 case D: 467 switch (instr->FunctionFieldRaw()) { 468 case ADD_D: 469 Format(instr, "add.d 'fd, 'fs, 'ft"); 470 break; 471 case SUB_D: 472 Format(instr, "sub.d 'fd, 'fs, 'ft"); 473 break; 474 case MUL_D: 475 Format(instr, "mul.d 'fd, 'fs, 'ft"); 476 break; 477 case DIV_D: 478 Format(instr, "div.d 'fd, 'fs, 'ft"); 479 break; 480 case ABS_D: 481 Format(instr, "abs.d 'fd, 'fs"); 482 break; 483 case MOV_D: 484 Format(instr, "mov.d 'fd, 'fs"); 485 break; 486 case NEG_D: 487 Format(instr, "neg.d 'fd, 'fs"); 488 break; 489 case SQRT_D: 490 Format(instr, "sqrt.d 'fd, 'fs"); 491 break; 492 case CVT_W_D: 493 Format(instr, "cvt.w.d 'fd, 'fs"); 494 break; 495 case CVT_L_D: { 496 if (kArchVariant == kMips32r2) { 497 Format(instr, "cvt.l.d 'fd, 'fs"); 498 } else { 499 Unknown(instr); 500 } 501 break; 502 } 503 case TRUNC_W_D: 504 Format(instr, "trunc.w.d 'fd, 'fs"); 505 break; 506 case TRUNC_L_D: { 507 if (kArchVariant == kMips32r2) { 508 Format(instr, "trunc.l.d 'fd, 'fs"); 509 } else { 510 Unknown(instr); 511 } 512 break; 513 } 514 case ROUND_W_D: 515 Format(instr, "round.w.d 'fd, 'fs"); 516 break; 517 case FLOOR_W_D: 518 Format(instr, "floor.w.d 'fd, 'fs"); 519 break; 520 case CEIL_W_D: 521 Format(instr, "ceil.w.d 'fd, 'fs"); 522 break; 523 case CVT_S_D: 524 Format(instr, "cvt.s.d 'fd, 'fs"); 525 break; 526 case C_F_D: 527 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); 528 break; 529 case C_UN_D: 530 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); 531 break; 532 case C_EQ_D: 533 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); 534 break; 535 case C_UEQ_D: 536 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); 537 break; 538 case C_OLT_D: 539 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); 540 break; 541 case C_ULT_D: 542 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); 543 break; 544 case C_OLE_D: 545 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); 546 break; 547 case C_ULE_D: 548 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); 549 break; 550 default: 551 Format(instr, "unknown.cop1.d"); 552 break; 553 } 554 break; 555 case S: 556 UNIMPLEMENTED_MIPS(); 557 break; 558 case W: 559 switch (instr->FunctionFieldRaw()) { 560 case CVT_S_W: // Convert word to float (single). 561 Format(instr, "cvt.s.w 'fd, 'fs"); 562 break; 563 case CVT_D_W: // Convert word to double. 564 Format(instr, "cvt.d.w 'fd, 'fs"); 565 break; 566 default: 567 UNREACHABLE(); 568 } 569 break; 570 case L: 571 switch (instr->FunctionFieldRaw()) { 572 case CVT_D_L: { 573 if (kArchVariant == kMips32r2) { 574 Format(instr, "cvt.d.l 'fd, 'fs"); 575 } else { 576 Unknown(instr); 577 } 578 break; 579 } 580 case CVT_S_L: { 581 if (kArchVariant == kMips32r2) { 582 Format(instr, "cvt.s.l 'fd, 'fs"); 583 } else { 584 Unknown(instr); 585 } 586 break; 587 } 588 default: 589 UNREACHABLE(); 590 } 591 break; 592 case PS: 593 UNIMPLEMENTED_MIPS(); 594 break; 595 default: 596 UNREACHABLE(); 597 } 598 break; 599 case COP1X: 600 switch (instr->FunctionFieldRaw()) { 601 case MADD_D: 602 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); 603 break; 604 default: 605 UNREACHABLE(); 606 } 607 break; 608 case SPECIAL: 609 switch (instr->FunctionFieldRaw()) { 610 case JR: 611 Format(instr, "jr 'rs"); 612 break; 613 case JALR: 614 Format(instr, "jalr 'rs"); 615 break; 616 case SLL: 617 if ( 0x0 == static_cast<int>(instr->InstructionBits())) 618 Format(instr, "nop"); 619 else 620 Format(instr, "sll 'rd, 'rt, 'sa"); 621 break; 622 case SRL: 623 if (instr->RsValue() == 0) { 624 Format(instr, "srl 'rd, 'rt, 'sa"); 625 } else { 626 if (kArchVariant == kMips32r2) { 627 Format(instr, "rotr 'rd, 'rt, 'sa"); 628 } else { 629 Unknown(instr); 630 } 631 } 632 break; 633 case SRA: 634 Format(instr, "sra 'rd, 'rt, 'sa"); 635 break; 636 case SLLV: 637 Format(instr, "sllv 'rd, 'rt, 'rs"); 638 break; 639 case SRLV: 640 if (instr->SaValue() == 0) { 641 Format(instr, "srlv 'rd, 'rt, 'rs"); 642 } else { 643 if (kArchVariant == kMips32r2) { 644 Format(instr, "rotrv 'rd, 'rt, 'rs"); 645 } else { 646 Unknown(instr); 647 } 648 } 649 break; 650 case SRAV: 651 Format(instr, "srav 'rd, 'rt, 'rs"); 652 break; 653 case MFHI: 654 Format(instr, "mfhi 'rd"); 655 break; 656 case MFLO: 657 Format(instr, "mflo 'rd"); 658 break; 659 case MULT: 660 Format(instr, "mult 'rs, 'rt"); 661 break; 662 case MULTU: 663 Format(instr, "multu 'rs, 'rt"); 664 break; 665 case DIV: 666 Format(instr, "div 'rs, 'rt"); 667 break; 668 case DIVU: 669 Format(instr, "divu 'rs, 'rt"); 670 break; 671 case ADD: 672 Format(instr, "add 'rd, 'rs, 'rt"); 673 break; 674 case ADDU: 675 Format(instr, "addu 'rd, 'rs, 'rt"); 676 break; 677 case SUB: 678 Format(instr, "sub 'rd, 'rs, 'rt"); 679 break; 680 case SUBU: 681 Format(instr, "subu 'rd, 'rs, 'rt"); 682 break; 683 case AND: 684 Format(instr, "and 'rd, 'rs, 'rt"); 685 break; 686 case OR: 687 if (0 == instr->RsValue()) { 688 Format(instr, "mov 'rd, 'rt"); 689 } else if (0 == instr->RtValue()) { 690 Format(instr, "mov 'rd, 'rs"); 691 } else { 692 Format(instr, "or 'rd, 'rs, 'rt"); 693 } 694 break; 695 case XOR: 696 Format(instr, "xor 'rd, 'rs, 'rt"); 697 break; 698 case NOR: 699 Format(instr, "nor 'rd, 'rs, 'rt"); 700 break; 701 case SLT: 702 Format(instr, "slt 'rd, 'rs, 'rt"); 703 break; 704 case SLTU: 705 Format(instr, "sltu 'rd, 'rs, 'rt"); 706 break; 707 case BREAK: 708 Format(instr, "break, code: 'code"); 709 break; 710 case TGE: 711 Format(instr, "tge 'rs, 'rt, code: 'code"); 712 break; 713 case TGEU: 714 Format(instr, "tgeu 'rs, 'rt, code: 'code"); 715 break; 716 case TLT: 717 Format(instr, "tlt 'rs, 'rt, code: 'code"); 718 break; 719 case TLTU: 720 Format(instr, "tltu 'rs, 'rt, code: 'code"); 721 break; 722 case TEQ: 723 Format(instr, "teq 'rs, 'rt, code: 'code"); 724 break; 725 case TNE: 726 Format(instr, "tne 'rs, 'rt, code: 'code"); 727 break; 728 case MOVZ: 729 Format(instr, "movz 'rd, 'rs, 'rt"); 730 break; 731 case MOVN: 732 Format(instr, "movn 'rd, 'rs, 'rt"); 733 break; 734 case MOVCI: 735 if (instr->Bit(16)) { 736 Format(instr, "movt 'rd, 'rs, 'bc"); 737 } else { 738 Format(instr, "movf 'rd, 'rs, 'bc"); 739 } 740 break; 741 default: 742 UNREACHABLE(); 743 } 744 break; 745 case SPECIAL2: 746 switch (instr->FunctionFieldRaw()) { 747 case MUL: 748 Format(instr, "mul 'rd, 'rs, 'rt"); 749 break; 750 case CLZ: 751 Format(instr, "clz 'rd, 'rs"); 752 break; 753 default: 754 UNREACHABLE(); 755 } 756 break; 757 case SPECIAL3: 758 switch (instr->FunctionFieldRaw()) { 759 case INS: { 760 if (kArchVariant == kMips32r2) { 761 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); 762 } else { 763 Unknown(instr); 764 } 765 break; 766 } 767 case EXT: { 768 if (kArchVariant == kMips32r2) { 769 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); 770 } else { 771 Unknown(instr); 772 } 773 break; 774 } 775 default: 776 UNREACHABLE(); 777 } 778 break; 779 default: 780 UNREACHABLE(); 781 } 782} 783 784 785void Decoder::DecodeTypeImmediate(Instruction* instr) { 786 switch (instr->OpcodeFieldRaw()) { 787 // ------------- REGIMM class. 788 case COP1: 789 switch (instr->RsFieldRaw()) { 790 case BC1: 791 if (instr->FBtrueValue()) { 792 Format(instr, "bc1t 'bc, 'imm16u"); 793 } else { 794 Format(instr, "bc1f 'bc, 'imm16u"); 795 } 796 break; 797 default: 798 UNREACHABLE(); 799 } 800 break; // Case COP1. 801 case REGIMM: 802 switch (instr->RtFieldRaw()) { 803 case BLTZ: 804 Format(instr, "bltz 'rs, 'imm16u"); 805 break; 806 case BLTZAL: 807 Format(instr, "bltzal 'rs, 'imm16u"); 808 break; 809 case BGEZ: 810 Format(instr, "bgez 'rs, 'imm16u"); 811 break; 812 case BGEZAL: 813 Format(instr, "bgezal 'rs, 'imm16u"); 814 break; 815 default: 816 UNREACHABLE(); 817 } 818 break; // Case REGIMM. 819 // ------------- Branch instructions. 820 case BEQ: 821 Format(instr, "beq 'rs, 'rt, 'imm16u"); 822 break; 823 case BNE: 824 Format(instr, "bne 'rs, 'rt, 'imm16u"); 825 break; 826 case BLEZ: 827 Format(instr, "blez 'rs, 'imm16u"); 828 break; 829 case BGTZ: 830 Format(instr, "bgtz 'rs, 'imm16u"); 831 break; 832 // ------------- Arithmetic instructions. 833 case ADDI: 834 Format(instr, "addi 'rt, 'rs, 'imm16s"); 835 break; 836 case ADDIU: 837 Format(instr, "addiu 'rt, 'rs, 'imm16s"); 838 break; 839 case SLTI: 840 Format(instr, "slti 'rt, 'rs, 'imm16s"); 841 break; 842 case SLTIU: 843 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); 844 break; 845 case ANDI: 846 Format(instr, "andi 'rt, 'rs, 'imm16x"); 847 break; 848 case ORI: 849 Format(instr, "ori 'rt, 'rs, 'imm16x"); 850 break; 851 case XORI: 852 Format(instr, "xori 'rt, 'rs, 'imm16x"); 853 break; 854 case LUI: 855 Format(instr, "lui 'rt, 'imm16x"); 856 break; 857 // ------------- Memory instructions. 858 case LB: 859 Format(instr, "lb 'rt, 'imm16s('rs)"); 860 break; 861 case LH: 862 Format(instr, "lh 'rt, 'imm16s('rs)"); 863 break; 864 case LWL: 865 Format(instr, "lwl 'rt, 'imm16s('rs)"); 866 break; 867 case LW: 868 Format(instr, "lw 'rt, 'imm16s('rs)"); 869 break; 870 case LBU: 871 Format(instr, "lbu 'rt, 'imm16s('rs)"); 872 break; 873 case LHU: 874 Format(instr, "lhu 'rt, 'imm16s('rs)"); 875 break; 876 case LWR: 877 Format(instr, "lwr 'rt, 'imm16s('rs)"); 878 break; 879 case PREF: 880 Format(instr, "pref 'rt, 'imm16s('rs)"); 881 break; 882 case SB: 883 Format(instr, "sb 'rt, 'imm16s('rs)"); 884 break; 885 case SH: 886 Format(instr, "sh 'rt, 'imm16s('rs)"); 887 break; 888 case SWL: 889 Format(instr, "swl 'rt, 'imm16s('rs)"); 890 break; 891 case SW: 892 Format(instr, "sw 'rt, 'imm16s('rs)"); 893 break; 894 case SWR: 895 Format(instr, "swr 'rt, 'imm16s('rs)"); 896 break; 897 case LWC1: 898 Format(instr, "lwc1 'ft, 'imm16s('rs)"); 899 break; 900 case LDC1: 901 Format(instr, "ldc1 'ft, 'imm16s('rs)"); 902 break; 903 case SWC1: 904 Format(instr, "swc1 'ft, 'imm16s('rs)"); 905 break; 906 case SDC1: 907 Format(instr, "sdc1 'ft, 'imm16s('rs)"); 908 break; 909 default: 910 UNREACHABLE(); 911 break; 912 } 913} 914 915 916void Decoder::DecodeTypeJump(Instruction* instr) { 917 switch (instr->OpcodeFieldRaw()) { 918 case J: 919 Format(instr, "j 'imm26x"); 920 break; 921 case JAL: 922 Format(instr, "jal 'imm26x"); 923 break; 924 default: 925 UNREACHABLE(); 926 } 927} 928 929 930// Disassemble the instruction at *instr_ptr into the output buffer. 931int Decoder::InstructionDecode(byte* instr_ptr) { 932 Instruction* instr = Instruction::At(instr_ptr); 933 // Print raw instruction bytes. 934 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 935 "%08x ", 936 instr->InstructionBits()); 937 switch (instr->InstructionType()) { 938 case Instruction::kRegisterType: { 939 DecodeTypeRegister(instr); 940 break; 941 } 942 case Instruction::kImmediateType: { 943 DecodeTypeImmediate(instr); 944 break; 945 } 946 case Instruction::kJumpType: { 947 DecodeTypeJump(instr); 948 break; 949 } 950 default: { 951 Format(instr, "UNSUPPORTED"); 952 UNSUPPORTED_MIPS(); 953 } 954 } 955 return Instruction::kInstrSize; 956} 957 958 959} } // namespace v8::internal 960 961 962 963//------------------------------------------------------------------------------ 964 965namespace disasm { 966 967const char* NameConverter::NameOfAddress(byte* addr) const { 968 v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 969 return tmp_buffer_.start(); 970} 971 972 973const char* NameConverter::NameOfConstant(byte* addr) const { 974 return NameOfAddress(addr); 975} 976 977 978const char* NameConverter::NameOfCPURegister(int reg) const { 979 return v8::internal::Registers::Name(reg); 980} 981 982 983const char* NameConverter::NameOfXMMRegister(int reg) const { 984 return v8::internal::FPURegisters::Name(reg); 985} 986 987 988const char* NameConverter::NameOfByteCPURegister(int reg) const { 989 UNREACHABLE(); // MIPS does not have the concept of a byte register. 990 return "nobytereg"; 991} 992 993 994const char* NameConverter::NameInCode(byte* addr) const { 995 // The default name converter is called for unknown code. So we will not try 996 // to access any memory. 997 return ""; 998} 999 1000 1001//------------------------------------------------------------------------------ 1002 1003Disassembler::Disassembler(const NameConverter& converter) 1004 : converter_(converter) {} 1005 1006 1007Disassembler::~Disassembler() {} 1008 1009 1010int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1011 byte* instruction) { 1012 v8::internal::Decoder d(converter_, buffer); 1013 return d.InstructionDecode(instruction); 1014} 1015 1016 1017// The MIPS assembler does not currently use constant pools. 1018int Disassembler::ConstantPoolSizeAt(byte* instruction) { 1019 return -1; 1020} 1021 1022 1023void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1024 NameConverter converter; 1025 Disassembler d(converter); 1026 for (byte* pc = begin; pc < end;) { 1027 v8::internal::EmbeddedVector<char, 128> buffer; 1028 buffer[0] = '\0'; 1029 byte* prev_pc = pc; 1030 pc += d.InstructionDecode(buffer, pc); 1031 v8::internal::PrintF(f, "%p %08x %s\n", 1032 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1033 } 1034} 1035 1036 1037#undef UNSUPPORTED 1038 1039} // namespace disasm 1040 1041#endif // V8_TARGET_ARCH_MIPS 1042