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