Thumb parsing and encoding for STM.
[oota-llvm.git] / lib / Target / ARM / AsmParser / ARMAsmParser.cpp
index 6bb59d4fa9e98a8a36a9453f725e5ee19b3086fc..40efea74545cd89208d426a54025b39a32ed64da 100644 (file)
@@ -2755,7 +2755,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
   // predicated but do have a carry-set and so weren't caught above.
   if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
       Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
-      Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls") {
+      Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
+      Mnemonic != "sbcs") {
     unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
       .Case("eq", ARMCC::EQ)
       .Case("ne", ARMCC::NE)
@@ -3046,6 +3047,24 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
 }
 
 // Validate context-sensitive operand constraints.
+
+// return 'true' if register list contains non-low GPR registers,
+// 'false' otherwise. If Reg is in the register list or is HiReg, set
+// 'containsReg' to true.
+static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
+                                 unsigned HiReg, bool &containsReg) {
+  containsReg = false;
+  for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
+    unsigned OpReg = Inst.getOperand(i).getReg();
+    if (OpReg == Reg)
+      containsReg = true;
+    // Anything other than a low register isn't legal here.
+    if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
+      return true;
+  }
+  return false;
+}
+
 // FIXME: We would really like to be able to tablegen'erate this.
 bool ARMAsmParser::
 validateInstruction(MCInst &Inst,
@@ -3100,22 +3119,16 @@ validateInstruction(MCInst &Inst,
     bool hasWritebackToken =
       (static_cast<ARMOperand*>(Operands[3])->isToken() &&
        static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
-    bool doesWriteback = true;
-    for (unsigned i = 3; i < Inst.getNumOperands(); ++i) {
-      unsigned Reg = Inst.getOperand(i).getReg();
-      if (Reg == Rn)
-        doesWriteback = false;
-      // Anything other than a low register isn't legal here.
-      if (!isARMLowRegister(Reg))
-        return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
-                     "registers must be in range r0-r7");
-    }
+    bool listContainsBase;
+    if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase))
+      return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
+                   "registers must be in range r0-r7");
     // If we should have writeback, then there should be a '!' token.
-    if (doesWriteback && !hasWritebackToken)
+    if (!listContainsBase && !hasWritebackToken)
       return Error(Operands[2]->getStartLoc(),
                    "writeback operator '!' expected");
     // Likewise, if we should not have writeback, there must not be a '!'
-    if (!doesWriteback && hasWritebackToken)
+    if (listContainsBase && hasWritebackToken)
       return Error(Operands[3]->getStartLoc(),
                    "writeback operator '!' not allowed when base register "
                    "in register list");
@@ -3123,23 +3136,24 @@ validateInstruction(MCInst &Inst,
     break;
   }
   case ARM::tPOP: {
-    for (unsigned i = 2; i < Inst.getNumOperands(); ++i) {
-      unsigned Reg = Inst.getOperand(i).getReg();
-      // Anything other than a low register isn't legal here.
-      if (!isARMLowRegister(Reg) && Reg != ARM::PC)
-        return Error(Operands[2]->getStartLoc(),
-                     "registers must be in range r0-r7 or pc");
-    }
+    bool listContainsBase;
+    if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
+      return Error(Operands[2]->getStartLoc(),
+                   "registers must be in range r0-r7 or pc");
     break;
   }
   case ARM::tPUSH: {
-    for (unsigned i = 2; i < Inst.getNumOperands(); ++i) {
-      unsigned Reg = Inst.getOperand(i).getReg();
-      // Anything other than a low register isn't legal here.
-      if (!isARMLowRegister(Reg) && Reg != ARM::LR)
-        return Error(Operands[2]->getStartLoc(),
-                     "registers must be in range r0-r7 or lr");
-    }
+    bool listContainsBase;
+    if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
+      return Error(Operands[2]->getStartLoc(),
+                   "registers must be in range r0-r7 or lr");
+    break;
+  }
+  case ARM::tSTMIA_UPD: {
+    bool listContainsBase;
+    if (checkLowRegisterList(Inst, 3, 0, 0, listContainsBase))
+      return Error(Operands[4]->getStartLoc(),
+                   "registers must be in range r0-r7");
     break;
   }
   }