mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
[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:
parent
fbdf2017ea
commit
82e78e2e9d
@ -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));
|
||||
|
@ -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";
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user