Index: lib/Target/ARM/Disassembler/ARMDisassembler.cpp =================================================================== --- lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -3974,7 +3974,53 @@ 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; } Index: test/MC/Disassembler/ARM/invalid-thumb-MSR-MClass.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/ARM/invalid-thumb-MSR-MClass.txt @@ -0,0 +1,34 @@ +# RUN: not llvm-mc -disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m3 2>&1 | FileCheck %s + +#------------------------------------------------------------------------------ +# Undefined encodings for mrs +#------------------------------------------------------------------------------ + +# invalid SYSm +# CHECK: warning: invalid instruction encoding +# CHECK-NEXT: [0xef 0xf3 0x80 0x80] +[0xef 0xf3 0x80 0x80] + +#------------------------------------------------------------------------------ +# Undefined encodings for msr +#------------------------------------------------------------------------------ + +# invalid mask = '00' +# CHECK: warning: invalid instruction encoding +# CHECK-NEXT: [0x80 0xf3 0x00 0x80] +[0x80 0xf3 0x00 0x80] + +# invalid mask = '11' with SYSm not in {0..3} +# CHECK: warning: invalid instruction encoding +# CHECK-NEXT: [0x80 0xf3 0x04 0x8c] +[0x80 0xf3 0x04 0x8c] + +# invalid mask = '01' (Cortex-M3 does not have the DSP extension) +# CHECK: warning: invalid instruction encoding +# CHECK-NEXT: [0x80 0xf3 0x00 0x84] +[0x80 0xf3 0x00 0x84] + +# invalid SYSm +# CHECK: warning: invalid instruction encoding +# CHECK-NEXT: [0x80 0xf3 0x80 0x88] +[0x80 0xf3 0x80 0x88] Index: test/MC/Disassembler/ARM/thumb-MSR-MClass.txt =================================================================== --- test/MC/Disassembler/ARM/thumb-MSR-MClass.txt +++ test/MC/Disassembler/ARM/thumb-MSR-MClass.txt @@ -1,7 +1,94 @@ -# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m3 | FileCheck %s +# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m4 | FileCheck %s -# CHECK: msr primask, r0 -0x80 0xf3 0x10 0x80 +#------------------------------------------------------------------------------ +# MRS +#------------------------------------------------------------------------------ -# CHECK: mrs r0, primask +# CHECK: mrs r0, apsr +# CHECK: mrs r0, iapsr +# CHECK: mrs r0, eapsr +# CHECK: mrs r0, xpsr +# CHECK: mrs r0, ipsr +# CHECK: mrs r0, epsr +# CHECK: mrs r0, iepsr +# CHECK: mrs r0, msp +# CHECK: mrs r0, psp +# CHECK: mrs r0, primask +# CHECK: mrs r0, basepri +# CHECK: mrs r0, basepri_max +# CHECK: mrs r0, faultmask +# CHECK: mrs r0, control + +0xef 0xf3 0x00 0x80 +0xef 0xf3 0x01 0x80 +0xef 0xf3 0x02 0x80 +0xef 0xf3 0x03 0x80 +0xef 0xf3 0x05 0x80 +0xef 0xf3 0x06 0x80 +0xef 0xf3 0x07 0x80 +0xef 0xf3 0x08 0x80 +0xef 0xf3 0x09 0x80 0xef 0xf3 0x10 0x80 +0xef 0xf3 0x11 0x80 +0xef 0xf3 0x12 0x80 +0xef 0xf3 0x13 0x80 +0xef 0xf3 0x14 0x80 + + +#------------------------------------------------------------------------------ +# MSR +#------------------------------------------------------------------------------ + +# CHECK: msr apsr, r0 +# CHECK: msr apsr_g, r0 +# CHECK: msr apsr_nzcvqg, r0 + +0x80 0xf3 0x00 0x88 +0x80 0xf3 0x00 0x84 +0x80 0xf3 0x00 0x8c + +# CHECK: msr iapsr, r0 +# CHECK: msr iapsr_g, r0 +# CHECK: msr iapsr_nzcvqg, r0 + +0x80 0xf3 0x01 0x88 +0x80 0xf3 0x01 0x84 +0x80 0xf3 0x01 0x8c + +# CHECK: msr eapsr, r0 +# CHECK: msr eapsr_g, r0 +# CHECK: msr eapsr_nzcvqg, r0 + +0x80 0xf3 0x02 0x88 +0x80 0xf3 0x02 0x84 +0x80 0xf3 0x02 0x8c + +# CHECK: msr xpsr, r0 +# CHECK: msr xpsr_g, r0 +# CHECK: msr xpsr_nzcvqg, r0 + +0x80 0xf3 0x03 0x88 +0x80 0xf3 0x03 0x84 +0x80 0xf3 0x03 0x8c + +# CHECK: msr ipsr, r0 +# CHECK: msr epsr, r0 +# CHECK: msr iepsr, r0 +# CHECK: msr msp, r0 +# CHECK: msr psp, r0 +# CHECK: msr primask, r0 +# CHECK: msr basepri, r0 +# CHECK: msr basepri_max, r0 +# CHECK: msr faultmask, r0 +# CHECK: msr control, r0 + +0x80 0xf3 0x05 0x88 +0x80 0xf3 0x06 0x88 +0x80 0xf3 0x07 0x88 +0x80 0xf3 0x08 0x88 +0x80 0xf3 0x09 0x88 +0x80 0xf3 0x10 0x88 +0x80 0xf3 0x11 0x88 +0x80 0xf3 0x12 0x88 +0x80 0xf3 0x13 0x88 +0x80 0xf3 0x14 0x88