Thumb2 M-class MSR instruction support changes

This patch implements a few changes related to the Thumb2 M-class MSR instruction:
 * better handling of unpredictable encodings,
 * recognition of the _g and _nzcvqg variants by the asm parser only if the DSP
   extension is available, preferred output of MSR APSR moves with the _<bits>
   suffix for v7-M.

Patch by Petr Pavlu.

llvm-svn: 216874
This commit is contained in:
Renato Golin 2014-09-01 11:25:07 +00:00
parent 58aa72df97
commit 2400e22c37
8 changed files with 174 additions and 102 deletions

View File

@ -4013,15 +4013,17 @@ def t2MRSbanked : T2I<(outs rGPR:$Rd), (ins banked_reg:$banked),
//
// This MRS has a mask field in bits 7-0 and can take more values than
// the A/R class (a full msr_mask).
def t2MRS_M : T2I<(outs rGPR:$Rd), (ins msr_mask:$mask), NoItinerary,
"mrs", "\t$Rd, $mask", []>,
def t2MRS_M : T2I<(outs rGPR:$Rd), (ins msr_mask:$SYSm), NoItinerary,
"mrs", "\t$Rd, $SYSm", []>,
Requires<[IsThumb,IsMClass]> {
bits<4> Rd;
bits<8> mask;
bits<8> SYSm;
let Inst{31-12} = 0b11110011111011111000;
let Inst{11-8} = Rd;
let Inst{19-16} = 0b1111;
let Inst{7-0} = mask;
let Inst{7-0} = SYSm;
let Unpredictable{20-16} = 0b11111;
let Unpredictable{13} = 0b1;
}
@ -4077,7 +4079,13 @@ def t2MSR_M : T2I<(outs), (ins msr_mask:$SYSm, rGPR:$Rn),
let Inst{20} = 0b0;
let Inst{19-16} = Rn;
let Inst{15-12} = 0b1000;
let Inst{11-0} = SYSm;
let Inst{11-10} = SYSm{11-10};
let Inst{9-8} = 0b00;
let Inst{7-0} = SYSm{7-0};
let Unpredictable{20} = 0b1;
let Unpredictable{13} = 0b1;
let Unpredictable{9-8} = 0b11;
}

View File

