diff options
author | Joerg Sonnenberger <joerg@bec.de> | 2014-08-10 12:41:50 +0000 |
---|---|---|
committer | Joerg Sonnenberger <joerg@bec.de> | 2014-08-10 12:41:50 +0000 |
commit | bfef1dd694d4c646f79521fa3258bbb2398a990c (patch) | |
tree | c6469f3e8f44682535a91575bc38220e790b800e /llvm/lib/Target/PowerPC | |
parent | 16055e77b922695e2141b810a38508bc1aa00e0a (diff) | |
download | bcm5719-llvm-bfef1dd694d4c646f79521fa3258bbb2398a990c.tar.gz bcm5719-llvm-bfef1dd694d4c646f79521fa3258bbb2398a990c.zip |
@l and friends adjust their value depending the context used in.
For ori, they are unsigned, for addi, signed. Create a new target
expression type to handle this and evaluate Fixups accordingly.
llvm-svn: 215315
Diffstat (limited to 'llvm/lib/Target/PowerPC')
-rw-r--r-- | llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 98 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp | 68 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.td | 8 |
4 files changed, 142 insertions, 36 deletions
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index d1664febd39..98bec19b53d 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -297,6 +297,7 @@ struct PPCOperand : public MCParsedAsmOperand { enum KindTy { Token, Immediate, + ContextImmediate, Expression, TLSRegister } Kind; @@ -341,6 +342,7 @@ public: Tok = o.Tok; break; case Immediate: + case ContextImmediate: Imm = o.Imm; break; case Expression: @@ -365,6 +367,16 @@ public: assert(Kind == Immediate && "Invalid access!"); return Imm.Val; } + int64_t getImmS16Context() const { + assert((Kind == Immediate || Kind == ContextImmediate) && "Invalid access!"); + if (Kind == Immediate) + return Imm.Val; + return static_cast<int16_t>(Imm.Val); + } + int64_t getImmU16Context() const { + assert((Kind == Immediate || Kind == ContextImmediate) && "Invalid access!"); + return Imm.Val; + } const MCExpr *getExpr() const { assert(Kind == Expression && "Invalid access!"); @@ -422,15 +434,42 @@ public: bool isU8ImmX8() const { return Kind == Immediate && isUInt<8>(getImm()) && (getImm() & 7) == 0; } - bool isU16Imm() const { return Kind == Expression || - (Kind == Immediate && isUInt<16>(getImm())); } - bool isS16Imm() const { return Kind == Expression || - (Kind == Immediate && isInt<16>(getImm())); } + bool isU16Imm() const { + switch (Kind) { + case Expression: + return true; + case Immediate: + case ContextImmediate: + return isUInt<16>(getImmU16Context()); + default: + return false; + } + } + bool isS16Imm() const { + switch (Kind) { + case Expression: + return true; + case Immediate: + case ContextImmediate: + return isInt<16>(getImmS16Context()); + default: + return false; + } + } bool isS16ImmX4() const { return Kind == Expression || (Kind == Immediate && isInt<16>(getImm()) && (getImm() & 3) == 0); } - bool isS17Imm() const { return Kind == Expression || - (Kind == Immediate && isInt<17>(getImm())); } + bool isS17Imm() const { + switch (Kind) { + case Expression: + return true; + case Immediate: + case ContextImmediate: + return isInt<17>(getImmS16Context()); + default: + return false; + } + } bool isTLSReg() const { return Kind == TLSRegister; } bool isDirectBr() const { if (Kind == Expression) @@ -553,6 +592,36 @@ public: Inst.addOperand(MCOperand::CreateExpr(getExpr())); } + void addS16ImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + switch (Kind) { + case Immediate: + Inst.addOperand(MCOperand::CreateImm(getImm())); + break; + case ContextImmediate: + Inst.addOperand(MCOperand::CreateImm(getImmS16Context())); + break; + default: + Inst.addOperand(MCOperand::CreateExpr(getExpr())); + break; + } + } + + void addU16ImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + switch (Kind) { + case Immediate: + Inst.addOperand(MCOperand::CreateImm(getImm())); + break; + case ContextImmediate: + Inst.addOperand(MCOperand::CreateImm(getImmU16Context())); + break; + default: + Inst.addOperand(MCOperand::CreateExpr(getExpr())); + break; + } + } + void addBranchTargetOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); if (Kind == Immediate) @@ -634,6 +703,16 @@ public: } static std::unique_ptr<PPCOperand> + CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) { + auto Op = make_unique<PPCOperand>(ContextImmediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + Op->IsPPC64 = IsPPC64; + return Op; + } + + static std::unique_ptr<PPCOperand> CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) { if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val)) return CreateImm(CE->getValue(), S, E, IsPPC64); @@ -642,6 +721,12 @@ public: if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS) return CreateTLSReg(SRE, S, E, IsPPC64); + if (const PPCMCExpr *TE = dyn_cast<PPCMCExpr>(Val)) { + int64_t Res; + if (TE->EvaluateAsConstant(Res)) + return CreateContextImm(Res, S, E, IsPPC64); + } + return CreateExpr(Val, S, E, IsPPC64); } }; @@ -654,6 +739,7 @@ void PPCOperand::print(raw_ostream &OS) const { OS << "'" << getToken() << "'"; break; case Immediate: + case ContextImmediate: OS << getImm(); break; case Expression: diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp index e8512cd2332..7204befe15e 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "PPCFixupKinds.h" #include "PPCMCExpr.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" @@ -52,6 +53,43 @@ void PPCMCExpr::PrintImpl(raw_ostream &OS) const { } bool +PPCMCExpr::EvaluateAsConstant(int64_t &Res) const { + MCValue Value; + + if (!getSubExpr()->EvaluateAsRelocatable(Value, nullptr, nullptr)) + return false; + + if (!Value.isAbsolute()) + return false; + + Res = EvaluateAsInt64(Value.getConstant()); + return true; +} + +int64_t +PPCMCExpr::EvaluateAsInt64(int64_t Value) const { + switch (Kind) { + case VK_PPC_LO: + return Value & 0xffff; + case VK_PPC_HI: + return (Value >> 16) & 0xffff; + case VK_PPC_HA: + return ((Value + 0x8000) >> 16) & 0xffff; + case VK_PPC_HIGHER: + return (Value >> 32) & 0xffff; + case VK_PPC_HIGHERA: + return ((Value + 0x8000) >> 32) & 0xffff; + case VK_PPC_HIGHEST: + return (Value >> 48) & 0xffff; + case VK_PPC_HIGHESTA: + return ((Value + 0x8000) >> 48) & 0xffff; + case VK_PPC_None: + break; + } + llvm_unreachable("Invalid kind!"); +} + +bool PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { @@ -61,32 +99,10 @@ PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, return false; if (Value.isAbsolute()) { - int64_t Result = Value.getConstant(); - switch (Kind) { - default: - llvm_unreachable("Invalid kind!"); - case VK_PPC_LO: - Result = Result & 0xffff; - break; - case VK_PPC_HI: - Result = (Result >> 16) & 0xffff; - break; - case VK_PPC_HA: - Result = ((Result + 0x8000) >> 16) & 0xffff; - break; - case VK_PPC_HIGHER: - Result = (Result >> 32) & 0xffff; - break; - case VK_PPC_HIGHERA: - Result = ((Result + 0x8000) >> 32) & 0xffff; - break; - case VK_PPC_HIGHEST: - Result = (Result >> 48) & 0xffff; - break; - case VK_PPC_HIGHESTA: - Result = ((Result + 0x8000) >> 48) & 0xffff; - break; - } + int64_t Result = EvaluateAsInt64(Value.getConstant()); + if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) && + (Result >= 0x8000)) + return false; Res = MCValue::get(Result); } else { if (!Layout) diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h index f9baf5de5a0..32b6f9a6c08 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h @@ -34,6 +34,8 @@ private: const MCExpr *Expr; bool IsDarwin; + int64_t EvaluateAsInt64(int64_t Value) const; + explicit PPCMCExpr(VariantKind _Kind, const MCExpr *_Expr, bool _IsDarwin) : Kind(_Kind), Expr(_Expr), IsDarwin(_IsDarwin) {} @@ -88,6 +90,8 @@ public: // There are no TLS PPCMCExprs at the moment. void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {} + bool EvaluateAsConstant(int64_t &Res) const; + static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index e33ded03952..3b2c7cb3d81 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -458,7 +458,7 @@ def u6imm : Operand<i32> { } def PPCS16ImmAsmOperand : AsmOperandClass { let Name = "S16Imm"; let PredicateMethod = "isS16Imm"; - let RenderMethod = "addImmOperands"; + let RenderMethod = "addS16ImmOperands"; } def s16imm : Operand<i32> { let PrintMethod = "printS16ImmOperand"; @@ -468,7 +468,7 @@ def s16imm : Operand<i32> { } def PPCU16ImmAsmOperand : AsmOperandClass { let Name = "U16Imm"; let PredicateMethod = "isU16Imm"; - let RenderMethod = "addImmOperands"; + let RenderMethod = "addU16ImmOperands"; } def u16imm : Operand<i32> { let PrintMethod = "printU16ImmOperand"; @@ -478,7 +478,7 @@ def u16imm : Operand<i32> { } def PPCS17ImmAsmOperand : AsmOperandClass { let Name = "S17Imm"; let PredicateMethod = "isS17Imm"; - let RenderMethod = "addImmOperands"; + let RenderMethod = "addS16ImmOperands"; } def s17imm : Operand<i32> { // This operand type is used for addis/lis to allow the assembler parser @@ -554,7 +554,7 @@ def ptr_rc_idx : Operand<iPTR>, PointerLikeRegClass<0> { def PPCDispRIOperand : AsmOperandClass { let Name = "DispRI"; let PredicateMethod = "isS16Imm"; - let RenderMethod = "addImmOperands"; + let RenderMethod = "addS16ImmOperands"; } def dispRI : Operand<iPTR> { let ParserMatchClass = PPCDispRIOperand; |