Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp
===================================================================
--- lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -174,8 +174,11 @@
     if (++ITState.CurPosition == 5 - TZ)
       ITState.CurPosition = ~0U; // Done with the IT block after this.
   }
+  bool lastInITBlock() {
+    unsigned TZ = countTrailingZeros(ITState.Mask);
+    return (ITState.CurPosition == 4 - TZ);
+  }
 
-
   MCAsmParser &getParser() const { return Parser; }
   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
 
@@ -323,6 +326,8 @@
   bool processInstruction(MCInst &Inst, const OperandVector &Ops);
   bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands);
   bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
+  bool validateRegListOperands(MCInst &Inst, const OperandVector &Operands,
+                               unsigned OpNo);
 
 public:
   enum ARMMatchResultTy {
@@ -5772,14 +5777,159 @@
   return false;
 }
 
-// Check if the specified regisgter is in the register list of the inst,
+// Check if there are any special registers in the register list of the inst,
 // starting at the indicated operand number.
-static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
+static void findSpecialRegsInList(MCInst &Inst, unsigned OpNo, bool &SP,
+                                  bool &PC, bool &LR, bool &BaseReg) {
+  SP = PC = LR = BaseReg = false;
+  unsigned Rn = Inst.getOperand(0).getReg();
   for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
     unsigned OpReg = Inst.getOperand(i).getReg();
-    if (OpReg == Reg)
-      return true;
+    if (OpReg == ARM::SP)
+      SP = true;
+    else if (OpReg == ARM::PC)
+      PC = true;
+    else if (OpReg == ARM::LR)
+      LR = true;
+    if (OpReg == Rn)
+      BaseReg = true;
   }