@ -265,6 +265,9 @@ class ARMAsmParser : public MCTargetAsmParser {
bool hasARM() const {
return !(STI.getFeatureBits() & ARM::FeatureNoARM);
}
bool hasThumb2DSP() const {
return STI.getFeatureBits() & ARM::FeatureDSPThumb2;
}
void SwitchMode() {
uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
@ -3928,9 +3931,6 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) {
// should really only be allowed when writing a special register. Note
// they get dropped in the MRS instruction reading a special register as
// the SYSm field is only 8 bits.
//
// FIXME: the _g and _nzcvqg versions are only allowed if the processor
// includes the DSP extension but that is not checked.
.Case("apsr", 0x800)
.Case("apsr_nzcvq", 0x800)
.Case("apsr_g", 0x400)
@ -3962,6 +3962,11 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) {
if (FlagsVal == ~0U)
return MatchOperand_NoMatch;
if (!hasThumb2DSP() && (FlagsVal & 0x400))
// The _g and _nzcvqg versions are only valid if the DSP extension is
// available.
return MatchOperand_NoMatch;
if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813)
// basepri, basepri_max and faultmask only valid for V7m.
return MatchOperand_NoMatch;

View File

@ -3976,6 +3976,7 @@ static DecodeStatus DecodeInstSyncBarrierOption(MCInst &Inst, unsigned Val,
static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
uint64_t FeatureBits = ((const MCDisassembler*)Decoder)->getSubtargetInfo()
.getFeatureBits();
if (FeatureBits & ARM::FeatureMClass) {
@ -4006,17 +4007,25 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
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;
if (Inst.getOpcode() == ARM::t2MSR_M) {
unsigned Mask = fieldFromInstruction(Val, 10, 2);
if (!(FeatureBits & ARM::HasV7Ops)) {
// The ARMv6-M MSR bits {11-10} can be only 0b10, other values are
// unpredictable.
if (Mask != 2)
S = MCDisassembler::SoftFail;
}
else {
// The ARMv7-M architecture stores an additional 2-bit mask value in
// MSR 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 (Mask == 0 || (Mask != 2 && ValLow > 3) ||
(!(FeatureBits & ARM::FeatureDSPThumb2) && (Mask & 1)))
S = MCDisassembler::SoftFail;
}
}
} else {
// A/R class
@ -4024,7 +4033,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val,
return MCDisassembler::Fail;
}
Inst.addOperand(MCOperand::CreateImm(Val));
return MCDisassembler::Success;
return S;
}
static DecodeStatus DecodeBankedReg(MCInst &Inst, unsigned Val,

View File

@ -807,52 +807,56 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
const MCOperand &Op = MI->getOperand(OpNum);
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
uint64_t FeatureBits = getAvailableFeatures();
if (getAvailableFeatures() & ARM::FeatureMClass) {
if (FeatureBits & ARM::FeatureMClass) {
unsigned SYSm = Op.getImm();
unsigned Opcode = MI->getOpcode();
// For reads of the special registers ignore the "mask encoding" bits
// which are only for writes.
if (Opcode == ARM::t2MRS_M)
SYSm &= 0xff;
// For writes, handle extended mask bits if the DSP extension is present.
if (Opcode == ARM::t2MSR_M && (FeatureBits & ARM::FeatureDSPThumb2)) {
switch (SYSm) {
case 0x400: O << "apsr_g"; return;
case 0xc00: O << "apsr_nzcvqg"; return;
case 0x401: O << "iapsr_g"; return;
case 0xc01: O << "iapsr_nzcvqg"; return;
case 0x402: O << "eapsr_g"; return;
case 0xc02: O << "eapsr_nzcvqg"; return;
case 0x403: O << "xpsr_g"; return;
case 0xc03: O << "xpsr_nzcvqg"; return;
}
}
// Handle the basic 8-bit mask.
SYSm &= 0xff;
if (Opcode == ARM::t2MSR_M && (FeatureBits & ARM::HasV7Ops)) {
// ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
// alias for MSR APSR_nzcvq.
switch (SYSm) {
case 0: O << "apsr_nzcvq"; return;
case 1: O << "iapsr_nzcvq"; return;
case 2: O << "eapsr_nzcvq"; return;
case 3: O << "xpsr_nzcvq"; return;
}
}
switch (SYSm) {
default: llvm_unreachable("Unexpected mask value!");
case 0:
case 0x800: O << "apsr"; return; // with _nzcvq bits is an alias for aspr
case 0x400: O << "apsr_g"; return;
case 0xc00: O << "apsr_nzcvqg"; return;
case 1:
case 0x801: O << "iapsr"; return; // with _nzcvq bits is an alias for iapsr
case 0x401: O << "iapsr_g"; return;
case 0xc01: O << "iapsr_nzcvqg"; return;
case 2:
case 0x802: O << "eapsr"; return; // with _nzcvq bits is an alias for eapsr
case 0x402: O << "eapsr_g"; return;
case 0xc02: O << "eapsr_nzcvqg"; return;
case 3:
case 0x803: O << "xpsr"; return; // with _nzcvq bits is an alias for xpsr
case 0x403: O << "xpsr_g"; return;
case 0xc03: O << "xpsr_nzcvqg"; return;
case 5:
case 0x805: O << "ipsr"; return;
case 6:
case 0x806: O << "epsr"; return;
case 7:
case 0x807: O << "iepsr"; return;
case 8:
case 0x808: O << "msp"; return;
case 9:
case 0x809: O << "psp"; return;
case 0x10:
case 0x810: O << "primask"; return;
case 0x11:
case 0x811: O << "basepri"; return;
case 0x12:
case 0x812: O << "basepri_max"; return;
case 0x13:
case 0x813: O << "faultmask"; return;
case 0x14:
case 0x814: O << "control"; return;
case 0: O << "apsr"; return;
case 1: O << "iapsr"; return;
case 2: O << "eapsr"; return;
case 3: O << "xpsr"; return;
case 5: O << "ipsr"; return;
case 6: O << "epsr"; return;
case 7: O << "iepsr"; return;
case 8: O << "msp"; return;
case 9: O << "psp"; return;
case 16: O << "primask"; return;
case 17: O << "basepri"; return;
case 18: O << "basepri_max"; return;
case 19: O << "faultmask"; return;
case 20: O << "control"; return;
}
}

View File

@ -1,7 +1,7 @@
@ RUN: llvm-mc -triple=thumbv7m-apple-darwin -show-encoding < %s | FileCheck %s
@ RUN: llvm-mc -triple=thumbv6m -show-encoding < %s | FileCheck %s
@ RUN: llvm-mc -triple=thumbv6m -show-encoding < %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-V6M %s
@ RUN: llvm-mc -triple=thumbv7m -show-encoding < %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-V7M %s
.syntax unified
.globl _func
@ Check that the assembler can handle the documented syntax from the ARM ARM.
@ These tests test instruction encodings specific to v6m & v7m (FeatureMClass).
@ -40,20 +40,12 @@
msr apsr, r0
msr apsr_nzcvq, r0
msr apsr_g, r0
msr apsr_nzcvqg, r0
msr iapsr, r0
msr iapsr_nzcvq, r0
msr iapsr_g, r0
msr iapsr_nzcvqg, r0
msr eapsr, r0
msr eapsr_nzcvq, r0
msr eapsr_g, r0
msr eapsr_nzcvqg, r0
msr xpsr, r0
msr xpsr_nzcvq, r0
msr xpsr_g, r0
msr xpsr_nzcvqg, r0
msr ipsr, r0
msr epsr, r0
msr iepsr, r0
@ -62,22 +54,22 @@
msr primask, r0
msr control, r0
@ CHECK: msr apsr, r0 @ encoding: [0x80,0xf3,0x00,0x88]
@ CHECK: msr apsr, r0 @ encoding: [0x80,0xf3,0x00,0x88]
@ CHECK: msr apsr_g, r0 @ encoding: [0x80,0xf3,0x00,0x84]
@ CHECK: msr apsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x00,0x8c]
@ CHECK: msr iapsr, r0 @ encoding: [0x80,0xf3,0x01,0x88]
@ CHECK: msr iapsr, r0 @ encoding: [0x80,0xf3,0x01,0x88]
@ CHECK: msr iapsr_g, r0 @ encoding: [0x80,0xf3,0x01,0x84]
@ CHECK: msr iapsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x01,0x8c]
@ CHECK: msr eapsr, r0 @ encoding: [0x80,0xf3,0x02,0x88]
@ CHECK: msr eapsr, r0 @ encoding: [0x80,0xf3,0x02,0x88]
@ CHECK: msr eapsr_g, r0 @ encoding: [0x80,0xf3,0x02,0x84]
@ CHECK: msr eapsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x02,0x8c]
@ CHECK: msr xpsr, r0 @ encoding: [0x80,0xf3,0x03,0x88]
@ CHECK: msr xpsr, r0 @ encoding: [0x80,0xf3,0x03,0x88]
@ CHECK: msr xpsr_g, r0 @ encoding: [0x80,0xf3,0x03,0x84]
@ CHECK: msr xpsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x03,0x8c]
@ CHECK-V6M: msr apsr, r0 @ encoding: [0x80,0xf3,0x00,0x88]
@ CHECK-V6M: msr apsr, r0 @ encoding: [0x80,0xf3,0x00,0x88]
@ CHECK-V6M: msr iapsr, r0 @ encoding: [0x80,0xf3,0x01,0x88]
@ CHECK-V6M: msr iapsr, r0 @ encoding: [0x80,0xf3,0x01,0x88]
@ CHECK-V6M: msr eapsr, r0 @ encoding: [0x80,0xf3,0x02,0x88]
@ CHECK-V6M: msr eapsr, r0 @ encoding: [0x80,0xf3,0x02,0x88]
@ CHECK-V6M: msr xpsr, r0 @ encoding: [0x80,0xf3,0x03,0x88]
@ CHECK-V6M: msr xpsr, r0 @ encoding: [0x80,0xf3,0x03,0x88]
@ CHECK-V7M: msr apsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x00,0x88]
@ CHECK-V7M: msr apsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x00,0x88]
@ CHECK-V7M: msr iapsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x01,0x88]
@ CHECK-V7M: msr iapsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x01,0x88]
@ CHECK-V7M: msr eapsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x02,0x88]
@ CHECK-V7M: msr eapsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x02,0x88]
@ CHECK-V7M: msr xpsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x03,0x88]
@ CHECK-V7M: msr xpsr_nzcvq, r0 @ encoding: [0x80,0xf3,0x03,0x88]
@ CHECK: msr ipsr, r0 @ encoding: [0x80,0xf3,0x05,0x88]
@ CHECK: msr epsr, r0 @ encoding: [0x80,0xf3,0x06,0x88]
@ CHECK: msr iepsr, r0 @ encoding: [0x80,0xf3,0x07,0x88]

