1 //===- subzero/src/IceInstMips32.cpp - Mips32 instruction implementation --===//
3 // The Subzero Code Generator
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Implements the InstMips32 and OperandMips32 classes, primarily the
12 /// constructors and the dump()/emit() methods.
14 //===----------------------------------------------------------------------===//
15 #include "IceAssemblerMIPS32.h"
17 #include "IceCfgNode.h"
19 #include "IceInstMIPS32.h"
20 #include "IceOperand.h"
21 #include "IceRegistersMIPS32.h"
22 #include "IceTargetLoweringMIPS32.h"
28 const struct InstMIPS32CondAttributes_ {
29 CondMIPS32::Cond Opposite;
30 const char *EmitString;
31 } InstMIPS32CondAttributes[] = {
32 #define X(tag, opp, emit) \
33 { CondMIPS32::opp, emit } \
35 ICEINSTMIPS32COND_TABLE
39 bool OperandMIPS32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
42 if ((std::numeric_limits<int16_t>::min() <= Offset) &&
43 (Offset <= std::numeric_limits<int16_t>::max()))
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.
53 // assert(!isNegAddrMode());
58 const char *InstMIPS32::getWidthString(Type Ty) {
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";
153 template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
154 if (!BuildDefs::dump())
156 Ostream &Str = Func->getContext()->getStrEmit();
157 assert(getSrcSize() == 1);
158 Str << "\t" << Opcode << "\t";
159 getDest()->emit(Func);
161 auto *Src0 = llvm::cast<Constant>(getSrc(0));
162 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
163 emitRelocOp(Str, Reloc);
165 CR->emitWithoutPrefix(Func->getTarget());
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) {}
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) {
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) {
196 CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
197 return InstMIPS32CondAttributes[Cond].Opposite;
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)
204 // Intra-block conditional branches can't be optimized.
205 if (Label != nullptr)
207 // Unconditional branch to the next node can be removed.
208 if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
209 assert(getTargetTrue() == nullptr);
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)
217 // If the fallthrough is to the next node, set fallthrough to nullptr to
219 if (getTargetTrue() == NextNode) {
220 TargetTrue = nullptr;
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;
236 bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
238 if (TargetFalse == OldNode) {
239 TargetFalse = NewNode;
242 if (TargetTrue == OldNode) {
243 TargetTrue = NewNode;
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(
255 ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
257 Name = GlobalString::createWithoutString(Func->getContext());
261 void InstMIPS32Label::dump(const Cfg *Func) const {
262 if (!BuildDefs::dump())
264 Ostream &Str = Func->getContext()->getStrDump();
265 Str << getLabelName() << ":";
268 void InstMIPS32Label::emit(const Cfg *Func) const {
269 if (!BuildDefs::dump())
271 Ostream &Str = Func->getContext()->getStrEmit();
272 Str << getLabelName() << ":";
275 void InstMIPS32Label::emitIAS(const Cfg *Func) const {
277 llvm_unreachable("Not yet implemented");
280 InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
281 : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
282 HasSideEffects = true;
283 addSource(CallTarget);
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);
291 assert(Dest64 == nullptr || Src64 == nullptr);
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();
299 if (Src64 == nullptr) {
302 addSource(Src64->getLo());
303 addSource(Src64->getHi());
307 InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
308 : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
314 // ======================== Dump routines ======================== //
316 void InstMIPS32::dump(const Cfg *Func) const {
317 if (!BuildDefs::dump())
319 Ostream &Str = Func->getContext()->getStrDump();
324 void OperandMIPS32Mem::emit(const Cfg *Func) const {
325 if (!BuildDefs::dump())
327 Ostream &Str = Func->getContext()->getStrEmit();
328 Operand *Offset = getOffset();
329 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
331 CR->emitWithoutPrefix(Func->getTarget());
336 getBase()->emit(Func);
340 void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
342 if (!BuildDefs::dump())
344 Ostream &Str = Func->getContext()->getStrEmit();
345 Str << "\t" << Opcode << "\t";
346 Inst->getDest()->emit(Func);
348 Inst->getSrc(0)->emit(Func);
350 void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
352 if (!BuildDefs::dump())
354 Ostream &Str = Func->getContext()->getStrEmit();
355 Str << "\t" << Opcode << "\t";
356 Inst->getDest()->emit(Func);
359 void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
361 if (!BuildDefs::dump())
363 Ostream &Str = Func->getContext()->getStrEmit();
364 Str << "\t" << Opcode << "\t";
365 Inst->getSrc(0)->emit(Func);
368 void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
370 if (!BuildDefs::dump())
372 Ostream &Str = Func->getContext()->getStrEmit();
373 assert(Inst->getSrcSize() == 2);
374 Str << "\t" << Opcode << "\t";
375 Inst->getDest()->emit(Func);
377 Inst->getSrc(0)->emit(Func);
379 Inst->getSrc(1)->emit(Func);
382 void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
384 if (!BuildDefs::dump())
386 Ostream &Str = Func->getContext()->getStrEmit();
387 assert(Inst->getSrcSize() == 1);
388 Str << "\t" << Opcode << "\t";
389 Inst->getDest()->emit(Func);
391 Inst->getSrc(0)->emit(Func);
394 void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
396 if (!BuildDefs::dump())
398 Ostream &Str = Func->getContext()->getStrEmit();
399 assert(Inst->getSrcSize() == 2);
400 Str << "\t" << Opcode << "\t";
401 Inst->getSrc(0)->emit(Func);
403 Inst->getSrc(1)->emit(Func);
406 void InstMIPS32Ret::emit(const Cfg *Func) const {
407 if (!BuildDefs::dump())
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();
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()));
430 Asm->bcc(Predicate, getSrc(0), getSrc(1),
431 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
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()));
446 void InstMIPS32Br::emit(const Cfg *Func) const {
447 if (!BuildDefs::dump())
449 Ostream &Str = Func->getContext()->getStrEmit();
451 "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
452 if (Label != nullptr) {
453 getSrc(0)->emit(Func);
455 getSrc(1)->emit(Func);
456 Str << ", " << Label->getLabelName();
458 if (isUnconditionalBranch()) {
459 Str << getTargetFalse()->getAsmName();
465 case CondMIPS32::NE: {
466 getSrc(0)->emit(Func);
468 getSrc(1)->emit(Func);
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);
483 Str << getTargetFalse()->getAsmName();
484 if (getTargetTrue()) {
487 << "\t" << getTargetTrue()->getAsmName();
493 void InstMIPS32Br::dump(const Cfg *Func) const {
494 if (!BuildDefs::dump())
496 Ostream &Str = Func->getContext()->getStrDump();
498 "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
500 if (Label != nullptr) {
501 getSrc(0)->dump(Func);
503 getSrc(1)->dump(Func);
504 Str << ", " << Label->getLabelName();
506 if (isUnconditionalBranch()) {
507 Str << getTargetFalse()->getAsmName();
511 Str << getTargetFalse()->getAsmName();
512 if (getTargetTrue()) {
515 << "\t" << getTargetTrue()->getAsmName();
521 void InstMIPS32Call::emit(const Cfg *Func) const {
522 if (!BuildDefs::dump())
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.
537 CallTarget->emitWithoutPrefix(Func->getTarget());
542 getCallTarget()->emit(Func);
546 void InstMIPS32Call::emitIAS(const Cfg *Func) const {
548 llvm_unreachable("Not yet implemented");
551 void InstMIPS32Call::dump(const Cfg *Func) const {
552 if (!BuildDefs::dump())
554 Ostream &Str = Func->getContext()->getStrDump();
560 getCallTarget()->dump(Func);
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);
572 void InstMIPS32Ret::dump(const Cfg *Func) const {
573 if (!BuildDefs::dump())
575 Ostream &Str = Func->getContext()->getStrDump();
576 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
577 Str << "ret." << Ty << " ";
581 void InstMIPS32Mov::emit(const Cfg *Func) const {
582 if (!BuildDefs::dump())
584 assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
586 emitMultiDestSingleSource(Func);
590 if (isMultiSource()) {
591 emitSingleDestMultiSource(Func);
595 emitSingleDestSingleSource(Func);
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.");
603 llvm_unreachable("Not yet implemented");
605 if (isMultiSource()) {
606 llvm_unreachable("Not yet implemented");
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());
617 if (DestIsReg && SrcIsReg) {
618 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
619 Asm->move(getDest(), getSrc(0));
622 llvm_unreachable("Not yet implemented");
625 void InstMIPS32Mov::dump(const Cfg *Func) const {
626 if (!BuildDefs::dump())
628 assert(getSrcSize() == 1 || getSrcSize() == 2);
629 Ostream &Str = Func->getContext()->getStrDump();
630 Variable *Dest = getDest();
631 Variable *DestHi = getDestHi();
637 dumpOpcode(Str, " = mov", getDest()->getType());
642 void InstMIPS32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
643 if (!BuildDefs::dump())
645 Ostream &Str = Func->getContext()->getStrEmit();
646 Variable *DestLo = getDest();
647 Variable *DestHi = getDestHi();
648 auto *Src = llvm::cast<Variable>(getSrc(0));
650 assert(DestHi->hasReg());
651 assert(DestLo->hasReg());
652 assert(llvm::isa<Variable>(Src) && Src->hasReg());
655 // << "vmov" << getPredicate() << "\t";
663 void InstMIPS32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
664 if (!BuildDefs::dump())
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));
671 assert(SrcHi->hasReg());
672 assert(SrcLo->hasReg());
673 assert(Dest->hasReg());
674 assert(getSrcSize() == 2);
677 // << "vmov" << getPredicate() << "\t";
685 void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
686 if (!BuildDefs::dump())
688 Ostream &Str = Func->getContext()->getStrEmit();
689 Variable *Dest = getDest();
690 Operand *Src = getSrc(0);
691 auto *SrcV = llvm::dyn_cast<Variable>(Src);
693 assert(!llvm::isa<Constant>(Src));
695 const char *ActualOpcode = nullptr;
696 const bool DestIsReg = Dest->hasReg();
697 const bool SrcIsReg = (SrcV && SrcV->hasReg());
700 if (DestIsReg && SrcIsReg) {
701 const Type DstType = Dest->getType();
702 const Type SrcType = Src->getType();
704 // move GP to/from FP
705 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
706 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
707 if (isScalarFloatingType(DstType)) {
711 getSrc(0)->emit(Func);
713 getDest()->emit(Func);
716 ActualOpcode = "mfc1";
718 switch (Dest->getType()) {
720 ActualOpcode = "mov.s";
723 ActualOpcode = "mov.d";
729 ActualOpcode = "move";
732 UnimplementedError(getFlags());
737 assert(ActualOpcode);
738 Str << "\t" << ActualOpcode << "\t";
739 getDest()->emit(Func);
741 getSrc(0)->emit(Func);
745 llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
748 template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
749 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
750 Asm->abs_d(getDest(), getSrc(0));
753 template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
754 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
755 Asm->abs_s(getDest(), getSrc(0));
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));
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));
768 template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
769 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
770 Asm->addiu(getDest(), getSrc(0), Imm);
773 template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
774 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
775 Asm->addu(getDest(), getSrc(0), getSrc(1));
778 template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
779 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
780 Asm->and_(getDest(), getSrc(0), getSrc(1));
783 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
784 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
785 Asm->andi(getDest(), getSrc(0), Imm);
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
858 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
859 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
860 Asm->clz(getDest(), getSrc(0));
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));
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));
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));
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));
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));
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));
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));
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));
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);
911 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
912 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
913 Asm->mfc1(getDest(), getSrc(0));
916 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
917 if (!BuildDefs::dump())
919 emitUnaryopGPRFLoHi(Opcode, this, Func);
922 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
923 if (!BuildDefs::dump())
925 emitUnaryopGPRFLoHi(Opcode, this, Func);
928 template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
929 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
930 Asm->mov_d(getDest(), getSrc(0));
933 template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
934 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
935 Asm->mov_s(getDest(), getSrc(0));
938 template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const {
939 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
940 Asm->movf(getDest(), getSrc(1), getSrc(2));
943 template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const {
944 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
945 Asm->movn(getDest(), getSrc(0), getSrc(1));
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));
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));
958 template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const {
959 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
960 Asm->movt(getDest(), getSrc(1), getSrc(2));
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));
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));
973 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
974 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
975 Asm->mtc1(getDest(), getSrc(0));
978 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
979 if (!BuildDefs::dump())
981 emitUnaryopGPRTLoHi(Opcode, this, Func);
984 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
985 if (!BuildDefs::dump())
987 emitUnaryopGPRTLoHi(Opcode, this, Func);
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));
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));
1000 template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
1001 if (!BuildDefs::dump())
1003 emitThreeAddrLoHi(Opcode, this, Func);
1006 template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
1007 if (!BuildDefs::dump())
1009 emitThreeAddrLoHi(Opcode, this, Func);
1012 template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
1013 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1014 Asm->nor(getDest(), getSrc(0), getSrc(1));
1017 template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
1018 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1019 Asm->or_(getDest(), getSrc(0), getSrc(1));
1022 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
1023 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1024 Asm->ori(getDest(), getSrc(0), Imm);
1027 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
1028 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1029 Asm->sll(getDest(), getSrc(0), Imm);
1032 template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
1033 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1034 Asm->slt(getDest(), getSrc(0), getSrc(1));
1037 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
1038 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1039 Asm->slti(getDest(), getSrc(0), Imm);
1042 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
1043 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1044 Asm->sltiu(getDest(), getSrc(0), Imm);
1047 template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
1048 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1049 Asm->sltu(getDest(), getSrc(0), getSrc(1));
1052 template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
1053 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1054 Asm->sqrt_d(getDest(), getSrc(0));
1057 template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
1058 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1059 Asm->sqrt_s(getDest(), getSrc(0));
1062 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
1063 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1064 Asm->sra(getDest(), getSrc(0), Imm);
1067 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
1068 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1069 Asm->srl(getDest(), getSrc(0), Imm);
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));
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));
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);
1090 template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
1091 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1092 Asm->teq(getSrc(0), getSrc(1), getTrapCode());
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));
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));
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));
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));
1115 template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
1116 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1117 Asm->xor_(getDest(), getSrc(0), getSrc(1));
1120 template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
1121 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1122 Asm->xori(getDest(), getSrc(0), Imm);
1125 } // end of namespace MIPS32
1126 } // end of namespace Ice