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