1 //===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides Mips specific target streamer methods. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "InstPrinter/MipsInstPrinter.h" 15 #include "MipsMCTargetDesc.h" 16 #include "MipsTargetObjectFile.h" 17 #include "MipsTargetStreamer.h" 18 #include "llvm/MC/MCContext.h" 19 #include "llvm/MC/MCELF.h" 20 #include "llvm/MC/MCSectionELF.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/MC/MCSymbol.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/ELF.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Support/FormattedStream.h" 27 28 using namespace llvm; 29 30 MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} 31 void MipsTargetStreamer::emitDirectiveSetMicroMips() {} 32 void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {} 33 void MipsTargetStreamer::emitDirectiveSetMips16() {} 34 void MipsTargetStreamer::emitDirectiveSetNoMips16() {} 35 void MipsTargetStreamer::emitDirectiveSetReorder() {} 36 void MipsTargetStreamer::emitDirectiveSetNoReorder() {} 37 void MipsTargetStreamer::emitDirectiveSetMacro() {} 38 void MipsTargetStreamer::emitDirectiveSetNoMacro() {} 39 void MipsTargetStreamer::emitDirectiveSetAt() {} 40 void MipsTargetStreamer::emitDirectiveSetNoAt() {} 41 void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {} 42 void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {} 43 void MipsTargetStreamer::emitDirectiveAbiCalls() {} 44 void MipsTargetStreamer::emitDirectiveNaN2008() {} 45 void MipsTargetStreamer::emitDirectiveNaNLegacy() {} 46 void MipsTargetStreamer::emitDirectiveOptionPic0() {} 47 void MipsTargetStreamer::emitDirectiveOptionPic2() {} 48 void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize, 49 unsigned ReturnReg) {} 50 void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} 51 void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { 52 } 53 void MipsTargetStreamer::emitDirectiveSetMips32R2() {} 54 void MipsTargetStreamer::emitDirectiveSetMips64() {} 55 void MipsTargetStreamer::emitDirectiveSetMips64R2() {} 56 void MipsTargetStreamer::emitDirectiveSetDsp() {} 57 void MipsTargetStreamer::emitDirectiveCpload(unsigned RegNo) {} 58 void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, 59 const MCSymbol &Sym, bool IsReg) { 60 } 61 62 MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, 63 formatted_raw_ostream &OS) 64 : MipsTargetStreamer(S), OS(OS) {} 65 66 void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() { 67 OS << "\t.set\tmicromips\n"; 68 } 69 70 void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() { 71 OS << "\t.set\tnomicromips\n"; 72 } 73 74 void MipsTargetAsmStreamer::emitDirectiveSetMips16() { 75 OS << "\t.set\tmips16\n"; 76 } 77 78 void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() { 79 OS << "\t.set\tnomips16\n"; 80 } 81 82 void MipsTargetAsmStreamer::emitDirectiveSetReorder() { 83 OS << "\t.set\treorder\n"; 84 } 85 86 void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() { 87 OS << "\t.set\tnoreorder\n"; 88 } 89 90 void MipsTargetAsmStreamer::emitDirectiveSetMacro() { 91 OS << "\t.set\tmacro\n"; 92 } 93 94 void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() { 95 OS << "\t.set\tnomacro\n"; 96 } 97 98 void MipsTargetAsmStreamer::emitDirectiveSetAt() { 99 OS << "\t.set\tat\n"; 100 } 101 102 void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { 103 OS << "\t.set\tnoat\n"; 104 } 105 106 void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) { 107 OS << "\t.end\t" << Name << '\n'; 108 } 109 110 void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { 111 OS << "\t.ent\t" << Symbol.getName() << '\n'; 112 } 113 114 void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; } 115 116 void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; } 117 118 void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() { 119 OS << "\t.nan\tlegacy\n"; 120 } 121 122 void MipsTargetAsmStreamer::emitDirectiveOptionPic0() { 123 OS << "\t.option\tpic0\n"; 124 } 125 126 void MipsTargetAsmStreamer::emitDirectiveOptionPic2() { 127 OS << "\t.option\tpic2\n"; 128 } 129 130 void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, 131 unsigned ReturnReg) { 132 OS << "\t.frame\t$" 133 << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << "," 134 << StackSize << ",$" 135 << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n'; 136 } 137 138 void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { 139 OS << "\t.set\tmips32r2\n"; 140 } 141 142 void MipsTargetAsmStreamer::emitDirectiveSetMips64() { 143 OS << "\t.set\tmips64\n"; 144 } 145 146 void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { 147 OS << "\t.set\tmips64r2\n"; 148 } 149 150 void MipsTargetAsmStreamer::emitDirectiveSetDsp() { 151 OS << "\t.set\tdsp\n"; 152 } 153 // Print a 32 bit hex number with all numbers. 154 static void printHex32(unsigned Value, raw_ostream &OS) { 155 OS << "0x"; 156 for (int i = 7; i >= 0; i--) 157 OS.write_hex((Value & (0xF << (i*4))) >> (i*4)); 158 } 159 160 void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask, 161 int CPUTopSavedRegOff) { 162 OS << "\t.mask \t"; 163 printHex32(CPUBitmask, OS); 164 OS << ',' << CPUTopSavedRegOff << '\n'; 165 } 166 167 void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask, 168 int FPUTopSavedRegOff) { 169 OS << "\t.fmask\t"; 170 printHex32(FPUBitmask, OS); 171 OS << "," << FPUTopSavedRegOff << '\n'; 172 } 173 174 void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) { 175 OS << "\t.cpload\t$" 176 << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; 177 } 178 179 void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, 180 int RegOrOffset, 181 const MCSymbol &Sym, 182 bool IsReg) { 183 OS << "\t.cpsetup\t$" 184 << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", "; 185 186 if (IsReg) 187 OS << "$" 188 << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower(); 189 else 190 OS << RegOrOffset; 191 192 OS << ", "; 193 194 OS << Sym.getName() << "\n"; 195 } 196 197 // This part is for ELF object output. 198 MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, 199 const MCSubtargetInfo &STI) 200 : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { 201 MCAssembler &MCA = getStreamer().getAssembler(); 202 uint64_t Features = STI.getFeatureBits(); 203 Triple T(STI.getTargetTriple()); 204 Pic = (MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) 205 ? true 206 : false; 207 208 // Update e_header flags 209 unsigned EFlags = 0; 210 211 // Architecture 212 if (Features & Mips::FeatureMips64r2) 213 EFlags |= ELF::EF_MIPS_ARCH_64R2; 214 else if (Features & Mips::FeatureMips64) 215 EFlags |= ELF::EF_MIPS_ARCH_64; 216 else if (Features & Mips::FeatureMips4) 217 EFlags |= ELF::EF_MIPS_ARCH_4; 218 else if (Features & Mips::FeatureMips32r2) 219 EFlags |= ELF::EF_MIPS_ARCH_32R2; 220 else if (Features & Mips::FeatureMips32) 221 EFlags |= ELF::EF_MIPS_ARCH_32; 222 223 if (T.isArch64Bit()) { 224 if (Features & Mips::FeatureN32) 225 EFlags |= ELF::EF_MIPS_ABI2; 226 else if (Features & Mips::FeatureO32) { 227 EFlags |= ELF::EF_MIPS_ABI_O32; 228 EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ 229 } 230 // No need to set any bit for N64 which is the default ABI at the moment 231 // for 64-bit Mips architectures. 232 } else { 233 if (Features & Mips::FeatureMips64r2 || Features & Mips::FeatureMips64) 234 EFlags |= ELF::EF_MIPS_32BITMODE; 235 236 // ABI 237 EFlags |= ELF::EF_MIPS_ABI_O32; 238 } 239 240 // Other options. 241 if (Features & Mips::FeatureNaN2008) 242 EFlags |= ELF::EF_MIPS_NAN2008; 243 244 MCA.setELFHeaderEFlags(EFlags); 245 } 246 247 void MipsTargetELFStreamer::emitLabel(MCSymbol *Symbol) { 248 if (!isMicroMipsEnabled()) 249 return; 250 MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Symbol); 251 uint8_t Type = MCELF::GetType(Data); 252 if (Type != ELF::STT_FUNC) 253 return; 254 255 // The "other" values are stored in the last 6 bits of the second byte 256 // The traditional defines for STO values assume the full byte and thus 257 // the shift to pack it. 258 MCELF::setOther(Data, ELF::STO_MIPS_MICROMIPS >> 2); 259 } 260 261 void MipsTargetELFStreamer::finish() { 262 MCAssembler &MCA = getStreamer().getAssembler(); 263 MCContext &Context = MCA.getContext(); 264 MCStreamer &OS = getStreamer(); 265 Triple T(STI.getTargetTriple()); 266 uint64_t Features = STI.getFeatureBits(); 267 268 if (T.isArch64Bit() && (Features & Mips::FeatureN64)) { 269 const MCSectionELF *Sec = Context.getELFSection( 270 ".MIPS.options", ELF::SHT_MIPS_OPTIONS, 271 ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, SectionKind::getMetadata()); 272 OS.SwitchSection(Sec); 273 274 OS.EmitIntValue(1, 1); // kind 275 OS.EmitIntValue(40, 1); // size 276 OS.EmitIntValue(0, 2); // section 277 OS.EmitIntValue(0, 4); // info 278 OS.EmitIntValue(0, 4); // ri_gprmask 279 OS.EmitIntValue(0, 4); // pad 280 OS.EmitIntValue(0, 4); // ri_cpr[0]mask 281 OS.EmitIntValue(0, 4); // ri_cpr[1]mask 282 OS.EmitIntValue(0, 4); // ri_cpr[2]mask 283 OS.EmitIntValue(0, 4); // ri_cpr[3]mask 284 OS.EmitIntValue(0, 8); // ri_gp_value 285 } else { 286 const MCSectionELF *Sec = 287 Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, 288 SectionKind::getMetadata()); 289 OS.SwitchSection(Sec); 290 291 OS.EmitIntValue(0, 4); // ri_gprmask 292 OS.EmitIntValue(0, 4); // ri_cpr[0]mask 293 OS.EmitIntValue(0, 4); // ri_cpr[1]mask 294 OS.EmitIntValue(0, 4); // ri_cpr[2]mask 295 OS.EmitIntValue(0, 4); // ri_cpr[3]mask 296 OS.EmitIntValue(0, 4); // ri_gp_value 297 } 298 } 299 300 void MipsTargetELFStreamer::emitAssignment(MCSymbol *Symbol, 301 const MCExpr *Value) { 302 // If on rhs is micromips symbol then mark Symbol as microMips. 303 if (Value->getKind() != MCExpr::SymbolRef) 304 return; 305 const MCSymbol &RhsSym = 306 static_cast<const MCSymbolRefExpr *>(Value)->getSymbol(); 307 MCSymbolData &Data = getStreamer().getOrCreateSymbolData(&RhsSym); 308 uint8_t Type = MCELF::GetType(Data); 309 if ((Type != ELF::STT_FUNC) 310 || !(MCELF::getOther(Data) & (ELF::STO_MIPS_MICROMIPS >> 2))) 311 return; 312 313 MCSymbolData &SymbolData = getStreamer().getOrCreateSymbolData(Symbol); 314 // The "other" values are stored in the last 6 bits of the second byte. 315 // The traditional defines for STO values assume the full byte and thus 316 // the shift to pack it. 317 MCELF::setOther(SymbolData, ELF::STO_MIPS_MICROMIPS >> 2); 318 } 319 320 MCELFStreamer &MipsTargetELFStreamer::getStreamer() { 321 return static_cast<MCELFStreamer &>(Streamer); 322 } 323 324 void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { 325 MicroMipsEnabled = true; 326 327 MCAssembler &MCA = getStreamer().getAssembler(); 328 unsigned Flags = MCA.getELFHeaderEFlags(); 329 Flags |= ELF::EF_MIPS_MICROMIPS; 330 MCA.setELFHeaderEFlags(Flags); 331 } 332 333 void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { 334 MicroMipsEnabled = false; 335 } 336 337 void MipsTargetELFStreamer::emitDirectiveSetMips16() { 338 MCAssembler &MCA = getStreamer().getAssembler(); 339 unsigned Flags = MCA.getELFHeaderEFlags(); 340 Flags |= ELF::EF_MIPS_ARCH_ASE_M16; 341 MCA.setELFHeaderEFlags(Flags); 342 } 343 344 void MipsTargetELFStreamer::emitDirectiveSetNoMips16() { 345 // FIXME: implement. 346 } 347 348 void MipsTargetELFStreamer::emitDirectiveSetReorder() { 349 // FIXME: implement. 350 } 351 352 void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { 353 MCAssembler &MCA = getStreamer().getAssembler(); 354 unsigned Flags = MCA.getELFHeaderEFlags(); 355 Flags |= ELF::EF_MIPS_NOREORDER; 356 MCA.setELFHeaderEFlags(Flags); 357 } 358 359 void MipsTargetELFStreamer::emitDirectiveSetMacro() { 360 // FIXME: implement. 361 } 362 363 void MipsTargetELFStreamer::emitDirectiveSetNoMacro() { 364 // FIXME: implement. 365 } 366 367 void MipsTargetELFStreamer::emitDirectiveSetAt() { 368 // FIXME: implement. 369 } 370 371 void MipsTargetELFStreamer::emitDirectiveSetNoAt() { 372 // FIXME: implement. 373 } 374 375 void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { 376 // FIXME: implement. 377 } 378 379 void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { 380 // FIXME: implement. 381 } 382 383 void MipsTargetELFStreamer::emitDirectiveAbiCalls() { 384 MCAssembler &MCA = getStreamer().getAssembler(); 385 unsigned Flags = MCA.getELFHeaderEFlags(); 386 Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC; 387 MCA.setELFHeaderEFlags(Flags); 388 } 389 390 void MipsTargetELFStreamer::emitDirectiveNaN2008() { 391 MCAssembler &MCA = getStreamer().getAssembler(); 392 unsigned Flags = MCA.getELFHeaderEFlags(); 393 Flags |= ELF::EF_MIPS_NAN2008; 394 MCA.setELFHeaderEFlags(Flags); 395 } 396 397 void MipsTargetELFStreamer::emitDirectiveNaNLegacy() { 398 MCAssembler &MCA = getStreamer().getAssembler(); 399 unsigned Flags = MCA.getELFHeaderEFlags(); 400 Flags &= ~ELF::EF_MIPS_NAN2008; 401 MCA.setELFHeaderEFlags(Flags); 402 } 403 404 void MipsTargetELFStreamer::emitDirectiveOptionPic0() { 405 MCAssembler &MCA = getStreamer().getAssembler(); 406 unsigned Flags = MCA.getELFHeaderEFlags(); 407 // This option overrides other PIC options like -KPIC. 408 Pic = false; 409 Flags &= ~ELF::EF_MIPS_PIC; 410 MCA.setELFHeaderEFlags(Flags); 411 } 412 413 void MipsTargetELFStreamer::emitDirectiveOptionPic2() { 414 MCAssembler &MCA = getStreamer().getAssembler(); 415 unsigned Flags = MCA.getELFHeaderEFlags(); 416 Pic = true; 417 // NOTE: We are following the GAS behaviour here which means the directive 418 // 'pic2' also sets the CPIC bit in the ELF header. This is different from 419 // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and 420 // EF_MIPS_CPIC to be mutually exclusive. 421 Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; 422 MCA.setELFHeaderEFlags(Flags); 423 } 424 425 void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize, 426 unsigned ReturnReg) { 427 // FIXME: implement. 428 } 429 430 void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask, 431 int CPUTopSavedRegOff) { 432 // FIXME: implement. 433 } 434 435 void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask, 436 int FPUTopSavedRegOff) { 437 // FIXME: implement. 438 } 439 440 void MipsTargetELFStreamer::emitDirectiveSetMips32R2() { 441 // No action required for ELF output. 442 } 443 444 void MipsTargetELFStreamer::emitDirectiveSetMips64() { 445 // No action required for ELF output. 446 } 447 448 void MipsTargetELFStreamer::emitDirectiveSetMips64R2() { 449 // No action required for ELF output. 450 } 451 452 void MipsTargetELFStreamer::emitDirectiveSetDsp() { 453 // No action required for ELF output. 454 } 455 456 void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) { 457 // .cpload $reg 458 // This directive expands to: 459 // lui $gp, %hi(_gp_disp) 460 // addui $gp, $gp, %lo(_gp_disp) 461 // addu $gp, $gp, $reg 462 // when support for position independent code is enabled. 463 if (!Pic || (isN32() || isN64())) 464 return; 465 466 // There's a GNU extension controlled by -mno-shared that allows 467 // locally-binding symbols to be accessed using absolute addresses. 468 // This is currently not supported. When supported -mno-shared makes 469 // .cpload expand to: 470 // lui $gp, %hi(__gnu_local_gp) 471 // addiu $gp, $gp, %lo(__gnu_local_gp) 472 473 StringRef SymName("_gp_disp"); 474 MCAssembler &MCA = getStreamer().getAssembler(); 475 MCSymbol *GP_Disp = MCA.getContext().GetOrCreateSymbol(SymName); 476 MCA.getOrCreateSymbolData(*GP_Disp); 477 478 MCInst TmpInst; 479 TmpInst.setOpcode(Mips::LUi); 480 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); 481 const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::Create( 482 "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext()); 483 TmpInst.addOperand(MCOperand::CreateExpr(HiSym)); 484 getStreamer().EmitInstruction(TmpInst, STI); 485 486 TmpInst.clear(); 487 488 TmpInst.setOpcode(Mips::ADDiu); 489 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); 490 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); 491 const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::Create( 492 "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext()); 493 TmpInst.addOperand(MCOperand::CreateExpr(LoSym)); 494 getStreamer().EmitInstruction(TmpInst, STI); 495 496 TmpInst.clear(); 497 498 TmpInst.setOpcode(Mips::ADDu); 499 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); 500 TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); 501 TmpInst.addOperand(MCOperand::CreateReg(RegNo)); 502 getStreamer().EmitInstruction(TmpInst, STI); 503 } 504 505 void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, 506 int RegOrOffset, 507 const MCSymbol &Sym, 508 bool IsReg) { 509 // Only N32 and N64 emit anything for .cpsetup iff PIC is set. 510 if (!Pic || !(isN32() || isN64())) 511 return; 512 513 MCAssembler &MCA = getStreamer().getAssembler(); 514 MCInst Inst; 515 516 // Either store the old $gp in a register or on the stack 517 if (IsReg) { 518 // move $save, $gpreg 519 Inst.setOpcode(Mips::DADDu); 520 Inst.addOperand(MCOperand::CreateReg(RegOrOffset)); 521 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 522 Inst.addOperand(MCOperand::CreateReg(Mips::ZERO)); 523 } else { 524 // sd $gpreg, offset($sp) 525 Inst.setOpcode(Mips::SD); 526 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 527 Inst.addOperand(MCOperand::CreateReg(Mips::SP)); 528 Inst.addOperand(MCOperand::CreateImm(RegOrOffset)); 529 } 530 getStreamer().EmitInstruction(Inst, STI); 531 Inst.clear(); 532 533 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( 534 Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext()); 535 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create( 536 Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext()); 537 // lui $gp, %hi(%neg(%gp_rel(funcSym))) 538 Inst.setOpcode(Mips::LUi); 539 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 540 Inst.addOperand(MCOperand::CreateExpr(HiExpr)); 541 getStreamer().EmitInstruction(Inst, STI); 542 Inst.clear(); 543 544 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) 545 Inst.setOpcode(Mips::ADDiu); 546 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 547 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 548 Inst.addOperand(MCOperand::CreateExpr(LoExpr)); 549 getStreamer().EmitInstruction(Inst, STI); 550 Inst.clear(); 551 552 // daddu $gp, $gp, $funcreg 553 Inst.setOpcode(Mips::DADDu); 554 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 555 Inst.addOperand(MCOperand::CreateReg(Mips::GP)); 556 Inst.addOperand(MCOperand::CreateReg(RegNo)); 557 getStreamer().EmitInstruction(Inst, STI); 558 } 559