[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
This commit is contained in:
Bradley Smith 2014-04-09 14:43:06 +00:00
parent 436fe613fc
commit 3d41487f0e
3 changed files with 98 additions and 141 deletions

View File

@ -701,9 +701,7 @@ class CRmSystemI<Operand crmtype, bits<3> 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<i32> {
@ -714,9 +712,7 @@ def mrs_sysreg_op : Operand<i32> {
def MSRSystemRegisterOperand : AsmOperandClass {
let Name = "MSRSystemRegister";
let ParserMethod = "tryParseMSRSystemRegister";
let RenderMethod = "addSystemRegisterOperands";
let PredicateMethod = "isSystemRegister";
let ParserMethod = "tryParseSysReg";
}
def msr_sysreg_op : Operand<i32> {
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<i32> {
let ParserMatchClass = SystemCPSRFieldOperand;

View File

@ -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 << "<barrier " << Name << ">";
else
OS << "<barrier invalid #" << getCPSRField() << ">";
break;
}
case k_SystemRegister: {
bool Valid;
StringRef Name = ARM64SysReg::MRSMapper().toString(getSystemRegister(), Valid);
if (!Valid)
Name = ARM64SysReg::MSRMapper().toString(getSystemRegister(), Valid);
if (Valid)
OS << "<systemreg " << Name << ">";
else
OS << "<systemreg invalid #" << getSystemRegister() << ">";
break;
}
case k_CPSRField: {
bool Valid;
StringRef Name = ARM64PState::PStateMapper().toString(getCPSRField(), Valid);
if (Valid)
OS << "<cpsrfield " << Name << ">";
else
OS << "<cpsrfield invalid #" << getCPSRField() << ">";
OS << "<barrier invalid #" << getBarrier() << ">";
break;
}
case k_Immediate:
@ -1751,6 +1735,9 @@ void ARM64Operand::print(raw_ostream &OS) const {
case k_VectorIndex:
OS << "<vectorindex " << getVectorIndex() << ">";
break;
case k_SysReg:
OS << "<sysreg: " << getSysReg() << '>';
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;
}

View File

@ -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