Fix some remaining issues with decoding ARM-mode memory instructions, and add another...
[oota-llvm.git] / lib / Target / ARM / Disassembler / ARMDisassembler.cpp
index c9684e1f81cd7bd193cb28a5e51b6580db9a4b4e..5cebabc65b25cca77896fda3f52b11d7996b83da 100644 (file)
@@ -129,10 +129,18 @@ static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
 static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
-static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Insn,
-                               uint64_t Address, const void *Decoder);
 static bool DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Insn,
                                uint64_t Address, const void *Decoder);
+static bool DecodeMSRMask(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
+static bool DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
+static bool DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
+static bool DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
+static bool DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
+                               uint64_t Address, const void *Decoder);
 
 
 static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
@@ -249,12 +257,32 @@ bool ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
   }
 
   MI.clear();
-  result = decodeNEONInstruction32(MI, insn, Address, this);
+  result = decodeNEONDataInstruction32(MI, insn, Address, this);
   if (result) {
+    Size = 4;
     // Add a fake predicate operand, because we share these instruction
     // definitions with Thumb2 where these instructions are predicable.
     if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false;
+    return true;
+  }
+
+  MI.clear();
+  result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this);
+  if (result) {
     Size = 4;
+    // Add a fake predicate operand, because we share these instruction
+    // definitions with Thumb2 where these instructions are predicable.
+    if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false;
+    return true;
+  }
+
+  MI.clear();
+  result = decodeNEONDupInstruction32(MI, insn, Address, this);
+  if (result) {
+    Size = 4;
+    // Add a fake predicate operand, because we share these instruction
+    // definitions with Thumb2 where these instructions are predicable.
+    if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false;
     return true;
   }
 
@@ -433,6 +461,14 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
     return true;
   }
 
+  MI.clear();
+  result = decodeCommonInstruction32(MI, insn32, Address, this);
+  if (result) {
+    Size = 4;
+    AddThumbPredicate(MI);
+    return true;
+  }
+
   MI.clear();
   result = decodeVFPInstruction32(MI, insn32, Address, this);
   if (result) {
@@ -442,7 +478,29 @@ bool ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
   }
 
   MI.clear();
-  result = decodeCommonInstruction32(MI, insn32, Address, this);
+  if (fieldFromInstruction32(insn32, 24, 4) == 0xF) {
+    uint32_t NEONDataInsn = insn32;
+    NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24
+    NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24
+    NEONDataInsn |= 0x12000000; // Set bits 28 and 25
+    result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this);
+    if (result) {
+      Size = 4;
+      AddThumbPredicate(MI);
+      return true;
+    }
+  }
+
+  MI.clear();
+  result = decodeNEONLoadStoreInstruction32(MI, insn32, Address, this);
+  if (result) {
+    Size = 4;
+    AddThumbPredicate(MI);
+    return true;
+  }
+
+  MI.clear();
+  result = decodeNEONDupInstruction32(MI, insn32, Address, this);
   if (result) {
     Size = 4;
     AddThumbPredicate(MI);
@@ -648,7 +706,7 @@ static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Val,
   unsigned imm = fieldFromInstruction32(Val, 7, 5);
 
   // Register-immediate
-  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
 
   ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
   switch (type) {
@@ -709,9 +767,12 @@ static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Val,
 
 static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
                                  uint64_t Address, const void *Decoder) {
+  // Empty register lists are not allowed.
+  if (CountPopulation_32(Val) == 0) return false;
   for (unsigned i = 0; i < 16; ++i) {
-    if (Val & (1 << i))
-      DecodeGPRRegisterClass(Inst, i, Address, Decoder);
+    if (Val & (1 << i)) {
+      if (!DecodeGPRRegisterClass(Inst, i, Address, Decoder)) return false;
+    }
   }
 
   return true;
@@ -722,9 +783,10 @@ static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
   unsigned Vd = fieldFromInstruction32(Val, 8, 4);
   unsigned regs = Val & 0xFF;
 
-  DecodeSPRRegisterClass(Inst, Vd, Address, Decoder);
-  for (unsigned i = 0; i < (regs - 1); ++i)
-    DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder);
+  if (!DecodeSPRRegisterClass(Inst, Vd, Address, Decoder)) return false;
+  for (unsigned i = 0; i < (regs - 1); ++i) {
+    if (!DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder)) return false;
+  }
 
   return true;
 }
