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