10b57cec5SDimitry Andric //===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file provides Mips specific target streamer methods. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MipsTargetStreamer.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h" 150b57cec5SDimitry Andric #include "MipsELFStreamer.h" 1681ad6265SDimitry Andric #include "MipsInstPrinter.h" 170b57cec5SDimitry Andric #include "MipsMCExpr.h" 180b57cec5SDimitry Andric #include "MipsMCTargetDesc.h" 190b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 2081ad6265SDimitry Andric #include "llvm/MC/MCAssembler.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 225f757f3fSDimitry Andric #include "llvm/MC/MCObjectFileInfo.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h" 2681ad6265SDimitry Andric #include "llvm/Support/Casting.h" 270b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 280b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 290b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace { 340b57cec5SDimitry Andric static cl::opt<bool> RoundSectionSizes( 350b57cec5SDimitry Andric "mips-round-section-sizes", cl::init(false), 360b57cec5SDimitry Andric cl::desc("Round section sizes up to the section alignment"), cl::Hidden); 370b57cec5SDimitry Andric } // end anonymous namespace 380b57cec5SDimitry Andric 398bcb0991SDimitry Andric static bool isMicroMips(const MCSubtargetInfo *STI) { 4006c3fb27SDimitry Andric return STI->hasFeature(Mips::FeatureMicroMips); 418bcb0991SDimitry Andric } 428bcb0991SDimitry Andric 4381ad6265SDimitry Andric static bool isMips32r6(const MCSubtargetInfo *STI) { 4406c3fb27SDimitry Andric return STI->hasFeature(Mips::FeatureMips32r6); 4581ad6265SDimitry Andric } 4681ad6265SDimitry Andric 470b57cec5SDimitry Andric MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) 480b57cec5SDimitry Andric : MCTargetStreamer(S), GPReg(Mips::GP), ModuleDirectiveAllowed(true) { 490b57cec5SDimitry Andric GPRInfoSet = FPRInfoSet = FrameInfoSet = false; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMicroMips() {} 520b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {} 530b57cec5SDimitry Andric void MipsTargetStreamer::setUsesMicroMips() {} 540b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips16() {} 550b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); } 560b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); } 570b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoReorder() {} 580b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMacro() { forbidModuleDirective(); } 590b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); } 600b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); } 610b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); } 620b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMt() {} 630b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); } 640b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetCRC() {} 650b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoCRC() {} 660b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetVirt() {} 670b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoVirt() {} 680b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetGINV() {} 690b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoGINV() {} 700b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } 710b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { 720b57cec5SDimitry Andric forbidModuleDirective(); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); } 750b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {} 760b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {} 770b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveAbiCalls() {} 780b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveNaN2008() {} 790b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveNaNLegacy() {} 800b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveOptionPic0() {} 810b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveOptionPic2() {} 820b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); } 830b57cec5SDimitry Andric void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize, 840b57cec5SDimitry Andric unsigned ReturnReg) {} 850b57cec5SDimitry Andric void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} 860b57cec5SDimitry Andric void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) { 890b57cec5SDimitry Andric forbidModuleDirective(); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); } 920b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); } 930b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); } 940b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); } 950b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); } 960b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); } 970b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); } 980b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); } 990b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); } 1000b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); } 1010b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); } 1020b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); } 1030b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); } 1040b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); } 1050b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); } 1060b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); } 1070b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); } 1080b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); } 1090b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetSoftFloat() { 1100b57cec5SDimitry Andric forbidModuleDirective(); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetHardFloat() { 1130b57cec5SDimitry Andric forbidModuleDirective(); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } 1160b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); } 1170b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } 1185ffd83dbSDimitry Andric void MipsTargetStreamer::emitDirectiveSetMips3D() { forbidModuleDirective(); } 1195ffd83dbSDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoMips3D() { forbidModuleDirective(); } 1205ffd83dbSDimitry Andric void MipsTargetStreamer::emitDirectiveCpAdd(unsigned RegNo) {} 1210b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} 1220b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) { 1230b57cec5SDimitry Andric // .cplocal $reg 1240b57cec5SDimitry Andric // This directive forces to use the alternate register for context pointer. 1250b57cec5SDimitry Andric // For example 1260b57cec5SDimitry Andric // .cplocal $4 1270b57cec5SDimitry Andric // jal foo 1280b57cec5SDimitry Andric // expands to 1290b57cec5SDimitry Andric // ld $25, %call16(foo)($4) 1300b57cec5SDimitry Andric // jalr $25 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric if (!getABI().IsN32() && !getABI().IsN64()) 1330b57cec5SDimitry Andric return; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric GPReg = RegNo; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric forbidModuleDirective(); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric bool MipsTargetStreamer::emitDirectiveCpRestore( 1400b57cec5SDimitry Andric int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, 1410b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 1420b57cec5SDimitry Andric forbidModuleDirective(); 1430b57cec5SDimitry Andric return true; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, 1460b57cec5SDimitry Andric const MCSymbol &Sym, bool IsReg) { 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation, 1490b57cec5SDimitry Andric bool SaveLocationIsRegister) {} 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleFP() {} 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleOddSPReg() { 1540b57cec5SDimitry Andric if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI) 1550b57cec5SDimitry Andric report_fatal_error("+nooddspreg is only valid for O32"); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {} 1580b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleHardFloat() {} 1590b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleMT() {} 1600b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleCRC() {} 1610b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleNoCRC() {} 1620b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleVirt() {} 1630b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleNoVirt() {} 1640b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleGINV() {} 1650b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveModuleNoGINV() {} 1660b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetFp( 1670b57cec5SDimitry Andric MipsABIFlagsSection::FpABIKind Value) { 1680b57cec5SDimitry Andric forbidModuleDirective(); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); } 1710b57cec5SDimitry Andric void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() { 1720b57cec5SDimitry Andric forbidModuleDirective(); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, 1760b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 1770b57cec5SDimitry Andric MCInst TmpInst; 1780b57cec5SDimitry Andric TmpInst.setOpcode(Opcode); 1790b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg0)); 1800b57cec5SDimitry Andric TmpInst.setLoc(IDLoc); 1815ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, *STI); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, 1850b57cec5SDimitry Andric SMLoc IDLoc, const MCSubtargetInfo *STI) { 1860b57cec5SDimitry Andric MCInst TmpInst; 1870b57cec5SDimitry Andric TmpInst.setOpcode(Opcode); 1880b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg0)); 1890b57cec5SDimitry Andric TmpInst.addOperand(Op1); 1900b57cec5SDimitry Andric TmpInst.setLoc(IDLoc); 1915ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, *STI); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, 1950b57cec5SDimitry Andric SMLoc IDLoc, const MCSubtargetInfo *STI) { 1960b57cec5SDimitry Andric emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, 2000b57cec5SDimitry Andric SMLoc IDLoc, const MCSubtargetInfo *STI) { 2010b57cec5SDimitry Andric emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, 2050b57cec5SDimitry Andric SMLoc IDLoc, const MCSubtargetInfo *STI) { 2060b57cec5SDimitry Andric MCInst TmpInst; 2070b57cec5SDimitry Andric TmpInst.setOpcode(Opcode); 2080b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(Imm1)); 2090b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(Imm2)); 2100b57cec5SDimitry Andric TmpInst.setLoc(IDLoc); 2115ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, *STI); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, 2150b57cec5SDimitry Andric MCOperand Op2, SMLoc IDLoc, 2160b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 2170b57cec5SDimitry Andric MCInst TmpInst; 2180b57cec5SDimitry Andric TmpInst.setOpcode(Opcode); 2190b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg0)); 2200b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg1)); 2210b57cec5SDimitry Andric TmpInst.addOperand(Op2); 2220b57cec5SDimitry Andric TmpInst.setLoc(IDLoc); 2235ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, *STI); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, 2270b57cec5SDimitry Andric unsigned Reg2, SMLoc IDLoc, 2280b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 2290b57cec5SDimitry Andric emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2328bcb0991SDimitry Andric void MipsTargetStreamer::emitRRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, 2338bcb0991SDimitry Andric unsigned Reg2, MCOperand Op3, SMLoc IDLoc, 2348bcb0991SDimitry Andric const MCSubtargetInfo *STI) { 2358bcb0991SDimitry Andric MCInst TmpInst; 2368bcb0991SDimitry Andric TmpInst.setOpcode(Opcode); 2378bcb0991SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg0)); 2388bcb0991SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg1)); 2398bcb0991SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg2)); 2408bcb0991SDimitry Andric TmpInst.addOperand(Op3); 2418bcb0991SDimitry Andric TmpInst.setLoc(IDLoc); 2425ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, *STI); 2438bcb0991SDimitry Andric } 2448bcb0991SDimitry Andric 2450b57cec5SDimitry Andric void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, 2460b57cec5SDimitry Andric int16_t Imm, SMLoc IDLoc, 2470b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 2480b57cec5SDimitry Andric emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0, 2520b57cec5SDimitry Andric unsigned Reg1, int16_t Imm0, int16_t Imm1, 2530b57cec5SDimitry Andric int16_t Imm2, SMLoc IDLoc, 2540b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 2550b57cec5SDimitry Andric MCInst TmpInst; 2560b57cec5SDimitry Andric TmpInst.setOpcode(Opcode); 2570b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg0)); 2580b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(Reg1)); 2590b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(Imm0)); 2600b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(Imm1)); 2610b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(Imm2)); 2620b57cec5SDimitry Andric TmpInst.setLoc(IDLoc); 2635ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, *STI); 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg, 2670b57cec5SDimitry Andric unsigned TrgReg, bool Is64Bit, 2680b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 2690b57cec5SDimitry Andric emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(), 2700b57cec5SDimitry Andric STI); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg, 2740b57cec5SDimitry Andric int16_t ShiftAmount, SMLoc IDLoc, 2750b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 2760b57cec5SDimitry Andric if (ShiftAmount >= 32) { 2770b57cec5SDimitry Andric emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI); 2780b57cec5SDimitry Andric return; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, 2850b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 28681ad6265SDimitry Andric // The default case of `nop` is `sll $zero, $zero, 0`. 28781ad6265SDimitry Andric unsigned Opc = Mips::SLL; 28881ad6265SDimitry Andric if (isMicroMips(STI) && hasShortDelaySlot) { 28981ad6265SDimitry Andric Opc = isMips32r6(STI) ? Mips::MOVE16_MMR6 : Mips::MOVE16_MM; 29081ad6265SDimitry Andric emitRR(Opc, Mips::ZERO, Mips::ZERO, IDLoc, STI); 29181ad6265SDimitry Andric return; 29281ad6265SDimitry Andric } 29381ad6265SDimitry Andric 29481ad6265SDimitry Andric if (isMicroMips(STI)) 29581ad6265SDimitry Andric Opc = isMips32r6(STI) ? Mips::SLL_MMR6 : Mips::SLL_MM; 29681ad6265SDimitry Andric 29781ad6265SDimitry Andric emitRRI(Opc, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) { 3018bcb0991SDimitry Andric if (isMicroMips(STI)) 3020b57cec5SDimitry Andric emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI); 3030b57cec5SDimitry Andric else 3040b57cec5SDimitry Andric emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric /// Emit the $gp restore operation for .cprestore. 3080b57cec5SDimitry Andric void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc, 3090b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 3100b57cec5SDimitry Andric emitLoadWithImmOffset(Mips::LW, GPReg, Mips::SP, Offset, GPReg, IDLoc, STI); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric /// Emit a store instruction with an immediate offset. 3140b57cec5SDimitry Andric void MipsTargetStreamer::emitStoreWithImmOffset( 3150b57cec5SDimitry Andric unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset, 3160b57cec5SDimitry Andric function_ref<unsigned()> GetATReg, SMLoc IDLoc, 3170b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 3180b57cec5SDimitry Andric if (isInt<16>(Offset)) { 3190b57cec5SDimitry Andric emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI); 3200b57cec5SDimitry Andric return; 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // sw $8, offset($8) => lui $at, %hi(offset) 3240b57cec5SDimitry Andric // add $at, $at, $8 3250b57cec5SDimitry Andric // sw $8, %lo(offset)($at) 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric unsigned ATReg = GetATReg(); 3280b57cec5SDimitry Andric if (!ATReg) 3290b57cec5SDimitry Andric return; 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric unsigned LoOffset = Offset & 0x0000ffff; 3320b57cec5SDimitry Andric unsigned HiOffset = (Offset & 0xffff0000) >> 16; 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric // If msb of LoOffset is 1(negative number) we must increment HiOffset 3350b57cec5SDimitry Andric // to account for the sign-extension of the low part. 3360b57cec5SDimitry Andric if (LoOffset & 0x8000) 3370b57cec5SDimitry Andric HiOffset++; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric // Generate the base address in ATReg. 3400b57cec5SDimitry Andric emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI); 3410b57cec5SDimitry Andric if (BaseReg != Mips::ZERO) 3420b57cec5SDimitry Andric emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); 3430b57cec5SDimitry Andric // Emit the store with the adjusted base and offset. 3440b57cec5SDimitry Andric emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric /// Emit a load instruction with an immediate offset. DstReg and TmpReg are 3480b57cec5SDimitry Andric /// permitted to be the same register iff DstReg is distinct from BaseReg and 3490b57cec5SDimitry Andric /// DstReg is a GPR. It is the callers responsibility to identify such cases 3500b57cec5SDimitry Andric /// and pass the appropriate register in TmpReg. 3510b57cec5SDimitry Andric void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, 3520b57cec5SDimitry Andric unsigned BaseReg, int64_t Offset, 3530b57cec5SDimitry Andric unsigned TmpReg, SMLoc IDLoc, 3540b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 3550b57cec5SDimitry Andric if (isInt<16>(Offset)) { 3560b57cec5SDimitry Andric emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI); 3570b57cec5SDimitry Andric return; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric // 1) lw $8, offset($9) => lui $8, %hi(offset) 3610b57cec5SDimitry Andric // add $8, $8, $9 3620b57cec5SDimitry Andric // lw $8, %lo(offset)($9) 3630b57cec5SDimitry Andric // 2) lw $8, offset($8) => lui $at, %hi(offset) 3640b57cec5SDimitry Andric // add $at, $at, $8 3650b57cec5SDimitry Andric // lw $8, %lo(offset)($at) 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric unsigned LoOffset = Offset & 0x0000ffff; 3680b57cec5SDimitry Andric unsigned HiOffset = (Offset & 0xffff0000) >> 16; 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric // If msb of LoOffset is 1(negative number) we must increment HiOffset 3710b57cec5SDimitry Andric // to account for the sign-extension of the low part. 3720b57cec5SDimitry Andric if (LoOffset & 0x8000) 3730b57cec5SDimitry Andric HiOffset++; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // Generate the base address in TmpReg. 3760b57cec5SDimitry Andric emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI); 3770b57cec5SDimitry Andric if (BaseReg != Mips::ZERO) 3780b57cec5SDimitry Andric emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); 3790b57cec5SDimitry Andric // Emit the load with the adjusted base and offset. 3800b57cec5SDimitry Andric emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, 3840b57cec5SDimitry Andric formatted_raw_ostream &OS) 3850b57cec5SDimitry Andric : MipsTargetStreamer(S), OS(OS) {} 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() { 3880b57cec5SDimitry Andric OS << "\t.set\tmicromips\n"; 3890b57cec5SDimitry Andric forbidModuleDirective(); 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() { 3930b57cec5SDimitry Andric OS << "\t.set\tnomicromips\n"; 3940b57cec5SDimitry Andric forbidModuleDirective(); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips16() { 3980b57cec5SDimitry Andric OS << "\t.set\tmips16\n"; 3990b57cec5SDimitry Andric forbidModuleDirective(); 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() { 4030b57cec5SDimitry Andric OS << "\t.set\tnomips16\n"; 4040b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoMips16(); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetReorder() { 4080b57cec5SDimitry Andric OS << "\t.set\treorder\n"; 4090b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetReorder(); 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() { 4130b57cec5SDimitry Andric OS << "\t.set\tnoreorder\n"; 4140b57cec5SDimitry Andric forbidModuleDirective(); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMacro() { 4180b57cec5SDimitry Andric OS << "\t.set\tmacro\n"; 4190b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMacro(); 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() { 4230b57cec5SDimitry Andric OS << "\t.set\tnomacro\n"; 4240b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoMacro(); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMsa() { 4280b57cec5SDimitry Andric OS << "\t.set\tmsa\n"; 4290b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMsa(); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() { 4330b57cec5SDimitry Andric OS << "\t.set\tnomsa\n"; 4340b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoMsa(); 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMt() { 4380b57cec5SDimitry Andric OS << "\t.set\tmt\n"; 4390b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMt(); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoMt() { 4430b57cec5SDimitry Andric OS << "\t.set\tnomt\n"; 4440b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoMt(); 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetCRC() { 4480b57cec5SDimitry Andric OS << "\t.set\tcrc\n"; 4490b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetCRC(); 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() { 4530b57cec5SDimitry Andric OS << "\t.set\tnocrc\n"; 4540b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoCRC(); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetVirt() { 4580b57cec5SDimitry Andric OS << "\t.set\tvirt\n"; 4590b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetVirt(); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() { 4630b57cec5SDimitry Andric OS << "\t.set\tnovirt\n"; 4640b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoVirt(); 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetGINV() { 4680b57cec5SDimitry Andric OS << "\t.set\tginv\n"; 4690b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetGINV(); 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() { 4730b57cec5SDimitry Andric OS << "\t.set\tnoginv\n"; 4740b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoGINV(); 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetAt() { 4780b57cec5SDimitry Andric OS << "\t.set\tat\n"; 4790b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetAt(); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { 4830b57cec5SDimitry Andric OS << "\t.set\tat=$" << Twine(RegNo) << "\n"; 4840b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo); 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { 4880b57cec5SDimitry Andric OS << "\t.set\tnoat\n"; 4890b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoAt(); 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) { 4930b57cec5SDimitry Andric OS << "\t.end\t" << Name << '\n'; 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { 4970b57cec5SDimitry Andric OS << "\t.ent\t" << Symbol.getName() << '\n'; 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; } 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() { 5050b57cec5SDimitry Andric OS << "\t.nan\tlegacy\n"; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveOptionPic0() { 5090b57cec5SDimitry Andric OS << "\t.option\tpic0\n"; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveOptionPic2() { 5130b57cec5SDimitry Andric OS << "\t.option\tpic2\n"; 5140b57cec5SDimitry Andric } 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveInsn() { 5170b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveInsn(); 5180b57cec5SDimitry Andric OS << "\t.insn\n"; 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, 5220b57cec5SDimitry Andric unsigned ReturnReg) { 5230b57cec5SDimitry Andric OS << "\t.frame\t$" 5240b57cec5SDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << "," 5250b57cec5SDimitry Andric << StackSize << ",$" 5260b57cec5SDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n'; 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) { 5300b57cec5SDimitry Andric OS << "\t.set arch=" << Arch << "\n"; 5310b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetArch(Arch); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips0() { 5350b57cec5SDimitry Andric OS << "\t.set\tmips0\n"; 5360b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips0(); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips1() { 5400b57cec5SDimitry Andric OS << "\t.set\tmips1\n"; 5410b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips1(); 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips2() { 5450b57cec5SDimitry Andric OS << "\t.set\tmips2\n"; 5460b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips2(); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips3() { 5500b57cec5SDimitry Andric OS << "\t.set\tmips3\n"; 5510b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips3(); 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips4() { 5550b57cec5SDimitry Andric OS << "\t.set\tmips4\n"; 5560b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips4(); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips5() { 5600b57cec5SDimitry Andric OS << "\t.set\tmips5\n"; 5610b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips5(); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips32() { 5650b57cec5SDimitry Andric OS << "\t.set\tmips32\n"; 5660b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips32(); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { 5700b57cec5SDimitry Andric OS << "\t.set\tmips32r2\n"; 5710b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips32R2(); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() { 5750b57cec5SDimitry Andric OS << "\t.set\tmips32r3\n"; 5760b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips32R3(); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() { 5800b57cec5SDimitry Andric OS << "\t.set\tmips32r5\n"; 5810b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips32R5(); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() { 5850b57cec5SDimitry Andric OS << "\t.set\tmips32r6\n"; 5860b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips32R6(); 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips64() { 5900b57cec5SDimitry Andric OS << "\t.set\tmips64\n"; 5910b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips64(); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { 5950b57cec5SDimitry Andric OS << "\t.set\tmips64r2\n"; 5960b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips64R2(); 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() { 6000b57cec5SDimitry Andric OS << "\t.set\tmips64r3\n"; 6010b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips64R3(); 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() { 6050b57cec5SDimitry Andric OS << "\t.set\tmips64r5\n"; 6060b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips64R5(); 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() { 6100b57cec5SDimitry Andric OS << "\t.set\tmips64r6\n"; 6110b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetMips64R6(); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetDsp() { 6150b57cec5SDimitry Andric OS << "\t.set\tdsp\n"; 6160b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetDsp(); 6170b57cec5SDimitry Andric } 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetDspr2() { 6200b57cec5SDimitry Andric OS << "\t.set\tdspr2\n"; 6210b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetDspr2(); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() { 6250b57cec5SDimitry Andric OS << "\t.set\tnodsp\n"; 6260b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoDsp(); 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6295ffd83dbSDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetMips3D() { 6305ffd83dbSDimitry Andric OS << "\t.set\tmips3d\n"; 6315ffd83dbSDimitry Andric MipsTargetStreamer::emitDirectiveSetMips3D(); 6325ffd83dbSDimitry Andric } 6335ffd83dbSDimitry Andric 6345ffd83dbSDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoMips3D() { 6355ffd83dbSDimitry Andric OS << "\t.set\tnomips3d\n"; 6365ffd83dbSDimitry Andric MipsTargetStreamer::emitDirectiveSetNoMips3D(); 6375ffd83dbSDimitry Andric } 6385ffd83dbSDimitry Andric 6390b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetPop() { 6400b57cec5SDimitry Andric OS << "\t.set\tpop\n"; 6410b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetPop(); 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetPush() { 6450b57cec5SDimitry Andric OS << "\t.set\tpush\n"; 6460b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetPush(); 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() { 6500b57cec5SDimitry Andric OS << "\t.set\tsoftfloat\n"; 6510b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetSoftFloat(); 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() { 6550b57cec5SDimitry Andric OS << "\t.set\thardfloat\n"; 6560b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetHardFloat(); 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric // Print a 32 bit hex number with all numbers. 6600b57cec5SDimitry Andric static void printHex32(unsigned Value, raw_ostream &OS) { 6610b57cec5SDimitry Andric OS << "0x"; 6620b57cec5SDimitry Andric for (int i = 7; i >= 0; i--) 6630b57cec5SDimitry Andric OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4)); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask, 6670b57cec5SDimitry Andric int CPUTopSavedRegOff) { 6680b57cec5SDimitry Andric OS << "\t.mask \t"; 6690b57cec5SDimitry Andric printHex32(CPUBitmask, OS); 6700b57cec5SDimitry Andric OS << ',' << CPUTopSavedRegOff << '\n'; 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask, 6740b57cec5SDimitry Andric int FPUTopSavedRegOff) { 6750b57cec5SDimitry Andric OS << "\t.fmask\t"; 6760b57cec5SDimitry Andric printHex32(FPUBitmask, OS); 6770b57cec5SDimitry Andric OS << "," << FPUTopSavedRegOff << '\n'; 6780b57cec5SDimitry Andric } 6790b57cec5SDimitry Andric 6805ffd83dbSDimitry Andric void MipsTargetAsmStreamer::emitDirectiveCpAdd(unsigned RegNo) { 6815ffd83dbSDimitry Andric OS << "\t.cpadd\t$" 6825ffd83dbSDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; 6835ffd83dbSDimitry Andric forbidModuleDirective(); 6845ffd83dbSDimitry Andric } 6855ffd83dbSDimitry Andric 6860b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) { 6870b57cec5SDimitry Andric OS << "\t.cpload\t$" 6880b57cec5SDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; 6890b57cec5SDimitry Andric forbidModuleDirective(); 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) { 6930b57cec5SDimitry Andric OS << "\t.cplocal\t$" 6940b57cec5SDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; 6950b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveCpLocal(RegNo); 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric bool MipsTargetAsmStreamer::emitDirectiveCpRestore( 6990b57cec5SDimitry Andric int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, 7000b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 7010b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); 7020b57cec5SDimitry Andric OS << "\t.cprestore\t" << Offset << "\n"; 7030b57cec5SDimitry Andric return true; 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, 7070b57cec5SDimitry Andric int RegOrOffset, 7080b57cec5SDimitry Andric const MCSymbol &Sym, 7090b57cec5SDimitry Andric bool IsReg) { 7100b57cec5SDimitry Andric OS << "\t.cpsetup\t$" 7110b57cec5SDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", "; 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric if (IsReg) 7140b57cec5SDimitry Andric OS << "$" 7150b57cec5SDimitry Andric << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower(); 7160b57cec5SDimitry Andric else 7170b57cec5SDimitry Andric OS << RegOrOffset; 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric OS << ", "; 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric OS << Sym.getName(); 7220b57cec5SDimitry Andric forbidModuleDirective(); 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation, 7260b57cec5SDimitry Andric bool SaveLocationIsRegister) { 7270b57cec5SDimitry Andric OS << "\t.cpreturn"; 7280b57cec5SDimitry Andric forbidModuleDirective(); 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleFP() { 7320b57cec5SDimitry Andric MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI(); 7330b57cec5SDimitry Andric if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT) 7340b57cec5SDimitry Andric OS << "\t.module\tsoftfloat\n"; 7350b57cec5SDimitry Andric else 7360b57cec5SDimitry Andric OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n"; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetFp( 7400b57cec5SDimitry Andric MipsABIFlagsSection::FpABIKind Value) { 7410b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetFp(Value); 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric OS << "\t.set\tfp="; 7440b57cec5SDimitry Andric OS << ABIFlagsSection.getFpABIString(Value) << "\n"; 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() { 7480b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveModuleOddSPReg(); 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n"; 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() { 7540b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetOddSPReg(); 7550b57cec5SDimitry Andric OS << "\t.set\toddspreg\n"; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() { 7590b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveSetNoOddSPReg(); 7600b57cec5SDimitry Andric OS << "\t.set\tnooddspreg\n"; 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() { 7640b57cec5SDimitry Andric OS << "\t.module\tsoftfloat\n"; 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleHardFloat() { 7680b57cec5SDimitry Andric OS << "\t.module\thardfloat\n"; 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleMT() { 7720b57cec5SDimitry Andric OS << "\t.module\tmt\n"; 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleCRC() { 7760b57cec5SDimitry Andric OS << "\t.module\tcrc\n"; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() { 7800b57cec5SDimitry Andric OS << "\t.module\tnocrc\n"; 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleVirt() { 7840b57cec5SDimitry Andric OS << "\t.module\tvirt\n"; 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() { 7880b57cec5SDimitry Andric OS << "\t.module\tnovirt\n"; 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleGINV() { 7920b57cec5SDimitry Andric OS << "\t.module\tginv\n"; 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() { 7960b57cec5SDimitry Andric OS << "\t.module\tnoginv\n"; 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric // This part is for ELF object output. 8000b57cec5SDimitry Andric MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, 8010b57cec5SDimitry Andric const MCSubtargetInfo &STI) 8020b57cec5SDimitry Andric : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { 8030b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler(); 804*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric // It's possible that MCObjectFileInfo isn't fully initialized at this point 8070b57cec5SDimitry Andric // due to an initialization order problem where LLVMTargetMachine creates the 8080b57cec5SDimitry Andric // target streamer before TargetLoweringObjectFile calls 8090b57cec5SDimitry Andric // InitializeMCObjectFileInfo. There doesn't seem to be a single place that 8100b57cec5SDimitry Andric // covers all cases so this statement covers most cases and direct object 8110b57cec5SDimitry Andric // emission must call setPic() once MCObjectFileInfo has been initialized. The 8120b57cec5SDimitry Andric // cases we don't handle here are covered by MipsAsmPrinter. 8130b57cec5SDimitry Andric Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent(); 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric const FeatureBitset &Features = STI.getFeatureBits(); 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric // Set the header flags that we can in the constructor. 8180b57cec5SDimitry Andric // FIXME: This is a fairly terrible hack. We set the rest 8190b57cec5SDimitry Andric // of these in the destructor. The problem here is two-fold: 8200b57cec5SDimitry Andric // 8210b57cec5SDimitry Andric // a: Some of the eflags can be set/reset by directives. 8220b57cec5SDimitry Andric // b: There aren't any usage paths that initialize the ABI 8230b57cec5SDimitry Andric // pointer until after we initialize either an assembler 8240b57cec5SDimitry Andric // or the target machine. 8250b57cec5SDimitry Andric // We can fix this by making the target streamer construct 8260b57cec5SDimitry Andric // the ABI, but this is fraught with wide ranging dependency 8270b57cec5SDimitry Andric // issues as well. 828*0fca6ea1SDimitry Andric unsigned EFlags = W.getELFHeaderEFlags(); 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric // FIXME: Fix a dependency issue by instantiating the ABI object to some 8310b57cec5SDimitry Andric // default based off the triple. The triple doesn't describe the target 8320b57cec5SDimitry Andric // fully, but any external user of the API that uses the MCTargetStreamer 8330b57cec5SDimitry Andric // would otherwise crash on assertion failure. 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric ABI = MipsABIInfo( 8360b57cec5SDimitry Andric STI.getTargetTriple().getArch() == Triple::ArchType::mipsel || 8370b57cec5SDimitry Andric STI.getTargetTriple().getArch() == Triple::ArchType::mips 8380b57cec5SDimitry Andric ? MipsABIInfo::O32() 8390b57cec5SDimitry Andric : MipsABIInfo::N64()); 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric // Architecture 8420b57cec5SDimitry Andric if (Features[Mips::FeatureMips64r6]) 8430b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_64R6; 8440b57cec5SDimitry Andric else if (Features[Mips::FeatureMips64r2] || 8450b57cec5SDimitry Andric Features[Mips::FeatureMips64r3] || 8460b57cec5SDimitry Andric Features[Mips::FeatureMips64r5]) 8470b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_64R2; 8480b57cec5SDimitry Andric else if (Features[Mips::FeatureMips64]) 8490b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_64; 8500b57cec5SDimitry Andric else if (Features[Mips::FeatureMips5]) 8510b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_5; 8520b57cec5SDimitry Andric else if (Features[Mips::FeatureMips4]) 8530b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_4; 8540b57cec5SDimitry Andric else if (Features[Mips::FeatureMips3]) 8550b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_3; 8560b57cec5SDimitry Andric else if (Features[Mips::FeatureMips32r6]) 8570b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_32R6; 8580b57cec5SDimitry Andric else if (Features[Mips::FeatureMips32r2] || 8590b57cec5SDimitry Andric Features[Mips::FeatureMips32r3] || 8600b57cec5SDimitry Andric Features[Mips::FeatureMips32r5]) 8610b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_32R2; 8620b57cec5SDimitry Andric else if (Features[Mips::FeatureMips32]) 8630b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_32; 8640b57cec5SDimitry Andric else if (Features[Mips::FeatureMips2]) 8650b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_2; 8660b57cec5SDimitry Andric else 8670b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ARCH_1; 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric // Machine 8700b57cec5SDimitry Andric if (Features[Mips::FeatureCnMips]) 8710b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_MACH_OCTEON; 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric // Other options. 8740b57cec5SDimitry Andric if (Features[Mips::FeatureNaN2008]) 8750b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_NAN2008; 8760b57cec5SDimitry Andric 877*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(EFlags); 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric void MipsTargetELFStreamer::emitLabel(MCSymbol *S) { 8810b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolELF>(S); 8820b57cec5SDimitry Andric getStreamer().getAssembler().registerSymbol(*Symbol); 8830b57cec5SDimitry Andric uint8_t Type = Symbol->getType(); 8840b57cec5SDimitry Andric if (Type != ELF::STT_FUNC) 8850b57cec5SDimitry Andric return; 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric if (isMicroMipsEnabled()) 8880b57cec5SDimitry Andric Symbol->setOther(ELF::STO_MIPS_MICROMIPS); 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric void MipsTargetELFStreamer::finish() { 8920b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler(); 893*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 8940b57cec5SDimitry Andric const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo(); 895*0fca6ea1SDimitry Andric MCELFStreamer &S = getStreamer(); 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric // .bss, .text and .data are always at least 16-byte aligned. 8980b57cec5SDimitry Andric MCSection &TextSection = *OFI.getTextSection(); 899*0fca6ea1SDimitry Andric S.switchSection(&TextSection); 9000b57cec5SDimitry Andric MCSection &DataSection = *OFI.getDataSection(); 901*0fca6ea1SDimitry Andric S.switchSection(&DataSection); 9020b57cec5SDimitry Andric MCSection &BSSSection = *OFI.getBSSSection(); 903*0fca6ea1SDimitry Andric S.switchSection(&BSSSection); 9040b57cec5SDimitry Andric 905bdd1243dSDimitry Andric TextSection.ensureMinAlignment(Align(16)); 906bdd1243dSDimitry Andric DataSection.ensureMinAlignment(Align(16)); 907bdd1243dSDimitry Andric BSSSection.ensureMinAlignment(Align(16)); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric if (RoundSectionSizes) { 9100b57cec5SDimitry Andric // Make sections sizes a multiple of the alignment. This is useful for 9110b57cec5SDimitry Andric // verifying the output of IAS against the output of other assemblers but 9120b57cec5SDimitry Andric // it's not necessary to produce a correct object and increases section 9130b57cec5SDimitry Andric // size. 914*0fca6ea1SDimitry Andric for (MCSection &Sec : MCA) { 915*0fca6ea1SDimitry Andric MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); 9160b57cec5SDimitry Andric 917bdd1243dSDimitry Andric Align Alignment = Section.getAlign(); 918*0fca6ea1SDimitry Andric S.switchSection(&Section); 91981ad6265SDimitry Andric if (Section.useCodeAlign()) 920*0fca6ea1SDimitry Andric S.emitCodeAlignment(Alignment, &STI, Alignment.value()); 9210b57cec5SDimitry Andric else 922*0fca6ea1SDimitry Andric S.emitValueToAlignment(Alignment, 0, 1, Alignment.value()); 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric const FeatureBitset &Features = STI.getFeatureBits(); 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric // Update e_header flags. See the FIXME and comment above in 9290b57cec5SDimitry Andric // the constructor for a full rundown on this. 930*0fca6ea1SDimitry Andric unsigned EFlags = W.getELFHeaderEFlags(); 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric // ABI 9330b57cec5SDimitry Andric // N64 does not require any ABI bits. 9340b57cec5SDimitry Andric if (getABI().IsO32()) 9350b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ABI_O32; 9360b57cec5SDimitry Andric else if (getABI().IsN32()) 9370b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_ABI2; 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric if (Features[Mips::FeatureGP64Bit]) { 9400b57cec5SDimitry Andric if (getABI().IsO32()) 9410b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ 9420b57cec5SDimitry Andric } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64]) 9430b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_32BITMODE; 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric // -mplt is not implemented but we should act as if it was 9460b57cec5SDimitry Andric // given. 9470b57cec5SDimitry Andric if (!Features[Mips::FeatureNoABICalls]) 9480b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_CPIC; 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric if (Pic) 9510b57cec5SDimitry Andric EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; 9520b57cec5SDimitry Andric 953*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(EFlags); 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric // Emit all the option records. 9560b57cec5SDimitry Andric // At the moment we are only emitting .Mips.options (ODK_REGINFO) and 9570b57cec5SDimitry Andric // .reginfo. 9580b57cec5SDimitry Andric MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer); 9590b57cec5SDimitry Andric MEF.EmitMipsOptionRecords(); 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric emitMipsAbiFlags(); 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) { 9650b57cec5SDimitry Andric auto *Symbol = cast<MCSymbolELF>(S); 9660b57cec5SDimitry Andric // If on rhs is micromips symbol then mark Symbol as microMips. 9670b57cec5SDimitry Andric if (Value->getKind() != MCExpr::SymbolRef) 9680b57cec5SDimitry Andric return; 9690b57cec5SDimitry Andric const auto &RhsSym = cast<MCSymbolELF>( 9700b57cec5SDimitry Andric static_cast<const MCSymbolRefExpr *>(Value)->getSymbol()); 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS)) 9730b57cec5SDimitry Andric return; 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric Symbol->setOther(ELF::STO_MIPS_MICROMIPS); 9760b57cec5SDimitry Andric } 9770b57cec5SDimitry Andric 9780b57cec5SDimitry Andric MCELFStreamer &MipsTargetELFStreamer::getStreamer() { 9790b57cec5SDimitry Andric return static_cast<MCELFStreamer &>(Streamer); 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { 9830b57cec5SDimitry Andric MicroMipsEnabled = true; 9840b57cec5SDimitry Andric forbidModuleDirective(); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { 9880b57cec5SDimitry Andric MicroMipsEnabled = false; 9890b57cec5SDimitry Andric forbidModuleDirective(); 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric void MipsTargetELFStreamer::setUsesMicroMips() { 993*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 994*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 9950b57cec5SDimitry Andric Flags |= ELF::EF_MIPS_MICROMIPS; 996*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 9970b57cec5SDimitry Andric } 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveSetMips16() { 1000*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1001*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 10020b57cec5SDimitry Andric Flags |= ELF::EF_MIPS_ARCH_ASE_M16; 1003*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 10040b57cec5SDimitry Andric forbidModuleDirective(); 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { 1008*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1009*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 10100b57cec5SDimitry Andric Flags |= ELF::EF_MIPS_NOREORDER; 1011*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 10120b57cec5SDimitry Andric forbidModuleDirective(); 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { 10160b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler(); 10170b57cec5SDimitry Andric MCContext &Context = MCA.getContext(); 10180b57cec5SDimitry Andric MCStreamer &OS = getStreamer(); 10190b57cec5SDimitry Andric 1020*0fca6ea1SDimitry Andric OS.pushSection(); 10210b57cec5SDimitry Andric MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0); 1022*0fca6ea1SDimitry Andric OS.switchSection(Sec); 1023*0fca6ea1SDimitry Andric Sec->setAlignment(Align(4)); 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric MCSymbol *Sym = Context.getOrCreateSymbol(Name); 10260b57cec5SDimitry Andric const MCSymbolRefExpr *ExprRef = 10270b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context); 10280b57cec5SDimitry Andric 10295ffd83dbSDimitry Andric OS.emitValueImpl(ExprRef, 4); 10300b57cec5SDimitry Andric 10315ffd83dbSDimitry Andric OS.emitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask 10325ffd83dbSDimitry Andric OS.emitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset 10330b57cec5SDimitry Andric 10345ffd83dbSDimitry Andric OS.emitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask 10355ffd83dbSDimitry Andric OS.emitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset 10360b57cec5SDimitry Andric 10375ffd83dbSDimitry Andric OS.emitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset 10385ffd83dbSDimitry Andric OS.emitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg 10395ffd83dbSDimitry Andric OS.emitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric // The .end directive marks the end of a procedure. Invalidate 10420b57cec5SDimitry Andric // the information gathered up until this point. 10430b57cec5SDimitry Andric GPRInfoSet = FPRInfoSet = FrameInfoSet = false; 10440b57cec5SDimitry Andric 104581ad6265SDimitry Andric OS.popSection(); 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric // .end also implicitly sets the size. 10480b57cec5SDimitry Andric MCSymbol *CurPCSym = Context.createTempSymbol(); 10495ffd83dbSDimitry Andric OS.emitLabel(CurPCSym); 10500b57cec5SDimitry Andric const MCExpr *Size = MCBinaryExpr::createSub( 10510b57cec5SDimitry Andric MCSymbolRefExpr::create(CurPCSym, MCSymbolRefExpr::VK_None, Context), 10520b57cec5SDimitry Andric ExprRef, Context); 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric // The ELFObjectWriter can determine the absolute size as it has access to 10550b57cec5SDimitry Andric // the layout information of the assembly file, so a size expression rather 10560b57cec5SDimitry Andric // than an absolute value is ok here. 10570b57cec5SDimitry Andric static_cast<MCSymbolELF *>(Sym)->setSize(Size); 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { 10610b57cec5SDimitry Andric GPRInfoSet = FPRInfoSet = FrameInfoSet = false; 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric // .ent also acts like an implicit '.type symbol, STT_FUNC' 10640b57cec5SDimitry Andric static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC); 10650b57cec5SDimitry Andric } 10660b57cec5SDimitry Andric 10670b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveAbiCalls() { 1068*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1069*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 10700b57cec5SDimitry Andric Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC; 1071*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveNaN2008() { 1075*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1076*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 10770b57cec5SDimitry Andric Flags |= ELF::EF_MIPS_NAN2008; 1078*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveNaNLegacy() { 1082*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1083*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 10840b57cec5SDimitry Andric Flags &= ~ELF::EF_MIPS_NAN2008; 1085*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveOptionPic0() { 1089*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1090*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 10910b57cec5SDimitry Andric // This option overrides other PIC options like -KPIC. 10920b57cec5SDimitry Andric Pic = false; 10930b57cec5SDimitry Andric Flags &= ~ELF::EF_MIPS_PIC; 1094*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveOptionPic2() { 1098*0fca6ea1SDimitry Andric ELFObjectWriter &W = getStreamer().getWriter(); 1099*0fca6ea1SDimitry Andric unsigned Flags = W.getELFHeaderEFlags(); 11000b57cec5SDimitry Andric Pic = true; 11010b57cec5SDimitry Andric // NOTE: We are following the GAS behaviour here which means the directive 11020b57cec5SDimitry Andric // 'pic2' also sets the CPIC bit in the ELF header. This is different from 11030b57cec5SDimitry Andric // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and 11040b57cec5SDimitry Andric // EF_MIPS_CPIC to be mutually exclusive. 11050b57cec5SDimitry Andric Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; 1106*0fca6ea1SDimitry Andric W.setELFHeaderEFlags(Flags); 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveInsn() { 11100b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveInsn(); 11110b57cec5SDimitry Andric MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer); 11120b57cec5SDimitry Andric MEF.createPendingLabelRelocs(); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize, 11160b57cec5SDimitry Andric unsigned ReturnReg_) { 11170b57cec5SDimitry Andric MCContext &Context = getStreamer().getAssembler().getContext(); 11180b57cec5SDimitry Andric const MCRegisterInfo *RegInfo = Context.getRegisterInfo(); 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric FrameInfoSet = true; 11210b57cec5SDimitry Andric FrameReg = RegInfo->getEncodingValue(StackReg); 11220b57cec5SDimitry Andric FrameOffset = StackSize; 11230b57cec5SDimitry Andric ReturnReg = RegInfo->getEncodingValue(ReturnReg_); 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask, 11270b57cec5SDimitry Andric int CPUTopSavedRegOff) { 11280b57cec5SDimitry Andric GPRInfoSet = true; 11290b57cec5SDimitry Andric GPRBitMask = CPUBitmask; 11300b57cec5SDimitry Andric GPROffset = CPUTopSavedRegOff; 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask, 11340b57cec5SDimitry Andric int FPUTopSavedRegOff) { 11350b57cec5SDimitry Andric FPRInfoSet = true; 11360b57cec5SDimitry Andric FPRBitMask = FPUBitmask; 11370b57cec5SDimitry Andric FPROffset = FPUTopSavedRegOff; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 11405ffd83dbSDimitry Andric void MipsTargetELFStreamer::emitDirectiveCpAdd(unsigned RegNo) { 11415ffd83dbSDimitry Andric // .cpadd $reg 11425ffd83dbSDimitry Andric // This directive inserts code to add $gp to the argument's register 11435ffd83dbSDimitry Andric // when support for position independent code is enabled. 11445ffd83dbSDimitry Andric if (!Pic) 11455ffd83dbSDimitry Andric return; 11465ffd83dbSDimitry Andric 11475ffd83dbSDimitry Andric emitAddu(RegNo, RegNo, GPReg, getABI().IsN64(), &STI); 11485ffd83dbSDimitry Andric forbidModuleDirective(); 11495ffd83dbSDimitry Andric } 11505ffd83dbSDimitry Andric 11510b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { 11520b57cec5SDimitry Andric // .cpload $reg 11530b57cec5SDimitry Andric // This directive expands to: 11540b57cec5SDimitry Andric // lui $gp, %hi(_gp_disp) 11550b57cec5SDimitry Andric // addui $gp, $gp, %lo(_gp_disp) 11560b57cec5SDimitry Andric // addu $gp, $gp, $reg 11570b57cec5SDimitry Andric // when support for position independent code is enabled. 11580b57cec5SDimitry Andric if (!Pic || (getABI().IsN32() || getABI().IsN64())) 11590b57cec5SDimitry Andric return; 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric // There's a GNU extension controlled by -mno-shared that allows 11620b57cec5SDimitry Andric // locally-binding symbols to be accessed using absolute addresses. 11630b57cec5SDimitry Andric // This is currently not supported. When supported -mno-shared makes 11640b57cec5SDimitry Andric // .cpload expand to: 11650b57cec5SDimitry Andric // lui $gp, %hi(__gnu_local_gp) 11660b57cec5SDimitry Andric // addiu $gp, $gp, %lo(__gnu_local_gp) 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric StringRef SymName("_gp_disp"); 11690b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler(); 11700b57cec5SDimitry Andric MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName); 11710b57cec5SDimitry Andric MCA.registerSymbol(*GP_Disp); 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andric MCInst TmpInst; 11740b57cec5SDimitry Andric TmpInst.setOpcode(Mips::LUi); 11750b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(GPReg)); 11760b57cec5SDimitry Andric const MCExpr *HiSym = MipsMCExpr::create( 11770b57cec5SDimitry Andric MipsMCExpr::MEK_HI, 11780b57cec5SDimitry Andric MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, 11790b57cec5SDimitry Andric MCA.getContext()), 11800b57cec5SDimitry Andric MCA.getContext()); 11810b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createExpr(HiSym)); 11825ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, STI); 11830b57cec5SDimitry Andric 11840b57cec5SDimitry Andric TmpInst.clear(); 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric TmpInst.setOpcode(Mips::ADDiu); 11870b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(GPReg)); 11880b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(GPReg)); 11890b57cec5SDimitry Andric const MCExpr *LoSym = MipsMCExpr::create( 11900b57cec5SDimitry Andric MipsMCExpr::MEK_LO, 11910b57cec5SDimitry Andric MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, 11920b57cec5SDimitry Andric MCA.getContext()), 11930b57cec5SDimitry Andric MCA.getContext()); 11940b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createExpr(LoSym)); 11955ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, STI); 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric TmpInst.clear(); 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric TmpInst.setOpcode(Mips::ADDu); 12000b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(GPReg)); 12010b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(GPReg)); 12020b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(RegNo)); 12035ffd83dbSDimitry Andric getStreamer().emitInstruction(TmpInst, STI); 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric forbidModuleDirective(); 12060b57cec5SDimitry Andric } 12070b57cec5SDimitry Andric 12080b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) { 12090b57cec5SDimitry Andric if (Pic) 12100b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveCpLocal(RegNo); 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric bool MipsTargetELFStreamer::emitDirectiveCpRestore( 12140b57cec5SDimitry Andric int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, 12150b57cec5SDimitry Andric const MCSubtargetInfo *STI) { 12160b57cec5SDimitry Andric MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); 12170b57cec5SDimitry Andric // .cprestore offset 12180b57cec5SDimitry Andric // When PIC mode is enabled and the O32 ABI is used, this directive expands 12190b57cec5SDimitry Andric // to: 12200b57cec5SDimitry Andric // sw $gp, offset($sp) 12210b57cec5SDimitry Andric // and adds a corresponding LW after every JAL. 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it 12240b57cec5SDimitry Andric // is used in non-PIC mode. 12250b57cec5SDimitry Andric if (!Pic || (getABI().IsN32() || getABI().IsN64())) 12260b57cec5SDimitry Andric return true; 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric // Store the $gp on the stack. 12290b57cec5SDimitry Andric emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc, 12300b57cec5SDimitry Andric STI); 12310b57cec5SDimitry Andric return true; 12320b57cec5SDimitry Andric } 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, 12350b57cec5SDimitry Andric int RegOrOffset, 12360b57cec5SDimitry Andric const MCSymbol &Sym, 12370b57cec5SDimitry Andric bool IsReg) { 12380b57cec5SDimitry Andric // Only N32 and N64 emit anything for .cpsetup iff PIC is set. 12390b57cec5SDimitry Andric if (!Pic || !(getABI().IsN32() || getABI().IsN64())) 12400b57cec5SDimitry Andric return; 12410b57cec5SDimitry Andric 12420b57cec5SDimitry Andric forbidModuleDirective(); 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler(); 12450b57cec5SDimitry Andric MCInst Inst; 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric // Either store the old $gp in a register or on the stack 12480b57cec5SDimitry Andric if (IsReg) { 12490b57cec5SDimitry Andric // move $save, $gpreg 12500b57cec5SDimitry Andric emitRRR(Mips::OR64, RegOrOffset, GPReg, Mips::ZERO, SMLoc(), &STI); 12510b57cec5SDimitry Andric } else { 12520b57cec5SDimitry Andric // sd $gpreg, offset($sp) 12530b57cec5SDimitry Andric emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI); 12540b57cec5SDimitry Andric } 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff( 12570b57cec5SDimitry Andric MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()), 12580b57cec5SDimitry Andric MCA.getContext()); 12590b57cec5SDimitry Andric const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff( 12600b57cec5SDimitry Andric MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()), 12610b57cec5SDimitry Andric MCA.getContext()); 12620b57cec5SDimitry Andric 12630b57cec5SDimitry Andric // lui $gp, %hi(%neg(%gp_rel(funcSym))) 12640b57cec5SDimitry Andric emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI); 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) 12670b57cec5SDimitry Andric emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(), 12680b57cec5SDimitry Andric &STI); 12690b57cec5SDimitry Andric 1270439352acSDimitry Andric // (d)addu $gp, $gp, $funcreg 1271439352acSDimitry Andric if (getABI().IsN32()) 1272439352acSDimitry Andric emitRRR(Mips::ADDu, GPReg, GPReg, RegNo, SMLoc(), &STI); 1273439352acSDimitry Andric else 12740b57cec5SDimitry Andric emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI); 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, 12780b57cec5SDimitry Andric bool SaveLocationIsRegister) { 12790b57cec5SDimitry Andric // Only N32 and N64 emit anything for .cpreturn iff PIC is set. 12800b57cec5SDimitry Andric if (!Pic || !(getABI().IsN32() || getABI().IsN64())) 12810b57cec5SDimitry Andric return; 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric MCInst Inst; 12840b57cec5SDimitry Andric // Either restore the old $gp from a register or on the stack 12850b57cec5SDimitry Andric if (SaveLocationIsRegister) { 12860b57cec5SDimitry Andric Inst.setOpcode(Mips::OR); 12870b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(GPReg)); 12880b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(SaveLocation)); 12890b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(Mips::ZERO)); 12900b57cec5SDimitry Andric } else { 12910b57cec5SDimitry Andric Inst.setOpcode(Mips::LD); 12920b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(GPReg)); 12930b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(Mips::SP)); 12940b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(SaveLocation)); 12950b57cec5SDimitry Andric } 12965ffd83dbSDimitry Andric getStreamer().emitInstruction(Inst, STI); 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric forbidModuleDirective(); 12990b57cec5SDimitry Andric } 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric void MipsTargetELFStreamer::emitMipsAbiFlags() { 13020b57cec5SDimitry Andric MCAssembler &MCA = getStreamer().getAssembler(); 13030b57cec5SDimitry Andric MCContext &Context = MCA.getContext(); 13040b57cec5SDimitry Andric MCStreamer &OS = getStreamer(); 13050b57cec5SDimitry Andric MCSectionELF *Sec = Context.getELFSection( 1306fe6060f1SDimitry Andric ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24); 130781ad6265SDimitry Andric OS.switchSection(Sec); 1308*0fca6ea1SDimitry Andric Sec->setAlignment(Align(8)); 13090b57cec5SDimitry Andric 13100b57cec5SDimitry Andric OS << ABIFlagsSection; 13110b57cec5SDimitry Andric } 1312