@@ -734,9 +796,10 @@ static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
   unsigned Vd = fieldFromInstruction32(Val, 8, 4);
   unsigned regs = (Val & 0xFF) / 2;
 
-  DecodeDPRRegisterClass(Inst, Vd, Address, Decoder);
-  for (unsigned i = 0; i < (regs - 1); ++i)
-    DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Vd, Address, Decoder)) return false;
+  for (unsigned i = 0; i < (regs - 1); ++i) {
+    if (!DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder)) return false;
+  }
 
   return true;
 }
@@ -791,7 +854,7 @@ static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
 
   Inst.addOperand(MCOperand::CreateImm(coproc));
   Inst.addOperand(MCOperand::CreateImm(CRd));
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   switch (Inst.getOpcode()) {
     case ARM::LDC_OPTION:
     case ARM::LDCL_OPTION:
@@ -884,34 +947,40 @@ static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
   switch (Inst.getOpcode()) {
     case ARM::STR_POST_IMM:
     case ARM::STR_POST_REG:
-    case ARM::STRTr:
-    case ARM::STRTi:
-    case ARM::STRBTr:
-    case ARM::STRBTi:
-      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+    case ARM::STRB_POST_IMM:
+    case ARM::STRB_POST_REG:
+    case ARM::STRT_POST_REG:
+    case ARM::STRT_POST_IMM:
+    case ARM::STRBT_POST_REG:
+    case ARM::STRBT_POST_IMM:
+      if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
       break;
     default:
       break;
   }
 
-  DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)) return false;
 
   // On loads, the writeback operand comes after Rt.
   switch (Inst.getOpcode()) {
     case ARM::LDR_POST_IMM:
     case ARM::LDR_POST_REG:
+    case ARM::LDRB_POST_IMM:
+    case ARM::LDRB_POST_REG:
     case ARM::LDR_PRE:
+    case ARM::LDRB_PRE:
     case ARM::LDRBT_POST_REG:
     case ARM::LDRBT_POST_IMM:
-    case ARM::LDRTr:
-    case ARM::LDRTi:
-      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+    case ARM::LDRT_POST_REG:
+    case ARM::LDRT_POST_IMM:
+      if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))
+        return false;
       break;
     default:
       break;
   }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
 
   ARM_AM::AddrOpc Op = ARM_AM::add;
   if (!fieldFromInstruction32(Insn, 23, 1))
@@ -924,8 +993,10 @@ static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
   else if (!P && writeback)
     idx_mode = ARMII::IndexModePost;
 
+  if (writeback && (Rn == 15 || Rn == Rt)) return false; // UNPREDICTABLE
+
   if (reg) {
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+    if (!DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)) return false;
     ARM_AM::ShiftOpc Opc = ARM_AM::lsl;
     switch( fieldFromInstruction32(Insn, 5, 2)) {
       case 0:
@@ -982,8 +1053,8 @@ static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Val,
       break;
   }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
-  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
   unsigned shift;
   if (U)
     shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp);
@@ -1018,14 +1089,19 @@ static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::STRD:
     case ARM::STRD_PRE:
     case ARM::STRD_POST:
-      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+    case ARM::STRH:
+    case ARM::STRH_PRE:
+    case ARM::STRH_POST:
+      if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))
+        return false;
       break;
     default:
       break;
     }
   }
 
-  DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder))
+    return false;
   switch (Inst.getOpcode()) {
     case ARM::STRD:
     case ARM::STRD_PRE:
@@ -1033,7 +1109,8 @@ static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::LDRD:
     case ARM::LDRD_PRE:
     case ARM::LDRD_POST:
-      DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder);
+      if (!DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder))
+        return false;
       break;
     default:
       break;
@@ -1045,22 +1122,34 @@ static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::LDRD:
     case ARM::LDRD_PRE:
     case ARM::LDRD_POST:
+    case ARM::LDRH:
+    case ARM::LDRH_PRE:
+    case ARM::LDRH_POST:
+    case ARM::LDRSH:
+    case ARM::LDRSH_PRE:
+    case ARM::LDRSH_POST:
+    case ARM::LDRSB:
+    case ARM::LDRSB_PRE:
+    case ARM::LDRSB_POST:
     case ARM::LDRHTr:
     case ARM::LDRSBTr:
