summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/ARM.td10
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td4
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td51
-rw-r--r--lib/Target/ARM/ARMSubtarget.cpp1
-rw-r--r--lib/Target/ARM/ARMSubtarget.h6
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp37
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp20
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp11
-rw-r--r--test/MC/ARM/thumb2-mclass.s74
-rw-r--r--test/MC/Disassembler/ARM/thumb-MSR-MClass.txt7
-rw-r--r--test/MC/Disassembler/ARM/thumb-tests.txt6
11 files changed, 215 insertions, 12 deletions
diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td
index 994271d678..5c727ad6e3 100644
--- a/lib/Target/ARM/ARM.td
+++ b/lib/Target/ARM/ARM.td
@@ -94,6 +94,10 @@ def FeatureDSPThumb2 : SubtargetFeature<"t2dsp", "Thumb2DSP", "true",
def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true",
"Supports Multiprocessing extension">;
+// M-series ISA?
+def FeatureMClass : SubtargetFeature<"mclass", "IsMClass", "true",
+ "Is microcontroller profile ('M' series)">;
+
// ARM ISAs.
def HasV4TOps : SubtargetFeature<"v4t", "HasV4TOps", "true",
"Support ARM v4T instructions">;
@@ -185,7 +189,7 @@ def : Processor<"mpcore", ARMV6Itineraries, [HasV6Ops, FeatureVFP2,
// V6M Processors.
def : Processor<"cortex-m0", ARMV6Itineraries, [HasV6Ops, FeatureNoARM,
- FeatureDB]>;
+ FeatureDB, FeatureMClass]>;
// V6T2 Processors.
def : Processor<"arm1156t2-s", ARMV6Itineraries, [HasV6T2Ops,
@@ -208,14 +212,14 @@ def : Processor<"cortex-a9-mp", CortexA9Itineraries,
// V7M Processors.
def : ProcNoItin<"cortex-m3", [HasV7Ops,
FeatureThumb2, FeatureNoARM, FeatureDB,
- FeatureHWDiv]>;
+ FeatureHWDiv, FeatureMClass]>;
// V7EM Processors.
def : ProcNoItin<"cortex-m4", [HasV7Ops,
FeatureThumb2, FeatureNoARM, FeatureDB,
FeatureHWDiv, FeatureDSPThumb2,
FeatureT2XtPk, FeatureVFP2,
- FeatureVFPOnlySP]>;
+ FeatureVFPOnlySP, FeatureMClass]>;
//===----------------------------------------------------------------------===//
// Register File Description
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index e2a6fd7bcf..f05d3b1e0a 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -205,6 +205,10 @@ def IsThumb : Predicate<"Subtarget->isThumb()">,
def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">;
def IsThumb2 : Predicate<"Subtarget->isThumb2()">,
AssemblerPredicate<"ModeThumb,FeatureThumb2">;
+def IsMClass : Predicate<"Subtarget->isMClass()">,
+ AssemblerPredicate<"FeatureMClass">;
+def IsARClass : Predicate<"!Subtarget->isMClass()">,
+ AssemblerPredicate<"!FeatureMClass">;
def IsARM : Predicate<"!Subtarget->isThumb()">,
AssemblerPredicate<"!ModeThumb">;
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 6ce4438943..b8a8519b7a 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -3540,30 +3540,55 @@ defm t2STC : T2LdStCop<0b1111, 0, "stc">;
// Move between special register and ARM core register -- for disassembly only
//
// Move to ARM core register from Special Register
-def t2MRS : T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, apsr", []> {
+
+// A/R class MRS.
+//
+// A/R class can only move from CPSR or SPSR.
+def t2MRS_AR : T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, apsr", []>,
+ Requires<[IsThumb2,IsARClass]> {
bits<4> Rd;
let Inst{31-12} = 0b11110011111011111000;
let Inst{11-8} = Rd;
let Inst{7-0} = 0b0000;
}
-def : t2InstAlias<"mrs${p} $Rd, cpsr", (t2MRS GPR:$Rd, pred:$p)>;
+def : t2InstAlias<"mrs${p} $Rd, cpsr", (t2MRS_AR GPR:$Rd, pred:$p)>;
-def t2MRSsys:T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr", []> {
+def t2MRSsys_AR: T2I<(outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr", []>,
+ Requires<[IsThumb2,IsARClass]> {
bits<4> Rd;
let Inst{31-12} = 0b11110011111111111000;
let Inst{11-8} = Rd;
let Inst{7-0} = 0b0000;
}
+// M class MRS.
+//
+// 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", []>,
+ Requires<[IsThumb2,IsMClass]> {
+ bits<4> Rd;
+ bits<8> mask;
+ let Inst{31-12} = 0b11110011111011111000;
+ let Inst{11-8} = Rd;
+ let Inst{19-16} = 0b1111;
+ let Inst{7-0} = mask;
+}
+
+
// Move from ARM core register to Special Register
//
+// A/R class MSR.
+//
// No need to have both system and application versions, the encodings are the
// same and the assembly parser has no way to distinguish between them. The mask
// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains
// the mask with the fields to be accessed in the special register.
-def t2MSR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn),
- NoItinerary, "msr", "\t$mask, $Rn", []> {
+def t2MSR_AR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn),
+ NoItinerary, "msr", "\t$mask, $Rn", []>,
+ Requires<[IsThumb2,IsARClass]> {
bits<5> mask;
bits<4> Rn;
let Inst{31-21} = 0b11110011100;
@@ -3574,6 +3599,22 @@ def t2MSR : T2I<(outs), (ins msr_mask:$mask, rGPR:$Rn),
let Inst{7-0} = 0;
}
+// M class MSR.
+//
+// Move from ARM core register to Special Register
+def t2MSR_M : T2I<(outs), (ins msr_mask:$SYSm, rGPR:$Rn),
+ NoItinerary, "msr", "\t$SYSm, $Rn", []>,
+ Requires<[IsThumb2,IsMClass]> {
+ bits<8> 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;
+}
+
+
//===----------------------------------------------------------------------===//
// Move between coprocessor and ARM core register
//
diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp
index f01d1d41cf..82e542281e 100644
--- a/lib/Target/ARM/ARMSubtarget.cpp
+++ b/lib/Target/ARM/ARMSubtarget.cpp
@@ -55,6 +55,7 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU,
, InThumbMode(false)
, InNaClMode(false)
, HasThumb2(false)
+ , IsMClass(false)
, NoARM(false)
, PostRAScheduler(false)
, IsR9Reserved(ReserveR9)
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h
index 76a502caa9..47e076a7f1 100644
--- a/lib/Target/ARM/ARMSubtarget.h
+++ b/lib/Target/ARM/ARMSubtarget.h
@@ -76,6 +76,10 @@ protected:
/// HasThumb2 - True if Thumb2 instructions are supported.
bool HasThumb2;
+ /// IsMClass - True if the subtarget belongs to the 'M' profile of CPUs -
+ /// v6m, v7m for example.
+ bool IsMClass;
+
/// NoARM - True if subtarget does not support ARM mode execution.
bool NoARM;
@@ -224,6 +228,8 @@ protected:
bool isThumb1Only() const { return InThumbMode && !HasThumb2; }
bool isThumb2() const { return InThumbMode && HasThumb2; }
bool hasThumb2() const { return HasThumb2; }
+ bool isMClass() const { return IsMClass; }
+ bool isARClass() const { return !IsMClass; }
bool isR9Reserved() const { return IsR9Reserved; }
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 543340f8e4..9d28a1cd09 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -114,10 +114,16 @@ class ARMAsmParser : public MCTargetAsmParser {
bool hasV6Ops() const {
return STI.getFeatureBits() & ARM::HasV6Ops;
}
+ bool hasV7Ops() const {
+ return STI.getFeatureBits() & ARM::HasV7Ops;
+ }
void SwitchMode() {
unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
setAvailableFeatures(FB);
}
+ bool isMClass() const {
+ return STI.getFeatureBits() & ARM::FeatureMClass;
+ }
/// @name Auto-generated Match Functions
/// {
@@ -2076,6 +2082,37 @@ parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
StringRef Mask = Tok.getString();
+ if (isMClass()) {
+ // See ARMv6-M 10.1.1
+ unsigned FlagsVal = StringSwitch<unsigned>(Mask)
+ .Case("apsr", 0)
+ .Case("iapsr", 1)
+ .Case("eapsr", 2)
+ .Case("xpsr", 3)
+ .Case("ipsr", 5)
+ .Case("epsr", 6)
+ .Case("iepsr", 7)
+ .Case("msp", 8)
+ .Case("psp", 9)
+ .Case("primask", 16)
+ .Case("basepri", 17)
+ .Case("basepri_max", 18)
+ .Case("faultmask", 19)
+ .Case("control", 20)
+ .Default(~0U);
+
+ if (FlagsVal == ~0U)
+ return MatchOperand_NoMatch;
+
+ if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
+ // basepri, basepri_max and faultmask only valid for V7m.
+ return MatchOperand_NoMatch;
+
+ Parser.Lex(); // Eat identifier token.
+ Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
+ return MatchOperand_Success;
+ }
+
// Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
size_t Start = 0, Next = Mask.find('_');
StringRef Flags = "";
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 49775f5c79..bcf91c73ed 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -621,6 +621,26 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
+ if (getAvailableFeatures() & ARM::FeatureMClass) {
+ switch (Op.getImm()) {
+ default: assert(0 && "Unexpected mask value!");
+ 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;
+ }
+ }
+
// As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
// APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
index 23f7f14561..5c582ca37f 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
@@ -56,18 +56,21 @@ std::string ARM_MC::ParseARMTriple(StringRef TT) {
unsigned SubVer = TT[Idx];
if (SubVer >= '7' && SubVer <= '9') {
if (Len >= Idx+2 && TT[Idx+1] == 'm') {
- // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv
- ARMArchFeature = "+v7,+noarm,+db,+hwdiv";
+ // v7m: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureMClass
+ ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+mclass";
} else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') {
// v7em: FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2,
- // FeatureT2XtPk
- ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk";
+ // FeatureT2XtPk, FeatureMClass
+ ARMArchFeature = "+v7,+noarm,+db,+hwdiv,+t2dsp,t2xtpk,+mclass";
} else
// v7a: FeatureNEON, FeatureDB, FeatureDSPThumb2, FeatureT2XtPk
ARMArchFeature = "+v7,+neon,+db,+t2dsp,+t2xtpk";
} else if (SubVer == '6') {
if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2')
ARMArchFeature = "+v6t2";
+ else if (Len >= Idx+2 && TT[Idx+1] == 'm')
+ // v6m: FeatureNoARM, FeatureMClass
+ ARMArchFeature = "+v6t2,+noarm,+mclass";
else
ARMArchFeature = "+v6";
} else if (SubVer == '5') {
diff --git a/test/MC/ARM/thumb2-mclass.s b/test/MC/ARM/thumb2-mclass.s
new file mode 100644
index 0000000000..10460f9145
--- /dev/null
+++ b/test/MC/ARM/thumb2-mclass.s
@@ -0,0 +1,74 @@
+@ RUN: llvm-mc -triple=thumbv7m-apple-darwin -show-encoding < %s | FileCheck %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 v7m & v7m (FeatureMClass).
+
+@------------------------------------------------------------------------------
+@ MRS
+@------------------------------------------------------------------------------
+
+ mrs r0, apsr
+ mrs r0, iapsr
+ mrs r0, eapsr
+ mrs r0, xpsr
+ mrs r0, ipsr
+ mrs r0, epsr
+ mrs r0, iepsr
+ mrs r0, msp
+ mrs r0, psp
+ mrs r0, primask
+ mrs r0, basepri
+ mrs r0, basepri_max
+ mrs r0, faultmask
+ mrs r0, control
+
+@ CHECK: mrs r0, apsr @ encoding: [0xef,0xf3,0x00,0x80]
+@ CHECK: mrs r0, iapsr @ encoding: [0xef,0xf3,0x01,0x80]
+@ CHECK: mrs r0, eapsr @ encoding: [0xef,0xf3,0x02,0x80]
+@ CHECK: mrs r0, xpsr @ encoding: [0xef,0xf3,0x03,0x80]
+@ CHECK: mrs r0, ipsr @ encoding: [0xef,0xf3,0x05,0x80]
+@ CHECK: mrs r0, epsr @ encoding: [0xef,0xf3,0x06,0x80]
+@ CHECK: mrs r0, iepsr @ encoding: [0xef,0xf3,0x07,0x80]
+@ CHECK: mrs r0, msp @ encoding: [0xef,0xf3,0x08,0x80]
+@ CHECK: mrs r0, psp @ encoding: [0xef,0xf3,0x09,0x80]
+@ CHECK: mrs r0, primask @ encoding: [0xef,0xf3,0x10,0x80]
+@ CHECK: mrs r0, basepri @ encoding: [0xef,0xf3,0x11,0x80]
+@ CHECK: mrs r0, basepri_max @ encoding: [0xef,0xf3,0x12,0x80]
+@ CHECK: mrs r0, faultmask @ encoding: [0xef,0xf3,0x13,0x80]
+@ CHECK: mrs r0, control @ encoding: [0xef,0xf3,0x14,0x80]
+
+@------------------------------------------------------------------------------
+@ MSR
+@------------------------------------------------------------------------------
+
+ msr apsr, r0
+ msr iapsr, r0
+ msr eapsr, r0
+ msr xpsr, r0
+ msr ipsr, r0
+ msr epsr, r0
+ msr iepsr, r0
+ msr msp, r0
+ msr psp, r0
+ msr primask, r0
+ msr basepri, r0
+ msr basepri_max, r0
+ 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 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]
+@ CHECK: msr msp, r0 @ encoding: [0x80,0xf3,0x08,0x80]
+@ CHECK: msr psp, r0 @ encoding: [0x80,0xf3,0x09,0x80]
+@ CHECK: msr primask, r0 @ encoding: [0x80,0xf3,0x10,0x80]
+@ CHECK: msr basepri, r0 @ encoding: [0x80,0xf3,0x11,0x80]
+@ CHECK: msr basepri_max, r0 @ encoding: [0x80,0xf3,0x12,0x80]
+@ CHECK: msr faultmask, r0 @ encoding: [0x80,0xf3,0x13,0x80]
+@ CHECK: msr control, r0 @ encoding: [0x80,0xf3,0x14,0x80]
diff --git a/test/MC/Disassembler/ARM/thumb-MSR-MClass.txt b/test/MC/Disassembler/ARM/thumb-MSR-MClass.txt
new file mode 100644
index 0000000000..497cb9a2a5
--- /dev/null
+++ b/test/MC/Disassembler/ARM/thumb-MSR-MClass.txt
@@ -0,0 +1,7 @@
+# RUN: llvm-mc --disassemble %s -triple=thumbv7-apple-darwin9 -mcpu cortex-m3 | FileCheck %s
+
+# CHECK: msr primask, r0
+0x80 0xf3 0x10 0x80
+
+# CHECK: mrs r0, primask
+0xef 0xf3 0x10 0x80
diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt
index 06cf6636e8..c8b7e117de 100644
--- a/test/MC/Disassembler/ARM/thumb-tests.txt
+++ b/test/MC/Disassembler/ARM/thumb-tests.txt
@@ -295,3 +295,9 @@
# CHECK: pldw [r11, r12, lsl #2]
0x3b 0xf8 0x2c 0xf0
+
+# CHECK: msr CPSR_fc, r0
+0x80 0xf3 0x00 0x89
+
+# CHECK: mrs r0, apsr
+0xef 0xf3 0x00 0x80