summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorTom Coxon <tom.coxon@arm.com>2014-10-01 10:13:59 +0000
committerTom Coxon <tom.coxon@arm.com>2014-10-01 10:13:59 +0000
commite493f177eeee84a9c6000ca7c92499233490f1d1 (patch)
tree613ad78107f7dd0817fb95636899b8e86ed2db30 /llvm/lib
parent815f2869adfe7e9dfec14f4f30639a6c129ee5cf (diff)
downloadbcm5719-llvm-e493f177eeee84a9c6000ca7c92499233490f1d1.tar.gz
bcm5719-llvm-e493f177eeee84a9c6000ca7c92499233490f1d1.zip
[AArch64] Allow access to all system registers with MRS/MSR instructions.
The A64 instruction set includes a generic register syntax for accessing implementation-defined system registers. The syntax for these registers is: S<op0>_<op1>_<CRn>_<CRm>_<op2> The encoding space permitted for implementation-defined system registers is: op0 op1 CRn CRm op2 11 xxx 1x11 xxxx xxx The full encoding space can now be accessed: op0 op1 CRn CRm op2 xx xxx xxxx xxxx xxx This is useful to anyone needing to write assembly code supporting new system registers before the assembler has learned the official names for them. llvm-svn: 218753
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrFormats.td12
-rw-r--r--llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp24
-rw-r--r--llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp12
-rw-r--r--llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp36
-rw-r--r--llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h2
5 files changed, 26 insertions, 60 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 4b89035fa8e..2b0f5d2e32a 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -843,7 +843,7 @@ def MRSSystemRegisterOperand : AsmOperandClass {
let ParserMethod = "tryParseSysReg";
let DiagnosticType = "MRS";
}
-// concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
+// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
def mrs_sysreg_op : Operand<i32> {
let ParserMatchClass = MRSSystemRegisterOperand;
let DecoderMethod = "DecodeMRSSystemRegister";
@@ -863,9 +863,8 @@ def msr_sysreg_op : Operand<i32> {
class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
"mrs", "\t$Rt, $systemreg"> {
- bits<15> systemreg;
- let Inst{20} = 1;
- let Inst{19-5} = systemreg;
+ bits<16> systemreg;
+ let Inst{20-5} = systemreg;
}
// FIXME: Some of these def NZCV, others don't. Best way to model that?
@@ -873,9 +872,8 @@ class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
// would do it, but feels like overkill at this point.
class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
"msr", "\t$systemreg, $Rt"> {
- bits<15> systemreg;
- let Inst{20} = 1;
- let Inst{19-5} = systemreg;
+ bits<16> systemreg;
+ let Inst{20-5} = systemreg;
}
def SystemPStateFieldOperand : AsmOperandClass {
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 87b2d5096dd..f522ca59a9a 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -626,35 +626,19 @@ static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm,
static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm,
uint64_t Address,
const void *Decoder) {
- const AArch64Disassembler *Dis =
- static_cast<const AArch64Disassembler *>(Decoder);
- const MCSubtargetInfo &STI = Dis->getSubtargetInfo();
-
- Imm |= 0x8000;
Inst.addOperand(MCOperand::CreateImm(Imm));
- bool ValidNamed;
- (void)AArch64SysReg::MRSMapper(STI.getFeatureBits())
- .toString(Imm, ValidNamed);
-
- return ValidNamed ? Success : Fail;
+ // Every system register in the encoding space is valid with the syntax
+ // S<op0>_<op1>_<Cn>_<Cm>_<op2>, so decoding system registers always succeeds.
+ return Success;
}
static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm,
uint64_t Address,
const void *Decoder) {
- const AArch64Disassembler *Dis =
- static_cast<const AArch64Disassembler *>(Decoder);
- const MCSubtargetInfo &STI = Dis->getSubtargetInfo();
-
- Imm |= 0x8000;
Inst.addOperand(MCOperand::CreateImm(Imm));
- bool ValidNamed;
- (void)AArch64SysReg::MSRMapper(STI.getFeatureBits())
- .toString(Imm, ValidNamed);
-
- return ValidNamed ? Success : Fail;
+ return Success;
}
static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn,
diff --git a/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
index 0091ab354a0..46a1d797872 100644
--- a/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
@@ -1276,24 +1276,20 @@ void AArch64InstPrinter::printMRSSystemRegister(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned Val = MI->getOperand(OpNo).getImm();
- bool Valid;
auto Mapper = AArch64SysReg::MRSMapper(getAvailableFeatures());
- std::string Name = Mapper.toString(Val, Valid);
+ std::string Name = Mapper.toString(Val);
- if (Valid)
- O << StringRef(Name).upper();
+ O << StringRef(Name).upper();
}
void AArch64InstPrinter::printMSRSystemRegister(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned Val = MI->getOperand(OpNo).getImm();
- bool Valid;
auto Mapper = AArch64SysReg::MSRMapper(getAvailableFeatures());
- std::string Name = Mapper.toString(Val, Valid);
+ std::string Name = Mapper.toString(Val);
- if (Valid)
- O << StringRef(Name).upper();
+ O << StringRef(Name).upper();
}
void AArch64InstPrinter::printSystemPStateField(const MCInst *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
index 3c24bb30a26..bc6c7a96f85 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
@@ -791,22 +791,22 @@ AArch64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
}
}
- // Try to parse an S<op0>_<op1>_<Cn>_<Cm>_<op2> register name, where the bits
- // are: 11 xxx 1x11 xxxx xxx
- Regex GenericRegPattern("^s3_([0-7])_c(1[15])_c([0-9]|1[0-5])_([0-7])$");
+ // Try to parse an S<op0>_<op1>_<Cn>_<Cm>_<op2> register name
+ Regex GenericRegPattern("^s([0-3])_([0-7])_c([0-9]|1[0-5])_c([0-9]|1[0-5])_([0-7])$");
- SmallVector<StringRef, 4> Ops;
+ SmallVector<StringRef, 5> Ops;
if (!GenericRegPattern.match(NameLower, &Ops)) {
Valid = false;
return -1;
}
- uint32_t Op0 = 3, Op1 = 0, CRn = 0, CRm = 0, Op2 = 0;
+ uint32_t Op0 = 0, Op1 = 0, CRn = 0, CRm = 0, Op2 = 0;
uint32_t Bits;
- Ops[1].getAsInteger(10, Op1);
- Ops[2].getAsInteger(10, CRn);
- Ops[3].getAsInteger(10, CRm);
- Ops[4].getAsInteger(10, Op2);
+ Ops[1].getAsInteger(10, Op0);
+ Ops[2].getAsInteger(10, Op1);
+ Ops[3].getAsInteger(10, CRn);
+ Ops[4].getAsInteger(10, CRm);
+ Ops[5].getAsInteger(10, Op2);
Bits = (Op0 << 14) | (Op1 << 11) | (CRn << 7) | (CRm << 3) | Op2;
Valid = true;
@@ -814,11 +814,10 @@ AArch64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
}
std::string
-AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
+AArch64SysReg::SysRegMapper::toString(uint32_t Bits) const {
// First search the registers shared by all
for (unsigned i = 0; i < array_lengthof(SysRegPairs); ++i) {
if (SysRegPairs[i].Value == Bits) {
- Valid = true;
return SysRegPairs[i].Name;
}
}
@@ -827,7 +826,6 @@ AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
if (FeatureBits & AArch64::ProcCyclone) {
for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) {
if (CycloneSysRegPairs[i].Value == Bits) {
- Valid = true;
return CycloneSysRegPairs[i].Name;
}
}
@@ -837,28 +835,18 @@ AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
// write-only).
for (unsigned i = 0; i < NumInstPairs; ++i) {
if (InstPairs[i].Value == Bits) {
- Valid = true;
return InstPairs[i].Name;
}
}
+ assert(Bits < 0x10000);
uint32_t Op0 = (Bits >> 14) & 0x3;
uint32_t Op1 = (Bits >> 11) & 0x7;
uint32_t CRn = (Bits >> 7) & 0xf;
uint32_t CRm = (Bits >> 3) & 0xf;
uint32_t Op2 = Bits & 0x7;
- // Only combinations matching: 11 xxx 1x11 xxxx xxx are valid for a generic
- // name.
- if (Op0 != 3 || (CRn != 11 && CRn != 15)) {
- Valid = false;
- return "";
- }
-
- assert(Op0 == 3 && (CRn == 11 || CRn == 15) && "Invalid generic sysreg");
-
- Valid = true;
- return "s3_" + utostr(Op1) + "_c" + utostr(CRn)
+ return "s" + utostr(Op0)+ "_" + utostr(Op1) + "_c" + utostr(CRn)
+ "_c" + utostr(CRm) + "_" + utostr(Op2);
}
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index 326eb9995d7..c60b09a5f11 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -1143,7 +1143,7 @@ namespace AArch64SysReg {
SysRegMapper(uint64_t FeatureBits) : FeatureBits(FeatureBits) { }
uint32_t fromString(StringRef Name, bool &Valid) const;
- std::string toString(uint32_t Bits, bool &Valid) const;
+ std::string toString(uint32_t Bits) const;
};
struct MSRMapper : SysRegMapper {
OpenPOWER on IntegriCloud