ARM assembly parsing and encoding for SETEND instruction.
authorJim Grosbach <grosbach@apple.com>
Fri, 22 Jul 2011 17:44:50 +0000 (17:44 +0000)
committerJim Grosbach <grosbach@apple.com>
Fri, 22 Jul 2011 17:44:50 +0000 (17:44 +0000)
Add parsing and diagnostics for malformed inputs. Tests for diagnostics and
for correct encodings.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135776 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/basic-arm-instructions.s
test/MC/ARM/diagnostics.s

index e673fe71e8485b39e4ad3442abcfe6609af8c7b8..278bd5bda79c810cf12c1795929e54b5c859fb5e 100644 (file)
@@ -193,8 +193,13 @@ def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> {
 
 // ARM special operands for disassembly only.
 //
+def SetEndAsmOperand : AsmOperandClass {
+  let Name = "SetEndImm";
+  let ParserMethod = "parseSetEndImm";
+}
 def setend_op : Operand<i32> {
   let PrintMethod = "printSetendOperand";
+  let ParserMatchClass = SetEndAsmOperand;
 }
 
 def msr_mask : Operand<i32> {
index fd8f815207da0503ef5f40def1d699fe3da6af3c..ef611b21e72d87d95033bd65ad58a66520273f6d 100644 (file)
@@ -126,6 +126,7 @@ class ARMAsmParser : public TargetAsmParser {
   OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
     return parsePKHImm(O, "asr", 1, 32);
   }
+  OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
 
   // Asm Match Converter Methods
   bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@@ -476,6 +477,14 @@ public:
     int64_t Value = CE->getValue();
     return ARM_AM::getT2SOImmVal(Value) != -1;
   }
+  bool isSetEndImm() const {
+    if (Kind != Immediate)
+      return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE) return false;
+    int64_t Value = CE->getValue();
+    return Value == 1 || Value == 0;
+  }
   bool isReg() const { return Kind == Register; }
   bool isRegList() const { return Kind == RegisterList; }
   bool isDPRRegList() const { return Kind == DPRRegisterList; }
@@ -715,6 +724,11 @@ public:
     addExpr(Inst, getImm());
   }
 
+  void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    addExpr(Inst, getImm());
+  }
+
   void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
@@ -1644,6 +1658,30 @@ parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
   return MatchOperand_Success;
 }
 
+ARMAsmParser::OperandMatchResultTy ARMAsmParser::
+parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  const AsmToken &Tok = Parser.getTok();
+  SMLoc S = Tok.getLoc();
+  if (Tok.isNot(AsmToken::Identifier)) {
+    Error(Tok.getLoc(), "'be' or 'le' operand expected");
+    return MatchOperand_ParseFail;
+  }
+  int Val = StringSwitch<int>(Tok.getString())
+    .Case("be", 1)
+    .Case("le", 0)
+    .Default(-1);
+  Parser.Lex(); // Eat the token.
+
+  if (Val == -1) {
+    Error(Tok.getLoc(), "'be' or 'le' operand expected");
+    return MatchOperand_ParseFail;
+  }
+  Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
+                                                                  getContext()),
+                                           S, Parser.getTok().getLoc()));
+  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.
@@ -2197,6 +2235,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
       Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
       Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
       Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "clrex" ||
+      Mnemonic == "setend" ||
       Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumb())) {
     CanAcceptPredicationCode = false;
   } else {
@@ -2221,7 +2260,7 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
   unsigned ProcessorIMod;
   bool CarrySetting;
   Mnemonic = SplitMnemonic(Mnemonic, PredicationCode, CarrySetting,
-                       ProcessorIMod);
+                           ProcessorIMod);
 
   Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
 
@@ -2245,6 +2284,13 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
     return Error(NameLoc, "instruction '" + Mnemonic +
                  "' can not set flags, but 's' suffix specified");
   }
+  // If we had a predication code on an instruction that can't do that, issue an
+  // error.
+  if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
+    Parser.EatToEndOfStatement();
+    return Error(NameLoc, "instruction '" + Mnemonic +
+                 "' is not predicable, but condition code specified");
+  }
 
   // Add the carry setting operand, if necessary.
   //
@@ -2259,11 +2305,6 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
   if (CanAcceptPredicationCode) {
     Operands.push_back(ARMOperand::CreateCondCode(
                          ARMCC::CondCodes(PredicationCode), NameLoc));
-  } else {
-    // This mnemonic can't ever accept a predication code, but the user wrote
-    // one (or misspelled another mnemonic).
-
-    // FIXME: Issue a nice error.
   }
 
   // Add the processor imod operand, if necessary.
index 0bde0f63595208765bd6d3de93c85b010b873fc7..00087f3a667f34a481037f03a5d47c7ce533172e 100644 (file)
@@ -1303,6 +1303,16 @@ _func:
 @ CHECK: selne r9, r2, r1              @ encoding: [0xb1,0x9f,0x82,0x16]
 
 
+@------------------------------------------------------------------------------
+@ SETEND
+@------------------------------------------------------------------------------
+        setend be
+        setend le
+
+       sel     r9, r2, r1              @ encoding: [0xb1,0x9f,0x82,0xe6]
+       selne   r9, r2, r1              @ encoding: [0xb1,0x9f,0x82,0x16]
+
+
 @------------------------------------------------------------------------------
 @ STM*
 @------------------------------------------------------------------------------
index abefca60afdf2b38825dd4704c0a0602fdbdf389..305a5fa65e1791597e9c2a01ed3f2d64f86c0399 100644 (file)
 @ CHECK: error: asr operand expected.
 @ CHECK:         pkhtb r2, r2, r3, lsl #3
 @ CHECK:                           ^
+
+
+        @ bad values for SETEND
+        setendne be
+        setend me
+        setend 1
+
+@ CHECK: error: instruction 'setend' is not predicable, but condition code specified
+@ CHECK:         setendne be
+@ CHECK:         ^
+@ CHECK: error: 'be' or 'le' operand expected
+@ CHECK:         setend me
+@ CHECK:                  ^
+@ CHECK: error: 'be' or 'le' operand expected
+@ CHECK:         setend 1
+@ CHECK:                ^