• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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