diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 103 |
1 files changed, 82 insertions, 21 deletions
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 56fdf19a0720..a33f44542eb5 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -105,10 +105,9 @@ class PPCAsmParser : public MCTargetAsmParser { bool MatchRegisterName(MCRegister &RegNo, int64_t &IntVal); - bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) override; - OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) override; + bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; + ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, + SMLoc &EndLoc) override; const MCExpr *ExtractModifierFromExpr(const MCExpr *E, PPCMCExpr::VariantKind &Variant); @@ -887,6 +886,26 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, Inst = TmpInst; break; } + case PPC::PLA8: + case PPC::PLA: { + MCInst TmpInst; + TmpInst.setOpcode(Opcode == PPC::PLA ? PPC::PADDI : PPC::PADDI8); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(Inst.getOperand(1)); + TmpInst.addOperand(Inst.getOperand(2)); + Inst = TmpInst; + break; + } + case PPC::PLA8pc: + case PPC::PLApc: { + MCInst TmpInst; + TmpInst.setOpcode(Opcode == PPC::PLApc ? PPC::PADDIpc : PPC::PADDI8pc); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(MCOperand::createImm(0)); + TmpInst.addOperand(Inst.getOperand(1)); + Inst = TmpInst; + break; + } case PPC::SUBI: { MCInst TmpInst; TmpInst.setOpcode(PPC::ADDI); @@ -896,6 +915,15 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, Inst = TmpInst; break; } + case PPC::PSUBI: { + MCInst TmpInst; + TmpInst.setOpcode(PPC::PADDI); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(Inst.getOperand(1)); + addNegOperand(TmpInst, Inst.getOperand(2), getContext()); + Inst = TmpInst; + break; + } case PPC::SUBIS: { MCInst TmpInst; TmpInst.setOpcode(PPC::ADDIS); @@ -1320,24 +1348,23 @@ bool PPCAsmParser::MatchRegisterName(MCRegister &RegNo, int64_t &IntVal) { return false; } -bool PPCAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc, +bool PPCAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) { - if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) + if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess()) return TokError("invalid register name"); return false; } -OperandMatchResultTy PPCAsmParser::tryParseRegister(MCRegister &RegNo, - SMLoc &StartLoc, - SMLoc &EndLoc) { +ParseStatus PPCAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, + SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); StartLoc = Tok.getLoc(); EndLoc = Tok.getEndLoc(); - RegNo = 0; + Reg = PPC::NoRegister; int64_t IntVal; - if (MatchRegisterName(RegNo, IntVal)) - return MatchOperand_NoMatch; - return MatchOperand_Success; + if (MatchRegisterName(Reg, IntVal)) + return ParseStatus::NoMatch; + return ParseStatus::Success; } /// Extract \code @l/@ha \endcode modifier from expression. Recursively scan @@ -1544,24 +1571,58 @@ bool PPCAsmParser::ParseOperand(OperandVector &Operands) { Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64())); // Check whether this is a TLS call expression - bool TLSCall = false; - if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(EVal)) - TLSCall = Ref->getSymbol().getName() == "__tls_get_addr"; + const char TlsGetAddr[] = "__tls_get_addr"; + bool TlsCall = false; + const MCExpr *TlsCallAddend = nullptr; + if (auto *Ref = dyn_cast<MCSymbolRefExpr>(EVal)) { + TlsCall = Ref->getSymbol().getName() == TlsGetAddr; + } else if (auto *Bin = dyn_cast<MCBinaryExpr>(EVal); + Bin && Bin->getOpcode() == MCBinaryExpr::Add) { + if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Bin->getLHS())) { + TlsCall = Ref->getSymbol().getName() == TlsGetAddr; + TlsCallAddend = Bin->getRHS(); + } + } - if (TLSCall && parseOptionalToken(AsmToken::LParen)) { + if (TlsCall && parseOptionalToken(AsmToken::LParen)) { const MCExpr *TLSSym; - S = Parser.getTok().getLoc(); + const SMLoc S2 = Parser.getTok().getLoc(); if (ParseExpression(TLSSym)) - return Error(S, "invalid TLS call expression"); + return Error(S2, "invalid TLS call expression"); + E = Parser.getTok().getLoc(); if (parseToken(AsmToken::RParen, "expected ')'")) return true; - E = Parser.getTok().getLoc(); + // PPC32 allows bl __tls_get_addr[+a](x@tlsgd)@plt+b. Parse "@plt[+b]". + if (!isPPC64() && parseOptionalToken(AsmToken::At)) { + AsmToken Tok = getTok(); + if (!(parseOptionalToken(AsmToken::Identifier) && + Tok.getString().compare_insensitive("plt") == 0)) + return Error(Tok.getLoc(), "expected 'plt'"); + EVal = MCSymbolRefExpr::create(TlsGetAddr, MCSymbolRefExpr::VK_PLT, + getContext()); + if (parseOptionalToken(AsmToken::Plus)) { + const MCExpr *Addend = nullptr; + SMLoc EndLoc; + if (parsePrimaryExpr(Addend, EndLoc)) + return true; + if (TlsCallAddend) // __tls_get_addr+a(x@tlsgd)@plt+b + TlsCallAddend = + MCBinaryExpr::createAdd(TlsCallAddend, Addend, getContext()); + else // __tls_get_addr(x@tlsgd)@plt+b + TlsCallAddend = Addend; + } + if (TlsCallAddend) + EVal = MCBinaryExpr::createAdd(EVal, TlsCallAddend, getContext()); + // Add a __tls_get_addr operand with addend a, b, or a+b. + Operands.back() = PPCOperand::CreateFromMCExpr( + EVal, S, Parser.getTok().getLoc(), false); + } Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64())); } // Otherwise, check for D-form memory operands - if (!TLSCall && parseOptionalToken(AsmToken::LParen)) { + if (!TlsCall && parseOptionalToken(AsmToken::LParen)) { S = Parser.getTok().getLoc(); int64_t IntVal; |
