[MC layer][AArch64] llvm-mc accepts 4-bit immediate values for

"msr pan, #imm", while only 1-bit immediate values should be valid.
Changed encoding and decoding for msr pstate instructions.

Differential Revision: http://reviews.llvm.org/D13011

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249313 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alexandros Lamprineas 2015-10-05 13:42:31 +00:00
parent fbdf2017ea
commit 82e78e2e9d
7 changed files with 94 additions and 18 deletions

View File

@ -2265,7 +2265,15 @@ SDNode *AArch64DAGToDAGISel::SelectWriteRegister(SDNode *N) {
assert (isa<ConstantSDNode>(N->getOperand(2))
&& "Expected a constant integer expression.");
uint64_t Immed = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
return CurDAG->getMachineNode(AArch64::MSRpstate, DL, MVT::Other,
unsigned State;
if (Reg == AArch64PState::PAN) {
assert(Immed < 2 && "Bad imm");
State = AArch64::MSRpstateImm1;
} else {
assert(Immed < 16 && "Bad imm");
State = AArch64::MSRpstateImm4;
}
return CurDAG->getMachineNode(State, DL, MVT::Other,
CurDAG->getTargetConstant(Reg, DL, MVT::i32),
CurDAG->getTargetConstant(Immed, DL, MVT::i16),
N->getOperand(0));

View File

@ -408,6 +408,7 @@ def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
let ParserMatchClass = Imm1_32Operand;
}
def Imm0_1Operand : AsmImmRange<0, 1>;
def Imm0_7Operand : AsmImmRange<0, 7>;
def Imm0_15Operand : AsmImmRange<0, 15>;
def Imm0_31Operand : AsmImmRange<0, 31>;
@ -538,6 +539,13 @@ def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
let ParserMatchClass = Imm0_31Operand;
}
// imm0_1 predicate - True if the immediate is in the range [0,1]
def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
return ((uint64_t)Imm) < 2;
}]> {
let ParserMatchClass = Imm0_1Operand;
}
// imm0_15 predicate - True if the immediate is in the range [0,15]
def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
return ((uint64_t)Imm) < 16;
@ -905,19 +913,19 @@ class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
let Inst{20-5} = systemreg;
}
def SystemPStateFieldOperand : AsmOperandClass {
let Name = "SystemPStateField";
def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
let Name = "SystemPStateFieldWithImm0_15";
let ParserMethod = "tryParseSysReg";
}
def pstatefield_op : Operand<i32> {
let ParserMatchClass = SystemPStateFieldOperand;
def pstatefield4_op : Operand<i32> {
let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
let PrintMethod = "printSystemPStateField";
}
let Defs = [NZCV] in
class MSRpstateI
: SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
"msr", "\t$pstate_field, $imm">,
class MSRpstateImm0_15
: SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
"msr", "\t$pstatefield, $imm">,
Sched<[WriteSys]> {
bits<6> pstatefield;
bits<4> imm;
@ -933,6 +941,34 @@ class MSRpstateI
let hasCompleteDecoder = 0;
}
def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
let Name = "SystemPStateFieldWithImm0_1";
let ParserMethod = "tryParseSysReg";
}
def pstatefield1_op : Operand<i32> {
let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
let PrintMethod = "printSystemPStateField";
}
let Defs = [NZCV] in
class MSRpstateImm0_1
: SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
"msr", "\t$pstatefield, $imm">,
Sched<[WriteSys]> {
bits<6> pstatefield;
bit imm;
let Inst{20-19} = 0b00;
let Inst{18-16} = pstatefield{5-3};
let Inst{15-9} = 0b0100000;
let Inst{8} = imm;
let Inst{7-5} = pstatefield{2-0};
let DecoderMethod = "DecodeSystemPStateInstruction";
// MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
// Fail the decoder should attempt to decode the instruction as MSRI.
let hasCompleteDecoder = 0;
}
// SYS and SYSL generic system instructions.
def SysCRAsmOperand : AsmOperandClass {
let Name = "SysCR";

View File

@ -399,7 +399,8 @@ def : InstAlias<"isb", (ISB 0xf)>;
def MRS : MRSI;
def MSR : MSRI;
def MSRpstate: MSRpstateI;
def MSRpstateImm1 : MSRpstateImm0_1;
def MSRpstateImm4 : MSRpstateImm0_15;
// The thread pointer (on Linux, at least, where this has been implemented) is
// TPIDR_EL0.

View File

@ -497,6 +497,15 @@ public:
return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
}
bool isImm0_1() const {
if (!isImm())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return false;
int64_t Val = MCE->getValue();
return (Val >= 0 && Val < 2);
}
bool isImm0_7() const {
if (!isImm())
return false;
@ -876,12 +885,14 @@ public:
}
bool isMSRSystemRegister() const {
if (!isSysReg()) return false;
return SysReg.MSRReg != -1U;
}
bool isSystemPStateField() const {
bool isSystemPStateFieldWithImm0_1() const {
if (!isSysReg()) return false;
return SysReg.PStateField == AArch64PState::PAN;
}
bool isSystemPStateFieldWithImm0_15() const {
if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
return SysReg.PStateField != -1U;
}
bool isReg() const override { return Kind == k_Register && !Reg.isVector; }
@ -1304,6 +1315,12 @@ public:
Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
}
void addImm0_1Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Inst.addOperand(MCOperand::createImm(MCE->getValue()));
}
void addImm0_7Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
@ -1491,7 +1508,13 @@ public:
Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
}
void addSystemPStateFieldOperands(MCInst &Inst, unsigned N) const {
void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
}
void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
@ -3601,6 +3624,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
case Match_InvalidMemoryIndexed16:
return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
case Match_InvalidImm0_1:
return Error(Loc, "immediate must be an integer in range [0, 1].");
case Match_InvalidImm0_7:
return Error(Loc, "immediate must be an integer in range [0, 7].");
case Match_InvalidImm0_15:
@ -4029,6 +4054,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidMemoryIndexed8SImm7:
case Match_InvalidMemoryIndexed16SImm7:
case Match_InvalidMemoryIndexedSImm9:
case Match_InvalidImm0_1:
case Match_InvalidImm0_7:
case Match_InvalidImm0_15:
case Match_InvalidImm0_31:

