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 
61 template <> const char *InstMIPS32Abs_d::Opcode = "abs.d";
62 template <> const char *InstMIPS32Abs_s::Opcode = "abs.s";
63 template <> const char *InstMIPS32Addi::Opcode = "addi";
64 template <> const char *InstMIPS32Add::Opcode = "add";
65 template <> const char *InstMIPS32Add_d::Opcode = "add.d";
66 template <> const char *InstMIPS32Add_s::Opcode = "add.s";
67 template <> const char *InstMIPS32Addiu::Opcode = "addiu";
68 template <> const char *InstMIPS32Addu::Opcode = "addu";
69 template <> const char *InstMIPS32And::Opcode = "and";
70 template <> const char *InstMIPS32Andi::Opcode = "andi";
71 template <> const char *InstMIPS32C_eq_d::Opcode = "c.eq.d";
72 template <> const char *InstMIPS32C_eq_s::Opcode = "c.eq.s";
73 template <> const char *InstMIPS32C_ole_d::Opcode = "c.ole.d";
74 template <> const char *InstMIPS32C_ole_s::Opcode = "c.ole.s";
75 template <> const char *InstMIPS32C_olt_d::Opcode = "c.olt.d";
76 template <> const char *InstMIPS32C_olt_s::Opcode = "c.olt.s";
77 template <> const char *InstMIPS32C_ueq_d::Opcode = "c.ueq.d";
78 template <> const char *InstMIPS32C_ueq_s::Opcode = "c.ueq.s";
79 template <> const char *InstMIPS32C_ule_d::Opcode = "c.ule.d";
80 template <> const char *InstMIPS32C_ule_s::Opcode = "c.ule.s";
81 template <> const char *InstMIPS32C_ult_d::Opcode = "c.ult.d";
82 template <> const char *InstMIPS32C_ult_s::Opcode = "c.ult.s";
83 template <> const char *InstMIPS32C_un_d::Opcode = "c.un.d";
84 template <> const char *InstMIPS32C_un_s::Opcode = "c.un.s";
85 template <> const char *InstMIPS32Clz::Opcode = "clz";
86 template <> const char *InstMIPS32Cvt_d_l::Opcode = "cvt.d.l";
87 template <> const char *InstMIPS32Cvt_d_s::Opcode = "cvt.d.s";
88 template <> const char *InstMIPS32Cvt_d_w::Opcode = "cvt.d.w";
89 template <> const char *InstMIPS32Cvt_s_d::Opcode = "cvt.s.d";
90 template <> const char *InstMIPS32Cvt_s_l::Opcode = "cvt.s.l";
91 template <> const char *InstMIPS32Cvt_s_w::Opcode = "cvt.s.w";
92 template <> const char *InstMIPS32Div::Opcode = "div";
93 template <> const char *InstMIPS32Div_d::Opcode = "div.d";
94 template <> const char *InstMIPS32Div_s::Opcode = "div.s";
95 template <> const char *InstMIPS32Divu::Opcode = "divu";
96 template <> const char *InstMIPS32La::Opcode = "la";
97 template <> const char *InstMIPS32Ldc1::Opcode = "ldc1";
98 template <> const char *InstMIPS32Ll::Opcode = "ll";
99 template <> const char *InstMIPS32Lui::Opcode = "lui";
100 template <> const char *InstMIPS32Lw::Opcode = "lw";
101 template <> const char *InstMIPS32Lwc1::Opcode = "lwc1";
102 template <> const char *InstMIPS32Mfc1::Opcode = "mfc1";
103 template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
104 template <> const char *InstMIPS32Mflo::Opcode = "mflo";
105 template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
106 template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
107 template <> const char *InstMIPS32Movf::Opcode = "movf";
108 template <> const char *InstMIPS32Movn::Opcode = "movn";
109 template <> const char *InstMIPS32Movn_d::Opcode = "movn.d";
110 template <> const char *InstMIPS32Movn_s::Opcode = "movn.s";
111 template <> const char *InstMIPS32Movt::Opcode = "movt";
112 template <> const char *InstMIPS32Movz::Opcode = "movz";
113 template <> const char *InstMIPS32Movz_d::Opcode = "movz.d";
114 template <> const char *InstMIPS32Movz_s::Opcode = "movz.s";
115 template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
116 template <> const char *InstMIPS32Mthi::Opcode = "mthi";
117 template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
118 template <> const char *InstMIPS32Mul::Opcode = "mul";
119 template <> const char *InstMIPS32Mul_d::Opcode = "mul.d";
120 template <> const char *InstMIPS32Mul_s::Opcode = "mul.s";
121 template <> const char *InstMIPS32Mult::Opcode = "mult";
122 template <> const char *InstMIPS32Multu::Opcode = "multu";
123 template <> const char *InstMIPS32Nor::Opcode = "nor";
124 template <> const char *InstMIPS32Or::Opcode = "or";
125 template <> const char *InstMIPS32Ori::Opcode = "ori";
126 template <> const char *InstMIPS32Sc::Opcode = "sc";
127 template <> const char *InstMIPS32Sdc1::Opcode = "sdc1";
128 template <> const char *InstMIPS32Sll::Opcode = "sll";
129 template <> const char *InstMIPS32Sllv::Opcode = "sllv";
130 template <> const char *InstMIPS32Slt::Opcode = "slt";
131 template <> const char *InstMIPS32Slti::Opcode = "slti";
132 template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
133 template <> const char *InstMIPS32Sltu::Opcode = "sltu";
134 template <> const char *InstMIPS32Sqrt_d::Opcode = "sqrt.d";
135 template <> const char *InstMIPS32Sqrt_s::Opcode = "sqrt.s";
136 template <> const char *InstMIPS32Sra::Opcode = "sra";
137 template <> const char *InstMIPS32Srav::Opcode = "srav";
138 template <> const char *InstMIPS32Srl::Opcode = "srl";
139 template <> const char *InstMIPS32Srlv::Opcode = "srlv";
140 template <> const char *InstMIPS32Sub::Opcode = "sub";
141 template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
142 template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
143 template <> const char *InstMIPS32Subu::Opcode = "subu";
144 template <> const char *InstMIPS32Sw::Opcode = "sw";
145 template <> const char *InstMIPS32Swc1::Opcode = "swc1";
146 const char *InstMIPS32Sync::Opcode = "sync";
147 template <> const char *InstMIPS32Teq::Opcode = "teq";
148 template <> const char *InstMIPS32Trunc_l_d::Opcode = "trunc.l.d";
149 template <> const char *InstMIPS32Trunc_l_s::Opcode = "trunc.l.s";
150 template <> const char *InstMIPS32Trunc_w_d::Opcode = "trunc.w.d";
151 template <> const char *InstMIPS32Trunc_w_s::Opcode = "trunc.w.s";
152 template <> const char *InstMIPS32Xor::Opcode = "xor";
153 template <> const char *InstMIPS32Xori::Opcode = "xori";
154 
emit(const Cfg * Func) const155 template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
156   if (!BuildDefs::dump())
157     return;
158   Ostream &Str = Func->getContext()->getStrEmit();
159   assert(getSrcSize() == 1);
160   Str << "\t" << Opcode << "\t";
161   getDest()->emit(Func);
162   Str << ", ";
163   auto *Src0 = llvm::cast<Constant>(getSrc(0));
164   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
165     emitRelocOp(Str, Reloc);
166     Str << "(";
167     CR->emitWithoutPrefix(Func->getTarget());
168     Str << ")";
169   } else {
170     Src0->emit(Func);
171   }
172 }
173 
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)174 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
175                            const CfgNode *TargetFalse,
176                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
177     : InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
178       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {}
179 
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,Operand * Src0,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)180 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
181                            const CfgNode *TargetFalse, Operand *Src0,
182                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
183     : InstMIPS32(Func, InstMIPS32::Br, 1, nullptr), TargetTrue(TargetTrue),
184       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
185   addSource(Src0);
186 }
187 
InstMIPS32Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,Operand * Src0,Operand * Src1,const InstMIPS32Label * Label,CondMIPS32::Cond Cond)188 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
189                            const CfgNode *TargetFalse, Operand *Src0,
190                            Operand *Src1, const InstMIPS32Label *Label,
191                            CondMIPS32::Cond Cond)
192     : InstMIPS32(Func, InstMIPS32::Br, 2, nullptr), TargetTrue(TargetTrue),
193       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
194   addSource(Src0);
195   addSource(Src1);
196 }
197 
getOppositeCondition(CondMIPS32::Cond Cond)198 CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
199   return InstMIPS32CondAttributes[Cond].Opposite;
200 }
201 
optimizeBranch(const CfgNode * NextNode)202 bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
203   // If there is no next block, then there can be no fallthrough to optimize.
204   if (NextNode == nullptr)
205     return false;
206   // Intra-block conditional branches can't be optimized.
207   if (Label != nullptr)
208     return false;
209   // Unconditional branch to the next node can be removed.
210   if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
211     assert(getTargetTrue() == nullptr);
212     setDeleted();
213     return true;
214   }
215   // If there is no fallthrough node, such as a non-default case label for a
216   // switch instruction, then there is no opportunity to optimize.
217   if (getTargetTrue() == nullptr)
218     return false;
219   // If the fallthrough is to the next node, set fallthrough to nullptr to
220   // indicate.
221   if (getTargetTrue() == NextNode) {
222     TargetTrue = nullptr;
223     return true;
224   }
225   // If TargetFalse is the next node, and TargetTrue is not nullptr
226   // then invert the branch condition, swap the targets, and set new
227   // fallthrough to nullptr.
228   if (getTargetFalse() == NextNode) {
229     assert(Predicate != CondMIPS32::AL);
230     setPredicate(getOppositeCondition(getPredicate()));
231     TargetFalse = getTargetTrue();
232     TargetTrue = nullptr;
233     return true;
234   }
235   return false;
236 }
237 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)238 bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
239   bool Found = false;
240   if (TargetFalse == OldNode) {
241     TargetFalse = NewNode;
242     Found = true;
243   }
244   if (TargetTrue == OldNode) {
245     TargetTrue = NewNode;
246     Found = true;
247   }
248   return Found;
249 }
250 
InstMIPS32Label(Cfg * Func,TargetMIPS32 * Target)251 InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
252     : InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
253       Number(Target->makeNextLabelNumber()) {
254   if (BuildDefs::dump()) {
255     Name = GlobalString::createWithString(
256         Func->getContext(),
257         ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
258   } else {
259     Name = GlobalString::createWithoutString(Func->getContext());
260   }
261 }
262 
dump(const Cfg * Func) const263 void InstMIPS32Label::dump(const Cfg *Func) const {
264   if (!BuildDefs::dump())
265     return;
266   Ostream &Str = Func->getContext()->getStrDump();
267   Str << getLabelName() << ":";
268 }
269 
emit(const Cfg * Func) const270 void InstMIPS32Label::emit(const Cfg *Func) const {
271   if (!BuildDefs::dump())
272     return;
273   Ostream &Str = Func->getContext()->getStrEmit();
274   Str << getLabelName() << ":";
275 }
276 
emitIAS(const Cfg * Func) const277 void InstMIPS32Label::emitIAS(const Cfg *Func) const {
278   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
279   Asm->bindLocalLabel(this, Number);
280 }
281 
InstMIPS32Call(Cfg * Func,Variable * Dest,Operand * CallTarget)282 InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
283     : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
284   HasSideEffects = true;
285   addSource(CallTarget);
286 }
287 
InstMIPS32Mov(Cfg * Func,Variable * Dest,Operand * Src,Operand * Src2)288 InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src,
289                              Operand *Src2)
290     : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
291   auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
292   auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
293 
294   assert(Dest64 == nullptr || Src64 == nullptr);
295 
296   if (Dest->getType() == IceType_f64 && Src2 != nullptr) {
297     addSource(Src);
298     addSource(Src2);
299     return;
300   }
301 
302   if (Dest64 != nullptr) {
303     // this-> is needed below because there is a parameter named Dest.
304     this->Dest = Dest64->getLo();
305     DestHi = Dest64->getHi();
306   }
307 
308   if (Src64 == nullptr) {
309     addSource(Src);
310   } else {
311     addSource(Src64->getLo());
312     addSource(Src64->getHi());
313   }
314 }
315 
InstMIPS32MovFP64ToI64(Cfg * Func,Variable * Dst,Operand * Src,Int64Part Int64HiLo)316 InstMIPS32MovFP64ToI64::InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dst,
317                                                Operand *Src,
318                                                Int64Part Int64HiLo)
319     : InstMIPS32(Func, InstMIPS32::Mov_fp, 1, Dst), Int64HiLo(Int64HiLo) {
320   addSource(Src);
321 }
322 
InstMIPS32Ret(Cfg * Func,Variable * RA,Variable * Source)323 InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
324     : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
325   addSource(RA);
326   if (Source)
327     addSource(Source);
328 }
329 
330 // ======================== Dump routines ======================== //
331 
dump(const Cfg * Func) const332 void InstMIPS32::dump(const Cfg *Func) const {
333   if (!BuildDefs::dump())
334     return;
335   Ostream &Str = Func->getContext()->getStrDump();
336   Str << "[MIPS32] ";
337   Inst::dump(Func);
338 }
339 
emit(const Cfg * Func) const340 void OperandMIPS32Mem::emit(const Cfg *Func) const {
341   if (!BuildDefs::dump())
342     return;
343   Ostream &Str = Func->getContext()->getStrEmit();
344   Operand *Offset = getOffset();
345   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
346     Str << "(";
347     CR->emitWithoutPrefix(Func->getTarget());
348     Str << ")";
349   } else
350     Offset->emit(Func);
351   Str << "(";
352   getBase()->emit(Func);
353   Str << ")";
354 }
355 
emitUnaryopGPR(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)356 void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
357                                 const Cfg *Func) {
358   if (!BuildDefs::dump())
359     return;
360   Ostream &Str = Func->getContext()->getStrEmit();
361   Str << "\t" << Opcode << "\t";
362   Inst->getDest()->emit(Func);
363   Str << ", ";
364   Inst->getSrc(0)->emit(Func);
365 }
emitUnaryopGPRFLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)366 void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
367                                      const Cfg *Func) {
368   if (!BuildDefs::dump())
369     return;
370   Ostream &Str = Func->getContext()->getStrEmit();
371   Str << "\t" << Opcode << "\t";
372   Inst->getDest()->emit(Func);
373 }
374 
emitUnaryopGPRTLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)375 void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
376                                      const Cfg *Func) {
377   if (!BuildDefs::dump())
378     return;
379   Ostream &Str = Func->getContext()->getStrEmit();
380   Str << "\t" << Opcode << "\t";
381   Inst->getSrc(0)->emit(Func);
382 }
383 
emitThreeAddr(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)384 void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
385                                const Cfg *Func) {
386   if (!BuildDefs::dump())
387     return;
388   Ostream &Str = Func->getContext()->getStrEmit();
389   assert(Inst->getSrcSize() == 2);
390   Str << "\t" << Opcode << "\t";
391   Inst->getDest()->emit(Func);
392   Str << ", ";
393   Inst->getSrc(0)->emit(Func);
394   Str << ", ";
395   Inst->getSrc(1)->emit(Func);
396 }
397 
emitTwoAddr(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)398 void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
399                              const Cfg *Func) {
400   if (!BuildDefs::dump())
401     return;
402   Ostream &Str = Func->getContext()->getStrEmit();
403   assert(Inst->getSrcSize() == 1);
404   Str << "\t" << Opcode << "\t";
405   Inst->getDest()->emit(Func);
406   Str << ", ";
407   Inst->getSrc(0)->emit(Func);
408 }
409 
emitThreeAddrLoHi(const char * Opcode,const InstMIPS32 * Inst,const Cfg * Func)410 void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
411                                    const Cfg *Func) {
412   if (!BuildDefs::dump())
413     return;
414   Ostream &Str = Func->getContext()->getStrEmit();
415   assert(Inst->getSrcSize() == 2);
416   Str << "\t" << Opcode << "\t";
417   Inst->getSrc(0)->emit(Func);
418   Str << ", ";
419   Inst->getSrc(1)->emit(Func);
420 }
421 
emit(const Cfg * Func) const422 void InstMIPS32Ret::emit(const Cfg *Func) const {
423   if (!BuildDefs::dump())
424     return;
425   assert(getSrcSize() > 0);
426   auto *RA = llvm::cast<Variable>(getSrc(0));
427   assert(RA->hasReg());
428   assert(RA->getRegNum() == RegMIPS32::Reg_RA);
429   Ostream &Str = Func->getContext()->getStrEmit();
430   Str << "\t"
431          "jr"
432          "\t";
433   RA->emit(Func);
434 }
435 
emitIAS(const Cfg * Func) const436 void InstMIPS32Br::emitIAS(const Cfg *Func) const {
437   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
438   if (Label != nullptr) {
439     // Intra-block branches are of kind bcc
440     if (isUnconditionalBranch()) {
441       Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()));
442     } else {
443       Asm->bcc(Predicate, getSrc(0), getSrc(1),
444                Asm->getOrCreateLocalLabel(Label->getNumber()));
445     }
446   } else if (isUnconditionalBranch()) {
447     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
448   } else {
449     switch (Predicate) {
450     default:
451       break;
452     case CondMIPS32::EQ:
453     case CondMIPS32::NE:
454       Asm->bcc(Predicate, getSrc(0), getSrc(1),
455                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
456       break;
457     case CondMIPS32::EQZ:
458     case CondMIPS32::NEZ:
459     case CondMIPS32::LEZ:
460     case CondMIPS32::LTZ:
461     case CondMIPS32::GEZ:
462     case CondMIPS32::GTZ:
463       Asm->bzc(Predicate, getSrc(0),
464                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
465       break;
466     }
467     if (getTargetTrue()) {
468       Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()));
469     }
470   }
471 }
472 
emit(const Cfg * Func) const473 void InstMIPS32Br::emit(const Cfg *Func) const {
474   if (!BuildDefs::dump())
475     return;
476   Ostream &Str = Func->getContext()->getStrEmit();
477   Str << "\t"
478          "b"
479       << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
480   if (Label != nullptr) {
481     if (isUnconditionalBranch()) {
482       Str << Label->getLabelName();
483     } else {
484       getSrc(0)->emit(Func);
485       Str << ", ";
486       getSrc(1)->emit(Func);
487       Str << ", " << Label->getLabelName();
488     }
489   } else {
490     if (isUnconditionalBranch()) {
491       Str << getTargetFalse()->getAsmName();
492     } else {
493       switch (Predicate) {
494       default:
495         break;
496       case CondMIPS32::EQ:
497       case CondMIPS32::NE: {
498         getSrc(0)->emit(Func);
499         Str << ", ";
500         getSrc(1)->emit(Func);
501         Str << ", ";
502         break;
503       }
504       case CondMIPS32::EQZ:
505       case CondMIPS32::NEZ:
506       case CondMIPS32::LEZ:
507       case CondMIPS32::LTZ:
508       case CondMIPS32::GEZ:
509       case CondMIPS32::GTZ: {
510         getSrc(0)->emit(Func);
511         Str << ", ";
512         break;
513       }
514       }
515       Str << getTargetFalse()->getAsmName();
516       if (getTargetTrue()) {
517         Str << "\n\t"
518             << "b"
519             << "\t" << getTargetTrue()->getAsmName();
520       }
521     }
522   }
523 }
524 
dump(const Cfg * Func) const525 void InstMIPS32Br::dump(const Cfg *Func) const {
526   if (!BuildDefs::dump())
527     return;
528   Ostream &Str = Func->getContext()->getStrDump();
529   Str << "\t"
530          "b"
531       << 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