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 <stdarg.h> 28 #include <stdio.h> 29 #include <string.h> 30 31 #include "src/v8.h" 32 33 #if V8_TARGET_ARCH_MIPS 34 35 #include "src/base/platform/platform.h" 36 #include "src/disasm.h" 37 #include "src/macro-assembler.h" 38 #include "src/mips/constants-mips.h" 39 40 namespace v8 { 41 namespace 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. 48 class 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 PrintXImm21(Instruction* instr); 90 void PrintXImm26(Instruction* instr); 91 void PrintCode(Instruction* instr); // For break and trap instructions. 92 // Printing of instruction name. 93 void PrintInstructionName(Instruction* instr); 94 95 // Handle formatting of instructions and their options. 96 int FormatRegister(Instruction* instr, const char* option); 97 int FormatFPURegister(Instruction* instr, const char* option); 98 int FormatOption(Instruction* instr, const char* option); 99 void Format(Instruction* instr, const char* format); 100 void Unknown(Instruction* instr); 101 102 // Each of these functions decodes one particular instruction type. 103 void DecodeTypeRegister(Instruction* instr); 104 void DecodeTypeImmediate(Instruction* instr); 105 void DecodeTypeJump(Instruction* instr); 106 107 const disasm::NameConverter& converter_; 108 v8::internal::Vector<char> out_buffer_; 109 int out_buffer_pos_; 110 111 DISALLOW_COPY_AND_ASSIGN(Decoder); 112 }; 113 114 115 // Support for assertions in the Decoder formatting functions. 116 #define STRING_STARTS_WITH(string, compare_string) \ 117 (strncmp(string, compare_string, strlen(compare_string)) == 0) 118 119 120 // Append the ch to the output buffer. 121 void Decoder::PrintChar(const char ch) { 122 out_buffer_[out_buffer_pos_++] = ch; 123 } 124 125 126 // Append the str to the output buffer. 127 void Decoder::Print(const char* str) { 128 char cur = *str++; 129 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 130 PrintChar(cur); 131 cur = *str++; 132 } 133 out_buffer_[out_buffer_pos_] = 0; 134 } 135 136 137 // Print the register name according to the active name converter. 138 void Decoder::PrintRegister(int reg) { 139 Print(converter_.NameOfCPURegister(reg)); 140 } 141 142 143 void Decoder::PrintRs(Instruction* instr) { 144 int reg = instr->RsValue(); 145 PrintRegister(reg); 146 } 147 148 149 void Decoder::PrintRt(Instruction* instr) { 150 int reg = instr->RtValue(); 151 PrintRegister(reg); 152 } 153 154 155 void Decoder::PrintRd(Instruction* instr) { 156 int reg = instr->RdValue(); 157 PrintRegister(reg); 158 } 159 160 161 // Print the FPUregister name according to the active name converter. 162 void Decoder::PrintFPURegister(int freg) { 163 Print(converter_.NameOfXMMRegister(freg)); 164 } 165 166 167 void Decoder::PrintFs(Instruction* instr) { 168 int freg = instr->RsValue(); 169 PrintFPURegister(freg); 170 } 171 172 173 void Decoder::PrintFt(Instruction* instr) { 174 int freg = instr->RtValue(); 175 PrintFPURegister(freg); 176 } 177 178 179 void Decoder::PrintFd(Instruction* instr) { 180 int freg = instr->RdValue(); 181 PrintFPURegister(freg); 182 } 183 184 185 // Print the integer value of the sa field. 186 void Decoder::PrintSa(Instruction* instr) { 187 int sa = instr->SaValue(); 188 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa); 189 } 190 191 192 // Print the integer value of the rd field, when it is not used as reg. 193 void Decoder::PrintSd(Instruction* instr) { 194 int sd = instr->RdValue(); 195 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd); 196 } 197 198 199 // Print the integer value of the rd field, when used as 'ext' size. 200 void Decoder::PrintSs1(Instruction* instr) { 201 int ss = instr->RdValue(); 202 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1); 203 } 204 205 206 // Print the integer value of the rd field, when used as 'ins' size. 207 void Decoder::PrintSs2(Instruction* instr) { 208 int ss = instr->RdValue(); 209 int pos = instr->SaValue(); 210 out_buffer_pos_ += 211 SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1); 212 } 213 214 215 // Print the integer value of the cc field for the bc1t/f instructions. 216 void Decoder::PrintBc(Instruction* instr) { 217 int cc = instr->FBccValue(); 218 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc); 219 } 220 221 222 // Print the integer value of the cc field for the FP compare instructions. 223 void Decoder::PrintCc(Instruction* instr) { 224 int cc = instr->FCccValue(); 225 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc); 226 } 227 228 229 // Print 16-bit unsigned immediate value. 230 void Decoder::PrintUImm16(Instruction* instr) { 231 int32_t imm = instr->Imm16Value(); 232 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm); 233 } 234 235 236 // Print 16-bit signed immediate value. 237 void Decoder::PrintSImm16(Instruction* instr) { 238 int32_t imm = ((instr->Imm16Value()) << 16) >> 16; 239 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 240 } 241 242 243 // Print 16-bit hexa immediate value. 244 void Decoder::PrintXImm16(Instruction* instr) { 245 int32_t imm = instr->Imm16Value(); 246 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 247 } 248 249 250 // Print 21-bit immediate value. 251 void Decoder::PrintXImm21(Instruction* instr) { 252 uint32_t imm = instr->Imm21Value(); 253 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 254 } 255 256 257 // Print 26-bit immediate value. 258 void Decoder::PrintXImm26(Instruction* instr) { 259 uint32_t imm = instr->Imm26Value() << kImmFieldShift; 260 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 261 } 262 263 264 // Print 26-bit immediate value. 265 void Decoder::PrintCode(Instruction* instr) { 266 if (instr->OpcodeFieldRaw() != SPECIAL) 267 return; // Not a break or trap instruction. 268 switch (instr->FunctionFieldRaw()) { 269 case BREAK: { 270 int32_t code = instr->Bits(25, 6); 271 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 272 "0x%05x (%d)", code, code); 273 break; 274 } 275 case TGE: 276 case TGEU: 277 case TLT: 278 case TLTU: 279 case TEQ: 280 case TNE: { 281 int32_t code = instr->Bits(15, 6); 282 out_buffer_pos_ += 283 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code); 284 break; 285 } 286 default: // Not a break or trap instruction. 287 break; 288 } 289 } 290 291 292 // Printing of instruction name. 293 void Decoder::PrintInstructionName(Instruction* instr) { 294 } 295 296 297 // Handle all register based formatting in this function to reduce the 298 // complexity of FormatOption. 299 int Decoder::FormatRegister(Instruction* instr, const char* format) { 300 DCHECK(format[0] == 'r'); 301 if (format[1] == 's') { // 'rs: Rs register. 302 int reg = instr->RsValue(); 303 PrintRegister(reg); 304 return 2; 305 } else if (format[1] == 't') { // 'rt: rt register. 306 int reg = instr->RtValue(); 307 PrintRegister(reg); 308 return 2; 309 } else if (format[1] == 'd') { // 'rd: rd register. 310 int reg = instr->RdValue(); 311 PrintRegister(reg); 312 return 2; 313 } 314 UNREACHABLE(); 315 return -1; 316 } 317 318 319 // Handle all FPUregister based formatting in this function to reduce the 320 // complexity of FormatOption. 321 int Decoder::FormatFPURegister(Instruction* instr, const char* format) { 322 DCHECK(format[0] == 'f'); 323 if (format[1] == 's') { // 'fs: fs register. 324 int reg = instr->FsValue(); 325 PrintFPURegister(reg); 326 return 2; 327 } else if (format[1] == 't') { // 'ft: ft register. 328 int reg = instr->FtValue(); 329 PrintFPURegister(reg); 330 return 2; 331 } else if (format[1] == 'd') { // 'fd: fd register. 332 int reg = instr->FdValue(); 333 PrintFPURegister(reg); 334 return 2; 335 } else if (format[1] == 'r') { // 'fr: fr register. 336 int reg = instr->FrValue(); 337 PrintFPURegister(reg); 338 return 2; 339 } 340 UNREACHABLE(); 341 return -1; 342 } 343 344 345 // FormatOption takes a formatting string and interprets it based on 346 // the current instructions. The format string points to the first 347 // character of the option string (the option escape has already been 348 // consumed by the caller.) FormatOption returns the number of 349 // characters that were consumed from the formatting string. 350 int Decoder::FormatOption(Instruction* instr, const char* format) { 351 switch (format[0]) { 352 case 'c': { // 'code for break or trap instructions. 353 DCHECK(STRING_STARTS_WITH(format, "code")); 354 PrintCode(instr); 355 return 4; 356 } 357 case 'i': { // 'imm16u or 'imm26. 358 if (format[3] == '1') { 359 DCHECK(STRING_STARTS_WITH(format, "imm16")); 360 if (format[5] == 's') { 361 DCHECK(STRING_STARTS_WITH(format, "imm16s")); 362 PrintSImm16(instr); 363 } else if (format[5] == 'u') { 364 DCHECK(STRING_STARTS_WITH(format, "imm16u")); 365 PrintSImm16(instr); 366 } else { 367 DCHECK(STRING_STARTS_WITH(format, "imm16x")); 368 PrintXImm16(instr); 369 } 370 return 6; 371 } else if (format[3] == '2' && format[4] == '1') { 372 DCHECK(STRING_STARTS_WITH(format, "imm21x")); 373 PrintXImm21(instr); 374 return 6; 375 } else if (format[3] == '2' && format[4] == '6') { 376 DCHECK(STRING_STARTS_WITH(format, "imm26x")); 377 PrintXImm26(instr); 378 return 6; 379 } 380 } 381 case 'r': { // 'r: registers. 382 return FormatRegister(instr, format); 383 } 384 case 'f': { // 'f: FPUregisters. 385 return FormatFPURegister(instr, format); 386 } 387 case 's': { // 'sa. 388 switch (format[1]) { 389 case 'a': { 390 DCHECK(STRING_STARTS_WITH(format, "sa")); 391 PrintSa(instr); 392 return 2; 393 } 394 case 'd': { 395 DCHECK(STRING_STARTS_WITH(format, "sd")); 396 PrintSd(instr); 397 return 2; 398 } 399 case 's': { 400 if (format[2] == '1') { 401 DCHECK(STRING_STARTS_WITH(format, "ss1")); /* ext size */ 402 PrintSs1(instr); 403 return 3; 404 } else { 405 DCHECK(STRING_STARTS_WITH(format, "ss2")); /* ins size */ 406 PrintSs2(instr); 407 return 3; 408 } 409 } 410 } 411 } 412 case 'b': { // 'bc - Special for bc1 cc field. 413 DCHECK(STRING_STARTS_WITH(format, "bc")); 414 PrintBc(instr); 415 return 2; 416 } 417 case 'C': { // 'Cc - Special for c.xx.d cc field. 418 DCHECK(STRING_STARTS_WITH(format, "Cc")); 419 PrintCc(instr); 420 return 2; 421 } 422 } 423 UNREACHABLE(); 424 return -1; 425 } 426 427 428 // Format takes a formatting string for a whole instruction and prints it into 429 // the output buffer. All escaped options are handed to FormatOption to be 430 // parsed further. 431 void Decoder::Format(Instruction* instr, const char* format) { 432 char cur = *format++; 433 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 434 if (cur == '\'') { // Single quote is used as the formatting escape. 435 format += FormatOption(instr, format); 436 } else { 437 out_buffer_[out_buffer_pos_++] = cur; 438 } 439 cur = *format++; 440 } 441 out_buffer_[out_buffer_pos_] = '\0'; 442 } 443 444 445 // For currently unimplemented decodings the disassembler calls Unknown(instr) 446 // which will just print "unknown" of the instruction bits. 447 void Decoder::Unknown(Instruction* instr) { 448 Format(instr, "unknown"); 449 } 450 451 452 void Decoder::DecodeTypeRegister(Instruction* instr) { 453 switch (instr->OpcodeFieldRaw()) { 454 case COP1: // Coprocessor instructions. 455 switch (instr->RsFieldRaw()) { 456 case BC1: // bc1 handled in DecodeTypeImmediate. 457 UNREACHABLE(); 458 break; 459 case MFC1: 460 Format(instr, "mfc1 'rt, 'fs"); 461 break; 462 case MFHC1: 463 Format(instr, "mfhc1 'rt, 'fs"); 464 break; 465 case MTC1: 466 Format(instr, "mtc1 'rt, 'fs"); 467 break; 468 // These are called "fs" too, although they are not FPU registers. 469 case CTC1: 470 Format(instr, "ctc1 'rt, 'fs"); 471 break; 472 case CFC1: 473 Format(instr, "cfc1 'rt, 'fs"); 474 break; 475 case MTHC1: 476 Format(instr, "mthc1 'rt, 'fs"); 477 break; 478 case D: 479 switch (instr->FunctionFieldRaw()) { 480 case ADD_D: 481 Format(instr, "add.d 'fd, 'fs, 'ft"); 482 break; 483 case SUB_D: 484 Format(instr, "sub.d 'fd, 'fs, 'ft"); 485 break; 486 case MUL_D: 487 Format(instr, "mul.d 'fd, 'fs, 'ft"); 488 break; 489 case DIV_D: 490 Format(instr, "div.d 'fd, 'fs, 'ft"); 491 break; 492 case ABS_D: 493 Format(instr, "abs.d 'fd, 'fs"); 494 break; 495 case MOV_D: 496 Format(instr, "mov.d 'fd, 'fs"); 497 break; 498 case NEG_D: 499 Format(instr, "neg.d 'fd, 'fs"); 500 break; 501 case SQRT_D: 502 Format(instr, "sqrt.d 'fd, 'fs"); 503 break; 504 case CVT_W_D: 505 Format(instr, "cvt.w.d 'fd, 'fs"); 506 break; 507 case CVT_L_D: 508 Format(instr, "cvt.l.d 'fd, 'fs"); 509 break; 510 case TRUNC_W_D: 511 Format(instr, "trunc.w.d 'fd, 'fs"); 512 break; 513 case TRUNC_L_D: 514 Format(instr, "trunc.l.d 'fd, 'fs"); 515 break; 516 case ROUND_W_D: 517 Format(instr, "round.w.d 'fd, 'fs"); 518 break; 519 case FLOOR_W_D: 520 Format(instr, "floor.w.d 'fd, 'fs"); 521 break; 522 case CEIL_W_D: 523 Format(instr, "ceil.w.d 'fd, 'fs"); 524 break; 525 case CVT_S_D: 526 Format(instr, "cvt.s.d 'fd, 'fs"); 527 break; 528 case C_F_D: 529 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); 530 break; 531 case C_UN_D: 532 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); 533 break; 534 case C_EQ_D: 535 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); 536 break; 537 case C_UEQ_D: 538 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); 539 break; 540 case C_OLT_D: 541 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); 542 break; 543 case C_ULT_D: 544 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); 545 break; 546 case C_OLE_D: 547 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); 548 break; 549 case C_ULE_D: 550 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); 551 break; 552 default: 553 Format(instr, "unknown.cop1.d"); 554 break; 555 } 556 break; 557 case S: 558 UNIMPLEMENTED_MIPS(); 559 break; 560 case W: 561 switch (instr->FunctionFieldRaw()) { 562 case CVT_S_W: // Convert word to float (single). 563 Format(instr, "cvt.s.w 'fd, 'fs"); 564 break; 565 case CVT_D_W: // Convert word to double. 566 Format(instr, "cvt.d.w 'fd, 'fs"); 567 break; 568 default: 569 UNREACHABLE(); 570 } 571 break; 572 case L: 573 switch (instr->FunctionFieldRaw()) { 574 case CVT_D_L: 575 Format(instr, "cvt.d.l 'fd, 'fs"); 576 break; 577 case CVT_S_L: 578 Format(instr, "cvt.s.l 'fd, 'fs"); 579 break; 580 case CMP_UN: 581 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); 582 break; 583 case CMP_EQ: 584 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); 585 break; 586 case CMP_UEQ: 587 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); 588 break; 589 case CMP_LT: 590 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); 591 break; 592 case CMP_ULT: 593 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); 594 break; 595 case CMP_LE: 596 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); 597 break; 598 case CMP_ULE: 599 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); 600 break; 601 case CMP_OR: 602 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); 603 break; 604 case CMP_UNE: 605 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); 606 break; 607 case CMP_NE: 608 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); 609 break; 610 default: 611 UNREACHABLE(); 612 } 613 break; 614 case PS: 615 UNIMPLEMENTED_MIPS(); 616 break; 617 default: 618 UNREACHABLE(); 619 } 620 break; 621 case COP1X: 622 switch (instr->FunctionFieldRaw()) { 623 case MADD_D: 624 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); 625 break; 626 default: 627 UNREACHABLE(); 628 } 629 break; 630 case SPECIAL: 631 switch (instr->FunctionFieldRaw()) { 632 case JR: 633 Format(instr, "jr 'rs"); 634 break; 635 case JALR: 636 Format(instr, "jalr 'rs"); 637 break; 638 case SLL: 639 if ( 0x0 == static_cast<int>(instr->InstructionBits())) 640 Format(instr, "nop"); 641 else 642 Format(instr, "sll 'rd, 'rt, 'sa"); 643 break; 644 case SRL: 645 if (instr->RsValue() == 0) { 646 Format(instr, "srl 'rd, 'rt, 'sa"); 647 } else { 648 if (IsMipsArchVariant(kMips32r2)) { 649 Format(instr, "rotr 'rd, 'rt, 'sa"); 650 } else { 651 Unknown(instr); 652 } 653 } 654 break; 655 case SRA: 656 Format(instr, "sra 'rd, 'rt, 'sa"); 657 break; 658 case SLLV: 659 Format(instr, "sllv 'rd, 'rt, 'rs"); 660 break; 661 case SRLV: 662 if (instr->SaValue() == 0) { 663 Format(instr, "srlv 'rd, 'rt, 'rs"); 664 } else { 665 if (IsMipsArchVariant(kMips32r2)) { 666 Format(instr, "rotrv 'rd, 'rt, 'rs"); 667 } else { 668 Unknown(instr); 669 } 670 } 671 break; 672 case SRAV: 673 Format(instr, "srav 'rd, 'rt, 'rs"); 674 break; 675 case MFHI: 676 if (instr->Bits(25, 16) == 0) { 677 Format(instr, "mfhi 'rd"); 678 } else { 679 if ((instr->FunctionFieldRaw() == CLZ_R6) 680 && (instr->FdValue() == 1)) { 681 Format(instr, "clz 'rd, 'rs"); 682 } else if ((instr->FunctionFieldRaw() == CLO_R6) 683 && (instr->FdValue() == 1)) { 684 Format(instr, "clo 'rd, 'rs"); 685 } 686 } 687 break; 688 case MFLO: 689 Format(instr, "mflo 'rd"); 690 break; 691 case MULT: // @Mips32r6 == MUL_MUH. 692 if (!IsMipsArchVariant(kMips32r6)) { 693 Format(instr, "mult 'rs, 'rt"); 694 } else { 695 if (instr->SaValue() == MUL_OP) { 696 Format(instr, "mul 'rd, 'rs, 'rt"); 697 } else { 698 Format(instr, "muh 'rd, 'rs, 'rt"); 699 } 700 } 701 break; 702 case MULTU: // @Mips32r6 == MUL_MUH_U. 703 if (!IsMipsArchVariant(kMips32r6)) { 704 Format(instr, "multu 'rs, 'rt"); 705 } else { 706 if (instr->SaValue() == MUL_OP) { 707 Format(instr, "mulu 'rd, 'rs, 'rt"); 708 } else { 709 Format(instr, "muhu 'rd, 'rs, 'rt"); 710 } 711 } 712 break; 713 case DIV: // @Mips32r6 == DIV_MOD. 714 if (!IsMipsArchVariant(kMips32r6)) { 715 Format(instr, "div 'rs, 'rt"); 716 } else { 717 if (instr->SaValue() == DIV_OP) { 718 Format(instr, "div 'rd, 'rs, 'rt"); 719 } else { 720 Format(instr, "mod 'rd, 'rs, 'rt"); 721 } 722 } 723 break; 724 case DIVU: // @Mips32r6 == DIV_MOD_U. 725 if (!IsMipsArchVariant(kMips32r6)) { 726 Format(instr, "divu 'rs, 'rt"); 727 } else { 728 if (instr->SaValue() == DIV_OP) { 729 Format(instr, "divu 'rd, 'rs, 'rt"); 730 } else { 731 Format(instr, "modu 'rd, 'rs, 'rt"); 732 } 733 } 734 break; 735 case ADD: 736 Format(instr, "add 'rd, 'rs, 'rt"); 737 break; 738 case ADDU: 739 Format(instr, "addu 'rd, 'rs, 'rt"); 740 break; 741 case SUB: 742 Format(instr, "sub 'rd, 'rs, 'rt"); 743 break; 744 case SUBU: 745 Format(instr, "subu 'rd, 'rs, 'rt"); 746 break; 747 case AND: 748 Format(instr, "and 'rd, 'rs, 'rt"); 749 break; 750 case OR: 751 if (0 == instr->RsValue()) { 752 Format(instr, "mov 'rd, 'rt"); 753 } else if (0 == instr->RtValue()) { 754 Format(instr, "mov 'rd, 'rs"); 755 } else { 756 Format(instr, "or 'rd, 'rs, 'rt"); 757 } 758 break; 759 case XOR: 760 Format(instr, "xor 'rd, 'rs, 'rt"); 761 break; 762 case NOR: 763 Format(instr, "nor 'rd, 'rs, 'rt"); 764 break; 765 case SLT: 766 Format(instr, "slt 'rd, 'rs, 'rt"); 767 break; 768 case SLTU: 769 Format(instr, "sltu 'rd, 'rs, 'rt"); 770 break; 771 case BREAK: 772 Format(instr, "break, code: 'code"); 773 break; 774 case TGE: 775 Format(instr, "tge 'rs, 'rt, code: 'code"); 776 break; 777 case TGEU: 778 Format(instr, "tgeu 'rs, 'rt, code: 'code"); 779 break; 780 case TLT: 781 Format(instr, "tlt 'rs, 'rt, code: 'code"); 782 break; 783 case TLTU: 784 Format(instr, "tltu 'rs, 'rt, code: 'code"); 785 break; 786 case TEQ: 787 Format(instr, "teq 'rs, 'rt, code: 'code"); 788 break; 789 case TNE: 790 Format(instr, "tne 'rs, 'rt, code: 'code"); 791 break; 792 case MOVZ: 793 Format(instr, "movz 'rd, 'rs, 'rt"); 794 break; 795 case MOVN: 796 Format(instr, "movn 'rd, 'rs, 'rt"); 797 break; 798 case MOVCI: 799 if (instr->Bit(16)) { 800 Format(instr, "movt 'rd, 'rs, 'bc"); 801 } else { 802 Format(instr, "movf 'rd, 'rs, 'bc"); 803 } 804 break; 805 case SELEQZ_S: 806 Format(instr, "seleqz 'rd, 'rs, 'rt"); 807 break; 808 case SELNEZ_S: 809 Format(instr, "selnez 'rd, 'rs, 'rt"); 810 break; 811 default: 812 UNREACHABLE(); 813 } 814 break; 815 case SPECIAL2: 816 switch (instr->FunctionFieldRaw()) { 817 case MUL: 818 Format(instr, "mul 'rd, 'rs, 'rt"); 819 break; 820 case CLZ: 821 if (!IsMipsArchVariant(kMips32r6)) { 822 Format(instr, "clz 'rd, 'rs"); 823 } 824 break; 825 default: 826 UNREACHABLE(); 827 } 828 break; 829 case SPECIAL3: 830 switch (instr->FunctionFieldRaw()) { 831 case INS: { 832 if (IsMipsArchVariant(kMips32r2)) { 833 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); 834 } else { 835 Unknown(instr); 836 } 837 break; 838 } 839 case EXT: { 840 if (IsMipsArchVariant(kMips32r2)) { 841 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); 842 } else { 843 Unknown(instr); 844 } 845 break; 846 } 847 default: 848 UNREACHABLE(); 849 } 850 break; 851 default: 852 UNREACHABLE(); 853 } 854 } 855 856 857 void Decoder::DecodeTypeImmediate(Instruction* instr) { 858 switch (instr->OpcodeFieldRaw()) { 859 case COP1: 860 switch (instr->RsFieldRaw()) { 861 case BC1: 862 if (instr->FBtrueValue()) { 863 Format(instr, "bc1t 'bc, 'imm16u"); 864 } else { 865 Format(instr, "bc1f 'bc, 'imm16u"); 866 } 867 break; 868 case BC1EQZ: 869 Format(instr, "bc1eqz 'ft, 'imm16u"); 870 break; 871 case BC1NEZ: 872 Format(instr, "bc1nez 'ft, 'imm16u"); 873 break; 874 case W: // CMP.S instruction. 875 switch (instr->FunctionValue()) { 876 case CMP_AF: 877 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); 878 break; 879 case CMP_UN: 880 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); 881 break; 882 case CMP_EQ: 883 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); 884 break; 885 case CMP_UEQ: 886 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); 887 break; 888 case CMP_LT: 889 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); 890 break; 891 case CMP_ULT: 892 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); 893 break; 894 case CMP_LE: 895 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); 896 break; 897 case CMP_ULE: 898 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); 899 break; 900 case CMP_OR: 901 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); 902 break; 903 case CMP_UNE: 904 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); 905 break; 906 case CMP_NE: 907 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); 908 break; 909 default: 910 UNREACHABLE(); 911 } 912 break; 913 case L: // CMP.D instruction. 914 switch (instr->FunctionValue()) { 915 case CMP_AF: 916 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); 917 break; 918 case CMP_UN: 919 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); 920 break; 921 case CMP_EQ: 922 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); 923 break; 924 case CMP_UEQ: 925 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); 926 break; 927 case CMP_LT: 928 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); 929 break; 930 case CMP_ULT: 931 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); 932 break; 933 case CMP_LE: 934 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); 935 break; 936 case CMP_ULE: 937 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); 938 break; 939 case CMP_OR: 940 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); 941 break; 942 case CMP_UNE: 943 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); 944 break; 945 case CMP_NE: 946 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); 947 break; 948 default: 949 UNREACHABLE(); 950 } 951 break; 952 case S: 953 switch (instr->FunctionValue()) { 954 case SEL: 955 Format(instr, "sel.S 'ft, 'fs, 'fd"); 956 break; 957 case SELEQZ_C: 958 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); 959 break; 960 case SELNEZ_C: 961 Format(instr, "selnez.S 'ft, 'fs, 'fd"); 962 break; 963 case MIN: 964 Format(instr, "min.S 'ft, 'fs, 'fd"); 965 break; 966 case MINA: 967 Format(instr, "mina.S 'ft, 'fs, 'fd"); 968 break; 969 case MAX: 970 Format(instr, "max.S 'ft, 'fs, 'fd"); 971 break; 972 case MAXA: 973 Format(instr, "maxa.S 'ft, 'fs, 'fd"); 974 break; 975 default: 976 UNREACHABLE(); 977 } 978 break; 979 case D: 980 switch (instr->FunctionValue()) { 981 case SEL: 982 Format(instr, "sel.D 'ft, 'fs, 'fd"); 983 break; 984 case SELEQZ_C: 985 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); 986 break; 987 case SELNEZ_C: 988 Format(instr, "selnez.D 'ft, 'fs, 'fd"); 989 break; 990 case MIN: 991 Format(instr, "min.D 'ft, 'fs, 'fd"); 992 break; 993 case MINA: 994 Format(instr, "mina.D 'ft, 'fs, 'fd"); 995 break; 996 case MAX: 997 Format(instr, "max.D 'ft, 'fs, 'fd"); 998 break; 999 case MAXA: 1000 Format(instr, "maxa.D 'ft, 'fs, 'fd"); 1001 break; 1002 default: 1003 UNREACHABLE(); 1004 } 1005 break; 1006 default: 1007 UNREACHABLE(); 1008 } 1009 1010 break; // Case COP1. 1011 // ------------- REGIMM class. 1012 case REGIMM: 1013 switch (instr->RtFieldRaw()) { 1014 case BLTZ: 1015 Format(instr, "bltz 'rs, 'imm16u"); 1016 break; 1017 case BLTZAL: 1018 Format(instr, "bltzal 'rs, 'imm16u"); 1019 break; 1020 case BGEZ: 1021 Format(instr, "bgez 'rs, 'imm16u"); 1022 break; 1023 case BGEZAL: 1024 Format(instr, "bgezal 'rs, 'imm16u"); 1025 break; 1026 case BGEZALL: 1027 Format(instr, "bgezall 'rs, 'imm16u"); 1028 break; 1029 default: 1030 UNREACHABLE(); 1031 } 1032 break; // Case REGIMM. 1033 // ------------- Branch instructions. 1034 case BEQ: 1035 Format(instr, "beq 'rs, 'rt, 'imm16u"); 1036 break; 1037 case BNE: 1038 Format(instr, "bne 'rs, 'rt, 'imm16u"); 1039 break; 1040 case BLEZ: 1041 if ((instr->RtFieldRaw() == 0) 1042 && (instr->RsFieldRaw() != 0)) { 1043 Format(instr, "blez 'rs, 'imm16u"); 1044 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) 1045 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { 1046 Format(instr, "bgeuc 'rs, 'rt, 'imm16u"); 1047 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) 1048 && (instr->RtFieldRaw() != 0)) { 1049 Format(instr, "bgezalc 'rs, 'imm16u"); 1050 } else if ((instr->RsFieldRaw() == 0) 1051 && (instr->RtFieldRaw() != 0)) { 1052 Format(instr, "blezalc 'rs, 'imm16u"); 1053 } else { 1054 UNREACHABLE(); 1055 } 1056 break; 1057 case BGTZ: 1058 if ((instr->RtFieldRaw() == 0) 1059 && (instr->RsFieldRaw() != 0)) { 1060 Format(instr, "bgtz 'rs, 'imm16u"); 1061 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) 1062 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { 1063 Format(instr, "bltuc 'rs, 'rt, 'imm16u"); 1064 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) 1065 && (instr->RtFieldRaw() != 0)) { 1066 Format(instr, "bltzalc 'rt, 'imm16u"); 1067 } else if ((instr->RsFieldRaw() == 0) 1068 && (instr->RtFieldRaw() != 0)) { 1069 Format(instr, "bgtzalc 'rt, 'imm16u"); 1070 } else { 1071 UNREACHABLE(); 1072 } 1073 break; 1074 case BLEZL: 1075 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) 1076 && (instr->RtFieldRaw() != 0)) { 1077 Format(instr, "bgezc 'rt, 'imm16u"); 1078 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) 1079 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { 1080 Format(instr, "bgec 'rs, 'rt, 'imm16u"); 1081 } else if ((instr->RsFieldRaw() == 0) 1082 && (instr->RtFieldRaw() != 0)) { 1083 Format(instr, "blezc 'rt, 'imm16u"); 1084 } else { 1085 UNREACHABLE(); 1086 } 1087 break; 1088 case BGTZL: 1089 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) 1090 && (instr->RtFieldRaw() != 0)) { 1091 Format(instr, "bltzc 'rt, 'imm16u"); 1092 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) 1093 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { 1094 Format(instr, "bltc 'rs, 'rt, 'imm16u"); 1095 } else if ((instr->RsFieldRaw() == 0) 1096 && (instr->RtFieldRaw() != 0)) { 1097 Format(instr, "bgtzc 'rt, 'imm16u"); 1098 } else { 1099 UNREACHABLE(); 1100 } 1101 break; 1102 case BEQZC: 1103 if (instr->RsFieldRaw() != 0) { 1104 Format(instr, "beqzc 'rs, 'imm21x"); 1105 } 1106 break; 1107 case BNEZC: 1108 if (instr->RsFieldRaw() != 0) { 1109 Format(instr, "bnezc 'rs, 'imm21x"); 1110 } 1111 break; 1112 // ------------- Arithmetic instructions. 1113 case ADDI: 1114 if (!IsMipsArchVariant(kMips32r6)) { 1115 Format(instr, "addi 'rt, 'rs, 'imm16s"); 1116 } else { 1117 // Check if BOVC or BEQC instruction. 1118 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { 1119 Format(instr, "bovc 'rs, 'rt, 'imm16s"); 1120 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { 1121 Format(instr, "beqc 'rs, 'rt, 'imm16s"); 1122 } else { 1123 UNREACHABLE(); 1124 } 1125 } 1126 break; 1127 case DADDI: 1128 if (IsMipsArchVariant(kMips32r6)) { 1129 // Check if BNVC or BNEC instruction. 1130 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { 1131 Format(instr, "bnvc 'rs, 'rt, 'imm16s"); 1132 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { 1133 Format(instr, "bnec 'rs, 'rt, 'imm16s"); 1134 } else { 1135 UNREACHABLE(); 1136 } 1137 } 1138 break; 1139 case ADDIU: 1140 Format(instr, "addiu 'rt, 'rs, 'imm16s"); 1141 break; 1142 case SLTI: 1143 Format(instr, "slti 'rt, 'rs, 'imm16s"); 1144 break; 1145 case SLTIU: 1146 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); 1147 break; 1148 case ANDI: 1149 Format(instr, "andi 'rt, 'rs, 'imm16x"); 1150 break; 1151 case ORI: 1152 Format(instr, "ori 'rt, 'rs, 'imm16x"); 1153 break; 1154 case XORI: 1155 Format(instr, "xori 'rt, 'rs, 'imm16x"); 1156 break; 1157 case LUI: 1158 if (!IsMipsArchVariant(kMips32r6)) { 1159 Format(instr, "lui 'rt, 'imm16x"); 1160 } else { 1161 if (instr->RsValue() != 0) { 1162 Format(instr, "aui 'rt, 'imm16x"); 1163 } else { 1164 Format(instr, "lui 'rt, 'imm16x"); 1165 } 1166 } 1167 break; 1168 // ------------- Memory instructions. 1169 case LB: 1170 Format(instr, "lb 'rt, 'imm16s('rs)"); 1171 break; 1172 case LH: 1173 Format(instr, "lh 'rt, 'imm16s('rs)"); 1174 break; 1175 case LWL: 1176 Format(instr, "lwl 'rt, 'imm16s('rs)"); 1177 break; 1178 case LW: 1179 Format(instr, "lw 'rt, 'imm16s('rs)"); 1180 break; 1181 case LBU: 1182 Format(instr, "lbu 'rt, 'imm16s('rs)"); 1183 break; 1184 case LHU: 1185 Format(instr, "lhu 'rt, 'imm16s('rs)"); 1186 break; 1187 case LWR: 1188 Format(instr, "lwr 'rt, 'imm16s('rs)"); 1189 break; 1190 case PREF: 1191 Format(instr, "pref 'rt, 'imm16s('rs)"); 1192 break; 1193 case SB: 1194 Format(instr, "sb 'rt, 'imm16s('rs)"); 1195 break; 1196 case SH: 1197 Format(instr, "sh 'rt, 'imm16s('rs)"); 1198 break; 1199 case SWL: 1200 Format(instr, "swl 'rt, 'imm16s('rs)"); 1201 break; 1202 case SW: 1203 Format(instr, "sw 'rt, 'imm16s('rs)"); 1204 break; 1205 case SWR: 1206 Format(instr, "swr 'rt, 'imm16s('rs)"); 1207 break; 1208 case LWC1: 1209 Format(instr, "lwc1 'ft, 'imm16s('rs)"); 1210 break; 1211 case LDC1: 1212 Format(instr, "ldc1 'ft, 'imm16s('rs)"); 1213 break; 1214 case SWC1: 1215 Format(instr, "swc1 'ft, 'imm16s('rs)"); 1216 break; 1217 case SDC1: 1218 Format(instr, "sdc1 'ft, 'imm16s('rs)"); 1219 break; 1220 default: 1221 printf("a 0x%x \n", instr->OpcodeFieldRaw()); 1222 UNREACHABLE(); 1223 break; 1224 } 1225 } 1226 1227 1228 void Decoder::DecodeTypeJump(Instruction* instr) { 1229 switch (instr->OpcodeFieldRaw()) { 1230 case J: 1231 Format(instr, "j 'imm26x"); 1232 break; 1233 case JAL: 1234 Format(instr, "jal 'imm26x"); 1235 break; 1236 default: 1237 UNREACHABLE(); 1238 } 1239 } 1240 1241 1242 // Disassemble the instruction at *instr_ptr into the output buffer. 1243 int Decoder::InstructionDecode(byte* instr_ptr) { 1244 Instruction* instr = Instruction::At(instr_ptr); 1245 // Print raw instruction bytes. 1246 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, 1247 "%08x ", 1248 instr->InstructionBits()); 1249 switch (instr->InstructionType()) { 1250 case Instruction::kRegisterType: { 1251 DecodeTypeRegister(instr); 1252 break; 1253 } 1254 case Instruction::kImmediateType: { 1255 DecodeTypeImmediate(instr); 1256 break; 1257 } 1258 case Instruction::kJumpType: { 1259 DecodeTypeJump(instr); 1260 break; 1261 } 1262 default: { 1263 Format(instr, "UNSUPPORTED"); 1264 UNSUPPORTED_MIPS(); 1265 } 1266 } 1267 return Instruction::kInstrSize; 1268 } 1269 1270 1271 } } // namespace v8::internal 1272 1273 1274 1275 //------------------------------------------------------------------------------ 1276 1277 namespace disasm { 1278 1279 const char* NameConverter::NameOfAddress(byte* addr) const { 1280 v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 1281 return tmp_buffer_.start(); 1282 } 1283 1284 1285 const char* NameConverter::NameOfConstant(byte* addr) const { 1286 return NameOfAddress(addr); 1287 } 1288 1289 1290 const char* NameConverter::NameOfCPURegister(int reg) const { 1291 return v8::internal::Registers::Name(reg); 1292 } 1293 1294 1295 const char* NameConverter::NameOfXMMRegister(int reg) const { 1296 return v8::internal::FPURegisters::Name(reg); 1297 } 1298 1299 1300 const char* NameConverter::NameOfByteCPURegister(int reg) const { 1301 UNREACHABLE(); // MIPS does not have the concept of a byte register. 1302 return "nobytereg"; 1303 } 1304 1305 1306 const char* NameConverter::NameInCode(byte* addr) const { 1307 // The default name converter is called for unknown code. So we will not try 1308 // to access any memory. 1309 return ""; 1310 } 1311 1312 1313 //------------------------------------------------------------------------------ 1314 1315 Disassembler::Disassembler(const NameConverter& converter) 1316 : converter_(converter) {} 1317 1318 1319 Disassembler::~Disassembler() {} 1320 1321 1322 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 1323 byte* instruction) { 1324 v8::internal::Decoder d(converter_, buffer); 1325 return d.InstructionDecode(instruction); 1326 } 1327 1328 1329 // The MIPS assembler does not currently use constant pools. 1330 int Disassembler::ConstantPoolSizeAt(byte* instruction) { 1331 return -1; 1332 } 1333 1334 1335 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 1336 NameConverter converter; 1337 Disassembler d(converter); 1338 for (byte* pc = begin; pc < end;) { 1339 v8::internal::EmbeddedVector<char, 128> buffer; 1340 buffer[0] = '\0'; 1341 byte* prev_pc = pc; 1342 pc += d.InstructionDecode(buffer, pc); 1343 v8::internal::PrintF(f, "%p %08x %s\n", 1344 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1345 } 1346 } 1347 1348 1349 #undef UNSUPPORTED 1350 1351 } // namespace disasm 1352 1353 #endif // V8_TARGET_ARCH_MIPS 1354