[ARM] Unify handling of M-Class system registers

This patch cleans up and fixes issues in the M-Class system register handling:

1. It defines the system registers and the encoding (SYSm values) in one place:
   a new ARMSystemRegister.td using SearchableTable, thereby removing the
   hand-coded values which existed in multiple places.

2. Some system registers e.g. BASEPRI_MAX_NS which do not exist were being allowed!
   Ref: ARMv6/7/8M architecture reference manual.

Reviewed by: @t.p.northover, @olist01, @john.brawn
Differential Revision: https://reviews.llvm.org/D35209

llvm-svn: 308456
This commit is contained in:
Javed Absar 2017-07-19 12:57:16 +00:00
parent e845d29c41
commit ca6d1aaf93
15 changed files with 293 additions and 302 deletions

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "ARM.h"
#include "Utils/ARMBaseInfo.h"
#include "ARMBaseInstrInfo.h"
#include "ARMTargetMachine.h"
#include "MCTargetDesc/ARMAddressingModes.h"
@ -3801,31 +3802,6 @@ static inline int getBankedRegisterMask(StringRef RegString) {
.Default(-1);
}
// Maps a MClass special register string to its value for use in the
// t2MRS_M / t2MSR_M instruction nodes as the SYSm value operand.
// Returns -1 to signify that the string was invalid.
static inline int getMClassRegisterSYSmValueMask(StringRef RegString) {
return StringSwitch<int>(RegString.lower())
.Case("apsr", 0x0)
.Case("iapsr", 0x1)
.Case("eapsr", 0x2)
.Case("xpsr", 0x3)
.Case("ipsr", 0x5)
.Case("epsr", 0x6)
.Case("iepsr", 0x7)
.Case("msp", 0x8)
.Case("psp", 0x9)
.Case("primask", 0x10)
.Case("basepri", 0x11)
.Case("basepri_max", 0x12)
.Case("faultmask", 0x13)
.Case("control", 0x14)
.Case("msplim", 0x0a)
.Case("psplim", 0x0b)
.Case("sp", 0x18)
.Default(-1);
}
// The flags here are common to those allowed for apsr in the A class cores and
// those allowed for the special registers in the M class cores. Returns a
// value representing which flags were present, -1 if invalid.
@ -3839,58 +3815,15 @@ static inline int getMClassFlagsMask(StringRef Flags) {
.Default(-1);
}
static int getMClassRegisterMask(StringRef Reg, StringRef Flags, bool IsRead,
const ARMSubtarget *Subtarget) {
// Ensure that the register (without flags) was a valid M Class special
// register.
int SYSmvalue = getMClassRegisterSYSmValueMask(Reg);
if (SYSmvalue == -1)
// Maps MClass special registers string to its value for use in the
// t2MRS_M/t2MSR_M instruction nodes as the SYSm value operand.
// Returns -1 to signify that the string was invalid.
static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) {
auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg);
const FeatureBitset &FeatureBits = Subtarget->getFeatureBits();
if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits))
return -1;
// basepri, basepri_max and faultmask are only valid for V7m.
if (!Subtarget->hasV7Ops() && SYSmvalue >= 0x11 && SYSmvalue <= 0x13)
return -1;
if (Subtarget->has8MSecExt() && Flags.lower() == "ns") {
Flags = "";
SYSmvalue |= 0x80;
}
if (!Subtarget->has8MSecExt() &&
(SYSmvalue == 0xa || SYSmvalue == 0xb || SYSmvalue > 0x14))
return -1;
if (!Subtarget->hasV8MMainlineOps() &&
(SYSmvalue == 0x8a || SYSmvalue == 0x8b || SYSmvalue == 0x91 ||
SYSmvalue == 0x93))
return -1;
// If it was a read then we won't be expecting flags and so at this point
// we can return the mask.
if (IsRead) {
if (Flags.empty())
return SYSmvalue;
else
return -1;
}
// We know we are now handling a write so need to get the mask for the flags.
int Mask = getMClassFlagsMask(Flags);
// Only apsr, iapsr, eapsr, xpsr can have flags. The other register values
// shouldn't have flags present.
if ((SYSmvalue < 0x4 && Mask == -1) || (SYSmvalue > 0x4 && !Flags.empty()))
return -1;
// The _g and _nzcvqg versions are only valid if the DSP extension is
// available.
if (!Subtarget->hasDSP() && (Mask & 0x1))
return -1;
// The register was valid so need to put the mask in the correct place
// (the flags need to be in bits 11-10) and combine with the SYSmvalue to
// construct the operand for the instruction node.
return SYSmvalue | Mask << 10;
return (int)(TheReg->Encoding & 0xFFF); // SYSm value
}
static int getARClassRegisterMask(StringRef Reg, StringRef Flags) {
@ -4032,13 +3965,7 @@ bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){
// is an acceptable value, so check that a mask can be constructed from the
// string.
if (Subtarget->isMClass()) {
StringRef Flags = "", Reg = SpecialReg;
if (Reg.endswith("_ns")) {
Flags = "ns";
Reg = Reg.drop_back(3);
}
int SYSmValue = getMClassRegisterMask(Reg, Flags, true, Subtarget);
int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
if (SYSmValue == -1)
return false;
@ -4149,12 +4076,7 @@ bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){
// If the target was M Class then need to validate the special register value
// and retrieve the mask for use in the instruction node.
if (Subtarget->isMClass()) {
// basepri_max gets split so need to correct Reg and Flags.
if (SpecialReg == "basepri_max") {
Reg = SpecialReg;
Flags = "";
}
int SYSmValue = getMClassRegisterMask(Reg, Flags, false, Subtarget);
int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget);
if (SYSmValue == -1)
return false;

View File

@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
include "ARMSystemRegister.td"
//===----------------------------------------------------------------------===//
// Declarations that describe the ARM register file
//===----------------------------------------------------------------------===//

View File

@ -0,0 +1,108 @@
//===-- ARMSystemRegister.td - ARM Register defs -------------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
include "llvm/TableGen/SearchableTable.td"
//===----------------------------------------------------------------------===//
// Declarations that describe the ARM system-registers
//===----------------------------------------------------------------------===//
// M-Class System Registers.
// 'Mask' bits create unique keys for searches.
//
class MClassSysReg<bits<1> UniqMask1,
bits<1> UniqMask2,
bits<1> UniqMask3,
bits<12> Enc12,
string name> : SearchableTable {
let SearchableFields = ["Name", "M1Encoding12", "M2M3Encoding8", "Encoding"];
string Name;
bits<13> M1Encoding12;
bits<10> M2M3Encoding8;
bits<12> Encoding;
let Name = name;
let EnumValueField = "M1Encoding12";
let EnumValueField = "M2M3Encoding8";
let EnumValueField = "Encoding";
let M1Encoding12{12} = UniqMask1;
let M1Encoding12{11-00} = Enc12;
let Encoding = Enc12;
let M2M3Encoding8{9} = UniqMask2;
let M2M3Encoding8{8} = UniqMask3;
let M2M3Encoding8{7-0} = Enc12{7-0};
code Requires = [{ {} }];
}
// [|i|e|x]apsr_nzcvq has alias [|i|e|x]apsr.
// Mask1 Mask2 Mask3 Enc12, Name
let Requires = [{ {ARM::FeatureDSP} }] in {
def : MClassSysReg<0, 0, 0, 0x400, "apsr_g">;
def : MClassSysReg<0, 1, 1, 0xc00, "apsr_nzcvqg">;
def : MClassSysReg<0, 0, 0, 0x401, "iapsr_g">;
def : MClassSysReg<0, 1, 1, 0xc01, "iapsr_nzcvqg">;
def : MClassSysReg<0, 0, 0, 0x402, "eapsr_g">;
def : MClassSysReg<0, 1, 1, 0xc02, "eapsr_nzcvqg">;
def : MClassSysReg<0, 0, 0, 0x403, "xpsr_g">;
def : MClassSysReg<0, 1, 1, 0xc03, "xpsr_nzcvqg">;
}
def : MClassSysReg<0, 0, 1, 0x800, "apsr">;
def : MClassSysReg<1, 1, 0, 0x800, "apsr_nzcvq">;
def : MClassSysReg<0, 0, 1, 0x801, "iapsr">;
def : MClassSysReg<1, 1, 0, 0x801, "iapsr_nzcvq">;
def : MClassSysReg<0, 0, 1, 0x802, "eapsr">;
def : MClassSysReg<1, 1, 0, 0x802, "eapsr_nzcvq">;
def : MClassSysReg<0, 0, 1, 0x803, "xpsr">;
def : MClassSysReg<1, 1, 0, 0x803, "xpsr_nzcvq">;
def : MClassSysReg<0, 0, 1, 0x805, "ipsr">;
def : MClassSysReg<0, 0, 1, 0x806, "epsr">;
def : MClassSysReg<0, 0, 1, 0x807, "iepsr">;
def : MClassSysReg<0, 0, 1, 0x808, "msp">;
def : MClassSysReg<0, 0, 1, 0x809, "psp">;
let Requires = [{ {ARM::HasV8MBaselineOps} }] in {
def : MClassSysReg<0, 0, 1, 0x80a, "msplim">;
def : MClassSysReg<0, 0, 1, 0x80b, "psplim">;
}
def : MClassSysReg<0, 0, 1, 0x810, "primask">;
let Requires = [{ {ARM::HasV7Ops} }] in {
def : MClassSysReg<0, 0, 1, 0x811, "basepri">;
def : MClassSysReg<0, 0, 1, 0x812, "basepri_max">;
def : MClassSysReg<0, 0, 1, 0x813, "faultmask">;
}
def : MClassSysReg<0, 0, 1, 0x814, "control">;
let Requires = [{ {ARM::Feature8MSecExt} }] in {
def : MClassSysReg<0, 0, 1, 0x888, "msp_ns">;
def : MClassSysReg<0, 0, 1, 0x889, "psp_ns">;
}
let Requires = [{ {ARM::Feature8MSecExt, ARM::HasV8MBaselineOps} }] in {
def : MClassSysReg<0, 0, 1, 0x88a, "msplim_ns">;
def : MClassSysReg<0, 0, 1, 0x88b, "psplim_ns">;
}
def : MClassSysReg<0, 0, 1, 0x890, "primask_ns">;
let Requires = [{ {ARM::Feature8MSecExt, ARM::HasV7Ops} }] in {
def : MClassSysReg<0, 0, 1, 0x891, "basepri_ns">;
def : MClassSysReg<0, 0, 1, 0x893, "faultmask_ns">;
}
let Requires = [{ {ARM::Feature8MSecExt} }] in {
def : MClassSysReg<0, 0, 1, 0x894, "control_ns">;
def : MClassSysReg<0, 0, 1, 0x898, "sp_ns">;
}

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ARMFeatures.h"
#include "Utils/ARMBaseInfo.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "MCTargetDesc/ARMMCExpr.h"
@ -4089,81 +4090,14 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) {
StringRef Mask = Tok.getString();
if (isMClass()) {
// See ARMv6-M 10.1.1
std::string Name = Mask.lower();
unsigned FlagsVal = StringSwitch<unsigned>(Name)
// Note: in the documentation:
// ARM deprecates using MSR APSR without a _<bits> 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.
.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", 0x805)
.Case("epsr", 0x806)
.Case("iepsr", 0x807)
.Case("msp", 0x808)
.Case("psp", 0x809)
.Case("primask", 0x810)
.Case("basepri", 0x811)
.Case("basepri_max", 0x812)
.Case("faultmask", 0x813)
.Case("control", 0x814)
.Case("msplim", 0x80a)
.Case("psplim", 0x80b)
.Case("msp_ns", 0x888)
.Case("psp_ns", 0x889)
.Case("msplim_ns", 0x88a)
.Case("psplim_ns", 0x88b)
.Case("primask_ns", 0x890)
.Case("basepri_ns", 0x891)
.Case("basepri_max_ns", 0x892)
.Case("faultmask_ns", 0x893)
.Case("control_ns", 0x894)
.Case("sp_ns", 0x898)
.Default(~0U);
if (FlagsVal == ~0U)
auto TheReg = ARMSysReg::lookupMClassSysRegByName(Mask.lower());
if (!TheReg || !TheReg->hasRequiredFeatures(getSTI().getFeatureBits()))
return MatchOperand_NoMatch;
if (!hasDSP() && (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;
if (!has8MSecExt() && (FlagsVal == 0x80a || FlagsVal == 0x80b ||
(FlagsVal > 0x814 && FlagsVal < 0xc00)))
return MatchOperand_NoMatch;
if (!hasV8MMainline() && (FlagsVal == 0x88a || FlagsVal == 0x88b ||
(FlagsVal > 0x890 && FlagsVal <= 0x893)))
return MatchOperand_NoMatch;
unsigned SYSmvalue = TheReg->Encoding & 0xFFF;
Parser.Lex(); // Eat identifier token.
Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S));
return MatchOperand_Success;
}

View File

@ -19,5 +19,5 @@
type = Library
name = ARMAsmParser
parent = ARM
required_libraries = ARMDesc ARMInfo MC MCParser Support
required_libraries = ARMDesc ARMInfo MC MCParser Support ARMUtils
add_to_library_groups = ARM

View File

@ -15,6 +15,7 @@ tablegen(LLVM ARMGenFastISel.inc -gen-fast-isel)
tablegen(LLVM ARMGenCallingConv.inc -gen-callingconv)
tablegen(LLVM ARMGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM ARMGenSystemRegister.inc -gen-searchable-tables)
add_public_tablegen_target(ARMCommonTableGen)
# Add GlobalISel files if the user wants to build it.
@ -73,3 +74,4 @@ add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(Utils)

View File

@ -12,6 +12,9 @@
//===----------------------------------------------------------------------===//
#include "ARMInstPrinter.h"
#include "Utils/ARMBaseInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "llvm/MC/MCAsmInfo.h"
@ -789,152 +792,48 @@ void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNum);
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
const FeatureBitset &FeatureBits = STI.getFeatureBits();
if (FeatureBits[ARM::FeatureMClass]) {
unsigned SYSm = Op.getImm();
unsigned SYSm = Op.getImm() & 0xFFF; // 12-bit SYSm
unsigned Opcode = MI->getOpcode();
// For writes, handle extended mask bits if the DSP extension is present.
if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
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;
auto TheReg =ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm);
if (TheReg && TheReg->isInRequiredFeatures({ARM::FeatureDSP})) {
O << TheReg->Name;
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;
auto TheReg = ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm);
if (TheReg) {
O << TheReg->Name;
return;
}
}
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 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;
case 10:
O << "msplim";
return;
case 11:
O << "psplim";
return;
case 0x88:
O << "msp_ns";
return;
case 0x89:
O << "psp_ns";
return;
case 0x8a:
O << "msplim_ns";
return;
case 0x8b:
O << "psplim_ns";
return;
case 0x90:
O << "primask_ns";
return;
case 0x91:
O << "basepri_ns";
return;
case 0x92:
O << "basepri_max_ns";
return;
case 0x93:
O << "faultmask_ns";
return;
case 0x94:
O << "control_ns";
return;
case 0x98:
O << "sp_ns";
auto TheReg = ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm);
if (TheReg) {
O << TheReg->Name;
return;
}
llvm_unreachable("Unexpected mask value!");
return;
}
// As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
// APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
O << "APSR_";
switch (Mask) {

View File

@ -19,5 +19,5 @@
type = Library
name = ARMAsmPrinter
parent = ARM
required_libraries = MC Support
required_libraries = MC Support ARMUtils
add_to_library_groups = ARM

View File

@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo
subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo Utils
[component_0]
type = TargetGroup
@ -31,5 +31,5 @@ has_jit = 1
type = Library
name = ARMCodeGen
parent = ARM
required_libraries = ARMAsmPrinter ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel
required_libraries = ARMAsmPrinter ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel ARMUtils
add_to_library_groups = ARM

View File

@ -0,0 +1,44 @@
//===-- ARMBaseInfo.cpp - ARM Base encoding information------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides basic encoding and assembly information for ARM.
//
//===----------------------------------------------------------------------===//
#include "ARMBaseInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Regex.h"
using namespace llvm;
namespace llvm {
namespace ARMSysReg {
// lookup system register using 12-bit SYSm value.
// Note: the search is uniqued using M1 mask
const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm) {
return lookupMClassSysRegByM1Encoding12(SYSm);
}
// returns APSR with _<bits> qualifier.
// Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm) {
return lookupMClassSysRegByM2M3Encoding8((1<<9)|(SYSm & 0xFF));
}
// lookup system registers using 8-bit SYSm value
const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm) {
return ARMSysReg::lookupMClassSysRegByM2M3Encoding8((1<<8)|(SYSm & 0xFF));
}
#define GET_MCLASSSYSREG_IMPL
#include "ARMGenSystemRegister.inc"
}
}

