summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorToma Tabacu <toma.tabacu@imgtec.com>2014-08-14 10:29:17 +0000
committerToma Tabacu <toma.tabacu@imgtec.com>2014-08-14 10:29:17 +0000
commit0d64b20c037dfc09debb4f6fb753d122f46a6dd6 (patch)
tree98dbd9e8f8cfa22f9dfe6c520cf7176f14353ccc /llvm/lib
parentab751a8f71d7dc4a463aa0bd837c59513697ed06 (diff)
downloadbcm5719-llvm-0d64b20c037dfc09debb4f6fb753d122f46a6dd6.tar.gz
bcm5719-llvm-0d64b20c037dfc09debb4f6fb753d122f46a6dd6.zip
[mips] Add assembler support for the "la $reg,symbol" pseudo-instruction.
Summary: This pseudo-instruction allows the programmer to load an address from a symbolic expression into a register. Patch by David Chisnall. His work was sponsored by: DARPA, AFRL I've made some minor changes to the original, such as improving the formatting and adding some comments, and I've also added a test case. Reviewers: dsanders Reviewed By: dsanders Differential Revision: http://reviews.llvm.org/D4808 llvm-svn: 215630
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp97
1 files changed, 91 insertions, 6 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index c0d830eaad5..0fabbe2e720 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -148,6 +148,9 @@ class MipsAsmParser : public MCTargetAsmParser {
bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
+ void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
+
void expandMemInst(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions, bool isLoad,
bool isImmOpnd);
@@ -1103,8 +1106,8 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
}
namespace {
-template <int Shift, bool PerformShift>
-void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
+template <bool PerformShift>
+void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
MCInst tmpInst;
if (PerformShift) {
@@ -1119,11 +1122,18 @@ void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
tmpInst.setOpcode(Mips::ORi);
tmpInst.addOperand(MCOperand::CreateReg(RegNo));
tmpInst.addOperand(MCOperand::CreateReg(RegNo));
- tmpInst.addOperand(
- MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
+ tmpInst.addOperand(Operand);
tmpInst.setLoc(IDLoc);
Instructions.push_back(tmpInst);
}
+
+template <int Shift, bool PerformShift>
+void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ createShiftOr<PerformShift>(
+ MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
+ IDLoc, Instructions);
+}
}
bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
@@ -1228,7 +1238,12 @@ MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
MCInst tmpInst;
const MCOperand &ImmOp = Inst.getOperand(2);
- assert(ImmOp.isImm() && "expected immediate operand kind");
+ assert((ImmOp.isImm() || ImmOp.isExpr()) &&
+ "expected immediate operand kind");
+ if (!ImmOp.isImm()) {
+ expandLoadAddressSym(Inst, IDLoc, Instructions);
+ return false;
+ }
const MCOperand &SrcRegOp = Inst.getOperand(1);
assert(SrcRegOp.isReg() && "expected register operand kind");
const MCOperand &DstRegOp = Inst.getOperand(0);
@@ -1272,7 +1287,12 @@ MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
MCInst tmpInst;
const MCOperand &ImmOp = Inst.getOperand(1);
- assert(ImmOp.isImm() && "expected immediate operand kind");
+ assert((ImmOp.isImm() || ImmOp.isExpr()) &&
+ "expected immediate operand kind");
+ if (!ImmOp.isImm()) {
+ expandLoadAddressSym(Inst, IDLoc, Instructions);
+ return false;
+ }
const MCOperand &RegOp = Inst.getOperand(0);
assert(RegOp.isReg() && "expected register operand kind");
int ImmValue = ImmOp.getImm();
@@ -1302,6 +1322,71 @@ MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
return false;
}
+void
+MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ // FIXME: If we do have a valid at register to use, we should generate a
+ // slightly shorter sequence here.
+ MCInst tmpInst;
+ int ExprOperandNo = 1;
+ // Sometimes the assembly parser will get the immediate expression as
+ // a $zero + an immediate.
+ if (Inst.getNumOperands() == 3) {
+ assert(Inst.getOperand(1).getReg() ==
+ (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
+ ExprOperandNo = 2;
+ }
+ const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
+ assert(SymOp.isExpr() && "expected symbol operand kind");
+ const MCOperand &RegOp = Inst.getOperand(0);
+ unsigned RegNo = RegOp.getReg();
+ const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
+ const MCSymbolRefExpr *HiExpr =
+ MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
+ MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
+ const MCSymbolRefExpr *LoExpr =
+ MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
+ MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
+ if (isGP64bit()) {
+ // If it's a 64-bit architecture, expand to:
+ // la d,sym => lui d,highest(sym)
+ // ori d,d,higher(sym)
+ // dsll d,d,16
+ // ori d,d,hi16(sym)
+ // dsll d,d,16
+ // ori d,d,lo16(sym)
+ const MCSymbolRefExpr *HighestExpr =
+ MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
+ MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
+ const MCSymbolRefExpr *HigherExpr =
+ MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
+ MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
+
+ tmpInst.setOpcode(Mips::LUi);
+ tmpInst.addOperand(MCOperand::CreateReg(RegNo));
+ tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
+ Instructions.push_back(tmpInst);
+
+ createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
+ Instructions);
+ createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
+ Instructions);
+ createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
+ Instructions);
+ } else {
+ // Otherwise, expand to:
+ // la d,sym => lui d,hi16(sym)
+ // ori d,d,lo16(sym)
+ tmpInst.setOpcode(Mips::LUi);
+ tmpInst.addOperand(MCOperand::CreateReg(RegNo));
+ tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
+ Instructions.push_back(tmpInst);
+
+ createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
+ Instructions);
+ }
+}
+
void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions,
bool isLoad, bool isImmOpnd) {
OpenPOWER on IntegriCloud