diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -438,6 +438,9 @@ def FeatureMOPS : SubtargetFeature<"mops", "HasMOPS", "true", "Enable Armv8.8-A memcpy and memset acceleration instructions">; +def FeatureNMI : SubtargetFeature<"nmi", "HasNMI", + "true", "Enable Armv8.8-A Non-maskable Interrupts (FEAT_NMI)">; + def FeatureBRBE : SubtargetFeature<"brbe", "HasBRBE", "true", "Enable Branch Record Buffer Extension">; @@ -521,7 +524,7 @@ def HasV8_8aOps : SubtargetFeature< "v8.8a", "HasV8_8aOps", "true", "Support ARM v8.8a instructions", - [HasV8_7aOps, FeatureHBC, FeatureMOPS]>; + [HasV8_7aOps, FeatureHBC, FeatureMOPS, FeatureNMI]>; def HasV9_0aOps : SubtargetFeature< "v9a", "HasV9_0aOps", "true", "Support ARM v9a instructions", diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -3138,13 +3138,13 @@ // immediate value has been provided as an argument, we know that this is // the case as it has been ensured by semantic checking. auto PMapper = AArch64PState::lookupPStateByName(RegString->getString()); - if (PMapper) { + if (PMapper && PMapper->haveFeatures(Subtarget->getFeatureBits())) { assert (isa(N->getOperand(2)) && "Expected a constant integer expression."); unsigned Reg = PMapper->Encoding; uint64_t Immed = cast(N->getOperand(2))->getZExtValue(); unsigned State; - if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO || Reg == AArch64PState::SSBS) { + if (PMapper->ZeroOneImm) { assert(Immed < 2 && "Bad imm"); State = AArch64::MSRpstateImm1; } else { diff --git a/llvm/lib/Target/AArch64/AArch64SystemOperands.td b/llvm/lib/Target/AArch64/AArch64SystemOperands.td --- a/llvm/lib/Target/AArch64/AArch64SystemOperands.td +++ b/llvm/lib/Target/AArch64/AArch64SystemOperands.td @@ -338,35 +338,39 @@ // PState instruction options. //===----------------------------------------------------------------------===// -class PState encoding> : SearchableTable { +class PState op1, bits<3> op2> : SearchableTable { let SearchableFields = ["Name", "Encoding"]; let EnumValueField = "Encoding"; string Name = name; - bits<5> Encoding; - let Encoding = encoding; + bits<6> Encoding; + let Encoding{5-3} = op1; + let Encoding{2-0} = op2; code Requires = [{ {} }]; } -def : PState<"SPSel", 0b00101>; -def : PState<"DAIFSet", 0b11110>; -def : PState<"DAIFClr", 0b11111>; +def : PState<"SPSel", 0b000, 0b101>; +def : PState<"DAIFSet", 0b011, 0b110>; +def : PState<"DAIFClr", 0b011, 0b111>; // v8.1a "Privileged Access Never" extension-specific PStates let Requires = [{ {AArch64::FeaturePAN} }] in -def : PState<"PAN", 0b00100>; +def : PState<"PAN", 0b000, 0b100>; // v8.2a "User Access Override" extension-specific PStates let Requires = [{ {AArch64::FeaturePsUAO} }] in -def : PState<"UAO", 0b00011>; +def : PState<"UAO", 0b000, 0b011>; // v8.4a timing insensitivity of data processing instructions let Requires = [{ {AArch64::FeatureDIT} }] in -def : PState<"DIT", 0b11010>; +def : PState<"DIT", 0b011, 0b010>; // v8.5a Spectre Mitigation let Requires = [{ {AArch64::FeatureSSBS} }] in -def : PState<"SSBS", 0b11001>; +def : PState<"SSBS", 0b011, 0b001>; // v8.5a Memory Tagging Extension let Requires = [{ {AArch64::FeatureMTE} }] in -def : PState<"TCO", 0b11100>; +def : PState<"TCO", 0b011, 0b100>; +// v8.8a Non-Maskable Interrupts +let Requires = [{ {AArch64::FeatureNMI} }] in +def : PState<"ALLINT", 0b001, 0b000>; //===----------------------------------------------------------------------===// // SVCR instruction options. @@ -1717,3 +1721,7 @@ let Requires = [{ {AArch64::FeatureMPAM, AArch64::FeatureSME} }] in { def : RWSysReg<"MPAMSM_EL1", 0b11, 0b000, 0b1010, 0b0101, 0b011>; } // HasMPAM, HasSME + +// v8.8a Non-Maskable Interrupts +let Requires = [{ {AArch64::FeatureNMI} }] in +def : RWSysReg<"ALLINT", 0b11, 0b000, 0b0100, 0b0011, 0b000>; diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -1119,15 +1119,21 @@ bool isSystemPStateFieldWithImm0_1() const { if (!isSysReg()) return false; - return (SysReg.PStateField == AArch64PState::PAN || - SysReg.PStateField == AArch64PState::DIT || - SysReg.PStateField == AArch64PState::UAO || - SysReg.PStateField == AArch64PState::SSBS); + if (SysReg.PStateField == -1U) + return false; + + auto PState = AArch64PState::lookupPStateByEncoding(SysReg.PStateField); + if (!PState) + return false; + return PState->hasZeroOneImm(); } bool isSystemPStateFieldWithImm0_15() const { - if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false; - return SysReg.PStateField != -1U; + if (!isSysReg()) + return false; + if (SysReg.PStateField == -1U) + return false; + return !isSystemPStateFieldWithImm0_1(); } bool isSVCR() const { diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -1712,25 +1712,27 @@ uint64_t crm = fieldFromInstruction(insn, 8, 4); uint64_t pstate_field = (op1 << 3) | op2; - switch (pstate_field) { - case 0x01: // XAFlag - case 0x02: // AXFlag - return Fail; + if (op1 == 0) { + switch (op2) { + case 0b000: // CFINV + case 0b001: // XAFLAG + case 0b010: // AXFLAG + return Fail; + } } - if ((pstate_field == AArch64PState::PAN || - pstate_field == AArch64PState::UAO || - pstate_field == AArch64PState::SSBS) && crm > 1) + auto PState = AArch64PState::lookupPStateByEncoding(pstate_field); + if (!PState || + !PState->haveFeatures(Decoder->getSubtargetInfo().getFeatureBits())) + return Fail; + + if (PState->hasZeroOneImm() && crm > 1) return Fail; Inst.addOperand(MCOperand::createImm(pstate_field)); Inst.addOperand(MCOperand::createImm(crm)); - auto PState = AArch64PState::lookupPStateByEncoding(pstate_field); - if (PState && - PState->haveFeatures(Decoder->getSubtargetInfo().getFeatureBits())) - return Success; - return Fail; + return Success; } static DecodeStatus DecodeTestAndBranch(MCInst &Inst, uint32_t insn, diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h --- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h +++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h @@ -522,11 +522,15 @@ } namespace AArch64PState { - struct PState : SysAlias{ - using SysAlias::SysAlias; - }; - #define GET_PSTATE_DECL - #include "AArch64GenSystemOperands.inc" +struct PState; +#define GET_PSTATE_DECL +#include "AArch64GenSystemOperands.inc" + +struct PState : SysAlias { + using SysAlias::SysAlias; + + bool hasZeroOneImm() const { return Encoding == AArch64PState::ALLINT; } +}; } namespace AArch64PSBHint { diff --git a/llvm/test/MC/AArch64/armv8.1a-pan.s b/llvm/test/MC/AArch64/armv8.1a-pan.s --- a/llvm/test/MC/AArch64/armv8.1a-pan.s +++ b/llvm/test/MC/AArch64/armv8.1a-pan.s @@ -15,16 +15,16 @@ // CHECK: mrs x13, PAN // encoding: [0x6d,0x42,0x38,0xd5] msr pan, #-1 - msr pan, #2 + msr pan, #16 msr pan, w0 mrs w0, pan -// CHECK-ERROR: error: immediate must be an integer in range [0, 1]. +// CHECK-ERROR: error: immediate must be an integer in range [0, 15]. // CHECK-ERROR: msr pan, #-1 // CHECK-ERROR: ^ -// CHECK-ERROR: error: immediate must be an integer in range [0, 1]. -// CHECK-ERROR: msr pan, #2 +// CHECK-ERROR: error: immediate must be an integer in range [0, 15]. +// CHECK-ERROR: msr pan, #16 // CHECK-ERROR: ^ -// CHECK-ERROR: error: immediate must be an integer in range [0, 1]. +// CHECK-ERROR: error: immediate must be an integer in range [0, 15]. // CHECK-ERROR: msr pan, w0 // CHECK-ERROR: ^ // CHECK-ERROR: error: invalid operand for instruction diff --git a/llvm/test/MC/AArch64/armv8.2a-uao.s b/llvm/test/MC/AArch64/armv8.2a-uao.s --- a/llvm/test/MC/AArch64/armv8.2a-uao.s +++ b/llvm/test/MC/AArch64/armv8.2a-uao.s @@ -8,9 +8,9 @@ // CHECK: msr UAO, #0 // encoding: [0x7f,0x40,0x00,0xd5] // CHECK: msr UAO, #1 // encoding: [0x7f,0x41,0x00,0xd5] - msr uao, #2 -// CHECK-ERROR: error: immediate must be an integer in range [0, 1]. -// CHECK-ERROR: msr uao, #2 + msr uao, #16 +// CHECK-ERROR: error: immediate must be an integer in range [0, 15]. +// CHECK-ERROR: msr uao, #16 // CHECK-ERROR: ^ msr uao, x1 diff --git a/llvm/test/MC/AArch64/armv8.4a-dit.s b/llvm/test/MC/AArch64/armv8.4a-dit.s --- a/llvm/test/MC/AArch64/armv8.4a-dit.s +++ b/llvm/test/MC/AArch64/armv8.4a-dit.s @@ -14,13 +14,13 @@ //CHECK-NEXT: msr DIT, x0 // encoding: [0xa0,0x42,0x1b,0xd5] //CHECK-NEXT: mrs x0, DIT // encoding: [0xa0,0x42,0x3b,0xd5] -msr DIT, #2 +msr DIT, #16 msr DIT, #-1 -//CHECK-ERROR: error: immediate must be an integer in range [0, 1]. -//CHECK-ERROR-NEXT: msr DIT, #2 +//CHECK-ERROR: error: immediate must be an integer in range [0, 15]. +//CHECK-ERROR-NEXT: msr DIT, #16 //CHECK-ERROR-NEXT: ^ -//CHECK-ERROR-NEXT: error: immediate must be an integer in range [0, 1]. +//CHECK-ERROR-NEXT: error: immediate must be an integer in range [0, 15]. //CHECK-ERROR-NEXT: msr DIT, #-1 //CHECK-ERROR-NEXT: ^ @@ -34,7 +34,7 @@ //CHECK-NO-V84-NEXT: mrs x0, DIT //CHECK-NO-V84-NEXT: ^ //CHECK-NO-V84-NEXT: error: expected writable system register or pstate -//CHECK-NO-V84-NEXT: msr DIT, #2 +//CHECK-NO-V84-NEXT: msr DIT, #16 //CHECK-NO-V84-NEXT: ^ //CHECK-NO-V84-NEXT: error: expected writable system register or pstate //CHECK-NO-V84-NEXT: msr DIT, #-1 diff --git a/llvm/test/MC/AArch64/armv8.5a-ssbs-error.s b/llvm/test/MC/AArch64/armv8.5a-ssbs-error.s --- a/llvm/test/MC/AArch64/armv8.5a-ssbs-error.s +++ b/llvm/test/MC/AArch64/armv8.5a-ssbs-error.s @@ -2,9 +2,9 @@ // RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=+v8.5a < %s 2>&1 | FileCheck %s // RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=-ssbs < %s 2>&1 | FileCheck %s --check-prefix=NOSPECID -msr SSBS, #2 +msr SSBS, #16 -// CHECK: error: immediate must be an integer in range [0, 1]. -// CHECK-NEXT: msr SSBS, #2 +// CHECK: error: immediate must be an integer in range [0, 15]. +// CHECK-NEXT: msr SSBS, #16 // NOSPECID: error: expected writable system register or pstate -// NOSPECID-NEXT: msr {{ssbs|SSBS}}, #2 +// NOSPECID-NEXT: msr {{ssbs|SSBS}}, #16 diff --git a/llvm/test/MC/AArch64/armv8.8a-nmi-error.s b/llvm/test/MC/AArch64/armv8.8a-nmi-error.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/armv8.8a-nmi-error.s @@ -0,0 +1,9 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+nmi < %s 2>&1 | FileCheck %s +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.8a < %s 2>&1 | FileCheck %s + + msr ALLINT, #-1 +// CHECK: [[@LINE-1]]:17: error: immediate must be an integer in range [0, 1] +// CHECK-NEXT: msr ALLINT, #-1 + msr ALLINT, #2 +// CHECK: [[@LINE-1]]:17: error: immediate must be an integer in range [0, 1] +// CHECK-NEXT: msr ALLINT, #2 diff --git a/llvm/test/MC/AArch64/armv8.8a-nmi.s b/llvm/test/MC/AArch64/armv8.8a-nmi.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/armv8.8a-nmi.s @@ -0,0 +1,17 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+nmi < %s | FileCheck %s +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.8a < %s | FileCheck %s +// RUN: not llvm-mc -triple aarch64-none-linux-gnu < %s 2>&1 | FileCheck --check-prefix=ERROR-NO-NMI %s + + + msr ALLINT, x0 +// CHECK: msr ALLINT, x0 // encoding: [0x00,0x43,0x18,0xd5] +// ERROR-NO-NMI: [[@LINE-2]]:9: error: expected writable system register or pstate + mrs x0, ALLINT +// CHECK: mrs x0, ALLINT // encoding: [0x00,0x43,0x38,0xd5] +// ERROR-NO-NMI: [[@LINE-2]]:13: error: expected readable system register + msr ALLINT, #0 +// CHECK: msr ALLINT, #0 // encoding: [0x1f,0x40,0x01,0xd5] +// ERROR-NO-NMI: [[@LINE-2]]:9: error: expected writable system register or pstate + msr ALLINT, #1 +// CHECK: msr ALLINT, #1 // encoding: [0x1f,0x41,0x01,0xd5] +// ERROR-NO-NMI: [[@LINE-2]]:9: error: expected writable system register or pstate diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.1a-pan.txt b/llvm/test/MC/Disassembler/AArch64/armv8.1a-pan.txt --- a/llvm/test/MC/Disassembler/AArch64/armv8.1a-pan.txt +++ b/llvm/test/MC/Disassembler/AArch64/armv8.1a-pan.txt @@ -2,11 +2,11 @@ 0x9f,0x40,0x00,0xd5 0x9f,0x41,0x00,0xd5 -0x9f,0x42,0x00,0xd5 +0x9f,0x4f,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, #15 # CHECK: msr PAN, x5 # CHECK: mrs x13, PAN diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.2a-uao.txt b/llvm/test/MC/Disassembler/AArch64/armv8.2a-uao.txt --- a/llvm/test/MC/Disassembler/AArch64/armv8.2a-uao.txt +++ b/llvm/test/MC/Disassembler/AArch64/armv8.2a-uao.txt @@ -3,13 +3,13 @@ [0x7f,0x40,0x00,0xd5] [0x7f,0x41,0x00,0xd5] -[0x7f,0x42,0x00,0xd5] +[0x7f,0x4f,0x00,0xd5] # CHECK: msr UAO, #0 # CHECK: msr UAO, #1 -# CHECK: msr S0_0_C4_C2_3, xzr +# CHECK: msr UAO, #15 # NO_V82A: msr S0_0_C4_C0_3, xzr # NO_V82A: msr S0_0_C4_C1_3, xzr -# NO_V82A: msr S0_0_C4_C2_3, xzr +# NO_V82A: msr S0_0_C4_C15_3, xzr [0x81,0x42,0x18,0xd5] [0x82,0x42,0x38,0xd5] diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.8a-nmi.txt b/llvm/test/MC/Disassembler/AArch64/armv8.8a-nmi.txt new file mode 100644 --- /dev/null +++ b/llvm/test/MC/Disassembler/AArch64/armv8.8a-nmi.txt @@ -0,0 +1,21 @@ +# RUN: llvm-mc -triple=aarch64 -mattr=+nmi -disassemble %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -mattr=+v8.8a -disassemble %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -disassemble %s | FileCheck --check-prefix=NO-NMI %s + +[0x00,0x43,0x18,0xd5] +# CHECK: msr ALLINT, x0 +# NO-NMI: msr S3_0_C4_C3_0, x0 +[0x00,0x43,0x38,0xd5] +# CHECK: mrs x0, ALLINT +# NO-NMI: mrs x0, S3_0_C4_C3_0 +[0x1f,0x40,0x01,0xd5] +# CHECK: msr ALLINT, #0 +# NO-NMI: msr S0_1_C4_C0_0, xzr +[0x1f,0x41,0x01,0xd5] +# CHECK: msr ALLINT, #1 +# NO-NMI: msr S0_1_C4_C1_0, xzr + + +[0x1f,0x42,0x01,0xd5] +# CHECK: msr S0_1_C4_C2_0, xzr +# NO-NMI: msr S0_1_C4_C2_0, xzr