From 0fd4f3c8de07e9cfe2a86093ccada82d64f38bfe Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Thu, 17 May 2012 22:18:01 +0000 Subject: [PATCH] Fix the encoding of the armv7m (MClass) for MSR APSR writes which was missing the 0b10 mask encoding bits. Make MSR APSR writes without a _ qualifier an alias for MSR APSR_nzcvq even though ARM as deprecated it use. Also add support for suffixes (_nzcvq, _g, _nzcvqg) for APSR versions. Some FIXMEs in the code for better error checking when versions shouldn't be used. rdar://11457025 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157019 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrThumb2.td | 4 +-- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 33 ++++++++++++++++--- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 28 +++++++++++++--- test/MC/ARM/thumb2-mclass.s | 32 +++++++++++++++--- 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 2b9442274861..3b73c1fd438e 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -3683,13 +3683,13 @@ def t2MSR_AR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn), def t2MSR_M : T2I<(outs), (ins msr_mask:$SYSm, rGPR:$Rn), NoItinerary, "msr", "\t$SYSm, $Rn", []>, Requires<[IsThumb,IsMClass]> { - bits<8> SYSm; + bits<12> SYSm; bits<4> Rn; let Inst{31-21} = 0b11110011100; let Inst{20} = 0b0; let Inst{19-16} = Rn; let Inst{15-12} = 0b1000; - let Inst{7-0} = SYSm; + let Inst{11-0} = SYSm; } diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 88659796705d..00e7f6e8fb99 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -3324,10 +3324,35 @@ parseMSRMaskOperand(SmallVectorImpl &Operands) { // See ARMv6-M 10.1.1 std::string Name = Mask.lower(); unsigned FlagsVal = StringSwitch(Name) - .Case("apsr", 0) - .Case("iapsr", 1) - .Case("eapsr", 2) - .Case("xpsr", 3) + // Note: in the documentation: + // ARM deprecates using MSR APSR without a _ qualifier as an alias + // for MSR APSR_nzcvq. + // but we do make it an alias here. This is so to get the "mask encoding" + // bits correct on MSR APSR writes. + // + // FIXME: Note the 0xc00 "mask encoding" bits version of the registers + // 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) + .Case("apsr_nzcvqg", 0xc00) + .Case("iapsr", 0x801) + .Case("iapsr_nzcvq", 0x801) + .Case("iapsr_g", 0x401) + .Case("iapsr_nzcvqg", 0xc01) + .Case("eapsr", 0x802) + .Case("eapsr_nzcvq", 0x802) + .Case("eapsr_g", 0x402) + .Case("eapsr_nzcvqg", 0xc02) + .Case("xpsr", 0x803) + .Case("xpsr_nzcvq", 0x803) + .Case("xpsr_g", 0x403) + .Case("xpsr_nzcvqg", 0xc03) .Case("ipsr", 5) .Case("epsr", 6) .Case("iepsr", 7) diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index be7e098b55fd..70e4317cef67 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -647,12 +647,30 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum, unsigned Mask = Op.getImm() & 0xf; if (getAvailableFeatures() & ARM::FeatureMClass) { - switch (Op.getImm()) { + 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; + switch (SYSm) { default: llvm_unreachable("Unexpected mask value!"); - case 0: O << "apsr"; return; - case 1: O << "iapsr"; return; - case 2: O << "eapsr"; return; - case 3: O << "xpsr"; return; + 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: O << "ipsr"; return; case 6: O << "epsr"; return; case 7: O << "iepsr"; return; diff --git a/test/MC/ARM/thumb2-mclass.s b/test/MC/ARM/thumb2-mclass.s index 10460f914509..df4e4c93b922 100644 --- a/test/MC/ARM/thumb2-mclass.s +++ b/test/MC/ARM/thumb2-mclass.s @@ -44,9 +44,21 @@ @------------------------------------------------------------------------------ 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 @@ -58,10 +70,22 @@ msr faultmask, r0 msr control, r0 -@ CHECK: msr apsr, r0 @ encoding: [0x80,0xf3,0x00,0x80] -@ CHECK: msr iapsr, r0 @ encoding: [0x80,0xf3,0x01,0x80] -@ CHECK: msr eapsr, r0 @ encoding: [0x80,0xf3,0x02,0x80] -@ CHECK: msr xpsr, r0 @ encoding: [0x80,0xf3,0x03,0x80] +@ 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: msr ipsr, r0 @ encoding: [0x80,0xf3,0x05,0x80] @ CHECK: msr epsr, r0 @ encoding: [0x80,0xf3,0x06,0x80] @ CHECK: msr iepsr, r0 @ encoding: [0x80,0xf3,0x07,0x80]