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: {
741     UnimplementedError(getFlags());
742   }
743   }
744 }
745 
lwc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)746 void AssemblerMIPS32::lwc1(const Operand *OpRt, const Operand *OpBase,
747                            const Operand *OpOff, const RelocOp Reloc) {
748   IValueT Opcode = 0xC4000000;
749   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "lwc1");
750   const IValueT Base = encodeGPRegister(OpBase, "Base", "lwc1");
751   IValueT Imm16 = 0;
752 
753   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
754     emitFixup(createMIPS32Fixup(Reloc, OpRel));
755   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
756     Imm16 = C32->getValue();
757   } else {
758     llvm::report_fatal_error("lwc1: Invalid 2nd operand");
759   }
760 
761   Opcode |= Base << 21;
762   Opcode |= Rt << 16;
763   Opcode |= Imm16;
764   emitInst(Opcode);
765 }
766 
mfc1(const Operand * OpRt,const Operand * OpFs)767 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
768   static constexpr IValueT Opcode = 0x44000000;
769   emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
770 }
771 
mfhi(const Operand * OpRd)772 void AssemblerMIPS32::mfhi(const Operand *OpRd) {
773   IValueT Opcode = 0x000000010;
774   IValueT Rd = encodeGPRegister(OpRd, "Rd", "mfhi");
775   Opcode |= Rd << 11;
776   emitInst(Opcode);
777 }
778 
mflo(const Operand * OpRd)779 void AssemblerMIPS32::mflo(const Operand *OpRd) {
780   IValueT Opcode = 0x000000012;
781   IValueT Rd = encodeGPRegister(OpRd, "Rd", "mflo");
782   Opcode |= Rd << 11;
783   emitInst(Opcode);
784 }
785 
mov_d(const Operand * OpFd,const Operand * OpFs)786 void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) {
787   static constexpr IValueT Opcode = 0x44000006;
788   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d");
789 }
790 
mov_s(const Operand * OpFd,const Operand * OpFs)791 void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) {
792   static constexpr IValueT Opcode = 0x44000006;
793   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s");
794 }
795 
move(const Operand * OpRd,const Operand * OpRs)796 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
797 
798   const Type DstType = OpRd->getType();
799   const Type SrcType = OpRs->getType();
800 
801   if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
802       (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
803     if (isScalarFloatingType(DstType)) {
804       mtc1(OpRs, OpRd);
805     } else {
806       mfc1(OpRd, OpRs);
807     }
808   } else {
809     switch (DstType) {
810     case IceType_f32:
811       mov_s(OpRd, OpRs);
812       break;
813     case IceType_f64:
814       mov_d(OpRd, OpRs);
815       break;
816     case IceType_i1:
817     case IceType_i8:
818     case IceType_i16:
819     case IceType_i32: {
820       IValueT Opcode = 0x00000021;
821       const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
822       const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
823       const IValueT Rt = 0; // $0
824       Opcode |= Rs << 21;
825       Opcode |= Rt << 16;
826       Opcode |= Rd << 11;
827       emitInst(Opcode);
828       break;
829     }
830     default: {
831       UnimplementedError(getFlags());
832     }
833     }
834   }
835 }
836 
movf(const Operand * OpRd,const Operand * OpRs,const Operand * OpCc)837 void AssemblerMIPS32::movf(const Operand *OpRd, const Operand *OpRs,
838                            const Operand *OpCc) {
839   IValueT Opcode = 0x00000001;
840   const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movf");
841   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movf");
842   OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0;
843   if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) {
844     Cc = OpFCC->getFCC();
845   }
846   const IValueT InstEncodingFalse = 0;
847   Opcode |= Rd << 11;
848   Opcode |= InstEncodingFalse << 16;
849   Opcode |= Cc << 18;
850   Opcode |= Rs << 21;
851   emitInst(Opcode);
852 }
853 
movn(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)854 void AssemblerMIPS32::movn(const Operand *OpRd, const Operand *OpRs,
855                            const Operand *OpRt) {
856   static constexpr IValueT Opcode = 0x0000000B;
857   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movn");
858 }
859 
movn_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)860 void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs,
861                              const Operand *OpFt) {
862   static constexpr IValueT Opcode = 0x44000013;
863   emitCOP1FmtRtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movn.d");
864 }
865 
movn_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)866 void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs,
867                              const Operand *OpFt) {
868   static constexpr IValueT Opcode = 0x44000013;
869   emitCOP1FmtRtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s");
870 }
871 
movt(const Operand * OpRd,const Operand * OpRs,const Operand * OpCc)872 void AssemblerMIPS32::movt(const Operand *OpRd, const Operand *OpRs,
873                            const Operand *OpCc) {
874   IValueT Opcode = 0x00000001;
875   const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movt");
876   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movt");
877   OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0;
878   if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) {
879     Cc = OpFCC->getFCC();
880   }
881   const IValueT InstEncodingTrue = 1;
882   Opcode |= Rd << 11;
883   Opcode |= InstEncodingTrue << 16;
884   Opcode |= Cc << 18;
885   Opcode |= Rs << 21;
886   emitInst(Opcode);
887 }
888 
movz_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)889 void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs,
890                              const Operand *OpFt) {
891   static constexpr IValueT Opcode = 0x44000012;
892   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movz.d");
893 }
894 
movz(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)895 void AssemblerMIPS32::movz(const Operand *OpRd, const Operand *OpRs,
896                            const Operand *OpRt) {
897   static constexpr IValueT Opcode = 0x0000000A;
898   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movz");
899 }
900 
movz_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)901 void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs,
902                              const Operand *OpFt) {
903   static constexpr IValueT Opcode = 0x44000012;
904   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s");
905 }
906 
mtc1(const Operand * OpRt,const Operand * OpFs)907 void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) {
908   static constexpr IValueT Opcode = 0x44800000;
909   emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1");
910 }
911 
mthi(const Operand * OpRs)912 void AssemblerMIPS32::mthi(const Operand *OpRs) {
913   IValueT Opcode = 0x000000011;
914   IValueT Rs = encodeGPRegister(OpRs, "Rs", "mthi");
915   Opcode |= Rs << 21;
916   emitInst(Opcode);
917 }
918 
mtlo(const Operand * OpRs)919 void AssemblerMIPS32::mtlo(const Operand *OpRs) {
920   IValueT Opcode = 0x000000013;
921   IValueT Rs = encodeGPRegister(OpRs, "Rs", "mtlo");
922   Opcode |= Rs << 21;
923   emitInst(Opcode);
924 }
925 
mul(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)926 void AssemblerMIPS32::mul(const Operand *OpRd, const Operand *OpRs,
927                           const Operand *OpRt) {
928   static constexpr IValueT Opcode = 0x70000002;
929   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "mul");
930 }
931 
mul_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)932 void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs,
933                             const Operand *OpFt) {
934   static constexpr IValueT Opcode = 0x44000002;
935   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d");
936 }
937 
mul_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)938 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs,
939                             const Operand *OpFt) {
940   static constexpr IValueT Opcode = 0x44000002;
941   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s");
942 }
943 
mult(const Operand * OpRs,const Operand * OpRt)944 void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) {
945   static constexpr IValueT Opcode = 0x00000018;
946   emitRsRt(Opcode, OpRs, OpRt, "mult");
947 }
948 
multu(const Operand * OpRs,const Operand * OpRt)949 void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) {
950   static constexpr IValueT Opcode = 0x00000019;
951   emitRsRt(Opcode, OpRs, OpRt, "multu");
952 }
953 
nor(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)954 void AssemblerMIPS32::nor(const Operand *OpRd, const Operand *OpRs,
955                           const Operand *OpRt) {
956   static constexpr IValueT Opcode = 0x00000027;
957   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "nor");
958 }
959 
or_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)960 void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
961                           const Operand *OpRt) {
962   static constexpr IValueT Opcode = 0x00000025;
963   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or");
964 }
965 
ori(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)966 void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs,
967                           const uint32_t Imm) {
968   static constexpr IValueT Opcode = 0x34000000;
969   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
970 }
971 
ret(void)972 void AssemblerMIPS32::ret(void) {
973   static constexpr IValueT Opcode = 0x03E00008; // JR $31
974   emitInst(Opcode);
975   nop(); // delay slot
976 }
977 
sc(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)978 void AssemblerMIPS32::sc(const Operand *OpRt, const Operand *OpBase,
979                          const uint32_t Offset) {
980   static constexpr IValueT Opcode = 0xE0000000;
981   emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sc");
982 }
983 
sll(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)984 void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt,
985                           const uint32_t Sa) {
986   static constexpr IValueT Opcode = 0x00000000;
987   emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
988 }
989 
sllv(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)990 void AssemblerMIPS32::sllv(const Operand *OpRd, const Operand *OpRt,
991                            const Operand *OpRs) {
992   static constexpr IValueT Opcode = 0x00000004;
993   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sllv");
994 }
995 
slt(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)996 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
997                           const Operand *OpRt) {
998   static constexpr IValueT Opcode = 0x0000002A;
999   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
1000 }
1001 
slti(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)1002 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs,
1003                            const uint32_t Imm) {
1004   static constexpr IValueT Opcode = 0x28000000;
1005   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti");
1006 }
1007 
sltu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)1008 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs,
1009                            const Operand *OpRt) {
1010   static constexpr IValueT Opcode = 0x0000002B;
1011   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
1012 }
1013 
sltiu(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)1014 void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs,
1015                             const uint32_t Imm) {
1016   static constexpr IValueT Opcode = 0x2c000000;
1017   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu");
1018 }
1019 
sqrt_d(const Operand * OpFd,const Operand * OpFs)1020 void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) {
1021   static constexpr IValueT Opcode = 0x44000004;
1022   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d");
1023 }
1024 
sqrt_s(const Operand * OpFd,const Operand * OpFs)1025 void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) {
1026   static constexpr IValueT Opcode = 0x44000004;
1027   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s");
1028 }
1029 
sra(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)1030 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
1031                           const uint32_t Sa) {
1032   static constexpr IValueT Opcode = 0x00000003;
1033   emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra");
1034 }
1035 
srl(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)1036 void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt,
1037                           const uint32_t Sa) {
1038   static constexpr IValueT Opcode = 0x00000002;
1039   emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
1040 }
1041 
srav(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)1042 void AssemblerMIPS32::srav(const Operand *OpRd, const Operand *OpRt,
1043                            const Operand *OpRs) {
1044   static constexpr IValueT Opcode = 0x00000007;
1045   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srav");
1046 }
1047 
srlv(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)1048 void AssemblerMIPS32::srlv(const Operand *OpRd, const Operand *OpRt,
1049                            const Operand *OpRs) {
1050   static constexpr IValueT Opcode = 0x00000006;
1051   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srlv");
1052 }
1053 
sub_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)1054 void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs,
1055                             const Operand *OpFt) {
1056   static constexpr IValueT Opcode = 0x44000001;
1057   emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d");
1058 }
1059 
sub_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)1060 void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs,
1061                             const Operand *OpFt) {
1062   static constexpr IValueT Opcode = 0x44000001;
1063   emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s");
1064 }
1065 
subu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)1066 void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs,
1067                            const Operand *OpRt) {
1068   static constexpr IValueT Opcode = 0x00000023;
1069   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu");
1070 }
1071 
sdc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)1072 void AssemblerMIPS32::sdc1(const Operand *OpRt, const Operand *OpBase,
1073                            const Operand *OpOff, const RelocOp Reloc) {
1074   IValueT Opcode = 0xF4000000;
1075   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "sdc1");
1076   const IValueT Base = encodeGPRegister(OpBase, "Base", "sdc1");
1077   IValueT Imm16 = 0;
1078 
1079   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
1080     emitFixup(createMIPS32Fixup(Reloc, OpRel));
1081   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
1082     Imm16 = C32->getValue();
1083   } else {
1084     llvm::report_fatal_error("sdc1: Invalid 2nd operand");
1085   }
1086 
1087   Opcode |= Base << 21;
1088   Opcode |= Rt << 16;
1089   Opcode |= Imm16;
1090   emitInst(Opcode);
1091 }
1092 
sw(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)1093 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
1094                          const uint32_t Offset) {
1095   switch (OpRt->getType()) {
1096   case IceType_i1:
1097   case IceType_i8: {
1098     static constexpr IValueT Opcode = 0xA0000000;
1099     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb");
1100     break;
1101   }
1102   case IceType_i16: {
1103     static constexpr IValueT Opcode = 0xA4000000;
1104     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh");
1105     break;
1106   }
1107   case IceType_i32: {
1108     static constexpr IValueT Opcode = 0xAC000000;
1109     emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
1110     break;
1111   }
1112   case IceType_f32: {
1113     static constexpr IValueT Opcode = 0xE4000000;
1114     emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1");
1115     break;
1116   }
1117   case IceType_f64: {
1118     static constexpr IValueT Opcode = 0xF4000000;
1119     emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1");
1120     break;
1121   }
1122   default: {
1123     UnimplementedError(getFlags());
1124   }
1125   }
1126 }
1127 
swc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)1128 void AssemblerMIPS32::swc1(const Operand *OpRt, const Operand *OpBase,
1129                            const Operand *OpOff, const RelocOp Reloc) {
1130   IValueT Opcode = 0xE4000000;
1131   const IValueT Rt = encodeFPRegister(OpRt, "Ft", "swc1");
1132   const IValueT Base = encodeGPRegister(OpBase, "Base", "swc1");
1133   IValueT Imm16 = 0;
1134 
1135   if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
1136     emitFixup(createMIPS32Fixup(Reloc, OpRel));
1137   } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
1138     Imm16 = C32->getValue();
1139   } else {
1140     llvm::report_fatal_error("swc1: Invalid 2nd operand");
1141   }
1142 
1143   Opcode |= Base << 21;
1144   Opcode |= Rt << 16;
1145   Opcode |= Imm16;
1146   emitInst(Opcode);
1147 }
1148 
sync()1149 void AssemblerMIPS32::sync() {
1150   static constexpr IValueT Opcode = 0x0000000f;
1151   emitInst(Opcode);
1152 }
1153 
teq(const Operand * OpRs,const Operand * OpRt,const uint32_t TrapCode)1154 void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt,
1155                           const uint32_t TrapCode) {
1156   IValueT Opcode = 0x00000034;
1157   const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq");
1158   const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq");
1159   Opcode |= (TrapCode & 0xFFFFF) << 6;
1160   Opcode |= Rt << 16;
1161   Opcode |= Rs << 21;
1162   emitInst(Opcode);
1163 }
1164 
trunc_l_d(const Operand * OpFd,const Operand * OpFs)1165 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) {
1166   static constexpr IValueT Opcode = 0x4400000D;
1167   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d");
1168 }
1169 
trunc_l_s(const Operand * OpFd,const Operand * OpFs)1170 void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) {
1171   static constexpr IValueT Opcode = 0x4400000D;
1172   emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s");
1173 }
1174 
trunc_w_d(const Operand * OpFd,const Operand * OpFs)1175 void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) {
1176   static constexpr IValueT Opcode = 0x4400000D;
1177   emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "trunc.w.d");
1178 }
1179 
trunc_w_s(const Operand * OpFd,const Operand * OpFs)1180 void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) {
1181   static constexpr IValueT Opcode = 0x4400000D;
1182   emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "trunc.w.s");
1183 }
1184 
xor_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)1185 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
1186                            const Operand *OpRt) {
1187   static constexpr IValueT Opcode = 0x00000026;
1188   emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
1189 }
1190 
xori(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)1191 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs,
1192                            const uint32_t Imm) {
1193   static constexpr IValueT Opcode = 0x38000000;
1194   emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
1195 }
1196 
emitBr(const CondMIPS32::Cond Cond,const Operand * OpRs,const Operand * OpRt,IOffsetT Offset)1197 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
1198                              const Operand *OpRt, IOffsetT Offset) {
1199   IValueT Opcode = 0;
1200 
1201   switch (Cond) {
1202   default:
1203     break;
1204   case CondMIPS32::AL:
1205   case CondMIPS32::EQ:
1206   case CondMIPS32::EQZ:
1207     Opcode = 0x10000000;
1208     break;
1209   case CondMIPS32::NE:
1210   case CondMIPS32::NEZ:
1211     Opcode = 0x14000000;
1212     break;
1213   case CondMIPS32::LEZ:
1214     Opcode = 0x18000000;
1215     break;
1216   case CondMIPS32::LTZ:
1217     Opcode = 0x04000000;
1218     break;
1219   case CondMIPS32::GEZ:
1220     Opcode = 0x04010000;
1221     break;
1222   case CondMIPS32::GTZ:
1223     Opcode = 0x1C000000;
1224     break;
1225   }
1226 
1227   if (Opcode == 0) {
1228     llvm::report_fatal_error("Branch: Invalid condition");
1229   }
1230 
1231   if (OpRs != nullptr) {
1232     IValueT Rs = encodeGPRegister(OpRs, "Rs", "branch");
1233     Opcode |= Rs << 21;
1234   }
1235 
1236   if (OpRt != nullptr) {
1237     IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch");
1238     Opcode |= Rt << 16;
1239   }
1240 
1241   Opcode = encodeBranchOffset(Offset, Opcode);
1242   emitInst(Opcode);
1243   nop(); // delay slot
1244 }
1245 
bcc(const CondMIPS32::Cond Cond,const Operand * OpRs,const Operand * OpRt,Label * TargetLabel)1246 void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
1247                           const Operand *OpRt, Label *TargetLabel) {
1248   if (TargetLabel->isBound()) {
1249     const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
1250     emitBr(Cond, OpRs, OpRt, Dest);
1251     return;
1252   }
1253   const IOffsetT Position = Buffer.size();
1254   IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
1255   if (PrevPosition != 0)
1256     PrevPosition = Position - PrevPosition;
1257   emitBr(Cond, OpRs, OpRt, PrevPosition);
1258   TargetLabel->linkTo(*this, Position);
1259 }
1260 
bzc(const CondMIPS32::Cond Cond,const Operand * OpRs,Label * TargetLabel)1261 void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
1262                           Label *TargetLabel) {
1263   static constexpr Operand *OpRtNone = nullptr;
1264   if (TargetLabel->isBound()) {
1265     const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
1266     emitBr(Cond, OpRs, OpRtNone, Dest);
1267     return;
1268   }
1269   const IOffsetT Position = Buffer.size();
1270   IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
1271   if (PrevPosition)
1272     PrevPosition = Position - PrevPosition;
1273   emitBr(Cond, OpRs, OpRtNone, PrevPosition);
1274   TargetLabel->linkTo(*this, Position);
1275 }
1276 
1277 } // end of namespace MIPS32
1278 } // end of namespace Ice
1279