From: Bradley Smith Date: Wed, 9 Apr 2014 14:43:06 +0000 (+0000) Subject: [ARM64] Rework system register parsing to overcome SPSel clash in MSR variants. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3d41487f0efa0079bdf24b95d09bb3eb1590f6ed;p=oota-llvm.git [ARM64] Rework system register parsing to overcome SPSel clash in MSR variants. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205875 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM64/ARM64InstrFormats.td b/lib/Target/ARM64/ARM64InstrFormats.td index f6811ee6681..16db02ed275 100644 --- a/lib/Target/ARM64/ARM64InstrFormats.td +++ b/lib/Target/ARM64/ARM64InstrFormats.td @@ -701,9 +701,7 @@ class CRmSystemI opc, string asm> // a different subset of registers can be accessed through each instruction. def MRSSystemRegisterOperand : AsmOperandClass { let Name = "MRSSystemRegister"; - let ParserMethod = "tryParseMRSSystemRegister"; - let RenderMethod = "addSystemRegisterOperands"; - let PredicateMethod = "isSystemRegister"; + let ParserMethod = "tryParseSysReg"; } // concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate. def mrs_sysreg_op : Operand { @@ -714,9 +712,7 @@ def mrs_sysreg_op : Operand { def MSRSystemRegisterOperand : AsmOperandClass { let Name = "MSRSystemRegister"; - let ParserMethod = "tryParseMSRSystemRegister"; - let RenderMethod = "addSystemRegisterOperands"; - let PredicateMethod = "isSystemRegister"; + let ParserMethod = "tryParseSysReg"; } def msr_sysreg_op : Operand { let ParserMatchClass = MSRSystemRegisterOperand; @@ -743,7 +739,7 @@ class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt), def SystemCPSRFieldOperand : AsmOperandClass { let Name = "SystemCPSRField"; - let ParserMethod = "tryParseCPSRField"; + let ParserMethod = "tryParseSysReg"; } def cpsrfield_op : Operand { let ParserMatchClass = SystemCPSRFieldOperand; diff --git a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index 7fe336329b7..79a4cd5a4d7 100644 --- a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -89,8 +89,7 @@ private: OperandMatchResultTy tryParseNoIndexMemory(OperandVector &Operands); OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands); OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands); - OperandMatchResultTy tryParseMSRSystemRegister(OperandVector &Operands); - OperandMatchResultTy tryParseCPSRField(OperandVector &Operands); + OperandMatchResultTy tryParseSysReg(OperandVector &Operands); OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands); OperandMatchResultTy tryParsePrefetch(OperandVector &Operands); OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands); @@ -142,14 +141,13 @@ private: k_VectorList, k_VectorIndex, k_Token, + k_SysReg, k_SysCR, k_Prefetch, k_Shifter, k_Extend, k_FPImm, - k_Barrier, - k_SystemRegister, - k_CPSRField + k_Barrier } Kind; SMLoc StartLoc, EndLoc, OffsetLoc; @@ -188,14 +186,9 @@ private: unsigned Val; // Not the enum since not all values have names. }; - struct SystemRegisterOp { - // 16-bit immediate, usually from the ARM64SysReg::SysRegValues enum - // but not limited to those values. - uint16_t Val; - }; - - struct CPSRFieldOp { - ARM64PState::PStateValues Field; + struct SysRegOp { + const char *Data; + unsigned Length; }; struct SysCRImmOp { @@ -232,8 +225,7 @@ private: struct ImmOp Imm; struct FPImmOp FPImm; struct BarrierOp Barrier; - struct SystemRegisterOp SystemRegister; - struct CPSRFieldOp CPSRField; + struct SysRegOp SysReg; struct SysCRImmOp SysCRImm; struct PrefetchOp Prefetch; struct ShifterOp Shifter; @@ -266,12 +258,6 @@ public: case k_Barrier: Barrier = o.Barrier; break; - case k_SystemRegister: - SystemRegister = o.SystemRegister; - break; - case k_CPSRField: - CPSRField = o.CPSRField; - break; case k_Register: Reg = o.Reg; break; @@ -281,6 +267,9 @@ public: case k_VectorIndex: VectorIndex = o.VectorIndex; break; + case k_SysReg: + SysReg = o.SysReg; + break; case k_SysCR: SysCRImm = o.SysCRImm; break; @@ -331,16 +320,6 @@ public: return Barrier.Val; } - uint16_t getSystemRegister() const { - assert(Kind == k_SystemRegister && "Invalid access!"); - return SystemRegister.Val; - } - - ARM64PState::PStateValues getCPSRField() const { - assert(Kind == k_CPSRField && "Invalid access!"); - return CPSRField.Field; - } - unsigned getReg() const { assert(Kind == k_Register && "Invalid access!"); return Reg.RegNum; @@ -361,6 +340,11 @@ public: return VectorIndex.Val; } + StringRef getSysReg() const { + assert(Kind == k_SysReg && "Invalid access!"); + return StringRef(SysReg.Data, SysReg.Length); + } + unsigned getSysCR() const { assert(Kind == k_SysCR && "Invalid access!"); return SysCRImm.Val; @@ -665,14 +649,31 @@ public: bool isFPImm() const { return Kind == k_FPImm; } bool isBarrier() const { return Kind == k_Barrier; } - bool isSystemRegister() const { - if (Kind == k_SystemRegister) - return true; - // SPSel is legal for both the system register and the CPSR-field - // variants of MSR, so special case that. Fugly. - return (Kind == k_CPSRField && getCPSRField() == ARM64PState::SPSel); + bool isSysReg() const { return Kind == k_SysReg; } + bool isMRSSystemRegister() const { + if (!isSysReg()) return false; + + bool IsKnownRegister; + ARM64SysReg::MRSMapper().fromString(getSysReg(), IsKnownRegister); + + return IsKnownRegister; + } + bool isMSRSystemRegister() const { + if (!isSysReg()) return false; + + bool IsKnownRegister; + ARM64SysReg::MSRMapper().fromString(getSysReg(), IsKnownRegister); + + return IsKnownRegister; + } + bool isSystemCPSRField() const { + if (!isSysReg()) return false; + + bool IsKnownRegister; + ARM64PState::PStateMapper().fromString(getSysReg(), IsKnownRegister); + + return IsKnownRegister; } - bool isSystemCPSRField() const { return Kind == k_CPSRField; } bool isReg() const { return Kind == k_Register && !Reg.isVector; } bool isVectorReg() const { return Kind == k_Register && Reg.isVector; } @@ -1280,19 +1281,31 @@ public: Inst.addOperand(MCOperand::CreateImm(getBarrier())); } - void addSystemRegisterOperands(MCInst &Inst, unsigned N) const { + void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - if (Kind == k_SystemRegister) - Inst.addOperand(MCOperand::CreateImm(getSystemRegister())); - else { - assert(Kind == k_CPSRField && getCPSRField() == ARM64PState::SPSel); - Inst.addOperand(MCOperand::CreateImm(ARM64SysReg::SPSel)); - } + + bool Valid; + uint32_t Bits = ARM64SysReg::MRSMapper().fromString(getSysReg(), Valid); + + Inst.addOperand(MCOperand::CreateImm(Bits)); + } + + void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + + bool Valid; + uint32_t Bits = ARM64SysReg::MSRMapper().fromString(getSysReg(), Valid); + + Inst.addOperand(MCOperand::CreateImm(Bits)); } void addSystemCPSRFieldOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getCPSRField())); + + bool Valid; + uint32_t Bits = ARM64PState::PStateMapper().fromString(getSysReg(), Valid); + + Inst.addOperand(MCOperand::CreateImm(Bits)); } void addSysCROperands(MCInst &Inst, unsigned N) const { @@ -1606,19 +1619,10 @@ public: return Op; } - static ARM64Operand *CreateSystemRegister(uint16_t Val, SMLoc S, - MCContext &Ctx) { - ARM64Operand *Op = new ARM64Operand(k_SystemRegister, Ctx); - Op->SystemRegister.Val = Val; - Op->StartLoc = S; - Op->EndLoc = S; - return Op; - } - - static ARM64Operand *CreateCPSRField(ARM64PState::PStateValues Field, SMLoc S, - MCContext &Ctx) { - ARM64Operand *Op = new ARM64Operand(k_CPSRField, Ctx); - Op->CPSRField.Field = Field; + static ARM64Operand *CreateSysReg(StringRef Str, SMLoc S, MCContext &Ctx) { + ARM64Operand *Op = new ARM64Operand(k_SysReg, Ctx); + Op->SysReg.Data = Str.data(); + Op->SysReg.Length = Str.size(); Op->StartLoc = S; Op->EndLoc = S; return Op; @@ -1708,27 +1712,7 @@ void ARM64Operand::print(raw_ostream &OS) const { if (Valid) OS << ""; else - OS << ""; - break; - } - case k_SystemRegister: { - bool Valid; - StringRef Name = ARM64SysReg::MRSMapper().toString(getSystemRegister(), Valid); - if (!Valid) - Name = ARM64SysReg::MSRMapper().toString(getSystemRegister(), Valid); - if (Valid) - OS << ""; - else - OS << ""; - break; - } - case k_CPSRField: { - bool Valid; - StringRef Name = ARM64PState::PStateMapper().toString(getCPSRField(), Valid); - if (Valid) - OS << ""; - else - OS << ""; + OS << ""; break; } case k_Immediate: @@ -1751,6 +1735,9 @@ void ARM64Operand::print(raw_ostream &OS) const { case k_VectorIndex: OS << ""; break; + case k_SysReg: + OS << "'; + break; case k_Token: OS << "'" << getToken() << "'"; break; @@ -2612,65 +2599,15 @@ ARM64AsmParser::tryParseBarrierOperand(OperandVector &Operands) { } ARM64AsmParser::OperandMatchResultTy -ARM64AsmParser::tryParseMRSSystemRegister(OperandVector &Operands) { +ARM64AsmParser::tryParseSysReg(OperandVector &Operands) { const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return MatchOperand_NoMatch; - bool Valid; - auto Mapper = ARM64SysReg::MRSMapper(); - uint32_t Reg = Mapper.fromString(Tok.getString(), Valid); - - if (Valid) { - Operands.push_back( - ARM64Operand::CreateSystemRegister((uint16_t)Reg, getLoc(), - getContext())); - Parser.Lex(); // Consume the register name. - return MatchOperand_Success; - } - - return MatchOperand_NoMatch; -} - -ARM64AsmParser::OperandMatchResultTy -ARM64AsmParser::tryParseMSRSystemRegister(OperandVector &Operands) { - const AsmToken &Tok = Parser.getTok(); - - if (Tok.isNot(AsmToken::Identifier)) - return MatchOperand_NoMatch; - - bool Valid; - auto Mapper = ARM64SysReg::MSRMapper(); - uint32_t Reg = Mapper.fromString(Tok.getString(), Valid); - - if (Valid) { - Operands.push_back( - ARM64Operand::CreateSystemRegister((uint16_t)Reg, getLoc(), - getContext())); - Parser.Lex(); // Consume the register name. - return MatchOperand_Success; - } - - return MatchOperand_NoMatch; -} - -ARM64AsmParser::OperandMatchResultTy -ARM64AsmParser::tryParseCPSRField(OperandVector &Operands) { - const AsmToken &Tok = Parser.getTok(); - - if (Tok.isNot(AsmToken::Identifier)) - return MatchOperand_NoMatch; - - bool Valid; - ARM64PState::PStateValues Field = (ARM64PState::PStateValues) - ARM64PState::PStateMapper().fromString(Tok.getString(), Valid); - - if (!Valid) - return MatchOperand_NoMatch; - Operands.push_back( - ARM64Operand::CreateCPSRField(Field, getLoc(), getContext())); - Parser.Lex(); // Consume the register name. + Operands.push_back(ARM64Operand::CreateSysReg(Tok.getString(), getLoc(), + getContext())); + Parser.Lex(); // Eat identifier return MatchOperand_Success; } diff --git a/test/MC/ARM64/spsel-sysreg.s b/test/MC/ARM64/spsel-sysreg.s new file mode 100644 index 00000000000..e6ff4bf51a1 --- /dev/null +++ b/test/MC/ARM64/spsel-sysreg.s @@ -0,0 +1,24 @@ +// RUN: not llvm-mc -triple arm64 -show-encoding < %s 2>%t | FileCheck %s +// RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s + +msr SPSel, #0 +msr SPSel, x0 +msr DAIFSet, #0 +msr ESR_EL1, x0 +mrs x0, SPSel +mrs x0, ESR_EL1 + +// CHECK: msr SPSEL, #0 // encoding: [0xbf,0x40,0x00,0xd5] +// CHECK: msr SPSEL, x0 // encoding: [0x00,0x42,0x18,0xd5] +// CHECK: msr DAIFSET, #0 // encoding: [0xdf,0x40,0x03,0xd5] +// CHECK: msr ESR_EL1, x0 // encoding: [0x00,0x52,0x18,0xd5] +// CHECK: mrs x0, SPSEL // encoding: [0x00,0x42,0x38,0xd5] +// CHECK: mrs x0, ESR_EL1 // encoding: [0x00,0x52,0x38,0xd5] + + +msr DAIFSet, x0 +msr ESR_EL1, #0 +mrs x0, DAIFSet +// CHECK-ERRORS: error: invalid operand for instruction +// CHECK-ERRORS: error: invalid operand for instruction +// CHECK-ERRORS: error: invalid operand for instruction