View File

@ -0,0 +1,64 @@
//===-- ARMBaseInfo.h - Top level definitions for ARM ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains small standalone helper functions and enum definitions for
// the ARM target useful for the compiler back-end and the MC libraries.
// As such, it deliberately does not include references to LLVM core
// code gen types, passes, etc..
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
#define LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/MC/SubtargetFeature.h"
#include "MCTargetDesc/ARMMCTargetDesc.h"
namespace llvm {
namespace ARMSysReg {
struct MClassSysReg {
const char *Name;
uint16_t M1Encoding12;
uint16_t M2M3Encoding8;
uint16_t Encoding;
FeatureBitset FeaturesRequired;
// return true if FeaturesRequired are all present in ActiveFeatures
bool hasRequiredFeatures(FeatureBitset ActiveFeatures) const {
return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
}
// returns true if TestFeatures are all present in FeaturesRequired
bool isInRequiredFeatures(FeatureBitset TestFeatures) const {
return (FeaturesRequired & TestFeatures) == TestFeatures;
}
};
#define GET_MCLASSSYSREG_DECL
#include "ARMGenSystemRegister.inc"
// lookup system register using 12-bit SYSm value.
// Note: the search is uniqued using M1 mask
const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm);
// returns APSR with _<bits> qualifier.
// Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm);
// lookup system registers using 8-bit SYSm value
const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm);
} // end namespace ARMSysReg
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H

