1 //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===// 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 Assembler class for MIPS32. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "IceAssemblerMIPS32.h" 16 #include "IceCfgNode.h" 17 #include "IceRegistersMIPS32.h" 18 #include "IceUtils.h" 19 20 namespace { 21 22 using namespace Ice; 23 using namespace Ice::MIPS32; 24 25 // Offset modifier to current PC for next instruction. 26 static constexpr IOffsetT kPCReadOffset = 4; 27 28 // Mask to pull out PC offset from branch instruction. 29 static constexpr int kBranchOffsetBits = 16; 30 static constexpr IOffsetT kBranchOffsetMask = 0x0000ffff; 31 32 } // end of anonymous namespace 33 34 namespace Ice { 35 namespace MIPS32 { 36 37 void AssemblerMIPS32::emitTextInst(const std::string &Text, SizeT InstSize) { 38 AssemblerFixup *F = createTextFixup(Text, InstSize); 39 emitFixup(F); 40 for (SizeT I = 0; I < InstSize; ++I) { 41 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 42 Buffer.emit<char>(0); 43 } 44 } 45 46 namespace { 47 48 // TEQ $0, $0 - Trap if equal 49 static constexpr uint8_t TrapBytesRaw[] = {0x00, 0x00, 0x00, 0x34}; 50 51 const auto TrapBytes = 52 llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw)); 53 54 } // end of anonymous namespace 55 56 llvm::ArrayRef<uint8_t> AssemblerMIPS32::getNonExecBundlePadding() const { 57 return TrapBytes; 58 } 59 60 void AssemblerMIPS32::trap() { 61 AssemblerBuffer::EnsureCapacity ensured(&Buffer); 62 for (const uint8_t &Byte : reverse_range(TrapBytes)) 63 Buffer.emit<uint8_t>(Byte); 64 } 65 66 void AssemblerMIPS32::nop() { emitInst(0); } 67 68 void AssemblerMIPS32::padWithNop(intptr_t Padding) { 69 constexpr intptr_t InstWidth = sizeof(IValueT); 70 assert(Padding % InstWidth == 0 && 71 "Padding not multiple of instruction size"); 72 for (intptr_t i = 0; i < Padding; i += InstWidth) 73 nop(); 74 } 75 76 Label *AssemblerMIPS32::getOrCreateLabel(SizeT Number, LabelVector &Labels) { 77 Label *L = nullptr; 78 if (Number == Labels.size()) { 79 L = new (this->allocate<Label>()) Label(); 80 Labels.push_back(L); 81 return L; 82 } 83 if (Number > Labels.size()) { 84 Labels.resize(Number + 1); 85 } 86 L = Labels[Number]; 87 if (L == nullptr) { 88 L = new (this->allocate<Label>()) Label(); 89 Labels[Number] = L; 90 } 91 return L; 92 } 93 94 void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) { 95 if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) { 96 constexpr SizeT InstSize = 0; 97 emitTextInst(Node->getAsmName() + ":", InstSize); 98 } 99 SizeT NodeNumber = Node->getIndex(); 100 assert(!getPreliminary()); 101 Label *L = getOrCreateCfgNodeLabel(NodeNumber); 102 this->bind(L); 103 } 104 105 namespace { 106 107 // Checks that Offset can fit in imm16 constant of branch instruction. 108 void assertCanEncodeBranchOffset(IOffsetT Offset) { 109 (void)Offset; 110 (void)kBranchOffsetBits; 111 assert(Utils::IsAligned(Offset, 4)); 112 assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2)); 113 } 114 115 IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { 116 Offset -= kPCReadOffset; 117 assertCanEncodeBranchOffset(Offset); 118 Offset >>= 2; 119 Offset &= kBranchOffsetMask; 120 return (Inst & ~kBranchOffsetMask) | Offset; 121 } 122 123 enum RegSetWanted { WantGPRegs, WantFPRegs }; 124 125 IValueT getEncodedGPRegNum(const Variable *Var) { 126 assert(Var->hasReg() && isScalarIntegerType(Var->getType())); 127 const auto Reg = Var->getRegNum(); 128 return RegMIPS32::getEncodedGPR(Reg); 129 } 130 131 IValueT getEncodedFPRegNum(const Variable *Var) { 132 assert(Var->hasReg() && isScalarFloatingType(Var->getType())); 133 const auto Reg = Var->getRegNum(); 134 IValueT RegEncoding; 135 if (RegMIPS32::isFPRReg(Reg)) { 136 RegEncoding = RegMIPS32::getEncodedFPR(Reg); 137 } else { 138 RegEncoding = RegMIPS32::getEncodedFPR64(Reg); 139 } 140 return RegEncoding; 141 } 142 143 bool encodeOperand(const Operand *Opnd, IValueT &Value, 144 RegSetWanted WantedRegSet) { 145 Value = 0; 146 if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) { 147 if (Var->hasReg()) { 148 switch (WantedRegSet) { 149 case WantGPRegs: 150 Value = getEncodedGPRegNum(Var); 151 break; 152 case WantFPRegs: 153 Value = getEncodedFPRegNum(Var); 154 break; 155 } 156 return true; 157 } 158 return false; 159 } 160 return false; 161 } 162 163 IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, 164 const char *RegName, const char *InstName) { 165 IValueT Reg = 0; 166 if (encodeOperand(OpReg, Reg, WantedRegSet) != true) 167 llvm::report_fatal_error(std::string(InstName) + ": Can't find register " + 168 RegName); 169 return Reg; 170 } 171 172 IValueT encodeGPRegister(const Operand *OpReg, const char *RegName, 173 const char *InstName) { 174 return encodeRegister(OpReg, WantGPRegs, RegName, InstName); 175 } 176 177 IValueT encodeFPRegister(const Operand *OpReg, const char *RegName, 178 const char *InstName) { 179 return encodeRegister(OpReg, WantFPRegs, RegName, InstName); 180 } 181 182 } // end of anonymous namespace 183 184 IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) { 185 int16_t imm = (Inst & kBranchOffsetMask); 186 IOffsetT Offset = imm; 187 Offset = Offset << 2; 188 return (Offset + kPCReadOffset); 189 } 190 191 void AssemblerMIPS32::bind(Label *L) { 192 IOffsetT BoundPc = Buffer.size(); 193 assert(!L->isBound()); // Labels can only be bound once. 194 while (L->isLinked()) { 195 IOffsetT Position = L->getLinkPosition(); 196 IOffsetT Dest = BoundPc - Position; 197 IValueT Inst = Buffer.load<IValueT>(Position); 198 Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst)); 199 IOffsetT NextBrPc = decodeBranchOffset(Inst); 200 if (NextBrPc != 0) 201 NextBrPc = Position - NextBrPc; 202 L->setPosition(NextBrPc); 203 } 204 L->bindTo(BoundPc); 205 } 206 207 void AssemblerMIPS32::emitRsRt(IValueT Opcode, const Operand *OpRs, 208 const Operand *OpRt, const char *InsnName) { 209 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); 210 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 211 212 Opcode |= Rs << 21; 213 Opcode |= Rt << 16; 214 215 emitInst(Opcode); 216 } 217 218 void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt, 219 const Operand *OpRs, const uint32_t Imm, 220 const char *InsnName) { 221 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 222 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); 223 224 Opcode |= Rs << 21; 225 Opcode |= Rt << 16; 226 Opcode |= Imm & 0xffff; 227 228 emitInst(Opcode); 229 } 230 231 void AssemblerMIPS32::emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt, 232 const Operand *OpRs, 233 const Operand *OpImm, 234 const RelocOp Reloc, 235 const char *InsnName) { 236 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 237 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); 238 uint32_t Imm16 = 0; 239 240 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) { 241 emitFixup(createMIPS32Fixup(Reloc, OpRel)); 242 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) { 243 Imm16 = C32->getValue(); 244 } else { 245 llvm::report_fatal_error(std::string(InsnName) + ": Invalid 3rd operand"); 246 } 247 248 Opcode |= Rs << 21; 249 Opcode |= Rt << 16; 250 Opcode |= Imm16 & 0xffff; 251 252 emitInst(Opcode); 253 } 254 255 void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt, 256 const Operand *OpRs, const uint32_t Imm, 257 const char *InsnName) { 258 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); 259 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); 260 261 Opcode |= Rs << 21; 262 Opcode |= Ft << 16; 263 Opcode |= Imm & 0xffff; 264 265 emitInst(Opcode); 266 } 267 268 void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd, 269 const Operand *OpRt, const uint32_t Sa, 270 const char *InsnName) { 271 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); 272 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 273 274 Opcode |= Rt << 16; 275 Opcode |= Rd << 11; 276 Opcode |= (Sa & 0x1f) << 6; 277 278 emitInst(Opcode); 279 } 280 281 void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd, 282 const Operand *OpRs, const Operand *OpRt, 283 const char *InsnName) { 284 const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName); 285 const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName); 286 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 287 288 Opcode |= Rs << 21; 289 Opcode |= Rt << 16; 290 Opcode |= Rd << 11; 291 292 emitInst(Opcode); 293 } 294 295 void AssemblerMIPS32::emitCOP1Fcmp(IValueT Opcode, FPInstDataFormat Format, 296 const Operand *OpFs, const Operand *OpFt, 297 IValueT CC, const char *InsnName) { 298 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); 299 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); 300 301 Opcode |= CC << 8; 302 Opcode |= Fs << 11; 303 Opcode |= Ft << 16; 304 Opcode |= Format << 21; 305 306 emitInst(Opcode); 307 } 308 309 void AssemblerMIPS32::emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format, 310 const Operand *OpFd, const Operand *OpFs, 311 const char *InsnName) { 312 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); 313 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); 314 315 Opcode |= Fd << 6; 316 Opcode |= Fs << 11; 317 Opcode |= Format << 21; 318 319 emitInst(Opcode); 320 } 321 322 void AssemblerMIPS32::emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format, 323 const Operand *OpFd, 324 const Operand *OpFs, 325 const Operand *OpFt, 326 const char *InsnName) { 327 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); 328 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); 329 const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName); 330 331 Opcode |= Fd << 6; 332 Opcode |= Fs << 11; 333 Opcode |= Ft << 16; 334 Opcode |= Format << 21; 335 336 emitInst(Opcode); 337 } 338 339 void AssemblerMIPS32::emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format, 340 const Operand *OpFd, 341 const Operand *OpFs, 342 const Operand *OpRt, 343 const char *InsnName) { 344 const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName); 345 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); 346 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 347 348 Opcode |= Fd << 6; 349 Opcode |= Fs << 11; 350 Opcode |= Rt << 16; 351 Opcode |= Format << 21; 352 353 emitInst(Opcode); 354 } 355 356 void AssemblerMIPS32::emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt, 357 const Operand *OpFs, 358 const char *InsnName) { 359 const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName); 360 const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName); 361 Opcode |= Fs << 11; 362 Opcode |= Rt << 16; 363 364 emitInst(Opcode); 365 } 366 367 void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) { 368 static constexpr IValueT Opcode = 0x44000005; 369 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d"); 370 } 371 372 void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) { 373 static constexpr IValueT Opcode = 0x44000005; 374 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s"); 375 } 376 377 void AssemblerMIPS32::addi(const Operand *OpRt, const Operand *OpRs, 378 const uint32_t Imm) { 379 static constexpr IValueT Opcode = 0x20000000; 380 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addi"); 381 } 382 383 void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs, 384 const Operand *OpFt) { 385 static constexpr IValueT Opcode = 0x44000000; 386 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d"); 387 } 388 389 void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs, 390 const Operand *OpFt) { 391 static constexpr IValueT Opcode = 0x44000000; 392 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s"); 393 } 394 395 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, 396 const uint32_t Imm) { 397 static constexpr IValueT Opcode = 0x24000000; 398 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu"); 399 } 400 401 void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs, 402 const Operand *OpImm, const RelocOp Reloc) { 403 static constexpr IValueT Opcode = 0x24000000; 404 emitRtRsImm16Rel(Opcode, OpRt, OpRs, OpImm, Reloc, "addiu"); 405 } 406 407 void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs, 408 const Operand *OpRt) { 409 static constexpr IValueT Opcode = 0x00000021; 410 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu"); 411 } 412 413 void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs, 414 const Operand *OpRt) { 415 static constexpr IValueT Opcode = 0x00000024; 416 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and"); 417 } 418 419 void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs, 420 const uint32_t Imm) { 421 static constexpr IValueT Opcode = 0x30000000; 422 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi"); 423 } 424 425 void AssemblerMIPS32::b(Label *TargetLabel) { 426 static constexpr Operand *OpRsNone = nullptr; 427 static constexpr Operand *OpRtNone = nullptr; 428 if (TargetLabel->isBound()) { 429 const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); 430 emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest); 431 return; 432 } 433 const IOffsetT Position = Buffer.size(); 434 IOffsetT PrevPosition = TargetLabel->getEncodedPosition(); 435 if (PrevPosition != 0) 436 PrevPosition = Position - PrevPosition; 437 emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, PrevPosition); 438 TargetLabel->linkTo(*this, Position); 439 } 440 441 void AssemblerMIPS32::c_eq_d(const Operand *OpFs, const Operand *OpFt) { 442 static constexpr IValueT Opcode = 0x44000032; 443 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 444 "c.eq.d"); 445 } 446 447 void AssemblerMIPS32::c_eq_s(const Operand *OpFs, const Operand *OpFt) { 448 static constexpr IValueT Opcode = 0x44000032; 449 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 450 "c.eq.s"); 451 } 452 453 void AssemblerMIPS32::c_ole_d(const Operand *OpFs, const Operand *OpFt) { 454 static constexpr IValueT Opcode = 0x44000036; 455 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 456 "c.ole.d"); 457 } 458 459 void AssemblerMIPS32::c_ole_s(const Operand *OpFs, const Operand *OpFt) { 460 static constexpr IValueT Opcode = 0x44000036; 461 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 462 "c.ole.s"); 463 } 464 465 void AssemblerMIPS32::c_olt_d(const Operand *OpFs, const Operand *OpFt) { 466 static constexpr IValueT Opcode = 0x44000034; 467 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 468 "c.olt.d"); 469 } 470 471 void AssemblerMIPS32::c_olt_s(const Operand *OpFs, const Operand *OpFt) { 472 static constexpr IValueT Opcode = 0x44000034; 473 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 474 "c.olt.s"); 475 } 476 477 void AssemblerMIPS32::c_ueq_d(const Operand *OpFs, const Operand *OpFt) { 478 static constexpr IValueT Opcode = 0x44000033; 479 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 480 "c.ueq.d"); 481 } 482 483 void AssemblerMIPS32::c_ueq_s(const Operand *OpFs, const Operand *OpFt) { 484 static constexpr IValueT Opcode = 0x44000033; 485 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 486 "c.ueq.s"); 487 } 488 489 void AssemblerMIPS32::c_ule_d(const Operand *OpFs, const Operand *OpFt) { 490 static constexpr IValueT Opcode = 0x44000037; 491 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 492 "c.ule.d"); 493 } 494 495 void AssemblerMIPS32::c_ule_s(const Operand *OpFs, const Operand *OpFt) { 496 static constexpr IValueT Opcode = 0x44000037; 497 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 498 "c.ule.s"); 499 } 500 501 void AssemblerMIPS32::c_ult_d(const Operand *OpFs, const Operand *OpFt) { 502 static constexpr IValueT Opcode = 0x44000035; 503 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 504 "c.ult.d"); 505 } 506 507 void AssemblerMIPS32::c_ult_s(const Operand *OpFs, const Operand *OpFt) { 508 static constexpr IValueT Opcode = 0x44000035; 509 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 510 "c.ult.s"); 511 } 512 513 void AssemblerMIPS32::c_un_d(const Operand *OpFs, const Operand *OpFt) { 514 static constexpr IValueT Opcode = 0x44000031; 515 emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 516 "c.un.d"); 517 } 518 519 void AssemblerMIPS32::c_un_s(const Operand *OpFs, const Operand *OpFt) { 520 static constexpr IValueT Opcode = 0x44000031; 521 emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0, 522 "c.un.s"); 523 } 524 525 void AssemblerMIPS32::clz(const Operand *OpRd, const Operand *OpRs) { 526 IValueT Opcode = 0x70000020; 527 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "clz"); 528 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "clz"); 529 Opcode |= Rd << 11; 530 Opcode |= Rd << 16; 531 Opcode |= Rs << 21; 532 emitInst(Opcode); 533 } 534 535 void AssemblerMIPS32::cvt_d_l(const Operand *OpFd, const Operand *OpFs) { 536 static constexpr IValueT Opcode = 0x44000021; 537 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.d.l"); 538 } 539 540 void AssemblerMIPS32::cvt_d_s(const Operand *OpFd, const Operand *OpFs) { 541 static constexpr IValueT Opcode = 0x44000021; 542 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "cvt.d.s"); 543 } 544 545 void AssemblerMIPS32::cvt_d_w(const Operand *OpFd, const Operand *OpFs) { 546 static constexpr IValueT Opcode = 0x44000021; 547 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.d.w"); 548 } 549 550 void AssemblerMIPS32::cvt_s_d(const Operand *OpFd, const Operand *OpFs) { 551 static constexpr IValueT Opcode = 0x44000020; 552 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "cvt.s.d"); 553 } 554 555 void AssemblerMIPS32::cvt_s_l(const Operand *OpFd, const Operand *OpFs) { 556 static constexpr IValueT Opcode = 0x44000020; 557 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.s.l"); 558 } 559 560 void AssemblerMIPS32::cvt_s_w(const Operand *OpFd, const Operand *OpFs) { 561 static constexpr IValueT Opcode = 0x44000020; 562 emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.s.w"); 563 } 564 565 void AssemblerMIPS32::div(const Operand *OpRs, const Operand *OpRt) { 566 static constexpr IValueT Opcode = 0x0000001A; 567 emitRsRt(Opcode, OpRs, OpRt, "div"); 568 } 569 570 void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs, 571 const Operand *OpFt) { 572 static constexpr IValueT Opcode = 0x44000003; 573 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d"); 574 } 575 576 void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs, 577 const Operand *OpFt) { 578 static constexpr IValueT Opcode = 0x44000003; 579 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s"); 580 } 581 582 void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) { 583 static constexpr IValueT Opcode = 0x0000001B; 584 emitRsRt(Opcode, OpRs, OpRt, "divu"); 585 } 586 587 MIPS32Fixup *AssemblerMIPS32::createMIPS32Fixup(const RelocOp Reloc, 588 const Constant *RelOp) { 589 MIPS32Fixup *Fixup = new (allocate<MIPS32Fixup>()) MIPS32Fixup(); 590 switch (Reloc) { 591 case RelocOp::RO_Hi: 592 Fixup->set_kind(llvm::ELF::R_MIPS_HI16); 593 break; 594 case RelocOp::RO_Lo: 595 Fixup->set_kind(llvm::ELF::R_MIPS_LO16); 596 break; 597 case RelocOp::RO_Jal: 598 Fixup->set_kind(llvm::ELF::R_MIPS_26); 599 break; 600 default: 601 llvm::report_fatal_error("Fixup: Invalid Reloc type"); 602 break; 603 } 604 Fixup->set_value(RelOp); 605 Buffer.installFixup(Fixup); 606 return Fixup; 607 } 608 609 size_t MIPS32Fixup::emit(GlobalContext *Ctx, const Assembler &Asm) const { 610 if (!BuildDefs::dump()) 611 return InstMIPS32::InstSize; 612 Ostream &Str = Ctx->getStrEmit(); 613 IValueT Inst = Asm.load<IValueT>(position()); 614 const auto Symbol = symbol().toString(); 615 Str << "\t" 616 << ".word " << llvm::format_hex(Inst, 8) << " # "; 617 switch (kind()) { 618 case llvm::ELF::R_MIPS_HI16: 619 Str << "R_MIPS_HI16 "; 620 break; 621 case llvm::ELF::R_MIPS_LO16: 622 Str << "R_MIPS_LO16 "; 623 break; 624 case llvm::ELF::R_MIPS_26: 625 Str << "R_MIPS_26 "; 626 break; 627 default: 628 Str << "Unknown "; 629 break; 630 } 631 Str << Symbol << "\n"; 632 return InstMIPS32::InstSize; 633 } 634 635 void MIPS32Fixup::emitOffset(Assembler *Asm) const { 636 const IValueT Inst = Asm->load<IValueT>(position()); 637 IValueT ImmMask = 0; 638 const IValueT Imm = offset(); 639 if (kind() == llvm::ELF::R_MIPS_26) { 640 ImmMask = 0x03FFFFFF; 641 } else { 642 ImmMask = 0x0000FFFF; 643 } 644 Asm->store(position(), (Inst & ~ImmMask) | (Imm & ImmMask)); 645 } 646 647 void AssemblerMIPS32::jal(const ConstantRelocatable *Target) { 648 IValueT Opcode = 0x0C000000; 649 emitFixup(createMIPS32Fixup(RelocOp::RO_Jal, Target)); 650 emitInst(Opcode); 651 nop(); 652 } 653 654 void AssemblerMIPS32::jalr(const Operand *OpRs, const Operand *OpRd) { 655 IValueT Opcode = 0x00000009; 656 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "jalr"); 657 const IValueT Rd = 658 (OpRd == nullptr) ? 31 : encodeGPRegister(OpRd, "Rd", "jalr"); 659 Opcode |= Rd << 11; 660 Opcode |= Rs << 21; 661 emitInst(Opcode); 662 nop(); 663 } 664 665 void AssemblerMIPS32::lui(const Operand *OpRt, const Operand *OpImm, 666 const RelocOp Reloc) { 667 IValueT Opcode = 0x3C000000; 668 const IValueT Rt = encodeGPRegister(OpRt, "Rt", "lui"); 669 IValueT Imm16 = 0; 670 671 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) { 672 emitFixup(createMIPS32Fixup(Reloc, OpRel)); 673 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) { 674 Imm16 = C32->getValue(); 675 } else { 676 llvm::report_fatal_error("lui: Invalid 2nd operand"); 677 } 678 679 Opcode |= Rt << 16; 680 Opcode |= Imm16; 681 emitInst(Opcode); 682 } 683 684 void AssemblerMIPS32::ldc1(const Operand *OpRt, const Operand *OpBase, 685 const Operand *OpOff, const RelocOp Reloc) { 686 IValueT Opcode = 0xD4000000; 687 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "ldc1"); 688 const IValueT Base = encodeGPRegister(OpBase, "Base", "ldc1"); 689 IValueT Imm16 = 0; 690 691 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { 692 emitFixup(createMIPS32Fixup(Reloc, OpRel)); 693 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { 694 Imm16 = C32->getValue(); 695 } else { 696 llvm::report_fatal_error("ldc1: Invalid 2nd operand"); 697 } 698 699 Opcode |= Base << 21; 700 Opcode |= Rt << 16; 701 Opcode |= Imm16; 702 emitInst(Opcode); 703 } 704 705 void AssemblerMIPS32::ll(const Operand *OpRt, const Operand *OpBase, 706 const uint32_t Offset) { 707 static constexpr IValueT Opcode = 0xC0000000; 708 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "ll"); 709 } 710 711 void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase, 712 const uint32_t Offset) { 713 switch (OpRt->getType()) { 714 case IceType_i1: 715 case IceType_i8: { 716 static constexpr IValueT Opcode = 0x80000000; 717 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb"); 718 break; 719 } 720 case IceType_i16: { 721 static constexpr IValueT Opcode = 0x84000000; 722 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh"); 723 break; 724 } 725 case IceType_i32: { 726 static constexpr IValueT Opcode = 0x8C000000; 727 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw"); 728 break; 729 } 730 case IceType_f32: { 731 static constexpr IValueT Opcode = 0xC4000000; 732 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1"); 733 break; 734 } 735 case IceType_f64: { 736 static constexpr IValueT Opcode = 0xD4000000; 737 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1"); 738 break; 739 } 740 default: { UnimplementedError(getFlags()); } 741 } 742 } 743 744 void AssemblerMIPS32::lwc1(const Operand *OpRt, const Operand *OpBase, 745 const Operand *OpOff, const RelocOp Reloc) { 746 IValueT Opcode = 0xC4000000; 747 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "lwc1"); 748 const IValueT Base = encodeGPRegister(OpBase, "Base", "lwc1"); 749 IValueT Imm16 = 0; 750 751 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { 752 emitFixup(createMIPS32Fixup(Reloc, OpRel)); 753 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { 754 Imm16 = C32->getValue(); 755 } else { 756 llvm::report_fatal_error("lwc1: Invalid 2nd operand"); 757 } 758 759 Opcode |= Base << 21; 760 Opcode |= Rt << 16; 761 Opcode |= Imm16; 762 emitInst(Opcode); 763 } 764 765 void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) { 766 static constexpr IValueT Opcode = 0x44000000; 767 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1"); 768 } 769 770 void AssemblerMIPS32::mfhi(const Operand *OpRd) { 771 IValueT Opcode = 0x000000010; 772 IValueT Rd = encodeGPRegister(OpRd, "Rd", "mfhi"); 773 Opcode |= Rd << 11; 774 emitInst(Opcode); 775 } 776 777 void AssemblerMIPS32::mflo(const Operand *OpRd) { 778 IValueT Opcode = 0x000000012; 779 IValueT Rd = encodeGPRegister(OpRd, "Rd", "mflo"); 780 Opcode |= Rd << 11; 781 emitInst(Opcode); 782 } 783 784 void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) { 785 static constexpr IValueT Opcode = 0x44000006; 786 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d"); 787 } 788 789 void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) { 790 static constexpr IValueT Opcode = 0x44000006; 791 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s"); 792 } 793 794 void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) { 795 796 const Type DstType = OpRd->getType(); 797 const Type SrcType = OpRs->getType(); 798 799 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) || 800 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) { 801 if (isScalarFloatingType(DstType)) { 802 mtc1(OpRs, OpRd); 803 } else { 804 mfc1(OpRd, OpRs); 805 } 806 } else { 807 switch (DstType) { 808 case IceType_f32: 809 mov_s(OpRd, OpRs); 810 break; 811 case IceType_f64: 812 mov_d(OpRd, OpRs); 813 break; 814 case IceType_i1: 815 case IceType_i8: 816 case IceType_i16: 817 case IceType_i32: { 818 IValueT Opcode = 0x00000021; 819 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move"); 820 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move"); 821 const IValueT Rt = 0; // $0 822 Opcode |= Rs << 21; 823 Opcode |= Rt << 16; 824 Opcode |= Rd << 11; 825 emitInst(Opcode); 826 break; 827 } 828 default: { UnimplementedError(getFlags()); } 829 } 830 } 831 } 832 833 void AssemblerMIPS32::movf(const Operand *OpRd, const Operand *OpRs, 834 const Operand *OpCc) { 835 IValueT Opcode = 0x00000001; 836 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movf"); 837 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movf"); 838 OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0; 839 if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) { 840 Cc = OpFCC->getFCC(); 841 } 842 const IValueT InstEncodingFalse = 0; 843 Opcode |= Rd << 11; 844 Opcode |= InstEncodingFalse << 16; 845 Opcode |= Cc << 18; 846 Opcode |= Rs << 21; 847 emitInst(Opcode); 848 } 849 850 void AssemblerMIPS32::movn(const Operand *OpRd, const Operand *OpRs, 851 const Operand *OpRt) { 852 static constexpr IValueT Opcode = 0x0000000B; 853 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movn"); 854 } 855 856 void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs, 857 const Operand *OpFt) { 858 static constexpr IValueT Opcode = 0x44000013; 859 emitCOP1FmtRtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movn.d"); 860 } 861 862 void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs, 863 const Operand *OpFt) { 864 static constexpr IValueT Opcode = 0x44000013; 865 emitCOP1FmtRtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s"); 866 } 867 868 void AssemblerMIPS32::movt(const Operand *OpRd, const Operand *OpRs, 869 const Operand *OpCc) { 870 IValueT Opcode = 0x00000001; 871 const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movt"); 872 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movt"); 873 OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0; 874 if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) { 875 Cc = OpFCC->getFCC(); 876 } 877 const IValueT InstEncodingTrue = 1; 878 Opcode |= Rd << 11; 879 Opcode |= InstEncodingTrue << 16; 880 Opcode |= Cc << 18; 881 Opcode |= Rs << 21; 882 emitInst(Opcode); 883 } 884 885 void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs, 886 const Operand *OpFt) { 887 static constexpr IValueT Opcode = 0x44000012; 888 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movz.d"); 889 } 890 891 void AssemblerMIPS32::movz(const Operand *OpRd, const Operand *OpRs, 892 const Operand *OpRt) { 893 static constexpr IValueT Opcode = 0x0000000A; 894 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movz"); 895 } 896 897 void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs, 898 const Operand *OpFt) { 899 static constexpr IValueT Opcode = 0x44000012; 900 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s"); 901 } 902 903 void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) { 904 static constexpr IValueT Opcode = 0x44800000; 905 emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1"); 906 } 907 908 void AssemblerMIPS32::mthi(const Operand *OpRs) { 909 IValueT Opcode = 0x000000011; 910 IValueT Rs = encodeGPRegister(OpRs, "Rs", "mthi"); 911 Opcode |= Rs << 21; 912 emitInst(Opcode); 913 } 914 915 void AssemblerMIPS32::mtlo(const Operand *OpRs) { 916 IValueT Opcode = 0x000000013; 917 IValueT Rs = encodeGPRegister(OpRs, "Rs", "mtlo"); 918 Opcode |= Rs << 21; 919 emitInst(Opcode); 920 } 921 922 void AssemblerMIPS32::mul(const Operand *OpRd, const Operand *OpRs, 923 const Operand *OpRt) { 924 static constexpr IValueT Opcode = 0x70000002; 925 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "mul"); 926 } 927 928 void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs, 929 const Operand *OpFt) { 930 static constexpr IValueT Opcode = 0x44000002; 931 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d"); 932 } 933 934 void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs, 935 const Operand *OpFt) { 936 static constexpr IValueT Opcode = 0x44000002; 937 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s"); 938 } 939 940 void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) { 941 static constexpr IValueT Opcode = 0x00000018; 942 emitRsRt(Opcode, OpRs, OpRt, "mult"); 943 } 944 945 void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) { 946 static constexpr IValueT Opcode = 0x00000019; 947 emitRsRt(Opcode, OpRs, OpRt, "multu"); 948 } 949 950 void AssemblerMIPS32::nor(const Operand *OpRd, const Operand *OpRs, 951 const Operand *OpRt) { 952 static constexpr IValueT Opcode = 0x00000027; 953 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "nor"); 954 } 955 956 void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs, 957 const Operand *OpRt) { 958 static constexpr IValueT Opcode = 0x00000025; 959 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or"); 960 } 961 962 void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs, 963 const uint32_t Imm) { 964 static constexpr IValueT Opcode = 0x34000000; 965 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori"); 966 } 967 968 void AssemblerMIPS32::ret(void) { 969 static constexpr IValueT Opcode = 0x03E00008; // JR $31 970 emitInst(Opcode); 971 nop(); // delay slot 972 } 973 974 void AssemblerMIPS32::sc(const Operand *OpRt, const Operand *OpBase, 975 const uint32_t Offset) { 976 static constexpr IValueT Opcode = 0xE0000000; 977 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sc"); 978 } 979 980 void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt, 981 const uint32_t Sa) { 982 static constexpr IValueT Opcode = 0x00000000; 983 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll"); 984 } 985 986 void AssemblerMIPS32::sllv(const Operand *OpRd, const Operand *OpRt, 987 const Operand *OpRs) { 988 static constexpr IValueT Opcode = 0x00000004; 989 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sllv"); 990 } 991 992 void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs, 993 const Operand *OpRt) { 994 static constexpr IValueT Opcode = 0x0000002A; 995 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt"); 996 } 997 998 void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs, 999 const uint32_t Imm) { 1000 static constexpr IValueT Opcode = 0x28000000; 1001 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti"); 1002 } 1003 1004 void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs, 1005 const Operand *OpRt) { 1006 static constexpr IValueT Opcode = 0x0000002B; 1007 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu"); 1008 } 1009 1010 void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs, 1011 const uint32_t Imm) { 1012 static constexpr IValueT Opcode = 0x2c000000; 1013 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu"); 1014 } 1015 1016 void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) { 1017 static constexpr IValueT Opcode = 0x44000004; 1018 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d"); 1019 } 1020 1021 void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) { 1022 static constexpr IValueT Opcode = 0x44000004; 1023 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s"); 1024 } 1025 1026 void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt, 1027 const uint32_t Sa) { 1028 static constexpr IValueT Opcode = 0x00000003; 1029 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra"); 1030 } 1031 1032 void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt, 1033 const uint32_t Sa) { 1034 static constexpr IValueT Opcode = 0x00000002; 1035 emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl"); 1036 } 1037 1038 void AssemblerMIPS32::srav(const Operand *OpRd, const Operand *OpRt, 1039 const Operand *OpRs) { 1040 static constexpr IValueT Opcode = 0x00000007; 1041 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srav"); 1042 } 1043 1044 void AssemblerMIPS32::srlv(const Operand *OpRd, const Operand *OpRt, 1045 const Operand *OpRs) { 1046 static constexpr IValueT Opcode = 0x00000006; 1047 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srlv"); 1048 } 1049 1050 void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs, 1051 const Operand *OpFt) { 1052 static constexpr IValueT Opcode = 0x44000001; 1053 emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d"); 1054 } 1055 1056 void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs, 1057 const Operand *OpFt) { 1058 static constexpr IValueT Opcode = 0x44000001; 1059 emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s"); 1060 } 1061 1062 void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs, 1063 const Operand *OpRt) { 1064 static constexpr IValueT Opcode = 0x00000023; 1065 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu"); 1066 } 1067 1068 void AssemblerMIPS32::sdc1(const Operand *OpRt, const Operand *OpBase, 1069 const Operand *OpOff, const RelocOp Reloc) { 1070 IValueT Opcode = 0xF4000000; 1071 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "sdc1"); 1072 const IValueT Base = encodeGPRegister(OpBase, "Base", "sdc1"); 1073 IValueT Imm16 = 0; 1074 1075 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { 1076 emitFixup(createMIPS32Fixup(Reloc, OpRel)); 1077 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { 1078 Imm16 = C32->getValue(); 1079 } else { 1080 llvm::report_fatal_error("sdc1: Invalid 2nd operand"); 1081 } 1082 1083 Opcode |= Base << 21; 1084 Opcode |= Rt << 16; 1085 Opcode |= Imm16; 1086 emitInst(Opcode); 1087 } 1088 1089 void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase, 1090 const uint32_t Offset) { 1091 switch (OpRt->getType()) { 1092 case IceType_i1: 1093 case IceType_i8: { 1094 static constexpr IValueT Opcode = 0xA0000000; 1095 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb"); 1096 break; 1097 } 1098 case IceType_i16: { 1099 static constexpr IValueT Opcode = 0xA4000000; 1100 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh"); 1101 break; 1102 } 1103 case IceType_i32: { 1104 static constexpr IValueT Opcode = 0xAC000000; 1105 emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw"); 1106 break; 1107 } 1108 case IceType_f32: { 1109 static constexpr IValueT Opcode = 0xE4000000; 1110 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1"); 1111 break; 1112 } 1113 case IceType_f64: { 1114 static constexpr IValueT Opcode = 0xF4000000; 1115 emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1"); 1116 break; 1117 } 1118 default: { UnimplementedError(getFlags()); } 1119 } 1120 } 1121 1122 void AssemblerMIPS32::swc1(const Operand *OpRt, const Operand *OpBase, 1123 const Operand *OpOff, const RelocOp Reloc) { 1124 IValueT Opcode = 0xE4000000; 1125 const IValueT Rt = encodeFPRegister(OpRt, "Ft", "swc1"); 1126 const IValueT Base = encodeGPRegister(OpBase, "Base", "swc1"); 1127 IValueT Imm16 = 0; 1128 1129 if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) { 1130 emitFixup(createMIPS32Fixup(Reloc, OpRel)); 1131 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) { 1132 Imm16 = C32->getValue(); 1133 } else { 1134 llvm::report_fatal_error("swc1: Invalid 2nd operand"); 1135 } 1136 1137 Opcode |= Base << 21; 1138 Opcode |= Rt << 16; 1139 Opcode |= Imm16; 1140 emitInst(Opcode); 1141 } 1142 1143 void AssemblerMIPS32::sync() { 1144 static constexpr IValueT Opcode = 0x0000000f; 1145 emitInst(Opcode); 1146 } 1147 1148 void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt, 1149 const uint32_t TrapCode) { 1150 IValueT Opcode = 0x00000034; 1151 const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq"); 1152 const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq"); 1153 Opcode |= (TrapCode & 0xFFFFF) << 6; 1154 Opcode |= Rt << 16; 1155 Opcode |= Rs << 21; 1156 emitInst(Opcode); 1157 } 1158 1159 void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) { 1160 static constexpr IValueT Opcode = 0x4400000D; 1161 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d"); 1162 } 1163 1164 void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) { 1165 static constexpr IValueT Opcode = 0x4400000D; 1166 emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s"); 1167 } 1168 1169 void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) { 1170 static constexpr IValueT Opcode = 0x4400000D; 1171 emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "trunc.w.d"); 1172 } 1173 1174 void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) { 1175 static constexpr IValueT Opcode = 0x4400000D; 1176 emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "trunc.w.s"); 1177 } 1178 1179 void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs, 1180 const Operand *OpRt) { 1181 static constexpr IValueT Opcode = 0x00000026; 1182 emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor"); 1183 } 1184 1185 void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs, 1186 const uint32_t Imm) { 1187 static constexpr IValueT Opcode = 0x38000000; 1188 emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori"); 1189 } 1190 1191 void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs, 1192 const Operand *OpRt, IOffsetT Offset) { 1193 IValueT Opcode = 0; 1194 1195 switch (Cond) { 1196 default: 1197 break; 1198 case CondMIPS32::AL: 1199 case CondMIPS32::EQ: 1200 case CondMIPS32::EQZ: 1201 Opcode = 0x10000000; 1202 break; 1203 case CondMIPS32::NE: 1204 case CondMIPS32::NEZ: 1205 Opcode = 0x14000000; 1206 break; 1207 case CondMIPS32::LEZ: 1208 Opcode = 0x18000000; 1209 break; 1210 case CondMIPS32::LTZ: 1211 Opcode = 0x04000000; 1212 break; 1213 case CondMIPS32::GEZ: 1214 Opcode = 0x04010000; 1215 break; 1216 case CondMIPS32::GTZ: 1217 Opcode = 0x1C000000; 1218 break; 1219 } 1220 1221 if (Opcode == 0) { 1222 llvm::report_fatal_error("Branch: Invalid condition"); 1223 } 1224 1225 if (OpRs != nullptr) { 1226 IValueT Rs = encodeGPRegister(OpRs, "Rs", "branch"); 1227 Opcode |= Rs << 21; 1228 } 1229 1230 if (OpRt != nullptr) { 1231 IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch"); 1232 Opcode |= Rt << 16; 1233 } 1234 1235 Opcode = encodeBranchOffset(Offset, Opcode); 1236 emitInst(Opcode); 1237 nop(); // delay slot 1238 } 1239 1240 void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs, 1241 const Operand *OpRt, Label *TargetLabel) { 1242 if (TargetLabel->isBound()) { 1243 const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); 1244 emitBr(Cond, OpRs, OpRt, Dest); 1245 return; 1246 } 1247 const IOffsetT Position = Buffer.size(); 1248 IOffsetT PrevPosition = TargetLabel->getEncodedPosition(); 1249 if (PrevPosition != 0) 1250 PrevPosition = Position - PrevPosition; 1251 emitBr(Cond, OpRs, OpRt, PrevPosition); 1252 TargetLabel->linkTo(*this, Position); 1253 } 1254 1255 void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs, 1256 Label *TargetLabel) { 1257 static constexpr Operand *OpRtNone = nullptr; 1258 if (TargetLabel->isBound()) { 1259 const int32_t Dest = TargetLabel->getPosition() - Buffer.size(); 1260 emitBr(Cond, OpRs, OpRtNone, Dest); 1261 return; 1262 } 1263 const IOffsetT Position = Buffer.size(); 1264 IOffsetT PrevPosition = TargetLabel->getEncodedPosition(); 1265 if (PrevPosition) 1266 PrevPosition = Position - PrevPosition; 1267 emitBr(Cond, OpRs, OpRtNone, PrevPosition); 1268 TargetLabel->linkTo(*this, Position); 1269 } 1270 1271 } // end of namespace MIPS32 1272 } // end of namespace Ice 1273