From 5606fcae50951e9d9aef7def18531b5fd017971b Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 4 Jul 2013 14:24:00 +0000 Subject: [PATCH] [PowerPC] Add asm parser support for CR expressions This adds support for specifying condition registers and condition register fields via expressions using the symbols defined by the PowerISA, like "4*cr2+eq". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185633 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 87 ++++++++++++++- lib/Target/PowerPC/PPCInstrInfo.td | 2 +- test/MC/PowerPC/ppc64-encoding-ext.s | 100 +++++++++++++++++- 3 files changed, 183 insertions(+), 6 deletions(-) diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 489296311e1..e4fc3b9ded7 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -107,6 +107,67 @@ static unsigned CRRegs[8] = { PPC::CR4, PPC::CR5, PPC::CR6, PPC::CR7 }; +// Evaluate an expression containing condition register +// or condition register field symbols. Returns positive +// value on success, or -1 on error. +static int64_t +EvaluateCRExpr(const MCExpr *E) { + switch (E->getKind()) { + case MCExpr::Target: + return -1; + + case MCExpr::Constant: { + int64_t Res = cast(E)->getValue(); + return Res < 0 ? -1 : Res; + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr *SRE = cast(E); + StringRef Name = SRE->getSymbol().getName(); + + if (Name == "lt") return 0; + if (Name == "gt") return 1; + if (Name == "eq") return 2; + if (Name == "so") return 3; + if (Name == "un") return 3; + + if (Name == "cr0") return 0; + if (Name == "cr1") return 1; + if (Name == "cr2") return 2; + if (Name == "cr3") return 3; + if (Name == "cr4") return 4; + if (Name == "cr5") return 5; + if (Name == "cr6") return 6; + if (Name == "cr7") return 7; + + return -1; + } + + case MCExpr::Unary: + return -1; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(E); + int64_t LHSVal = EvaluateCRExpr(BE->getLHS()); + int64_t RHSVal = EvaluateCRExpr(BE->getRHS()); + int64_t Res; + + if (LHSVal < 0 || RHSVal < 0) + return -1; + + switch (BE->getOpcode()) { + default: return -1; + case MCBinaryExpr::Add: Res = LHSVal + RHSVal; break; + case MCBinaryExpr::Mul: Res = LHSVal * RHSVal; break; + } + + return Res < 0 ? -1 : Res; + } + } + + llvm_unreachable("Invalid expression kind!"); +} + struct PPCOperand; class PPCAsmParser : public MCTargetAsmParser { @@ -193,6 +254,7 @@ struct PPCOperand : public MCParsedAsmOperand { struct ExprOp { const MCExpr *Val; + int64_t CRVal; // Cached result of EvaluateCRExpr(Val) }; union { @@ -240,6 +302,11 @@ public: return Expr.Val; } + int64_t getExprCRVal() const { + assert(Kind == Expression && "Invalid access!"); + return Expr.CRVal; + } + unsigned getReg() const { assert(isRegNumber() && "Invalid access!"); return (unsigned) Imm.Val; @@ -247,7 +314,12 @@ public: unsigned getCCReg() const { assert(isCCRegNumber() && "Invalid access!"); - return (unsigned) Imm.Val; + return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); + } + + unsigned getCRBit() const { + assert(isCRBitNumber() && "Invalid access!"); + return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); } unsigned getCRBitMask() const { @@ -276,8 +348,14 @@ public: (Kind == Immediate && isInt<16>(getImm()) && (getImm() & 3) == 0); } bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); } - bool isCCRegNumber() const { return Kind == Immediate && - isUInt<3>(getImm()); } + bool isCCRegNumber() const { return (Kind == Expression + && isUInt<3>(getExprCRVal())) || + (Kind == Immediate + && isUInt<3>(getImm())); } + bool isCRBitNumber() const { return (Kind == Expression + && isUInt<5>(getExprCRVal())) || + (Kind == Immediate + && isUInt<5>(getImm())); } bool isCRBitMask() const { return Kind == Immediate && isUInt<8>(getImm()) && isPowerOf2_32(getImm()); } bool isMem() const { return false; } @@ -338,7 +416,7 @@ public: void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(CRBITRegs[getReg()])); + Inst.addOperand(MCOperand::CreateReg(CRBITRegs[getCRBit()])); } void addRegCRRCOperands(MCInst &Inst, unsigned N) const { @@ -397,6 +475,7 @@ public: SMLoc S, SMLoc E, bool IsPPC64) { PPCOperand *Op = new PPCOperand(Expression); Op->Expr.Val = Val; + Op->Expr.CRVal = EvaluateCRExpr(Val); Op->StartLoc = S; Op->EndLoc = E; Op->IsPPC64 = IsPPC64; diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 022c15179b9..e104ea5ceb6 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -392,7 +392,7 @@ def vrrc : RegisterOperand { let ParserMatchClass = PPCRegVRRCAsmOperand; } def PPCRegCRBITRCAsmOperand : AsmOperandClass { - let Name = "RegCRBITRC"; let PredicateMethod = "isRegNumber"; + let Name = "RegCRBITRC"; let PredicateMethod = "isCRBitNumber"; } def crbitrc : RegisterOperand { let ParserMatchClass = PPCRegCRBITRCAsmOperand; diff --git a/test/MC/PowerPC/ppc64-encoding-ext.s b/test/MC/PowerPC/ppc64-encoding-ext.s index 0bc1a398355..9bbeba0f340 100644 --- a/test/MC/PowerPC/ppc64-encoding-ext.s +++ b/test/MC/PowerPC/ppc64-encoding-ext.s @@ -1,7 +1,105 @@ # RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding %s | FileCheck %s -# FIXME: Condition register bit symbols +# Condition register bit symbols + +# CHECK: beqlr 0 # encoding: [0x4d,0x82,0x00,0x20] + beqlr cr0 +# CHECK: beqlr 1 # encoding: [0x4d,0x86,0x00,0x20] + beqlr cr1 +# CHECK: beqlr 2 # encoding: [0x4d,0x8a,0x00,0x20] + beqlr cr2 +# CHECK: beqlr 3 # encoding: [0x4d,0x8e,0x00,0x20] + beqlr cr3 +# CHECK: beqlr 4 # encoding: [0x4d,0x92,0x00,0x20] + beqlr cr4 +# CHECK: beqlr 5 # encoding: [0x4d,0x96,0x00,0x20] + beqlr cr5 +# CHECK: beqlr 6 # encoding: [0x4d,0x9a,0x00,0x20] + beqlr cr6 +# CHECK: beqlr 7 # encoding: [0x4d,0x9e,0x00,0x20] + beqlr cr7 + +# CHECK: bclr 12, 0, 0 # encoding: [0x4d,0x80,0x00,0x20] + btlr 4*cr0+lt +# CHECK: bclr 12, 1, 0 # encoding: [0x4d,0x81,0x00,0x20] + btlr 4*cr0+gt +# CHECK: bclr 12, 2, 0 # encoding: [0x4d,0x82,0x00,0x20] + btlr 4*cr0+eq +# CHECK: bclr 12, 3, 0 # encoding: [0x4d,0x83,0x00,0x20] + btlr 4*cr0+so +# CHECK: bclr 12, 3, 0 # encoding: [0x4d,0x83,0x00,0x20] + btlr 4*cr0+un +# CHECK: bclr 12, 4, 0 # encoding: [0x4d,0x84,0x00,0x20] + btlr 4*cr1+lt +# CHECK: bclr 12, 5, 0 # encoding: [0x4d,0x85,0x00,0x20] + btlr 4*cr1+gt +# CHECK: bclr 12, 6, 0 # encoding: [0x4d,0x86,0x00,0x20] + btlr 4*cr1+eq +# CHECK: bclr 12, 7, 0 # encoding: [0x4d,0x87,0x00,0x20] + btlr 4*cr1+so +# CHECK: bclr 12, 7, 0 # encoding: [0x4d,0x87,0x00,0x20] + btlr 4*cr1+un +# CHECK: bclr 12, 8, 0 # encoding: [0x4d,0x88,0x00,0x20] + btlr 4*cr2+lt +# CHECK: bclr 12, 9, 0 # encoding: [0x4d,0x89,0x00,0x20] + btlr 4*cr2+gt +# CHECK: bclr 12, 10, 0 # encoding: [0x4d,0x8a,0x00,0x20] + btlr 4*cr2+eq +# CHECK: bclr 12, 11, 0 # encoding: [0x4d,0x8b,0x00,0x20] + btlr 4*cr2+so +# CHECK: bclr 12, 11, 0 # encoding: [0x4d,0x8b,0x00,0x20] + btlr 4*cr2+un +# CHECK: bclr 12, 12, 0 # encoding: [0x4d,0x8c,0x00,0x20] + btlr 4*cr3+lt +# CHECK: bclr 12, 13, 0 # encoding: [0x4d,0x8d,0x00,0x20] + btlr 4*cr3+gt +# CHECK: bclr 12, 14, 0 # encoding: [0x4d,0x8e,0x00,0x20] + btlr 4*cr3+eq +# CHECK: bclr 12, 15, 0 # encoding: [0x4d,0x8f,0x00,0x20] + btlr 4*cr3+so +# CHECK: bclr 12, 15, 0 # encoding: [0x4d,0x8f,0x00,0x20] + btlr 4*cr3+un +# CHECK: bclr 12, 16, 0 # encoding: [0x4d,0x90,0x00,0x20] + btlr 4*cr4+lt +# CHECK: bclr 12, 17, 0 # encoding: [0x4d,0x91,0x00,0x20] + btlr 4*cr4+gt +# CHECK: bclr 12, 18, 0 # encoding: [0x4d,0x92,0x00,0x20] + btlr 4*cr4+eq +# CHECK: bclr 12, 19, 0 # encoding: [0x4d,0x93,0x00,0x20] + btlr 4*cr4+so +# CHECK: bclr 12, 19, 0 # encoding: [0x4d,0x93,0x00,0x20] + btlr 4*cr4+un +# CHECK: bclr 12, 20, 0 # encoding: [0x4d,0x94,0x00,0x20] + btlr 4*cr5+lt +# CHECK: bclr 12, 21, 0 # encoding: [0x4d,0x95,0x00,0x20] + btlr 4*cr5+gt +# CHECK: bclr 12, 22, 0 # encoding: [0x4d,0x96,0x00,0x20] + btlr 4*cr5+eq +# CHECK: bclr 12, 23, 0 # encoding: [0x4d,0x97,0x00,0x20] + btlr 4*cr5+so +# CHECK: bclr 12, 23, 0 # encoding: [0x4d,0x97,0x00,0x20] + btlr 4*cr5+un +# CHECK: bclr 12, 24, 0 # encoding: [0x4d,0x98,0x00,0x20] + btlr 4*cr6+lt +# CHECK: bclr 12, 25, 0 # encoding: [0x4d,0x99,0x00,0x20] + btlr 4*cr6+gt +# CHECK: bclr 12, 26, 0 # encoding: [0x4d,0x9a,0x00,0x20] + btlr 4*cr6+eq +# CHECK: bclr 12, 27, 0 # encoding: [0x4d,0x9b,0x00,0x20] + btlr 4*cr6+so +# CHECK: bclr 12, 27, 0 # encoding: [0x4d,0x9b,0x00,0x20] + btlr 4*cr6+un +# CHECK: bclr 12, 28, 0 # encoding: [0x4d,0x9c,0x00,0x20] + btlr 4*cr7+lt +# CHECK: bclr 12, 29, 0 # encoding: [0x4d,0x9d,0x00,0x20] + btlr 4*cr7+gt +# CHECK: bclr 12, 30, 0 # encoding: [0x4d,0x9e,0x00,0x20] + btlr 4*cr7+eq +# CHECK: bclr 12, 31, 0 # encoding: [0x4d,0x9f,0x00,0x20] + btlr 4*cr7+so +# CHECK: bclr 12, 31, 0 # encoding: [0x4d,0x9f,0x00,0x20] + btlr 4*cr7+un # Branch mnemonics