mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-06 09:44:39 +00:00
Check in a patch that has already been code reviewed by Owen that I'd forgotten to commit.
Build on previous patches to successfully distinguish between an M-series and A/R-series MSR and MRS instruction. These take different mask names and have a *slightly* different opcode format. Add decoder and disassembler tests. Improvement on the previous patch - successfully distinguish between valid v6m and v7m masks (one is a subset of the other). The patch had to be edited slightly to apply to ToT. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140696 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
113aa86120
commit
acad68da50
@ -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
|
||||
|
@ -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()">;
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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)
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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 = "";
|
||||
|
@ -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)) {
|
||||
|
@ -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') {
|
||||
|
74
test/MC/ARM/thumb2-mclass.s
Normal file
74
test/MC/ARM/thumb2-mclass.s
Normal file
@ -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]
|
7
test/MC/Disassembler/ARM/thumb-MSR-MClass.txt
Normal file
7
test/MC/Disassembler/ARM/thumb-MSR-MClass.txt
Normal file
@ -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
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user