-      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+      if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))
+        return false;
       break;
     default:
       break;
     }
   }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))
+    return false;
 
   if (type) {
     Inst.addOperand(MCOperand::CreateReg(0));
     Inst.addOperand(MCOperand::CreateImm(U | (imm << 4) | Rm));
   } else {
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))
+      return false;
     Inst.addOperand(MCOperand::CreateImm(U));
   }
 
@@ -1090,7 +1179,7 @@ static bool DecodeRFEInstruction(llvm::MCInst &Inst, unsigned Insn,
   }
 
   Inst.addOperand(MCOperand::CreateImm(mode));
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
 
   return true;
 }
@@ -1132,10 +1221,11 @@ static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst &Inst,
     return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
   }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); // Tied
-  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
-  DecodeRegListOperand(Inst, reglist, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)   ||
+      !DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)   || // Tied
+      !DecodePredicateOperand(Inst, pred, Address, Decoder) ||
+      !DecodeRegListOperand(Inst, reglist, Address, Decoder))
+    return false;
 
   return true;
 }
@@ -1181,10 +1271,13 @@ static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
   if (pred == 0xF)
     return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
 
-  DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder);
-  DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder);
-  DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder);
-  DecodeGPRnopcRegisterClass(Inst, Ra, Address, Decoder);
+  if (!DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder) ||
+      !DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder) ||
+      !DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder) ||
+      !DecodeGPRnopcRegisterClass(Inst, Ra, Address, Decoder))
+    return false;
+
+  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
 
   return true;
 }
@@ -1195,7 +1288,8 @@ static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
   unsigned imm = fieldFromInstruction32(Val, 0, 12);
   unsigned Rn = fieldFromInstruction32(Val, 13, 4);
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))
+    return false;
 
   if (!add) imm *= -1;
   if (imm == 0 && !add) imm = INT32_MIN;
@@ -1210,7 +1304,8 @@ static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
   unsigned U = fieldFromInstruction32(Val, 8, 1);
   unsigned imm = fieldFromInstruction32(Val, 0, 8);
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))
+    return false;
 
   if (U)
     Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, imm)));
@@ -1255,7 +1350,8 @@ static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
   unsigned Rm = fieldFromInstruction32(Val, 0, 4);
   unsigned align = fieldFromInstruction32(Val, 4, 2);
 
-  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))
+    return false;
   if (!align)
     Inst.addOperand(MCOperand::CreateImm(0));
   else
@@ -1274,7 +1370,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
   unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
 
   // First output register
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
 
   // Second output register
   switch (Inst.getOpcode()) {
@@ -1326,7 +1422,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4d8_UPD:
     case ARM::VLD4d16_UPD:
     case ARM::VLD4d32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)) return false;
       break;
     case ARM::VLD2b8:
     case ARM::VLD2b16:
@@ -1346,7 +1442,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4q8_UPD:
     case ARM::VLD4q16_UPD:
     case ARM::VLD4q32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)) return false;
     default:
       break;
   }
@@ -1387,7 +1483,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4d8_UPD:
     case ARM::VLD4d16_UPD:
     case ARM::VLD4d32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)) return false;
       break;
     case ARM::VLD3q8:
     case ARM::VLD3q16:
@@ -1401,7 +1497,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4q8_UPD:
     case ARM::VLD4q16_UPD:
     case ARM::VLD4q32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder)) return false;
       break;
     default:
       break;
@@ -1429,7 +1525,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4d8_UPD:
     case ARM::VLD4d16_UPD:
     case ARM::VLD4d32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder)) return false;
       break;
     case ARM::VLD4q8:
     case ARM::VLD4q16:
@@ -1437,7 +1533,7 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4q8_UPD:
     case ARM::VLD4q16_UPD:
     case ARM::VLD4q32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder)) return false;
       break;
     default:
       break;
@@ -1482,20 +1578,22 @@ static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VLD4q8_UPD:
     case ARM::VLD4q16_UPD:
     case ARM::VLD4q32_UPD:
-      DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
+      if (!DecodeGPRRegisterClass(Inst, wb, Address, Decoder)) return false;
       break;
     default:
       break;
   }
 
   // AddrMode6 Base (register+alignment)
