[llvm-commits] [llvm] r136399 - in /llvm/trunk: lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/AsmParser/ARMAsmParser.cpp test/MC/ARM/basic-arm-instructions.s

Jim Grosbach grosbach at apple.com
Thu Jul 28 14:34:26 PDT 2011


Author: grosbach
Date: Thu Jul 28 16:34:26 2011
New Revision: 136399

URL: http://llvm.org/viewvc/llvm-project?rev=136399&view=rev
Log:
ARM assembly parsing and encoding for BFC and BFI.

Add parsing support that handles converting the lsb+width source into the
odd way we represent the instruction (an inverted bitfield mask).

Modified:
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/test/MC/ARM/basic-arm-instructions.s

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=136399&r1=136398&r2=136399&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Thu Jul 28 16:34:26 2011
@@ -536,12 +536,17 @@
 
 /// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield
 /// e.g., 0xf000ffff
+def BitfieldAsmOperand : AsmOperandClass {
+  let Name = "Bitfield";
+  let ParserMethod = "parseBitfield";
+}
 def bf_inv_mask_imm : Operand<i32>,
                       PatLeaf<(imm), [{
   return ARM::isBitFieldInvertedMask(N->getZExtValue());
 }] > {
   let EncoderMethod = "getBitfieldInvertedMaskOpValue";
   let PrintMethod = "printBitfieldInvMaskImmOperand";
+  let ParserMatchClass = BitfieldAsmOperand;
 }
 
 /// lsb_pos_imm - position of the lsb bit, used by BFI4p and t2BFI4p

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=136399&r1=136398&r2=136399&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Thu Jul 28 16:34:26 2011
@@ -125,6 +125,7 @@
   OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
   OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
   OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
+  OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
 
   // Asm Match Converter Methods
   bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@@ -184,6 +185,7 @@
     ShiftedImmediate,
     ShifterImmediate,
     RotateImmediate,
+    BitfieldDescriptor,
     Token
   } Kind;
 
@@ -260,6 +262,10 @@
     struct {
       unsigned Imm;
     } RotImm;
+    struct {
+      unsigned LSB;
+      unsigned Width;
+    } Bitfield;
   };
 
   ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -315,6 +321,9 @@
     case RotateImmediate:
       RotImm = o.RotImm;
       break;
+    case BitfieldDescriptor:
+      Bitfield = o.Bitfield;
+      break;
     }
   }
 
@@ -535,6 +544,7 @@
   bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
   bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
   bool isRotImm() const { return Kind == RotateImmediate; }
+  bool isBitfield() const { return Kind == BitfieldDescriptor; }
   bool isMemMode2() const {
     if (getMemAddrMode() != ARMII::AddrMode2)
       return false;
@@ -711,6 +721,17 @@
     Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
   }
 
+  void addBitfieldOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    // Munge the lsb/width into a bitfield mask.
+    unsigned lsb = Bitfield.LSB;
+    unsigned width = Bitfield.Width;
+    // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
+    uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
+                      (32 - (lsb + width)));
+    Inst.addOperand(MCOperand::CreateImm(Mask));
+  }
+
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     addExpr(Inst, getImm());
@@ -1026,6 +1047,16 @@
     return Op;
   }
 