53
test/MC/ARM/thumbv7em.s Normal file
View File

@ -0,0 +1,53 @@
@ RUN: llvm-mc -triple=thumbv7em -show-encoding < %s | FileCheck %s
@ RUN: not llvm-mc -triple=thumbv7m -show-encoding 2>&1 < %s | FileCheck --check-prefix=CHECK-V7M %s
.syntax unified
@ Check that the assembler can handle the documented syntax from the ARM ARM.
@ These tests test instruction encodings specific to ARMv7E-M.
@------------------------------------------------------------------------------
@ MSR
@------------------------------------------------------------------------------
msr apsr_g, r0
msr apsr_nzcvqg, r0
msr iapsr_g, r0
msr iapsr_nzcvqg, r0
msr eapsr_g, r0
msr eapsr_nzcvqg, r0
msr xpsr_g, r0
msr xpsr_nzcvqg, r0
@ CHECK: msr apsr_g, r0 @ encoding: [0x80,0xf3,0x00,0x84]
@ CHECK: msr apsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x00,0x8c]
@ CHECK: msr iapsr_g, r0 @ encoding: [0x80,0xf3,0x01,0x84]
@ CHECK: msr iapsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x01,0x8c]
@ CHECK: msr eapsr_g, r0 @ encoding: [0x80,0xf3,0x02,0x84]
@ CHECK: msr eapsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x02,0x8c]
@ CHECK: msr xpsr_g, r0 @ encoding: [0x80,0xf3,0x03,0x84]
@ CHECK: msr xpsr_nzcvqg, r0 @ encoding: [0x80,0xf3,0x03,0x8c]
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr apsr_g, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr apsr_nzcvqg, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr iapsr_g, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr iapsr_nzcvqg, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr eapsr_g, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr eapsr_nzcvqg, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr xpsr_g, r0
@ CHECK-V7M-NEXT: ^
@ CHECK-V7M: error: invalid operand for instruction
@ CHECK-V7M-NEXT: msr xpsr_nzcvqg, r0
@ CHECK-V7M-NEXT: ^