View File

@ -1516,6 +1516,9 @@ static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst,
uint64_t pstate_field = (op1 << 3) | op2;
if (pstate_field == AArch64PState::PAN && crm > 1)
return Fail;
Inst.addOperand(MCOperand::createImm(pstate_field));
Inst.addOperand(MCOperand::createImm(crm));

View File

@ -13,16 +13,16 @@
// CHECK: mrs x13, PAN // encoding: [0x6d,0x42,0x38,0xd5]
msr pan, #-1
msr pan, #20
msr pan, #2
msr pan, w0
mrs w0, pan
// CHECK-ERROR: error: immediate must be an integer in range [0, 15].
// CHECK-ERROR: error: immediate must be an integer in range [0, 1].
// CHECK-ERROR: msr pan, #-1
// CHECK-ERROR: ^
// CHECK-ERROR: error: immediate must be an integer in range [0, 15].
// CHECK-ERROR: msr pan, #20
// CHECK-ERROR: error: immediate must be an integer in range [0, 1].
// CHECK-ERROR: msr pan, #2
// CHECK-ERROR: ^
// CHECK-ERROR: error: immediate must be an integer in range [0, 15].
// CHECK-ERROR: error: immediate must be an integer in range [0, 1].
// CHECK-ERROR: msr pan, w0
// CHECK-ERROR: ^
// CHECK-ERROR: error: invalid operand for instruction

View File

@ -2,9 +2,11 @@
0x9f,0x40,0x00,0xd5
0x9f,0x41,0x00,0xd5
0x9f,0x42,0x00,0xd5
0x65,0x42,0x18,0xd5
0x6d,0x42,0x38,0xd5
# CHECK: msr PAN, #0
# CHECK: msr PAN, #1
# CHECK-NOT: msr PAN, #2
# CHECK: msr PAN, x5
# CHECK: mrs x13, PAN