mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-27 15:02:16 +00:00
[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:
parent
e845d29c41
commit
ca6d1aaf93
@ -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;
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "ARMSystemRegister.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declarations that describe the ARM register file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
108
lib/Target/ARM/ARMSystemRegister.td
Normal file
108
lib/Target/ARM/ARMSystemRegister.td
Normal 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">;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -19,5 +19,5 @@
|
||||
type = Library
|
||||
name = ARMAsmPrinter
|
||||
parent = ARM
|
||||
required_libraries = MC Support
|
||||
required_libraries = MC Support ARMUtils
|
||||
add_to_library_groups = ARM
|
||||
|
@ -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
|
||||
|
44
lib/Target/ARM/Utils/ARMBaseInfo.cpp
Normal file
44
lib/Target/ARM/Utils/ARMBaseInfo.cpp
Normal 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"
|
||||
|
||||
}
|
||||
}
|
64
lib/Target/ARM/Utils/ARMBaseInfo.h
Normal file
64
lib/Target/ARM/Utils/ARMBaseInfo.h
Normal 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
|
3
lib/Target/ARM/Utils/CMakeLists.txt
Normal file
3
lib/Target/ARM/Utils/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_llvm_library(LLVMARMUtils
|
||||
ARMBaseInfo.cpp
|
||||
)
|
24
lib/Target/ARM/Utils/LLVMBuild.txt
Normal file
24
lib/Target/ARM/Utils/LLVMBuild.txt
Normal 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
|
||||
|
@ -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"}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user