Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -102,6 +102,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, @@ -177,6 +179,10 @@ void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions, bool isLoad, bool isImmOpnd); + + void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); @@ -190,6 +196,7 @@ bool parseSetArchDirective(); bool parseSetFeature(uint64_t Feature); bool parseDirectiveCpLoad(SMLoc Loc); + bool parseDirectiveCpRestore(SMLoc Loc); bool parseDirectiveCPSetup(); bool parseDirectiveNaN(); bool parseDirectiveSet(); @@ -341,6 +348,8 @@ IsPicEnabled = (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_); + + IsCpRestoreSet = false; } /// True if all of $fcc0 - $fcc7 exist for the current ISA. @@ -1043,7 +1052,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions) { const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); - + bool ExpandedJalSym = false; Inst.setLoc(IDLoc); if (MCID.isBranch() || MCID.isCall()) { @@ -1186,7 +1195,9 @@ } MCInst JalrInst; - if (inMicroMipsMode()) + if (IsCpRestoreSet && inMicroMipsMode()) + JalrInst.setOpcode(Mips::JALRS_MM); + else if (inMicroMipsMode()) JalrInst.setOpcode(Mips::JALR_MM); else JalrInst.setOpcode(Mips::JALR); @@ -1201,6 +1212,7 @@ // we're jumping to. Inst = JalrInst; + ExpandedJalSym = true; } if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { @@ -1219,7 +1231,9 @@ NopInst.addOperand(MCOperand::CreateImm(0)); } Instructions.push_back(NopInst); - return false; + + if (ExpandedJalSym == false) + return false; } if (MCID.mayLoad() || MCID.mayStore()) { @@ -1330,11 +1344,48 @@ } } - if (needsExpansion(Inst)) - return expandInstruction(Inst, IDLoc, Instructions); - else + if (needsExpansion(Inst)) { + if (expandInstruction(Inst, IDLoc, Instructions)) + return true; + } else { Instructions.push_back(Inst); + } + + if ((Inst.getOpcode() == Mips::JalOneReg || + Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && + inPicMode() && !(isABI_N32() || isABI_N64())) { + if (IsCpRestoreSet) { + // Emit a NOP after the JALR, even if .set reorder has not been used. + if (!AssemblerOptions.back()->isReorder()) { + MCInst NopInst; + if (hasShortDelaySlot(Inst.getOpcode()) || + ((Inst.getOpcode() == Mips::JalOneReg || + Inst.getOpcode() == Mips::JalTwoReg) && + inMicroMipsMode())) { + NopInst.setOpcode(Mips::MOVE16_MM); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + } else { + 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); + } + + // 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; } @@ -1418,7 +1469,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 { @@ -1428,7 +1482,9 @@ } } else if (Opcode == Mips::JalTwoReg) { // jal $rd, $rs => jalr $rd, $rs - if (inMicroMipsMode()) + if (IsCpRestoreSet && inMicroMipsMode()) + JalrInst.setOpcode(Mips::JALRS_MM); + else if (inMicroMipsMode()) JalrInst.setOpcode(Mips::JALR_MM); else JalrInst.setOpcode(Mips::JALR); @@ -1441,13 +1497,17 @@ // 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)); + if (hasShortDelaySlot(JalrInst.getOpcode())) { + NopInst.setOpcode(Mips::MOVE16_MM); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + } else { + 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); } @@ -1821,6 +1881,26 @@ TempInst.clear(); } +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 (StackOffset < -32768 || StackOffset > 32767) + 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. @@ -3284,6 +3364,57 @@ return false; } +bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { + MCAsmParser &Parser = getParser(); + + if (isABI_N32() || isABI_N64()) + Warning(Loc, ".cprestore is not supported on the N32 and N64 ABIs"); + + if (!inPicMode()) + Warning(Loc, ".cprestore requires 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; @@ -3688,6 +3819,8 @@ if (IDVal == ".cpload") return parseDirectiveCpLoad(DirectiveID.getLoc()); + if (IDVal == ".cprestore") + return parseDirectiveCpRestore(DirectiveID.getLoc()); if (IDVal == ".dword") { parseDataDirective(8, DirectiveID.getLoc()); return false; @@ -3738,6 +3871,7 @@ getTargetStreamer().emitDirectiveEnt(*Sym); CurrentFn = Sym; + IsCpRestoreSet = false; return false; } @@ -3766,6 +3900,7 @@ getTargetStreamer().emitDirectiveEnd(SymbolName); CurrentFn = nullptr; + IsCpRestoreSet = false; return false; } @@ -3837,6 +3972,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 @@ -76,6 +76,8 @@ void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} +void MipsTargetStreamer::emitDirectiveCpRestore( + SmallVector &StoreInsts, int Offset) {} void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) { } @@ -284,6 +286,12 @@ forbidModuleDirective(); } +void MipsTargetAsmStreamer::emitDirectiveCpRestore( + SmallVector &StoreInsts, int Offset) { + OS << "\t.cprestore\t" << Offset << "\n"; + forbidModuleDirective(); +} + void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, @@ -648,6 +656,23 @@ forbidModuleDirective(); } +void MipsTargetELFStreamer::emitDirectiveCpRestore( + SmallVector &StoreInsts, int 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. + + if (!Pic || (isN32() || isN64())) + return; + + for (const MCInst &Inst : StoreInsts) + getStreamer().EmitInstruction(Inst, STI); + + forbidModuleDirective(); +} + 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 @@ -68,6 +68,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); @@ -172,6 +174,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; @@ -218,6 +222,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,35 @@ +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=pic 2>%t1 +# RUN: FileCheck %s < %t1 + +# RUN: not llvm-mc %s -arch=mips -mcpu=mips32 -relocation-model=static 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=NO-PIC + +# RUN: not llvm-mc %s -arch=mips -mcpu=mips64 -mattr=-n64,+n32 -relocation-model=pic 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=BAD-ABI + +# RUN: not llvm-mc %s -arch=mips -mcpu=mips64 -mattr=+n64 -relocation-model=pic 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=BAD-ABI + + .text + .set noreorder + .cpload $25 + .cprestore 8 +# BAD-ABI: :[[@LINE-1]]:3: warning: .cprestore is not supported on the N32 and N64 ABIs +# NO-PIC: :[[@LINE-2]]:3: warning: .cprestore requires PIC mode + + .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,131 @@ +# 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 -mattr=-n64,+n32 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI + +# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -mattr=+n64 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI + + .text + .weak weak_label + + .ent local_label +local_label: + .frame $sp, 0, $ra + .set noreorder + + .cpload $25 + .cprestore 8 + + jal $25 + jal $4, $25 + + jal local_label + jal weak_label + jal external_label + + .end local_label + +# 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(.text)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: .text@GOT, kind: fixup_Mips_GOT_Local +# CHECK: addiu $25, $25, %lo(.text) # encoding: [0x27,0x39,A,A] +# CHECK: # fixup A - offset: 0, value: .text@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: lw $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_Mips_CALL16 +# 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: lw $25, %call16(external_label)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: external_label@GOT_CALL, kind: fixup_Mips_CALL16 +# 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 local_label + +# MICROMIPS: .cprestore 8 +# MICROMIPS: jalrs16 $25 # encoding: [0x45,0xf9] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: jalrs $4, $25 # encoding: [0x00,0x99,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %got(local_label)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: local_label@GOT, kind: fixup_MICROMIPS_GOT16 +# MICROMIPS: addiu $25, $25, %lo(local_label) # encoding: [0x33,0x39,A,A] +# MICROMIPS: # fixup A - offset: 0, value: local_label@ABS_LO, kind: fixup_MICROMIPS_LO16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %call16(weak_label)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %call16(external_label)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: external_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] +# MICROMIPS: .end local_label + +# NO-PIC: .cprestore 8 +# NO-PIC: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# NO-PIC: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] + +# NO-PIC: jal local_label # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: local_label, kind: fixup_Mips_26 + +# NO-PIC: jal weak_label # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: weak_label, kind: fixup_Mips_26 + +# NO-PIC: jal external_label # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: external_label, kind: fixup_Mips_26 +# NO-PIC: .end local_label + +# BAD-ABI: .cprestore 8 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] + +# BAD-ABI: lw $25, %got_disp(.text)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: .text@GOT_DISP, kind: fixup_Mips_GOT_DISP +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] + +# BAD-ABI: lw $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_Mips_CALL16 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] + +# BAD-ABI: lw $25, %call16(external_label)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: external_label@GOT_CALL, kind: fixup_Mips_CALL16 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI: .end local_label Index: test/MC/Mips/cprestore-reorder.s =================================================================== --- /dev/null +++ test/MC/Mips/cprestore-reorder.s @@ -0,0 +1,132 @@ +# 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 -mattr=-n64,+n32 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI + +# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -mattr=+n64 -relocation-model=pic -show-encoding | \ +# RUN: FileCheck %s -check-prefix=BAD-ABI + + .text + .weak weak_label + + .ent local_label +local_label: + .frame $sp, 0, $ra + .set noreorder + .cpload $25 + .set reorder + + .cprestore 8 + + jal $25 + jal $4, $25 + + jal local_label + jal weak_label + jal external_label + + .end local_label + +# 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(.text)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: .text@GOT, kind: fixup_Mips_GOT_Local +# CHECK: addiu $25, $25, %lo(.text) # encoding: [0x27,0x39,A,A] +# CHECK: # fixup A - offset: 0, value: .text@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: lw $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_Mips_CALL16 +# 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: lw $25, %call16(external_label)($gp) # encoding: [0x8f,0x99,A,A] +# CHECK: # fixup A - offset: 0, value: external_label@GOT_CALL, kind: fixup_Mips_CALL16 +# 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 local_label + +# MICROMIPS: .cprestore 8 +# MICROMIPS: jalrs16 $25 # encoding: [0x45,0xf9] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: jalrs $4, $25 # encoding: [0x00,0x99,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %got(local_label)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: local_label@GOT, kind: fixup_MICROMIPS_GOT16 +# MICROMIPS: addiu $25, $25, %lo(local_label) # encoding: [0x33,0x39,A,A] +# MICROMIPS: # fixup A - offset: 0, value: local_label@ABS_LO, kind: fixup_MICROMIPS_LO16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %call16(weak_label)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] + +# MICROMIPS: lw $25, %call16(external_label)($gp) # encoding: [0xff,0x3c,A,A] +# MICROMIPS: # fixup A - offset: 0, value: external_label@GOT_CALL, kind: fixup_MICROMIPS_CALL16 +# MICROMIPS: jalrs $ra, $25 # encoding: [0x03,0xf9,0x4f,0x3c] +# MICROMIPS: move $zero, $zero # encoding: [0x0c,0x00] +# MICROMIPS: lw $gp, 8($sp) # encoding: [0xff,0x9d,0x00,0x08] +# MICROMIPS: .end local_label + +# NO-PIC: .cprestore 8 +# NO-PIC: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# NO-PIC: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] + +# NO-PIC: jal local_label # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: local_label, kind: fixup_Mips_26 + +# NO-PIC: jal weak_label # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: weak_label, kind: fixup_Mips_26 + +# NO-PIC: jal external_label # encoding: [0b000011AA,A,A,A] +# NO-PIC: # fixup A - offset: 0, value: external_label, kind: fixup_Mips_26 +# NO-PIC: .end local_label + +# BAD-ABI: .cprestore 8 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI: jalr $4, $25 # encoding: [0x03,0x20,0x20,0x09] + +# BAD-ABI: lw $25, %got_disp(.text)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: .text@GOT_DISP, kind: fixup_Mips_GOT_DISP +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] + +# BAD-ABI: lw $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: weak_label@GOT_CALL, kind: fixup_Mips_CALL16 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] + +# BAD-ABI: lw $25, %call16(external_label)($gp) # encoding: [0x8f,0x99,A,A] +# BAD-ABI: # fixup A - offset: 0, value: external_label@GOT_CALL, kind: fixup_Mips_CALL16 +# BAD-ABI: jalr $25 # encoding: [0x03,0x20,0xf8,0x09] +# BAD-ABI: .end local_label 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