View File

@ -0,0 +1,3 @@
add_llvm_library(LLVMARMUtils
ARMBaseInfo.cpp
)

View File

@ -0,0 +1,24 @@
;===- ./lib/Target/ARM/Utils/LLVMBuild.txt ----------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = ARMUtils
parent = ARM
required_libraries = Support
add_to_library_groups = ARM

View File

@ -1,7 +1,7 @@
; RUN: not llc < %s -mtriple=thumbv8m.base-none-eabi 2>&1 | FileCheck %s --check-prefix=BASELINE
; RUN: llc < %s -mtriple=thumbv8m.main-none-eabi -mattr=+dsp 2>&1 | FileCheck %s --check-prefix=MAINLINE
; BASELINE: LLVM ERROR: Invalid register name "basepri_max_ns".
; BASELINE: LLVM ERROR: Invalid register name "faultmask_ns".
define i32 @read_mclass_registers() nounwind {
entry:
@ -31,7 +31,6 @@ entry:
; MAINLINE: mrs r1, faultmask_ns
; MAINLINE: mrs r1, control_ns
; MAINLINE: mrs r1, sp_ns
; MAINLINE: mrs r1, basepri_max_ns
%0 = call i32 @llvm.read_register.i32(metadata !0)
%1 = call i32 @llvm.read_register.i32(metadata !4)
@ -82,9 +81,7 @@ entry:
%add23 = add i32 %add22, %23
%24 = call i32 @llvm.read_register.i32(metadata !36)
%add24 = add i32 %add23, %24
%25 = call i32 @llvm.read_register.i32(metadata !37)
%add25 = add i32 %add24, %25
ret i32 %add25
ret i32 %add24
}
define void @write_mclass_registers(i32 %x) nounwind {
@ -127,7 +124,6 @@ entry:
; MAINLINE: msr faultmask_ns, r0
; MAINLINE: msr control_ns, r0
; MAINLINE: msr sp_ns, r0
; MAINLINE: msr basepri_max_ns, r0
call void @llvm.write_register.i32(metadata !0, i32 %x)
call void @llvm.write_register.i32(metadata !1, i32 %x)
@ -166,7 +162,6 @@ entry:
call void @llvm.write_register.i32(metadata !34, i32 %x)
call void @llvm.write_register.i32(metadata !35, i32 %x)
call void @llvm.write_register.i32(metadata !36, i32 %x)
call void @llvm.write_register.i32(metadata !37, i32 %x)
ret void
}
@ -210,5 +205,4 @@ declare void @llvm.write_register.i32(metadata, i32) nounwind
!34 = !{!"faultmask_ns"}
!35 = !{!"control_ns"}
!36 = !{!"sp_ns"}
!37 = !{!"basepri_max_ns"}