+  static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
+                                    SMLoc S, SMLoc E) {
+    ARMOperand *Op = new ARMOperand(BitfieldDescriptor);
+    Op->Bitfield.LSB = LSB;
+    Op->Bitfield.Width = Width;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
   static ARMOperand *
   CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
                 SMLoc StartLoc, SMLoc EndLoc) {
@@ -1204,6 +1235,10 @@
   case RotateImmediate:
     OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
     break;
+  case BitfieldDescriptor:
+    OS << "<bitfield " << "lsb: " << Bitfield.LSB
+       << ", width: " << Bitfield.Width << ">";
+    break;
   case RegisterList:
   case DPRRegisterList:
   case SPRRegisterList: {
@@ -1883,6 +1918,72 @@
   return MatchOperand_Success;
 }
 
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  SMLoc S = Parser.getTok().getLoc();
+  // The bitfield descriptor is really two operands, the LSB and the width.
+  if (Parser.getTok().isNot(AsmToken::Hash)) {
+    Error(Parser.getTok().getLoc(), "'#' expected");
+    return MatchOperand_ParseFail;
+  }
+  Parser.Lex(); // Eat hash token.
+
+  const MCExpr *LSBExpr;
+  SMLoc E = Parser.getTok().getLoc();
+  if (getParser().ParseExpression(LSBExpr)) {
+    Error(E, "malformed immediate expression");
+    return MatchOperand_ParseFail;
+  }
+  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
+  if (!CE) {
+    Error(E, "'lsb' operand must be an immediate");
+    return MatchOperand_ParseFail;
+  }
+
+  int64_t LSB = CE->getValue();
+  // The LSB must be in the range [0,31]
+  if (LSB < 0 || LSB > 31) {
+    Error(E, "'lsb' operand must be in the range [0,31]");
+    return MatchOperand_ParseFail;
+  }
+  E = Parser.getTok().getLoc();
+
+  // Expect another immediate operand.
+  if (Parser.getTok().isNot(AsmToken::Comma)) {
+    Error(Parser.getTok().getLoc(), "too few operands");
+    return MatchOperand_ParseFail;
+  }
+  Parser.Lex(); // Eat hash token.
+  if (Parser.getTok().isNot(AsmToken::Hash)) {
+    Error(Parser.getTok().getLoc(), "'#' expected");
+    return MatchOperand_ParseFail;
+  }
+  Parser.Lex(); // Eat hash token.
+
+  const MCExpr *WidthExpr;
+  if (getParser().ParseExpression(WidthExpr)) {
+    Error(E, "malformed immediate expression");
+    return MatchOperand_ParseFail;
+  }
+  CE = dyn_cast<MCConstantExpr>(WidthExpr);
+  if (!CE) {
+    Error(E, "'width' operand must be an immediate");
+    return MatchOperand_ParseFail;
+  }
+
+  int64_t Width = CE->getValue();
+  // The LSB must be in the range [1,32-lsb]
+  if (Width < 1 || Width > 32 - LSB) {
+    Error(E, "'width' operand must be in the range [1,32-lsb]");
+    return MatchOperand_ParseFail;
+  }
+  E = Parser.getTok().getLoc();
+
+  Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
+
+  return MatchOperand_Success;
+}
+
 /// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
 /// Needed here because the Asm Gen Matcher can't handle properly tied operands
 /// when they refer multiple MIOperands inside a single one.

Modified: llvm/trunk/test/MC/ARM/basic-arm-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/basic-arm-instructions.s?rev=136399&r1=136398&r2=136399&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/basic-arm-instructions.s (original)
+++ llvm/trunk/test/MC/ARM/basic-arm-instructions.s Thu Jul 28 16:34:26 2011
@@ -258,12 +258,34 @@
 @------------------------------------------------------------------------------
 @ FIXME: B
 @------------------------------------------------------------------------------
+        b _bar
+        beq _baz
+
+@ CHECK: b	_bar                    @ encoding: [A,A,A,0xea]
+                                        @   fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
+@ CHECK: beq	_baz                    @ encoding: [A,A,A,0x0a]
+                                        @   fixup A - offset: 0, value: _baz, kind: fixup_arm_condbranch
+
+
 @------------------------------------------------------------------------------
-@ FIXME: BFC
+@ BFC
 @------------------------------------------------------------------------------
+  bfc r5, #3, #17
+  bfccc r5, #3, #17
+
+@ CHECK: bfc	r5, #3, #17             @ encoding: [0x9f,0x51,0xd3,0xe7]
+@ CHECK: bfclo	r5, #3, #17             @ encoding: [0x9f,0x51,0xd3,0x37]
+
+
 @------------------------------------------------------------------------------
-@ FIXME: BFI
+@ BFI
 @------------------------------------------------------------------------------
+  bfi r5, r2, #3, #17
+  bfine r5, r2, #3, #17
+
+@ CHECK: bfi	r5, r2, #3, #17         @ encoding: [0x92,0x51,0xd3,0xe7]
+@ CHECK: bfine	r5, r2, #3, #17         @ encoding: [0x92,0x51,0xd3,0x17]
+
 
 @------------------------------------------------------------------------------
 @ BIC





More information about the llvm-commits mailing list