mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-01 07:09:02 +00:00
[mips][ias] Fix O32 .cprestore directive when inside .set noat region and offset is in range.
Summary: This expands on r269179 to fix an additional case that was not covered by our tests. The assembler temporary is not needed when the .cprestore offset fits inside a simm16 and it is not an error to use it inside a '.set noat' in this case. Reviewers: emaste, seanbruno, sdardis Subscribers: dsanders, sdardis, llvm-commits Differential Revision: http://reviews.llvm.org/D20199 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269295 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d89f32c83d
commit
100018952c
lib/Target/Mips
test/MC/Mips
@ -2633,16 +2633,17 @@ void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
|
||||
unsigned SrcReg = Inst.getOperand(0).getReg();
|
||||
unsigned BaseReg = Inst.getOperand(1).getReg();
|
||||
|
||||
if (IsImmOpnd) {
|
||||
TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
|
||||
Inst.getOperand(2).getImm(),
|
||||
[&]() { return getATReg(IDLoc); }, IDLoc, STI);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ATReg = getATReg(IDLoc);
|
||||
if (!ATReg)
|
||||
return;
|
||||
|
||||
if (IsImmOpnd) {
|
||||
TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
|
||||
Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
|
||||
return;
|
||||
}
|
||||
|
||||
const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
|
||||
MCOperand LoOperand = MCOperand::createExpr(
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
|
||||
@ -3626,12 +3627,8 @@ void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset,
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ATReg = getATReg(IDLoc);
|
||||
if (!ATReg)
|
||||
return;
|
||||
|
||||
TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset, ATReg,
|
||||
IDLoc, STI);
|
||||
TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset,
|
||||
[&]() { return getATReg(IDLoc); }, IDLoc, STI);
|
||||
}
|
||||
|
||||
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
|
||||
|
@ -228,7 +228,8 @@ void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
|
||||
/// Emit a store instruction with an immediate offset.
|
||||
void MipsTargetStreamer::emitStoreWithImmOffset(
|
||||
unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
|
||||
unsigned ATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) {
|
||||
std::function<unsigned()> GetATReg, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI) {
|
||||
if (isInt<16>(Offset)) {
|
||||
emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
|
||||
return;
|
||||
@ -238,6 +239,10 @@ void MipsTargetStreamer::emitStoreWithImmOffset(
|
||||
// add $at, $at, $8
|
||||
// sw $8, %lo(offset)($at)
|
||||
|
||||
unsigned ATReg = GetATReg();
|
||||
if (!ATReg)
|
||||
return;
|
||||
|
||||
unsigned LoOffset = Offset & 0x0000ffff;
|
||||
unsigned HiOffset = (Offset & 0xffff0000) >> 16;
|
||||
|
||||
@ -1055,12 +1060,8 @@ bool MipsTargetELFStreamer::emitDirectiveCpRestore(
|
||||
if (!Pic || (getABI().IsN32() || getABI().IsN64()))
|
||||
return true;
|
||||
|
||||
unsigned ATReg = GetATReg();
|
||||
if (!ATReg)
|
||||
return false;
|
||||
|
||||
// Store the $gp on the stack.
|
||||
emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, ATReg, IDLoc,
|
||||
emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc,
|
||||
STI);
|
||||
return true;
|
||||
}
|
||||
|
@ -122,9 +122,18 @@ public:
|
||||
void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI);
|
||||
void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI);
|
||||
|
||||
/// Emit a store instruction with an offset. If the offset is out of range
|
||||
/// then it will be synthesized using the assembler temporary.
|
||||
///
|
||||
/// GetATReg() is a callback that can be used to obtain the current assembler
|
||||
/// temporary and is only called when the assembler temporary is required. It
|
||||
/// must handle the case where no assembler temporary is available (typically
|
||||
/// by reporting an error).
|
||||
void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg,
|
||||
unsigned BaseReg, int64_t Offset, unsigned ATReg,
|
||||
SMLoc IDLoc, const MCSubtargetInfo *STI);
|
||||
unsigned BaseReg, int64_t Offset,
|
||||
std::function<unsigned()> GetATReg, SMLoc IDLoc,
|
||||
const MCSubtargetInfo *STI);
|
||||
void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg,
|
||||
unsigned BaseReg, MCOperand &HiOperand,
|
||||
MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
|
||||
@ -237,6 +246,14 @@ public:
|
||||
|
||||
// PIC support
|
||||
void emitDirectiveCpLoad(unsigned RegNo) override;
|
||||
|
||||
/// Emit a .cprestore directive. If the offset is out of range then it will
|
||||
/// be synthesized using the assembler temporary.
|
||||
///
|
||||
/// GetATReg() is a callback that can be used to obtain the current assembler
|
||||
/// temporary and is only called when the assembler temporary is required. It
|
||||
/// must handle the case where no assembler temporary is available (typically
|
||||
/// by reporting an error).
|
||||
bool emitDirectiveCpRestore(int Offset, std::function<unsigned()> GetATReg,
|
||||
SMLoc IDLoc, const MCSubtargetInfo *STI) override;
|
||||
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
|
||||
|
@ -24,7 +24,7 @@ foo:
|
||||
|
||||
.cpload $25
|
||||
.cprestore 8
|
||||
# O32: :[[@LINE-1]]:3: error: pseudo-instruction requires $at, which is not available
|
||||
# O32-NOT: error: pseudo-instruction requires $at, which is not available
|
||||
# N32-NOT: error: pseudo-instruction requires $at, which is not available
|
||||
# N64-NOT: error: pseudo-instruction requires $at, which is not available
|
||||
# NO-STORE-NOT: sw $gp, 8($sp)
|
||||
@ -34,3 +34,22 @@ foo:
|
||||
jal foo
|
||||
|
||||
.end foo
|
||||
|
||||
.ent bar
|
||||
bar:
|
||||
.frame $sp, 0, $ra
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
.cpload $25
|
||||
.cprestore 65536
|
||||
# O32: :[[@LINE-1]]:3: error: pseudo-instruction requires $at, which is not available
|
||||
# N32-NOT: error: pseudo-instruction requires $at, which is not available
|
||||
# N64-NOT: error: pseudo-instruction requires $at, which is not available
|
||||
# NO-STORE-NOT: sw $gp,
|
||||
|
||||
jal $25
|
||||
jal $4, $25
|
||||
jal bar
|
||||
|
||||
.end bar
|
||||
|
Loading…
x
Reference in New Issue
Block a user