diff options
| author | Toma Tabacu <toma.tabacu@imgtec.com> | 2014-08-14 10:29:17 +0000 |
|---|---|---|
| committer | Toma Tabacu <toma.tabacu@imgtec.com> | 2014-08-14 10:29:17 +0000 |
| commit | 0d64b20c037dfc09debb4f6fb753d122f46a6dd6 (patch) | |
| tree | 98dbd9e8f8cfa22f9dfe6c520cf7176f14353ccc /llvm/lib | |
| parent | ab751a8f71d7dc4a463aa0bd837c59513697ed06 (diff) | |
| download | bcm5719-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.cpp | 97 |
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) { |