+
+  return;
+}
+
+struct RegListOperandRules {
+  unsigned OPcode;
+  bool AllowSP;
+  bool AllowPC;
+  bool AllowPCAndLR;
+  bool AllowInITBlock;
+  bool AllowBaseRegister;
+
+  bool operator==(const RegListOperandRules &rhs) const {
+    return (OPcode == rhs.OPcode && AllowSP == rhs.AllowSP &&
+            AllowPC == rhs.AllowPC && AllowPCAndLR == rhs.AllowPCAndLR &&
+            AllowInITBlock == rhs.AllowInITBlock &&
+            AllowBaseRegister == rhs.AllowBaseRegister);
+  }
+};
+
+static const RegListOperandRules AllowedCombinations[] = {
+    {ARM::tLDMIA, false, true, false, false,
+     true}, /// Notionally handles ARM::tLDMIA_UPD too
+    {ARM::tLDMIA_UPD, false, true, false, false, false},
+    {ARM::t2LDMIA, false, true, false, false, true},
+    {ARM::t2LDMDB, false, true, false, false, true},
+    {ARM::t2LDMIA_UPD, false, true, false, false, false},
+    {ARM::t2LDMDB_UPD, false, true, false, false, false},
+    {ARM::tPOP, false, true, false, true,
+     true}, // there is no restriction on POP instruction w.r.t IT block, the
+            // last field is actually NA. Same holds for following instructions.
+    {ARM::tSTMIA_UPD, false, false, true, true, false},
+    {ARM::t2STMIA, false, false, true, true, true},
+    {ARM::t2STMDB, false, false, true, true, true},
+    {ARM::t2STMIA_UPD, false, false, true, true, false},
+    {ARM::t2STMDB_UPD, false, false, true, true, false},
+    {ARM::tPUSH, false, false, true, true, true},
+    {ARM::LDMIA_UPD, true, true, true, true, false},
+    {ARM::LDMDB_UPD, true, true, true, true, false},
+    {ARM::LDMIB_UPD, true, true, true, true, false},
+    {ARM::LDMDA_UPD, true, true, true, true, false}};
+
+bool ARMAsmParser::validateRegListOperands(MCInst &Inst,
+                                           const OperandVector &Operands,
+                                           unsigned OpNo) {
+  bool SP, PC, LR, BaseReg;
+  const unsigned Opcode = Inst.getOpcode();
+  findSpecialRegsInList(Inst, OpNo, SP, PC, LR, BaseReg);
+  RegListOperandRules RegListOperand;
+  RegListOperand.OPcode = Opcode;
+  RegListOperand.AllowSP = SP;
+  RegListOperand.AllowPC = PC;
+  RegListOperand.AllowPCAndLR = (PC && LR);
+  RegListOperand.AllowInITBlock = inITBlock();
+  RegListOperand.AllowBaseRegister = BaseReg;
+
+  if (std::find(std::begin(AllowedCombinations), std::end(AllowedCombinations),
+                RegListOperand) == std::end(AllowedCombinations)) {
+    switch (Opcode) {
+    case ARM::t2LDMIA_UPD:
+    case ARM::t2LDMDB_UPD: {
+      if (BaseReg)
+        return Error(Operands.back()->getStartLoc(),
+                     "writeback register not allowed in register list");
+    }
+    case ARM::tLDMIA: {
+      bool HasWritebackToken =
+          (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
+           static_cast<ARMOperand &>(*Operands[3]).getToken() == "!");
+
+      // If we should not have writeback, there must not be a '!'. This is
+      // true even for the 32-bit wide encodings.
+      if (BaseReg && HasWritebackToken)
+        return Error(Operands[3]->getStartLoc(),
+                     "writeback operator '!' not allowed when base register "
+                     "in register list");
+    }
+    case ARM::t2LDMIA:
+    case ARM::t2LDMDB:
+    case ARM::tPOP: {
+      if (SP)
+        return Error(Operands[OpNo]->getStartLoc(),
+                     "SP not allowed in register list");
+      if (PC && LR)
+        return Error(
+            Operands[OpNo]->getStartLoc(),
+            "LR not allowed in the list, when PC is in the register list");
+      if (PC && inITBlock() && !lastInITBlock())
+        return Error(Operands[OpNo]->getStartLoc(),
+                     "Instruction should be outside an IT block or last in IT "
+                     "block, when PC is in the register list");
+      break;
+    }
+    case ARM::t2STMIA_UPD:
+    case ARM::t2STMDB_UPD: {
+      if (BaseReg)
+        return Error(Operands.back()->getStartLoc(),
+                     "writeback register not allowed in register list");
+    }
+    case ARM::tSTMIA_UPD: {
+      // This would be converted to a 32-bit stm, but that's not valid if the
+      // writeback register is in the list.
+      if (BaseReg)
+        return Error(Operands[4]->getStartLoc(),
+                     "writeback operator '!' not allowed when base register "
+                     "in register list");
+    }
+    case ARM::t2STMIA:
+    case ARM::t2STMDB:
+    case ARM::tPUSH: {
+      if (SP || PC)
+        return Error(Operands[OpNo]->getStartLoc(),
+                     "SP, PC not allowed in register list");
+      break;
+    }
+    case ARM::LDMIA_UPD:
+    case ARM::LDMDB_UPD:
+    case ARM::LDMIB_UPD:
+    case ARM::LDMDA_UPD: {
+      if (BaseReg)
+        return Error(Operands.back()->getStartLoc(),
+                     "writeback register not allowed in register list");
+      break;
+    }
+    case ARM::sysLDMIA_UPD:
+    case ARM::sysLDMDA_UPD:
+    case ARM::sysLDMDB_UPD:
+    case ARM::sysLDMIB_UPD: {
+      if (!PC)
+        return Error(Operands[4]->getStartLoc(),
+                     "writeback register only allowed on system LDM "
+                     "if PC in register-list");
+      break;
+    }
+    }
+  }
   return false;
 }
 
@@ -5970,15 +6120,7 @@
     if (!ListContainsBase && !HasWritebackToken && !isThumbTwo())
       return Error(Operands[2]->getStartLoc(),
                    "writeback operator '!' expected");
-    // If we should not have writeback, there must not be a '!'. This is
-    // true even for the 32-bit wide encodings.
-    if (ListContainsBase && HasWritebackToken)
-      return Error(Operands[3]->getStartLoc(),
-                   "writeback operator '!' not allowed when base register "
-                   "in register list");
-    if (listContainsReg(Inst, 3 + HasWritebackToken, ARM::SP))
-      return Error(Operands[3 + HasWritebackToken]->getStartLoc(),
-                   "SP not allowed in register list");
+    validateRegListOperands(Inst, Operands, 3);
     break;
   }
   case ARM::LDMIA_UPD:
@@ -5989,41 +6131,23 @@
     // UNPREDICTABLE on v7 upwards. Goodness knows what they did before.
     if (!hasV7Ops())
       break;
-    if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
-      return Error(Operands.back()->getStartLoc(),
-                   "writeback register not allowed in register list");
+    validateRegListOperands(Inst, Operands, 3);
     break;
   case ARM::t2LDMIA:
   case ARM::t2LDMDB:
   case ARM::t2STMIA:
-  case ARM::t2STMDB: {
-    if (listContainsReg(Inst, 3, ARM::SP))
-      return Error(Operands.back()->getStartLoc(),
-                   "SP not allowed in register list");
-    break;
-  }
+  case ARM::t2STMDB:
   case ARM::t2LDMIA_UPD:
   case ARM::t2LDMDB_UPD:
   case ARM::t2STMIA_UPD:
-  case ARM::t2STMDB_UPD: {
-    if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
-      return Error(Operands.back()->getStartLoc(),
-                   "writeback register not allowed in register list");
-
-    if (listContainsReg(Inst, 4, ARM::SP))
-      return Error(Operands.back()->getStartLoc(),
-                   "SP not allowed in register list");
-    break;
-  }
+  case ARM::t2STMDB_UPD:
   case ARM::sysLDMIA_UPD:
   case ARM::sysLDMDA_UPD:
   case ARM::sysLDMDB_UPD:
-  case ARM::sysLDMIB_UPD:
-    if (!listContainsReg(Inst, 3, ARM::PC))
-      return Error(Operands[4]->getStartLoc(),
-                   "writeback register only allowed on system LDM "
-                   "if PC in register-list");
+  case ARM::sysLDMIB_UPD: {
+    validateRegListOperands(Inst, Operands, 3);
     break;
+  }
   case ARM::sysSTMIA_UPD:
   case ARM::sysSTMDA_UPD:
   case ARM::sysSTMDB_UPD:
@@ -6057,6 +6181,7 @@
         !isThumbTwo())
       return Error(Operands[2]->getStartLoc(),
                    "registers must be in range r0-r7 or pc");
+    validateRegListOperands(Inst, Operands, 2);
     break;
   }
   case ARM::tPUSH: {
@@ -6065,6 +6190,7 @@
         !isThumbTwo())
       return Error(Operands[2]->getStartLoc(),
                    "registers must be in range r0-r7 or lr");