View File

@ -215,17 +215,12 @@ MSR PSPLIM,r9
// CHECK: msr psplim, r9 @ encoding: [0x89,0xf3,0x0b,0x88]
MRS r10, MSPLIM_NS
// CHECK-MAINLINE: mrs r10, msplim_ns @ encoding: [0xef,0xf3,0x8a,0x8a]
// UNDEF-BASELINE: error: invalid operand for instruction
// CHECK: mrs r10, msplim_ns @ encoding: [0xef,0xf3,0x8a,0x8a]
MSR PSPLIM_NS, r11
// CHECK-MAINLINE: msr psplim_ns, r11 @ encoding: [0x8b,0xf3,0x8b,0x88]
// UNDEF-BASELINE: error: invalid operand for instruction
// CHECK: msr psplim_ns, r11 @ encoding: [0x8b,0xf3,0x8b,0x88]
MRS r12, BASEPRI_NS
// CHECK-MAINLINE: mrs r12, basepri_ns @ encoding: [0xef,0xf3,0x91,0x8c]
// UNDEF-BASELINE: error: invalid operand for instruction
MRS r12, BASEPRI_MAX_NS
// CHECK-MAINLINE: mrs r12, basepri_max_ns @ encoding: [0xef,0xf3,0x92,0x8c]
// UNDEF-BASELINE: error: invalid operand for instruction
MSR FAULTMASK_NS, r14
// CHECK-MAINLINE: msr faultmask_ns, lr @ encoding: [0x8e,0xf3,0x93,0x88]
// UNDEF-BASELINE: error: invalid operand for instruction