1 //===- subzero/src/IceInstMips32.cpp - Mips32 instruction implementation --===//
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 InstMips32 and OperandMips32 classes, primarily the
12 /// constructors and the dump()/emit() methods.
13 ///
14 //===----------------------------------------------------------------------===//
15 #include "IceInstMIPS32.h"
16 #include "IceAssemblerMIPS32.h"
17 #include "IceCfg.h"
18 #include "IceCfgNode.h"
19 #include "IceInst.h"
20 #include "IceOperand.h"
21 #include "IceRegistersMIPS32.h"
22 #include "IceTargetLoweringMIPS32.h"
23 #include <limits>
24
25 namespace Ice {
26 namespace MIPS32 {
27
28 const struct InstMIPS32CondAttributes_ {
29 CondMIPS32::Cond Opposite;
30 const char *EmitString;
31 } InstMIPS32CondAttributes[] = {
32 #define X(tag, opp, emit) {CondMIPS32::opp, emit},
33 ICEINSTMIPS32COND_TABLE
34 #undef X
35 };
36
canHoldOffset(Type Ty,bool SignExt,int32_t Offset)37 bool OperandMIPS32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
38 (void)SignExt;
39 (void)Ty;
40 if ((std::numeric_limits<int16_t>::min() <= Offset) &&
41 (Offset <= std::numeric_limits<int16_t>::max()))
42 return true;
43 return false;
44 }
45
OperandMIPS32Mem(Cfg * Func,Type Ty,Variable * Base,Operand * ImmOffset,AddrMode Mode)46 OperandMIPS32Mem::OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base,
47 Operand *ImmOffset, AddrMode Mode)
48 : OperandMIPS32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Mode(Mode) {
49 // The Neg modes are only needed for Reg +/- Reg.
50 (void)Func;
51 // assert(!isNegAddrMode());
52 NumVars = 1;
53 Vars = &this->Base;
54 }
55
getWidthString(Type Ty)56 const char *InstMIPS32::getWidthString(Type Ty) {
57 (void)Ty;
58 return "TBD";
59 }
60
emit(const Cfg * Func) const61 template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
62 if (!BuildDefs::dump())
63 return;
64 Ostream &Str = Func->getContext()->getStrEmit();
65 assert(getSrcSize() == 1);
66 Str << "\t" << Opcode << "\t";
67 getDest()->emit(Func);
68 Str << ", ";
69 auto *Src0 = llvm::cast<Constant>(getSrc(0));
70 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
71 emitRelocOp(Str, Reloc);
72 Str << "(";
73 CR->emitWithoutPrefix(Func->getTarget());
74 Str << ")";
75 } else {
76 Src0->emit(Func);
77 }
78 }
79
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)80 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
81 const CfgNode *TargetFalse,
82 const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
83 : InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
84 TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {}
85
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,Operand * Src0,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)86 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
87 const CfgNode *TargetFalse, Operand *Src0,
88 const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
89 : InstMIPS32(Func, InstMIPS32::Br, 1, nullptr), TargetTrue(TargetTrue),
90 TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
91 addSource(Src0);
92 }
93
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,Operand * Src0,Operand * Src1,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)94 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
95 const CfgNode *TargetFalse, Operand *Src0,
96 Operand *Src1, const InstMIPS32Label *Label,
97 CondMIPS32::Cond Cond)
98 : InstMIPS32(Func, InstMIPS32::Br, 2, nullptr), TargetTrue(TargetTrue),
99 TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
100 addSource(Src0);
101 addSource(Src1);
102 }
103
getOppositeCondition(CondMIPS32::Cond Cond)104 CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
105 return InstMIPS32CondAttributes[Cond].Opposite;
106 }
107
optimizeBranch(const CfgNode * NextNode)108 bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
109 // If there is no next block, then there can be no fallthrough to optimize.
110 if (NextNode == nullptr)
111 return false;
112 // Intra-block conditional branches can't be optimized.
113 if (Label != nullptr)
114 return false;
115 // Unconditional branch to the next node can be removed.
116 if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
117 assert(getTargetTrue() == nullptr);
118 setDeleted();
119 return true;
120 }
121 // If there is no fallthrough node, such as a non-default case label for a
122 // switch instruction, then there is no opportunity to optimize.
123 if (getTargetTrue() == nullptr)
124 return false;
125 // If the fallthrough is to the next node, set fallthrough to nullptr to
126 // indicate.
127 if (getTargetTrue() == NextNode) {
128 TargetTrue = nullptr;
129 return true;
130 }
131 // If TargetFalse is the next node, and TargetTrue is not nullptr
132 // then invert the branch condition, swap the targets, and set new
133 // fallthrough to nullptr.
134 if (getTargetFalse() == NextNode) {
135 assert(Predicate != CondMIPS32::AL);
136 setPredicate(getOppositeCondition(getPredicate()));
137 TargetFalse = getTargetTrue();
138 TargetTrue = nullptr;
139 return true;
140 }
141 return false;
142 }
143
repointEdges(CfgNode * OldNode,CfgNode * NewNode)144 bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
145 bool Found = false;
146 if (TargetFalse == OldNode) {
147 TargetFalse = NewNode;
148 Found = true;
149 }
150 if (TargetTrue == OldNode) {
151 TargetTrue = NewNode;
152 Found = true;
153 }
154 return Found;
155 }
156
InstMIPS32Label(Cfg * Func,TargetMIPS32 * Target)157 InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
158 : InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
159 Number(Target->makeNextLabelNumber()) {
160 if (BuildDefs::dump()) {
161 Name = GlobalString::createWithString(
162 Func->getContext(),
163 ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
164 } else {
165 Name = GlobalString::createWithoutString(Func->getContext());
166 }
167 }
168
dump(const Cfg * Func) const169 void InstMIPS32Label::dump(const Cfg *Func) const {
170 if (!BuildDefs::dump())
171 return;
172 Ostream &Str = Func->getContext()->getStrDump();
173 Str << getLabelName() << ":";
174 }
175
emit(const Cfg * Func) const176 void InstMIPS32Label::emit(const Cfg *Func) const {
177 if (!BuildDefs::dump())
178 return;
179 Ostream &Str = Func->getContext()->getStrEmit();
180 Str << getLabelName() << ":";
181 }
182
emitIAS(const Cfg * Func) const183 void InstMIPS32Label::emitIAS(const Cfg *Func) const {
184 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
185 Asm->bindLocalLabel(this, Number);
186 }
187
InstMIPS32Call(Cfg * Func,Variable * Dest,Operand * CallTarget)188 InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
189 : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
190 HasSideEffects = true;
191 addSource(CallTarget);
192 }
193
InstMIPS32Mov(Cfg * Func,Variable * Dest,Operand * Src,Operand * Src2)194 InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src,
195 Operand *Src2)
196 : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
197 auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
198 auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
199
200 assert(Dest64 == nullptr || Src64 == nullptr);
201
202 if (Dest->getType() == IceType_f64 && Src2 != nullptr) {
203 addSource(Src);
204 addSource(Src2);
205 return;
206 }
207
208 if (Dest64 != nullptr) {
209 // this-> is needed below because there is a parameter named Dest.
210 this->Dest = Dest64->getLo();
211 DestHi = Dest64->getHi();
212 }
213
214 if (Src64 == nullptr) {
215 addSource(Src);
216 } else {
217 addSource(Src64->getLo());
218 addSource(Src64->getHi());
219 }
220 }
221
InstMIPS32MovFP64ToI64(Cfg * Func,Variable * Dst,Operand * Src,Int64Part Int64HiLo)222 InstMIPS32MovFP64ToI64::InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dst,
223 Operand *Src,
224 Int64Part Int64HiLo)
225 : InstMIPS32(Func, InstMIPS32::Mov_fp, 1, Dst), Int64HiLo(Int64HiLo) {
226 addSource(Src);
227 }
228
InstMIPS32Ret(Cfg * Func,Variable * RA,Variable * Source)229 InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
230 : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
231 addSource(RA);
232 if (Source)
233 addSource(Source);
234 }
235
236 // ======================== Dump routines ======================== //
237
dump(const Cfg * Func) const238 void InstMIPS32::dump(const Cfg *Func) const {
239 if (!BuildDefs::dump())
240 return;
241 Ostream &Str = Func->getContext()->getStrDump();
242 Str << "[MIPS32] ";
243 Inst::dump(Func);
244 }
245
emit(const Cfg * Func) const246 void OperandMIPS32Mem::emit(const Cfg *Func) const {
247 if (!BuildDefs::dump())
248 return;
249 Ostream &Str = Func->getContext()->getStrEmit();
250 Operand *Offset = getOffset();
251 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
252 Str << "(";
253 CR->emitWithoutPrefix(Func->getTarget());
254 Str << ")";
255 } else
256 Offset->emit(Func);
257 Str << "(";
258 getBase()->emit(Func);
259 Str << ")";
260 }
261
emitUnaryopGPR(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)262 void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
263 const Cfg *Func) {
264 if (!BuildDefs::dump())
265 return;
266 Ostream &Str = Func->getContext()->getStrEmit();
267 Str << "\t" << Opcode << "\t";
268 Inst->getDest()->emit(Func);
269 Str << ", ";
270 Inst->getSrc(0)->emit(Func);
271 }
emitUnaryopGPRFLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)272 void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
273 const Cfg *Func) {
274 if (!BuildDefs::dump())
275 return;
276 Ostream &Str = Func->getContext()->getStrEmit();
277 Str << "\t" << Opcode << "\t";
278 Inst->getDest()->emit(Func);
279 }
280
emitUnaryopGPRTLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)281 void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
282 const Cfg *Func) {
283 if (!BuildDefs::dump())
284 return;
285 Ostream &Str = Func->getContext()->getStrEmit();
286 Str << "\t" << Opcode << "\t";
287 Inst->getSrc(0)->emit(Func);
288 }
289
emitThreeAddr(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)290 void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
291 const Cfg *Func) {
292 if (!BuildDefs::dump())
293 return;
294 Ostream &Str = Func->getContext()->getStrEmit();
295 assert(Inst->getSrcSize() == 2);
296 Str << "\t" << Opcode << "\t";
297 Inst->getDest()->emit(Func);
298 Str << ", ";
299 Inst->getSrc(0)->emit(Func);
300 Str << ", ";
301 Inst->getSrc(1)->emit(Func);
302 }
303
emitTwoAddr(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)304 void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
305 const Cfg *Func) {
306 if (!BuildDefs::dump())
307 return;
308 Ostream &Str = Func->getContext()->getStrEmit();
309 assert(Inst->getSrcSize() == 1);
310 Str << "\t" << Opcode << "\t";
311 Inst->getDest()->emit(Func);
312 Str << ", ";
313 Inst->getSrc(0)->emit(Func);
314 }
315
emitThreeAddrLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)316 void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
317 const Cfg *Func) {
318 if (!BuildDefs::dump())
319 return;
320 Ostream &Str = Func->getContext()->getStrEmit();
321 assert(Inst->getSrcSize() == 2);
322 Str << "\t" << Opcode << "\t";
323 Inst->getSrc(0)->emit(Func);
324 Str << ", ";
325 Inst->getSrc(1)->emit(Func);
326 }
327
emit(const Cfg * Func) const328 void InstMIPS32Ret::emit(const Cfg *Func) const {
329 if (!BuildDefs::dump())
330 return;
331 assert(getSrcSize() > 0);
332 auto *RA = llvm::cast<Variable>(getSrc(0));
333 assert(RA->hasReg());
334 assert(RA->getRegNum() == RegMIPS32::Reg_RA);
335 Ostream &Str = Func->getContext()->getStrEmit();
336 Str << "\t"
337 "jr"
338 "\t";
339 RA->emit(Func);
340 }
341
emitIAS(const Cfg * Func) const342 void InstMIPS32Br::emitIAS(const Cfg *Func) const {
343 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
344 if (Label != nullptr) {
345 // Intra-block branches are of kind bcc
346 if (isUnconditionalBranch()) {
347 Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()));
348 } else {
349 Asm->bcc(Predicate, getSrc(0), getSrc(1),
350 Asm->getOrCreateLocalLabel(Label->getNumber()));
351 }
352 } else if (isUnconditionalBranch()) {
353 Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
354 } else {
355 switch (Predicate) {
356 default:
357 break;
358 case CondMIPS32::EQ:
359 case CondMIPS32::NE:
360 Asm->bcc(Predicate, getSrc(0), getSrc(1),
361 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
362 break;
363 case CondMIPS32::EQZ:
364 case CondMIPS32::NEZ:
365 case CondMIPS32::LEZ:
366 case CondMIPS32::LTZ:
367 case CondMIPS32::GEZ:
368 case CondMIPS32::GTZ:
369 Asm->bzc(Predicate, getSrc(0),
370 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
371 break;
372 }
373 if (getTargetTrue()) {
374 Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()));
375 }
376 }
377 }
378
emit(const Cfg * Func) const379 void InstMIPS32Br::emit(const Cfg *Func) const {
380 if (!BuildDefs::dump())
381 return;
382 Ostream &Str = Func->getContext()->getStrEmit();
383 Str << "\t"
384 "b"
385 << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
386 if (Label != nullptr) {
387 if (isUnconditionalBranch()) {
388 Str << Label->getLabelName();
389 } else {
390 getSrc(0)->emit(Func);
391 Str << ", ";
392 getSrc(1)->emit(Func);
393 Str << ", " << Label->getLabelName();
394 }
395 } else {
396 if (isUnconditionalBranch()) {
397 Str << getTargetFalse()->getAsmName();
398 } else {
399 switch (Predicate) {
400 default:
401 break;
402 case CondMIPS32::EQ:
403 case CondMIPS32::NE: {
404 getSrc(0)->emit(Func);
405 Str << ", ";
406 getSrc(1)->emit(Func);
407 Str << ", ";
408 break;
409 }
410 case CondMIPS32::EQZ:
411 case CondMIPS32::NEZ:
412 case CondMIPS32::LEZ:
413 case CondMIPS32::LTZ:
414 case CondMIPS32::GEZ:
415 case CondMIPS32::GTZ: {
416 getSrc(0)->emit(Func);
417 Str << ", ";
418 break;
419 }
420 }
421 Str << getTargetFalse()->getAsmName();
422 if (getTargetTrue()) {
423 Str << "\n\t"
424 << "b"
425 << "\t" << getTargetTrue()->getAsmName();
426 }
427 }
428 }
429 }
430
dump(const Cfg * Func) const431 void InstMIPS32Br::dump(const Cfg *Func) const {
432 if (!BuildDefs::dump())
433 return;
434 Ostream &Str = Func->getContext()->getStrDump();
435 Str << "\t"
436 "b"
437 << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
438
439 if (Label != nullptr) {
440 if (isUnconditionalBranch()) {
441 Str << Label->getLabelName();
442 } else {
443 getSrc(0)->dump(Func);
444 Str << ", ";
445 getSrc(1)->dump(Func);
446 Str << ", " << Label->getLabelName();
447 }
448 } else {
449 if (isUnconditionalBranch()) {
450 Str << getTargetFalse()->getAsmName();
451 } else {
452 dumpSources(Func);
453 Str << ", ";
454 Str << getTargetFalse()->getAsmName();
455 if (getTargetTrue()) {
456 Str << "\n\t"
457 << "b"
458 << "\t" << getTargetTrue()->getAsmName();
459 }
460 }
461 }
462 }
463
emit(const Cfg * Func) const464 void InstMIPS32Call::emit(const Cfg *Func) const {
465 if (!BuildDefs::dump())
466 return;
467 Ostream &Str = Func->getContext()->getStrEmit();
468 assert(getSrcSize() == 1);
469 if (llvm::isa<ConstantInteger32>(getCallTarget())) {
470 // This shouldn't happen (typically have to copy the full 32-bits to a
471 // register and do an indirect jump).
472 llvm::report_fatal_error("MIPS2Call to ConstantInteger32");
473 } else if (const auto *CallTarget =
474 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
475 // Calls only have 26-bits, but the linker should insert veneers to extend
476 // the range if needed.
477 Str << "\t"
478 "jal"
479 "\t";
480 CallTarget->emitWithoutPrefix(Func->getTarget());
481 } else {
482 Str << "\t"
483 "jalr"
484 "\t";
485 getCallTarget()->emit(Func);
486 }
487 }
488
emitIAS(const Cfg * Func) const489 void InstMIPS32Call::emitIAS(const Cfg *Func) const {
490 assert(getSrcSize() == 1);
491 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
492 if (llvm::isa<ConstantInteger32>(getCallTarget())) {
493 llvm::report_fatal_error("MIPS32Call to ConstantInteger32");
494 } else if (const auto *CallTarget =
495 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
496 Asm->jal(CallTarget);
497 } else {
498 const Operand *ImplicitRA = nullptr;
499 Asm->jalr(getCallTarget(), ImplicitRA);
500 }
501 }
502
dump(const Cfg * Func) const503 void InstMIPS32Call::dump(const Cfg *Func) const {
504 if (!BuildDefs::dump())
505 return;
506 Ostream &Str = Func->getContext()->getStrDump();
507 if (getDest()) {
508 dumpDest(Func);
509 Str << " = ";
510 }
511 Str << "call ";
512 getCallTarget()->dump(Func);
513 }
514
emitIAS(const Cfg * Func) const515 void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
516 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
517 auto *RA = llvm::cast<Variable>(getSrc(0));
518 assert(RA->hasReg());
519 assert(RA->getRegNum() == RegMIPS32::Reg_RA);
520 (void)RA;
521 Asm->ret();
522 }
523
dump(const Cfg * Func) const524 void InstMIPS32Ret::dump(const Cfg *Func) const {
525 if (!BuildDefs::dump())
526 return;
527 Ostream &Str = Func->getContext()->getStrDump();
528 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
529 Str << "ret." << Ty << " ";
530 dumpSources(Func);
531 }
532
emit(const Cfg * Func) const533 void InstMIPS32Mov::emit(const Cfg *Func) const {
534 if (!BuildDefs::dump())
535 return;
536
537 Ostream &Str = Func->getContext()->getStrEmit();
538 Variable *Dest = getDest();
539 Operand *Src = getSrc(0);
540 auto *SrcV = llvm::dyn_cast<Variable>(Src);
541
542 assert(!llvm::isa<Constant>(Src));
543
544 const char *ActualOpcode = nullptr;
545 const bool DestIsReg = Dest->hasReg();
546 const bool SrcIsReg = (SrcV && SrcV->hasReg());
547
548 // reg to reg
549 if (DestIsReg && SrcIsReg) {
550 const Type DstType = Dest->getType();
551 const Type SrcType = Src->getType();
552
553 // move GP to/from FP
554 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
555 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
556 if (isScalarFloatingType(DstType)) {
557 Str << "\t"
558 "mtc1"
559 "\t";
560 getSrc(0)->emit(Func);
561 Str << ", ";
562 getDest()->emit(Func);
563 return;
564 }
565 ActualOpcode = "mfc1";
566 } else {
567 switch (Dest->getType()) {
568 case IceType_f32:
569 ActualOpcode = "mov.s";
570 break;
571 case IceType_f64:
572 ActualOpcode = "mov.d";
573 break;
574 case IceType_i1:
575 case IceType_i8:
576 case IceType_i16:
577 case IceType_i32:
578 ActualOpcode = "move";
579 break;
580 default:
581 UnimplementedError(getFlags());
582 return;
583 }
584 }
585
586 assert(ActualOpcode);
587 Str << "\t" << ActualOpcode << "\t";
588 getDest()->emit(Func);
589 Str << ", ";
590 getSrc(0)->emit(Func);
591 return;
592 }
593
594 llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
595 }
596
emitIAS(const Cfg * Func) const597 void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
598 Variable *Dest = getDest();
599 Operand *Src = getSrc(0);
600 auto *SrcV = llvm::dyn_cast<Variable>(Src);
601 assert(!llvm::isa<Constant>(Src));
602 const bool DestIsReg = Dest->hasReg();
603 const bool SrcIsReg = (SrcV && SrcV->hasReg());
604
605 // reg to reg
606 if (DestIsReg && SrcIsReg) {
607 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
608 Asm->move(getDest(), getSrc(0));
609 return;
610 }
611
612 llvm::report_fatal_error("InstMIPS32Mov invalid operands");
613 }
614
dump(const Cfg * Func) const615 void InstMIPS32Mov::dump(const Cfg *Func) const {
616 if (!BuildDefs::dump())
617 return;
618 assert(getSrcSize() == 1 || getSrcSize() == 2);
619 Ostream &Str = Func->getContext()->getStrDump();
620 Variable *Dest = getDest();
621 Variable *DestHi = getDestHi();
622 Dest->dump(Func);
623 if (DestHi) {
624 Str << ", ";
625 DestHi->dump(Func);
626 }
627 dumpOpcode(Str, " = mov", getDest()->getType());
628 Str << " ";
629 dumpSources(Func);
630 }
631
emitIAS(const Cfg * Func) const632 template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
633 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
634 Asm->abs_d(getDest(), getSrc(0));
635 }
636
emitIAS(const Cfg * Func) const637 template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
638 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
639 Asm->abs_s(getDest(), getSrc(0));
640 }
641
emitIAS(const Cfg * Func) const642 template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const {
643 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
644 Asm->addi(getDest(), getSrc(0), Imm);
645 }
646
emitIAS(const Cfg * Func) const647 template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
648 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
649 Asm->add_d(getDest(), getSrc(0), getSrc(1));
650 }
651
emitIAS(const Cfg * Func) const652 template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
653 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
654 Asm->add_s(getDest(), getSrc(0), getSrc(1));
655 }
656
emitIAS(const Cfg * Func) const657 template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
658 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
659 if (Reloc == RO_No) {
660 Asm->addiu(getDest(), getSrc(0), Imm);
661 } else {
662 Asm->addiu(getDest(), getSrc(0), getSrc(1), Reloc);
663 }
664 }
665
emitIAS(const Cfg * Func) const666 template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
667 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
668 Asm->addu(getDest(), getSrc(0), getSrc(1));
669 }
670
emitIAS(const Cfg * Func) const671 template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
672 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
673 Asm->and_(getDest(), getSrc(0), getSrc(1));
674 }
675
emitIAS(const Cfg * Func) const676 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
677 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
678 Asm->andi(getDest(), getSrc(0), Imm);
679 }
680
emitIAS(const Cfg * Func) const681 template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const {
682 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
683 Asm->c_eq_d(getSrc(0), getSrc(1));
684 }
685
emitIAS(const Cfg * Func) const686 template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const {
687 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
688 Asm->c_eq_s(getSrc(0), getSrc(1));
689 }
690
emitIAS(const Cfg * Func) const691 template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const {
692 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
693 Asm->c_ole_d(getSrc(0), getSrc(1));
694 }
695
emitIAS(const Cfg * Func) const696 template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const {
697 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
698 Asm->c_ole_s(getSrc(0), getSrc(1));
699 }
700
emitIAS(const Cfg * Func) const701 template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const {
702 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
703 Asm->c_olt_d(getSrc(0), getSrc(1));
704 }
705
emitIAS(const Cfg * Func) const706 template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const {
707 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
708 Asm->c_olt_s(getSrc(0), getSrc(1));
709 }
710
emitIAS(const Cfg * Func) const711 template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const {
712 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
713 Asm->c_ueq_d(getSrc(0), getSrc(1));
714 }
715
emitIAS(const Cfg * Func) const716 template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const {
717 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
718 Asm->c_ueq_s(getSrc(0), getSrc(1));
719 }
720
emitIAS(const Cfg * Func) const721 template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const {
722 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
723 Asm->c_ule_d(getSrc(0), getSrc(1));
724 }
725
emitIAS(const Cfg * Func) const726 template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const {
727 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
728 Asm->c_ule_s(getSrc(0), getSrc(1));
729 }
730
emitIAS(const Cfg * Func) const731 template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const {
732 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
733 Asm->c_ult_d(getSrc(0), getSrc(1));
734 }
735
emitIAS(const Cfg * Func) const736 template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const {
737 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
738 Asm->c_ult_s(getSrc(0), getSrc(1));
739 }
740
emitIAS(const Cfg * Func) const741 template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const {
742 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
743 Asm->c_un_d(getSrc(0), getSrc(1));
744 }
745
emitIAS(const Cfg * Func) const746 template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const {
747 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
748 Asm->c_un_s(getSrc(0), getSrc(1));
749 }
750
emitIAS(const Cfg * Func) const751 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
752 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
753 Asm->clz(getDest(), getSrc(0));
754 }
755
emitIAS(const Cfg * Func) const756 template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const {
757 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
758 Asm->cvt_d_l(getDest(), getSrc(0));
759 }
760
emitIAS(const Cfg * Func) const761 template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const {
762 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
763 Asm->cvt_d_s(getDest(), getSrc(0));
764 }
765
emitIAS(const Cfg * Func) const766 template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const {
767 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
768 Asm->cvt_d_w(getDest(), getSrc(0));
769 }
770
emitIAS(const Cfg * Func) const771 template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const {
772 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
773 Asm->cvt_s_d(getDest(), getSrc(0));
774 }
775
emitIAS(const Cfg * Func) const776 template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const {
777 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
778 Asm->cvt_s_l(getDest(), getSrc(0));
779 }
780
emitIAS(const Cfg * Func) const781 template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
782 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
783 Asm->cvt_s_w(getDest(), getSrc(0));
784 }
785
emitIAS(const Cfg * Func) const786 template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const {
787 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
788 Asm->div(getSrc(0), getSrc(1));
789 }
790
emitIAS(const Cfg * Func) const791 template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
792 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
793 Asm->div_d(getDest(), getSrc(0), getSrc(1));
794 }
795
emitIAS(const Cfg * Func) const796 template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
797 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
798 Asm->div_s(getDest(), getSrc(0), getSrc(1));
799 }
800
emitIAS(const Cfg * Func) const801 template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const {
802 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
803 Asm->divu(getSrc(0), getSrc(1));
804 }
805
emitIAS(const Cfg * Func) const806 template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const {
807 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
808 Asm->lui(getDest(), getSrc(0), Reloc);
809 }
810
emitIAS(const Cfg * Func) const811 template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const {
812 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
813 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
814 Asm->ldc1(getDest(), Mem->getBase(), Mem->getOffset(), Reloc);
815 }
816
emitIAS(const Cfg * Func) const817 template <> void InstMIPS32Ll::emitIAS(const Cfg *Func) const {
818 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
819 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
820 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
821 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
822 Asm->ll(getDest(), Mem->getBase(), Imm);
823 }
824
emitIAS(const Cfg * Func) const825 template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
826 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
827 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
828 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
829 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
830 Asm->lw(getDest(), Mem->getBase(), Imm);
831 }
832
emitIAS(const Cfg * Func) const833 template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const {
834 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
835 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
836 Asm->lwc1(getDest(), Mem->getBase(), Mem->getOffset(), Reloc);
837 }
838
emitIAS(const Cfg * Func) const839 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
840 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
841 Asm->mfc1(getDest(), getSrc(0));
842 }
843
emit(const Cfg * Func) const844 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
845 if (!BuildDefs::dump())
846 return;
847 emitUnaryopGPRFLoHi(Opcode, this, Func);
848 }
849
emitIAS(const Cfg * Func) const850 template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const {
851 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
852 Asm->mflo(getDest());
853 }
854
emit(const Cfg * Func) const855 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
856 if (!BuildDefs::dump())
857 return;
858 emitUnaryopGPRFLoHi(Opcode, this, Func);
859 }
860
emitIAS(const Cfg * Func) const861 template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const {
862 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
863 Asm->mfhi(getDest());
864 }
865
emitIAS(const Cfg * Func) const866 template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
867 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
868 Asm->mov_d(getDest(), getSrc(0));
869 }
870
emitIAS(const Cfg * Func) const871 template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
872 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
873 Asm->mov_s(getDest(), getSrc(0));
874 }
875
emitIAS(const Cfg * Func) const876 template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const {
877 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
878 Asm->movf(getDest(), getSrc(0), getSrc(1));
879 }
880
emitIAS(const Cfg * Func) const881 template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const {
882 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
883 Asm->movn(getDest(), getSrc(0), getSrc(1));
884 }
885
emitIAS(const Cfg * Func) const886 template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const {
887 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
888 Asm->movn_d(getDest(), getSrc(0), getSrc(1));
889 }
890
emitIAS(const Cfg * Func) const891 template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const {
892 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
893 Asm->movn_s(getDest(), getSrc(0), getSrc(1));
894 }
895
emitIAS(const Cfg * Func) const896 template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const {
897 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
898 Asm->movt(getDest(), getSrc(0), getSrc(1));
899 }
900
emitIAS(const Cfg * Func) const901 template <> void InstMIPS32Movz::emitIAS(const Cfg *Func) const {
902 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
903 Asm->movz(getDest(), getSrc(0), getSrc(1));
904 }
905
emitIAS(const Cfg * Func) const906 template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const {
907 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
908 Asm->movz_d(getDest(), getSrc(0), getSrc(1));
909 }
910
emitIAS(const Cfg * Func) const911 template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const {
912 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
913 Asm->movz_s(getDest(), getSrc(0), getSrc(1));
914 }
915
emit(const Cfg * Func) const916 template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const {
917 if (!BuildDefs::dump())
918 return;
919 Ostream &Str = Func->getContext()->getStrEmit();
920 assert(getSrcSize() == 1);
921 Str << "\t" << Opcode << "\t";
922 getSrc(0)->emit(Func);
923 Str << ", ";
924 getDest()->emit(Func);
925 }
926
emitIAS(const Cfg * Func) const927 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
928 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
929 Asm->mtc1(getSrc(0), getDest());
930 }
931
emit(const Cfg * Func) const932 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
933 if (!BuildDefs::dump())
934 return;
935 emitUnaryopGPRTLoHi(Opcode, this, Func);
936 }
937
emitIAS(const Cfg * Func) const938 template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const {
939 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
940 Asm->mtlo(getDest());
941 }
942
emit(const Cfg * Func) const943 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
944 if (!BuildDefs::dump())
945 return;
946 emitUnaryopGPRTLoHi(Opcode, this, Func);
947 }
948
emitIAS(const Cfg * Func) const949 template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const {
950 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
951 Asm->mthi(getDest());
952 }
953
emitIAS(const Cfg * Func) const954 template <> void InstMIPS32Mul::emitIAS(const Cfg *Func) const {
955 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
956 Asm->mul(getDest(), getSrc(0), getSrc(1));
957 }
958
emitIAS(const Cfg * Func) const959 template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const {
960 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
961 Asm->mul_d(getDest(), getSrc(0), getSrc(1));
962 }
963
emitIAS(const Cfg * Func) const964 template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const {
965 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
966 Asm->mul_s(getDest(), getSrc(0), getSrc(1));
967 }
968
emit(const Cfg * Func) const969 template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
970 if (!BuildDefs::dump())
971 return;
972 emitThreeAddrLoHi(Opcode, this, Func);
973 }
974
emitIAS(const Cfg * Func) const975 template <> void InstMIPS32Mult::emitIAS(const Cfg *Func) const {
976 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
977 Asm->mult(getDest(), getSrc(0));
978 }
979
emit(const Cfg * Func) const980 template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
981 if (!BuildDefs::dump())
982 return;
983 emitThreeAddrLoHi(Opcode, this, Func);
984 }
985
emitIAS(const Cfg * Func) const986 template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const {
987 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
988 Asm->multu(getSrc(0), getSrc(1));
989 }
990
emitIAS(const Cfg * Func) const991 template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
992 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
993 Asm->nor(getDest(), getSrc(0), getSrc(1));
994 }
995
emitIAS(const Cfg * Func) const996 template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
997 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
998 Asm->or_(getDest(), getSrc(0), getSrc(1));
999 }
1000
emitIAS(const Cfg * Func) const1001 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
1002 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1003 Asm->ori(getDest(), getSrc(0), Imm);
1004 }
1005
emitIAS(const Cfg * Func) const1006 template <> void InstMIPS32Sc::emitIAS(const Cfg *Func) const {
1007 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1008 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1009 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1010 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1011 Asm->sc(getSrc(0), Mem->getBase(), Imm);
1012 }
1013
emitIAS(const Cfg * Func) const1014 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
1015 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1016 Asm->sll(getDest(), getSrc(0), Imm);
1017 }
1018
emitIAS(const Cfg * Func) const1019 template <> void InstMIPS32Sllv::emitIAS(const Cfg *Func) const {
1020 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1021 Asm->sllv(getDest(), getSrc(0), getSrc(1));
1022 }
1023
emitIAS(const Cfg * Func) const1024 template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
1025 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1026 Asm->slt(getDest(), getSrc(0), getSrc(1));
1027 }
1028
emitIAS(const Cfg * Func) const1029 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
1030 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1031 Asm->slti(getDest(), getSrc(0), Imm);
1032 }
1033
emitIAS(const Cfg * Func) const1034 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
1035 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1036 Asm->sltiu(getDest(), getSrc(0), Imm);
1037 }
1038
emitIAS(const Cfg * Func) const1039 template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
1040 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1041 Asm->sltu(getDest(), getSrc(0), getSrc(1));
1042 }
1043
emitIAS(const Cfg * Func) const1044 template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
1045 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1046 Asm->sqrt_d(getDest(), getSrc(0));
1047 }
1048
emitIAS(const Cfg * Func) const1049 template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
1050 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1051 Asm->sqrt_s(getDest(), getSrc(0));
1052 }
1053
emitIAS(const Cfg * Func) const1054 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
1055 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1056 Asm->sra(getDest(), getSrc(0), Imm);
1057 }
1058
emitIAS(const Cfg * Func) const1059 template <> void InstMIPS32Srav::emitIAS(const Cfg *Func) const {
1060 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1061 Asm->srav(getDest(), getSrc(0), getSrc(1));
1062 }
1063
emitIAS(const Cfg * Func) const1064 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
1065 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1066 Asm->srl(getDest(), getSrc(0), Imm);
1067 }
1068
emitIAS(const Cfg * Func) const1069 template <> void InstMIPS32Srlv::emitIAS(const Cfg *Func) const {
1070 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1071 Asm->srlv(getDest(), getSrc(0), getSrc(1));
1072 }
1073
emitIAS(const Cfg * Func) const1074 template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const {
1075 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1076 Asm->sub_d(getDest(), getSrc(0), getSrc(1));
1077 }
1078
emitIAS(const Cfg * Func) const1079 template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const {
1080 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1081 Asm->sub_s(getDest(), getSrc(0), getSrc(1));
1082 }
1083
emitIAS(const Cfg * Func) const1084 template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const {
1085 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1086 Asm->subu(getDest(), getSrc(0), getSrc(1));
1087 }
1088
emitIAS(const Cfg * Func) const1089 template <> void InstMIPS32Sdc1::emitIAS(const Cfg *Func) const {
1090 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1091 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
1092 Asm->sdc1(getSrc(0), Mem->getBase(), Mem->getOffset(), Reloc);
1093 }
1094
emitIAS(const Cfg * Func) const1095 template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
1096 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1097 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1098 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1099 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1100 Asm->sw(getSrc(0), Mem->getBase(), Imm);
1101 }
1102
emitIAS(const Cfg * Func) const1103 template <> void InstMIPS32Swc1::emitIAS(const Cfg *Func) const {
1104 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1105 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
1106 Asm->swc1(getSrc(0), Mem->getBase(), Mem->getOffset(), Reloc);
1107 }
1108
emitIAS(const Cfg * Func) const1109 void InstMIPS32Sync::emitIAS(const Cfg *Func) const {
1110 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1111 Asm->sync();
1112 }
1113
emitIAS(const Cfg * Func) const1114 template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
1115 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1116 Asm->teq(getSrc(0), getSrc(1), getTrapCode());
1117 }
1118
emitIAS(const Cfg * Func) const1119 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
1120 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1121 Asm->trunc_l_d(getDest(), getSrc(0));
1122 }
1123
emitIAS(const Cfg * Func) const1124 template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const {
1125 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1126 Asm->trunc_l_s(getDest(), getSrc(0));
1127 }
1128
emitIAS(const Cfg * Func) const1129 template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const {
1130 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1131 Asm->trunc_w_d(getDest(), getSrc(0));
1132 }
1133
emitIAS(const Cfg * Func) const1134 template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const {
1135 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1136 Asm->trunc_w_s(getDest(), getSrc(0));
1137 }
1138
emitIAS(const Cfg * Func) const1139 template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
1140 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1141 Asm->xor_(getDest(), getSrc(0), getSrc(1));
1142 }
1143
emitIAS(const Cfg * Func) const1144 template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
1145 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1146 Asm->xori(getDest(), getSrc(0), Imm);
1147 }
1148
1149 } // end of namespace MIPS32
1150 } // end of namespace Ice
1151