mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-21 21:41:43 +00:00
[mips] Implement 'la' macro in PIC mode for O32.
Summary: N32 support will follow in a later patch since the symbol version of 'la' incorrectly believes N32 to have 64-bit pointers and rejects it early. This fixes the three incorrectly expanded 'la' macros found in bionic. Reviewers: sdardis Subscribers: dsanders, llvm-commits, sdardis Differential Revision: http://reviews.llvm.org/D20820 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271644 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d86b0520ce
commit
5716739c7d
@ -2376,15 +2376,85 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
MCStreamer &Out,
|
||||
const MCSubtargetInfo *STI) {
|
||||
MipsTargetStreamer &TOut = getTargetStreamer();
|
||||
bool UseSrcReg = SrcReg != Mips::NoRegister;
|
||||
warnIfNoMacro(IDLoc);
|
||||
|
||||
const MCExpr *Symbol = cast<MCExpr>(SymExpr);
|
||||
const MipsMCExpr *HiExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
|
||||
const MipsMCExpr *LoExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());
|
||||
if (inPicMode() && ABI.IsO32()) {
|
||||
MCValue Res;
|
||||
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
|
||||
Error(IDLoc, "expected relocatable expression");
|
||||
return true;
|
||||
}
|
||||
if (Res.getSymB() != nullptr) {
|
||||
Error(IDLoc, "expected relocatable expression with only one symbol");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UseSrcReg = SrcReg != Mips::NoRegister;
|
||||
// The case where the result register is $25 is somewhat special. If the
|
||||
// symbol in the final relocation is external and not modified with a
|
||||
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
|
||||
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
|
||||
Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
|
||||
!Res.getSymA()->getSymbol().isTemporary()) {
|
||||
const MCExpr *CallExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
||||
TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
|
||||
MCOperand::createExpr(CallExpr), IDLoc, STI);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The remaining cases are:
|
||||
// External GOT: lw $tmp, %got(symbol+offset)($gp)
|
||||
// >addiu $tmp, $tmp, %lo(offset)
|
||||
// >addiu $rd, $tmp, $rs
|
||||
// Local GOT: lw $tmp, %got(symbol+offset)($gp)
|
||||
// addiu $tmp, $tmp, %lo(symbol+offset)($gp)
|
||||
// >addiu $rd, $tmp, $rs
|
||||
// The addiu's marked with a '>' may be omitted if they are redundant. If
|
||||
// this happens then the last instruction must use $rd as the result
|
||||
// register.
|
||||
const MipsMCExpr *GotExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
||||
const MCExpr *LoExpr = nullptr;
|
||||
if (Res.getSymA()->getSymbol().isInSection() ||
|
||||
Res.getSymA()->getSymbol().isTemporary())
|
||||
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
||||
else if (Res.getConstant() != 0) {
|
||||
// External symbols fully resolve the symbol with just the %got(symbol)
|
||||
// but we must still account for any offset to the symbol for expressions
|
||||
// like symbol+8.
|
||||
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
||||
}
|
||||
|
||||
unsigned TmpReg = DstReg;
|
||||
if (UseSrcReg &&
|
||||
getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
|
||||
SrcReg)) {
|
||||
// If $rs is the same as $rd, we need to use AT.
|
||||
// If it is not available we exit.
|
||||
unsigned ATReg = getATReg(IDLoc);
|
||||
if (!ATReg)
|
||||
return true;
|
||||
TmpReg = ATReg;
|
||||
}
|
||||
|
||||
TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
|
||||
MCOperand::createExpr(GotExpr), IDLoc, STI);
|
||||
|
||||
if (LoExpr)
|
||||
TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
||||
IDLoc, STI);
|
||||
|
||||
if (UseSrcReg)
|
||||
TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const MipsMCExpr *HiExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
|
||||
const MipsMCExpr *LoExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
||||
|
||||
// This is the 64-bit symbol address expansion.
|
||||
if (ABI.ArePtrs64bit() && isGP64bit()) {
|
||||
@ -2395,9 +2465,9 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
return true;
|
||||
|
||||
const MipsMCExpr *HighestExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
|
||||
const MipsMCExpr *HigherExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
|
||||
|
||||
if (UseSrcReg &&
|
||||
getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
|
||||
|
@ -122,33 +122,6 @@ void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
}
|
||||
}
|
||||
|
||||
static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
|
||||
raw_ostream &OS) {
|
||||
int Offset = 0;
|
||||
const MCSymbolRefExpr *SRE;
|
||||
|
||||
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
|
||||
SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
|
||||
assert(SRE && CE && "Binary expression must be sym+const.");
|
||||
Offset = CE->getValue();
|
||||
} else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) {
|
||||
ME->print(OS, MAI);
|
||||
return;
|
||||
} else
|
||||
SRE = cast<MCSymbolRefExpr>(Expr);
|
||||
|
||||
assert(SRE->getKind() == MCSymbolRefExpr::VK_None && "Invalid kind!");
|
||||
|
||||
SRE->getSymbol().print(OS, MAI);
|
||||
|
||||
if (Offset) {
|
||||
if (Offset > 0)
|
||||
OS << '+';
|
||||
OS << Offset;
|
||||
}
|
||||
}
|
||||
|
||||
void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
@ -163,7 +136,7 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
}
|
||||
|
||||
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
||||
printExpr(Op.getExpr(), &MAI, O);
|
||||
Op.getExpr()->print(O, &MAI, true);
|
||||
}
|
||||
|
||||
template <unsigned Bits, unsigned Offset>
|
||||
|
@ -102,6 +102,10 @@ unsigned MipsABIInfo::GetBasePtr() const {
|
||||
return ArePtrs64bit() ? Mips::S7_64 : Mips::S7;
|
||||
}
|
||||
|
||||
unsigned MipsABIInfo::GetGlobalPtr() const {
|
||||
return ArePtrs64bit() ? Mips::GP_64 : Mips::GP;
|
||||
}
|
||||
|
||||
unsigned MipsABIInfo::GetNullPtr() const {
|
||||
return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO;
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
unsigned GetStackPtr() const;
|
||||
unsigned GetFramePtr() const;
|
||||
unsigned GetBasePtr() const;
|
||||
unsigned GetGlobalPtr() const;
|
||||
unsigned GetNullPtr() const;
|
||||
unsigned GetZeroReg() const;
|
||||
unsigned GetPtrAdduOp() const;
|
||||
|
@ -23,7 +23,7 @@ entry:
|
||||
; ALL: .set reorder
|
||||
; ALL: .reloc 0, R_MIPS_NONE, v_sf
|
||||
; GAS: la $25, $__fn_local_v_sf
|
||||
; IAS: lui $25, %hi($$__fn_local_v_sf)
|
||||
; IAS: lw $25, %got($$__fn_local_v_sf)($gp)
|
||||
; IAS: addiu $25, $25, %lo($$__fn_local_v_sf)
|
||||
; ALL: mfc1 $4, $f12
|
||||
; ALL: jr $25
|
||||
|
54
test/MC/Mips/macro-la-pic.s
Normal file
54
test/MC/Mips/macro-la-pic.s
Normal file
@ -0,0 +1,54 @@
|
||||
# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r2 | \
|
||||
# RUN: FileCheck %s
|
||||
# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding -mcpu=mips32r6 | \
|
||||
# RUN: FileCheck %s
|
||||
# N32 should be acceptable too but it currently errors out.
|
||||
# N64 should be acceptable too but we cannot convert la to dla yet.
|
||||
|
||||
.option pic2
|
||||
la $5, symbol # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x85,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||
la $5, symbol($6) # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x85,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||
# CHECK: addu $5, $5, $6 # encoding: [0x00,0xa6,0x28,0x21]
|
||||
la $6, symbol($6) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||
# CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21]
|
||||
la $5, symbol+8 # CHECK: lw $5, %got(symbol+8)($gp) # encoding: [0x8f,0x85,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
||||
la $5, symbol+8($6) # CHECK: lw $5, %got(symbol+8)($gp) # encoding: [0x8f,0x85,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
||||
# CHECK: addu $5, $5, $6 # encoding: [0x00,0xa6,0x28,0x21]
|
||||
la $6, symbol+8($6) # CHECK: lw $1, %got(symbol+8)($gp) # encoding: [0x8f,0x81,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
||||
# CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08]
|
||||
# CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21]
|
||||
la $5, 1f # CHECK: lw $5, %got($tmp0)($gp) # encoding: [0x8f,0x85,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got($tmp0), kind: fixup_Mips_GOT
|
||||
# CHECK: addiu $5, $5, %lo($tmp0) # encoding: [0x24,0xa5,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
|
||||
1:
|
||||
|
||||
# PIC expansions involving $25 are special.
|
||||
la $25, symbol # CHECK: lw $25, %call16(symbol)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %call16(symbol), kind: fixup_Mips_CALL16
|
||||
la $25, symbol($6) # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||
# CHECK: addu $25, $25, $6 # encoding: [0x03,0x26,0xc8,0x21]
|
||||
la $25, symbol($25) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||
# CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21]
|
||||
la $25, symbol+8 # CHECK: lw $25, %got(symbol+8)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
||||
la $25, symbol+8($6) # CHECK: lw $25, %got(symbol+8)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
||||
# CHECK: addu $25, $25, $6 # encoding: [0x03,0x26,0xc8,0x21]
|
||||
la $25, symbol+8($25) # CHECK: lw $1, %got(symbol+8)($gp) # encoding: [0x8f,0x81,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
||||
# CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08]
|
||||
# CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21]
|
||||
la $25, 1f # CHECK: lw $25, %got($tmp1)($gp) # encoding: [0x8f,0x99,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %got($tmp1), kind: fixup_Mips_GOT
|
||||
# CHECK: addiu $25, $25, %lo($tmp1) # encoding: [0x27,0x39,A,A]
|
||||
# CHECK: # fixup A - offset: 0, value: %lo($tmp1), kind: fixup_Mips_LO16
|
||||
1:
|
Loading…
x
Reference in New Issue
Block a user