[PowerPC] Add asm parser support for CR expressions
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 4 Jul 2013 14:24:00 +0000 (14:24 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Thu, 4 Jul 2013 14:24:00 +0000 (14:24 +0000)
This adds support for specifying condition registers and
condition register fields via expressions using the symbols
defined by the PowerISA, like "4*cr2+eq".

llvm-svn: 185633

llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
llvm/lib/Target/PowerPC/PPCInstrInfo.td
llvm/test/MC/PowerPC/ppc64-encoding-ext.s

index 4892963..e4fc3b9 100644 (file)
@@ -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<MCConstantExpr>(E)->getValue();
+    return Res < 0 ? -1 : Res;
+  }
+
+  case MCExpr::SymbolRef: {
+    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(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<MCBinaryExpr>(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;
index 022c151..e104ea5 100644 (file)
@@ -392,7 +392,7 @@ def vrrc : RegisterOperand<VRRC> {
   let ParserMatchClass = PPCRegVRRCAsmOperand;
 }
 def PPCRegCRBITRCAsmOperand : AsmOperandClass {
-  let Name = "RegCRBITRC"; let PredicateMethod = "isRegNumber";
+  let Name = "RegCRBITRC"; let PredicateMethod = "isCRBitNumber";
 }
 def crbitrc : RegisterOperand<CRBITRC> {
   let ParserMatchClass = PPCRegCRBITRCAsmOperand;
index 0bc1a39..9bbeba0 100644 (file)
@@ -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