Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -183,6 +183,10 @@ const MCOperand *SrcRegOp, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions); + bool loadSymbolAddress(const MCOperand *SymOp, const MCOperand *DstRegOp, + const MCOperand *SrcRegOp, bool Is32BitSym, + SMLoc IDLoc, SmallVectorImpl &Instructions); + bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl &Instructions); @@ -194,10 +198,6 @@ bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions); - void expandLoadAddressSym(const MCOperand *DstRegOp, const MCOperand *SymOp, - bool Is32BitSym, SMLoc IDLoc, - SmallVectorImpl &Instructions); - void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions, bool isLoad, bool isImmOpnd); @@ -1907,31 +1907,9 @@ assert((ImmOp->isImm() || ImmOp->isExpr()) && "expected immediate operand kind"); if (!ImmOp->isImm()) { - unsigned DstReg = DstRegOp->getReg(); - unsigned SrcReg = SrcRegOp->getReg(); - - bool UseAT = false; - unsigned ATReg = 0; - MCOperand ATRegOp; - if (DstReg == SrcReg) { - // At this point we need AT to perform the expansions and we exit if it is - // not available. - ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - ATRegOp = MCOperand::CreateReg(ATReg); - UseAT = true; - } - - expandLoadAddressSym(UseAT ? &ATRegOp : DstRegOp, ImmOp, Is32BitImm, IDLoc, - Instructions); - - MCInst TmpInst; - TmpInst.setOpcode(Mips::ADDu); - TmpInst.addOperand(MCOperand::CreateReg(DstReg)); - TmpInst.addOperand(MCOperand::CreateReg(UseAT ? ATReg : DstReg)); - TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); - Instructions.push_back(TmpInst); + if (loadSymbolAddress(ImmOp, DstRegOp, SrcRegOp, Is32BitImm, IDLoc, + Instructions)) + return true; return false; } @@ -1952,7 +1930,10 @@ assert((ImmOp->isImm() || ImmOp->isExpr()) && "expected immediate operand kind"); if (!ImmOp->isImm()) { - expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions); + if (loadSymbolAddress(ImmOp, DstRegOp, nullptr, Is32BitImm, IDLoc, + Instructions)) + return true; + return false; } @@ -1962,19 +1943,39 @@ return false; } -void MipsAsmParser::expandLoadAddressSym( - const MCOperand *DstRegOp, const MCOperand *SymOp, bool Is32BitSym, - SMLoc IDLoc, SmallVectorImpl &Instructions) { +bool MipsAsmParser::loadSymbolAddress(const MCOperand *SymOp, + const MCOperand *DstRegOp, + const MCOperand *SrcRegOp, + bool Is32BitSym, SMLoc IDLoc, + SmallVectorImpl &Instructions) { if (Is32BitSym && isGP64bit()) Warning(IDLoc, "instruction loads a 32-bit address on a 64-bit architecture"); + unsigned SrcReg = 0; + bool UseSrcReg = false; + if (SrcRegOp) { + SrcReg = SrcRegOp->getReg(); + UseSrcReg = true; + } + MCInst tmpInst; - unsigned RegNo = DstRegOp->getReg(); + unsigned DstReg = DstRegOp->getReg(); const MCExpr *HiExpr = evaluateRelocExpr(SymOp->getExpr(), "hi"); const MCExpr *LoExpr = evaluateRelocExpr(SymOp->getExpr(), "lo"); + bool UseAT = false; + unsigned ATReg = 0; + if (UseSrcReg && (DstReg == SrcReg)) { + UseAT = true; + // At this point we need AT to perform the expansions and we exit if it is + // not available. + ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + } + if (!Is32BitSym) { // If it's a 64-bit architecture, expand to: // la d,sym => lui d,highest(sym) @@ -1987,28 +1988,45 @@ const MCExpr *HigherExpr = evaluateRelocExpr(SymOp->getExpr(), "higher"); tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); + tmpInst.addOperand(MCOperand::CreateReg(UseAT ? ATReg : DstReg)); tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr)); Instructions.push_back(tmpInst); - createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(), - Instructions); - createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(), - Instructions); - createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(), - Instructions); + createLShiftOri<0>(MCOperand::CreateExpr(HigherExpr), + UseAT ? ATReg : DstReg, SMLoc(), Instructions); + createLShiftOri<16>(MCOperand::CreateExpr(HiExpr), UseAT ? ATReg : DstReg, + SMLoc(), Instructions); + createLShiftOri<16>(MCOperand::CreateExpr(LoExpr), UseAT ? ATReg : DstReg, + SMLoc(), Instructions); + if (UseSrcReg) { + tmpInst.clear(); + tmpInst.setOpcode(Mips::DADDu); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(UseAT ? ATReg : DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + Instructions.push_back(tmpInst); + } } 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::CreateReg(UseAT ? ATReg : DstReg)); tmpInst.addOperand(MCOperand::CreateExpr(HiExpr)); Instructions.push_back(tmpInst); - createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(), - Instructions); + createLShiftOri<0>(MCOperand::CreateExpr(LoExpr), UseAT ? ATReg : DstReg, + SMLoc(), Instructions); + if (UseSrcReg) { + tmpInst.clear(); + tmpInst.setOpcode(Mips::ADDu); + tmpInst.addOperand(MCOperand::CreateReg(DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(UseAT ? ATReg : DstReg)); + tmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + Instructions.push_back(tmpInst); + } } + return false; } bool MipsAsmParser::expandUncondBranchMMPseudo(