OSDN Git Service

Subzero, MIPS32: Intrinsic call Ctlz for i32
[android-x86/external-swiftshader.git] / src / IceInstMIPS32.cpp
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
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
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
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 *InstMIPS32Add::Opcode = "add";
66 template <> const char *InstMIPS32Add_d::Opcode = "add.d";
67 template <> const char *InstMIPS32Add_s::Opcode = "add.s";
68 template <> const char *InstMIPS32Addiu::Opcode = "addiu";
69 template <> const char *InstMIPS32Addu::Opcode = "addu";
70 template <> const char *InstMIPS32And::Opcode = "and";
71 template <> const char *InstMIPS32Andi::Opcode = "andi";
72 template <> const char *InstMIPS32C_eq_d::Opcode = "c.eq.d";
73 template <> const char *InstMIPS32C_eq_s::Opcode = "c.eq.s";
74 template <> const char *InstMIPS32C_ole_d::Opcode = "c.ole.d";
75 template <> const char *InstMIPS32C_ole_s::Opcode = "c.ole.s";
76 template <> const char *InstMIPS32C_olt_d::Opcode = "c.olt.d";
77 template <> const char *InstMIPS32C_olt_s::Opcode = "c.olt.s";
78 template <> const char *InstMIPS32C_ueq_d::Opcode = "c.ueq.d";
79 template <> const char *InstMIPS32C_ueq_s::Opcode = "c.ueq.s";
80 template <> const char *InstMIPS32C_ule_d::Opcode = "c.ule.d";
81 template <> const char *InstMIPS32C_ule_s::Opcode = "c.ule.s";
82 template <> const char *InstMIPS32C_ult_d::Opcode = "c.ult.d";
83 template <> const char *InstMIPS32C_ult_s::Opcode = "c.ult.s";
84 template <> const char *InstMIPS32C_un_d::Opcode = "c.un.d";
85 template <> const char *InstMIPS32C_un_s::Opcode = "c.un.s";
86 template <> const char *InstMIPS32Clz::Opcode = "clz";
87 template <> const char *InstMIPS32Cvt_d_l::Opcode = "cvt.d.l";
88 template <> const char *InstMIPS32Cvt_d_s::Opcode = "cvt.d.s";
89 template <> const char *InstMIPS32Cvt_d_w::Opcode = "cvt.d.w";
90 template <> const char *InstMIPS32Cvt_s_d::Opcode = "cvt.s.d";
91 template <> const char *InstMIPS32Cvt_s_l::Opcode = "cvt.s.l";
92 template <> const char *InstMIPS32Cvt_s_w::Opcode = "cvt.s.w";
93 template <> const char *InstMIPS32Div::Opcode = "div";
94 template <> const char *InstMIPS32Div_d::Opcode = "div.d";
95 template <> const char *InstMIPS32Div_s::Opcode = "div.s";
96 template <> const char *InstMIPS32Divu::Opcode = "divu";
97 template <> const char *InstMIPS32La::Opcode = "la";
98 template <> const char *InstMIPS32Ldc1::Opcode = "ldc1";
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 *InstMIPS32Sdc1::Opcode = "sdc1";
127 template <> const char *InstMIPS32Sll::Opcode = "sll";
128 template <> const char *InstMIPS32Sllv::Opcode = "sllv";
129 template <> const char *InstMIPS32Slt::Opcode = "slt";
130 template <> const char *InstMIPS32Slti::Opcode = "slti";
131 template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
132 template <> const char *InstMIPS32Sltu::Opcode = "sltu";
133 template <> const char *InstMIPS32Sqrt_d::Opcode = "sqrt.d";
134 template <> const char *InstMIPS32Sqrt_s::Opcode = "sqrt.s";
135 template <> const char *InstMIPS32Sra::Opcode = "sra";
136 template <> const char *InstMIPS32Srav::Opcode = "srav";
137 template <> const char *InstMIPS32Srl::Opcode = "srl";
138 template <> const char *InstMIPS32Srlv::Opcode = "srlv";
139 template <> const char *InstMIPS32Sub::Opcode = "sub";
140 template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
141 template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
142 template <> const char *InstMIPS32Subu::Opcode = "subu";
143 template <> const char *InstMIPS32Sw::Opcode = "sw";
144 template <> const char *InstMIPS32Swc1::Opcode = "swc1";
145 template <> const char *InstMIPS32Teq::Opcode = "teq";
146 template <> const char *InstMIPS32Trunc_l_d::Opcode = "trunc.l.d";
147 template <> const char *InstMIPS32Trunc_l_s::Opcode = "trunc.l.s";
148 template <> const char *InstMIPS32Trunc_w_d::Opcode = "trunc.w.d";
149 template <> const char *InstMIPS32Trunc_w_s::Opcode = "trunc.w.s";
150 template <> const char *InstMIPS32Xor::Opcode = "xor";
151 template <> const char *InstMIPS32Xori::Opcode = "xori";
152
153 template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
154   if (!BuildDefs::dump())
155     return;
156   Ostream &Str = Func->getContext()->getStrEmit();
157   assert(getSrcSize() == 1);
158   Str << "\t" << Opcode << "\t";
159   getDest()->emit(Func);
160   Str << ", ";
161   auto *Src0 = llvm::cast<Constant>(getSrc(0));
162   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
163     emitRelocOp(Str, Reloc);
164     Str << "(";
165     CR->emitWithoutPrefix(Func->getTarget());
166     Str << ")";
167   } else {
168     Src0->emit(Func);
169   }
170 }
171
172 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
173                            const CfgNode *TargetFalse,
174                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
175     : InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
176       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {}
177
178 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
179                            const CfgNode *TargetFalse, Operand *Src0,
180                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
181     : InstMIPS32(Func, InstMIPS32::Br, 1, nullptr), TargetTrue(TargetTrue),
182       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
183   addSource(Src0);
184 }
185
186 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
187                            const CfgNode *TargetFalse, Operand *Src0,
188                            Operand *Src1, const InstMIPS32Label *Label,
189                            CondMIPS32::Cond Cond)
190     : InstMIPS32(Func, InstMIPS32::Br, 2, nullptr), TargetTrue(TargetTrue),
191       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
192   addSource(Src0);
193   addSource(Src1);
194 }
195
196 CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
197   return InstMIPS32CondAttributes[Cond].Opposite;
198 }
199
200 bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
201   // If there is no next block, then there can be no fallthrough to optimize.
202   if (NextNode == nullptr)
203     return false;
204   // Intra-block conditional branches can't be optimized.
205   if (Label != nullptr)
206     return false;
207   // Unconditional branch to the next node can be removed.
208   if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
209     assert(getTargetTrue() == nullptr);
210     setDeleted();
211     return true;
212   }
213   // If there is no fallthrough node, such as a non-default case label for a
214   // switch instruction, then there is no opportunity to optimize.
215   if (getTargetTrue() == nullptr)
216     return false;
217   // If the fallthrough is to the next node, set fallthrough to nullptr to
218   // indicate.
219   if (getTargetTrue() == NextNode) {
220     TargetTrue = nullptr;
221     return true;
222   }
223   // If TargetFalse is the next node, and TargetTrue is not nullptr
224   // then invert the branch condition, swap the targets, and set new
225   // fallthrough to nullptr.
226   if (getTargetFalse() == NextNode) {
227     assert(Predicate != CondMIPS32::AL);
228     setPredicate(getOppositeCondition(getPredicate()));
229     TargetFalse = getTargetTrue();
230     TargetTrue = nullptr;
231     return true;
232   }
233   return false;
234 }
235
236 bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
237   bool Found = false;
238   if (TargetFalse == OldNode) {
239     TargetFalse = NewNode;
240     Found = true;
241   }
242   if (TargetTrue == OldNode) {
243     TargetTrue = NewNode;
244     Found = true;
245   }
246   return Found;
247 }
248
249 InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
250     : InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
251       Number(Target->makeNextLabelNumber()) {
252   if (BuildDefs::dump()) {
253     Name = GlobalString::createWithString(
254         Func->getContext(),
255         ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
256   } else {
257     Name = GlobalString::createWithoutString(Func->getContext());
258   }
259 }
260
261 void InstMIPS32Label::dump(const Cfg *Func) const {
262   if (!BuildDefs::dump())
263     return;
264   Ostream &Str = Func->getContext()->getStrDump();
265   Str << getLabelName() << ":";
266 }
267
268 void InstMIPS32Label::emit(const Cfg *Func) const {
269   if (!BuildDefs::dump())
270     return;
271   Ostream &Str = Func->getContext()->getStrEmit();
272   Str << getLabelName() << ":";
273 }
274
275 void InstMIPS32Label::emitIAS(const Cfg *Func) const {
276   (void)Func;
277   llvm_unreachable("Not yet implemented");
278 }
279
280 InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
281     : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
282   HasSideEffects = true;
283   addSource(CallTarget);
284 }
285
286 InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src)
287     : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
288   auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
289   auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
290
291   assert(Dest64 == nullptr || Src64 == nullptr);
292
293   if (Dest64 != nullptr) {
294     // this-> is needed below because there is a parameter named Dest.
295     this->Dest = Dest64->getLo();
296     DestHi = Dest64->getHi();
297   }
298
299   if (Src64 == nullptr) {
300     addSource(Src);
301   } else {
302     addSource(Src64->getLo());
303     addSource(Src64->getHi());
304   }
305 }
306
307 InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
308     : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
309   addSource(RA);
310   if (Source)
311     addSource(Source);
312 }
313
314 // ======================== Dump routines ======================== //
315
316 void InstMIPS32::dump(const Cfg *Func) const {
317   if (!BuildDefs::dump())
318     return;
319   Ostream &Str = Func->getContext()->getStrDump();
320   Str << "[MIPS32] ";
321   Inst::dump(Func);
322 }
323
324 void OperandMIPS32Mem::emit(const Cfg *Func) const {
325   if (!BuildDefs::dump())
326     return;
327   Ostream &Str = Func->getContext()->getStrEmit();
328   Operand *Offset = getOffset();
329   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
330     Str << "(";
331     CR->emitWithoutPrefix(Func->getTarget());
332     Str << ")";
333   } else
334     Offset->emit(Func);
335   Str << "(";
336   getBase()->emit(Func);
337   Str << ")";
338 }
339
340 void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
341                                 const Cfg *Func) {
342   if (!BuildDefs::dump())
343     return;
344   Ostream &Str = Func->getContext()->getStrEmit();
345   Str << "\t" << Opcode << "\t";
346   Inst->getDest()->emit(Func);
347   Str << ", ";
348   Inst->getSrc(0)->emit(Func);
349 }
350 void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
351                                      const Cfg *Func) {
352   if (!BuildDefs::dump())
353     return;
354   Ostream &Str = Func->getContext()->getStrEmit();
355   Str << "\t" << Opcode << "\t";
356   Inst->getDest()->emit(Func);
357 }
358
359 void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
360                                      const Cfg *Func) {
361   if (!BuildDefs::dump())
362     return;
363   Ostream &Str = Func->getContext()->getStrEmit();
364   Str << "\t" << Opcode << "\t";
365   Inst->getSrc(0)->emit(Func);
366 }
367
368 void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
369                                const Cfg *Func) {
370   if (!BuildDefs::dump())
371     return;
372   Ostream &Str = Func->getContext()->getStrEmit();
373   assert(Inst->getSrcSize() == 2);
374   Str << "\t" << Opcode << "\t";
375   Inst->getDest()->emit(Func);
376   Str << ", ";
377   Inst->getSrc(0)->emit(Func);
378   Str << ", ";
379   Inst->getSrc(1)->emit(Func);
380 }
381
382 void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
383                              const Cfg *Func) {
384   if (!BuildDefs::dump())
385     return;
386   Ostream &Str = Func->getContext()->getStrEmit();
387   assert(Inst->getSrcSize() == 1);
388   Str << "\t" << Opcode << "\t";
389   Inst->getDest()->emit(Func);
390   Str << ", ";
391   Inst->getSrc(0)->emit(Func);
392 }
393
394 void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
395                                    const Cfg *Func) {
396   if (!BuildDefs::dump())
397     return;
398   Ostream &Str = Func->getContext()->getStrEmit();
399   assert(Inst->getSrcSize() == 2);
400   Str << "\t" << Opcode << "\t";
401   Inst->getSrc(0)->emit(Func);
402   Str << ", ";
403   Inst->getSrc(1)->emit(Func);
404 }
405
406 void InstMIPS32Ret::emit(const Cfg *Func) const {
407   if (!BuildDefs::dump())
408     return;
409   assert(getSrcSize() > 0);
410   auto *RA = llvm::cast<Variable>(getSrc(0));
411   assert(RA->hasReg());
412   assert(RA->getRegNum() == RegMIPS32::Reg_RA);
413   Ostream &Str = Func->getContext()->getStrEmit();
414   Str << "\t"
415          "jr"
416          "\t";
417   RA->emit(Func);
418 }
419
420 void InstMIPS32Br::emitIAS(const Cfg *Func) const {
421   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
422   if (isUnconditionalBranch()) {
423     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
424   } else {
425     switch (Predicate) {
426     default:
427       break;
428     case CondMIPS32::EQ:
429     case CondMIPS32::NE:
430       Asm->bcc(Predicate, getSrc(0), getSrc(1),
431                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
432       break;
433     case CondMIPS32::EQZ:
434     case CondMIPS32::NEZ:
435     case CondMIPS32::LEZ:
436     case CondMIPS32::LTZ:
437     case CondMIPS32::GEZ:
438     case CondMIPS32::GTZ:
439       Asm->bzc(Predicate, getSrc(0),
440                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
441       break;
442     }
443   }
444 }
445
446 void InstMIPS32Br::emit(const Cfg *Func) const {
447   if (!BuildDefs::dump())
448     return;
449   Ostream &Str = Func->getContext()->getStrEmit();
450   Str << "\t"
451          "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
452   if (Label != nullptr) {
453     getSrc(0)->emit(Func);
454     Str << ", ";
455     getSrc(1)->emit(Func);
456     Str << ", " << Label->getLabelName();
457   } else {
458     if (isUnconditionalBranch()) {
459       Str << getTargetFalse()->getAsmName();
460     } else {
461       switch (Predicate) {
462       default:
463         break;
464       case CondMIPS32::EQ:
465       case CondMIPS32::NE: {
466         getSrc(0)->emit(Func);
467         Str << ", ";
468         getSrc(1)->emit(Func);
469         Str << ", ";
470         break;
471       }
472       case CondMIPS32::EQZ:
473       case CondMIPS32::NEZ:
474       case CondMIPS32::LEZ:
475       case CondMIPS32::LTZ:
476       case CondMIPS32::GEZ:
477       case CondMIPS32::GTZ: {
478         getSrc(0)->emit(Func);
479         Str << ", ";
480         break;
481       }
482       }
483       Str << getTargetFalse()->getAsmName();
484       if (getTargetTrue()) {
485         Str << "\n\t"
486             << "b"
487             << "\t" << getTargetTrue()->getAsmName();
488       }
489     }
490   }
491 }
492
493 void InstMIPS32Br::dump(const Cfg *Func) const {
494   if (!BuildDefs::dump())
495     return;
496   Ostream &Str = Func->getContext()->getStrDump();
497   Str << "\t"
498          "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
499
500   if (Label != nullptr) {
501     getSrc(0)->dump(Func);
502     Str << ", ";
503     getSrc(1)->dump(Func);
504     Str << ", " << Label->getLabelName();
505   } else {
506     if (isUnconditionalBranch()) {
507       Str << getTargetFalse()->getAsmName();
508     } else {
509       dumpSources(Func);
510       Str << ", ";
511       Str << getTargetFalse()->getAsmName();
512       if (getTargetTrue()) {
513         Str << "\n\t"
514             << "b"
515             << "\t" << getTargetTrue()->getAsmName();
516       }
517     }
518   }
519 }
520
521 void InstMIPS32Call::emit(const Cfg *Func) const {
522   if (!BuildDefs::dump())
523     return;
524   Ostream &Str = Func->getContext()->getStrEmit();
525   assert(getSrcSize() == 1);
526   if (llvm::isa<ConstantInteger32>(getCallTarget())) {
527     // This shouldn't happen (typically have to copy the full 32-bits to a
528     // register and do an indirect jump).
529     llvm::report_fatal_error("MIPS2Call to ConstantInteger32");
530   } else if (const auto *CallTarget =
531                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
532     // Calls only have 24-bits, but the linker should insert veneers to extend
533     // the range if needed.
534     Str << "\t"
535            "jal"
536            "\t";
537     CallTarget->emitWithoutPrefix(Func->getTarget());
538   } else {
539     Str << "\t"
540            "jal"
541            "\t";
542     getCallTarget()->emit(Func);
543   }
544 }
545
546 void InstMIPS32Call::emitIAS(const Cfg *Func) const {
547   (void)Func;
548   llvm_unreachable("Not yet implemented");
549 }
550
551 void InstMIPS32Call::dump(const Cfg *Func) const {
552   if (!BuildDefs::dump())
553     return;
554   Ostream &Str = Func->getContext()->getStrDump();
555   if (getDest()) {
556     dumpDest(Func);
557     Str << " = ";
558   }
559   Str << "call ";
560   getCallTarget()->dump(Func);
561 }
562
563 void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
564   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
565   auto *RA = llvm::cast<Variable>(getSrc(0));
566   assert(RA->hasReg());
567   assert(RA->getRegNum() == RegMIPS32::Reg_RA);
568   (void)RA;
569   Asm->ret();
570 }
571
572 void InstMIPS32Ret::dump(const Cfg *Func) const {
573   if (!BuildDefs::dump())
574     return;
575   Ostream &Str = Func->getContext()->getStrDump();
576   Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
577   Str << "ret." << Ty << " ";
578   dumpSources(Func);
579 }
580
581 void InstMIPS32Mov::emit(const Cfg *Func) const {
582   if (!BuildDefs::dump())
583     return;
584   assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
585   if (isMultiDest()) {
586     emitMultiDestSingleSource(Func);
587     return;
588   }
589
590   if (isMultiSource()) {
591     emitSingleDestMultiSource(Func);
592     return;
593   }
594
595   emitSingleDestSingleSource(Func);
596 }
597
598 // TODO(jaydeep.patil) Handle all types of operands in mov
599 void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
600   assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
601
602   if (isMultiDest()) {
603     llvm_unreachable("Not yet implemented");
604   }
605   if (isMultiSource()) {
606     llvm_unreachable("Not yet implemented");
607   }
608
609   Variable *Dest = getDest();
610   Operand *Src = getSrc(0);
611   auto *SrcV = llvm::dyn_cast<Variable>(Src);
612   assert(!llvm::isa<Constant>(Src));
613   const bool DestIsReg = Dest->hasReg();
614   const bool SrcIsReg = (SrcV && SrcV->hasReg());
615
616   // reg to reg
617   if (DestIsReg && SrcIsReg) {
618     auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
619     Asm->move(getDest(), getSrc(0));
620     return;
621   }
622   llvm_unreachable("Not yet implemented");
623 }
624
625 void InstMIPS32Mov::dump(const Cfg *Func) const {
626   if (!BuildDefs::dump())
627     return;
628   assert(getSrcSize() == 1 || getSrcSize() == 2);
629   Ostream &Str = Func->getContext()->getStrDump();
630   Variable *Dest = getDest();
631   Variable *DestHi = getDestHi();
632   Dest->dump(Func);
633   if (DestHi) {
634     Str << ", ";
635     DestHi->dump(Func);
636   }
637   dumpOpcode(Str, " = mov", getDest()->getType());
638   Str << " ";
639   dumpSources(Func);
640 }
641
642 void InstMIPS32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
643   if (!BuildDefs::dump())
644     return;
645   Ostream &Str = Func->getContext()->getStrEmit();
646   Variable *DestLo = getDest();
647   Variable *DestHi = getDestHi();
648   auto *Src = llvm::cast<Variable>(getSrc(0));
649
650   assert(DestHi->hasReg());
651   assert(DestLo->hasReg());
652   assert(llvm::isa<Variable>(Src) && Src->hasReg());
653
654   // Str << "\t"
655   //    << "vmov" << getPredicate() << "\t";
656   DestLo->emit(Func);
657   Str << ", ";
658   DestHi->emit(Func);
659   Str << ", ";
660   Src->emit(Func);
661 }
662
663 void InstMIPS32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
664   if (!BuildDefs::dump())
665     return;
666   Ostream &Str = Func->getContext()->getStrEmit();
667   Variable *Dest = getDest();
668   auto *SrcLo = llvm::cast<Variable>(getSrc(0));
669   auto *SrcHi = llvm::cast<Variable>(getSrc(1));
670
671   assert(SrcHi->hasReg());
672   assert(SrcLo->hasReg());
673   assert(Dest->hasReg());
674   assert(getSrcSize() == 2);
675
676   // Str << "\t"
677   //    << "vmov" << getPredicate() << "\t";
678   Dest->emit(Func);
679   Str << ", ";
680   SrcLo->emit(Func);
681   Str << ", ";
682   SrcHi->emit(Func);
683 }
684
685 void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
686   if (!BuildDefs::dump())
687     return;
688   Ostream &Str = Func->getContext()->getStrEmit();
689   Variable *Dest = getDest();
690   Operand *Src = getSrc(0);
691   auto *SrcV = llvm::dyn_cast<Variable>(Src);
692
693   assert(!llvm::isa<Constant>(Src));
694
695   const char *ActualOpcode = nullptr;
696   const bool DestIsReg = Dest->hasReg();
697   const bool SrcIsReg = (SrcV && SrcV->hasReg());
698
699   // reg to reg
700   if (DestIsReg && SrcIsReg) {
701     const Type DstType = Dest->getType();
702     const Type SrcType = Src->getType();
703
704     // move GP to/from FP
705     if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
706         (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
707       if (isScalarFloatingType(DstType)) {
708         Str << "\t"
709                "mtc1"
710                "\t";
711         getSrc(0)->emit(Func);
712         Str << ", ";
713         getDest()->emit(Func);
714         return;
715       }
716       ActualOpcode = "mfc1";
717     } else {
718       switch (Dest->getType()) {
719       case IceType_f32:
720         ActualOpcode = "mov.s";
721         break;
722       case IceType_f64:
723         ActualOpcode = "mov.d";
724         break;
725       case IceType_i1:
726       case IceType_i8:
727       case IceType_i16:
728       case IceType_i32:
729         ActualOpcode = "move";
730         break;
731       default:
732         UnimplementedError(getFlags());
733         return;
734       }
735     }
736
737     assert(ActualOpcode);
738     Str << "\t" << ActualOpcode << "\t";
739     getDest()->emit(Func);
740     Str << ", ";
741     getSrc(0)->emit(Func);
742     return;
743   }
744
745   llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
746 }
747
748 template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
749   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
750   Asm->abs_d(getDest(), getSrc(0));
751 }
752
753 template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
754   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
755   Asm->abs_s(getDest(), getSrc(0));
756 }
757
758 template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
759   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
760   Asm->add_d(getDest(), getSrc(0), getSrc(1));
761 }
762
763 template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
764   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
765   Asm->add_s(getDest(), getSrc(0), getSrc(1));
766 }
767
768 template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
769   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
770   Asm->addiu(getDest(), getSrc(0), Imm);
771 }
772
773 template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
774   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
775   Asm->addu(getDest(), getSrc(0), getSrc(1));
776 }
777
778 template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
779   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
780   Asm->and_(getDest(), getSrc(0), getSrc(1));
781 }
782
783 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
784   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
785   Asm->andi(getDest(), getSrc(0), Imm);
786 }
787
788 template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const {
789   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
790   Asm->c_eq_d(getSrc(0), getSrc(1));
791 }
792
793 template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const {
794   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
795   Asm->c_eq_s(getSrc(0), getSrc(1));
796 }
797
798 template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const {
799   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
800   Asm->c_ole_d(getSrc(0), getSrc(1));
801 }
802
803 template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const {
804   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
805   Asm->c_ole_s(getSrc(0), getSrc(1));
806 }
807
808 template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const {
809   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
810   Asm->c_olt_d(getSrc(0), getSrc(1));
811 }
812
813 template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const {
814   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
815   Asm->c_olt_s(getSrc(0), getSrc(1));
816 }
817
818 template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const {
819   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
820   Asm->c_ueq_d(getSrc(0), getSrc(1));
821 }
822
823 template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const {
824   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
825   Asm->c_ueq_s(getSrc(0), getSrc(1));
826 }
827
828 template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const {
829   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
830   Asm->c_ule_d(getSrc(0), getSrc(1));
831 }
832
833 template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const {
834   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
835   Asm->c_ule_s(getSrc(0), getSrc(1));
836 }
837
838 template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const {
839   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
840   Asm->c_ult_d(getSrc(0), getSrc(1));
841 }
842
843 template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const {
844   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
845   Asm->c_ult_s(getSrc(0), getSrc(1));
846 }
847
848 template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const {
849   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
850   Asm->c_un_d(getSrc(0), getSrc(1));
851 }
852
853 template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const {
854   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
855   Asm->c_un_s(getSrc(0), getSrc(1));
856 }
857
858 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
859   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
860   Asm->clz(getDest(), getSrc(0));
861 }
862
863 template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const {
864   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
865   Asm->cvt_d_l(getDest(), getSrc(0));
866 }
867
868 template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const {
869   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
870   Asm->cvt_d_s(getDest(), getSrc(0));
871 }
872
873 template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const {
874   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
875   Asm->cvt_d_w(getDest(), getSrc(0));
876 }
877
878 template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const {
879   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
880   Asm->cvt_s_d(getDest(), getSrc(0));
881 }
882
883 template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const {
884   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
885   Asm->cvt_s_l(getDest(), getSrc(0));
886 }
887
888 template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
889   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
890   Asm->cvt_s_w(getDest(), getSrc(0));
891 }
892
893 template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
894   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
895   Asm->div_d(getDest(), getSrc(0), getSrc(1));
896 }
897
898 template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
899   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
900   Asm->div_s(getDest(), getSrc(0), getSrc(1));
901 }
902
903 template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
904   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
905   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
906   ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
907   uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
908   Asm->lw(getDest(), Mem->getBase(), Imm);
909 }
910
911 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
912   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
913   Asm->mfc1(getDest(), getSrc(0));
914 }
915
916 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
917   if (!BuildDefs::dump())
918     return;
919   emitUnaryopGPRFLoHi(Opcode, this, Func);
920 }
921
922 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
923   if (!BuildDefs::dump())
924     return;
925   emitUnaryopGPRFLoHi(Opcode, this, Func);
926 }
927
928 template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
929   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
930   Asm->mov_d(getDest(), getSrc(0));
931 }
932
933 template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
934   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
935   Asm->mov_s(getDest(), getSrc(0));
936 }
937
938 template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const {
939   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
940   Asm->movf(getDest(), getSrc(1), getSrc(2));
941 }
942
943 template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const {
944   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
945   Asm->movn(getDest(), getSrc(0), getSrc(1));
946 }
947
948 template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const {
949   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
950   Asm->movn_d(getDest(), getSrc(0), getSrc(1));
951 }
952
953 template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const {
954   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
955   Asm->movn_s(getDest(), getSrc(0), getSrc(1));
956 }
957
958 template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const {
959   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
960   Asm->movt(getDest(), getSrc(1), getSrc(2));
961 }
962
963 template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const {
964   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
965   Asm->movz_d(getDest(), getSrc(0), getSrc(1));
966 }
967
968 template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const {
969   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
970   Asm->movz_s(getDest(), getSrc(0), getSrc(1));
971 }
972
973 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
974   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
975   Asm->mtc1(getDest(), getSrc(0));
976 }
977
978 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
979   if (!BuildDefs::dump())
980     return;
981   emitUnaryopGPRTLoHi(Opcode, this, Func);
982 }
983
984 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
985   if (!BuildDefs::dump())
986     return;
987   emitUnaryopGPRTLoHi(Opcode, this, Func);
988 }
989
990 template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const {
991   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
992   Asm->mul_d(getDest(), getSrc(0), getSrc(1));
993 }
994
995 template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const {
996   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
997   Asm->mul_s(getDest(), getSrc(0), getSrc(1));
998 }
999
1000 template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
1001   if (!BuildDefs::dump())
1002     return;
1003   emitThreeAddrLoHi(Opcode, this, Func);
1004 }
1005
1006 template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
1007   if (!BuildDefs::dump())
1008     return;
1009   emitThreeAddrLoHi(Opcode, this, Func);
1010 }
1011
1012 template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
1013   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1014   Asm->nor(getDest(), getSrc(0), getSrc(1));
1015 }
1016
1017 template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
1018   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1019   Asm->or_(getDest(), getSrc(0), getSrc(1));
1020 }
1021
1022 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
1023   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1024   Asm->ori(getDest(), getSrc(0), Imm);
1025 }
1026
1027 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
1028   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1029   Asm->sll(getDest(), getSrc(0), Imm);
1030 }
1031
1032 template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
1033   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1034   Asm->slt(getDest(), getSrc(0), getSrc(1));
1035 }
1036
1037 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
1038   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1039   Asm->slti(getDest(), getSrc(0), Imm);
1040 }
1041
1042 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
1043   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1044   Asm->sltiu(getDest(), getSrc(0), Imm);
1045 }
1046
1047 template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
1048   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1049   Asm->sltu(getDest(), getSrc(0), getSrc(1));
1050 }
1051
1052 template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
1053   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1054   Asm->sqrt_d(getDest(), getSrc(0));
1055 }
1056
1057 template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
1058   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1059   Asm->sqrt_s(getDest(), getSrc(0));
1060 }
1061
1062 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
1063   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1064   Asm->sra(getDest(), getSrc(0), Imm);
1065 }
1066
1067 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
1068   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1069   Asm->srl(getDest(), getSrc(0), Imm);
1070 }
1071
1072 template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const {
1073   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1074   Asm->sub_d(getDest(), getSrc(0), getSrc(1));
1075 }
1076
1077 template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const {
1078   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1079   Asm->sub_s(getDest(), getSrc(0), getSrc(1));
1080 }
1081
1082 template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
1083   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1084   auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1085   ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1086   uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1087   Asm->sw(getSrc(0), Mem->getBase(), Imm);
1088 }
1089
1090 template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
1091   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1092   Asm->teq(getSrc(0), getSrc(1), getTrapCode());
1093 }
1094
1095 template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
1096   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1097   Asm->trunc_l_d(getDest(), getSrc(0));
1098 }
1099
1100 template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const {
1101   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1102   Asm->trunc_l_s(getDest(), getSrc(0));
1103 }
1104
1105 template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const {
1106   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1107   Asm->trunc_w_d(getDest(), getSrc(0));
1108 }
1109
1110 template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const {
1111   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1112   Asm->trunc_w_s(getDest(), getSrc(0));
1113 }
1114
1115 template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
1116   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1117   Asm->xor_(getDest(), getSrc(0), getSrc(1));
1118 }
1119
1120 template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
1121   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1122   Asm->xori(getDest(), getSrc(0), Imm);
1123 }
1124
1125 } // end of namespace MIPS32
1126 } // end of namespace Ice