Allow only disassembling of M-class MSR masks that the assembler knows how to assembl...
[oota-llvm.git] / lib / Target / ARM / Disassembler / ARMDisassembler.cpp
index 4d4038deac7c94f6a8558d1c3184f4b24a322fd2..48bcc9b2dcd03aba15b3338056e335d9d441b6fa 100644 (file)
@@ -3974,7 +3974,53 @@ static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Val,
 
 static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
                           uint64_t Address, const void *Decoder) {
-  if (!Val) return MCDisassembler::Fail;
+  uint64_t FeatureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
+                                                          .getFeatureBits();
+  if (FeatureBits & ARM::FeatureMClass) {
+    unsigned ValLow = Val & 0xff;
+
+    // Validate the SYSm value first.
+    switch (ValLow) {
+    case  0: // apsr
+    case  1: // iapsr
+    case  2: // eapsr
+    case  3: // xpsr
+    case  5: // ipsr
+    case  6: // epsr
+    case  7: // iepsr
+    case  8: // msp
+    case  9: // psp
+    case 16: // primask
+    case 20: // control
+      break;
+    case 17: // basepri
+    case 18: // basepri_max
+    case 19: // faultmask
+      if (!(FeatureBits & ARM::HasV7Ops))
+        // Values basepri, basepri_max and faultmask are only valid for v7m.
+        return MCDisassembler::Fail;
+      break;
+    default:
+      return MCDisassembler::Fail;
+    }
+
+    // The ARMv7-M architecture has an additional 2-bit mask value in the MSR
+    // instruction (bits {11,10}). The mask is used only with apsr, iapsr,
+    // eapsr and xpsr, it has to be 0b10 in other cases. Bit mask{1} indicates
+    // if the NZCVQ bits should be moved by the instruction. Bit mask{0}
+    // indicates the move for the GE{3:0} bits, the mask{0} bit can be set
+    // only if the processor includes the DSP extension.
+    if ((FeatureBits & ARM::HasV7Ops) && Inst.getOpcode() == ARM::t2MSR_M) {
+      unsigned Mask = (Val >> 10) & 3;
+      if (Mask == 0 || (Mask != 2 && ValLow > 3) ||
+          (!(FeatureBits & ARM::FeatureDSPThumb2) && Mask == 1))
+        return MCDisassembler::Fail;
+    }
+  } else {
+    // A/R class
+    if (Val == 0)
+      return MCDisassembler::Fail;
+  }
   Inst.addOperand(MCOperand::CreateImm(Val));
   return MCDisassembler::Success;
 }