• 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 "IceAssemblerMIPS32.h"
16 #include "IceCfg.h"
17 #include "IceCfgNode.h"
18 #include "IceInst.h"
19 #include "IceInstMIPS32.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)                                                      \
33   { CondMIPS32::opp, emit }                                                    \
34   ,
35     ICEINSTMIPS32COND_TABLE
36 #undef X
37 };
38 
canHoldOffset(Type Ty,bool SignExt,int32_t Offset)39 bool OperandMIPS32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
40   (void)SignExt;
41   (void)Ty;
42   if ((std::numeric_limits<int16_t>::min() <= Offset) &&
43       (Offset <= std::numeric_limits<int16_t>::max()))
44     return true;
45   return false;
46 }
47 
OperandMIPS32Mem(Cfg * Func,Type Ty,Variable * Base,Operand * ImmOffset,AddrMode Mode)48 OperandMIPS32Mem::OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base,
49                                    Operand *ImmOffset, AddrMode Mode)
50     : OperandMIPS32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Mode(Mode) {
51   // The Neg modes are only needed for Reg +/- Reg.
52   (void)Func;
53   // assert(!isNegAddrMode());
54   NumVars = 1;
55   Vars = &this->Base;
56 }
57 
getWidthString(Type Ty)58 const char *InstMIPS32::getWidthString(Type Ty) {
59   (void)Ty;
60   return "TBD";
61 }
62 
63 template <> const char *InstMIPS32Abs_d::Opcode = "abs.d";
64 template <> const char *InstMIPS32Abs_s::Opcode = "abs.s";
65 template <> const char *InstMIPS32Addi::Opcode = "addi";
66 template <> const char *InstMIPS32Add::Opcode = "add";
67 template <> const char *InstMIPS32Add_d::Opcode = "add.d";
68 template <> const char *InstMIPS32Add_s::Opcode = "add.s";
69 template <> const char *InstMIPS32Addiu::Opcode = "addiu";
70 template <> const char *InstMIPS32Addu::Opcode = "addu";
71 template <> const char *InstMIPS32And::Opcode = "and";
72 template <> const char *InstMIPS32Andi::Opcode = "andi";
73 template <> const char *InstMIPS32C_eq_d::Opcode = "c.eq.d";
74 template <> const char *InstMIPS32C_eq_s::Opcode = "c.eq.s";
75 template <> const char *InstMIPS32C_ole_d::Opcode = "c.ole.d";
76 template <> const char *InstMIPS32C_ole_s::Opcode = "c.ole.s";
77 template <> const char *InstMIPS32C_olt_d::Opcode = "c.olt.d";
78 template <> const char *InstMIPS32C_olt_s::Opcode = "c.olt.s";
79 template <> const char *InstMIPS32C_ueq_d::Opcode = "c.ueq.d";
80 template <> const char *InstMIPS32C_ueq_s::Opcode = "c.ueq.s";
81 template <> const char *InstMIPS32C_ule_d::Opcode = "c.ule.d";
82 template <> const char *InstMIPS32C_ule_s::Opcode = "c.ule.s";
83 template <> const char *InstMIPS32C_ult_d::Opcode = "c.ult.d";
84 template <> const char *InstMIPS32C_ult_s::Opcode = "c.ult.s";
85 template <> const char *InstMIPS32C_un_d::Opcode = "c.un.d";
86 template <> const char *InstMIPS32C_un_s::Opcode = "c.un.s";
87 template <> const char *InstMIPS32Clz::Opcode = "clz";
88 template <> const char *InstMIPS32Cvt_d_l::Opcode = "cvt.d.l";
89 template <> const char *InstMIPS32Cvt_d_s::Opcode = "cvt.d.s";
90 template <> const char *InstMIPS32Cvt_d_w::Opcode = "cvt.d.w";
91 template <> const char *InstMIPS32Cvt_s_d::Opcode = "cvt.s.d";
92 template <> const char *InstMIPS32Cvt_s_l::Opcode = "cvt.s.l";
93 template <> const char *InstMIPS32Cvt_s_w::Opcode = "cvt.s.w";
94 template <> const char *InstMIPS32Div::Opcode = "div";
95 template <> const char *InstMIPS32Div_d::Opcode = "div.d";
96 template <> const char *InstMIPS32Div_s::Opcode = "div.s";
97 template <> const char *InstMIPS32Divu::Opcode = "divu";
98 template <> const char *InstMIPS32La::Opcode = "la";
99 template <> const char *InstMIPS32Ldc1::Opcode = "ldc1";
100 template <> const char *InstMIPS32Ll::Opcode = "ll";
101 template <> const char *InstMIPS32Lui::Opcode = "lui";
102 template <> const char *InstMIPS32Lw::Opcode = "lw";
103 template <> const char *InstMIPS32Lwc1::Opcode = "lwc1";
104 template <> const char *InstMIPS32Mfc1::Opcode = "mfc1";
105 template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
106 template <> const char *InstMIPS32Mflo::Opcode = "mflo";
107 template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
108 template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
109 template <> const char *InstMIPS32Movf::Opcode = "movf";
110 template <> const char *InstMIPS32Movn::Opcode = "movn";
111 template <> const char *InstMIPS32Movn_d::Opcode = "movn.d";
112 template <> const char *InstMIPS32Movn_s::Opcode = "movn.s";
113 template <> const char *InstMIPS32Movt::Opcode = "movt";
114 template <> const char *InstMIPS32Movz::Opcode = "movz";
115 template <> const char *InstMIPS32Movz_d::Opcode = "movz.d";
116 template <> const char *InstMIPS32Movz_s::Opcode = "movz.s";
117 template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
118 template <> const char *InstMIPS32Mthi::Opcode = "mthi";
119 template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
120 template <> const char *InstMIPS32Mul::Opcode = "mul";
121 template <> const char *InstMIPS32Mul_d::Opcode = "mul.d";
122 template <> const char *InstMIPS32Mul_s::Opcode = "mul.s";
123 template <> const char *InstMIPS32Mult::Opcode = "mult";
124 template <> const char *InstMIPS32Multu::Opcode = "multu";
125 template <> const char *InstMIPS32Nor::Opcode = "nor";
126 template <> const char *InstMIPS32Or::Opcode = "or";
127 template <> const char *InstMIPS32Ori::Opcode = "ori";
128 template <> const char *InstMIPS32Sc::Opcode = "sc";
129 template <> const char *InstMIPS32Sdc1::Opcode = "sdc1";
130 template <> const char *InstMIPS32Sll::Opcode = "sll";
131 template <> const char *InstMIPS32Sllv::Opcode = "sllv";
132 template <> const char *InstMIPS32Slt::Opcode = "slt";
133 template <> const char *InstMIPS32Slti::Opcode = "slti";
134 template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
135 template <> const char *InstMIPS32Sltu::Opcode = "sltu";
136 template <> const char *InstMIPS32Sqrt_d::Opcode = "sqrt.d";
137 template <> const char *InstMIPS32Sqrt_s::Opcode = "sqrt.s";
138 template <> const char *InstMIPS32Sra::Opcode = "sra";
139 template <> const char *InstMIPS32Srav::Opcode = "srav";
140 template <> const char *InstMIPS32Srl::Opcode = "srl";
141 template <> const char *InstMIPS32Srlv::Opcode = "srlv";
142 template <> const char *InstMIPS32Sub::Opcode = "sub";
143 template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
144 template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
145 template <> const char *InstMIPS32Subu::Opcode = "subu";
146 template <> const char *InstMIPS32Sw::Opcode = "sw";
147 template <> const char *InstMIPS32Swc1::Opcode = "swc1";
148 const char *InstMIPS32Sync::Opcode = "sync";
149 template <> const char *InstMIPS32Teq::Opcode = "teq";
150 template <> const char *InstMIPS32Trunc_l_d::Opcode = "trunc.l.d";
151 template <> const char *InstMIPS32Trunc_l_s::Opcode = "trunc.l.s";
152 template <> const char *InstMIPS32Trunc_w_d::Opcode = "trunc.w.d";
153 template <> const char *InstMIPS32Trunc_w_s::Opcode = "trunc.w.s";
154 template <> const char *InstMIPS32Xor::Opcode = "xor";
155 template <> const char *InstMIPS32Xori::Opcode = "xori";
156 
emit(const Cfg * Func) const157 template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
158   if (!BuildDefs::dump())
159     return;
160   Ostream &Str = Func->getContext()->getStrEmit();
161   assert(getSrcSize() == 1);
162   Str << "\t" << Opcode << "\t";
163   getDest()->emit(Func);
164   Str << ", ";
165   auto *Src0 = llvm::cast<Constant>(getSrc(0));
166   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
167     emitRelocOp(Str, Reloc);
168     Str << "(";
169     CR->emitWithoutPrefix(Func->getTarget());
170     Str << ")";
171   } else {
172     Src0->emit(Func);
173   }
174 }
175 
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)176 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
177                            const CfgNode *TargetFalse,
178                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
179     : InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
180       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {}
181 
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,Operand * Src0,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)182 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
183                            const CfgNode *TargetFalse, Operand *Src0,
184                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
185     : InstMIPS32(Func, InstMIPS32::Br, 1, nullptr), TargetTrue(TargetTrue),
186       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
187   addSource(Src0);
188 }
189 
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,Operand * Src0,Operand * Src1,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)190 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
191                            const CfgNode *TargetFalse, Operand *Src0,
192                            Operand *Src1, const InstMIPS32Label *Label,
193                            CondMIPS32::Cond Cond)
194     : InstMIPS32(Func, InstMIPS32::Br, 2, nullptr), TargetTrue(TargetTrue),
195       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
196   addSource(Src0);
197   addSource(Src1);
198 }
199 
getOppositeCondition(CondMIPS32::Cond Cond)200 CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
201   return InstMIPS32CondAttributes[Cond].Opposite;
202 }
203 
optimizeBranch(const CfgNode * NextNode)204 bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
205   // If there is no next block, then there can be no fallthrough to optimize.
206   if (NextNode == nullptr)
207     return false;
208   // Intra-block conditional branches can't be optimized.
209   if (Label != nullptr)
210     return false;
211   // Unconditional branch to the next node can be removed.
212   if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
213     assert(getTargetTrue() == nullptr);
214     setDeleted();
215     return true;
216   }
217   // If there is no fallthrough node, such as a non-default case label for a
218   // switch instruction, then there is no opportunity to optimize.
219   if (getTargetTrue() == nullptr)
220     return false;
221   // If the fallthrough is to the next node, set fallthrough to nullptr to
222   // indicate.
223   if (getTargetTrue() == NextNode) {
224     TargetTrue = nullptr;
225     return true;
226   }
227   // If TargetFalse is the next node, and TargetTrue is not nullptr
228   // then invert the branch condition, swap the targets, and set new
229   // fallthrough to nullptr.
230   if (getTargetFalse() == NextNode) {
231     assert(Predicate != CondMIPS32::AL);
232     setPredicate(getOppositeCondition(getPredicate()));
233     TargetFalse = getTargetTrue();
234     TargetTrue = nullptr;
235     return true;
236   }
237   return false;
238 }
239 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)240 bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
241   bool Found = false;
242   if (TargetFalse == OldNode) {
243     TargetFalse = NewNode;
244     Found = true;
245   }
246   if (TargetTrue == OldNode) {
247     TargetTrue = NewNode;
248     Found = true;
249   }
250   return Found;
251 }
252 
InstMIPS32Label(Cfg * Func,TargetMIPS32 * Target)253 InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
254     : InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
255       Number(Target->makeNextLabelNumber()) {
256   if (BuildDefs::dump()) {
257     Name = GlobalString::createWithString(
258         Func->getContext(),
259         ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
260   } else {
261     Name = GlobalString::createWithoutString(Func->getContext());
262   }
263 }
264 
dump(const Cfg * Func) const265 void InstMIPS32Label::dump(const Cfg *Func) const {
266   if (!BuildDefs::dump())
267     return;
268   Ostream &Str = Func->getContext()->getStrDump();
269   Str << getLabelName() << ":";
270 }
271 
emit(const Cfg * Func) const272 void InstMIPS32Label::emit(const Cfg *Func) const {
273   if (!BuildDefs::dump())
274     return;
275   Ostream &Str = Func->getContext()->getStrEmit();
276   Str << getLabelName() << ":";
277 }
278 
emitIAS(const Cfg * Func) const279 void InstMIPS32Label::emitIAS(const Cfg *Func) const {
280   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
281   Asm->bindLocalLabel(this, Number);
282 }
283 
InstMIPS32Call(Cfg * Func,Variable * Dest,Operand * CallTarget)284 InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
285     : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
286   HasSideEffects = true;
287   addSource(CallTarget);
288 }
289 
InstMIPS32Mov(Cfg * Func,Variable * Dest,Operand * Src,Operand * Src2)290 InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src,
291                              Operand *Src2)
292     : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
293   auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
294   auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
295 
296   assert(Dest64 == nullptr || Src64 == nullptr);
297 
298   if (Dest->getType() == IceType_f64 && Src2 != nullptr) {
299     addSource(Src);
300     addSource(Src2);
301     return;
302   }
303 
304   if (Dest64 != nullptr) {
305     // this-> is needed below because there is a parameter named Dest.
306     this->Dest = Dest64->getLo();
307     DestHi = Dest64->getHi();
308   }
309 
310   if (Src64 == nullptr) {
311     addSource(Src);
312   } else {
313     addSource(Src64->getLo());
314     addSource(Src64->getHi());
315   }
316 }
317 
InstMIPS32MovFP64ToI64(Cfg * Func,Variable * Dst,Operand * Src,Int64Part Int64HiLo)318 InstMIPS32MovFP64ToI64::InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dst,
319                                                Operand *Src,
320                                                Int64Part Int64HiLo)
321     : InstMIPS32(Func, InstMIPS32::Mov_fp, 1, Dst), Int64HiLo(Int64HiLo) {
322   addSource(Src);
323 }
324 
InstMIPS32Ret(Cfg * Func,Variable * RA,Variable * Source)325 InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
326     : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
327   addSource(RA);
328   if (Source)
329     addSource(Source);
330 }
331 
332 // ======================== Dump routines ======================== //
333 
dump(const Cfg * Func) const334 void InstMIPS32::dump(const Cfg *Func) const {
335   if (!BuildDefs::dump())
336     return;
337   Ostream &Str = Func->getContext()->getStrDump();
338   Str << "[MIPS32] ";
339   Inst::dump(Func);
340 }
341 
emit(const Cfg * Func) const342 void OperandMIPS32Mem::emit(const Cfg *Func) const {
343   if (!BuildDefs::dump())
344     return;
345   Ostream &Str = Func->getContext()->getStrEmit();
346   Operand *Offset = getOffset();
347   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
348     Str << "(";
349     CR->emitWithoutPrefix(Func->getTarget());
350     Str << ")";
351   } else
352     Offset->emit(Func);
353   Str << "(";
354   getBase()->emit(Func);
355   Str << ")";
356 }
357 
emitUnaryopGPR(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)358 void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
359                                 const Cfg *Func) {
360   if (!BuildDefs::dump())
361     return;
362   Ostream &Str = Func->getContext()->getStrEmit();
363   Str << "\t" << Opcode << "\t";
364   Inst->getDest()->emit(Func);
365   Str << ", ";
366   Inst->getSrc(0)->emit(Func);
367 }
emitUnaryopGPRFLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)368 void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
369                                      const Cfg *Func) {
370   if (!BuildDefs::dump())
371     return;
372   Ostream &Str = Func->getContext()->getStrEmit();
373   Str << "\t" << Opcode << "\t";
374   Inst->getDest()->emit(Func);
375 }
376 
emitUnaryopGPRTLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)377 void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
378                                      const Cfg *Func) {
379   if (!BuildDefs::dump())
380     return;
381   Ostream &Str = Func->getContext()->getStrEmit();
382   Str << "\t" << Opcode << "\t";
383   Inst->getSrc(0)->emit(Func);
384 }
385 
emitThreeAddr(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)386 void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
387                                const Cfg *Func) {
388   if (!BuildDefs::dump())
389     return;
390   Ostream &Str = Func->getContext()->getStrEmit();
391   assert(Inst->getSrcSize() == 2);
392   Str << "\t" << Opcode << "\t";
393   Inst->getDest()->emit(Func);
394   Str << ", ";
395   Inst->getSrc(0)->emit(Func);
396   Str << ", ";
397   Inst->getSrc(1)->emit(Func);
398 }
399 
emitTwoAddr(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)400 void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
401                              const Cfg *Func) {
402   if (!BuildDefs::dump())
403     return;
404   Ostream &Str = Func->getContext()->getStrEmit();
405   assert(Inst->getSrcSize() == 1);
406   Str << "\t" << Opcode << "\t";
407   Inst->getDest()->emit(Func);
408   Str << ", ";
409   Inst->getSrc(0)->emit(Func);
410 }
411 
emitThreeAddrLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)412 void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
413                                    const Cfg *Func) {
414   if (!BuildDefs::dump())
415     return;
416   Ostream &Str = Func->getContext()->getStrEmit();
417   assert(Inst->getSrcSize() == 2);
418   Str << "\t" << Opcode << "\t";
419   Inst->getSrc(0)->emit(Func);
420   Str << ", ";
421   Inst->getSrc(1)->emit(Func);
422 }
423 
emit(const Cfg * Func) const424 void InstMIPS32Ret::emit(const Cfg *Func) const {
425   if (!BuildDefs::dump())
426     return;
427   assert(getSrcSize() > 0);
428   auto *RA = llvm::cast<Variable>(getSrc(0));
429   assert(RA->hasReg());
430   assert(RA->getRegNum() == RegMIPS32::Reg_RA);
431   Ostream &Str = Func->getContext()->getStrEmit();
432   Str << "\t"
433          "jr"
434          "\t";
435   RA->emit(Func);
436 }
437 
emitIAS(const Cfg * Func) const438 void InstMIPS32Br::emitIAS(const Cfg *Func) const {
439   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
440   if (Label != nullptr) {
441     // Intra-block branches are of kind bcc
442     if (isUnconditionalBranch()) {
443       Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()));
444     } else {
445       Asm->bcc(Predicate, getSrc(0), getSrc(1),
446                Asm->getOrCreateLocalLabel(Label->getNumber()));
447     }
448   } else if (isUnconditionalBranch()) {
449     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
450   } else {
451     switch (Predicate) {
452     default:
453       break;
454     case CondMIPS32::EQ:
455     case CondMIPS32::NE:
456       Asm->bcc(Predicate, getSrc(0), getSrc(1),
457                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
458       break;
459     case CondMIPS32::EQZ:
460     case CondMIPS32::NEZ:
461     case CondMIPS32::LEZ:
462     case CondMIPS32::LTZ:
463     case CondMIPS32::GEZ:
464     case CondMIPS32::GTZ:
465       Asm->bzc(Predicate, getSrc(0),
466                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
467       break;
468     }
469     if (getTargetTrue()) {
470       Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()));
471     }
472   }
473 }
474 
emit(const Cfg * Func) const475 void InstMIPS32Br::emit(const Cfg *Func) const {
476   if (!BuildDefs::dump())
477     return;
478   Ostream &Str = Func->getContext()->getStrEmit();
479   Str << "\t"
480          "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
481   if (Label != nullptr) {
482     if (isUnconditionalBranch()) {
483       Str << Label->getLabelName();
484     } else {
485       getSrc(0)->emit(Func);
486       Str << ", ";
487       getSrc(1)->emit(Func);
488       Str << ", " << Label->getLabelName();
489     }
490   } else {
491     if (isUnconditionalBranch()) {
492       Str << getTargetFalse()->getAsmName();
493     } else {
494       switch (Predicate) {
495       default:
496         break;
497       case CondMIPS32::EQ:
498       case CondMIPS32::NE: {
499         getSrc(0)->emit(Func);
500         Str << ", ";
501         getSrc(1)->emit(Func);
502         Str << ", ";
503         break;
504       }
505       case CondMIPS32::EQZ:
506       case CondMIPS32::NEZ:
507       case CondMIPS32::LEZ:
508       case CondMIPS32::LTZ:
509       case CondMIPS32::GEZ:
510       case CondMIPS32::GTZ: {
511         getSrc(0)->emit(Func);
512         Str << ", ";
513         break;
514       }
515       }
516       Str << getTargetFalse()->getAsmName();
517       if (getTargetTrue()) {
518         Str << "\n\t"
519             << "b"
520             << "\t" << getTargetTrue()->getAsmName();
521       }
522     }
523   }
524 }
525 
dump(const Cfg * Func) const526 void InstMIPS32Br::dump(const Cfg *Func) const {
527   if (!BuildDefs::dump())
528     return;
529   Ostream &Str = Func->getContext()->getStrDump();
530   Str << "\t"
531          "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
532 
533   if (Label != nullptr) {
534     if (isUnconditionalBranch()) {
535       Str << Label->getLabelName();
536     } else {
537       getSrc(0)->dump(Func);
538       Str << ", ";
539       getSrc(1)->dump(Func);
540       Str << ", " << Label->getLabelName();
541     }
542   } else {
543     if (isUnconditionalBranch()) {
544       Str << getTargetFalse()->getAsmName();
545     } else {
546       dumpSources(Func);
547       Str << ", ";
548       Str << getTargetFalse()->getAsmName();
549       if (getTargetTrue()) {
550         Str << "\n\t"
551             << "b"
552             << "\t" << getTargetTrue()->getAsmName();
553       }
554     }
555   }
556 }
557 
emit(const Cfg * Func) const558 void InstMIPS32Call::emit(const Cfg *Func) const {
559   if (!BuildDefs::dump())
560     return;
561   Ostream &Str = Func->getContext()->getStrEmit();
562   assert(getSrcSize() == 1);
563   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
564     // This shouldn't happen (typically have to copy the full 32-bits to a
565     // register and do an indirect jump).
566     llvm::report_fatal_error("MIPS2Call to ConstantInteger32");
567   } else if (const auto *CallTarget =
568                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
569     // Calls only have 26-bits, but the linker should insert veneers to extend
570     // the range if needed.
571     Str << "\t"
572            "jal"
573            "\t";
574     CallTarget->emitWithoutPrefix(Func->getTarget());
575   } else {
576     Str << "\t"
577            "jalr"
578            "\t";
579     getCallTarget()->emit(Func);
580   }
581 }
582 
emitIAS(const Cfg * Func) const583 void InstMIPS32Call::emitIAS(const Cfg *Func) const {
584   assert(getSrcSize() == 1);
585   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
586   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
587     llvm::report_fatal_error("MIPS32Call to ConstantInteger32");
588   } else if (const auto *CallTarget =
589                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
590     Asm->jal(CallTarget);
591   } else {
592     const Operand *ImplicitRA = nullptr;
593     Asm->jalr(getCallTarget(), ImplicitRA);
594   }
595 }
596 
dump(const Cfg * Func) const597 void InstMIPS32Call::dump(const Cfg *Func) const {
598   if (!BuildDefs::dump())
599     return;
600   Ostream &Str = Func->getContext()->getStrDump();
601   if (getDest()) {
602     dumpDest(Func);
603     Str << " = ";
604   }
605   Str << "call ";
606   getCallTarget()->dump(Func);
607 }
608 
emitIAS(const Cfg * Func) const609 void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
610   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
611   auto *RA = llvm::cast<Variable>(getSrc(0));
612   assert(RA->hasReg());
613   assert(RA->getRegNum() == RegMIPS32::Reg_RA);
614   (void)RA;
615   Asm->ret();
616 }
617 
dump(const Cfg * Func) const618 void InstMIPS32Ret::dump(const Cfg *Func) const {
619   if (!BuildDefs::dump())
620     return;
621   Ostream &Str = Func->getContext()->getStrDump();
622   Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
623   Str << "ret." << Ty << " ";
624   dumpSources(Func);
625 }
626 
emit(const Cfg * Func) const627 void InstMIPS32Mov::emit(const Cfg *Func) const {
628   if (!BuildDefs::dump())
629     return;
630 
631   Ostream &Str = Func->getContext()->getStrEmit();
632   Variable *Dest = getDest();
633   Operand *Src = getSrc(0);
634   auto *SrcV = llvm::dyn_cast<Variable>(Src);
635 
636   assert(!llvm::isa<Constant>(Src));
637 
638   const char *ActualOpcode = nullptr;
639   const bool DestIsReg = Dest->hasReg();
640   const bool SrcIsReg = (SrcV && SrcV->hasReg());
641 
642   // reg to reg
643   if (DestIsReg && SrcIsReg) {
644     const Type DstType = Dest->getType();
645     const Type SrcType = Src->getType();
646 
647     // move GP to/from FP
648     if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
649         (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
650       if (isScalarFloatingType(DstType)) {
651         Str << "\t"
652                "mtc1"
653                "\t";
654         getSrc(0)->emit(Func);
655         Str << ", ";
656         getDest()->emit(Func);
657         return;
658       }
659       ActualOpcode = "mfc1";
660     } else {
661       switch (Dest->getType()) {
662       case IceType_f32:
663         ActualOpcode = "mov.s";
664         break;
665       case IceType_f64:
666         ActualOpcode = "mov.d";
667         break;
668       case IceType_i1:
669       case IceType_i8:
670       case IceType_i16:
671       case IceType_i32:
672         ActualOpcode = "move";
673         break;
674       default:
675         UnimplementedError(getFlags());
676         return;
677       }
678     }
679 
680     assert(ActualOpcode);
681     Str << "\t" << ActualOpcode << "\t";
682     getDest()->emit(Func);
683     Str << ", ";
684     getSrc(0)->emit(Func);
685     return;
686   }
687 
688   llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
689 }
690 
emitIAS(const Cfg * Func) const691 void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
692   Variable *Dest = getDest();
693   Operand *Src = getSrc(0);
694   auto *SrcV = llvm::dyn_cast<Variable>(Src);
695   assert(!llvm::isa<Constant>(Src));
696   const bool DestIsReg = Dest->hasReg();
697   const bool SrcIsReg = (SrcV && SrcV->hasReg());
698 
699   // reg to reg
700   if (DestIsReg && SrcIsReg) {
701     auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
702     Asm->move(getDest(), getSrc(0));
703     return;
704   }
705 
706   llvm::report_fatal_error("InstMIPS32Mov invalid operands");
707 }
708 
dump(const Cfg * Func) const709 void InstMIPS32Mov::dump(const Cfg *Func) const {
710   if (!BuildDefs::dump())
711     return;
712   assert(getSrcSize() == 1 || getSrcSize() == 2);
713   Ostream &Str = Func->getContext()->getStrDump();
714   Variable *Dest = getDest();
715   Variable *DestHi = getDestHi();
716   Dest->dump(Func);
717   if (DestHi) {
718     Str << ", ";
719     DestHi->dump(Func);
720   }
721   dumpOpcode(Str, " = mov", getDest()->getType());
722   Str << " ";
723   dumpSources(Func);
724 }
725 
emitIAS(const Cfg * Func) const726 template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
727   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
728   Asm->abs_d(getDest(), getSrc(0));
729 }
730 
emitIAS(const Cfg * Func) const731 template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
732   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
733   Asm->abs_s(getDest(), getSrc(0));
734 }
735 
emitIAS(const Cfg * Func) const736 template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const {
737   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
738   Asm->addi(getDest(), getSrc(0), Imm);
739 }
740 
emitIAS(const Cfg * Func) const741 template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
742   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
743   Asm->add_d(getDest(), getSrc(0), getSrc(1));
744 }
745 
emitIAS(const Cfg * Func) const746 template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
747   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
748   Asm->add_s(getDest(), getSrc(0), getSrc(1));
749 }
750 
emitIAS(const Cfg * Func) const751 template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
752   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
753   if (Reloc == RO_No) {
754     Asm->addiu(getDest(), getSrc(0), Imm);
755   } else {
756     Asm->addiu(getDest(), getSrc(0), getSrc(1), Reloc);
757   }
758 }
759 
emitIAS(const Cfg * Func) const760 template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
761   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
762   Asm->addu(getDest(), getSrc(0), getSrc(1));
763 }
764 
emitIAS(const Cfg * Func) const765 template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
766   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
767   Asm->and_(getDest(), getSrc(0), getSrc(1));
768 }
769 
emitIAS(const Cfg * Func) const770 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
771   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
772   Asm->andi(getDest(), getSrc(0), Imm);
773 }
774 
emitIAS(const Cfg * Func) const775 template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const {
776   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
777   Asm->c_eq_d(getSrc(0), getSrc(1));
778 }
779 
emitIAS(const Cfg * Func) const780 template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const {
781   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
782   Asm->c_eq_s(getSrc(0), getSrc(1));
783 }
784 
emitIAS(const Cfg * Func) const785 template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const {
786   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
787   Asm->c_ole_d(getSrc(0), getSrc(1));
788 }
789 
emitIAS(const Cfg * Func) const790 template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const {
791   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
792   Asm->c_ole_s(getSrc(0), getSrc(1));
793 }
794 
emitIAS(const Cfg * Func) const795 template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const {
796   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
797   Asm->c_olt_d(getSrc(0), getSrc(1));
798 }
799 
emitIAS(const Cfg * Func) const800 template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const {
801   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
802   Asm->c_olt_s(getSrc(0), getSrc(1));
803 }
804 
emitIAS(const Cfg * Func) const805 template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const {
806   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
807   Asm->c_ueq_d(getSrc(0), getSrc(1));
808 }
809 
emitIAS(const Cfg * Func) const810 template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const {
811   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
812   Asm->c_ueq_s(getSrc(0), getSrc(1));
813 }
814 
emitIAS(const Cfg * Func) const815 template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const {
816   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
817   Asm->c_ule_d(getSrc(0), getSrc(1));
818 }
819 
emitIAS(const Cfg * Func) const820 template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const {
821   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
822   Asm->c_ule_s(getSrc(0), getSrc(1));
823 }
824 
emitIAS(const Cfg * Func) const825 template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const {
826   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
827   Asm->c_ult_d(getSrc(0), getSrc(1));
828 }
829 
emitIAS(const Cfg * Func) const830 template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const {
831   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
832   Asm->c_ult_s(getSrc(0), getSrc(1));
833 }
834 
emitIAS(const Cfg * Func) const835 template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const {
836   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
837   Asm->c_un_d(getSrc(0), getSrc(1));
838 }
839 
emitIAS(const Cfg * Func) const840 template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const {
841   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
842   Asm->c_un_s(getSrc(0), getSrc(1));
843 }
844 
emitIAS(const Cfg * Func) const845 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
846   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
847   Asm->clz(getDest(), getSrc(0));
848 }
849 
emitIAS(const Cfg * Func) const850 template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const {
851   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
852   Asm->cvt_d_l(getDest(), getSrc(0));
853 }
854 
emitIAS(const Cfg * Func) const855 template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const {
856   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
857   Asm->cvt_d_s(getDest(), getSrc(0));
858 }
859 
emitIAS(const Cfg * Func) const860 template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const {
861   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
862   Asm->cvt_d_w(getDest(), getSrc(0));
863 }
864 
emitIAS(const Cfg * Func) const865 template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const {
866   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
867   Asm->cvt_s_d(getDest(), getSrc(0));
868 }
869 
emitIAS(const Cfg * Func) const870 template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const {
871   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
872   Asm->cvt_s_l(getDest(), getSrc(0));
873 }
874 
emitIAS(const Cfg * Func) const875 template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
876   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
877   Asm->cvt_s_w(getDest(), getSrc(0));
878 }
879 
emitIAS(const Cfg * Func) const880 template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const {
881   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
882   Asm->div(getSrc(0), getSrc(1));
883 }
884 
emitIAS(const Cfg * Func) const885 template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
886   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
887   Asm->div_d(getDest(), getSrc(0), getSrc(1));
888 }
889 
emitIAS(const Cfg * Func) const890 template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
891   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
892   Asm->div_s(getDest(), getSrc(0), getSrc(1));
893 }
894 
emitIAS(const Cfg * Func) const895 template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const {
896   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
897   Asm->divu(getSrc(0), getSrc(1));
898 }
899 
emitIAS(const Cfg * Func) const900 template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const {
901   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
902   Asm->lui(getDest(), getSrc(0), Reloc);
903 }
904 
emitIAS(const Cfg * Func) const905 template <> void InstMIPS32Ldc1::emitIAS(const Cfg *Func) const {
906   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
907   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
908   Asm->ldc1(getDest(), Mem->getBase(), Mem->getOffset(), Reloc);
909 }
910 
emitIAS(const Cfg * Func) const911 template <> void InstMIPS32Ll::emitIAS(const Cfg *Func) const {
912   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
913   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
914   ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
915   uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
916   Asm->ll(getDest(), Mem->getBase(), Imm);
917 }
918 
emitIAS(const Cfg * Func) const919 template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
920   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
921   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
922   ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
923   uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
924   Asm->lw(getDest(), Mem->getBase(), Imm);
925 }
926 
emitIAS(const Cfg * Func) const927 template <> void InstMIPS32Lwc1::emitIAS(const Cfg *Func) const {
928   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
929   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
930   Asm->lwc1(getDest(), Mem->getBase(), Mem->getOffset(), Reloc);
931 }
932 
emitIAS(const Cfg * Func) const933 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
934   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
935   Asm->mfc1(getDest(), getSrc(0));
936 }
937 
emit(const Cfg * Func) const938 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
939   if (!BuildDefs::dump())
940     return;
941   emitUnaryopGPRFLoHi(Opcode, this, Func);
942 }
943 
emitIAS(const Cfg * Func) const944 template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const {
945   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
946   Asm->mflo(getDest());
947 }
948 
emit(const Cfg * Func) const949 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
950   if (!BuildDefs::dump())
951     return;
952   emitUnaryopGPRFLoHi(Opcode, this, Func);
953 }
954 
emitIAS(const Cfg * Func) const955 template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const {
956   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
957   Asm->mfhi(getDest());
958 }
959 
emitIAS(const Cfg * Func) const960 template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
961   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
962   Asm->mov_d(getDest(), getSrc(0));
963 }
964 
emitIAS(const Cfg * Func) const965 template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
966   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
967   Asm->mov_s(getDest(), getSrc(0));
968 }
969 
emitIAS(const Cfg * Func) const970 template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const {
971   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
972   Asm->movf(getDest(), getSrc(0), getSrc(1));
973 }
974 
emitIAS(const Cfg * Func) const975 template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const {
976   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
977   Asm->movn(getDest(), getSrc(0), getSrc(1));
978 }
979 
emitIAS(const Cfg * Func) const980 template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const {
981   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
982   Asm->movn_d(getDest(), getSrc(0), getSrc(1));
983 }
984 
emitIAS(const Cfg * Func) const985 template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const {
986   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
987   Asm->movn_s(getDest(), getSrc(0), getSrc(1));
988 }
989 
emitIAS(const Cfg * Func) const990 template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const {
991   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
992   Asm->movt(getDest(), getSrc(0), getSrc(1));
993 }
994 
emitIAS(const Cfg * Func) const995 template <> void InstMIPS32Movz::emitIAS(const Cfg *Func) const {
996   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
997   Asm->movz(getDest(), getSrc(0), getSrc(1));
998 }
999 
emitIAS(const Cfg * Func) const1000 template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const {
1001   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1002   Asm->movz_d(getDest(), getSrc(0), getSrc(1));
1003 }
1004 
emitIAS(const Cfg * Func) const1005 template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const {
1006   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1007   Asm->movz_s(getDest(), getSrc(0), getSrc(1));
1008 }
1009 
emit(const Cfg * Func) const1010 template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const {
1011   if (!BuildDefs::dump())
1012     return;
1013   Ostream &Str = Func->getContext()->getStrEmit();
1014   assert(getSrcSize() == 1);
1015   Str << "\t" << Opcode << "\t";
1016   getSrc(0)->emit(Func);
1017   Str << ", ";
1018   getDest()->emit(Func);
1019 }
1020 
emitIAS(const Cfg * Func) const1021 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
1022   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1023   Asm->mtc1(getSrc(0), getDest());
1024 }
1025 
emit(const Cfg * Func) const1026 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
1027   if (!BuildDefs::dump())
1028     return;
1029   emitUnaryopGPRTLoHi(Opcode, this, Func);
1030 }
1031 
emitIAS(const Cfg * Func) const1032 template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const {
1033   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1034   Asm->mtlo(getDest());
1035 }
1036 
emit(const Cfg * Func) const1037 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
1038   if (!BuildDefs::dump())
1039     return;
1040   emitUnaryopGPRTLoHi(Opcode, this, Func);
1041 }
1042 
emitIAS(const Cfg * Func) const1043 template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const {
1044   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1045   Asm->mthi(getDest());
1046 }
1047 
emitIAS(const Cfg * Func) const1048 template <> void InstMIPS32Mul::emitIAS(const Cfg *Func) const {
1049   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1050   Asm->mul(getDest(), getSrc(0), getSrc(1));
1051 }
1052 
emitIAS(const Cfg * Func) const1053 template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const {
1054   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1055   Asm->mul_d(getDest(), getSrc(0), getSrc(1));
1056 }
1057 
emitIAS(const Cfg * Func) const1058 template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const {
1059   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1060   Asm->mul_s(getDest(), getSrc(0), getSrc(1));
1061 }
1062 
emit(const Cfg * Func) const1063 template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
1064   if (!BuildDefs::dump())
1065     return;
1066   emitThreeAddrLoHi(Opcode, this, Func);
1067 }
1068 
emitIAS(const Cfg * Func) const1069 template <> void InstMIPS32Mult::emitIAS(const Cfg *Func) const {
1070   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1071   Asm->mult(getDest(), getSrc(0));
1072 }
1073 
emit(const Cfg * Func) const1074 template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
1075   if (!BuildDefs::dump())
1076     return;
1077   emitThreeAddrLoHi(Opcode, this, Func);
1078 }
1079 
emitIAS(const Cfg * Func) const1080 template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const {
1081   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1082   Asm->multu(getSrc(0), getSrc(1));
1083 }
1084 
emitIAS(const Cfg * Func) const1085 template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
1086   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1087   Asm->nor(getDest(), getSrc(0), getSrc(1));
1088 }
1089 
emitIAS(const Cfg * Func) const1090 template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
1091   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1092   Asm->or_(getDest(), getSrc(0), getSrc(1));
1093 }
1094 
emitIAS(const Cfg * Func) const1095 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
1096   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1097   Asm->ori(getDest(), getSrc(0), Imm);
1098 }
1099 
emitIAS(const Cfg * Func) const1100 template <> void InstMIPS32Sc::emitIAS(const Cfg *Func) const {
1101   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1102   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1103   ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1104   uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1105   Asm->sc(getSrc(0), Mem->getBase(), Imm);
1106 }
1107 
emitIAS(const Cfg * Func) const1108 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
1109   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1110   Asm->sll(getDest(), getSrc(0), Imm);
1111 }
1112 
emitIAS(const Cfg * Func) const1113 template <> void InstMIPS32Sllv::emitIAS(const Cfg *Func) const {
1114   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1115   Asm->sllv(getDest(), getSrc(0), getSrc(1));
1116 }
1117 
emitIAS(const Cfg * Func) const1118 template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
1119   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1120   Asm->slt(getDest(), getSrc(0), getSrc(1));
1121 }
1122 
emitIAS(const Cfg * Func) const1123 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
1124   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1125   Asm->slti(getDest(), getSrc(0), Imm);
1126 }
1127 
emitIAS(const Cfg * Func) const1128 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
1129   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1130   Asm->sltiu(getDest(), getSrc(0), Imm);
1131 }
1132 
emitIAS(const Cfg * Func) const1133 template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
1134   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1135   Asm->sltu(getDest(), getSrc(0), getSrc(1));
1136 }
1137 
emitIAS(const Cfg * Func) const1138 template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
1139   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1140   Asm->sqrt_d(getDest(), getSrc(0));
1141 }
1142 
emitIAS(const Cfg * Func) const1143 template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
1144   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1145   Asm->sqrt_s(getDest(), getSrc(0));
1146 }
1147 
emitIAS(const Cfg * Func) const1148 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
1149   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1150   Asm->sra(getDest(), getSrc(0), Imm);
1151 }
1152 
emitIAS(const Cfg * Func) const1153 template <> void InstMIPS32Srav::emitIAS(const Cfg *Func) const {
1154   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1155   Asm->srav(getDest(), getSrc(0), getSrc(1));
1156 }
1157 
emitIAS(const Cfg * Func) const1158 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
1159   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1160   Asm->srl(getDest(), getSrc(0), Imm);
1161 }
1162 
emitIAS(const Cfg * Func) const1163 template <> void InstMIPS32Srlv::emitIAS(const Cfg *Func) const {
1164   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1165   Asm->srlv(getDest(), getSrc(0), getSrc(1));
1166 }
1167 
emitIAS(const Cfg * Func) const1168 template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const {
1169   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1170   Asm->sub_d(getDest(), getSrc(0), getSrc(1));
1171 }
1172 
emitIAS(const Cfg * Func) const1173 template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const {
1174   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1175   Asm->sub_s(getDest(), getSrc(0), getSrc(1));
1176 }
1177 
emitIAS(const Cfg * Func) const1178 template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const {
1179   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1180   Asm->subu(getDest(), getSrc(0), getSrc(1));
1181 }
1182 
emitIAS(const Cfg * Func) const1183 template <> void InstMIPS32Sdc1::emitIAS(const Cfg *Func) const {
1184   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1185   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
1186   Asm->sdc1(getSrc(0), Mem->getBase(), Mem->getOffset(), Reloc);
1187 }
1188 
emitIAS(const Cfg * Func) const1189 template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
1190   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1191   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1192   ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1193   uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1194   Asm->sw(getSrc(0), Mem->getBase(), Imm);
1195 }
1196 
emitIAS(const Cfg * Func) const1197 template <> void InstMIPS32Swc1::emitIAS(const Cfg *Func) const {
1198   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1199   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
1200   Asm->swc1(getSrc(0), Mem->getBase(), Mem->getOffset(), Reloc);
1201 }
1202 
emitIAS(const Cfg * Func) const1203 void InstMIPS32Sync::emitIAS(const Cfg *Func) const {
1204   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1205   Asm->sync();
1206 }
1207 
emitIAS(const Cfg * Func) const1208 template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
1209   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1210   Asm->teq(getSrc(0), getSrc(1), getTrapCode());
1211 }
1212 
emitIAS(const Cfg * Func) const1213 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
1214   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1215   Asm->trunc_l_d(getDest(), getSrc(0));
1216 }
1217 
emitIAS(const Cfg * Func) const1218 template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const {
1219   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1220   Asm->trunc_l_s(getDest(), getSrc(0));
1221 }
1222 
emitIAS(const Cfg * Func) const1223 template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const {
1224   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1225   Asm->trunc_w_d(getDest(), getSrc(0));
1226 }
1227 
emitIAS(const Cfg * Func) const1228 template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const {
1229   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1230   Asm->trunc_w_s(getDest(), getSrc(0));
1231 }
1232 
emitIAS(const Cfg * Func) const1233 template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
1234   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1235   Asm->xor_(getDest(), getSrc(0), getSrc(1));
1236 }
1237 
emitIAS(const Cfg * Func) const1238 template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
1239   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1240   Asm->xori(getDest(), getSrc(0), Imm);
1241 }
1242 
1243 } // end of namespace MIPS32
1244 } // end of namespace Ice
1245