Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -383,6 +383,11 @@ return StringRef(SysReg.Data, SysReg.Length); } + uint32_t getSysPStateField() const { + assert(Kind == k_SysReg && "Invalid access!"); + return SysReg.PStateField; + } + unsigned getSysCR() const { assert(Kind == k_SysCR && "Invalid access!"); return SysCRImm.Val; @@ -3921,6 +3926,29 @@ } } + // Hack to handle MSR Pstate expecting 1-bit Imm + if (NumOperands == 3 && Tok == "msr") { + + AArch64Operand &Op1 = static_cast(*Operands[1]); + AArch64Operand &Op2 = static_cast(*Operands[2]); + + if (Op1.isSystemPStateField() && + Op1.getSysPStateField() == AArch64PState::PAN) { + + // should be 1-bit Imm, or GPR64 + if (Op2.isImm()) { + + const MCConstantExpr *MCE = dyn_cast(Op2.getImm()); + + if (!MCE || MCE->getValue() < 0 || MCE->getValue() > 1) + return Error(Op2.getStartLoc(), + "immediate must be an integer in range [0, 1]."); + } + else if (!Op2.isGPR32as64()) + return showMatchError(Op2.getStartLoc(), Match_InvalidOperand); + } + } + MCInst Inst; // First try to match against the secondary set of tables containing the // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2"). Index: lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -1516,6 +1516,9 @@ 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)); Index: test/MC/AArch64/armv8.1a-pan.s =================================================================== --- test/MC/AArch64/armv8.1a-pan.s +++ test/MC/AArch64/armv8.1a-pan.s @@ -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: invalid operand for instruction // CHECK-ERROR: msr pan, w0 // CHECK-ERROR: ^ // CHECK-ERROR: error: invalid operand for instruction Index: test/MC/Disassembler/AArch64/armv8.1a-pan.txt =================================================================== --- test/MC/Disassembler/AArch64/armv8.1a-pan.txt +++ test/MC/Disassembler/AArch64/armv8.1a-pan.txt @@ -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