Index: lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp =================================================================== --- lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -195,6 +195,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return MatchOperand_NoMatch; Operands.push_back(ARM64Operand::CreateSysReg(Tok.getString(), getLoc(), - getContext())); + STI.getFeatureBits(), getContext())); Parser.Lex(); // Eat identifier return MatchOperand_Success; Index: lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp =================================================================== --- lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -601,11 +601,15 @@ 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 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; } Index: lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp =================================================================== --- lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp +++ lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp @@ -1397,7 +1397,7 @@ 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 @@ 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) Index: lib/Target/ARM64/Utils/ARM64BaseInfo.h =================================================================== --- lib/Target/ARM64/Utils/ARM64BaseInfo.h +++ lib/Target/ARM64/Utils/ARM64BaseInfo.h @@ -1136,8 +1136,10 @@ 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 @@ // 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); Index: lib/Target/ARM64/Utils/ARM64BaseInfo.cpp =================================================================== --- lib/Target/ARM64/Utils/ARM64BaseInfo.cpp +++ lib/Target/ARM64/Utils/ARM64BaseInfo.cpp @@ -245,7 +245,8 @@ {"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 @@ {"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 @@ {"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 @@ } } + // 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 @@ 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 @@ } } + // 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; Index: test/MC/ARM64/system-encoding.s =================================================================== --- test/MC/ARM64/system-encoding.s +++ test/MC/ARM64/system-encoding.s @@ -586,14 +586,12 @@ 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] Index: test/MC/ARM64/target-specific-sysreg.s =================================================================== --- /dev/null +++ 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]