-  DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
+  if (!DecodeAddrMode6Operand(Inst, Rn, Address, Decoder)) return false;
 
   // AddrMode6 Offset (register)
   if (Rm == 0xD)
     Inst.addOperand(MCOperand::CreateReg(0));
-  else if (Rm != 0xF)
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  else if (Rm != 0xF) {
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))
+      return false;
+  }
 
   return true;
 }
@@ -1548,23 +1646,25 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4q8_UPD:
     case ARM::VST4q16_UPD:
     case ARM::VST4q32_UPD:
-      DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
+      if (!DecodeGPRRegisterClass(Inst, wb, Address, Decoder))
+        return false;
       break;
     default:
       break;
   }
 
   // AddrMode6 Base (register+alignment)
-  DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
+  if (!DecodeAddrMode6Operand(Inst, Rn, Address, Decoder)) return false;
 
   // AddrMode6 Offset (register)
   if (Rm == 0xD)
     Inst.addOperand(MCOperand::CreateReg(0));
-  else if (Rm != 0xF)
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  else if (Rm != 0xF) {
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
+  }
 
   // First input register
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
 
   // Second input register
   switch (Inst.getOpcode()) {
@@ -1616,7 +1716,7 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4d8_UPD:
     case ARM::VST4d16_UPD:
     case ARM::VST4d32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)) return false;
       break;
     case ARM::VST2b8:
     case ARM::VST2b16:
@@ -1636,7 +1736,7 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4q8_UPD:
     case ARM::VST4q16_UPD:
     case ARM::VST4q32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)) return false;
       break;
     default:
       break;
@@ -1678,7 +1778,7 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4d8_UPD:
     case ARM::VST4d16_UPD:
     case ARM::VST4d32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder)) return false;
       break;
     case ARM::VST3q8:
     case ARM::VST3q16:
@@ -1692,7 +1792,7 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4q8_UPD:
     case ARM::VST4q16_UPD:
     case ARM::VST4q32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder)) return false;
       break;
     default:
       break;
@@ -1720,7 +1820,7 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4d8_UPD:
     case ARM::VST4d16_UPD:
     case ARM::VST4d32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder)) return false;
       break;
     case ARM::VST4q8:
     case ARM::VST4q16:
@@ -1728,7 +1828,7 @@ static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VST4q8_UPD:
     case ARM::VST4q16_UPD:
     case ARM::VST4q32_UPD:
-      DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder)) return false;
       break;
     default:
       break;
@@ -1749,17 +1849,22 @@ static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Insn,
 
   align *= (1 << size);
 
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
-  if (regs == 2) DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
-  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+  if (regs == 2) {
+    if (!DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder)) return false;
+  }
+  if (Rm == 0xD) {
+    if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(align));
 
   if (Rm == 0xD)
     Inst.addOperand(MCOperand::CreateReg(0));
-  else if (Rm != 0xF)
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  else if (Rm != 0xF) {
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
+  }
 
   return true;
 }
@@ -1775,17 +1880,20 @@ static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Insn,
   unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
   align *= 2*size;
 
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
-  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+  if (!DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)) return false;
+  if (Rm == 0xD) {
+    if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(align));
 
   if (Rm == 0xD)
     Inst.addOperand(MCOperand::CreateReg(0));
-  else if (Rm != 0xF)
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  else if (Rm != 0xF) {
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
+  }
 
   return true;
 }
@@ -1798,18 +1906,22 @@ static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Insn,
   unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
   unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
 
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
-  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)          ||
+      !DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder) ||
+      !DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder))
+    return false;
+  if (Rm == 0xD) {
+    if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(0));
 
   if (Rm == 0xD)
     Inst.addOperand(MCOperand::CreateReg(0));
-  else if (Rm != 0xF)
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  else if (Rm != 0xF) {
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
+  }
 
   return true;
 }
@@ -1837,19 +1949,23 @@ static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Insn,
     }
   }
 
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder);
-  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)            ||
+      !DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder)   ||
+      !DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder) ||
+      !DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder))
+    return false;
+  if (Rm == 0xD) {
+    if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(align));
 
   if (Rm == 0xD)
     Inst.addOperand(MCOperand::CreateReg(0));
-  else if (Rm != 0xF)
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  else if (Rm != 0xF) {
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
+  }
 
   return true;
 }