+    validateRegListOperands(Inst, Operands, 2);
     break;
   }
   case ARM::tSTMIA_UPD: {
@@ -6075,15 +6201,8 @@
       return Error(Operands[4]->getStartLoc(),
                    "registers must be in range r0-r7");
 
-    // This would be converted to a 32-bit stm, but that's not valid if the
-    // writeback register is in the list.
-    if (InvalidLowList && ListContainsBase)
-      return Error(Operands[4]->getStartLoc(),
-                   "writeback operator '!' not allowed when base register "
-                   "in register list");
-    if (listContainsReg(Inst, 4, ARM::SP) && !inITBlock())
-      return Error(Operands.back()->getStartLoc(),
-                   "SP not allowed in register list");
+    if (InvalidLowList)
+      validateRegListOperands(Inst, Operands, 4);
     break;
   }
   case ARM::tADDrSP: {
Index: test/MC/ARM/thumb-diagnostics.s
===================================================================
--- test/MC/ARM/thumb-diagnostics.s
+++ test/MC/ARM/thumb-diagnostics.s
@@ -68,6 +68,7 @@
         ldmfd r2!, {r1, r3-r6, sp}
         ldmdb r1, {r2, r3, sp}
         ldmdb r1!, {r2, r3, sp} 
+        ldm r2, {r5, lr, pc}
 @ CHECK-ERRORS: error: registers must be in range r0-r7
 @ CHECK-ERRORS:         ldm r2!, {r5, r8}
 @ CHECK-ERRORS:                  ^
@@ -104,16 +105,31 @@
 @ CHECK-ERRORS-V7M: error: SP not allowed in register list
 @ CHECK-ERRORS-V7M:         ldmdb r1!, {r2, r3, sp}
 @ CHECK-ERRORS-V7M:                    ^
+@ CHECK-ERRORS-V7M: error: LR not allowed in the list, when PC is in the register list
+@ CHECK-ERRORS-V7M:         ldm r2, {r5, lr, pc}
+@ CHECK-ERRORS-V7M:                 ^
 
 @ Invalid writeback and register lists for PUSH/POP
         pop {r1, r2, r10}
+        pop {r1, r2, lr, pc}
         push {r8, r9}
+        push {r8, r9, sp}
+        push {r8, r9, pc}
 @ CHECK-ERRORS: error: registers must be in range r0-r7 or pc
 @ CHECK-ERRORS:         pop {r1, r2, r10}
 @ CHECK-ERRORS:             ^
+@ CHECK-ERRORS-V7M: error: LR not allowed in the list, when PC is in the register list
+@ CHECK-ERRORS-V7M:         pop {r1, r2, lr, pc}
+@ CHECK-ERRORS-V7M:             ^
 @ CHECK-ERRORS: error: registers must be in range r0-r7 or lr
 @ CHECK-ERRORS:         push {r8, r9}
 @ CHECK-ERRORS:              ^
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
+@ CHECK-ERRORS-V7M:          push {r8, r9, sp}
+@ CHECK-ERRORS-V7M:               ^
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
+@ CHECK-ERRORS-V7M:          push {r8, r9, pc}
+@ CHECK-ERRORS-V7M:               ^
 
 
 @ Invalid writeback and register lists for STM
@@ -125,6 +141,8 @@
         stmia r4!, {r0-r3, sp}
         stmdb r1, {r2, r3, sp}
         stmdb r1!, {r2, r3, sp}
+        stmia r4, {r2, sp, pc}
+        stmdb r1!, {r2, r3, pc} 
 @ CHECK-ERRORS: error: instruction requires: thumb2
 @ CHECK-ERRORS:         stm r1, {r2, r6}
 @ CHECK-ERRORS:         ^
@@ -137,18 +155,24 @@
 @ CHECK-ERRORS-V8: error: writeback register not allowed in register list
 @ CHECK-ERRORS-V8:         stmdb r2!, {r0, r2}
 @ CHECK-ERRORS-V8:                  ^
-@ CHECK-ERRORS-V7M: error: SP not allowed in register list
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
 @ CHECK-ERRORS-V7M:         stm r1!, {r2, sp}
 @ CHECK-ERRORS-V7M:                  ^
-@ CHECK-ERRORS-V7M: error: SP not allowed in register list
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
 @ CHECK-ERRORS-V7M:         stmia r4!, {r0-r3, sp}
 @ CHECK-ERRORS-V7M:                    ^
-@ CHECK-ERRORS-V7M: error: SP not allowed in register list
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
 @ CHECK-ERRORS-V7M:         stmdb r1, {r2, r3, sp}
 @ CHECK-ERRORS-V7M:                   ^
-@ CHECK-ERRORS-V7M: error: SP not allowed in register list
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
 @ CHECK-ERRORS-V7M:         stmdb r1!, {r2, r3, sp}
 @ CHECK-ERRORS-V7M:                    ^
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
+@ CHECK-ERRORS-V7M:         stmia r4, {r2, sp, pc}
+@ CHECK-ERRORS-V7M:                   ^
+@ CHECK-ERRORS-V7M: error: SP, PC not allowed in register list
+@ CHECK-ERRORS-V7M:         stmdb r1!, {r2, r3, pc}
+@ CHECK-ERRORS-V7M:                    ^
 
 @ Out of range immediates for LSL instruction.
         lsls r4, r5, #-1
Index: test/MC/ARM/thumb2-diagnostics.s
===================================================================
--- test/MC/ARM/thumb2-diagnostics.s
+++ test/MC/ARM/thumb2-diagnostics.s
@@ -9,6 +9,9 @@
         iteeee gt
         ittfe le
         nopeq
+        ite eq
+        ldmiaeq sp!, {r4, pc}
+        movne r0, #0
 
 @ CHECK-ERRORS: error: incorrect condition in IT block; got 'le', but expected 'eq'
 @ CHECK-ERRORS:         addle r0, r1, r2
@@ -28,6 +31,9 @@
 @ CHECK-ERRORS: error: predicated instructions must be in IT block
 @ CHECK-ERRORS:         nopeq
 @ CHECK-ERRORS:         ^
+@ CHECK-ERRORS: error: Instruction should be outside an IT block or last in IT block, when PC is in the register list
+@ CHECK-ERRORS:         ldmiaeq sp!, {r4, pc}
+@ CHECK-ERRORS:                      ^
 
         @ Out of range immediates for MRC/MRC2/MRRC/MRRC2
         mrc  p14, #8, r1, c1, c2, #4
Index: test/MC/ARM/v8_IT_manual.s
===================================================================
--- test/MC/ARM/v8_IT_manual.s
+++ test/MC/ARM/v8_IT_manual.s
@@ -554,11 +554,11 @@
 @ PUSH, encoding T2 (32-bit)
 @ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 it ge
-pushge {r1, r13, r7}
+pushge {r1, r3, r7}
 @ PUSH, encoding T3 (32-bit)
 @ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 it ge
-pushge {r13}
+pushge {r3}
 
 @ REV, encoding T1
 @ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
@@ -614,9 +614,10 @@
 @ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 it ge
 stmge r1, {r2, r3}
+@ STM, encoding T3 (32-bit)
 @ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 it ge
-stmge r1!, {r2, r13}
+stmge r1!, {r2}
 
 @ LDM, encoding T1
 @ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block