Skip to content

Commit

Permalink
[MC layer][AArch64] llvm-mc accepts 4-bit immediate values for
Browse files Browse the repository at this point in the history
"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
  • Loading branch information
labrinea committed Oct 5, 2015
1 parent fbdf201 commit 82e78e2
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 18 deletions.
10 changes: 9 additions & 1 deletion lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
50 changes: 43 additions & 7 deletions lib/Target/AArch64/AArch64InstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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";
Expand Down
3 changes: 2 additions & 1 deletion lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
34 changes: 30 additions & 4 deletions lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,15 @@ class AArch64Operand : public MCParsedAsmOperand {
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;
Expand Down Expand Up @@ -876,12 +885,14 @@ class AArch64Operand : public MCParsedAsmOperand {
}
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; }
Expand Down Expand Up @@ -1304,6 +1315,12 @@ class AArch64Operand : public MCParsedAsmOperand {
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());
Expand Down Expand Up @@ -1491,7 +1508,13 @@ class AArch64Operand : public MCParsedAsmOperand {
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));
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
10 changes: 5 additions & 5 deletions test/MC/AArch64/armv8.1a-pan.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions test/MC/Disassembler/AArch64/armv8.1a-pan.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 82e78e2

Please sign in to comment.