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