View File

@ -1,4 +1,5 @@
# RUN: not llvm-mc -disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m3 2>&1 | FileCheck %s
# RUN: not llvm-mc -disassemble %s -triple=thumbv7em 2>&1 | FileCheck --check-prefix=CHECK %s
# RUN: not llvm-mc -disassemble %s -triple=thumbv7m 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-V7M %s
#------------------------------------------------------------------------------
# Undefined encodings for mrs
@ -14,18 +15,18 @@
#------------------------------------------------------------------------------
# invalid mask = '00'
# CHECK: warning: invalid instruction encoding
# CHECK: warning: potentially undefined 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]
# CHECK: warning: potentially undefined instruction encoding
# CHECK-NEXT: [0x80 0xf3 0x05 0x8c]
[0x80 0xf3 0x05 0x8c]
# invalid mask = '01' (Cortex-M3 does not have the DSP extension)
# CHECK: warning: invalid instruction encoding
# CHECK-NEXT: [0x80 0xf3 0x00 0x84]
# invalid mask = '01' (ThumbV7M does not have the DSP extension)
# CHECK-V7M: warning: potentially undefined instruction encoding
# CHECK-V7M-NEXT: [0x80 0xf3 0x00 0x84]
[0x80 0xf3 0x00 0x84]
# invalid SYSm

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m4 | FileCheck %s
# RUN: llvm-mc --disassemble %s -triple=thumbv7em | FileCheck %s
#------------------------------------------------------------------------------
# MRS
@ -39,7 +39,7 @@
# MSR
#------------------------------------------------------------------------------
# CHECK: msr apsr, r0
# CHECK: msr apsr_nzcvq, r0
# CHECK: msr apsr_g, r0
# CHECK: msr apsr_nzcvqg, r0
@ -47,7 +47,7 @@
0x80 0xf3 0x00 0x84
0x80 0xf3 0x00 0x8c
# CHECK: msr iapsr, r0
# CHECK: msr iapsr_nzcvq, r0
# CHECK: msr iapsr_g, r0
# CHECK: msr iapsr_nzcvqg, r0
@ -55,7 +55,7 @@
0x80 0xf3 0x01 0x84
0x80 0xf3 0x01 0x8c
# CHECK: msr eapsr, r0
# CHECK: msr eapsr_nzcvq, r0
# CHECK: msr eapsr_g, r0
# CHECK: msr eapsr_nzcvqg, r0
@ -63,7 +63,7 @@
0x80 0xf3 0x02 0x84
0x80 0xf3 0x02 0x8c
# CHECK: msr xpsr, r0
# CHECK: msr xpsr_nzcvq, r0
# CHECK: msr xpsr_g, r0
# CHECK: msr xpsr_nzcvqg, r0