Home | History | Annotate | Download | only in src
      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 *InstMIPS32Addi::Opcode = "addi";
     66 template <> const char *InstMIPS32Add::Opcode = "add";
     67 template <> const char *InstMIPS32Add_d::Opcode = "add.d";
     68 template <> const char *InstMIPS32Add_s::Opcode = "add.s";
     69 template <> const char *InstMIPS32Addiu::Opcode = "addiu";
     70 template <> const char *InstMIPS32Addu::Opcode = "addu";
     71 template <> const char *InstMIPS32And::Opcode = "and";
     72 template <> const char *InstMIPS32Andi::Opcode = "andi";
     73 template <> const char *InstMIPS32C_eq_d::Opcode = "c.eq.d";
     74 template <> const char *InstMIPS32C_eq_s::Opcode = "c.eq.s";
     75 template <> const char *InstMIPS32C_ole_d::Opcode = "c.ole.d";
     76 template <> const char *InstMIPS32C_ole_s::Opcode = "c.ole.s";
     77 template <> const char *InstMIPS32C_olt_d::Opcode = "c.olt.d";
     78 template <> const char *InstMIPS32C_olt_s::Opcode = "c.olt.s";
     79 template <> const char *InstMIPS32C_ueq_d::Opcode = "c.ueq.d";
     80 template <> const char *InstMIPS32C_ueq_s::Opcode = "c.ueq.s";
     81 template <> const char *InstMIPS32C_ule_d::Opcode = "c.ule.d";
     82 template <> const char *InstMIPS32C_ule_s::Opcode = "c.ule.s";
     83 template <> const char *InstMIPS32C_ult_d::Opcode = "c.ult.d";
     84 template <> const char *InstMIPS32C_ult_s::Opcode = "c.ult.s";
     85 template <> const char *InstMIPS32C_un_d::Opcode = "c.un.d";
     86 template <> const char *InstMIPS32C_un_s::Opcode = "c.un.s";
     87 template <> const char *InstMIPS32Clz::Opcode = "clz";
     88 template <> const char *InstMIPS32Cvt_d_l::Opcode = "cvt.d.l";
     89 template <> const char *InstMIPS32Cvt_d_s::Opcode = "cvt.d.s";
     90 template <> const char *InstMIPS32Cvt_d_w::Opcode = "cvt.d.w";
     91 template <> const char *InstMIPS32Cvt_s_d::Opcode = "cvt.s.d";
     92 template <> const char *InstMIPS32Cvt_s_l::Opcode = "cvt.s.l";
     93 template <> const char *InstMIPS32Cvt_s_w::Opcode = "cvt.s.w";
     94 template <> const char *InstMIPS32Div::Opcode = "div";
     95 template <> const char *InstMIPS32Div_d::Opcode = "div.d";
     96 template <> const char *InstMIPS32Div_s::Opcode = "div.s";
     97 template <> const char *InstMIPS32Divu::Opcode = "divu";
     98 template <> const char *InstMIPS32La::Opcode = "la";
     99 template <> const char *InstMIPS32Ldc1::Opcode = "ldc1";
    100 template <> const char *InstMIPS32Ll::Opcode = "ll";
    101 template <> const char *InstMIPS32Lui::Opcode = "lui";
    102 template <> const char *InstMIPS32Lw::Opcode = "lw";
    103 template <> const char *InstMIPS32Lwc1::Opcode = "lwc1";
    104 template <> const char *InstMIPS32Mfc1::Opcode = "mfc1";
    105 template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
    106 template <> const char *InstMIPS32Mflo::Opcode = "mflo";
    107 template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
    108 template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
    109 template <> const char *InstMIPS32Movf::Opcode = "movf";
    110 template <> const char *InstMIPS32Movn::Opcode = "movn";
    111 template <> const char *InstMIPS32Movn_d::Opcode = "movn.d";
    112 template <> const char *InstMIPS32Movn_s::Opcode = "movn.s";
    113 template <> const char *InstMIPS32Movt::Opcode = "movt";
    114 template <> const char *InstMIPS32Movz::Opcode = "movz";
    115 template <> const char *InstMIPS32Movz_d::Opcode = "movz.d";
    116 template <> const char *InstMIPS32Movz_s::Opcode = "movz.s";
    117 template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
    118 template <> const char *InstMIPS32Mthi::Opcode = "mthi";
    119 template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
    120 template <> const char *InstMIPS32Mul::Opcode = "mul";
    121 template <> const char *InstMIPS32Mul_d::Opcode = "mul.d";
    122 template <> const char *InstMIPS32Mul_s::Opcode = "mul.s";
    123 template <> const char *InstMIPS32Mult::Opcode = "mult";
    124 template <> const char *InstMIPS32Multu::Opcode = "multu";
    125 template <> const char *InstMIPS32Nor::Opcode = "nor";
    126 template <> const char *InstMIPS32Or::Opcode = "or";
    127 template <> const char *InstMIPS32Ori::Opcode = "ori";
    128 template <> const char *InstMIPS32Sc::Opcode = "sc";
    129 template <> const char *InstMIPS32Sdc1::Opcode = "sdc1";
    130 template <> const char *InstMIPS32Sll::Opcode = "sll";
    131 template <> const char *InstMIPS32Sllv::Opcode = "sllv";
    132 template <> const char *InstMIPS32Slt::Opcode = "slt";
    133 template <> const char *InstMIPS32Slti::Opcode = "slti";
    134 template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
    135 template <> const char *InstMIPS32Sltu::Opcode = "sltu";
    136 template <> const char *InstMIPS32Sqrt_d::Opcode = "sqrt.d";
    137 template <> const char *InstMIPS32Sqrt_s::Opcode = "sqrt.s";
    138 template <> const char *InstMIPS32Sra::Opcode = "sra";
    139 template <> const char *InstMIPS32Srav::Opcode = "srav";
    140 template <> const char *InstMIPS32Srl::Opcode = "srl";
    141 template <> const char *InstMIPS32Srlv::Opcode = "srlv";
    142 template <> const char *InstMIPS32Sub::Opcode = "sub";
    143 template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
    144 template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
    145 template <> const char *InstMIPS32Subu::Opcode = "subu";
    146 template <> const char *InstMIPS32Sw::Opcode = "sw";
    147 template <> const char *InstMIPS32Swc1::Opcode = "swc1";
    148 const char *InstMIPS32Sync::Opcode = "sync";
    149 template <> const char *InstMIPS32Teq::Opcode = "teq";
    150 template <> const char *InstMIPS32Trunc_l_d::Opcode = "trunc.l.d";
    151 template <> const char *InstMIPS32Trunc_l_s::Opcode = "trunc.l.s";
    152 template <> const char *InstMIPS32Trunc_w_d::Opcode = "trunc.w.d";
    153 template <> const char *InstMIPS32Trunc_w_s::Opcode = "trunc.w.s";
    154 template <> const char *InstMIPS32Xor::Opcode = "xor";
    155 template <> const char *InstMIPS32Xori::Opcode = "xori";
    156 
    157 template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
    158   if (!BuildDefs::dump())
    159     return;
    160   Ostream &Str = Func->getContext()->getStrEmit();
    161   assert(getSrcSize() == 1);
    162   Str << "\t" << Opcode << "\t";
    163   getDest()->emit(Func);
    164   Str << ", ";
    165   auto *Src0 = llvm::cast<Constant>(getSrc(0));
    166   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
    167     emitRelocOp(Str, Reloc);
    168     Str << "(";
    169     CR->emitWithoutPrefix(Func->getTarget());
    170     Str << ")";
    171   } else {
    172     Src0->emit(Func);
    173   }
    174 }
    175 
    176 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
    177                            const CfgNode *TargetFalse,
    178                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
    179     : InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
    180       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {}
    181 
    182 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
    183                            const CfgNode *TargetFalse, Operand *Src0,
    184                            const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
    185     : InstMIPS32(Func, InstMIPS32::Br, 1, nullptr), TargetTrue(TargetTrue),
    186       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
    187   addSource(Src0);
    188 }
    189 
    190 InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
    191                            const CfgNode *TargetFalse, Operand *Src0,
    192                            Operand *Src1, const InstMIPS32Label *Label,
    193                            CondMIPS32::Cond Cond)
    194     : InstMIPS32(Func, InstMIPS32::Br, 2, nullptr), TargetTrue(TargetTrue),
    195       TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
    196   addSource(Src0);
    197   addSource(Src1);
    198 }
    199 
    200 CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
    201   return InstMIPS32CondAttributes[Cond].Opposite;
    202 }
    203 
    204 bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
    205   // If there is no next block, then there can be no fallthrough to optimize.
    206   if (NextNode == nullptr)
    207     return false;
    208   // Intra-block conditional branches can't be optimized.
    209   if (Label != nullptr)
    210     return false;
    211   // Unconditional branch to the next node can be removed.
    212   if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
    213     assert(getTargetTrue() == nullptr);
    214     setDeleted();
    215     return true;
    216   }
    217   // If there is no fallthrough node, such as a non-default case label for a
    218   // switch instruction, then there is no opportunity to optimize.
    219   if (getTargetTrue() == nullptr)
    220     return false;
    221   // If the fallthrough is to the next node, set fallthrough to nullptr to
    222   // indicate.
    223   if (getTargetTrue() == NextNode) {
    224     TargetTrue = nullptr;
    225     return true;
    226   }
    227   // If TargetFalse is the next node, and TargetTrue is not nullptr
    228   // then invert the branch condition, swap the targets, and set new
    229   // fallthrough to nullptr.
    230   if (getTargetFalse() == NextNode) {
    231     assert(Predicate != CondMIPS32::AL);
    232     setPredicate(getOppositeCondition(getPredicate()));
    233     TargetFalse = getTargetTrue();
    234     TargetTrue = nullptr;
    235     return true;
    236   }
    237   return false;
    238 }
    239 
    240 bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
    241   bool Found = false;
    242   if (TargetFalse == OldNode) {
    243     TargetFalse = NewNode;
    244     Found = true;
    245   }
    246   if (TargetTrue == OldNode) {
    247     TargetTrue = NewNode;
    248     Found = true;
    249   }
    250   return Found;
    251 }
    252 
    253 InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
    254     : InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
    255       Number(Target->makeNextLabelNumber()) {
    256   if (BuildDefs::dump()) {
    257     Name = GlobalString::createWithString(
    258         Func->getContext(),
    259         ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
    260   } else {
    261     Name = GlobalString::createWithoutString(Func->getContext());
    262   }
    263 }
    264 
    265 void InstMIPS32Label::dump(const Cfg *Func) const {
    266   if (!BuildDefs::dump())
    267     return;
    268   Ostream &Str = Func->getContext()->getStrDump();
    269   Str << getLabelName() << ":";
    270 }
    271 
    272 void InstMIPS32Label::emit(const Cfg *Func) const {
    273   if (!BuildDefs::dump())
    274     return;
    275   Ostream &Str = Func->getContext()->getStrEmit();
    276   Str << getLabelName() << ":";
    277 }
    278 
    279 void InstMIPS32Label::emitIAS(const Cfg *Func) const {
    280   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    281   Asm->bindLocalLabel(this, Number);
    282 }
    283 
    284 InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
    285     : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
    286   HasSideEffects = true;
    287   addSource(CallTarget);
    288 }
    289 
    290 InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src,
    291                              Operand *Src2)
    292     : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
    293   auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
    294   auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
    295 
    296   assert(Dest64 == nullptr || Src64 == nullptr);
    297 
    298   if (Dest->getType() == IceType_f64 && Src2 != nullptr) {
    299     addSource(Src);
    300     addSource(Src2);
    301     return;
    302   }
    303 
    304   if (Dest64 != nullptr) {
    305     // this-> is needed below because there is a parameter named Dest.
    306     this->Dest = Dest64->getLo();
    307     DestHi = Dest64->getHi();
    308   }
    309 
    310   if (Src64 == nullptr) {
    311     addSource(Src);
    312   } else {
    313     addSource(Src64->getLo());
    314     addSource(Src64->getHi());
    315   }
    316 }
    317 
    318 InstMIPS32MovFP64ToI64::InstMIPS32MovFP64ToI64(Cfg *Func, Variable *Dst,
    319                                                Operand *Src,
    320                                                Int64Part Int64HiLo)
    321     : InstMIPS32(Func, InstMIPS32::Mov_fp, 1, Dst), Int64HiLo(Int64HiLo) {
    322   addSource(Src);
    323 }
    324 
    325 InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
    326     : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
    327   addSource(RA);
    328   if (Source)
    329     addSource(Source);
    330 }
    331 
    332 // ======================== Dump routines ======================== //
    333 
    334 void InstMIPS32::dump(const Cfg *Func) const {
    335   if (!BuildDefs::dump())
    336     return;
    337   Ostream &Str = Func->getContext()->getStrDump();
    338   Str << "[MIPS32] ";
    339   Inst::dump(Func);
    340 }
    341 
    342 void OperandMIPS32Mem::emit(const Cfg *Func) const {
    343   if (!BuildDefs::dump())
    344     return;
    345   Ostream &Str = Func->getContext()->getStrEmit();
    346   Operand *Offset = getOffset();
    347   if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
    348     Str << "(";
    349     CR->emitWithoutPrefix(Func->getTarget());
    350     Str << ")";
    351   } else
    352     Offset->emit(Func);
    353   Str << "(";
    354   getBase()->emit(Func);
    355   Str << ")";
    356 }
    357 
    358 void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
    359                                 const Cfg *Func) {
    360   if (!BuildDefs::dump())
    361     return;
    362   Ostream &Str = Func->getContext()->getStrEmit();
    363   Str << "\t" << Opcode << "\t";
    364   Inst->getDest()->emit(Func);
    365   Str << ", ";
    366   Inst->getSrc(0)->emit(Func);
    367 }
    368 void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
    369                                      const Cfg *Func) {
    370   if (!BuildDefs::dump())
    371     return;
    372   Ostream &Str = Func->getContext()->getStrEmit();
    373   Str << "\t" << Opcode << "\t";
    374   Inst->getDest()->emit(Func);
    375 }
    376 
    377 void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
    378                                      const Cfg *Func) {
    379   if (!BuildDefs::dump())
    380     return;
    381   Ostream &Str = Func->getContext()->getStrEmit();
    382   Str << "\t" << Opcode << "\t";
    383   Inst->getSrc(0)->emit(Func);
    384 }
    385 
    386 void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
    387                                const Cfg *Func) {
    388   if (!BuildDefs::dump())
    389     return;
    390   Ostream &Str = Func->getContext()->getStrEmit();
    391   assert(Inst->getSrcSize() == 2);
    392   Str << "\t" << Opcode << "\t";
    393   Inst->getDest()->emit(Func);
    394   Str << ", ";
    395   Inst->getSrc(0)->emit(Func);
    396   Str << ", ";
    397   Inst->getSrc(1)->emit(Func);
    398 }
    399 
    400 void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
    401                              const Cfg *Func) {
    402   if (!BuildDefs::dump())
    403     return;
    404   Ostream &Str = Func->getContext()->getStrEmit();
    405   assert(Inst->getSrcSize() == 1);
    406   Str << "\t" << Opcode << "\t";
    407   Inst->getDest()->emit(Func);
    408   Str << ", ";
    409   Inst->getSrc(0)->emit(Func);
    410 }
    411 
    412 void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
    413                                    const Cfg *Func) {
    414   if (!BuildDefs::dump())
    415     return;
    416   Ostream &Str = Func->getContext()->getStrEmit();
    417   assert(Inst->getSrcSize() == 2);
    418   Str << "\t" << Opcode << "\t";
    419   Inst->getSrc(0)->emit(Func);
    420   Str << ", ";
    421   Inst->getSrc(1)->emit(Func);
    422 }
    423 
    424 void InstMIPS32Ret::emit(const Cfg *Func) const {
    425   if (!BuildDefs::dump())
    426     return;
    427   assert(getSrcSize() > 0);
    428   auto *RA = llvm::cast<Variable>(getSrc(0));
    429   assert(RA->hasReg());
    430   assert(RA->getRegNum() == RegMIPS32::Reg_RA);
    431   Ostream &Str = Func->getContext()->getStrEmit();
    432   Str << "\t"
    433          "jr"
    434          "\t";
    435   RA->emit(Func);
    436 }
    437 
    438 void InstMIPS32Br::emitIAS(const Cfg *Func) const {
    439   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    440   if (Label != nullptr) {
    441     // Intra-block branches are of kind bcc
    442     if (isUnconditionalBranch()) {
    443       Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()));
    444     } else {
    445       Asm->bcc(Predicate, getSrc(0), getSrc(1),
    446                Asm->getOrCreateLocalLabel(Label->getNumber()));
    447     }
    448   } else if (isUnconditionalBranch()) {
    449     Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
    450   } else {
    451     switch (Predicate) {
    452     default:
    453       break;
    454     case CondMIPS32::EQ:
    455     case CondMIPS32::NE:
    456       Asm->bcc(Predicate, getSrc(0), getSrc(1),
    457                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
    458       break;
    459     case CondMIPS32::EQZ:
    460     case CondMIPS32::NEZ:
    461     case CondMIPS32::LEZ:
    462     case CondMIPS32::LTZ:
    463     case CondMIPS32::GEZ:
    464     case CondMIPS32::GTZ:
    465       Asm->bzc(Predicate, getSrc(0),
    466                Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
    467       break;
    468     }
    469     if (getTargetTrue()) {
    470       Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()));
    471     }
    472   }
    473 }
    474 
    475 void InstMIPS32Br::emit(const Cfg *Func) const {
    476   if (!BuildDefs::dump())
    477     return;
    478   Ostream &Str = Func->getContext()->getStrEmit();
    479   Str << "\t"
    480          "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
    481   if (Label != nullptr) {
    482     if (isUnconditionalBranch()) {
    483       Str << Label->getLabelName();
    484     } else {
    485       getSrc(0)->emit(Func);
    486       Str << ", ";
    487       getSrc(1)->emit(Func);
    488       Str << ", " << Label->getLabelName();
    489     }
    490   } else {
    491     if (isUnconditionalBranch()) {
    492       Str << getTargetFalse()->getAsmName();
    493     } else {
    494       switch (Predicate) {
    495       default:
    496         break;
    497       case CondMIPS32::EQ:
    498       case CondMIPS32::NE: {
    499         getSrc(0)->emit(Func);
    500         Str << ", ";
    501         getSrc(1)->emit(Func);
    502         Str << ", ";
    503         break;
    504       }
    505       case CondMIPS32::EQZ:
    506       case CondMIPS32::NEZ:
    507       case CondMIPS32::LEZ:
    508       case CondMIPS32::LTZ:
    509       case CondMIPS32::GEZ:
    510       case CondMIPS32::GTZ: {
    511         getSrc(0)->emit(Func);
    512         Str << ", ";
    513         break;
    514       }
    515       }
    516       Str << getTargetFalse()->getAsmName();
    517       if (getTargetTrue()) {
    518         Str << "\n\t"
    519             << "b"
    520             << "\t" << getTargetTrue()->getAsmName();
    521       }
    522     }
    523   }
    524 }
    525 
    526 void InstMIPS32Br::dump(const Cfg *Func) const {
    527   if (!BuildDefs::dump())
    528     return;
    529   Ostream &Str = Func->getContext()->getStrDump();
    530   Str << "\t"
    531          "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
    532 
    533   if (Label != nullptr) {
    534     if (isUnconditionalBranch()) {
    535       Str << Label->getLabelName();
    536     } else {
    537       getSrc(0)->dump(Func);
    538       Str << ", ";
    539       getSrc(1)->dump(Func);
    540       Str << ", " << Label->getLabelName();
    541     }
    542   } else {
    543     if (isUnconditionalBranch()) {
    544       Str << getTargetFalse()->getAsmName();
    545     } else {
    546       dumpSources(Func);
    547       Str << ", ";
    548       Str << getTargetFalse()->getAsmName();
    549       if (getTargetTrue()) {
    550         Str << "\n\t"
    551             << "b"
    552             << "\t" << getTargetTrue()->getAsmName();
    553       }
    554     }
    555   }
    556 }
    557 
    558 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 
    583 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 
    597 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 
    609 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 
    618 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 
    627 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 
    691 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 
    709 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 
    726 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 
    731 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 
    736 template <> void InstMIPS32Addi::emitIAS(const Cfg *Func) const {
    737   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    738   Asm->addi(getDest(), getSrc(0), Imm);
    739 }
    740 
    741 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 
    746 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 
    751 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 
    760 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 
    765 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 
    770 template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
    771   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    772   Asm->andi(getDest(), getSrc(0), Imm);
    773 }
    774 
    775 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 
    780 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 
    785 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 
    790 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 
    795 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 
    800 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 
    805 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 
    810 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 
    815 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 
    820 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 
    825 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 
    830 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 
    835 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 
    840 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 
    845 template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
    846   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    847   Asm->clz(getDest(), getSrc(0));
    848 }
    849 
    850 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 
    855 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 
    860 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 
    865 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 
    870 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 
    875 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 
    880 template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const {
    881   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    882   Asm->div(getSrc(0), getSrc(1));
    883 }
    884 
    885 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 
    890 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 
    895 template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const {
    896   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    897   Asm->divu(getSrc(0), getSrc(1));
    898 }
    899 
    900 template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const {
    901   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    902   Asm->lui(getDest(), getSrc(0), Reloc);
    903 }
    904 
    905 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 
    911 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 
    919 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 
    927 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 
    933 template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
    934   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    935   Asm->mfc1(getDest(), getSrc(0));
    936 }
    937 
    938 template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
    939   if (!BuildDefs::dump())
    940     return;
    941   emitUnaryopGPRFLoHi(Opcode, this, Func);
    942 }
    943 
    944 template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const {
    945   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    946   Asm->mflo(getDest());
    947 }
    948 
    949 template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
    950   if (!BuildDefs::dump())
    951     return;
    952   emitUnaryopGPRFLoHi(Opcode, this, Func);
    953 }
    954 
    955 template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const {
    956   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
    957   Asm->mfhi(getDest());
    958 }
    959 
    960 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 
    965 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 
    970 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 
    975 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 
    980 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 
    985 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 
    990 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 
    995 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 
   1000 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 
   1005 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 
   1010 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 
   1021 template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
   1022   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1023   Asm->mtc1(getSrc(0), getDest());
   1024 }
   1025 
   1026 template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
   1027   if (!BuildDefs::dump())
   1028     return;
   1029   emitUnaryopGPRTLoHi(Opcode, this, Func);
   1030 }
   1031 
   1032 template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const {
   1033   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1034   Asm->mtlo(getDest());
   1035 }
   1036 
   1037 template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
   1038   if (!BuildDefs::dump())
   1039     return;
   1040   emitUnaryopGPRTLoHi(Opcode, this, Func);
   1041 }
   1042 
   1043 template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const {
   1044   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1045   Asm->mthi(getDest());
   1046 }
   1047 
   1048 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 
   1053 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 
   1058 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 
   1063 template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
   1064   if (!BuildDefs::dump())
   1065     return;
   1066   emitThreeAddrLoHi(Opcode, this, Func);
   1067 }
   1068 
   1069 template <> void InstMIPS32Mult::emitIAS(const Cfg *Func) const {
   1070   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1071   Asm->mult(getDest(), getSrc(0));
   1072 }
   1073 
   1074 template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
   1075   if (!BuildDefs::dump())
   1076     return;
   1077   emitThreeAddrLoHi(Opcode, this, Func);
   1078 }
   1079 
   1080 template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const {
   1081   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1082   Asm->multu(getSrc(0), getSrc(1));
   1083 }
   1084 
   1085 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 
   1090 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 
   1095 template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
   1096   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1097   Asm->ori(getDest(), getSrc(0), Imm);
   1098 }
   1099 
   1100 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 
   1108 template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
   1109   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1110   Asm->sll(getDest(), getSrc(0), Imm);
   1111 }
   1112 
   1113 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 
   1118 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 
   1123 template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
   1124   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1125   Asm->slti(getDest(), getSrc(0), Imm);
   1126 }
   1127 
   1128 template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
   1129   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1130   Asm->sltiu(getDest(), getSrc(0), Imm);
   1131 }
   1132 
   1133 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 
   1138 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 
   1143 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 
   1148 template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
   1149   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1150   Asm->sra(getDest(), getSrc(0), Imm);
   1151 }
   1152 
   1153 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 
   1158 template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
   1159   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1160   Asm->srl(getDest(), getSrc(0), Imm);
   1161 }
   1162 
   1163 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 
   1168 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 
   1173 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 
   1178 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 
   1183 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 
   1189 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 
   1197 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 
   1203 void InstMIPS32Sync::emitIAS(const Cfg *Func) const {
   1204   auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
   1205   Asm->sync();
   1206 }
   1207 
   1208 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 
   1213 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 
   1218 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 
   1223 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 
   1228 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 
   1233 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 
   1238 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