• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
emitTextInst(const std::string & Text,SizeT InstSize)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 
getNonExecBundlePadding() const56 llvm::ArrayRef<uint8_t> AssemblerMIPS32::getNonExecBundlePadding() const {
57   return TrapBytes;
58 }
59 
trap()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 
nop()66 void AssemblerMIPS32::nop() { emitInst(0); }
67 
padWithNop(intptr_t Padding)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 
getOrCreateLabel(SizeT Number,LabelVector & Labels)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 
bindCfgNodeLabel(const CfgNode * Node)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.
assertCanEncodeBranchOffset(IOffsetT Offset)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 
encodeBranchOffset(IOffsetT Offset,IValueT Inst)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 
getEncodedGPRegNum(const Variable * Var)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 
getEncodedFPRegNum(const Variable * Var)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 
encodeOperand(const Operand * Opnd,IValueT & Value,RegSetWanted WantedRegSet)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 
encodeRegister(const Operand * OpReg,RegSetWanted WantedRegSet,const char * RegName,const char * InstName)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 
encodeGPRegister(const Operand * OpReg,const char * RegName,const char * InstName)172 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
173                          const char *InstName) {
174   return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
175 }
176 
encodeFPRegister(const Operand * OpReg,const char * RegName,const char * InstName)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 
decodeBranchOffset(IValueT Inst)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 
bind(Label * L)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 
emitRsRt(IValueT Opcode,const Operand * OpRs,const Operand * OpRt,const char * InsnName)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 
emitRtRsImm16(IValueT Opcode,const Operand * OpRt,const Operand * OpRs,const uint32_t Imm,const char * InsnName)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 
emitRtRsImm16Rel(IValueT Opcode,const Operand * OpRt,const Operand * OpRs,const Operand * OpImm,const RelocOp Reloc,const char * InsnName)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 
emitFtRsImm16(IValueT Opcode,const Operand * OpFt,const Operand * OpRs,const uint32_t Imm,const char * InsnName)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 
emitRdRtSa(IValueT Opcode,const Operand * OpRd,const Operand * OpRt,const uint32_t Sa,const char * InsnName)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 
emitRdRsRt(IValueT Opcode,const Operand * OpRd,const Operand * OpRs,const Operand * OpRt,const char * InsnName)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 
emitCOP1Fcmp(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFs,const Operand * OpFt,IValueT CC,const char * InsnName)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 
emitCOP1FmtFsFd(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFd,const Operand * OpFs,const char * InsnName)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 
emitCOP1FmtFtFsFd(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFd,const Operand * OpFs,const Operand * OpFt,const char * InsnName)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 
emitCOP1FmtRtFsFd(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFd,const Operand * OpFs,const Operand * OpRt,const char * InsnName)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 
emitCOP1MovRtFs(IValueT Opcode,const Operand * OpRt,const Operand * OpFs,const char * InsnName)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 
abs_d(const Operand * OpFd,const Operand * OpFs)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 
abs_s(const Operand * OpFd,const Operand * OpFs)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 
addi(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
add_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
add_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
addiu(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
addiu(const Operand * OpRt,const Operand * OpRs,const Operand * OpImm,const RelocOp Reloc)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 
addu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
and_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
andi(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
b(Label * TargetLabel)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 
c_eq_d(const Operand * OpFs,const Operand * OpFt)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 
c_eq_s(const Operand * OpFs,const Operand * OpFt)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 
c_ole_d(const Operand * OpFs,const Operand * OpFt)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 
c_ole_s(const Operand * OpFs,const Operand * OpFt)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 
c_olt_d(const Operand * OpFs,const Operand * OpFt)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 
c_olt_s(const Operand * OpFs,const Operand * OpFt)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 
c_ueq_d(const Operand * OpFs,const Operand * OpFt)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 
c_ueq_s(const Operand * OpFs,const Operand * OpFt)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 
c_ule_d(const Operand * OpFs,const Operand * OpFt)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 
c_ule_s(const Operand * OpFs,const Operand * OpFt)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 
c_ult_d(const Operand * OpFs,const Operand * OpFt)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 
c_ult_s(const Operand * OpFs,const Operand * OpFt)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 
c_un_d(const Operand * OpFs,const Operand * OpFt)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 
c_un_s(const Operand * OpFs,const Operand * OpFt)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 
clz(const Operand * OpRd,const Operand * OpRs)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 
cvt_d_l(const Operand * OpFd,const Operand * OpFs)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 
cvt_d_s(const Operand * OpFd,const Operand * OpFs)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 
cvt_d_w(const Operand * OpFd,const Operand * OpFs)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 
cvt_s_d(const Operand * OpFd,const Operand * OpFs)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 
cvt_s_l(const Operand * OpFd,const Operand * OpFs)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 
cvt_s_w(const Operand * OpFd,const Operand * OpFs)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 
div(const Operand * OpRs,const Operand * OpRt)565 void AssemblerMIPS32::div(const Operand *OpRs, const Operand *OpRt) {
566   static constexpr IValueT Opcode = 0x0000001A;
567   emitRsRt(Opcode, OpRs, OpRt, "div");
568 }
569 
div_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
div_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
divu(const Operand * OpRs,const Operand * OpRt)582 void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) {
583   static constexpr IValueT Opcode = 0x0000001B;
584   emitRsRt(Opcode, OpRs, OpRt, "divu");
585 }
586 
createMIPS32Fixup(const RelocOp Reloc,const Constant * RelOp)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 
emit(GlobalContext * Ctx,const Assembler & Asm) const609 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 
emitOffset(Assembler * Asm) const635 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 
jal(const ConstantRelocatable * Target)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 
jalr(const Operand * OpRs,const Operand * OpRd)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 
lui(const Operand * OpRt,const Operand * OpImm,const RelocOp Reloc)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 
ldc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)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 
ll(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)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 
lw(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)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 
lwc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)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 
mfc1(const Operand * OpRt,const Operand * OpFs)765 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
766   static constexpr IValueT Opcode = 0x44000000;
767   emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
768 }
769 
mfhi(const Operand * OpRd)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 
mflo(const Operand * OpRd)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 
mov_d(const Operand * OpFd,const Operand * OpFs)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 
mov_s(const Operand * OpFd,const Operand * OpFs)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 
move(const Operand * OpRd,const Operand * OpRs)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 
movf(const Operand * OpRd,const Operand * OpRs,const Operand * OpCc)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 
movn(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
movn_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
movn_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
movt(const Operand * OpRd,const Operand * OpRs,const Operand * OpCc)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 
movz_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
movz(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
movz_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
mtc1(const Operand * OpRt,const Operand * OpFs)903 void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) {
904   static constexpr IValueT Opcode = 0x44800000;
905   emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1");
906 }
907 
mthi(const Operand * OpRs)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 
mtlo(const Operand * OpRs)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 
mul(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
mul_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
mul_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
mult(const Operand * OpRs,const Operand * OpRt)940 void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) {
941   static constexpr IValueT Opcode = 0x00000018;
942   emitRsRt(Opcode, OpRs, OpRt, "mult");
943 }
944 
multu(const Operand * OpRs,const Operand * OpRt)945 void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) {
946   static constexpr IValueT Opcode = 0x00000019;
947   emitRsRt(Opcode, OpRs, OpRt, "multu");
948 }
949 
nor(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
or_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
ori(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
ret(void)968 void AssemblerMIPS32::ret(void) {
969   static constexpr IValueT Opcode = 0x03E00008; // JR $31
970   emitInst(Opcode);
971   nop(); // delay slot
972 }
973 
sc(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)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 
sll(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)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 
sllv(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)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 
slt(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
slti(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
sltu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
sltiu(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
sqrt_d(const Operand * OpFd,const Operand * OpFs)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 
sqrt_s(const Operand * OpFd,const Operand * OpFs)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 
sra(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)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 
srl(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)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 
srav(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)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 
srlv(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)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 
sub_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
sub_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)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 
subu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
sdc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)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 
sw(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)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 
swc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)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 
sync()1143 void AssemblerMIPS32::sync() {
1144   static constexpr IValueT Opcode = 0x0000000f;
1145   emitInst(Opcode);
1146 }
1147 
teq(const Operand * OpRs,const Operand * OpRt,const uint32_t TrapCode)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 
trunc_l_d(const Operand * OpFd,const Operand * OpFs)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 
trunc_l_s(const Operand * OpFd,const Operand * OpFs)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 
trunc_w_d(const Operand * OpFd,const Operand * OpFs)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 
trunc_w_s(const Operand * OpFd,const Operand * OpFs)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 
xor_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)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 
xori(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)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 
emitBr(const CondMIPS32::Cond Cond,const Operand * OpRs,const Operand * OpRt,IOffsetT Offset)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 
bcc(const CondMIPS32::Cond Cond,const Operand * OpRs,const Operand * OpRt,Label * TargetLabel)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 
bzc(const CondMIPS32::Cond Cond,const Operand * OpRs,Label * TargetLabel)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