@@ -1865,10 +1981,11 @@ static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn,
   imm |= fieldFromInstruction32(Insn, 5, 1) << 12;
   unsigned Q = fieldFromInstruction32(Insn, 6, 1);
 
-  if (Q)
-    DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
-  else
-    DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
+  if (Q) {
+    if (!DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+  } else {
+    if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+  }
 
   Inst.addOperand(MCOperand::CreateImm(imm));
 
@@ -1877,13 +1994,13 @@ static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn,
     case ARM::VORRiv2i32:
     case ARM::VBICiv4i16:
     case ARM::VBICiv2i32:
-      DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
+      if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
       break;
     case ARM::VORRiv8i16:
     case ARM::VORRiv4i32:
     case ARM::VBICiv8i16:
     case ARM::VBICiv4i32:
-      DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
+      if (!DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
       break;
     default:
       break;
@@ -1900,8 +2017,8 @@ static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Insn,
   Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
   unsigned size = fieldFromInstruction32(Insn, 18, 2);
 
-  DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
-  DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeQPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+  if (!DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(8 << size));
 
   return true;
@@ -1942,13 +2059,16 @@ static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
   unsigned op = fieldFromInstruction32(Insn, 6, 1);
   unsigned length = fieldFromInstruction32(Insn, 8, 2) + 1;
 
-  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
-  if (op) DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); // Writeback
+  if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+  if (op) {
+    if (!DecodeDPRRegisterClass(Inst, Rd, Address, Decoder)) return false; // Writeback
+  }
 
-  for (unsigned i = 0; i < length; ++i)
-    DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder);
+  for (unsigned i = 0; i < length; ++i) {
+    if (!DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder)) return false;
+  }
 
-  DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
 
   return true;
 }
@@ -1983,7 +2103,7 @@ static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
   unsigned dst = fieldFromInstruction16(Insn, 8, 3);
   unsigned imm = fieldFromInstruction16(Insn, 0, 8);
 
-  DecodetGPRRegisterClass(Inst, dst, Address, Decoder);
+  if (!DecodetGPRRegisterClass(Inst, dst, Address, Decoder)) return false;
 
   if (Inst.getOpcode() == ARM::tADR)
     Inst.addOperand(MCOperand::CreateReg(ARM::PC));
@@ -2019,8 +2139,9 @@ static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
   unsigned Rn = fieldFromInstruction32(Val, 0, 3);
   unsigned Rm = fieldFromInstruction32(Val, 3, 3);
 
-  DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
-  DecodetGPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodetGPRRegisterClass(Inst, Rn, Address, Decoder) ||
+      !DecodetGPRRegisterClass(Inst, Rm, Address, Decoder))
+    return false;
 
   return true;
 }
@@ -2030,7 +2151,7 @@ static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
   unsigned Rn = fieldFromInstruction32(Val, 0, 3);
   unsigned imm = fieldFromInstruction32(Val, 3, 5);
 
-  DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodetGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(imm));
 
   return true;
@@ -2057,8 +2178,9 @@ static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
   unsigned Rm = fieldFromInstruction32(Val, 2, 4);
   unsigned imm = fieldFromInstruction32(Val, 0, 2);
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
-  DecoderGPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder) ||
+      !DecoderGPRRegisterClass(Inst, Rm, Address, Decoder))
+    return false;
   Inst.addOperand(MCOperand::CreateImm(imm));
 
   return true;
@@ -2068,7 +2190,7 @@ static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Insn,
                               uint64_t Address, const void *Decoder) {
   if (Inst.getOpcode() != ARM::t2PLDs) {
     unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
-    DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
+    if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)) return false;
   }
 
   unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
@@ -2123,8 +2245,9 @@ static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
   unsigned Rn = fieldFromInstruction32(Val, 9, 4);
   unsigned imm = fieldFromInstruction32(Val, 0, 9);
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
-  DecodeT2Imm8S4(Inst, imm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder) ||
+      !DecodeT2Imm8S4(Inst, imm, Address, Decoder))
+    return false;
 
   return true;
 }
@@ -2157,8 +2280,9 @@ static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
       break;
   }
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
-  DecodeT2Imm8(Inst, imm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder) ||
+      !DecodeT2Imm8(Inst, imm, Address, Decoder))
+    return false;
 
   return true;
 }
@@ -2169,7 +2293,7 @@ static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
   unsigned Rn = fieldFromInstruction32(Val, 13, 4);
   unsigned imm = fieldFromInstruction32(Val, 0, 12);
 
