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