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