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 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 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. 121void Decoder::PrintChar(const char ch) { 122 out_buffer_[out_buffer_pos_++] = ch; 123} 124 125 126// Append the str to the output buffer. 127void 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. 138void Decoder::PrintRegister(int reg) { 139 Print(converter_.NameOfCPURegister(reg)); 140} 141 142 143void Decoder::PrintRs(Instruction* instr) { 144 int reg = instr->RsValue(); 145 PrintRegister(reg); 146} 147 148 149void Decoder::PrintRt(Instruction* instr) { 150 int reg = instr->RtValue(); 151 PrintRegister(reg); 152} 153 154 155void 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. 162void Decoder::PrintFPURegister(int freg) { 163 Print(converter_.NameOfXMMRegister(freg)); 164} 165 166 167void Decoder::PrintFs(Instruction* instr) { 168 int freg = instr->RsValue(); 169 PrintFPURegister(freg); 170} 171 172 173void Decoder::PrintFt(Instruction* instr) { 174 int freg = instr->RtValue(); 175 PrintFPURegister(freg); 176} 177 178 179void Decoder::PrintFd(Instruction* instr) { 180 int freg = instr->RdValue(); 181 PrintFPURegister(freg); 182} 183 184 185// Print the integer value of the sa field. 186void 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. 193void 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. 200void 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. 207void 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. 216void 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. 223void 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. 230void 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. 237void 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. 244void 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. 251void 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. 258void 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. 265void 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. 293void Decoder::PrintInstructionName(Instruction* instr) { 294} 295 296 297// Handle all register based formatting in this function to reduce the 298// complexity of FormatOption. 299int 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. 321int 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. 350int 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. 431void 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. 447void Decoder::Unknown(Instruction* instr) { 448 Format(instr, "unknown"); 449} 450 451 452void 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 857void 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 1228void 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. 1243int 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 1277namespace disasm { 1278 1279const char* NameConverter::NameOfAddress(byte* addr) const { 1280 v8::internal::SNPrintF(tmp_buffer_, "%p", addr); 1281 return tmp_buffer_.start(); 1282} 1283 1284 1285const char* NameConverter::NameOfConstant(byte* addr) const { 1286 return NameOfAddress(addr); 1287} 1288 1289 1290const char* NameConverter::NameOfCPURegister(int reg) const { 1291 return v8::internal::Registers::Name(reg); 1292} 1293 1294 1295const char* NameConverter::NameOfXMMRegister(int reg) const { 1296 return v8::internal::FPURegisters::Name(reg); 1297} 1298 1299 1300const char* NameConverter::NameOfByteCPURegister(int reg) const { 1301 UNREACHABLE(); // MIPS does not have the concept of a byte register. 1302 return "nobytereg"; 1303} 1304 1305 1306const 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 1315Disassembler::Disassembler(const NameConverter& converter) 1316 : converter_(converter) {} 1317 1318 1319Disassembler::~Disassembler() {} 1320 1321 1322int 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. 1330int Disassembler::ConstantPoolSizeAt(byte* instruction) { 1331 return -1; 1332} 1333 1334 1335void 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