Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Implements the Assembler class for MIPS32.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "IceAssemblerMIPS32.h"
     16 #include "IceCfgNode.h"
     17 #include "IceRegistersMIPS32.h"
     18 #include "IceUtils.h"
     19 
     20 namespace {
     21 
     22 using namespace Ice;
     23 using namespace Ice::MIPS32;
     24 
     25 // Offset modifier to current PC for next instruction.
     26 static constexpr IOffsetT kPCReadOffset = 4;
     27 
     28 // Mask to pull out PC offset from branch instruction.
     29 static constexpr int kBranchOffsetBits = 16;
     30 static constexpr IOffsetT kBranchOffsetMask = 0x0000ffff;
     31 
     32 } // end of anonymous namespace
     33 
     34 namespace Ice {
     35 namespace MIPS32 {
     36 
     37 void AssemblerMIPS32::emitTextInst(const std::string &Text, SizeT InstSize) {
     38   AssemblerFixup *F = createTextFixup(Text, InstSize);
     39   emitFixup(F);
     40   for (SizeT I = 0; I < InstSize; ++I) {
     41     AssemblerBuffer::EnsureCapacity ensured(&Buffer);
     42     Buffer.emit<char>(0);
     43   }
     44 }
     45 
     46 namespace {
     47 
     48 // TEQ $0, $0 - Trap if equal
     49 static constexpr uint8_t TrapBytesRaw[] = {0x00, 0x00, 0x00, 0x34};
     50 
     51 const auto TrapBytes =
     52     llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw));
     53 
     54 } // end of anonymous namespace
     55 
     56 llvm::ArrayRef<uint8_t> AssemblerMIPS32::getNonExecBundlePadding() const {
     57   return TrapBytes;
     58 }
     59 
     60 void AssemblerMIPS32::trap() {
     61   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
     62   for (const uint8_t &Byte : reverse_range(TrapBytes))
     63     Buffer.emit<uint8_t>(Byte);
     64 }
     65 
     66 void AssemblerMIPS32::nop() { emitInst(0); }
     67 
     68 void AssemblerMIPS32::padWithNop(intptr_t Padding) {
     69   constexpr intptr_t InstWidth = sizeof(IValueT);
     70   assert(Padding % InstWidth == 0 &&
     71          "Padding not multiple of instruction size");
     72   for (intptr_t i = 0; i < Padding; i += InstWidth)
     73     nop();
     74 }
     75 
     76 Label *AssemblerMIPS32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
     77   Label *L = nullptr;
     78   if (Number == Labels.size()) {
     79     L = new (this->allocate<Label>()) Label();
     80     Labels.push_back(L);
     81     return L;
     82   }
     83   if (Number > Labels.size()) {
     84     Labels.resize(Number + 1);
     85   }
     86   L = Labels[Number];
     87   if (L == nullptr) {
     88     L = new (this->allocate<Label>()) Label();
     89     Labels[Number] = L;
     90   }
     91   return L;
     92 }
     93 
     94 void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) {
     95   if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
     96     constexpr SizeT InstSize = 0;
     97     emitTextInst(Node->getAsmName() + ":", InstSize);
     98   }
     99   SizeT NodeNumber = Node->getIndex();
    100   assert(!getPreliminary());
    101   Label *L = getOrCreateCfgNodeLabel(NodeNumber);
    102   this->bind(L);
    103 }
    104 
    105 namespace {
    106 
    107 // Checks that Offset can fit in imm16 constant of branch instruction.
    108 void assertCanEncodeBranchOffset(IOffsetT Offset) {
    109   (void)Offset;
    110   (void)kBranchOffsetBits;
    111   assert(Utils::IsAligned(Offset, 4));
    112   assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2));
    113 }
    114 
    115 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
    116   Offset -= kPCReadOffset;
    117   assertCanEncodeBranchOffset(Offset);
    118   Offset >>= 2;
    119   Offset &= kBranchOffsetMask;
    120   return (Inst & ~kBranchOffsetMask) | Offset;
    121 }
    122 
    123 enum RegSetWanted { WantGPRegs, WantFPRegs };
    124 
    125 IValueT getEncodedGPRegNum(const Variable *Var) {
    126   assert(Var->hasReg() && isScalarIntegerType(Var->getType()));
    127   const auto Reg = Var->getRegNum();
    128   return RegMIPS32::getEncodedGPR(Reg);
    129 }
    130 
    131 IValueT getEncodedFPRegNum(const Variable *Var) {
    132   assert(Var->hasReg() && isScalarFloatingType(Var->getType()));
    133   const auto Reg = Var->getRegNum();
    134   IValueT RegEncoding;
    135   if (RegMIPS32::isFPRReg(Reg)) {
    136     RegEncoding = RegMIPS32::getEncodedFPR(Reg);
    137   } else {
    138     RegEncoding = RegMIPS32::getEncodedFPR64(Reg);
    139   }
    140   return RegEncoding;
    141 }
    142 
    143 bool encodeOperand(const Operand *Opnd, IValueT &Value,
    144                    RegSetWanted WantedRegSet) {
    145   Value = 0;
    146   if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
    147     if (Var->hasReg()) {
    148       switch (WantedRegSet) {
    149       case WantGPRegs:
    150         Value = getEncodedGPRegNum(Var);
    151         break;
    152       case WantFPRegs:
    153         Value = getEncodedFPRegNum(Var);
    154         break;
    155       }
    156       return true;
    157     }
    158     return false;
    159   }
    160   return false;
    161 }
    162 
    163 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet,
    164                        const char *RegName, const char *InstName) {
    165   IValueT Reg = 0;
    166   if (encodeOperand(OpReg, Reg, WantedRegSet) != true)
    167     llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
    168                              RegName);
    169   return Reg;
    170 }
    171 
    172 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
    173                          const char *InstName) {
    174   return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
    175 }
    176 
    177 IValueT encodeFPRegister(const Operand *OpReg, const char *RegName,
    178                          const char *InstName) {
    179   return encodeRegister(OpReg, WantFPRegs, RegName, InstName);
    180 }
    181 
    182 } // end of anonymous namespace
    183 
    184 IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) {
    185   int16_t imm = (Inst & kBranchOffsetMask);
    186   IOffsetT Offset = imm;
    187   Offset = Offset << 2;
    188   return (Offset + kPCReadOffset);
    189 }
    190 
    191 void AssemblerMIPS32::bind(Label *L) {
    192   IOffsetT BoundPc = Buffer.size();
    193   assert(!L->isBound()); // Labels can only be bound once.
    194   while (L->isLinked()) {
    195     IOffsetT Position = L->getLinkPosition();
    196     IOffsetT Dest = BoundPc - Position;
    197     IValueT Inst = Buffer.load<IValueT>(Position);
    198     Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
    199     IOffsetT NextBrPc = decodeBranchOffset(Inst);
    200     if (NextBrPc != 0)
    201       NextBrPc = Position - NextBrPc;
    202     L->setPosition(NextBrPc);
    203   }
    204   L->bindTo(BoundPc);
    205 }
    206 
    207 void AssemblerMIPS32::emitRsRt(IValueT Opcode, const Operand *OpRs,
    208                                const Operand *OpRt, const char *InsnName) {
    209   const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
    210   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    211 
    212   Opcode |= Rs << 21;
    213   Opcode |= Rt << 16;
    214 
    215   emitInst(Opcode);
    216 }
    217 
    218 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
    219                                     const Operand *OpRs, const uint32_t Imm,
    220                                     const char *InsnName) {
    221   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    222   const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
    223 
    224   Opcode |= Rs << 21;
    225   Opcode |= Rt << 16;
    226   Opcode |= Imm & 0xffff;
    227 
    228   emitInst(Opcode);
    229 }
    230 
    231 void AssemblerMIPS32::emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
    232                                        const Operand *OpRs,
    233                                        const Operand *OpImm,
    234                                        const RelocOp Reloc,
    235                                        const char *InsnName) {
    236   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    237   const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
    238   uint32_t Imm16 = 0;
    239 
    240   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) {
    241     emitFixup(createMIPS32Fixup(Reloc, OpRel));
    242   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) {
    243     Imm16 = C32->getValue();
    244   } else {
    245     llvm::report_fatal_error(std::string(InsnName) + ": Invalid 3rd operand");
    246   }
    247 
    248   Opcode |= Rs << 21;
    249   Opcode |= Rt << 16;
    250   Opcode |= Imm16 & 0xffff;
    251 
    252   emitInst(Opcode);
    253 }
    254 
    255 void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt,
    256                                     const Operand *OpRs, const uint32_t Imm,
    257                                     const char *InsnName) {
    258   const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
    259   const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
    260 
    261   Opcode |= Rs << 21;
    262   Opcode |= Ft << 16;
    263   Opcode |= Imm & 0xffff;
    264 
    265   emitInst(Opcode);
    266 }
    267 
    268 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd,
    269                                  const Operand *OpRt, const uint32_t Sa,
    270                                  const char *InsnName) {
    271   const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
    272   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    273 
    274   Opcode |= Rt << 16;
    275   Opcode |= Rd << 11;
    276   Opcode |= (Sa & 0x1f) << 6;
    277 
    278   emitInst(Opcode);
    279 }
    280 
    281 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd,
    282                                  const Operand *OpRs, const Operand *OpRt,
    283                                  const char *InsnName) {
    284   const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
    285   const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
    286   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    287 
    288   Opcode |= Rs << 21;
    289   Opcode |= Rt << 16;
    290   Opcode |= Rd << 11;
    291 
    292   emitInst(Opcode);
    293 }
    294 
    295 void AssemblerMIPS32::emitCOP1Fcmp(IValueT Opcode, FPInstDataFormat Format,
    296                                    const Operand *OpFs, const Operand *OpFt,
    297                                    IValueT CC, const char *InsnName) {
    298   const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
    299   const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
    300 
    301   Opcode |= CC << 8;
    302   Opcode |= Fs << 11;
    303   Opcode |= Ft << 16;
    304   Opcode |= Format << 21;
    305 
    306   emitInst(Opcode);
    307 }
    308 
    309 void AssemblerMIPS32::emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
    310                                       const Operand *OpFd, const Operand *OpFs,
    311                                       const char *InsnName) {
    312   const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
    313   const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
    314 
    315   Opcode |= Fd << 6;
    316   Opcode |= Fs << 11;
    317   Opcode |= Format << 21;
    318 
    319   emitInst(Opcode);
    320 }
    321 
    322 void AssemblerMIPS32::emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
    323                                         const Operand *OpFd,
    324                                         const Operand *OpFs,
    325                                         const Operand *OpFt,
    326                                         const char *InsnName) {
    327   const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
    328   const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
    329   const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
    330 
    331   Opcode |= Fd << 6;
    332   Opcode |= Fs << 11;
    333   Opcode |= Ft << 16;
    334   Opcode |= Format << 21;
    335 
    336   emitInst(Opcode);
    337 }
    338 
    339 void AssemblerMIPS32::emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
    340                                         const Operand *OpFd,
    341                                         const Operand *OpFs,
    342                                         const Operand *OpRt,
    343                                         const char *InsnName) {
    344   const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
    345   const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
    346   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    347 
    348   Opcode |= Fd << 6;
    349   Opcode |= Fs << 11;
    350   Opcode |= Rt << 16;
    351   Opcode |= Format << 21;
    352 
    353   emitInst(Opcode);
    354 }
    355 
    356 void AssemblerMIPS32::emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt,
    357                                       const Operand *OpFs,
    358                                       const char *InsnName) {
    359   const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
    360   const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
    361   Opcode |= Fs << 11;
    362   Opcode |= Rt << 16;
    363 
    364   emitInst(Opcode);
    365 }
    366 
    367 void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) {
    368   static constexpr IValueT Opcode = 0x44000005;
    369   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d");
    370 }
    371 
    372 void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) {
    373   static constexpr IValueT Opcode = 0x44000005;
    374   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s");
    375 }
    376 
    377 void AssemblerMIPS32::addi(const Operand *OpRt, const Operand *OpRs,
    378                            const uint32_t Imm) {
    379   static constexpr IValueT Opcode = 0x20000000;
    380   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addi");
    381 }
    382 
    383 void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs,
    384                             const Operand *OpFt) {
    385   static constexpr IValueT Opcode = 0x44000000;
    386   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d");
    387 }
    388 
    389 void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs,
    390                             const Operand *OpFt) {
    391   static constexpr IValueT Opcode = 0x44000000;
    392   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s");
    393 }
    394 
    395 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
    396                             const uint32_t Imm) {
    397   static constexpr IValueT Opcode = 0x24000000;
    398   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
    399 }
    400 
    401 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
    402                             const Operand *OpImm, const RelocOp Reloc) {
    403   static constexpr IValueT Opcode = 0x24000000;
    404   emitRtRsImm16Rel(Opcode, OpRt, OpRs, OpImm, Reloc, "addiu");
    405 }
    406 
    407 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
    408                            const Operand *OpRt) {
    409   static constexpr IValueT Opcode = 0x00000021;
    410   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu");
    411 }
    412 
    413 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs,
    414                            const Operand *OpRt) {
    415   static constexpr IValueT Opcode = 0x00000024;
    416   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and");
    417 }
    418 
    419 void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs,
    420                            const uint32_t Imm) {
    421   static constexpr IValueT Opcode = 0x30000000;
    422   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi");
    423 }
    424 
    425 void AssemblerMIPS32::b(Label *TargetLabel) {
    426   static constexpr Operand *OpRsNone = nullptr;
    427   static constexpr Operand *OpRtNone = nullptr;
    428   if (TargetLabel->isBound()) {
    429     const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
    430     emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest);
    431     return;
    432   }
    433   const IOffsetT Position = Buffer.size();
    434   IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
    435   if (PrevPosition != 0)
    436     PrevPosition = Position - PrevPosition;
    437   emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, PrevPosition);
    438   TargetLabel->linkTo(*this, Position);
    439 }
    440 
    441 void AssemblerMIPS32::c_eq_d(const Operand *OpFs, const Operand *OpFt) {
    442   static constexpr IValueT Opcode = 0x44000032;
    443   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    444                "c.eq.d");
    445 }
    446 
    447 void AssemblerMIPS32::c_eq_s(const Operand *OpFs, const Operand *OpFt) {
    448   static constexpr IValueT Opcode = 0x44000032;
    449   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    450                "c.eq.s");
    451 }
    452 
    453 void AssemblerMIPS32::c_ole_d(const Operand *OpFs, const Operand *OpFt) {
    454   static constexpr IValueT Opcode = 0x44000036;
    455   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    456                "c.ole.d");
    457 }
    458 
    459 void AssemblerMIPS32::c_ole_s(const Operand *OpFs, const Operand *OpFt) {
    460   static constexpr IValueT Opcode = 0x44000036;
    461   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    462                "c.ole.s");
    463 }
    464 
    465 void AssemblerMIPS32::c_olt_d(const Operand *OpFs, const Operand *OpFt) {
    466   static constexpr IValueT Opcode = 0x44000034;
    467   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    468                "c.olt.d");
    469 }
    470 
    471 void AssemblerMIPS32::c_olt_s(const Operand *OpFs, const Operand *OpFt) {
    472   static constexpr IValueT Opcode = 0x44000034;
    473   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    474                "c.olt.s");
    475 }
    476 
    477 void AssemblerMIPS32::c_ueq_d(const Operand *OpFs, const Operand *OpFt) {
    478   static constexpr IValueT Opcode = 0x44000033;
    479   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    480                "c.ueq.d");
    481 }
    482 
    483 void AssemblerMIPS32::c_ueq_s(const Operand *OpFs, const Operand *OpFt) {
    484   static constexpr IValueT Opcode = 0x44000033;
    485   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    486                "c.ueq.s");
    487 }
    488 
    489 void AssemblerMIPS32::c_ule_d(const Operand *OpFs, const Operand *OpFt) {
    490   static constexpr IValueT Opcode = 0x44000037;
    491   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    492                "c.ule.d");
    493 }
    494 
    495 void AssemblerMIPS32::c_ule_s(const Operand *OpFs, const Operand *OpFt) {
    496   static constexpr IValueT Opcode = 0x44000037;
    497   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    498                "c.ule.s");
    499 }
    500 
    501 void AssemblerMIPS32::c_ult_d(const Operand *OpFs, const Operand *OpFt) {
    502   static constexpr IValueT Opcode = 0x44000035;
    503   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    504                "c.ult.d");
    505 }
    506 
    507 void AssemblerMIPS32::c_ult_s(const Operand *OpFs, const Operand *OpFt) {
    508   static constexpr IValueT Opcode = 0x44000035;
    509   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    510                "c.ult.s");
    511 }
    512 
    513 void AssemblerMIPS32::c_un_d(const Operand *OpFs, const Operand *OpFt) {
    514   static constexpr IValueT Opcode = 0x44000031;
    515   emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    516                "c.un.d");
    517 }
    518 
    519 void AssemblerMIPS32::c_un_s(const Operand *OpFs, const Operand *OpFt) {
    520   static constexpr IValueT Opcode = 0x44000031;
    521   emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
    522                "c.un.s");
    523 }
    524 
    525 void AssemblerMIPS32::clz(const Operand *OpRd, const Operand *OpRs) {
    526   IValueT Opcode = 0x70000020;
    527   const IValueT Rd = encodeGPRegister(OpRd, "Rd", "clz");
    528   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "clz");
    529   Opcode |= Rd << 11;
    530   Opcode |= Rd << 16;
    531   Opcode |= Rs << 21;
    532   emitInst(Opcode);
    533 }
    534 
    535 void AssemblerMIPS32::cvt_d_l(const Operand *OpFd, const Operand *OpFs) {
    536   static constexpr IValueT Opcode = 0x44000021;
    537   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.d.l");
    538 }
    539 
    540 void AssemblerMIPS32::cvt_d_s(const Operand *OpFd, const Operand *OpFs) {
    541   static constexpr IValueT Opcode = 0x44000021;
    542   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "cvt.d.s");
    543 }
    544 
    545 void AssemblerMIPS32::cvt_d_w(const Operand *OpFd, const Operand *OpFs) {
    546   static constexpr IValueT Opcode = 0x44000021;
    547   emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.d.w");
    548 }
    549 
    550 void AssemblerMIPS32::cvt_s_d(const Operand *OpFd, const Operand *OpFs) {
    551   static constexpr IValueT Opcode = 0x44000020;
    552   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "cvt.s.d");
    553 }
    554 
    555 void AssemblerMIPS32::cvt_s_l(const Operand *OpFd, const Operand *OpFs) {
    556   static constexpr IValueT Opcode = 0x44000020;
    557   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.s.l");
    558 }
    559 
    560 void AssemblerMIPS32::cvt_s_w(const Operand *OpFd, const Operand *OpFs) {
    561   static constexpr IValueT Opcode = 0x44000020;
    562   emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.s.w");
    563 }
    564 
    565 void AssemblerMIPS32::div(const Operand *OpRs, const Operand *OpRt) {
    566   static constexpr IValueT Opcode = 0x0000001A;
    567   emitRsRt(Opcode, OpRs, OpRt, "div");
    568 }
    569 
    570 void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs,
    571                             const Operand *OpFt) {
    572   static constexpr IValueT Opcode = 0x44000003;
    573   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d");
    574 }
    575 
    576 void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs,
    577                             const Operand *OpFt) {
    578   static constexpr IValueT Opcode = 0x44000003;
    579   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s");
    580 }
    581 
    582 void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) {
    583   static constexpr IValueT Opcode = 0x0000001B;
    584   emitRsRt(Opcode, OpRs, OpRt, "divu");
    585 }
    586 
    587 MIPS32Fixup *AssemblerMIPS32::createMIPS32Fixup(const RelocOp Reloc,
    588                                                 const Constant *RelOp) {
    589   MIPS32Fixup *Fixup = new (allocate<MIPS32Fixup>()) MIPS32Fixup();
    590   switch (Reloc) {
    591   case RelocOp::RO_Hi:
    592     Fixup->set_kind(llvm::ELF::R_MIPS_HI16);
    593     break;
    594   case RelocOp::RO_Lo:
    595     Fixup->set_kind(llvm::ELF::R_MIPS_LO16);
    596     break;
    597   case RelocOp::RO_Jal:
    598     Fixup->set_kind(llvm::ELF::R_MIPS_26);
    599     break;
    600   default:
    601     llvm::report_fatal_error("Fixup: Invalid Reloc type");
    602     break;
    603   }
    604   Fixup->set_value(RelOp);
    605   Buffer.installFixup(Fixup);
    606   return Fixup;
    607 }
    608 
    609 size_t MIPS32Fixup::emit(GlobalContext *Ctx, const Assembler &Asm) const {
    610   if (!BuildDefs::dump())
    611     return InstMIPS32::InstSize;
    612   Ostream &Str = Ctx->getStrEmit();
    613   IValueT Inst = Asm.load<IValueT>(position());
    614   const auto Symbol = symbol().toString();
    615   Str << "\t"
    616       << ".word " << llvm::format_hex(Inst, 8) << " # ";
    617   switch (kind()) {
    618   case llvm::ELF::R_MIPS_HI16:
    619     Str << "R_MIPS_HI16 ";
    620     break;
    621   case llvm::ELF::R_MIPS_LO16:
    622     Str << "R_MIPS_LO16 ";
    623     break;
    624   case llvm::ELF::R_MIPS_26:
    625     Str << "R_MIPS_26 ";
    626     break;
    627   default:
    628     Str << "Unknown ";
    629     break;
    630   }
    631   Str << Symbol << "\n";
    632   return InstMIPS32::InstSize;
    633 }
    634 
    635 void MIPS32Fixup::emitOffset(Assembler *Asm) const {
    636   const IValueT Inst = Asm->load<IValueT>(position());
    637   IValueT ImmMask = 0;
    638   const IValueT Imm = offset();
    639   if (kind() == llvm::ELF::R_MIPS_26) {
    640     ImmMask = 0x03FFFFFF;
    641   } else {
    642     ImmMask = 0x0000FFFF;
    643   }
    644   Asm->store(position(), (Inst & ~ImmMask) | (Imm & ImmMask));
    645 }
    646 
    647 void AssemblerMIPS32::jal(const ConstantRelocatable *Target) {
    648   IValueT Opcode = 0x0C000000;
    649   emitFixup(createMIPS32Fixup(RelocOp::RO_Jal, Target));
    650   emitInst(Opcode);
    651   nop();
    652 }
    653 
    654 void AssemblerMIPS32::jalr(const Operand *OpRs, const Operand *OpRd) {
    655   IValueT Opcode = 0x00000009;
    656   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "jalr");
    657   const IValueT Rd =
    658       (OpRd == nullptr) ? 31 : encodeGPRegister(OpRd, "Rd", "jalr");
    659   Opcode |= Rd << 11;
    660   Opcode |= Rs << 21;
    661   emitInst(Opcode);
    662   nop();
    663 }
    664 
    665 void AssemblerMIPS32::lui(const Operand *OpRt, const Operand *OpImm,
    666                           const RelocOp Reloc) {
    667   IValueT Opcode = 0x3C000000;
    668   const IValueT Rt = encodeGPRegister(OpRt, "Rt", "lui");
    669   IValueT Imm16 = 0;
    670 
    671   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) {
    672     emitFixup(createMIPS32Fixup(Reloc, OpRel));
    673   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) {
    674     Imm16 = C32->getValue();
    675   } else {
    676     llvm::report_fatal_error("lui: Invalid 2nd operand");
    677   }
    678 
    679   Opcode |= Rt << 16;
    680   Opcode |= Imm16;
    681   emitInst(Opcode);
    682 }
    683 
    684 void AssemblerMIPS32::ldc1(const Operand *OpRt, const Operand *OpBase,
    685                            const Operand *OpOff, const RelocOp Reloc) {
    686   IValueT Opcode = 0xD4000000;
    687   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "ldc1");
    688   const IValueT Base = encodeGPRegister(OpBase, "Base", "ldc1");
    689   IValueT Imm16 = 0;
    690 
    691   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
    692     emitFixup(createMIPS32Fixup(Reloc, OpRel));
    693   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
    694     Imm16 = C32->getValue();
    695   } else {
    696     llvm::report_fatal_error("ldc1: Invalid 2nd operand");
    697   }
    698 
    699   Opcode |= Base << 21;
    700   Opcode |= Rt << 16;
    701   Opcode |= Imm16;
    702   emitInst(Opcode);
    703 }
    704 
    705 void AssemblerMIPS32::ll(const Operand *OpRt, const Operand *OpBase,
    706                          const uint32_t Offset) {
    707   static constexpr IValueT Opcode = 0xC0000000;
    708   emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "ll");
    709 }
    710 
    711 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
    712                          const uint32_t Offset) {
    713   switch (OpRt->getType()) {
    714   case IceType_i1:
    715   case IceType_i8: {
    716     static constexpr IValueT Opcode = 0x80000000;
    717     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb");
    718     break;
    719   }
    720   case IceType_i16: {
    721     static constexpr IValueT Opcode = 0x84000000;
    722     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh");
    723     break;
    724   }
    725   case IceType_i32: {
    726     static constexpr IValueT Opcode = 0x8C000000;
    727     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
    728     break;
    729   }
    730   case IceType_f32: {
    731     static constexpr IValueT Opcode = 0xC4000000;
    732     emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1");
    733     break;
    734   }
    735   case IceType_f64: {
    736     static constexpr IValueT Opcode = 0xD4000000;
    737     emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1");
    738     break;
    739   }
    740   default: { UnimplementedError(getFlags()); }
    741   }
    742 }
    743 
    744 void AssemblerMIPS32::lwc1(const Operand *OpRt, const Operand *OpBase,
    745                            const Operand *OpOff, const RelocOp Reloc) {
    746   IValueT Opcode = 0xC4000000;
    747   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "lwc1");
    748   const IValueT Base = encodeGPRegister(OpBase, "Base", "lwc1");
    749   IValueT Imm16 = 0;
    750 
    751   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
    752     emitFixup(createMIPS32Fixup(Reloc, OpRel));
    753   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
    754     Imm16 = C32->getValue();
    755   } else {
    756     llvm::report_fatal_error("lwc1: Invalid 2nd operand");
    757   }
    758 
    759   Opcode |= Base << 21;
    760   Opcode |= Rt << 16;
    761   Opcode |= Imm16;
    762   emitInst(Opcode);
    763 }
    764 
    765 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
    766   static constexpr IValueT Opcode = 0x44000000;
    767   emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
    768 }
    769 
    770 void AssemblerMIPS32::mfhi(const Operand *OpRd) {
    771   IValueT Opcode = 0x000000010;
    772   IValueT Rd = encodeGPRegister(OpRd, "Rd", "mfhi");
    773   Opcode |= Rd << 11;
    774   emitInst(Opcode);
    775 }
    776 
    777 void AssemblerMIPS32::mflo(const Operand *OpRd) {
    778   IValueT Opcode = 0x000000012;
    779   IValueT Rd = encodeGPRegister(OpRd, "Rd", "mflo");
    780   Opcode |= Rd << 11;
    781   emitInst(Opcode);
    782 }
    783 
    784 void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) {
    785   static constexpr IValueT Opcode = 0x44000006;
    786   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d");
    787 }
    788 
    789 void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) {
    790   static constexpr IValueT Opcode = 0x44000006;
    791   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s");
    792 }
    793 
    794 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
    795 
    796   const Type DstType = OpRd->getType();
    797   const Type SrcType = OpRs->getType();
    798 
    799   if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
    800       (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
    801     if (isScalarFloatingType(DstType)) {
    802       mtc1(OpRs, OpRd);
    803     } else {
    804       mfc1(OpRd, OpRs);
    805     }
    806   } else {
    807     switch (DstType) {
    808     case IceType_f32:
    809       mov_s(OpRd, OpRs);
    810       break;
    811     case IceType_f64:
    812       mov_d(OpRd, OpRs);
    813       break;
    814     case IceType_i1:
    815     case IceType_i8:
    816     case IceType_i16:
    817     case IceType_i32: {
    818       IValueT Opcode = 0x00000021;
    819       const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
    820       const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
    821       const IValueT Rt = 0; // $0
    822       Opcode |= Rs << 21;
    823       Opcode |= Rt << 16;
    824       Opcode |= Rd << 11;
    825       emitInst(Opcode);
    826       break;
    827     }
    828     default: { UnimplementedError(getFlags()); }
    829     }
    830   }
    831 }
    832 
    833 void AssemblerMIPS32::movf(const Operand *OpRd, const Operand *OpRs,
    834                            const Operand *OpCc) {
    835   IValueT Opcode = 0x00000001;
    836   const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movf");
    837   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movf");
    838   OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0;
    839   if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) {
    840     Cc = OpFCC->getFCC();
    841   }
    842   const IValueT InstEncodingFalse = 0;
    843   Opcode |= Rd << 11;
    844   Opcode |= InstEncodingFalse << 16;
    845   Opcode |= Cc << 18;
    846   Opcode |= Rs << 21;
    847   emitInst(Opcode);
    848 }
    849 
    850 void AssemblerMIPS32::movn(const Operand *OpRd, const Operand *OpRs,
    851                            const Operand *OpRt) {
    852   static constexpr IValueT Opcode = 0x0000000B;
    853   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movn");
    854 }
    855 
    856 void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs,
    857                              const Operand *OpFt) {
    858   static constexpr IValueT Opcode = 0x44000013;
    859   emitCOP1FmtRtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movn.d");
    860 }
    861 
    862 void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs,
    863                              const Operand *OpFt) {
    864   static constexpr IValueT Opcode = 0x44000013;
    865   emitCOP1FmtRtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s");
    866 }
    867 
    868 void AssemblerMIPS32::movt(const Operand *OpRd, const Operand *OpRs,
    869                            const Operand *OpCc) {
    870   IValueT Opcode = 0x00000001;
    871   const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movt");
    872   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movt");
    873   OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0;
    874   if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) {
    875     Cc = OpFCC->getFCC();
    876   }
    877   const IValueT InstEncodingTrue = 1;
    878   Opcode |= Rd << 11;
    879   Opcode |= InstEncodingTrue << 16;
    880   Opcode |= Cc << 18;
    881   Opcode |= Rs << 21;
    882   emitInst(Opcode);
    883 }
    884 
    885 void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs,
    886                              const Operand *OpFt) {
    887   static constexpr IValueT Opcode = 0x44000012;
    888   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movz.d");
    889 }
    890 
    891 void AssemblerMIPS32::movz(const Operand *OpRd, const Operand *OpRs,
    892                            const Operand *OpRt) {
    893   static constexpr IValueT Opcode = 0x0000000A;
    894   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movz");
    895 }
    896 
    897 void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs,
    898                              const Operand *OpFt) {
    899   static constexpr IValueT Opcode = 0x44000012;
    900   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s");
    901 }
    902 
    903 void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) {
    904   static constexpr IValueT Opcode = 0x44800000;
    905   emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1");
    906 }
    907 
    908 void AssemblerMIPS32::mthi(const Operand *OpRs) {
    909   IValueT Opcode = 0x000000011;
    910   IValueT Rs = encodeGPRegister(OpRs, "Rs", "mthi");
    911   Opcode |= Rs << 21;
    912   emitInst(Opcode);
    913 }
    914 
    915 void AssemblerMIPS32::mtlo(const Operand *OpRs) {
    916   IValueT Opcode = 0x000000013;
    917   IValueT Rs = encodeGPRegister(OpRs, "Rs", "mtlo");
    918   Opcode |= Rs << 21;
    919   emitInst(Opcode);
    920 }
    921 
    922 void AssemblerMIPS32::mul(const Operand *OpRd, const Operand *OpRs,
    923                           const Operand *OpRt) {
    924   static constexpr IValueT Opcode = 0x70000002;
    925   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "mul");
    926 }
    927 
    928 void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs,
    929                             const Operand *OpFt) {
    930   static constexpr IValueT Opcode = 0x44000002;
    931   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d");
    932 }
    933 
    934 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs,
    935                             const Operand *OpFt) {
    936   static constexpr IValueT Opcode = 0x44000002;
    937   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s");
    938 }
    939 
    940 void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) {
    941   static constexpr IValueT Opcode = 0x00000018;
    942   emitRsRt(Opcode, OpRs, OpRt, "mult");
    943 }
    944 
    945 void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) {
    946   static constexpr IValueT Opcode = 0x00000019;
    947   emitRsRt(Opcode, OpRs, OpRt, "multu");
    948 }
    949 
    950 void AssemblerMIPS32::nor(const Operand *OpRd, const Operand *OpRs,
    951                           const Operand *OpRt) {
    952   static constexpr IValueT Opcode = 0x00000027;
    953   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "nor");
    954 }
    955 
    956 void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
    957                           const Operand *OpRt) {
    958   static constexpr IValueT Opcode = 0x00000025;
    959   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or");
    960 }
    961 
    962 void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs,
    963                           const uint32_t Imm) {
    964   static constexpr IValueT Opcode = 0x34000000;
    965   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
    966 }
    967 
    968 void AssemblerMIPS32::ret(void) {
    969   static constexpr IValueT Opcode = 0x03E00008; // JR $31
    970   emitInst(Opcode);
    971   nop(); // delay slot
    972 }
    973 
    974 void AssemblerMIPS32::sc(const Operand *OpRt, const Operand *OpBase,
    975                          const uint32_t Offset) {
    976   static constexpr IValueT Opcode = 0xE0000000;
    977   emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sc");
    978 }
    979 
    980 void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt,
    981                           const uint32_t Sa) {
    982   static constexpr IValueT Opcode = 0x00000000;
    983   emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
    984 }
    985 
    986 void AssemblerMIPS32::sllv(const Operand *OpRd, const Operand *OpRt,
    987                            const Operand *OpRs) {
    988   static constexpr IValueT Opcode = 0x00000004;
    989   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sllv");
    990 }
    991 
    992 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
    993                           const Operand *OpRt) {
    994   static constexpr IValueT Opcode = 0x0000002A;
    995   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
    996 }
    997 
    998 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs,
    999                            const uint32_t Imm) {
   1000   static constexpr IValueT Opcode = 0x28000000;
   1001   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti");
   1002 }
   1003 
   1004 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs,
   1005                            const Operand *OpRt) {
   1006   static constexpr IValueT Opcode = 0x0000002B;
   1007   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
   1008 }
   1009 
   1010 void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs,
   1011                             const uint32_t Imm) {
   1012   static constexpr IValueT Opcode = 0x2c000000;
   1013   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu");
   1014 }
   1015 
   1016 void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) {
   1017   static constexpr IValueT Opcode = 0x44000004;
   1018   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d");
   1019 }
   1020 
   1021 void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) {
   1022   static constexpr IValueT Opcode = 0x44000004;
   1023   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s");
   1024 }
   1025 
   1026 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
   1027                           const uint32_t Sa) {
   1028   static constexpr IValueT Opcode = 0x00000003;
   1029   emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra");
   1030 }
   1031 
   1032 void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt,
   1033                           const uint32_t Sa) {
   1034   static constexpr IValueT Opcode = 0x00000002;
   1035   emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
   1036 }
   1037 
   1038 void AssemblerMIPS32::srav(const Operand *OpRd, const Operand *OpRt,
   1039                            const Operand *OpRs) {
   1040   static constexpr IValueT Opcode = 0x00000007;
   1041   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srav");
   1042 }
   1043 
   1044 void AssemblerMIPS32::srlv(const Operand *OpRd, const Operand *OpRt,
   1045                            const Operand *OpRs) {
   1046   static constexpr IValueT Opcode = 0x00000006;
   1047   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srlv");
   1048 }
   1049 
   1050 void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs,
   1051                             const Operand *OpFt) {
   1052   static constexpr IValueT Opcode = 0x44000001;
   1053   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d");
   1054 }
   1055 
   1056 void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs,
   1057                             const Operand *OpFt) {
   1058   static constexpr IValueT Opcode = 0x44000001;
   1059   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s");
   1060 }
   1061 
   1062 void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs,
   1063                            const Operand *OpRt) {
   1064   static constexpr IValueT Opcode = 0x00000023;
   1065   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu");
   1066 }
   1067 
   1068 void AssemblerMIPS32::sdc1(const Operand *OpRt, const Operand *OpBase,
   1069                            const Operand *OpOff, const RelocOp Reloc) {
   1070   IValueT Opcode = 0xF4000000;
   1071   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "sdc1");
   1072   const IValueT Base = encodeGPRegister(OpBase, "Base", "sdc1");
   1073   IValueT Imm16 = 0;
   1074 
   1075   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
   1076     emitFixup(createMIPS32Fixup(Reloc, OpRel));
   1077   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
   1078     Imm16 = C32->getValue();
   1079   } else {
   1080     llvm::report_fatal_error("sdc1: Invalid 2nd operand");
   1081   }
   1082 
   1083   Opcode |= Base << 21;
   1084   Opcode |= Rt << 16;
   1085   Opcode |= Imm16;
   1086   emitInst(Opcode);
   1087 }
   1088 
   1089 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
   1090                          const uint32_t Offset) {
   1091   switch (OpRt->getType()) {
   1092   case IceType_i1:
   1093   case IceType_i8: {
   1094     static constexpr IValueT Opcode = 0xA0000000;
   1095     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb");
   1096     break;
   1097   }
   1098   case IceType_i16: {
   1099     static constexpr IValueT Opcode = 0xA4000000;
   1100     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh");
   1101     break;
   1102   }
   1103   case IceType_i32: {
   1104     static constexpr IValueT Opcode = 0xAC000000;
   1105     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
   1106     break;
   1107   }
   1108   case IceType_f32: {
   1109     static constexpr IValueT Opcode = 0xE4000000;
   1110     emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1");
   1111     break;
   1112   }
   1113   case IceType_f64: {
   1114     static constexpr IValueT Opcode = 0xF4000000;
   1115     emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1");
   1116     break;
   1117   }
   1118   default: { UnimplementedError(getFlags()); }
   1119   }
   1120 }
   1121 
   1122 void AssemblerMIPS32::swc1(const Operand *OpRt, const Operand *OpBase,
   1123                            const Operand *OpOff, const RelocOp Reloc) {
   1124   IValueT Opcode = 0xE4000000;
   1125   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "swc1");
   1126   const IValueT Base = encodeGPRegister(OpBase, "Base", "swc1");
   1127   IValueT Imm16 = 0;
   1128 
   1129   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
   1130     emitFixup(createMIPS32Fixup(Reloc, OpRel));
   1131   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
   1132     Imm16 = C32->getValue();
   1133   } else {
   1134     llvm::report_fatal_error("swc1: Invalid 2nd operand");
   1135   }
   1136 
   1137   Opcode |= Base << 21;
   1138   Opcode |= Rt << 16;
   1139   Opcode |= Imm16;
   1140   emitInst(Opcode);
   1141 }
   1142 
   1143 void AssemblerMIPS32::sync() {
   1144   static constexpr IValueT Opcode = 0x0000000f;
   1145   emitInst(Opcode);
   1146 }
   1147 
   1148 void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt,
   1149                           const uint32_t TrapCode) {
   1150   IValueT Opcode = 0x00000034;
   1151   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq");
   1152   const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq");
   1153   Opcode |= (TrapCode & 0xFFFFF) << 6;
   1154   Opcode |= Rt << 16;
   1155   Opcode |= Rs << 21;
   1156   emitInst(Opcode);
   1157 }
   1158 
   1159 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) {
   1160   static constexpr IValueT Opcode = 0x4400000D;
   1161   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d");
   1162 }
   1163 
   1164 void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) {
   1165   static constexpr IValueT Opcode = 0x4400000D;
   1166   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s");
   1167 }
   1168 
   1169 void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) {
   1170   static constexpr IValueT Opcode = 0x4400000D;
   1171   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "trunc.w.d");
   1172 }
   1173 
   1174 void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) {
   1175   static constexpr IValueT Opcode = 0x4400000D;
   1176   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "trunc.w.s");
   1177 }
   1178 
   1179 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
   1180                            const Operand *OpRt) {
   1181   static constexpr IValueT Opcode = 0x00000026;
   1182   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
   1183 }
   1184 
   1185 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs,
   1186                            const uint32_t Imm) {
   1187   static constexpr IValueT Opcode = 0x38000000;
   1188   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
   1189 }
   1190 
   1191 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
   1192                              const Operand *OpRt, IOffsetT Offset) {
   1193   IValueT Opcode = 0;
   1194 
   1195   switch (Cond) {
   1196   default:
   1197     break;
   1198   case CondMIPS32::AL:
   1199   case CondMIPS32::EQ:
   1200   case CondMIPS32::EQZ:
   1201     Opcode = 0x10000000;
   1202     break;
   1203   case CondMIPS32::NE:
   1204   case CondMIPS32::NEZ:
   1205     Opcode = 0x14000000;
   1206     break;
   1207   case CondMIPS32::LEZ:
   1208     Opcode = 0x18000000;
   1209     break;
   1210   case CondMIPS32::LTZ:
   1211     Opcode = 0x04000000;
   1212     break;
   1213   case CondMIPS32::GEZ:
   1214     Opcode = 0x04010000;
   1215     break;
   1216   case CondMIPS32::GTZ:
   1217     Opcode = 0x1C000000;
   1218     break;
   1219   }
   1220 
   1221   if (Opcode == 0) {
   1222     llvm::report_fatal_error("Branch: Invalid condition");
   1223   }
   1224 
   1225   if (OpRs != nullptr) {
   1226     IValueT Rs = encodeGPRegister(OpRs, "Rs", "branch");
   1227     Opcode |= Rs << 21;
   1228   }
   1229 
   1230   if (OpRt != nullptr) {
   1231     IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch");
   1232     Opcode |= Rt << 16;
   1233   }
   1234 
   1235   Opcode = encodeBranchOffset(Offset, Opcode);
   1236   emitInst(Opcode);
   1237   nop(); // delay slot
   1238 }
   1239 
   1240 void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
   1241                           const Operand *OpRt, Label *TargetLabel) {
   1242   if (TargetLabel->isBound()) {
   1243     const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
   1244     emitBr(Cond, OpRs, OpRt, Dest);
   1245     return;
   1246   }
   1247   const IOffsetT Position = Buffer.size();
   1248   IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
   1249   if (PrevPosition != 0)
   1250     PrevPosition = Position - PrevPosition;
   1251   emitBr(Cond, OpRs, OpRt, PrevPosition);
   1252   TargetLabel->linkTo(*this, Position);
   1253 }
   1254 
   1255 void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
   1256                           Label *TargetLabel) {
   1257   static constexpr Operand *OpRtNone = nullptr;
   1258   if (TargetLabel->isBound()) {
   1259     const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
   1260     emitBr(Cond, OpRs, OpRtNone, Dest);
   1261     return;
   1262   }
   1263   const IOffsetT Position = Buffer.size();
   1264   IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
   1265   if (PrevPosition)
   1266     PrevPosition = Position - PrevPosition;
   1267   emitBr(Cond, OpRs, OpRtNone, PrevPosition);
   1268   TargetLabel->linkTo(*this, Position);
   1269 }
   1270 
   1271 } // end of namespace MIPS32
   1272 } // end of namespace Ice
   1273