From e29cd17aeb82c9efb8752a901149cbf22359d1d9 Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Thu, 1 May 2014 10:25:36 +0000 Subject: [PATCH] [ARM64] Conditionalize CPU specific system registers on subtarget features git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207742 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp | 26 ++++++++++--- .../ARM64/Disassembler/ARM64Disassembler.cpp | 12 +++++- .../ARM64/InstPrinter/ARM64InstPrinter.cpp | 4 +- lib/Target/ARM64/Utils/ARM64BaseInfo.cpp | 38 +++++++++++++++++-- lib/Target/ARM64/Utils/ARM64BaseInfo.h | 12 ++++-- test/MC/ARM64/system-encoding.s | 2 - test/MC/ARM64/target-specific-sysreg.s | 10 +++++ 7 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 test/MC/ARM64/target-specific-sysreg.s diff --git a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index 764999b4e7b..bad7a1ce58a 100644 --- a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -195,6 +195,9 @@ private: struct SysRegOp { const char *Data; unsigned Length; + uint64_t FeatureBits; // We need to pass through information about which + // core we are compiling for so that the SysReg + // Mappers can appropriately conditionalize. }; struct SysCRImmOp { @@ -351,6 +354,11 @@ public: return StringRef(SysReg.Data, SysReg.Length); } + uint64_t getSysRegFeatureBits() const { + assert(Kind == k_SysReg && "Invalid access!"); + return SysReg.FeatureBits; + } + unsigned getSysCR() const { assert(Kind == k_SysCR && "Invalid access!"); return SysCRImm.Val; @@ -668,7 +676,8 @@ public: if (!isSysReg()) return false; bool IsKnownRegister; - ARM64SysReg::MRSMapper().fromString(getSysReg(), IsKnownRegister); + auto Mapper = ARM64SysReg::MRSMapper(getSysRegFeatureBits()); + Mapper.fromString(getSysReg(), IsKnownRegister); return IsKnownRegister; } @@ -676,7 +685,8 @@ public: if (!isSysReg()) return false; bool IsKnownRegister; - ARM64SysReg::MSRMapper().fromString(getSysReg(), IsKnownRegister); + auto Mapper = ARM64SysReg::MSRMapper(getSysRegFeatureBits()); + Mapper.fromString(getSysReg(), IsKnownRegister); return IsKnownRegister; } @@ -1332,7 +1342,8 @@ public: assert(N == 1 && "Invalid number of operands!"); bool Valid; - uint32_t Bits = ARM64SysReg::MRSMapper().fromString(getSysReg(), Valid); + auto Mapper = ARM64SysReg::MRSMapper(getSysRegFeatureBits()); + uint32_t Bits = Mapper.fromString(getSysReg(), Valid); Inst.addOperand(MCOperand::CreateImm(Bits)); } @@ -1341,7 +1352,8 @@ public: assert(N == 1 && "Invalid number of operands!"); bool Valid; - uint32_t Bits = ARM64SysReg::MSRMapper().fromString(getSysReg(), Valid); + auto Mapper = ARM64SysReg::MSRMapper(getSysRegFeatureBits()); + uint32_t Bits = Mapper.fromString(getSysReg(), Valid); Inst.addOperand(MCOperand::CreateImm(Bits)); } @@ -1666,10 +1678,12 @@ public: return Op; } - static ARM64Operand *CreateSysReg(StringRef Str, SMLoc S, MCContext &Ctx) { + static ARM64Operand *CreateSysReg(StringRef Str, SMLoc S, + uint64_t FeatureBits, MCContext &Ctx) { ARM64Operand *Op = new ARM64Operand(k_SysReg, Ctx); Op->SysReg.Data = Str.data(); Op->SysReg.Length = Str.size(); + Op->SysReg.FeatureBits = FeatureBits; Op->StartLoc = S; Op->EndLoc = S; return Op; @@ -2682,7 +2696,7 @@ ARM64AsmParser::tryParseSysReg(OperandVector &Operands) { return MatchOperand_NoMatch; Operands.push_back(ARM64Operand::CreateSysReg(Tok.getString(), getLoc(), - getContext())); + STI.getFeatureBits(), getContext())); Parser.Lex(); // Eat identifier return MatchOperand_Success; diff --git a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp index 0fc559c5cf7..f53592a73aa 100644 --- a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -601,11 +601,15 @@ static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { + const ARM64Disassembler *Dis = + static_cast(Decoder); + const MCSubtargetInfo &STI = Dis->getSubtargetInfo(); + Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); bool ValidNamed; - (void)ARM64SysReg::MRSMapper().toString(Imm, ValidNamed); + (void)ARM64SysReg::MRSMapper(STI.getFeatureBits()).toString(Imm, ValidNamed); return ValidNamed ? Success : Fail; } @@ -613,11 +617,15 @@ static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { + const ARM64Disassembler *Dis = + static_cast(Decoder); + const MCSubtargetInfo &STI = Dis->getSubtargetInfo(); + Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); bool ValidNamed; - (void)ARM64SysReg::MSRMapper().toString(Imm, ValidNamed); + (void)ARM64SysReg::MSRMapper(STI.getFeatureBits()).toString(Imm, ValidNamed); return ValidNamed ? Success : Fail; } diff --git a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp index 65d5eae2d21..8d217a9b394 100644 --- a/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp +++ b/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp @@ -1397,7 +1397,7 @@ void ARM64InstPrinter::printMRSSystemRegister(const MCInst *MI, unsigned OpNo, unsigned Val = MI->getOperand(OpNo).getImm(); bool Valid; - auto Mapper = ARM64SysReg::MRSMapper(); + auto Mapper = ARM64SysReg::MRSMapper(getAvailableFeatures()); std::string Name = Mapper.toString(Val, Valid); if (Valid) @@ -1409,7 +1409,7 @@ void ARM64InstPrinter::printMSRSystemRegister(const MCInst *MI, unsigned OpNo, unsigned Val = MI->getOperand(OpNo).getImm(); bool Valid; - auto Mapper = ARM64SysReg::MSRMapper(); + auto Mapper = ARM64SysReg::MSRMapper(getAvailableFeatures()); std::string Name = Mapper.toString(Val, Valid); if (Valid) diff --git a/lib/Target/ARM64/Utils/ARM64BaseInfo.cpp b/lib/Target/ARM64/Utils/ARM64BaseInfo.cpp index 8ab18e5fdbd..5142d18c23c 100644 --- a/lib/Target/ARM64/Utils/ARM64BaseInfo.cpp +++ b/lib/Target/ARM64/Utils/ARM64BaseInfo.cpp @@ -245,7 +245,8 @@ const ARM64NamedImmMapper::Mapping ARM64SysReg::MRSMapper::MRSPairs[] = { {"ich_elsr_el2", ICH_ELSR_EL2} }; -ARM64SysReg::MRSMapper::MRSMapper() { +ARM64SysReg::MRSMapper::MRSMapper(uint64_t FeatureBits) + : SysRegMapper(FeatureBits) { InstPairs = &MRSPairs[0]; NumInstPairs = llvm::array_lengthof(MRSPairs); } @@ -268,7 +269,8 @@ const ARM64NamedImmMapper::Mapping ARM64SysReg::MSRMapper::MSRPairs[] = { {"icc_sgi0r_el1", ICC_SGI0R_EL1} }; -ARM64SysReg::MSRMapper::MSRMapper() { +ARM64SysReg::MSRMapper::MSRMapper(uint64_t FeatureBits) + : SysRegMapper(FeatureBits) { InstPairs = &MSRPairs[0]; NumInstPairs = llvm::array_lengthof(MSRPairs); } @@ -750,14 +752,19 @@ const ARM64NamedImmMapper::Mapping ARM64SysReg::SysRegMapper::SysRegPairs[] = { {"ich_lr12_el2", ICH_LR12_EL2}, {"ich_lr13_el2", ICH_LR13_EL2}, {"ich_lr14_el2", ICH_LR14_EL2}, - {"ich_lr15_el2", ICH_LR15_EL2}, + {"ich_lr15_el2", ICH_LR15_EL2} +}; + +const ARM64NamedImmMapper::Mapping +ARM64SysReg::SysRegMapper::CycloneSysRegPairs[] = { {"cpm_ioacc_ctl_el3", CPM_IOACC_CTL_EL3} }; uint32_t ARM64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const { - // First search the registers shared by all std::string NameLower = Name.lower(); + + // First search the registers shared by all for (unsigned i = 0; i < array_lengthof(SysRegPairs); ++i) { if (SysRegPairs[i].Name == NameLower) { Valid = true; @@ -765,6 +772,16 @@ ARM64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const { } } + // Next search for target specific registers + if (FeatureBits & ARM64::ProcCyclone) { + for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) { + if (CycloneSysRegPairs[i].Name == NameLower) { + Valid = true; + return CycloneSysRegPairs[i].Value; + } + } + } + // Now try the instruction-specific registers (either read-only or // write-only). for (unsigned i = 0; i < NumInstPairs; ++i) { @@ -798,6 +815,7 @@ ARM64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const { std::string ARM64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const { + // First search the registers shared by all for (unsigned i = 0; i < array_lengthof(SysRegPairs); ++i) { if (SysRegPairs[i].Value == Bits) { Valid = true; @@ -805,6 +823,18 @@ ARM64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const { } } + // Next search for target specific registers + if (FeatureBits & ARM64::ProcCyclone) { + for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) { + if (CycloneSysRegPairs[i].Value == Bits) { + Valid = true; + return CycloneSysRegPairs[i].Name; + } + } + } + + // Now try the instruction-specific registers (either read-only or + // write-only). for (unsigned i = 0; i < NumInstPairs; ++i) { if (InstPairs[i].Value == Bits) { Valid = true; diff --git a/lib/Target/ARM64/Utils/ARM64BaseInfo.h b/lib/Target/ARM64/Utils/ARM64BaseInfo.h index ef4caefab94..8075d6b37c9 100644 --- a/lib/Target/ARM64/Utils/ARM64BaseInfo.h +++ b/lib/Target/ARM64/Utils/ARM64BaseInfo.h @@ -1136,8 +1136,10 @@ namespace ARM64SysReg { ICH_LR13_EL2 = 0xe66d, // 11 100 1100 1101 101 ICH_LR14_EL2 = 0xe66e, // 11 100 1100 1101 110 ICH_LR15_EL2 = 0xe66f, // 11 100 1100 1101 111 + }; - // Cyclone specific system registers + // Cyclone specific system registers + enum CycloneSysRegValues { CPM_IOACC_CTL_EL3 = 0xff90 }; @@ -1147,23 +1149,25 @@ namespace ARM64SysReg { // this one case. struct SysRegMapper { static const ARM64NamedImmMapper::Mapping SysRegPairs[]; + static const ARM64NamedImmMapper::Mapping CycloneSysRegPairs[]; const ARM64NamedImmMapper::Mapping *InstPairs; size_t NumInstPairs; + uint64_t FeatureBits; - SysRegMapper() {} + SysRegMapper(uint64_t FeatureBits) : FeatureBits(FeatureBits) { } uint32_t fromString(StringRef Name, bool &Valid) const; std::string toString(uint32_t Bits, bool &Valid) const; }; struct MSRMapper : SysRegMapper { static const ARM64NamedImmMapper::Mapping MSRPairs[]; - MSRMapper(); + MSRMapper(uint64_t FeatureBits); }; struct MRSMapper : SysRegMapper { static const ARM64NamedImmMapper::Mapping MRSPairs[]; - MRSMapper(); + MRSMapper(uint64_t FeatureBits); }; uint32_t ParseGenericRegister(StringRef Name, bool &Valid); diff --git a/test/MC/ARM64/system-encoding.s b/test/MC/ARM64/system-encoding.s index 9b3238bfb13..fc17a1bdf24 100644 --- a/test/MC/ARM64/system-encoding.s +++ b/test/MC/ARM64/system-encoding.s @@ -586,14 +586,12 @@ foo: msr RMR_EL3, x0 msr RMR_EL2, x0 msr RMR_EL1, x0 - msr CPM_IOACC_CTL_EL3, x0 msr OSLAR_EL1, x3 msr DBGDTRTX_EL0, x3 ; CHECK: msr RMR_EL3, x0 ; encoding: [0x40,0xc0,0x1e,0xd5] ; CHECK: msr RMR_EL2, x0 ; encoding: [0x40,0xc0,0x1c,0xd5] ; CHECK: msr RMR_EL1, x0 ; encoding: [0x40,0xc0,0x18,0xd5] -; CHECK: msr CPM_IOACC_CTL_EL3, x0 ; encoding: [0x00,0xf2,0x1f,0xd5] ; CHECK: msr OSLAR_EL1, x3 ; encoding: [0x83,0x10,0x10,0xd5] ; CHECK: msr DBGDTRTX_EL0, x3 ; encoding: [0x03,0x05,0x13,0xd5] diff --git a/test/MC/ARM64/target-specific-sysreg.s b/test/MC/ARM64/target-specific-sysreg.s new file mode 100644 index 00000000000..05cea3ac2da --- /dev/null +++ b/test/MC/ARM64/target-specific-sysreg.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -triple arm64 -mcpu=generic -show-encoding < %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-GENERIC +// +// RUN: llvm-mc -triple arm64 -mcpu=cyclone -show-encoding < %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-CYCLONE + +msr CPM_IOACC_CTL_EL3, x0 + +// CHECK-GENERIC: error: expected writable system register or pstate +// CHECK-CYCLONE: msr CPM_IOACC_CTL_EL3, x0 // encoding: [0x00,0xf2,0x1f,0xd5]