mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[mips] Reduce code duplication in the loadAndAddSymbolAddress
. NFC
llvm-svn: 372218
This commit is contained in:
parent
5b325c0c9d
commit
fa04b58fc7
@ -2877,7 +2877,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
SrcReg != Mips::ZERO_64;
|
SrcReg != Mips::ZERO_64;
|
||||||
warnIfNoMacro(IDLoc);
|
warnIfNoMacro(IDLoc);
|
||||||
|
|
||||||
if (inPicMode() && ABI.IsO32()) {
|
if (inPicMode()) {
|
||||||
MCValue Res;
|
MCValue Res;
|
||||||
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
|
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
|
||||||
Error(IDLoc, "expected relocatable expression");
|
Error(IDLoc, "expected relocatable expression");
|
||||||
@ -2888,6 +2888,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPtr64 = ABI.ArePtrs64bit();
|
||||||
bool IsLocalSym =
|
bool IsLocalSym =
|
||||||
Res.getSymA()->getSymbol().isInSection() ||
|
Res.getSymA()->getSymbol().isInSection() ||
|
||||||
Res.getSymA()->getSymbol().isTemporary() ||
|
Res.getSymA()->getSymbol().isTemporary() ||
|
||||||
@ -2897,117 +2898,66 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
|
|
||||||
// The case where the result register is $25 is somewhat special. If the
|
// 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
|
// 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.
|
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
|
||||||
|
// or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
|
||||||
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
|
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
|
||||||
Res.getConstant() == 0 && !IsLocalSym) {
|
Res.getConstant() == 0 && !IsLocalSym) {
|
||||||
const MCExpr *CallExpr =
|
const MCExpr *CallExpr =
|
||||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
||||||
TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
|
||||||
IDLoc, STI);
|
MCOperand::createExpr(CallExpr), IDLoc, STI);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The remaining cases are:
|
|
||||||
// External GOT: lw $tmp, %got(symbol)($gp)
|
|
||||||
// >addiu $tmp, $tmp, 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 = nullptr;
|
const MipsMCExpr *GotExpr = nullptr;
|
||||||
const MCExpr *LoExpr = nullptr;
|
const MCExpr *LoExpr = nullptr;
|
||||||
if (IsLocalSym) {
|
if (IsPtr64) {
|
||||||
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
// The remaining cases are:
|
||||||
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
// Small offset: ld $tmp, %got_disp(symbol)($gp)
|
||||||
} else {
|
// >daddiu $tmp, $tmp, offset
|
||||||
// External symbols fully resolve the symbol with just the %got(symbol)
|
// >daddu $rd, $tmp, $rs
|
||||||
// but we must still account for any offset to the symbol for expressions
|
// The daddiu's marked with a '>' may be omitted if they are redundant. If
|
||||||
// like symbol+8.
|
// this happens then the last instruction must use $rd as the result
|
||||||
GotExpr =
|
// register.
|
||||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(), getContext());
|
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),
|
||||||
if (Res.getConstant() != 0)
|
getContext());
|
||||||
|
if (Res.getConstant() != 0) {
|
||||||
|
// Symbols fully resolve with just the %got_disp(symbol) but we
|
||||||
|
// must still account for any offset to the symbol for
|
||||||
|
// expressions like symbol+8.
|
||||||
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
||||||
}
|
|
||||||
|
|
||||||
unsigned TmpReg = DstReg;
|
// FIXME: Offsets greater than 16 bits are not yet implemented.
|
||||||
if (UseSrcReg &&
|
// FIXME: The correct range is a 32-bit sign-extended number.
|
||||||
getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
|
if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
|
||||||
SrcReg)) {
|
Error(IDLoc, "macro instruction uses large offset, which is not "
|
||||||
// If $rs is the same as $rd, we need to use AT.
|
"currently supported");
|
||||||
// If it is not available we exit.
|
return true;
|
||||||
unsigned ATReg = getATReg(IDLoc);
|
}
|
||||||
if (!ATReg)
|
}
|
||||||
return true;
|
} else {
|
||||||
TmpReg = ATReg;
|
// The remaining cases are:
|
||||||
}
|
// External GOT: lw $tmp, %got(symbol)($gp)
|
||||||
|
// >addiu $tmp, $tmp, offset
|
||||||
TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
|
// >addiu $rd, $tmp, $rs
|
||||||
STI);
|
// Local GOT: lw $tmp, %got(symbol+offset)($gp)
|
||||||
|
// addiu $tmp, $tmp, %lo(symbol+offset)($gp)
|
||||||
if (LoExpr)
|
// >addiu $rd, $tmp, $rs
|
||||||
TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
// The addiu's marked with a '>' may be omitted if they are redundant. If
|
||||||
IDLoc, STI);
|
// this happens then the last instruction must use $rd as the result
|
||||||
|
// register.
|
||||||
if (UseSrcReg)
|
if (IsLocalSym) {
|
||||||
TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
|
GotExpr =
|
||||||
|
MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
||||||
return false;
|
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
||||||
}
|
} else {
|
||||||
|
// External symbols fully resolve the symbol with just the %got(symbol)
|
||||||
if (inPicMode() && ABI.ArePtrs64bit()) {
|
// but we must still account for any offset to the symbol for
|
||||||
MCValue Res;
|
// expressions like symbol+8.
|
||||||
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
|
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),
|
||||||
Error(IDLoc, "expected relocatable expression");
|
getContext());
|
||||||
return true;
|
if (Res.getConstant() != 0)
|
||||||
}
|
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
||||||
if (Res.getSymB() != nullptr) {
|
|
||||||
Error(IDLoc, "expected relocatable expression with only one symbol");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_GOT_DISP.
|
|
||||||
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
|
|
||||||
Res.getConstant() == 0 &&
|
|
||||||
!(Res.getSymA()->getSymbol().isInSection() ||
|
|
||||||
Res.getSymA()->getSymbol().isTemporary() ||
|
|
||||||
(Res.getSymA()->getSymbol().isELF() &&
|
|
||||||
cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
|
|
||||||
ELF::STB_LOCAL))) {
|
|
||||||
const MCExpr *CallExpr =
|
|
||||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
|
||||||
TOut.emitRRX(Mips::LD, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
|
||||||
IDLoc, STI);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The remaining cases are:
|
|
||||||
// Small offset: ld $tmp, %got_disp(symbol)($gp)
|
|
||||||
// >daddiu $tmp, $tmp, offset
|
|
||||||
// >daddu $rd, $tmp, $rs
|
|
||||||
// The daddiu'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_DISP,
|
|
||||||
Res.getSymA(),
|
|
||||||
getContext());
|
|
||||||
const MCExpr *LoExpr = nullptr;
|
|
||||||
if (Res.getConstant() != 0) {
|
|
||||||
// Symbols fully resolve with just the %got_disp(symbol) but we
|
|
||||||
// must still account for any offset to the symbol for
|
|
||||||
// expressions like symbol+8.
|
|
||||||
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
|
||||||
|
|
||||||
// FIXME: Offsets greater than 16 bits are not yet implemented.
|
|
||||||
// FIXME: The correct range is a 32-bit sign-extended number.
|
|
||||||
if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
|
|
||||||
Error(IDLoc, "macro instruction uses large offset, which is not "
|
|
||||||
"currently supported");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3023,15 +2973,16 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
TmpReg = ATReg;
|
TmpReg = ATReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
|
TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
|
||||||
STI);
|
MCOperand::createExpr(GotExpr), IDLoc, STI);
|
||||||
|
|
||||||
if (LoExpr)
|
if (LoExpr)
|
||||||
TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
|
||||||
IDLoc, STI);
|
MCOperand::createExpr(LoExpr), IDLoc, STI);
|
||||||
|
|
||||||
if (UseSrcReg)
|
if (UseSrcReg)
|
||||||
TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
|
TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
|
||||||
|
IDLoc, STI);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user