Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===// | 1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | 218 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); |
| 219 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | 219 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
| 220 | 220 |
| 221 Opcode |= Rs << 21; | 221 Opcode |= Rs << 21; |
| 222 Opcode |= Rt << 16; | 222 Opcode |= Rt << 16; |
| 223 Opcode |= Imm & 0xffff; | 223 Opcode |= Imm & 0xffff; |
| 224 | 224 |
| 225 emitInst(Opcode); | 225 emitInst(Opcode); |
| 226 } | 226 } |
| 227 | 227 |
| 228 void AssemblerMIPS32::emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt, | |
| 229 const Operand *OpRs, | |
| 230 const Operand *OpImm, | |
| 231 const RelocOp Reloc, | |
| 232 const char *InsnName) { | |
| 233 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); | |
| 234 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | |
| 235 uint32_t Imm16 = 0; | |
| 236 | |
| 237 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) { | |
| 238 emitFixup(createMIPS32Fixup(Reloc, OpRel)); | |
| 239 } else { | |
|
Jim Stichnoth
2016/10/27 13:58:15
else if ( ... ) ...
I think that pattern is easie
jaydeep.patil
2016/10/28 02:53:57
Done.
| |
| 240 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) { | |
| 241 Imm16 = C32->getValue(); | |
| 242 } else { | |
| 243 llvm::report_fatal_error(std::string(InsnName) + ": Invalid 3rd operand"); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 Opcode |= Rs << 21; | |
| 248 Opcode |= Rt << 16; | |
| 249 Opcode |= Imm16 & 0xffff; | |
| 250 | |
| 251 emitInst(Opcode); | |
| 252 } | |
| 253 | |
| 228 void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt, | 254 void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt, |
| 229 const Operand *OpRs, const uint32_t Imm, | 255 const Operand *OpRs, const uint32_t Imm, |
| 230 const char *InsnName) { | 256 const char *InsnName) { |
| 231 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); | 257 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); |
| 232 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); | 258 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); |
| 233 | 259 |
| 234 Opcode |= Rs << 21; | 260 Opcode |= Rs << 21; |
| 235 Opcode |= Ft << 16; | 261 Opcode |= Ft << 16; |
| 236 Opcode |= Imm & 0xffff; | 262 Opcode |= Imm & 0xffff; |
| 237 | 263 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) { | 366 void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) { |
| 341 static constexpr IValueT Opcode = 0x44000005; | 367 static constexpr IValueT Opcode = 0x44000005; |
| 342 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d"); | 368 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d"); |
| 343 } | 369 } |
| 344 | 370 |
| 345 void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) { | 371 void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) { |
| 346 static constexpr IValueT Opcode = 0x44000005; | 372 static constexpr IValueT Opcode = 0x44000005; |
| 347 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s"); | 373 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s"); |
| 348 } | 374 } |
| 349 | 375 |
| 376 void AssemblerMIPS32::addi(const Operand *OpRt, const Operand *OpRs, | |
| 377 const uint32_t Imm) { | |
| 378 static constexpr IValueT Opcode = 0x20000000; | |
| 379 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addi"); | |
| 380 } | |
| 381 | |
| 350 void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs, | 382 void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs, |
| 351 const Operand *OpFt) { | 383 const Operand *OpFt) { |
| 352 static constexpr IValueT Opcode = 0x44000000; | 384 static constexpr IValueT Opcode = 0x44000000; |
| 353 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d"); | 385 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d"); |
| 354 } | 386 } |
| 355 | 387 |
| 356 void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs, | 388 void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs, |
| 357 const Operand *OpFt) { | 389 const Operand *OpFt) { |
| 358 static constexpr IValueT Opcode = 0x44000000; | 390 static constexpr IValueT Opcode = 0x44000000; |
| 359 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s"); | 391 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s"); |
| 360 } | 392 } |
| 361 | 393 |
| 362 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, | 394 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, |
| 363 const uint32_t Imm) { | 395 const uint32_t Imm) { |
| 364 static constexpr IValueT Opcode = 0x24000000; | 396 static constexpr IValueT Opcode = 0x24000000; |
| 365 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); | 397 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); |
| 366 } | 398 } |
| 367 | 399 |
| 400 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, | |
| 401 const Operand *OpImm, const RelocOp Reloc) { | |
| 402 static constexpr IValueT Opcode = 0x24000000; | |
| 403 emitRtRsImm16Rel(Opcode, OpRt, OpRs, OpImm, Reloc, "addiu"); | |
| 404 } | |
| 405 | |
| 368 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, | 406 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, |
| 369 const Operand *OpRt) { | 407 const Operand *OpRt) { |
| 370 static constexpr IValueT Opcode = 0x00000021; | 408 static constexpr IValueT Opcode = 0x00000021; |
| 371 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); | 409 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); |
| 372 } | 410 } |
| 373 | 411 |
| 374 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs, | 412 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs, |
| 375 const Operand *OpRt) { | 413 const Operand *OpRt) { |
| 376 static constexpr IValueT Opcode = 0x00000024; | 414 static constexpr IValueT Opcode = 0x00000024; |
| 377 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and"); | 415 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and"); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 const Operand *OpFt) { | 573 const Operand *OpFt) { |
| 536 static constexpr IValueT Opcode = 0x44000003; | 574 static constexpr IValueT Opcode = 0x44000003; |
| 537 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s"); | 575 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s"); |
| 538 } | 576 } |
| 539 | 577 |
| 540 void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) { | 578 void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) { |
| 541 static constexpr IValueT Opcode = 0x0000001B; | 579 static constexpr IValueT Opcode = 0x0000001B; |
| 542 emitRsRt(Opcode, OpRs, OpRt, "divu"); | 580 emitRsRt(Opcode, OpRs, OpRt, "divu"); |
| 543 } | 581 } |
| 544 | 582 |
| 545 void AssemblerMIPS32::lui(const Operand *OpRt, const uint16_t Imm) { | 583 MIPS32Fixup *AssemblerMIPS32::createMIPS32Fixup(const RelocOp Reloc, |
| 584 const Constant *RelOp) { | |
| 585 MIPS32Fixup *Fixup = new (allocate<MIPS32Fixup>()) MIPS32Fixup(); | |
| 586 if (Reloc == RelocOp::RO_Hi) { | |
|
Jim Stichnoth
2016/10/27 13:58:15
Would it be better to use a switch on Reloc here?
jaydeep.patil
2016/10/28 02:53:56
Done.
| |
| 587 Fixup->set_kind(llvm::ELF::R_MIPS_HI16); | |
| 588 } else if (Reloc == RelocOp::RO_Lo) { | |
| 589 Fixup->set_kind(llvm::ELF::R_MIPS_LO16); | |
| 590 } else if (Reloc == RelocOp::RO_Jal) { | |
| 591 Fixup->set_kind(llvm::ELF::R_MIPS_26); | |
| 592 } else { | |
| 593 llvm::report_fatal_error("Fixup: Invalid Reloc type"); | |
| 594 } | |
| 595 Fixup->set_value(RelOp); | |
| 596 Buffer.installFixup(Fixup); | |
| 597 return Fixup; | |
| 598 } | |
| 599 | |
| 600 size_t MIPS32Fixup::emit(GlobalContext *Ctx, const Assembler &Asm) const { | |
| 601 if (!BuildDefs::dump()) | |
| 602 return InstMIPS32::InstSize; | |
| 603 Ostream &Str = Ctx->getStrEmit(); | |
| 604 IValueT Inst = Asm.load<IValueT>(position()); | |
| 605 const auto Symbol = symbol().toString(); | |
| 606 Str << "\t" | |
| 607 << ".word " << llvm::format_hex(Inst, 8) << " # "; | |
| 608 switch (kind()) { | |
| 609 case llvm::ELF::R_MIPS_HI16: | |
| 610 Str << "R_MIPS_HI16 "; | |
| 611 break; | |
| 612 case llvm::ELF::R_MIPS_LO16: | |
| 613 Str << "R_MIPS_LO16 "; | |
| 614 break; | |
| 615 case llvm::ELF::R_MIPS_26: | |
| 616 Str << "R_MIPS_26 "; | |
| 617 break; | |
| 618 default: | |
| 619 Str << "Unknown "; | |
| 620 break; | |
| 621 } | |
| 622 Str << Symbol << "\n"; | |
| 623 return InstMIPS32::InstSize; | |
| 624 } | |
| 625 | |
| 626 void MIPS32Fixup::emitOffset(Assembler *Asm) const { | |
| 627 const IValueT Inst = Asm->load<IValueT>(position()); | |
| 628 IValueT ImmMask = 0; | |
| 629 const IValueT Imm = offset(); | |
| 630 if (kind() == llvm::ELF::R_MIPS_26) { | |
| 631 ImmMask = 0x03FFFFFF; | |
| 632 } else { | |
| 633 ImmMask = 0x0000FFFF; | |
| 634 } | |
| 635 Asm->store(position(), (Inst & ~ImmMask) | (Imm & ImmMask)); | |
| 636 } | |
| 637 | |
| 638 void AssemblerMIPS32::jal(const ConstantRelocatable *Target) { | |
| 639 IValueT Opcode = 0x0C000000; | |
| 640 emitFixup(createMIPS32Fixup(RelocOp::RO_Jal, Target)); | |
| 641 emitInst(Opcode); | |
| 642 nop(); | |
| 643 } | |
| 644 | |
| 645 void AssemblerMIPS32::lui(const Operand *OpRt, const Operand *OpImm, | |
| 646 const RelocOp Reloc) { | |
| 546 IValueT Opcode = 0x3C000000; | 647 IValueT Opcode = 0x3C000000; |
| 547 const IValueT Rt = encodeGPRegister(OpRt, "Rt", "lui"); | 648 const IValueT Rt = encodeGPRegister(OpRt, "Rt", "lui"); |
| 649 IValueT Imm16 = 0; | |
| 650 | |
| 651 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) { | |
| 652 emitFixup(createMIPS32Fixup(Reloc, OpRel)); | |
| 653 } else { | |
| 654 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) { | |
| 655 Imm16 = C32->getValue(); | |
| 656 } else { | |
| 657 llvm::report_fatal_error("lui: Invalid 2nd operand"); | |
| 658 } | |
| 659 } | |
| 660 | |
| 548 Opcode |= Rt << 16; | 661 Opcode |= Rt << 16; |
| 549 Opcode |= Imm; | 662 Opcode |= Imm16; |
| 550 emitInst(Opcode); | 663 emitInst(Opcode); |
| 551 } | 664 } |
| 552 | 665 |
| 666 void AssemblerMIPS32::ldc1(const Operand *OpRt, const Operand *OpBase, | |
| 667 const Operand *OpOff, const RelocOp Reloc) { | |
| 668 IValueT Opcode = 0xD4000000; | |
| 669 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "ldc1"); | |
| 670 const IValueT Base = encodeGPRegister(OpBase, "Base", "ldc1"); | |
| 671 IValueT Imm16 = 0; | |
| 672 | |
| 673 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { | |
| 674 emitFixup(createMIPS32Fixup(Reloc, OpRel)); | |
| 675 } else { | |
| 676 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { | |
| 677 Imm16 = C32->getValue(); | |
| 678 } else { | |
| 679 llvm::report_fatal_error("ldc1: Invalid 2nd operand"); | |
| 680 } | |
| 681 } | |
| 682 | |
| 683 Opcode |= Base << 21; | |
| 684 Opcode |= Rt << 16; | |
| 685 Opcode |= Imm16; | |
| 686 emitInst(Opcode); | |
| 687 } | |
| 688 | |
| 553 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, | 689 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, |
| 554 const uint32_t Offset) { | 690 const uint32_t Offset) { |
| 555 switch (OpRt->getType()) { | 691 switch (OpRt->getType()) { |
| 556 case IceType_i1: | 692 case IceType_i1: |
| 557 case IceType_i8: { | 693 case IceType_i8: { |
| 558 static constexpr IValueT Opcode = 0x80000000; | 694 static constexpr IValueT Opcode = 0x80000000; |
| 559 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb"); | 695 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb"); |
| 560 break; | 696 break; |
| 561 } | 697 } |
| 562 case IceType_i16: { | 698 case IceType_i16: { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 576 } | 712 } |
| 577 case IceType_f64: { | 713 case IceType_f64: { |
| 578 static constexpr IValueT Opcode = 0xD4000000; | 714 static constexpr IValueT Opcode = 0xD4000000; |
| 579 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1"); | 715 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1"); |
| 580 break; | 716 break; |
| 581 } | 717 } |
| 582 default: { UnimplementedError(getFlags()); } | 718 default: { UnimplementedError(getFlags()); } |
| 583 } | 719 } |
| 584 } | 720 } |
| 585 | 721 |
| 722 void AssemblerMIPS32::lwc1(const Operand *OpRt, const Operand *OpBase, | |
| 723 const Operand *OpOff, const RelocOp Reloc) { | |
| 724 IValueT Opcode = 0xC4000000; | |
| 725 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "lwc1"); | |
| 726 const IValueT Base = encodeGPRegister(OpBase, "Base", "lwc1"); | |
| 727 IValueT Imm16 = 0; | |
| 728 | |
| 729 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { | |
| 730 emitFixup(createMIPS32Fixup(Reloc, OpRel)); | |
| 731 } else { | |
| 732 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { | |
| 733 Imm16 = C32->getValue(); | |
| 734 } else { | |
| 735 llvm::report_fatal_error("lwc1: Invalid 2nd operand"); | |
| 736 } | |
| 737 } | |
| 738 | |
| 739 Opcode |= Base << 21; | |
| 740 Opcode |= Rt << 16; | |
| 741 Opcode |= Imm16; | |
| 742 emitInst(Opcode); | |
| 743 } | |
| 744 | |
| 586 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) { | 745 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) { |
| 587 static constexpr IValueT Opcode = 0x44000000; | 746 static constexpr IValueT Opcode = 0x44000000; |
| 588 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1"); | 747 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1"); |
| 589 } | 748 } |
| 590 | 749 |
| 591 void AssemblerMIPS32::mfhi(const Operand *OpRd) { | 750 void AssemblerMIPS32::mfhi(const Operand *OpRd) { |
| 592 IValueT Opcode = 0x000000010; | 751 IValueT Opcode = 0x000000010; |
| 593 IValueT Rd = encodeGPRegister(OpRd, "Rd", "mfhi"); | 752 IValueT Rd = encodeGPRegister(OpRd, "Rd", "mfhi"); |
| 594 Opcode |= Rd << 11; | 753 Opcode |= Rd << 11; |
| 595 emitInst(Opcode); | 754 emitInst(Opcode); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 613 } | 772 } |
| 614 | 773 |
| 615 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { | 774 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { |
| 616 | 775 |
| 617 const Type DstType = OpRd->getType(); | 776 const Type DstType = OpRd->getType(); |
| 618 const Type SrcType = OpRs->getType(); | 777 const Type SrcType = OpRs->getType(); |
| 619 | 778 |
| 620 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) || | 779 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) || |
| 621 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) { | 780 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) { |
| 622 if (isScalarFloatingType(DstType)) { | 781 if (isScalarFloatingType(DstType)) { |
| 623 mtc1(OpRd, OpRs); | 782 mtc1(OpRs, OpRd); |
| 624 } else { | 783 } else { |
| 625 mfc1(OpRd, OpRs); | 784 mfc1(OpRd, OpRs); |
| 626 } | 785 } |
| 627 } else { | 786 } else { |
| 628 switch (DstType) { | 787 switch (DstType) { |
| 629 case IceType_f32: | 788 case IceType_f32: |
| 630 mov_s(OpRd, OpRs); | 789 mov_s(OpRd, OpRs); |
| 631 break; | 790 break; |
| 632 case IceType_f64: | 791 case IceType_f64: |
| 633 mov_d(OpRd, OpRs); | 792 mov_d(OpRd, OpRs); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 static constexpr IValueT Opcode = 0x44000002; | 910 static constexpr IValueT Opcode = 0x44000002; |
| 752 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d"); | 911 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d"); |
| 753 } | 912 } |
| 754 | 913 |
| 755 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs, | 914 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs, |
| 756 const Operand *OpFt) { | 915 const Operand *OpFt) { |
| 757 static constexpr IValueT Opcode = 0x44000002; | 916 static constexpr IValueT Opcode = 0x44000002; |
| 758 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s"); | 917 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s"); |
| 759 } | 918 } |
| 760 | 919 |
| 920 void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) { | |
| 921 static constexpr IValueT Opcode = 0x00000018; | |
| 922 emitRsRt(Opcode, OpRs, OpRt, "mult"); | |
| 923 } | |
| 924 | |
| 761 void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) { | 925 void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) { |
| 762 static constexpr IValueT Opcode = 0x00000019; | 926 static constexpr IValueT Opcode = 0x00000019; |
| 763 emitRsRt(Opcode, OpRs, OpRt, "multu"); | 927 emitRsRt(Opcode, OpRs, OpRt, "multu"); |
| 764 } | 928 } |
| 765 | 929 |
| 766 void AssemblerMIPS32::nor(const Operand *OpRd, const Operand *OpRs, | 930 void AssemblerMIPS32::nor(const Operand *OpRd, const Operand *OpRs, |
| 767 const Operand *OpRt) { | 931 const Operand *OpRt) { |
| 768 static constexpr IValueT Opcode = 0x00000027; | 932 static constexpr IValueT Opcode = 0x00000027; |
| 769 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "nor"); | 933 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "nor"); |
| 770 } | 934 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 868 static constexpr IValueT Opcode = 0x44000001; | 1032 static constexpr IValueT Opcode = 0x44000001; |
| 869 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s"); | 1033 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s"); |
| 870 } | 1034 } |
| 871 | 1035 |
| 872 void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs, | 1036 void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs, |
| 873 const Operand *OpRt) { | 1037 const Operand *OpRt) { |
| 874 static constexpr IValueT Opcode = 0x00000023; | 1038 static constexpr IValueT Opcode = 0x00000023; |
| 875 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu"); | 1039 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu"); |
| 876 } | 1040 } |
| 877 | 1041 |
| 1042 void AssemblerMIPS32::sdc1(const Operand *OpRt, const Operand *OpBase, | |
| 1043 const Operand *OpOff, const RelocOp Reloc) { | |
| 1044 IValueT Opcode = 0xF4000000; | |
| 1045 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "sdc1"); | |
| 1046 const IValueT Base = encodeGPRegister(OpBase, "Base", "sdc1"); | |
| 1047 IValueT Imm16 = 0; | |
| 1048 | |
| 1049 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { | |
| 1050 emitFixup(createMIPS32Fixup(Reloc, OpRel)); | |
| 1051 } else { | |
| 1052 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { | |
| 1053 Imm16 = C32->getValue(); | |
| 1054 } else { | |
| 1055 llvm::report_fatal_error("sdc1: Invalid 2nd operand"); | |
| 1056 } | |
| 1057 } | |
| 1058 | |
| 1059 Opcode |= Base << 21; | |
| 1060 Opcode |= Rt << 16; | |
| 1061 Opcode |= Imm16; | |
| 1062 emitInst(Opcode); | |
| 1063 } | |
| 1064 | |
| 878 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, | 1065 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, |
| 879 const uint32_t Offset) { | 1066 const uint32_t Offset) { |
| 880 switch (OpRt->getType()) { | 1067 switch (OpRt->getType()) { |
| 881 case IceType_i1: | 1068 case IceType_i1: |
| 882 case IceType_i8: { | 1069 case IceType_i8: { |
| 883 static constexpr IValueT Opcode = 0xA0000000; | 1070 static constexpr IValueT Opcode = 0xA0000000; |
| 884 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb"); | 1071 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb"); |
| 885 break; | 1072 break; |
| 886 } | 1073 } |
| 887 case IceType_i16: { | 1074 case IceType_i16: { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 901 } | 1088 } |
| 902 case IceType_f64: { | 1089 case IceType_f64: { |
| 903 static constexpr IValueT Opcode = 0xF4000000; | 1090 static constexpr IValueT Opcode = 0xF4000000; |
| 904 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1"); | 1091 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1"); |
| 905 break; | 1092 break; |
| 906 } | 1093 } |
| 907 default: { UnimplementedError(getFlags()); } | 1094 default: { UnimplementedError(getFlags()); } |
| 908 } | 1095 } |
| 909 } | 1096 } |
| 910 | 1097 |
| 1098 void AssemblerMIPS32::swc1(const Operand *OpRt, const Operand *OpBase, | |
| 1099 const Operand *OpOff, const RelocOp Reloc) { | |
| 1100 IValueT Opcode = 0xE4000000; | |
| 1101 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "swc1"); | |
| 1102 const IValueT Base = encodeGPRegister(OpBase, "Base", "swc1"); | |
| 1103 IValueT Imm16 = 0; | |
| 1104 | |
| 1105 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { | |
| 1106 emitFixup(createMIPS32Fixup(Reloc, OpRel)); | |
| 1107 } else { | |
| 1108 if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { | |
| 1109 Imm16 = C32->getValue(); | |
| 1110 } else { | |
| 1111 llvm::report_fatal_error("swc1: Invalid 2nd operand"); | |
| 1112 } | |
| 1113 } | |
| 1114 | |
| 1115 Opcode |= Base << 21; | |
| 1116 Opcode |= Rt << 16; | |
| 1117 Opcode |= Imm16; | |
| 1118 emitInst(Opcode); | |
| 1119 } | |
| 1120 | |
| 911 void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt, | 1121 void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt, |
| 912 const uint32_t TrapCode) { | 1122 const uint32_t TrapCode) { |
| 913 IValueT Opcode = 0x00000034; | 1123 IValueT Opcode = 0x00000034; |
| 914 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq"); | 1124 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq"); |
| 915 const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq"); | 1125 const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq"); |
| 916 Opcode |= (TrapCode & 0xFFFFF) << 6; | 1126 Opcode |= (TrapCode & 0xFFFFF) << 6; |
| 917 Opcode |= Rt << 16; | 1127 Opcode |= Rt << 16; |
| 918 Opcode |= Rs << 21; | 1128 Opcode |= Rs << 21; |
| 919 emitInst(Opcode); | 1129 emitInst(Opcode); |
| 920 } | 1130 } |
| 921 | 1131 |
| 922 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) { | 1132 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) { |
| 923 static constexpr IValueT Opcode = 0x4400000D; | 1133 static constexpr IValueT Opcode = 0x4400000D; |
| 924 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d"); | 1134 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d"); |
| 925 } | 1135 } |
| 926 | 1136 |
| 927 void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) { | 1137 void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) { |
| 928 static constexpr IValueT Opcode = 0x4400000D; | 1138 static constexpr IValueT Opcode = 0x4400000D; |
| 929 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s"); | 1139 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s"); |
| 930 } | 1140 } |
| 931 | 1141 |
| 932 void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) { | 1142 void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) { |
| 933 static constexpr IValueT Opcode = 0x4400000D; | 1143 static constexpr IValueT Opcode = 0x4400000D; |
| 934 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.d"); | 1144 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "trunc.w.d"); |
| 935 } | 1145 } |
| 936 | 1146 |
| 937 void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) { | 1147 void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) { |
| 938 static constexpr IValueT Opcode = 0x4400000D; | 1148 static constexpr IValueT Opcode = 0x4400000D; |
| 939 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "trunc.w.s"); | 1149 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "trunc.w.s"); |
| 940 } | 1150 } |
| 941 | 1151 |
| 942 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, | 1152 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, |
| 943 const Operand *OpRt) { | 1153 const Operand *OpRt) { |
| 944 static constexpr IValueT Opcode = 0x00000026; | 1154 static constexpr IValueT Opcode = 0x00000026; |
| 945 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor"); | 1155 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor"); |
| 946 } | 1156 } |
| 947 | 1157 |
| 948 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs, | 1158 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs, |
| 949 const uint32_t Imm) { | 1159 const uint32_t Imm) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1020 emitBr(Cond, OpRs, OpRtNone, Dest); | 1230 emitBr(Cond, OpRs, OpRtNone, Dest); |
| 1021 return; | 1231 return; |
| 1022 } | 1232 } |
| 1023 const IOffsetT Position = Buffer.size(); | 1233 const IOffsetT Position = Buffer.size(); |
| 1024 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); | 1234 emitBr(Cond, OpRs, OpRtNone, TargetLabel->getEncodedPosition()); |
| 1025 TargetLabel->linkTo(*this, Position); | 1235 TargetLabel->linkTo(*this, Position); |
| 1026 } | 1236 } |
| 1027 | 1237 |
| 1028 } // end of namespace MIPS32 | 1238 } // end of namespace MIPS32 |
| 1029 } // end of namespace Ice | 1239 } // end of namespace Ice |
| OLD | NEW |