-  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(imm));
 
   return true;
@@ -2193,15 +2317,15 @@ static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
     unsigned Rdm = fieldFromInstruction16(Insn, 0, 3);
     Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3;
 
-    DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
+    if (!DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder)) return false;
     Inst.addOperand(MCOperand::CreateReg(ARM::SP));
-    DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
+    if (!DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder)) return false;
   } else if (Inst.getOpcode() == ARM::tADDspr) {
     unsigned Rm = fieldFromInstruction16(Insn, 3, 4);
 
     Inst.addOperand(MCOperand::CreateReg(ARM::SP));
     Inst.addOperand(MCOperand::CreateReg(ARM::SP));
-    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+    if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
   }
 
   return true;
@@ -2223,7 +2347,7 @@ static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
   unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
   unsigned add = fieldFromInstruction32(Insn, 4, 1);
 
-  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
+  if (!DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)) return false;
   Inst.addOperand(MCOperand::CreateImm(add));
 
   return true;
@@ -2282,8 +2406,8 @@ static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn,
   brtarget |= fieldFromInstruction32(Insn, 16, 6) << 12;
   brtarget |= fieldFromInstruction32(Insn, 26, 1) << 20;
 
-  DecodeT2BROperand(Inst, brtarget, Address, Decoder);
-  if (!DecodePredicateOperand(Inst, pred, Address, Decoder))
+  if (!DecodeT2BROperand(Inst, brtarget, Address, Decoder) ||
+      !DecodePredicateOperand(Inst, pred, Address, Decoder))
     return false;
 
   return true;
@@ -2335,23 +2459,6 @@ static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
   return true;
 }
 
-static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Val,
-                                  uint64_t Address, const void *Decoder) {
-  bool isImm = fieldFromInstruction32(Val, 9, 1);
-  bool isAdd = fieldFromInstruction32(Val, 8, 1);
-  unsigned imm = fieldFromInstruction32(Val, 0, 8);
-
-  if (!isImm) {
-    DecodeGPRRegisterClass(Inst, imm, Address, Decoder);
-    Inst.addOperand(MCOperand::CreateImm(!isAdd << 8));
-  } else {
-    Inst.addOperand(MCOperand::CreateReg(0));
-    Inst.addOperand(MCOperand::CreateImm(imm | (!isAdd << 8)));
-  }
-
-  return true;
-}
-
 static bool DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Val,
                                    uint64_t Address, const void *Decoder) {
   switch (Val) {
@@ -2372,3 +2479,84 @@ static bool DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Val,
   return true;
 }
 
+static bool DecodeMSRMask(llvm::MCInst &Inst, unsigned Val,
+                          uint64_t Address, const void *Decoder) {
+  if (!Val) return false;
+  Inst.addOperand(MCOperand::CreateImm(Val));
+  return true;
+}
+
+static bool DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
+                                          uint64_t Address, const void *Decoder) {
+  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+  if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return false;
+
+  if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
+
+  return true;
+}
+
+
+static bool DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
+                                          uint64_t Address, const void *Decoder) {
+  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
+  unsigned Rt = fieldFromInstruction32(Insn, 0, 4);
+  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+  if (!DecoderGPRRegisterClass(Inst, Rd, Address, Decoder)) return false;
+
+  if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return false;
+  if (Rd == Rn || Rd == Rt || Rd == Rt+1) return false;
+
+  if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
+
+  return true;
+}
+
+static bool DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
+                            uint64_t Address, const void *Decoder) {
+  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+  unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+  imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
+  imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
+  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+  if (Rn == 0xF || Rn == Rt) return false; // UNPREDICTABLE
+
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)) return false;
+  if (!DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder)) return false;
+  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
+
+  return true;
+}
+
+static bool DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
+                            uint64_t Address, const void *Decoder) {
+  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
+  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
+  unsigned imm = fieldFromInstruction32(Insn, 0, 12);
+  imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
+  imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
+  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
+
+  if (Rn == 0xF || Rn == Rt) return false; // UNPREDICTABLE
+
+  if (!DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)) return false;
+  if (!DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)) return false;
+  if (!DecodeSORegMemOperand(Inst, imm, Address, Decoder)) return false;
+  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
+
+  return true;
+}