Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -115,6 +115,8 @@ // selected. This usually happens after an '.end func' // directive. bool IsPicEnabled; + bool IsCpRestoreSet; + int CpRestoreOffset; // Print a warning along with its fix-it message at the given range. void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, @@ -222,6 +224,9 @@ void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, SmallVectorImpl &Instructions); + void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); @@ -234,7 +239,9 @@ bool parseSetMips0Directive(); bool parseSetArchDirective(); bool parseSetFeature(uint64_t Feature); + bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup. bool parseDirectiveCpLoad(SMLoc Loc); + bool parseDirectiveCpRestore(SMLoc Loc); bool parseDirectiveCPSetup(); bool parseDirectiveNaN(); bool parseDirectiveSet(); @@ -392,6 +399,9 @@ IsPicEnabled = (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_); + + IsCpRestoreSet = false; + CpRestoreOffset = -1; } /// True if all of $fcc0 - $fcc7 exist for the current ISA. @@ -1310,6 +1320,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions) { const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); + bool ExpandedJalSym = false; Inst.setLoc(IDLoc); @@ -1530,7 +1541,10 @@ } MCInst JalrInst; - JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); + if (IsCpRestoreSet && inMicroMipsMode()) + JalrInst.setOpcode(Mips::JALRS_MM); + else + JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); JalrInst.addOperand(MCOperand::createReg(Mips::RA)); JalrInst.addOperand(MCOperand::createReg(Mips::T9)); @@ -1539,6 +1553,7 @@ // and is not necessary for correctness. Inst = JalrInst; + ExpandedJalSym = true; } if (MCID.mayLoad() || MCID.mayStore()) { @@ -1741,6 +1756,29 @@ if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); + if ((Inst.getOpcode() == Mips::JalOneReg || + Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && + isPicAndNotNxxAbi()) { + if (IsCpRestoreSet) { + // We need a NOP between the JALR and the LW: + // If .set reorder has been used, we've already emitted a NOP. + // If .set noreorder has been used, we need to emit a NOP at this point. + if (!AssemblerOptions.back()->isReorder()) + createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); + + // Load the $gp from the stack. + SmallVector LoadInsts; + createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/, + IDLoc, LoadInsts); + + for (const MCInst &Inst : LoadInsts) + Instructions.push_back(Inst); + + } else { + Warning(IDLoc, "no .cprestore used in PIC mode"); + } + } + return false; } @@ -1859,7 +1897,10 @@ if (Opcode == Mips::JalOneReg) { // jal $rs => jalr $rs - if (inMicroMipsMode()) { + if (IsCpRestoreSet && inMicroMipsMode()) { + JalrInst.setOpcode(Mips::JALRS16_MM); + JalrInst.addOperand(FirstRegOp); + } else if (inMicroMipsMode()) { JalrInst.setOpcode(Mips::JALR16_MM); JalrInst.addOperand(FirstRegOp); } else { @@ -1869,7 +1910,10 @@ } } else if (Opcode == Mips::JalTwoReg) { // jal $rd, $rs => jalr $rd, $rs - JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); + if (IsCpRestoreSet && inMicroMipsMode()) + JalrInst.setOpcode(Mips::JALRS_MM); + else + JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); JalrInst.addOperand(FirstRegOp); const MCOperand SecondRegOp = Inst.getOperand(1); JalrInst.addOperand(SecondRegOp); @@ -1877,16 +1921,8 @@ Instructions.push_back(JalrInst); // If .set reorder is active, emit a NOP after it. - if (AssemblerOptions.back()->isReorder()) { - // This is a 32-bit NOP because these 2 pseudo-instructions - // do not have a short delay slot. - MCInst NopInst; - NopInst.setOpcode(Mips::SLL); - NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::createImm(0)); - Instructions.push_back(NopInst); - } + if (AssemblerOptions.back()->isReorder()) + createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions); return false; } @@ -2607,6 +2643,26 @@ Instructions.push_back(AdduInst); } +void MipsAsmParser::createCpRestoreMemOp( + bool IsLoad, int StackOffset, SMLoc IDLoc, + SmallVectorImpl &Instructions) { + MCInst MemInst; + if (IsLoad) + MemInst.setOpcode(Mips::LW); + else + MemInst.setOpcode(Mips::SW); + + MemInst.addOperand(MCOperand::createReg(Mips::GP)); + MemInst.addOperand(MCOperand::createReg(Mips::SP)); + MemInst.addOperand(MCOperand::createImm(StackOffset)); + + // If the offset can not fit into 16 bits, we need to expand. + if (!isInt<16>(StackOffset)) + expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/); + else + Instructions.push_back(MemInst); +} + unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // As described by the Mips32r2 spec, the registers Rd and Rs for // jalr.hb must be different. @@ -4225,6 +4281,14 @@ return true; } +// Used to determine if .cpload, .cprestore, and .cpsetup have any effect. +// In this class, it is only used for .cprestore. +// FIXME: Only keep track of IsPicEnabled in one place, instead of in both +// MipsTargetELFStreamer and MipsAsmParser. +bool MipsAsmParser::isPicAndNotNxxAbi() { + return inPicMode() && !(isABI_N32() || isABI_N64()); +} + bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { if (AssemblerOptions.back()->isReorder()) Warning(Loc, ".cpload should be inside a noreorder section"); @@ -4257,6 +4321,54 @@ return false; } +bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { + MCAsmParser &Parser = getParser(); + + // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it + // is used in non-PIC mode. + + if (inMips16Mode()) { + reportParseError(".cprestore is not supported in Mips16 mode"); + return false; + } + + // Get the stack offset value. + const MCExpr *StackOffset; + int64_t StackOffsetVal; + if (Parser.parseExpression(StackOffset)) { + reportParseError("expected stack offset value"); + return false; + } + + if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) { + reportParseError("stack offset is not an absolute expression"); + return false; + } + + if (StackOffsetVal < 0) { + Warning(Loc, ".cprestore with negative stack offset has no effect"); + IsCpRestoreSet = false; + } else { + IsCpRestoreSet = true; + CpRestoreOffset = StackOffsetVal; + } + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + // Store the $gp on the stack. + SmallVector StoreInsts; + createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc, + StoreInsts); + + getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + bool MipsAsmParser::parseDirectiveCPSetup() { MCAsmParser &Parser = getParser(); unsigned FuncReg; @@ -4699,6 +4811,8 @@ if (IDVal == ".cpload") return parseDirectiveCpLoad(DirectiveID.getLoc()); + if (IDVal == ".cprestore") + return parseDirectiveCpRestore(DirectiveID.getLoc()); if (IDVal == ".dword") { parseDataDirective(8, DirectiveID.getLoc()); return false; @@ -4749,6 +4863,7 @@ getTargetStreamer().emitDirectiveEnt(*Sym); CurrentFn = Sym; + IsCpRestoreSet = false; return false; } @@ -4777,6 +4892,7 @@ getTargetStreamer().emitDirectiveEnd(SymbolName); CurrentFn = nullptr; + IsCpRestoreSet = false; return false; } @@ -4848,6 +4964,7 @@ getTargetStreamer().emitFrame(StackReg, FrameSizeVal, ReturnRegOpnd.getGPR32Reg()); + IsCpRestoreSet = false; return false; } Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -89,6 +89,10 @@ void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} +void MipsTargetStreamer::emitDirectiveCpRestore( + SmallVector &StoreInsts, int Offset) { + forbidModuleDirective(); +} void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) { } @@ -350,6 +354,12 @@ forbidModuleDirective(); } +void MipsTargetAsmStreamer::emitDirectiveCpRestore( + SmallVector &StoreInsts, int Offset) { + MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset); + OS << "\t.cprestore\t" << Offset << "\n"; +} + void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, @@ -730,6 +740,24 @@ forbidModuleDirective(); } +void MipsTargetELFStreamer::emitDirectiveCpRestore( + SmallVector &StoreInsts, int Offset) { + MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset); + // .cprestore offset + // When PIC mode is enabled and the O32 ABI is used, this directive expands + // to: + // sw $gp, offset($sp) + // and adds a corresponding LW after every JAL. + + // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it + // is used in non-PIC mode. + if (!Pic || (getABI().IsN32() || getABI().IsN64())) + return; + + for (const MCInst &Inst : StoreInsts) + getStreamer().EmitInstruction(Inst, STI); +} + void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -77,6 +77,8 @@ // PIC support virtual void emitDirectiveCpLoad(unsigned RegNo); + virtual void emitDirectiveCpRestore(SmallVector &StoreInsts, + int Offset); virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); @@ -195,6 +197,8 @@ // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; + void emitDirectiveCpRestore(SmallVector &StoreInsts, + int Offset) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; @@ -241,6 +245,8 @@ // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; + void emitDirectiveCpRestore(SmallVector &StoreInsts, + int Offset) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; Index: test/MC/Mips/cprestore-bad.s =================================================================== --- /dev/null +++ test/MC/Mips/cprestore-bad.s @@ -0,0 +1,23 @@ +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic 2>%t1 +# RUN: FileCheck %s < %t1 + + .text + .set noreorder + .cpload $25 + + .set mips16 + .cprestore 8 +# CHECK: :[[@LINE-1]]:14: error: .cprestore is not supported in Mips16 mode + .set nomips16 + + .cprestore +# CHECK: :[[@LINE-1]]:13: error: expected stack offset value + + .cprestore foo +# CHECK: :[[@LINE-1]]:17: error: stack offset is not an absolute expression + + .cprestore -8 +# CHECK: :[[@LINE-1]]:3: warning: .cprestore with negative stack offset has no effect + + .cprestore 8, 35, bar +# CHECK: :[[@LINE-1]]:15: error: unexpected token, expected end of statement Index: test/MC/Mips/cprestore-noreorder.s =================================================================== --- /dev/null +++ test/MC/Mips/cprestore-noreorder.s @@ -0,0 +1,97 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -filetype=obj -o -| \ +# RUN: llvm-objdump -d -r -arch=mips - | \ +# RUN: FileCheck %s -check-prefix=CHECK-FOR-STORE + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -mattr=+micromips -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=MICROMIPS + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=static -show-encoding | \ +# RUN: FileCheck %s -check-prefix=NO-PIC + +# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -target-abi n32 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N32 + +# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -target-abi n64 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N64 + + .text + .ent foo +foo: + .frame $sp, 0, $ra + .set noreorder + + .cpload $25 + .cprestore 8 + + jal $25 + jal $4, $25 + jal foo + + .end foo + +# CHECK-FOR-STORE: sw $gp, 8($sp) + +# CHECK: .cprestore 8 +# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# CHECK: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# CHECK: lw $25, %got(foo)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local +# CHECK: addiu $25, $25, %lo(foo) # encoding: [0x27,0x39,A,A] +# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16 +# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] +# CHECK: .end foo + +# MICROMIPS: .cprestore 8 +# MICROMIPS: jalrs16 $25 # encoding: [0x45,0xf9] +# MICROMIPS: nop # encoding: [0x00,0x00,0x00,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: jalrs $4, $25 # encoding: [0x00,0x99,0x4f,0x3c] +# MICROMIPS: nop # encoding: [0x00,0x00,0x00,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %got(foo)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: foo@GOT, kind: fixup_MICROMIPS_GOT16 +# MICROMIPS: addiu $25, $25, %lo(foo) # encoding: [0x33,0x39,A,A] +# MICROMIPS: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: nop # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] +# MICROMIPS: .end foo + +# NO-PIC: .cprestore 8 +# NO-PIC: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# NO-PIC: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] +# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# NO-PIC: jal foo # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: foo, kind: fixup_Mips_26 +# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] +# NO-PIC: .end foo + +# BAD-ABI: .cprestore 8 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# BAD-ABI: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] +# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# BAD-ABI-N32: lw $25, %got_disp(foo)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI-N64: ld $25, %got_disp(foo)($gp) # encoding: [0xdf,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] +# BAD-ABI: .end foo Index: test/MC/Mips/cprestore-reorder.s =================================================================== --- /dev/null +++ test/MC/Mips/cprestore-reorder.s @@ -0,0 +1,98 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic -filetype=obj -o -| \ +# RUN: llvm-objdump -d -r -arch=mips - | \ +# RUN: FileCheck %s -check-prefix=CHECK-FOR-STORE + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -mattr=+micromips -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=MICROMIPS + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=static -show-encoding | \ +# RUN: FileCheck %s -check-prefix=NO-PIC + +# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -target-abi n32 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N32 + +# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -target-abi n64 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI -check-prefix=BAD-ABI-N64 + + .text + .ent foo +foo: + .frame $sp, 0, $ra + .set noreorder + .cpload $25 + .set reorder + + .cprestore 8 + + jal $25 + jal $4, $25 + jal foo + + .end foo + +# CHECK-FOR-STORE: sw $gp, 8($sp) + +# CHECK: .cprestore 8 +# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# CHECK: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# CHECK: lw $25, %got(foo)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: foo@GOT, kind: fixup_Mips_GOT_Local +# CHECK: addiu $25, $25, %lo(foo) # encoding: [0x27,0x39,A,A] +# CHECK: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16 +# CHECK: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# CHECK: nop # encoding: [0x00,0x00,0x00,0x00] +# CHECK: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] +# CHECK: .end foo + +# MICROMIPS: .cprestore 8 +# MICROMIPS: jalrs16 $25 # encoding: [0x45,0xf9] +# MICROMIPS: nop # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: jalrs $4, $25 # encoding: [0x00,0x99,0x4f,0x3c] +# MICROMIPS: nop # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %got(foo)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: foo@GOT, kind: fixup_MICROMIPS_GOT16 +# MICROMIPS: addiu $25, $25, %lo(foo) # encoding: [0x33,0x39,A,A] +# MICROMIPS: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: nop # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] +# MICROMIPS: .end foo + +# NO-PIC: .cprestore 8 +# NO-PIC: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# NO-PIC: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] +# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# NO-PIC: jal foo # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: foo, kind: fixup_Mips_26 +# NO-PIC-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] +# NO-PIC: .end foo + +# BAD-ABI: .cprestore 8 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# BAD-ABI: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] +# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] + +# BAD-ABI-N32: lw $25, %got_disp(foo)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI-N64: ld $25, %got_disp(foo)($gp) # encoding: [0xdf,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: foo@GOT_DISP, kind: fixup_Mips_GOT_DISP +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI-NOT: lw $gp, 8($sp) # encoding: [0x8f,0xbc,0x00,0x08] +# BAD-ABI: .end foo Index: test/MC/Mips/cprestore-warning-unused.s =================================================================== --- /dev/null +++ test/MC/Mips/cprestore-warning-unused.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic 2>%t1 +# RUN: FileCheck %s < %t1 + + .text + .set noreorder + .cpload $25 + .set reorder + + jal $25 +# CHECK: :[[@LINE-1]]:3: warning: no .cprestore used in PIC mode