[lldb] [llvm] [AArch64][llvm] Tighten SYSP parsing; don't disassemble invalid encodings (PR #182410)

Jonathan Thackray via llvm-commits llvm-commits at lists.llvm.org
Fri May 1 07:44:35 PDT 2026


https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/182410

>From 36b228dbefa9bb753da6556687d62c0c25fab849 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 19 Feb 2026 23:54:20 +0000
Subject: [PATCH 01/13] [AArch64][llvm] Tighten SYSP; don't disassemble invalid
 encodings

Tighten SYSP aliases, so that invalid encodings are disassembled
to `<unknown>`. This is because:

```
  Cn is a 4-bit unsigned immediate, in the range 8 to 9
  Cm is a 4-bit unsigned immediate, in the range 0 to 7
  op1 is a 3-bit unsigned immediate, in the range 0 to 6
  op2 is a 3-bit unsigned immediate, in the range 0 to 7
```

Ensure we check this when disassembling, and also constrain
tablegen for compile-time errors of invalid encodings.

Also adjust the testcases in `armv9-sysp-diagnostics.s` and
`llvm/test/MC/AArch64/armv9a-sysp.s` as they were invalid,
and added a few invalid (outside of range) SYSP-alikes to
test that `<unknown>` is printed
---
 .../command-disassemble-aarch64-color.s       |   4 +-
 .../command-disassemble-aarch64-extensions.s  |   4 +-
 .../lib/Target/AArch64/AArch64InstrFormats.td |  26 +-
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  10 +-
 .../Disassembler/AArch64Disassembler.cpp      |  25 ++
 .../MCTargetDesc/AArch64InstPrinter.cpp       |   8 +
 llvm/test/MC/AArch64/armv9-sysp-diagnostics.s |  15 +-
 llvm/test/MC/AArch64/armv9-sysp-invalid.s     |  20 ++
 llvm/test/MC/AArch64/armv9a-sysp.s            | 222 +++++++++---------
 9 files changed, 207 insertions(+), 127 deletions(-)
 create mode 100644 llvm/test/MC/AArch64/armv9-sysp-invalid.s

diff --git a/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s b/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s
index bb97680a32970..6ddde3d974adc 100644
--- a/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s
+++ b/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s
@@ -17,7 +17,7 @@ fn:
   crc32b w0, w0, w0                     // AEK_CRC
   // AEK_CRYPTO enables a combination of other features
   smin x0, x0, #0                       // AEK_CSSC
-  sysp	#0, c2, c0, #0, x0, x1          // AEK_D128
+  sysp	#0, c8, c0, #0, x0, x1          // AEK_D128
   sdot v0.2s, v1.8b, v2.8b              // AEK_DOTPROD
   fmmla z0.s, z1.s, z2.s                // AEK_F32MM
 
@@ -28,6 +28,6 @@ fn:
 # CHECK-NEXT: [0xc] <+12>:   brb    iall
 # CHECK-NEXT: [0x10] <+16>:  crc32b w0, w0, w0
 # CHECK-NEXT: [0x14] <+20>:  smin   x0, x0, #0x0
-# CHECK-NEXT: [0x18] <+24>:  sysp   #0x0, c2, c0, #0x0, x0, x1
+# CHECK-NEXT: [0x18] <+24>:  sysp   #0x0, c8, c0, #0x0, x0, x1
 # CHECK-NEXT: [0x1c] <+28>:  sdot   v0.2s, v1.8b, v2.8b
 # CHECK-NEXT: [0x20] <+32>:  fmmla  z0.s, z1.s, z2.s
diff --git a/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s b/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
index 4e281332a33bb..945654e905876 100644
--- a/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
+++ b/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
@@ -17,7 +17,7 @@ fn:
   crc32b w0, w0, w0                     // AEK_CRC
   // AEK_CRYPTO enables a combination of other features
   smin x0, x0, #0                       // AEK_CSSC
-  sysp	#0, c2, c0, #0, x0, x1          // AEK_D128
+  sysp	#0, c8, c0, #0, x0, x1          // AEK_D128
   sdot v0.2s, v1.8b, v2.8b              // AEK_DOTPROD
   fmmla z0.s, z1.s, z2.s                // AEK_F32MM
   fmmla z0.d, z1.d, z2.d                // AEK_F64MM
@@ -72,7 +72,7 @@ lbl:
 # CHECK-NEXT: brb    iall
 # CHECK-NEXT: crc32b w0, w0, w0
 # CHECK-NEXT: smin   x0, x0, #0
-# CHECK-NEXT: sysp   #0x0, c2, c0, #0x0, x0, x1
+# CHECK-NEXT: sysp   #0x0, c8, c0, #0x0, x0, x1
 # CHECK-NEXT: sdot   v0.2s, v1.8b, v2.8b
 # CHECK-NEXT: fmmla  z0.s, z1.s, z2.s
 # CHECK-NEXT: fmmla  z0.d, z1.d, z2.d
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 894c36b8071ad..03a6b2bc62150 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2132,6 +2132,29 @@ def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
+def sysp_crn_op : Operand<i32>, ImmLeaf<i32, [{
+  return Imm == 8 || Imm == 9;
+}]> {
+  let PrintMethod = "printSysCROperand";
+  let ParserMatchClass = SysCRAsmOperand;
+  let OperandType = "OPERAND_IMMEDIATE";
+}
+
+def sysp_crm_op : Operand<i32>, ImmLeaf<i32, [{
+  return Imm >= 0 && Imm <= 7;
+}]> {
+  let PrintMethod = "printSysCROperand";
+  let ParserMatchClass = SysCRAsmOperand;
+  let OperandType = "OPERAND_IMMEDIATE";
+}
+
+def sysp_op1 : Operand<i64>, ImmLeaf<i64, [{
+  return Imm >= 0 && Imm <= 6;
+}]> {
+  let ParserMatchClass = Imm0_7Operand;
+  let OperandType = "OPERAND_IMMEDIATE";
+}
+
 class SystemXtI<string asm>
   : RtSystemI<0, (outs),
        (ins imm32_0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm32_0_7:$op2,
@@ -13318,7 +13341,8 @@ class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inpu
 }
 class SystemPXtI<bit L, string asm> :
   BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
-  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
+  (ins sysp_op1:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
+       XSeqPairClassOperand:$Rt)>;
 
 //----------------------------------------------------------------------------
 // 2023 Armv9.5 Extensions
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index a97bc37515438..563a1a3eed28e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -11593,11 +11593,14 @@ let Predicates = [HasRCPC3, HasNEON] in {
 //===----------------------------------------------------------------------===//
 // 128-bit System Instructions (FEAT_SYSINSTR128)
 //===----------------------------------------------------------------------===//
-def SYSPxt  : SystemPXtI<0, "sysp">;
+def SYSPxt  : SystemPXtI<0, "sysp"> {
+  let DecoderMethod = "DecodeSyspInstruction";
+}
 
 def SYSPxt_XZR
   : BaseSystemI<0, (outs),
-      (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, SyspXzrPairOperand:$xzr_pair),
+      (ins sysp_op1:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
+           SyspXzrPairOperand:$xzr_pair),
       "sysp", "\t$op1, $Cn, $Cm, $op2, $xzr_pair">,
     Sched<[WriteSys]>
 {
@@ -11623,7 +11626,8 @@ def SYSPxt_XZR
 }
 
 def : InstAlias<"sysp $op1, $Cn, $Cm, $op2",
-                (SYSPxt_XZR imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XZR)>;
+                (SYSPxt_XZR sysp_op1:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm,
+                            imm0_7:$op2, XZR)>;
 
 //---
 // 128-bit System Registers (FEAT_SYSREG128)
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 8fa1913ce24e5..ef0f9cb515d0b 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1395,6 +1395,10 @@ static DecodeStatus DecodeSyspXzrInstruction(MCInst &Inst, uint32_t insn,
   unsigned CRm = fieldFromInstruction(insn, 8, 4);
   unsigned op2 = fieldFromInstruction(insn, 5, 3);
   unsigned Rt = fieldFromInstruction(insn, 0, 5);
+
+  if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7 || op2 > 7)
+    return Fail;
+
   if (Rt != 0b11111)
     return Fail;
 
@@ -1408,6 +1412,27 @@ static DecodeStatus DecodeSyspXzrInstruction(MCInst &Inst, uint32_t insn,
   return Success;
 }
 
+static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
+                                          uint64_t Addr,
+                                          const MCDisassembler *Decoder) {
+  unsigned op1 = fieldFromInstruction(insn, 16, 3);
+  unsigned CRn = fieldFromInstruction(insn, 12, 4);
+  unsigned CRm = fieldFromInstruction(insn, 8, 4);
+  unsigned op2 = fieldFromInstruction(insn, 5, 3);
+  unsigned Rt = fieldFromInstruction(insn, 0, 5);
+
+  if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7 || op2 > 7)
+    return Fail;
+
+  Inst.addOperand(MCOperand::createImm(op1));
+  Inst.addOperand(MCOperand::createImm(CRn));
+  Inst.addOperand(MCOperand::createImm(CRm));
+  Inst.addOperand(MCOperand::createImm(op2));
+  DecodeXSeqPairsClassRegisterClass(Inst, Rt, Addr, Decoder);
+
+  return Success;
+}
+
 static DecodeStatus
 DecodeSVELogicalImmInstruction(MCInst &Inst, uint32_t insn, uint64_t Addr,
                                const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 2df769539960d..e79a677b8c311 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1142,6 +1142,14 @@ bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
   unsigned CmVal = Cm.getImm();
   unsigned Op2Val = Op2.getImm();
 
+  // Early checks for invalid SYSP aliases
+  //   Op1 == 0..6
+  //   Op2 == 0..7
+  //    Cm == 0..7
+  //    Cn == 8 or 9
+  if (Op1Val > 6 || Op2Val > 7 || CmVal > 7 || (CnVal != 8 && CnVal != 9))
+    return false;
+
   uint16_t Encoding = Op2Val;
   Encoding |= CmVal << 3;
   Encoding |= CnVal << 7;
diff --git a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
index 8b466c10b0aa7..51bb307912fef 100644
--- a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
@@ -7,22 +7,21 @@
 // registers with 128-bit formats (op0, op1, Cn, Cm, op2)
 // For sysp, op0 is 0
 
-sysp #0, c2, c0, #0, x0, x2
+sysp #0, c8, c0, #0, x0, x2
 // ERRORS: error: expected second odd register of a consecutive same-size even/odd register pair
-sysp #0, c2, c0, #0, x0
+sysp #0, c8, c0, #0, x0
 // ERRORS: error: expected comma
-sysp #0, c2, c0, #0, x1, x2
+sysp #0, c8, c0, #0, x1, x2
 // ERRORS: error: expected first even register of a consecutive same-size even/odd register pair
-sysp #0, c2, c0, #0, x31, x0
+sysp #0, c8, c0, #0, x31, x0
 // ERRORS: error: xzr must be followed by xzr
-sysp #0, c2, c0, #0, xzr, x30
+sysp #0, c8, c0, #0, xzr, x30
 // ERRORS: error: xzr must be followed by xzr
-sysp #0, c2, c0, #0, xzr
+sysp #0, c8, c0, #0, xzr
 // ERRORS: error: expected comma
-sysp #0, c2, c0, #0, xzr,
+sysp #0, c8, c0, #0, xzr,
 // ERRORS: error: expected register operand
 
-
 tlbip RVAE3IS
 // ERRORS: error: expected comma
 tlbip RVAE3IS,
diff --git a/llvm/test/MC/AArch64/armv9-sysp-invalid.s b/llvm/test/MC/AArch64/armv9-sysp-invalid.s
new file mode 100644
index 0000000000000..248d5ccc5056a
--- /dev/null
+++ b/llvm/test/MC/AArch64/armv9-sysp-invalid.s
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+d128 < %s \
+// RUN:   | llvm-objdump -d --mattr=+d128 --no-print-imm-hex - \
+// RUN:   | FileCheck %s --check-prefix=DISASM
+
+// Ensure invalid SYSP encodings are not printed as TLBIP aliases.
+
+// op1 = 7 (outside architecturally valid SYSP range for op1)
+// Cn = 8, Cm = 0, op2 = 0, Rt = 0 (x0, x1)
+.inst 0xd54f8000
+
+// Cn = 0 (outside architecturally valid SYSP range for Cn)
+.inst 0xd5480000
+
+// Cm = 8 (outside architecturally valid SYSP range for Cm)
+.inst 0xd5488800
+
+// DISASM-NOT: tlbip
+// DISASM: <unknown>
+// DISASM: <unknown>
+// DISASM: <unknown>
diff --git a/llvm/test/MC/AArch64/armv9a-sysp.s b/llvm/test/MC/AArch64/armv9a-sysp.s
index f1e039f3e8770..349f75eb95424 100644
--- a/llvm/test/MC/AArch64/armv9a-sysp.s
+++ b/llvm/test/MC/AArch64/armv9a-sysp.s
@@ -13,150 +13,150 @@
 // registers with 128-bit formats (op0, op1, Cn, Cm, op2)
 // For sysp, op0 is 0
 
-sysp #0, c2, c0, #0, x0, x1// TTBR0_EL1     3  0  2  0  0
-// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #1, x0, x1// TTBR1_EL1     3  0  2  0  1
-// CHECK-INST: sysp #0, c2, c0, #1, x0, x1
-// CHECK-ENCODING: encoding: [0x20,0x20,0x48,0xd5]
+sysp #0, c8, c0, #1, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #1, x0, x1
+// CHECK-ENCODING: encoding: [0x20,0x80,0x48,0xd5]
 
-sysp #0, c7, c4, #0, x0, x1// PAR_EL1       3  0  7  4  0
-// CHECK-INST: sysp #0, c7, c4, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x74,0x48,0xd5]
+sysp #0, c8, c4, #0, x0, x1
+// CHECK-INST: sysp #0, c8, c4, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x84,0x48,0xd5]
 
-sysp #0, c13, c0, #3, x0, x1         // RCWSMASK_EL1  3  0 13  0  3
-// CHECK-INST: sysp #0, c13, c0, #3, x0, x1
-// CHECK-ENCODING: encoding: [0x60,0xd0,0x48,0xd5]
+sysp #0, c8, c0, #3, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #3, x0, x1
+// CHECK-ENCODING: encoding: [0x60,0x80,0x48,0xd5]
 
-sysp #0, c13, c0, #6, x0, x1         // RCWMASK_EL1   3  0 13  0  6
-// CHECK-INST: sysp #0, c13, c0, #6, x0, x1
-// CHECK-ENCODING: encoding: [0xc0,0xd0,0x48,0xd5]
+sysp #0, c8, c0, #6, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #6, x0, x1
+// CHECK-ENCODING: encoding: [0xc0,0x80,0x48,0xd5]
 
-sysp #4, c2, c0, #0, x0, x1// TTBR0_EL2     3  4  2  0  0
-// CHECK-INST: sysp #4, c2, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x20,0x4c,0xd5]
+sysp #4, c8, c0, #0, x0, x1
+// CHECK-INST: sysp #4, c8, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x80,0x4c,0xd5]
 
-sysp #4, c2, c0, #1, x0, x1// TTBR1_EL2     3  4  2  0  1
-// CHECK-INST: sysp #4, c2, c0, #1, x0, x1
-// CHECK-ENCODING: encoding: [0x20,0x20,0x4c,0xd5]
+sysp #4, c8, c0, #3, x0, x1
+// CHECK-INST: sysp #4, c8, c0, #3, x0, x1
+// CHECK-ENCODING: encoding: [0x60,0x80,0x4c,0xd5]
 
-sysp #4, c2, c1, #0, x0, x1// VTTBR_EL2     3  4  2  1  0
-// CHECK-INST: sysp #4, c2, c1, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x21,0x4c,0xd5]
+sysp #4, c8, c1, #0, x0, x1
+// CHECK-INST: sysp #4, c8, c1, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x81,0x4c,0xd5]
 
-sysp #0, c2, c0, #0, x0, x1
-// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #1, x0, x1
-// CHECK-INST: sysp #0, c2, c0, #1, x0, x1
-// CHECK-ENCODING: encoding: [0x20,0x20,0x48,0xd5]
+sysp #0, c8, c0, #1, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #1, x0, x1
+// CHECK-ENCODING: encoding: [0x20,0x80,0x48,0xd5]
 
-sysp #0, c7, c4, #0, x0, x1
-// CHECK-INST: sysp #0, c7, c4, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x74,0x48,0xd5]
+sysp #0, c8, c4, #0, x0, x1
+// CHECK-INST: sysp #0, c8, c4, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x84,0x48,0xd5]
 
-sysp #0, c13, c0, #3, x0, x1
-// CHECK-INST: sysp #0, c13, c0, #3, x0, x1
-// CHECK-ENCODING: encoding: [0x60,0xd0,0x48,0xd5]
+sysp #0, c8, c0, #3, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #3, x0, x1
+// CHECK-ENCODING: encoding: [0x60,0x80,0x48,0xd5]
 
-sysp #0, c13, c0, #6, x0, x1
-// CHECK-INST: sysp #0, c13, c0, #6, x0, x1
-// CHECK-ENCODING: encoding: [0xc0,0xd0,0x48,0xd5]
+sysp #0, c8, c0, #6, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #6, x0, x1
+// CHECK-ENCODING: encoding: [0xc0,0x80,0x48,0xd5]
 
-sysp #4, c2, c0, #0, x0, x1
-// CHECK-INST: sysp #4, c2, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x20,0x4c,0xd5]
+sysp #4, c8, c0, #0, x0, x1
+// CHECK-INST: sysp #4, c8, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x80,0x4c,0xd5]
 
-sysp #4, c2, c0, #1, x0, x1
-// CHECK-INST: sysp #4, c2, c0, #1, x0, x1
-// CHECK-ENCODING: encoding: [0x20,0x20,0x4c,0xd5]
+sysp #4, c8, c0, #3, x0, x1
+// CHECK-INST: sysp #4, c8, c0, #3, x0, x1
+// CHECK-ENCODING: encoding: [0x60,0x80,0x4c,0xd5]
 
-sysp #4, c2, c1, #0, x0, x1
-// CHECK-INST: sysp #4, c2, c1, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x21,0x4c,0xd5]
+sysp #4, c8, c1, #0, x0, x1
+// CHECK-INST: sysp #4, c8, c1, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x81,0x4c,0xd5]
 
-sysp #0, c2, c0, #0, x0, x1
-// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c8, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x2, x3
-// CHECK-INST: sysp #0, c2, c0, #0, x2, x3
-// CHECK-ENCODING: encoding: [0x02,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x2, x3
+// CHECK-INST: sysp #0, c8, c0, #0, x2, x3
+// CHECK-ENCODING: encoding: [0x02,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x4, x5
-// CHECK-INST: sysp #0, c2, c0, #0, x4, x5
-// CHECK-ENCODING: encoding: [0x04,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x4, x5
+// CHECK-INST: sysp #0, c8, c0, #0, x4, x5
+// CHECK-ENCODING: encoding: [0x04,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x6, x7
-// CHECK-INST: sysp #0, c2, c0, #0, x6, x7
-// CHECK-ENCODING: encoding: [0x06,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x6, x7
+// CHECK-INST: sysp #0, c8, c0, #0, x6, x7
+// CHECK-ENCODING: encoding: [0x06,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x8, x9
-// CHECK-INST: sysp #0, c2, c0, #0, x8, x9
-// CHECK-ENCODING: encoding: [0x08,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x8, x9
+// CHECK-INST: sysp #0, c8, c0, #0, x8, x9
+// CHECK-ENCODING: encoding: [0x08,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x10, x11
-// CHECK-INST: sysp #0, c2, c0, #0, x10, x11
-// CHECK-ENCODING: encoding: [0x0a,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x10, x11
+// CHECK-INST: sysp #0, c8, c0, #0, x10, x11
+// CHECK-ENCODING: encoding: [0x0a,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x12, x13
-// CHECK-INST: sysp #0, c2, c0, #0, x12, x13
-// CHECK-ENCODING: encoding: [0x0c,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x12, x13
+// CHECK-INST: sysp #0, c8, c0, #0, x12, x13
+// CHECK-ENCODING: encoding: [0x0c,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x14, x15
-// CHECK-INST: sysp #0, c2, c0, #0, x14, x15
-// CHECK-ENCODING: encoding: [0x0e,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x14, x15
+// CHECK-INST: sysp #0, c8, c0, #0, x14, x15
+// CHECK-ENCODING: encoding: [0x0e,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x16, x17
-// CHECK-INST: sysp #0, c2, c0, #0, x16, x17
-// CHECK-ENCODING: encoding: [0x10,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x16, x17
+// CHECK-INST: sysp #0, c8, c0, #0, x16, x17
+// CHECK-ENCODING: encoding: [0x10,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x18, x19
-// CHECK-INST: sysp #0, c2, c0, #0, x18, x19
-// CHECK-ENCODING: encoding: [0x12,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x18, x19
+// CHECK-INST: sysp #0, c8, c0, #0, x18, x19
+// CHECK-ENCODING: encoding: [0x12,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x20, x21
-// CHECK-INST: sysp #0, c2, c0, #0, x20, x21
-// CHECK-ENCODING: encoding: [0x14,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x20, x21
+// CHECK-INST: sysp #0, c8, c0, #0, x20, x21
+// CHECK-ENCODING: encoding: [0x14,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x22, x23
-// CHECK-INST: sysp #0, c2, c0, #0, x22, x23
-// CHECK-ENCODING: encoding: [0x16,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x22, x23
+// CHECK-INST: sysp #0, c8, c0, #0, x22, x23
+// CHECK-ENCODING: encoding: [0x16,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x24, x25
-// CHECK-INST: sysp #0, c2, c0, #0, x24, x25
-// CHECK-ENCODING: encoding: [0x18,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x24, x25
+// CHECK-INST: sysp #0, c8, c0, #0, x24, x25
+// CHECK-ENCODING: encoding: [0x18,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x26, x27
-// CHECK-INST: sysp #0, c2, c0, #0, x26, x27
-// CHECK-ENCODING: encoding: [0x1a,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x26, x27
+// CHECK-INST: sysp #0, c8, c0, #0, x26, x27
+// CHECK-ENCODING: encoding: [0x1a,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x28, x29
-// CHECK-INST: sysp #0, c2, c0, #0, x28, x29
-// CHECK-ENCODING: encoding: [0x1c,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x28, x29
+// CHECK-INST: sysp #0, c8, c0, #0, x28, x29
+// CHECK-ENCODING: encoding: [0x1c,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x30, x31
-// CHECK-INST: sysp #0, c2, c0, #0, x30, xzr
-// CHECK-ENCODING: encoding: [0x1e,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x30, x31
+// CHECK-INST: sysp #0, c8, c0, #0, x30, xzr
+// CHECK-ENCODING: encoding: [0x1e,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x31, x31
-// CHECK-INST: sysp #0, c2, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x31, x31
+// CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, xzr, xzr
-// CHECK-INST: sysp #0, c2, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, xzr, xzr
+// CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, x31, xzr
-// CHECK-INST: sysp #0, c2, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, x31, xzr
+// CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0, xzr, x31
-// CHECK-INST: sysp #0, c2, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0, xzr, x31
+// CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
-sysp #0, c2, c0, #0
-// CHECK-INST: sysp #0, c2, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+sysp #0, c8, c0, #0
+// CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]

>From 94b54d5138d25df5ba379bc69e8fc2ca0b49f9f2 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 5 Mar 2026 12:32:15 +0000
Subject: [PATCH 02/13] fixup! Address Marian's PR comments: use imm0_6
 predicate

---
 llvm/lib/Target/AArch64/AArch64InstrFormats.td | 10 +++++++++-
 llvm/lib/Target/AArch64/AArch64InstrInfo.td    |  4 ++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 03a6b2bc62150..e9c9b153486df 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -951,6 +951,7 @@ def Imm0_1Operand : AsmImmRange<0, 1>;
 def Imm1_1Operand : AsmImmRange<1, 1>;
 def Imm0_3Operand : AsmImmRange<0, 3>;
 def Imm1_3Operand : AsmImmRange<1, 3>;
+def Imm0_6Operand : AsmImmRange<0, 6>;
 def Imm0_7Operand : AsmImmRange<0, 7>;
 def Imm1_7Operand : AsmImmRange<1, 7>;
 def Imm0_15Operand : AsmImmRange<0, 15>;
@@ -1184,6 +1185,13 @@ def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
   let ParserMatchClass = Imm0_15Operand;
 }
 
+// imm0_6 predicate - True if the immediate is in the range [0,6]
+def imm0_6 : Operand<i64>, ImmLeaf<i64, [{
+  return ((uint64_t)Imm) < 7;
+}]> {
+  let ParserMatchClass = Imm0_6Operand;
+}
+
 // imm0_7 predicate - True if the immediate is in the range [0,7]
 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
   return ((uint64_t)Imm) < 8;
@@ -13341,7 +13349,7 @@ class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inpu
 }
 class SystemPXtI<bit L, string asm> :
   BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
-  (ins sysp_op1:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
+  (ins imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
        XSeqPairClassOperand:$Rt)>;
 
 //----------------------------------------------------------------------------
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 563a1a3eed28e..293e0a50c5bdd 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -11599,7 +11599,7 @@ def SYSPxt  : SystemPXtI<0, "sysp"> {
 
 def SYSPxt_XZR
   : BaseSystemI<0, (outs),
-      (ins sysp_op1:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
+      (ins imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
            SyspXzrPairOperand:$xzr_pair),
       "sysp", "\t$op1, $Cn, $Cm, $op2, $xzr_pair">,
     Sched<[WriteSys]>
@@ -11626,7 +11626,7 @@ def SYSPxt_XZR
 }
 
 def : InstAlias<"sysp $op1, $Cn, $Cm, $op2",
-                (SYSPxt_XZR sysp_op1:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm,
+                (SYSPxt_XZR imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm,
                             imm0_7:$op2, XZR)>;
 
 //---

>From 331697dd668377390e127e19f1b0741671aa3f6e Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 5 Mar 2026 14:41:46 +0000
Subject: [PATCH 03/13] fixup! Templatise bounds checking and improve tests

---
 .../lib/Target/AArch64/AArch64InstrFormats.td | 17 ++++++++++++-----
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 18 ++++++++++++++++++
 .../MCTargetDesc/AArch64InstPrinter.cpp       |  8 --------
 llvm/test/MC/AArch64/armv9-sysp-diagnostics.s | 19 +++++++++++++++----
 4 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index e9c9b153486df..ff21c04792868 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2127,16 +2127,23 @@ class MSRpstateImm0_1
 }
 
 // SYS and SYSL generic system instructions.
-def SysCRAsmOperand : AsmOperandClass {
-  let Name = "SysCR";
+class SysCRAsmOperand<int Low, int High> : AsmOperandClass {
+  let Name = "SysCR" # Low # "_" # High;
+  let RenderMethod = "addSysCROperands";
   let ParserMethod = "tryParseSysCROperand";
+  let PredicateMethod = "isSysCRInRange<" # Low # "," # High # ">";
+  let DiagnosticType = "InvalidSysCR" # Low # "_" # High;
 }
 
+def SysCRm0_7AsmOperand : SysCRAsmOperand<0, 7>;
+def SysCRn8_9AsmOperand : SysCRAsmOperand<8, 9>;
+def SysCR0_15AsmOperand : SysCRAsmOperand<0, 15>;
+
 def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
   return ((uint32_t)Imm) < 16;
 }]> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRAsmOperand;
+  let ParserMatchClass = SysCR0_15AsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
@@ -2144,7 +2151,7 @@ def sysp_crn_op : Operand<i32>, ImmLeaf<i32, [{
   return Imm == 8 || Imm == 9;
 }]> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRAsmOperand;
+  let ParserMatchClass = SysCRn8_9AsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
@@ -2152,7 +2159,7 @@ def sysp_crm_op : Operand<i32>, ImmLeaf<i32, [{
   return Imm >= 0 && Imm <= 7;
 }]> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRAsmOperand;
+  let ParserMatchClass = SysCRm0_7AsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 6a6b73b8a4c88..8fdc2e3f66065 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -1551,6 +1551,12 @@ class AArch64Operand : public MCParsedAsmOperand {
     return Kind == k_Token && getToken() == Str;
   }
   bool isSysCR() const { return Kind == k_SysCR; }
+  template <unsigned low, unsigned high> bool isSysCRInRange() const {
+    if (!isSysCR())
+      return false;
+    unsigned Val = getSysCR();
+    return Val >= low && Val <= high;
+  }
   bool isPrefetch() const { return Kind == k_Prefetch; }
   bool isPSBHint() const { return Kind == k_PSBHint; }
   bool isPHint() const { return Kind == k_PHint; }
@@ -6282,6 +6288,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "immediate must be an integer in range [0, 1].");
   case Match_InvalidImm0_3:
     return Error(Loc, "immediate must be an integer in range [0, 3].");
+  case Match_InvalidImm0_6:
+    return Error(Loc, "immediate must be an integer in range [0, 6].");
   case Match_InvalidImm0_7:
     return Error(Loc, "immediate must be an integer in range [0, 7].");
   case Match_InvalidImm0_15:
@@ -6306,6 +6314,12 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "immediate must be an integer in range [1, 64].");
   case Match_InvalidImmM1_62:
     return Error(Loc, "immediate must be an integer in range [-1, 62].");
+  case Match_InvalidSysCR0_7:
+    return Error(Loc, "expected cM operand where 0 <= M <= 7");
+  case Match_InvalidSysCR8_9:
+    return Error(Loc, "expected cN operand where 8 <= N <= 9");
+  case Match_InvalidSysCR0_15:
+    return Error(Loc, "expected cN operand where 0 <= N <= 15");
   case Match_InvalidMemoryIndexedRange2UImm0:
     return Error(Loc, "vector select offset must be the immediate range 0:1.");
   case Match_InvalidMemoryIndexedRange2UImm1:
@@ -7070,6 +7084,7 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidImm0_0:
   case Match_InvalidImm0_1:
   case Match_InvalidImm0_3:
+  case Match_InvalidImm0_6:
   case Match_InvalidImm0_7:
   case Match_InvalidImm0_15:
   case Match_InvalidImm0_31:
@@ -7082,6 +7097,9 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidImm1_32:
   case Match_InvalidImm1_64:
   case Match_InvalidImmM1_62:
+  case Match_InvalidSysCR0_7:
+  case Match_InvalidSysCR8_9:
+  case Match_InvalidSysCR0_15:
   case Match_InvalidMemoryIndexedRange2UImm0:
   case Match_InvalidMemoryIndexedRange2UImm1:
   case Match_InvalidMemoryIndexedRange2UImm2:
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index e79a677b8c311..2df769539960d 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1142,14 +1142,6 @@ bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
   unsigned CmVal = Cm.getImm();
   unsigned Op2Val = Op2.getImm();
 
-  // Early checks for invalid SYSP aliases
-  //   Op1 == 0..6
-  //   Op2 == 0..7
-  //    Cm == 0..7
-  //    Cn == 8 or 9
-  if (Op1Val > 6 || Op2Val > 7 || CmVal > 7 || (CnVal != 8 && CnVal != 9))
-    return false;
-
   uint16_t Encoding = Op2Val;
   Encoding |= CmVal << 3;
   Encoding |= CnVal << 7;
diff --git a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
index 51bb307912fef..4e0ba1bbb1772 100644
--- a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
@@ -9,16 +9,22 @@
 
 sysp #0, c8, c0, #0, x0, x2
 // ERRORS: error: expected second odd register of a consecutive same-size even/odd register pair
-sysp #0, c8, c0, #0, x0
-// ERRORS: error: expected comma
 sysp #0, c8, c0, #0, x1, x2
 // ERRORS: error: expected first even register of a consecutive same-size even/odd register pair
 sysp #0, c8, c0, #0, x31, x0
 // ERRORS: error: xzr must be followed by xzr
 sysp #0, c8, c0, #0, xzr, x30
 // ERRORS: error: xzr must be followed by xzr
-sysp #0, c8, c0, #0, xzr
-// ERRORS: error: expected comma
+sysp #7, c8, c0, #0, x0, x1
+// ERRORS: error: immediate must be an integer in range [0, 6].
+sysp #0, c7, c0, #0, x0, x1
+// ERRORS: error: expected cN operand where 8 <= N <= 9
+sysp #0, c10, c0, #0, x0, x1
+// ERRORS: error: expected cN operand where 8 <= N <= 9
+sysp #0, c8, c8, #0, x0, x1
+// ERRORS: error: expected cM operand where 0 <= M <= 7
+sysp #0, c8, c0, #8, x0, x1
+// ERRORS: error: immediate must be an integer in range [0, 7].
 sysp #0, c8, c0, #0, xzr,
 // ERRORS: error: expected register operand
 
@@ -32,3 +38,8 @@ tlbip IPAS2E1, x4, x8
 // ERRORS: error: specified tlbip op requires a pair of registers
 tlbip RVAE3, x11, x11
 // ERRORS: error: specified tlbip op requires a pair of registers
+
+sysp #0, c8, c0, #0, x0
+// ERRORS: error: expected comma
+sysp #0, c8, c0, #0, xzr
+// ERRORS: error: expected comma

>From a1861bf8463b0e5df741bccd6734d77677d04355 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 9 Mar 2026 16:16:52 +0000
Subject: [PATCH 04/13] fixup! Remove SYSPxt_XZR and update code to reflect
 this

---
 .../lib/Target/AArch64/AArch64InstrFormats.td |  2 +-
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   | 32 +---------
 .../lib/Target/AArch64/AArch64RegisterInfo.td | 16 ++---
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 61 ++++++++-----------
 .../Disassembler/AArch64Disassembler.cpp      | 32 +++-------
 .../MCTargetDesc/AArch64InstPrinter.cpp       | 55 ++++++++++++-----
 .../AArch64/MCTargetDesc/AArch64InstPrinter.h |  4 +-
 llvm/test/MC/AArch64/armv9-sysp-diagnostics.s | 16 ++++-
 llvm/test/MC/AArch64/armv9-sysp-invalid.s     | 20 ------
 llvm/test/MC/AArch64/armv9a-sysp.s            |  4 ++
 10 files changed, 105 insertions(+), 137 deletions(-)
 delete mode 100644 llvm/test/MC/AArch64/armv9-sysp-invalid.s

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index ff21c04792868..9a783850f0be9 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -13357,7 +13357,7 @@ class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inpu
 class SystemPXtI<bit L, string asm> :
   BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
   (ins imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
-       XSeqPairClassOperand:$Rt)>;
+       SyspPairOperand:$Rt)>;
 
 //----------------------------------------------------------------------------
 // 2023 Armv9.5 Extensions
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 293e0a50c5bdd..c4c167a2ad3ba 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -11597,37 +11597,9 @@ def SYSPxt  : SystemPXtI<0, "sysp"> {
   let DecoderMethod = "DecodeSyspInstruction";
 }
 
-def SYSPxt_XZR
-  : BaseSystemI<0, (outs),
-      (ins imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
-           SyspXzrPairOperand:$xzr_pair),
-      "sysp", "\t$op1, $Cn, $Cm, $op2, $xzr_pair">,
-    Sched<[WriteSys]>
-{
-  // Had to use a custom decoder because tablegen interprets this as having 4 fields (why?)
-  // and therefore autogenerates a decoder that builds an MC representation that has 4 fields
-  // (decodeToMCInst), but when printing we expect the MC representation to have 5 fields (one
-  // extra for the XZR) because AArch64InstPrinter::printInstruction in AArch64GenAsmWriter.inc
-  // is based off of the asm template (maybe) and therefore wants to print 5 operands.
-  // I could add a bits<5> xzr_pair. But without a way to constrain it to 0b11111 here it would
-  // overlap with the main SYSP instruction.
-  let DecoderMethod = "DecodeSyspXzrInstruction";
-  bits<3> op1;
-  bits<4> Cn;
-  bits<4> Cm;
-  bits<3> op2;
-  let Inst{22}    = 0b1; // override BaseSystemI
-  let Inst{20-19} = 0b01;
-  let Inst{18-16} = op1;
-  let Inst{15-12} = Cn;
-  let Inst{11-8}  = Cm;
-  let Inst{7-5}   = op2;
-  let Inst{4-0}   = 0b11111;
-}
-
 def : InstAlias<"sysp $op1, $Cn, $Cm, $op2",
-                (SYSPxt_XZR imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm,
-                            imm0_7:$op2, XZR)>;
+                (SYSPxt imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm,
+                        imm0_7:$op2, XZR)>;
 
 //---
 // 128-bit System Registers (FEAT_SYSREG128)
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index cd94a2590c6d2..cc2798de60943 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -833,14 +833,14 @@ def MrrsMssrPairClassOperand :
     RegisterOperand<XSeqPairsClass, "printGPRSeqPairsClassOperand<64>"> {
   let ParserMatchClass = XSeqPairsAsmOperandClass;
 }
-def SyspXzrPairOperandMatcherClass : AsmOperandClass {
-  let Name = "SyspXzrPair";
-  let RenderMethod = "addSyspXzrPairOperand";
-  let ParserMethod = "tryParseSyspXzrPair";
-}
-def SyspXzrPairOperand :
-    RegisterOperand<GPR64, "printSyspXzrPair"> { // needed to allow alias with XZR operand
-  let ParserMatchClass = SyspXzrPairOperandMatcherClass;
+def SyspPairOperandMatcherClass : AsmOperandClass {
+  let Name = "SyspPair";
+  let RenderMethod = "addRegOperands";
+  let ParserMethod = "tryParseSyspPair";
+}
+def SyspPairOperand :
+    RegisterOperand<GPR64, "printSyspPair"> {
+  let ParserMatchClass = SyspPairOperandMatcherClass;
 }
 
 
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 8fdc2e3f66065..c71d5f8a2a5c1 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -279,7 +279,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
   bool tryParseNeonVectorRegister(OperandVector &Operands);
   ParseStatus tryParseVectorIndex(OperandVector &Operands);
   ParseStatus tryParseGPRSeqPair(OperandVector &Operands);
-  ParseStatus tryParseSyspXzrPair(OperandVector &Operands);
+  ParseStatus tryParseSyspPair(OperandVector &Operands);
   template <bool ParseShiftExtend,
             RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
   ParseStatus tryParseGPROperand(OperandVector &Operands);
@@ -1449,9 +1449,7 @@ class AArch64Operand : public MCParsedAsmOperand {
                Reg.Reg);
   }
 
-  bool isSyspXzrPair() const {
-    return isGPR64<AArch64::GPR64RegClassID>() && Reg.Reg == AArch64::XZR;
-  }
+  bool isSyspPair() const { return isGPR64<AArch64::GPR64RegClassID>(); }
 
   template<int64_t Angle, int64_t Remainder>
   DiagnosticPredicate isComplexRotation() const {
@@ -2271,21 +2269,6 @@ class AArch64Operand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createImm(Imm));
   }
 
-  void addSyspXzrPairOperand(MCInst &Inst, unsigned N) const {
-    assert(N == 1 && "Invalid number of operands!");
-
-    if (!isScalarReg())
-      return;
-
-    const MCRegisterInfo *RI = Ctx.getRegisterInfo();
-    MCRegister Reg = RI->getRegClass(AArch64::GPR64RegClassID)
-                         .getRegister(RI->getEncodingValue(getReg()));
-    if (Reg != AArch64::XZR)
-      llvm_unreachable("wrong register");
-
-    Inst.addOperand(MCOperand::createReg(AArch64::XZR));
-  }
-
   void addExtendOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     AArch64_AM::ShiftExtendType ET = getShiftExtendType();
@@ -3316,18 +3299,20 @@ ParseStatus AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
   return ParseStatus::Success;
 }
 
-ParseStatus AArch64AsmParser::tryParseSyspXzrPair(OperandVector &Operands) {
+ParseStatus AArch64AsmParser::tryParseSyspPair(OperandVector &Operands) {
   SMLoc StartLoc = getLoc();
 
-  MCRegister RegNum;
-
-  // The case where xzr, xzr is not present is handled by an InstAlias.
+  MCRegister FirstReg;
+  MCRegister SecondReg;
+  const MCRegisterInfo *RI = getContext().getRegisterInfo();
+  const MCRegisterClass &XRegClass =
+      AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
 
   auto RegTok = getTok(); // in case we need to backtrack
-  if (!tryParseScalarRegister(RegNum).isSuccess())
+  if (!tryParseScalarRegister(FirstReg).isSuccess())
     return ParseStatus::NoMatch;
 
-  if (RegNum != AArch64::XZR) {
+  if (!XRegClass.contains(FirstReg)) {
     getLexer().UnLex(RegTok);
     return ParseStatus::NoMatch;
   }
@@ -3335,16 +3320,26 @@ ParseStatus AArch64AsmParser::tryParseSyspXzrPair(OperandVector &Operands) {
   if (parseComma())
     return ParseStatus::Failure;
 
-  if (!tryParseScalarRegister(RegNum).isSuccess())
+  if (!tryParseScalarRegister(SecondReg).isSuccess())
     return TokError("expected register operand");
 
-  if (RegNum != AArch64::XZR)
-    return TokError("xzr must be followed by xzr");
+  if (FirstReg == AArch64::XZR) {
+    if (SecondReg != AArch64::XZR)
+      return TokError("xzr must be followed by xzr");
+    // The SYSP alias is UNDEFINED if Rt<0> == '1' && Rt != '11111'.
+  } else if (RI->getEncodingValue(FirstReg) & 1) {
+    return TokError("first register must be even-numbered or xzr");
+  } else if (!XRegClass.contains(SecondReg) ||
+             RI->getEncodingValue(SecondReg) !=
+                 RI->getEncodingValue(FirstReg) + 1) {
+    return TokError(
+        "second register must be the next consecutive register after the "
+        "first register");
+  }
 
-  // We need to push something, since we claim this is an operand in .td.
-  // See also AArch64AsmParser::parseKeywordOperand.
+  // SYSP encodes only the first register; the second is implied as Rt+1.
   Operands.push_back(AArch64Operand::CreateReg(
-      RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
+      FirstReg, RegKind::Scalar, StartLoc, getLoc(), getContext()));
 
   return ParseStatus::Success;
 }
@@ -4271,9 +4266,7 @@ bool AArch64AsmParser::parseSyspAlias(StringRef Name, SMLoc NameLoc,
 
   if (Tok.isNot(AsmToken::Identifier))
     return TokError("expected register identifier");
-  auto Result = tryParseSyspXzrPair(Operands);
-  if (Result.isNoMatch())
-    Result = tryParseGPRSeqPair(Operands);
+  auto Result = tryParseSyspPair(Operands);
   if (!Result.isSuccess())
     return TokError("specified " + Mnemonic +
                     " op requires a pair of registers");
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index ef0f9cb515d0b..67de69086dafb 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1387,9 +1387,9 @@ DecodeXSeqPairsClassRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr,
       Inst, AArch64::XSeqPairsClassRegClassID, RegNo, Addr, Decoder);
 }
 
-static DecodeStatus DecodeSyspXzrInstruction(MCInst &Inst, uint32_t insn,
-                                             uint64_t Addr,
-                                             const MCDisassembler *Decoder) {
+static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
+                                          uint64_t Addr,
+                                          const MCDisassembler *Decoder) {
   unsigned op1 = fieldFromInstruction(insn, 16, 3);
   unsigned CRn = fieldFromInstruction(insn, 12, 4);
   unsigned CRm = fieldFromInstruction(insn, 8, 4);
@@ -1399,40 +1399,22 @@ static DecodeStatus DecodeSyspXzrInstruction(MCInst &Inst, uint32_t insn,
   if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7 || op2 > 7)
     return Fail;
 
-  if (Rt != 0b11111)
+  // SYSP register pairs follow the same encoding constraints as XSeqPairsClass:
+  // the first register must be even-numbered, except for the XZR/XZR case.
+  if (Rt != 31 && (Rt & 0x1))
     return Fail;
 
   Inst.addOperand(MCOperand::createImm(op1));
   Inst.addOperand(MCOperand::createImm(CRn));
   Inst.addOperand(MCOperand::createImm(CRm));
   Inst.addOperand(MCOperand::createImm(op2));
+  // SYSP just encodes Rt. Print Rt and Rt+1 as a pair.
   DecodeSimpleRegisterClass<AArch64::GPR64RegClassID, 0, 32>(Inst, Rt, Addr,
                                                              Decoder);
 
   return Success;
 }
 
-static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
-                                          uint64_t Addr,
-                                          const MCDisassembler *Decoder) {
-  unsigned op1 = fieldFromInstruction(insn, 16, 3);
-  unsigned CRn = fieldFromInstruction(insn, 12, 4);
-  unsigned CRm = fieldFromInstruction(insn, 8, 4);
-  unsigned op2 = fieldFromInstruction(insn, 5, 3);
-  unsigned Rt = fieldFromInstruction(insn, 0, 5);
-
-  if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7 || op2 > 7)
-    return Fail;
-
-  Inst.addOperand(MCOperand::createImm(op1));
-  Inst.addOperand(MCOperand::createImm(CRn));
-  Inst.addOperand(MCOperand::createImm(CRm));
-  Inst.addOperand(MCOperand::createImm(op2));
-  DecodeXSeqPairsClassRegisterClass(Inst, Rt, Addr, Decoder);
-
-  return Success;
-}
-
 static DecodeStatus
 DecodeSVELogicalImmInstruction(MCInst &Inst, uint32_t insn, uint64_t Addr,
                                const MCDisassembler *Decoder) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 2df769539960d..2db39ed9d0d56 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -90,12 +90,26 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
       return;
     }
 
-  if (Opcode == AArch64::SYSPxt || Opcode == AArch64::SYSPxt_XZR)
+  if (Opcode == AArch64::SYSPxt) {
     if (printSyspAlias(MI, STI, O)) {
       printAnnotation(O, Annot);
       return;
     }
 
+    // Ok, so we should preserve compatibility when printing with the historic
+    // SYSP short form, when Rt encodes XZR (no explicit pair operand)
+    if (MI->getOperand(4).getReg() == AArch64::XZR) {
+      O << "\tsysp\t";
+      markup(O, Markup::Immediate) << "#" << MI->getOperand(0).getImm();
+      O << ", c" << MI->getOperand(1).getImm();
+      O << ", c" << MI->getOperand(2).getImm();
+      O << ", ";
+      markup(O, Markup::Immediate) << "#" << MI->getOperand(3).getImm();
+      printAnnotation(O, Annot);
+      return;
+    }
+  }
+
   // RPRFM overlaps PRFM (reg), so try to print it as RPRFM here.
   if ((Opcode == AArch64::PRFMroX) || (Opcode == AArch64::PRFMroW)) {
     if (printRangePrefetchAlias(MI, STI, O, Annot))
@@ -371,7 +385,12 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
     return;
   }
 
-  if (!PrintAliases || !printAliasInstr(MI, Address, STI, O))
+  // SYSP alias printing is handled explicitly by printSyspAlias above.
+  // Skip the generic alias printer for SYSPxt, because its XSeqPair aliases
+  // are only valid for a subset of SYSP register pairs and can misprint
+  // odd-started regs or xzr,xzr encodings.
+  if (!PrintAliases || Opcode == AArch64::SYSPxt ||
+      !printAliasInstr(MI, Address, STI, O))
     printInstruction(MI, Address, STI, O);
 
   printAnnotation(O, Annot);
@@ -1128,8 +1147,7 @@ bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
                                         raw_ostream &O) {
 #ifndef NDEBUG
   unsigned Opcode = MI->getOpcode();
-  assert((Opcode == AArch64::SYSPxt || Opcode == AArch64::SYSPxt_XZR) &&
-         "Invalid opcode for SYSP alias!");
+  assert(Opcode == AArch64::SYSPxt && "Invalid opcode for SYSP alias!");
 #endif
 
   const MCOperand &Op1 = MI->getOperand(0);
@@ -1168,10 +1186,8 @@ bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
 
   O << '\t' << Str;
   O << ", ";
-  if (MI->getOperand(4).getReg() == AArch64::XZR)
-    printSyspXzrPair(MI, 4, STI, O);
-  else
-    printGPRSeqPairsClassOperand<64>(MI, 4, STI, O);
+  // TLBIP alias keeps SYSP's pair formatting rules for the trailing operand.
+  printSyspPair(MI, 4, STI, O);
 
   return true;
 }
@@ -2252,13 +2268,24 @@ void AArch64InstPrinter::printGPR64x8(const MCInst *MI, unsigned OpNum,
   printRegName(O, MRI.getSubReg(Reg, AArch64::x8sub_0));
 }
 
-void AArch64InstPrinter::printSyspXzrPair(const MCInst *MI, unsigned OpNum,
-                                          const MCSubtargetInfo &STI,
-                                          raw_ostream &O) {
+void AArch64InstPrinter::printSyspPair(const MCInst *MI, unsigned OpNum,
+                                       const MCSubtargetInfo &STI,
+                                       raw_ostream &O) {
   MCRegister Reg = MI->getOperand(OpNum).getReg();
-  assert(Reg == AArch64::XZR &&
-         "MC representation of SyspXzrPair should be XZR");
-  O << getRegisterName(Reg) << ", " << getRegisterName(Reg);
+  printRegName(O, Reg);
+  O << ", ";
+  if (Reg == AArch64::XZR) {
+    printRegName(O, AArch64::XZR);
+    return;
+  }
+
+  const MCRegisterClass &XRegClass =
+      AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
+  // SYSP textual form prints the implied second register as Rt+1.
+  unsigned NextRegNo = MRI.getEncodingValue(Reg) + 1;
+  assert(NextRegNo < XRegClass.getNumRegs() &&
+         "SYSP pair starts from an invalid GPR64 register");
+  printRegName(O, XRegClass.getRegister(NextRegNo));
 }
 
 void AArch64InstPrinter::printPHintOp(const MCInst *MI, unsigned OpNum,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 3f7a3b4b0667b..0b34d9edfa82b 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -237,8 +237,8 @@ class AArch64InstPrinter : public MCInstPrinter {
                       const MCSubtargetInfo &STI, raw_ostream &O);
   void printGPR64x8(const MCInst *MI, unsigned OpNum,
                     const MCSubtargetInfo &STI, raw_ostream &O);
-  void printSyspXzrPair(const MCInst *MI, unsigned OpNum,
-                        const MCSubtargetInfo &STI, raw_ostream &O);
+  void printSyspPair(const MCInst *MI, unsigned OpNum,
+                     const MCSubtargetInfo &STI, raw_ostream &O);
   template <int Width>
   void printZPRasFPR(const MCInst *MI, unsigned OpNum,
                      const MCSubtargetInfo &STI, raw_ostream &O);
diff --git a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
index 4e0ba1bbb1772..2426acce2d95e 100644
--- a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
@@ -8,13 +8,23 @@
 // For sysp, op0 is 0
 
 sysp #0, c8, c0, #0, x0, x2
-// ERRORS: error: expected second odd register of a consecutive same-size even/odd register pair
-sysp #0, c8, c0, #0, x1, x2
-// ERRORS: error: expected first even register of a consecutive same-size even/odd register pair
+// ERRORS: error: second register must be the next consecutive register after the first register
+sysp #4, c8, c4, #1, x1, x2
+// ERRORS: error: first register must be even-numbered or xzr
+sysp #4, c8, c4, #1, x2, x4
+// ERRORS: error: second register must be the next consecutive register after the first register
+sysp #0, c8, c0, #0, x29, x31
+// ERRORS: error: first register must be even-numbered or xzr
+sysp #0, c8, c0, #0, x30, x30
+// ERRORS: error: second register must be the next consecutive register after the first register
 sysp #0, c8, c0, #0, x31, x0
 // ERRORS: error: xzr must be followed by xzr
+sysp #4, c8, c4, #1, xzr, x1
+// ERRORS: error: xzr must be followed by xzr
 sysp #0, c8, c0, #0, xzr, x30
 // ERRORS: error: xzr must be followed by xzr
+sysp #0, c8, c0, #0, w0, w1
+// ERRORS: error: invalid operand for instruction
 sysp #7, c8, c0, #0, x0, x1
 // ERRORS: error: immediate must be an integer in range [0, 6].
 sysp #0, c7, c0, #0, x0, x1
diff --git a/llvm/test/MC/AArch64/armv9-sysp-invalid.s b/llvm/test/MC/AArch64/armv9-sysp-invalid.s
deleted file mode 100644
index 248d5ccc5056a..0000000000000
--- a/llvm/test/MC/AArch64/armv9-sysp-invalid.s
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+d128 < %s \
-// RUN:   | llvm-objdump -d --mattr=+d128 --no-print-imm-hex - \
-// RUN:   | FileCheck %s --check-prefix=DISASM
-
-// Ensure invalid SYSP encodings are not printed as TLBIP aliases.
-
-// op1 = 7 (outside architecturally valid SYSP range for op1)
-// Cn = 8, Cm = 0, op2 = 0, Rt = 0 (x0, x1)
-.inst 0xd54f8000
-
-// Cn = 0 (outside architecturally valid SYSP range for Cn)
-.inst 0xd5480000
-
-// Cm = 8 (outside architecturally valid SYSP range for Cm)
-.inst 0xd5488800
-
-// DISASM-NOT: tlbip
-// DISASM: <unknown>
-// DISASM: <unknown>
-// DISASM: <unknown>
diff --git a/llvm/test/MC/AArch64/armv9a-sysp.s b/llvm/test/MC/AArch64/armv9a-sysp.s
index 349f75eb95424..c01e83c92fcfd 100644
--- a/llvm/test/MC/AArch64/armv9a-sysp.s
+++ b/llvm/test/MC/AArch64/armv9a-sysp.s
@@ -21,6 +21,10 @@ sysp #0, c8, c0, #1, x0, x1
 // CHECK-INST: sysp #0, c8, c0, #1, x0, x1
 // CHECK-ENCODING: encoding: [0x20,0x80,0x48,0xd5]
 
+sysp #0, c9, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c9, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x90,0x48,0xd5]
+
 sysp #0, c8, c4, #0, x0, x1
 // CHECK-INST: sysp #0, c8, c4, #0, x0, x1
 // CHECK-ENCODING: encoding: [0x00,0x84,0x48,0xd5]

>From 5990d03ca80afec022e1ba461bb44fc9febd5a05 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 10 Mar 2026 22:29:20 +0000
Subject: [PATCH 05/13] fixup! Add no-alias tests

---
 .../lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp | 7 ++++---
 llvm/test/MC/AArch64/armv9a-sysp.s                         | 7 +++++++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 2db39ed9d0d56..32c8315ba984b 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -96,9 +96,10 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
       return;
     }
 
-    // Ok, so we should preserve compatibility when printing with the historic
-    // SYSP short form, when Rt encodes XZR (no explicit pair operand)
-    if (MI->getOperand(4).getReg() == AArch64::XZR) {
+    // Preserve the historic SYSP short form for the XZR/XZR encoding, but
+    // only when aliases are enabled. In no-alias mode we must print the full
+    // canonical operand list.
+    if (PrintAliases && MI->getOperand(4).getReg() == AArch64::XZR) {
       O << "\tsysp\t";
       markup(O, Markup::Immediate) << "#" << MI->getOperand(0).getImm();
       O << ", c" << MI->getOperand(1).getImm();
diff --git a/llvm/test/MC/AArch64/armv9a-sysp.s b/llvm/test/MC/AArch64/armv9a-sysp.s
index c01e83c92fcfd..3753fcc684c4f 100644
--- a/llvm/test/MC/AArch64/armv9a-sysp.s
+++ b/llvm/test/MC/AArch64/armv9a-sysp.s
@@ -2,6 +2,8 @@
 // RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
 // RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \
 // RUN:        | llvm-objdump -d --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \
+// RUN:        | llvm-objdump -d -M no-aliases --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-NOALIAS
 // Disassemble encoding and check the re-encoding (-show-encoding) matches.
 // RUN: llvm-mc -triple=aarch64 -show-encoding < %s \
 // RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
@@ -147,20 +149,25 @@ sysp #0, c8, c0, #0, x30, x31
 
 sysp #0, c8, c0, #0, x31, x31
 // CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0, x31, xzr
 // CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0, xzr, x31
 // CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0
 // CHECK-INST: sysp #0, c8, c0, #0
+// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]

>From d262f6b2a2e43462931abc7491bf0c267d68dc84 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 12 Mar 2026 13:43:48 +0000
Subject: [PATCH 06/13] fixup! Address PR comments

---
 llvm/lib/Target/AArch64/AArch64InstrFormats.td     | 14 +++++---------
 .../Target/AArch64/AsmParser/AArch64AsmParser.cpp  |  5 ++---
 .../AArch64/Disassembler/AArch64Disassembler.cpp   |  3 +--
 llvm/test/MC/AArch64/armv9-sysp-diagnostics.s      |  2 +-
 4 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 9a783850f0be9..9f7d9faa91275 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2143,23 +2143,19 @@ def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
   return ((uint32_t)Imm) < 16;
 }]> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCR0_15AsmOperand;
+  let ParserMatchClass = SysCRAsmOperand<0, 15>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
-def sysp_crn_op : Operand<i32>, ImmLeaf<i32, [{
-  return Imm == 8 || Imm == 9;
-}]> {
+def sysp_crn_op : Operand<i32> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRn8_9AsmOperand;
+  let ParserMatchClass = SysCRAsmOperand<8, 9>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
-def sysp_crm_op : Operand<i32>, ImmLeaf<i32, [{
-  return Imm >= 0 && Imm <= 7;
-}]> {
+def sysp_crm_op : Operand<i32> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRm0_7AsmOperand;
+  let ParserMatchClass = SysCRAsmOperand<0, 7>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index c71d5f8a2a5c1..22ce78cb360bc 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -1548,9 +1548,8 @@ class AArch64Operand : public MCParsedAsmOperand {
   bool isTokenEqual(StringRef Str) const {
     return Kind == k_Token && getToken() == Str;
   }
-  bool isSysCR() const { return Kind == k_SysCR; }
   template <unsigned low, unsigned high> bool isSysCRInRange() const {
-    if (!isSysCR())
+    if (Kind != k_SysCR)
       return false;
     unsigned Val = getSysCR();
     return Val >= low && Val <= high;
@@ -6308,7 +6307,7 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
   case Match_InvalidImmM1_62:
     return Error(Loc, "immediate must be an integer in range [-1, 62].");
   case Match_InvalidSysCR0_7:
-    return Error(Loc, "expected cM operand where 0 <= M <= 7");
+    return Error(Loc, "expected cN operand where 0 <= N <= 7");
   case Match_InvalidSysCR8_9:
     return Error(Loc, "expected cN operand where 8 <= N <= 9");
   case Match_InvalidSysCR0_15:
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 67de69086dafb..74063d03e346d 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1396,10 +1396,9 @@ static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
   unsigned op2 = fieldFromInstruction(insn, 5, 3);
   unsigned Rt = fieldFromInstruction(insn, 0, 5);
 
-  if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7 || op2 > 7)
+  if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7)
     return Fail;
 
-  // SYSP register pairs follow the same encoding constraints as XSeqPairsClass:
   // the first register must be even-numbered, except for the XZR/XZR case.
   if (Rt != 31 && (Rt & 0x1))
     return Fail;
diff --git a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
index 2426acce2d95e..d3af63a994f5b 100644
--- a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
@@ -32,7 +32,7 @@ sysp #0, c7, c0, #0, x0, x1
 sysp #0, c10, c0, #0, x0, x1
 // ERRORS: error: expected cN operand where 8 <= N <= 9
 sysp #0, c8, c8, #0, x0, x1
-// ERRORS: error: expected cM operand where 0 <= M <= 7
+// ERRORS: error: expected cN operand where 0 <= N <= 7
 sysp #0, c8, c0, #8, x0, x1
 // ERRORS: error: immediate must be an integer in range [0, 7].
 sysp #0, c8, c0, #0, xzr,

>From 87bfe41b41d35daf81c616e1b61826998506dfc9 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 23 Mar 2026 15:05:29 +0000
Subject: [PATCH 07/13] fixup! Fixes after rebasing following Marian's change

---
 llvm/lib/Target/AArch64/AArch64InstrFormats.td | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 9f7d9faa91275..10f1500832600 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2143,19 +2143,19 @@ def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
   return ((uint32_t)Imm) < 16;
 }]> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRAsmOperand<0, 15>;
+  let ParserMatchClass = SysCR0_15AsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
 def sysp_crn_op : Operand<i32> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRAsmOperand<8, 9>;
+  let ParserMatchClass = SysCRn8_9AsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
 def sysp_crm_op : Operand<i32> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRAsmOperand<0, 7>;
+  let ParserMatchClass = SysCRm0_7AsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 

>From f35bcd8807243e76e93c106ad9c0f7dc2401b1f9 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 24 Mar 2026 13:27:27 +0000
Subject: [PATCH 08/13] fixup! Improve error parsing

---
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 71 ++++++++++++-------
 llvm/test/MC/AArch64/armv9-sysp-diagnostics.s | 24 +++----
 2 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 22ce78cb360bc..bf99754bc9f63 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -3299,46 +3299,65 @@ ParseStatus AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
 }
 
 ParseStatus AArch64AsmParser::tryParseSyspPair(OperandVector &Operands) {
-  SMLoc StartLoc = getLoc();
+  SMLoc S = getLoc();
+
+  if (getTok().isNot(AsmToken::Identifier))
+    return Error(S, "expected register");
 
   MCRegister FirstReg;
-  MCRegister SecondReg;
+  ParseStatus Res = tryParseScalarRegister(FirstReg);
+  if (!Res.isSuccess())
+    return Error(S,
+                 "expected xzr/xzr or the first even register of a consecutive "
+                 "64-bit register pair");
+
   const MCRegisterInfo *RI = getContext().getRegisterInfo();
   const MCRegisterClass &XRegClass =
       AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
+  if (!XRegClass.contains(FirstReg))
+    return Error(S,
+                 "expected xzr/xzr or the first even register of a consecutive "
+                 "64-bit register pair");
 
-  auto RegTok = getTok(); // in case we need to backtrack
-  if (!tryParseScalarRegister(FirstReg).isSuccess())
-    return ParseStatus::NoMatch;
+  unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
+  bool IsXZRPair = FirstReg == AArch64::XZR;
+  if (!IsXZRPair && (FirstEncoding & 1))
+    return Error(S,
+                 "expected xzr/xzr or the first even register of a consecutive "
+                 "64-bit register pair");
 
-  if (!XRegClass.contains(FirstReg)) {
-    getLexer().UnLex(RegTok);
-    return ParseStatus::NoMatch;
-  }
+  if (getTok().isNot(AsmToken::Comma))
+    return Error(getLoc(), "expected comma");
+  Lex();
 
-  if (parseComma())
-    return ParseStatus::Failure;
+  SMLoc E = getLoc();
+  MCRegister SecondReg;
+  Res = tryParseScalarRegister(SecondReg);
+  if (!Res.isSuccess())
+    return Error(
+        E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
+                     : "expected second odd register of a consecutive 64-bit "
+                       "register pair");
 
-  if (!tryParseScalarRegister(SecondReg).isSuccess())
-    return TokError("expected register operand");
+  if (!XRegClass.contains(SecondReg))
+    return Error(
+        E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
+                     : "expected second odd register of a consecutive 64-bit "
+                       "register pair");
 
-  if (FirstReg == AArch64::XZR) {
+  if (IsXZRPair) {
     if (SecondReg != AArch64::XZR)
-      return TokError("xzr must be followed by xzr");
+      return Error(E, "expected second xzr in xzr/xzr register pair");
     // The SYSP alias is UNDEFINED if Rt<0> == '1' && Rt != '11111'.
-  } else if (RI->getEncodingValue(FirstReg) & 1) {
-    return TokError("first register must be even-numbered or xzr");
-  } else if (!XRegClass.contains(SecondReg) ||
-             RI->getEncodingValue(SecondReg) !=
-                 RI->getEncodingValue(FirstReg) + 1) {
-    return TokError(
-        "second register must be the next consecutive register after the "
-        "first register");
+  } else if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1) {
+    return Error(
+        E,
+        "expected second odd register of a consecutive 64-bit register pair");
   }
 
   // SYSP encodes only the first register; the second is implied as Rt+1.
-  Operands.push_back(AArch64Operand::CreateReg(
-      FirstReg, RegKind::Scalar, StartLoc, getLoc(), getContext()));
+  Operands.push_back(AArch64Operand::CreateReg(FirstReg, RegKind::Scalar, S,
+                                               getLoc(), getContext()));
 
   return ParseStatus::Success;
 }
@@ -4266,6 +4285,8 @@ bool AArch64AsmParser::parseSyspAlias(StringRef Name, SMLoc NameLoc,
   if (Tok.isNot(AsmToken::Identifier))
     return TokError("expected register identifier");
   auto Result = tryParseSyspPair(Operands);
+  if (Result.isFailure())
+    return true;
   if (!Result.isSuccess())
     return TokError("specified " + Mnemonic +
                     " op requires a pair of registers");
diff --git a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
index d3af63a994f5b..498f090762764 100644
--- a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
@@ -8,23 +8,23 @@
 // For sysp, op0 is 0
 
 sysp #0, c8, c0, #0, x0, x2
-// ERRORS: error: second register must be the next consecutive register after the first register
+// ERRORS: error: expected second odd register of a consecutive 64-bit register pair
 sysp #4, c8, c4, #1, x1, x2
-// ERRORS: error: first register must be even-numbered or xzr
+// ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
 sysp #4, c8, c4, #1, x2, x4
-// ERRORS: error: second register must be the next consecutive register after the first register
+// ERRORS: error: expected second odd register of a consecutive 64-bit register pair
 sysp #0, c8, c0, #0, x29, x31
-// ERRORS: error: first register must be even-numbered or xzr
+// ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
 sysp #0, c8, c0, #0, x30, x30
-// ERRORS: error: second register must be the next consecutive register after the first register
+// ERRORS: error: expected second odd register of a consecutive 64-bit register pair
 sysp #0, c8, c0, #0, x31, x0
-// ERRORS: error: xzr must be followed by xzr
+// ERRORS: error: expected second xzr in xzr/xzr register pair
 sysp #4, c8, c4, #1, xzr, x1
-// ERRORS: error: xzr must be followed by xzr
+// ERRORS: error: expected second xzr in xzr/xzr register pair
 sysp #0, c8, c0, #0, xzr, x30
-// ERRORS: error: xzr must be followed by xzr
+// ERRORS: error: expected second xzr in xzr/xzr register pair
 sysp #0, c8, c0, #0, w0, w1
-// ERRORS: error: invalid operand for instruction
+// ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
 sysp #7, c8, c0, #0, x0, x1
 // ERRORS: error: immediate must be an integer in range [0, 6].
 sysp #0, c7, c0, #0, x0, x1
@@ -36,7 +36,7 @@ sysp #0, c8, c8, #0, x0, x1
 sysp #0, c8, c0, #8, x0, x1
 // ERRORS: error: immediate must be an integer in range [0, 7].
 sysp #0, c8, c0, #0, xzr,
-// ERRORS: error: expected register operand
+// ERRORS: error: expected second xzr in xzr/xzr register pair
 
 tlbip RVAE3IS
 // ERRORS: error: expected comma
@@ -45,9 +45,9 @@ tlbip RVAE3IS,
 tlbip VAE3,
 // ERRORS: error: expected register identifier
 tlbip IPAS2E1, x4, x8
-// ERRORS: error: specified tlbip op requires a pair of registers
+// ERRORS: error: expected second odd register of a consecutive 64-bit register pair
 tlbip RVAE3, x11, x11
-// ERRORS: error: specified tlbip op requires a pair of registers
+// ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
 
 sysp #0, c8, c0, #0, x0
 // ERRORS: error: expected comma

>From 33a7f7739e6c48e1e79662e2b66fa22abd210dd4 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 2 Apr 2026 16:15:13 +0100
Subject: [PATCH 09/13] fixup! Implement Marian's suggestion to implement as
 XSeqPairsClass + [XZR, XZR]

---
 .../lib/Target/AArch64/AArch64RegisterInfo.td |   9 +-
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 136 +++++++-----------
 .../Disassembler/AArch64Disassembler.cpp      |  21 +--
 .../MCTargetDesc/AArch64InstPrinter.cpp       | 108 +++++---------
 .../AArch64/MCTargetDesc/AArch64InstPrinter.h |   4 +-
 llvm/test/MC/AArch64/armv9a-sysp.s            |   7 -
 6 files changed, 110 insertions(+), 175 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index cc2798de60943..c43da765def2c 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -813,6 +813,13 @@ def XSeqPairsClass   : RegisterClass<"AArch64", [untyped], 64,
                                      (add XSeqPairs)>{
   let Size = 128;
 }
+def SyspPairsClass   : RegisterClass<"AArch64", [untyped], 64,
+                                     (add XSeqPairs, XZR)>{
+  let Size = 128;
+  let isAllocatable = 0;
+  let GeneratePressureSet = 0;
+  let CopyCost = -1;
+}
 
 
 let RenderMethod = "addRegOperands", ParserMethod="tryParseGPRSeqPair" in {
@@ -839,7 +846,7 @@ def SyspPairOperandMatcherClass : AsmOperandClass {
   let ParserMethod = "tryParseSyspPair";
 }
 def SyspPairOperand :
-    RegisterOperand<GPR64, "printSyspPair"> {
+    RegisterOperand<SyspPairsClass, "printGPRSeqPairsClassOperand<64>"> {
   let ParserMatchClass = SyspPairOperandMatcherClass;
 }
 
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index bf99754bc9f63..e68dc9510ed4c 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -280,6 +280,12 @@ class AArch64AsmParser : public MCTargetAsmParser {
   ParseStatus tryParseVectorIndex(OperandVector &Operands);
   ParseStatus tryParseGPRSeqPair(OperandVector &Operands);
   ParseStatus tryParseSyspPair(OperandVector &Operands);
+  ParseStatus tryParseConsecutiveGPRSeqPair(OperandVector &Operands,
+                                            std::optional<unsigned> WPairClass,
+                                            unsigned XPairClass,
+                                            bool AllowXZRPair,
+                                            StringRef FirstRegExpected,
+                                            StringRef SecondRegExpected);
   template <bool ParseShiftExtend,
             RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
   ParseStatus tryParseGPROperand(OperandVector &Operands);
@@ -1449,7 +1455,11 @@ class AArch64Operand : public MCParsedAsmOperand {
                Reg.Reg);
   }
 
-  bool isSyspPair() const { return isGPR64<AArch64::GPR64RegClassID>(); }
+  bool isSyspPair() const {
+    return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
+           AArch64MCRegisterClasses[AArch64::SyspPairsClassRegClassID].contains(
+               Reg.Reg);
+  }
 
   template<int64_t Angle, int64_t Remainder>
   DiagnosticPredicate isComplexRotation() const {
@@ -3299,67 +3309,12 @@ ParseStatus AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
 }
 
 ParseStatus AArch64AsmParser::tryParseSyspPair(OperandVector &Operands) {
-  SMLoc S = getLoc();
-
-  if (getTok().isNot(AsmToken::Identifier))
-    return Error(S, "expected register");
-
-  MCRegister FirstReg;
-  ParseStatus Res = tryParseScalarRegister(FirstReg);
-  if (!Res.isSuccess())
-    return Error(S,
-                 "expected xzr/xzr or the first even register of a consecutive "
-                 "64-bit register pair");
-
-  const MCRegisterInfo *RI = getContext().getRegisterInfo();
-  const MCRegisterClass &XRegClass =
-      AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
-  if (!XRegClass.contains(FirstReg))
-    return Error(S,
-                 "expected xzr/xzr or the first even register of a consecutive "
-                 "64-bit register pair");
-
-  unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
-  bool IsXZRPair = FirstReg == AArch64::XZR;
-  if (!IsXZRPair && (FirstEncoding & 1))
-    return Error(S,
-                 "expected xzr/xzr or the first even register of a consecutive "
-                 "64-bit register pair");
-
-  if (getTok().isNot(AsmToken::Comma))
-    return Error(getLoc(), "expected comma");
-  Lex();
-
-  SMLoc E = getLoc();
-  MCRegister SecondReg;
-  Res = tryParseScalarRegister(SecondReg);
-  if (!Res.isSuccess())
-    return Error(
-        E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
-                     : "expected second odd register of a consecutive 64-bit "
-                       "register pair");
-
-  if (!XRegClass.contains(SecondReg))
-    return Error(
-        E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
-                     : "expected second odd register of a consecutive 64-bit "
-                       "register pair");
-
-  if (IsXZRPair) {
-    if (SecondReg != AArch64::XZR)
-      return Error(E, "expected second xzr in xzr/xzr register pair");
-    // The SYSP alias is UNDEFINED if Rt<0> == '1' && Rt != '11111'.
-  } else if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1) {
-    return Error(
-        E,
-        "expected second odd register of a consecutive 64-bit register pair");
-  }
-
-  // SYSP encodes only the first register; the second is implied as Rt+1.
-  Operands.push_back(AArch64Operand::CreateReg(FirstReg, RegKind::Scalar, S,
-                                               getLoc(), getContext()));
-
-  return ParseStatus::Success;
+  return tryParseConsecutiveGPRSeqPair(
+      Operands, std::nullopt, AArch64::XSeqPairsClassRegClassID,
+      /*AllowXZRPair=*/true,
+      "expected xzr/xzr or the first even register of a consecutive 64-bit "
+      "register pair",
+      "expected second odd register of a consecutive 64-bit register pair");
 }
 
 /// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
@@ -8723,6 +8678,19 @@ unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
 }
 
 ParseStatus AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
+  return tryParseConsecutiveGPRSeqPair(
+      Operands, AArch64::WSeqPairsClassRegClassID,
+      AArch64::XSeqPairsClassRegClassID, /*AllowXZRPair=*/false,
+      "expected first even register of a consecutive same-size even/odd "
+      "register pair",
+      "expected second odd register of a consecutive same-size even/odd "
+      "register pair");
+}
+
+ParseStatus AArch64AsmParser::tryParseConsecutiveGPRSeqPair(
+    OperandVector &Operands, std::optional<unsigned> WPairClass,
+    unsigned XPairClass, bool AllowXZRPair, StringRef FirstRegExpected,
+    StringRef SecondRegExpected) {
 
   SMLoc S = getLoc();
 
@@ -8732,52 +8700,56 @@ ParseStatus AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
   MCRegister FirstReg;
   ParseStatus Res = tryParseScalarRegister(FirstReg);
   if (!Res.isSuccess())
-    return Error(S, "expected first even register of a consecutive same-size "
-                    "even/odd register pair");
+    return Error(S, FirstRegExpected);
 
   const MCRegisterClass &WRegClass =
       AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
   const MCRegisterClass &XRegClass =
       AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
 
-  bool isXReg = XRegClass.contains(FirstReg),
-       isWReg = WRegClass.contains(FirstReg);
-  if (!isXReg && !isWReg)
-    return Error(S, "expected first even register of a consecutive same-size "
-                    "even/odd register pair");
+  bool IsXZRPair = AllowXZRPair && FirstReg == AArch64::XZR;
+  bool IsXReg = XRegClass.contains(FirstReg);
+  bool IsWReg = WPairClass && WRegClass.contains(FirstReg);
+  if (!IsXZRPair && !IsXReg && !IsWReg)
+    return Error(S, FirstRegExpected);
 
   const MCRegisterInfo *RI = getContext().getRegisterInfo();
   unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
 
-  if (FirstEncoding & 0x1)
-    return Error(S, "expected first even register of a consecutive same-size "
-                    "even/odd register pair");
+  if (!IsXZRPair && (FirstEncoding & 0x1))
+    return Error(S, FirstRegExpected);
 
   if (getTok().isNot(AsmToken::Comma))
     return Error(getLoc(), "expected comma");
-  // Eat the comma
   Lex();
 
   SMLoc E = getLoc();
   MCRegister SecondReg;
   Res = tryParseScalarRegister(SecondReg);
   if (!Res.isSuccess())
-    return Error(E, "expected second odd register of a consecutive same-size "
-                    "even/odd register pair");
+    return Error(E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
+                              : SecondRegExpected);
+
+  if (IsXZRPair) {
+    if (!XRegClass.contains(SecondReg) || SecondReg != AArch64::XZR)
+      return Error(E, "expected second xzr in xzr/xzr register pair");
+    Operands.push_back(AArch64Operand::CreateReg(AArch64::XZR, RegKind::Scalar,
+                                                 S, getLoc(), getContext()));
+    return ParseStatus::Success;
+  }
 
   if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
-      (isXReg && !XRegClass.contains(SecondReg)) ||
-      (isWReg && !WRegClass.contains(SecondReg)))
-    return Error(E, "expected second odd register of a consecutive same-size "
-                    "even/odd register pair");
+      (IsXReg && !XRegClass.contains(SecondReg)) ||
+      (IsWReg && !WRegClass.contains(SecondReg)))
+    return Error(E, SecondRegExpected);
 
   MCRegister Pair;
-  if (isXReg) {
+  if (IsXReg) {
     Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
-           &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
+                                   &AArch64MCRegisterClasses[XPairClass]);
   } else {
     Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
-           &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
+                                   &AArch64MCRegisterClasses[*WPairClass]);
   }
 
   Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 74063d03e346d..eeba5563b9f96 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1387,6 +1387,17 @@ DecodeXSeqPairsClassRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr,
       Inst, AArch64::XSeqPairsClassRegClassID, RegNo, Addr, Decoder);
 }
 
+static DecodeStatus
+DecodeSyspPairClassRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr,
+                                 const MCDisassembler *Decoder) {
+  if (RegNo == 31) {
+    Inst.addOperand(MCOperand::createReg(AArch64::XZR));
+    return Success;
+  }
+
+  return DecodeXSeqPairsClassRegisterClass(Inst, RegNo, Addr, Decoder);
+}
+
 static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
                                           uint64_t Addr,
                                           const MCDisassembler *Decoder) {
@@ -1399,19 +1410,11 @@ static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
   if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7)
     return Fail;
 
-  // the first register must be even-numbered, except for the XZR/XZR case.
-  if (Rt != 31 && (Rt & 0x1))
-    return Fail;
-
   Inst.addOperand(MCOperand::createImm(op1));
   Inst.addOperand(MCOperand::createImm(CRn));
   Inst.addOperand(MCOperand::createImm(CRm));
   Inst.addOperand(MCOperand::createImm(op2));
-  // SYSP just encodes Rt. Print Rt and Rt+1 as a pair.
-  DecodeSimpleRegisterClass<AArch64::GPR64RegClassID, 0, 32>(Inst, Rt, Addr,
-                                                             Decoder);
-
-  return Success;
+  return DecodeSyspPairClassRegisterClass(Inst, Rt, Addr, Decoder);
 }
 
 static DecodeStatus
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 32c8315ba984b..c4f7bb40982f6 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -101,11 +101,12 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
     // canonical operand list.
     if (PrintAliases && MI->getOperand(4).getReg() == AArch64::XZR) {
       O << "\tsysp\t";
-      markup(O, Markup::Immediate) << "#" << MI->getOperand(0).getImm();
+      markup(O, Markup::Immediate) << "#" << formatImm(MI->getOperand(0).getImm());
       O << ", c" << MI->getOperand(1).getImm();
       O << ", c" << MI->getOperand(2).getImm();
       O << ", ";
-      markup(O, Markup::Immediate) << "#" << MI->getOperand(3).getImm();
+      markup(O, Markup::Immediate) << "#"
+                                   << formatImm(MI->getOperand(3).getImm());
       printAnnotation(O, Annot);
       return;
     }
@@ -914,10 +915,11 @@ bool AArch64InstPrinter::printRangePrefetchAlias(const MCInst *MI,
 
 bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
                                        const MCSubtargetInfo &STI,
-                                       raw_ostream &O) {
+                                       raw_ostream &O, bool PairOperand) {
 #ifndef NDEBUG
   unsigned Opcode = MI->getOpcode();
-  assert(Opcode == AArch64::SYSxt && "Invalid opcode for SYS alias!");
+  assert((Opcode == AArch64::SYSxt || Opcode == AArch64::SYSPxt) &&
+         "Invalid opcode for system alias!");
 #endif
 
   const MCOperand &Op1 = MI->getOperand(0);
@@ -940,7 +942,18 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
   std::string Ins;
   std::string Name;
 
-  if (CnVal == 7) {
+  if (PairOperand) {
+    if (CnVal != 8 && CnVal != 9)
+      return false;
+
+    const AArch64TLBIP::TLBIP *TLBIP =
+        AArch64TLBIP::lookupTLBIPByEncoding(Encoding);
+    if (!TLBIP || !TLBIP->haveFeatures(STI.getFeatureBits()))
+      return false;
+
+    Ins = "tlbip\t";
+    Name = std::string(TLBIP->Name);
+  } else if (CnVal == 7) {
     switch (CmVal) {
     default:
       return false;
@@ -1072,6 +1085,16 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
   } else
     return false;
 
+  std::string Str = Ins + Name;
+  llvm::transform(Str, Str.begin(), ::tolower);
+
+  if (PairOperand) {
+    O << '\t' << Str;
+    O << ", ";
+    printGPRSeqPairsClassOperand<64>(MI, 4, STI, O);
+    return true;
+  }
+
   StringRef Reg = getRegisterName(MI->getOperand(4).getReg());
   bool NotXZR = Reg != "xzr";
 
@@ -1081,9 +1104,6 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
   if (NotXZR && !NeedsReg && !OptionalReg)
     return false;
 
-  std::string Str = Ins + Name;
-  llvm::transform(Str, Str.begin(), ::tolower);
-
   O << '\t' << Str;
 
   // For optional registers, don't print the value if it's xzr/x31
@@ -1146,51 +1166,7 @@ bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
 bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
                                         const MCSubtargetInfo &STI,
                                         raw_ostream &O) {
-#ifndef NDEBUG
-  unsigned Opcode = MI->getOpcode();
-  assert(Opcode == AArch64::SYSPxt && "Invalid opcode for SYSP alias!");
-#endif
-
-  const MCOperand &Op1 = MI->getOperand(0);
-  const MCOperand &Cn = MI->getOperand(1);
-  const MCOperand &Cm = MI->getOperand(2);
-  const MCOperand &Op2 = MI->getOperand(3);
-
-  unsigned Op1Val = Op1.getImm();
-  unsigned CnVal = Cn.getImm();
-  unsigned CmVal = Cm.getImm();
-  unsigned Op2Val = Op2.getImm();
-
-  uint16_t Encoding = Op2Val;
-  Encoding |= CmVal << 3;
-  Encoding |= CnVal << 7;
-  Encoding |= Op1Val << 11;
-
-  std::string Ins;
-  std::string Name;
-
-  if (CnVal == 8 || CnVal == 9) {
-    // TLBIP aliases
-
-    const AArch64TLBIP::TLBIP *TLBIP =
-        AArch64TLBIP::lookupTLBIPByEncoding(Encoding);
-    if (!TLBIP || !TLBIP->haveFeatures(STI.getFeatureBits()))
-      return false;
-
-    Ins = "tlbip\t";
-    Name = std::string(TLBIP->Name);
-  } else
-    return false;
-
-  std::string Str = Ins + Name;
-  llvm::transform(Str, Str.begin(), ::tolower);
-
-  O << '\t' << Str;
-  O << ", ";
-  // TLBIP alias keeps SYSP's pair formatting rules for the trailing operand.
-  printSyspPair(MI, 4, STI, O);
-
-  return true;
+  return printSysAlias(MI, STI, O, /*PairOperand=*/true);
 }
 
 template <int EltSize>
@@ -1750,6 +1726,12 @@ void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst *MI,
   static_assert(size == 64 || size == 32,
                 "Template parameter must be either 32 or 64");
   MCRegister Reg = MI->getOperand(OpNum).getReg();
+  if (Reg == AArch64::XZR) {
+    printRegName(O, AArch64::XZR);
+    O << ", ";
+    printRegName(O, AArch64::XZR);
+    return;
+  }
 
   unsigned Sube = (size == 32) ? AArch64::sube32 : AArch64::sube64;
   unsigned Subo = (size == 32) ? AArch64::subo32 : AArch64::subo64;
@@ -2269,26 +2251,6 @@ void AArch64InstPrinter::printGPR64x8(const MCInst *MI, unsigned OpNum,
   printRegName(O, MRI.getSubReg(Reg, AArch64::x8sub_0));
 }
 
-void AArch64InstPrinter::printSyspPair(const MCInst *MI, unsigned OpNum,
-                                       const MCSubtargetInfo &STI,
-                                       raw_ostream &O) {
-  MCRegister Reg = MI->getOperand(OpNum).getReg();
-  printRegName(O, Reg);
-  O << ", ";
-  if (Reg == AArch64::XZR) {
-    printRegName(O, AArch64::XZR);
-    return;
-  }
-
-  const MCRegisterClass &XRegClass =
-      AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
-  // SYSP textual form prints the implied second register as Rt+1.
-  unsigned NextRegNo = MRI.getEncodingValue(Reg) + 1;
-  assert(NextRegNo < XRegClass.getNumRegs() &&
-         "SYSP pair starts from an invalid GPR64 register");
-  printRegName(O, XRegClass.getRegister(NextRegNo));
-}
-
 void AArch64InstPrinter::printPHintOp(const MCInst *MI, unsigned OpNum,
                                       const MCSubtargetInfo &STI,
                                       raw_ostream &O) {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 0b34d9edfa82b..378c6f106055d 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -51,7 +51,7 @@ class AArch64InstPrinter : public MCInstPrinter {
 
 protected:
   bool printSysAlias(const MCInst *MI, const MCSubtargetInfo &STI,
-                     raw_ostream &O);
+                     raw_ostream &O, bool PairOperand = false);
   bool printSyslAlias(const MCInst *MI, const MCSubtargetInfo &STI,
                       raw_ostream &O);
   bool printSyspAlias(const MCInst *MI, const MCSubtargetInfo &STI,
@@ -237,8 +237,6 @@ class AArch64InstPrinter : public MCInstPrinter {
                       const MCSubtargetInfo &STI, raw_ostream &O);
   void printGPR64x8(const MCInst *MI, unsigned OpNum,
                     const MCSubtargetInfo &STI, raw_ostream &O);
-  void printSyspPair(const MCInst *MI, unsigned OpNum,
-                     const MCSubtargetInfo &STI, raw_ostream &O);
   template <int Width>
   void printZPRasFPR(const MCInst *MI, unsigned OpNum,
                      const MCSubtargetInfo &STI, raw_ostream &O);
diff --git a/llvm/test/MC/AArch64/armv9a-sysp.s b/llvm/test/MC/AArch64/armv9a-sysp.s
index 3753fcc684c4f..c01e83c92fcfd 100644
--- a/llvm/test/MC/AArch64/armv9a-sysp.s
+++ b/llvm/test/MC/AArch64/armv9a-sysp.s
@@ -2,8 +2,6 @@
 // RUN:        | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
 // RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \
 // RUN:        | llvm-objdump -d --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
-// RUN: llvm-mc -triple=aarch64 -filetype=obj < %s \
-// RUN:        | llvm-objdump -d -M no-aliases --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-NOALIAS
 // Disassemble encoding and check the re-encoding (-show-encoding) matches.
 // RUN: llvm-mc -triple=aarch64 -show-encoding < %s \
 // RUN:        | sed '/.text/d' | sed 's/.*encoding: //g' \
@@ -149,25 +147,20 @@ sysp #0, c8, c0, #0, x30, x31
 
 sysp #0, c8, c0, #0, x31, x31
 // CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0, x31, xzr
 // CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0, xzr, x31
 // CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
 
 sysp #0, c8, c0, #0
 // CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-NOALIAS: sysp #0, c8, c0, #0, xzr, xzr
 // CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]

>From d7c907a6b50450d5dddd0e756b9fd7ce7f73afeb Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 17 Apr 2026 15:30:07 +0100
Subject: [PATCH 10/13] fixup! Address PR comment about shortened `sysp` with
 xzr/xzr

---
 .../MCTargetDesc/AArch64InstPrinter.cpp       | 33 ++++++++++---------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index c4f7bb40982f6..77c42b3657135 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -95,21 +95,6 @@ void AArch64InstPrinter::printInst(const MCInst *MI, uint64_t Address,
       printAnnotation(O, Annot);
       return;
     }
-
-    // Preserve the historic SYSP short form for the XZR/XZR encoding, but
-    // only when aliases are enabled. In no-alias mode we must print the full
-    // canonical operand list.
-    if (PrintAliases && MI->getOperand(4).getReg() == AArch64::XZR) {
-      O << "\tsysp\t";
-      markup(O, Markup::Immediate) << "#" << formatImm(MI->getOperand(0).getImm());
-      O << ", c" << MI->getOperand(1).getImm();
-      O << ", c" << MI->getOperand(2).getImm();
-      O << ", ";
-      markup(O, Markup::Immediate) << "#"
-                                   << formatImm(MI->getOperand(3).getImm());
-      printAnnotation(O, Annot);
-      return;
-    }
   }
 
   // RPRFM overlaps PRFM (reg), so try to print it as RPRFM here.
@@ -1166,7 +1151,23 @@ bool AArch64InstPrinter::printSyslAlias(const MCInst *MI,
 bool AArch64InstPrinter::printSyspAlias(const MCInst *MI,
                                         const MCSubtargetInfo &STI,
                                         raw_ostream &O) {
-  return printSysAlias(MI, STI, O, /*PairOperand=*/true);
+  if (printSysAlias(MI, STI, O, /*PairOperand=*/true))
+    return true;
+
+  // Preserve SYSP short form for XZR/XZR encoding:
+  //   sysp #op1, cN, cM, #op2
+  // instead of:
+  //   sysp #op1, cN, cM, #op2, xzr, xzr
+  if (MI->getOperand(4).getReg() != AArch64::XZR)
+    return false;
+
+  O << "\tsysp\t";
+  markup(O, Markup::Immediate) << "#" << formatImm(MI->getOperand(0).getImm());
+  O << ", c" << MI->getOperand(1).getImm();
+  O << ", c" << MI->getOperand(2).getImm();
+  O << ", ";
+  markup(O, Markup::Immediate) << "#" << formatImm(MI->getOperand(3).getImm());
+  return true;
 }
 
 template <int EltSize>

>From 14211442c7b9d2b40c6fcd41f7a0ecf90447ff94 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 28 Apr 2026 17:33:06 +0100
Subject: [PATCH 11/13] fixup! Remove superfluous code

---
 llvm/lib/Target/AArch64/AArch64InstrFormats.td | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 10f1500832600..5de1c17f40db9 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -2159,13 +2159,6 @@ def sysp_crm_op : Operand<i32> {
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
-def sysp_op1 : Operand<i64>, ImmLeaf<i64, [{
-  return Imm >= 0 && Imm <= 6;
-}]> {
-  let ParserMatchClass = Imm0_7Operand;
-  let OperandType = "OPERAND_IMMEDIATE";
-}
-
 class SystemXtI<string asm>
   : RtSystemI<0, (outs),
        (ins imm32_0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm32_0_7:$op2,

>From 4fa459d20f6f2beaf66dadb2a86a95bcbf591333 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 1 May 2026 14:33:15 +0100
Subject: [PATCH 12/13] fixup! Address Carol's PR comments

---
 llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 3 +++
 llvm/test/MC/AArch64/armv9a-tlbip.s                    | 5 +++++
 2 files changed, 8 insertions(+)

diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index e68dc9510ed4c..df68ef3718c44 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -8721,11 +8721,14 @@ ParseStatus AArch64AsmParser::tryParseConsecutiveGPRSeqPair(
 
   if (getTok().isNot(AsmToken::Comma))
     return Error(getLoc(), "expected comma");
+  // Eat the comma
   Lex();
 
   SMLoc E = getLoc();
   MCRegister SecondReg;
   Res = tryParseScalarRegister(SecondReg);
+  // SYSP accepts either no register pair or `xzr, xzr`. The omitted form
+  // is changed to `xzr, xzr` during assembly.
   if (!Res.isSuccess())
     return Error(E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
                               : SecondRegExpected);
diff --git a/llvm/test/MC/AArch64/armv9a-tlbip.s b/llvm/test/MC/AArch64/armv9a-tlbip.s
index 8764a83809472..ed68865f22698 100644
--- a/llvm/test/MC/AArch64/armv9a-tlbip.s
+++ b/llvm/test/MC/AArch64/armv9a-tlbip.s
@@ -55,6 +55,11 @@ tlbip VAE1, x8, x9
 // CHECK-TLBID: error: instruction requires: d128
 // CHECK-UNKNOWN: d5488728 sysp #0, c8, c7, #1, x8, x9
 
+sysp #0, c8, c7, #1, x8, x9
+// CHECK-INST: tlbip vae1, x8, x9
+// CHECK-ENCODING: encoding: [0x28,0x87,0x48,0xd5]
+// CHECK-UNKNOWN: d5488728 sysp #0, c8, c7, #1, x8, x9
+
 tlbip VAE1NXS, x8, x9
 // CHECK-INST: tlbip vae1nxs, x8, x9
 // CHECK-ENCODING: encoding: [0x28,0x97,0x48,0xd5]

>From 3b2d2ea9c4fe0f2785352f911875ddae0bd6aab4 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 1 May 2026 15:16:35 +0100
Subject: [PATCH 13/13] fixup! Update diff because SYSP definition has changed

---
 .../command-disassemble-aarch64-color.s       |   4 +-
 .../command-disassemble-aarch64-extensions.s  |   4 +-
 .../lib/Target/AArch64/AArch64InstrFormats.td |  39 +--
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |   3 +-
 .../AArch64/AsmParser/AArch64AsmParser.cpp    |  13 +-
 .../Disassembler/AArch64Disassembler.cpp      |   3 -
 llvm/test/MC/AArch64/armv9-sysp-diagnostics.s |  40 ++-
 llvm/test/MC/AArch64/armv9a-sysp.s            | 240 +++++++++---------
 8 files changed, 159 insertions(+), 187 deletions(-)

diff --git a/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s b/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s
index 6ddde3d974adc..bb97680a32970 100644
--- a/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s
+++ b/lldb/test/Shell/Commands/command-disassemble-aarch64-color.s
@@ -17,7 +17,7 @@ fn:
   crc32b w0, w0, w0                     // AEK_CRC
   // AEK_CRYPTO enables a combination of other features
   smin x0, x0, #0                       // AEK_CSSC
-  sysp	#0, c8, c0, #0, x0, x1          // AEK_D128
+  sysp	#0, c2, c0, #0, x0, x1          // AEK_D128
   sdot v0.2s, v1.8b, v2.8b              // AEK_DOTPROD
   fmmla z0.s, z1.s, z2.s                // AEK_F32MM
 
@@ -28,6 +28,6 @@ fn:
 # CHECK-NEXT: [0xc] <+12>:   brb    iall
 # CHECK-NEXT: [0x10] <+16>:  crc32b w0, w0, w0
 # CHECK-NEXT: [0x14] <+20>:  smin   x0, x0, #0x0
-# CHECK-NEXT: [0x18] <+24>:  sysp   #0x0, c8, c0, #0x0, x0, x1
+# CHECK-NEXT: [0x18] <+24>:  sysp   #0x0, c2, c0, #0x0, x0, x1
 # CHECK-NEXT: [0x1c] <+28>:  sdot   v0.2s, v1.8b, v2.8b
 # CHECK-NEXT: [0x20] <+32>:  fmmla  z0.s, z1.s, z2.s
diff --git a/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s b/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
index 945654e905876..4e281332a33bb 100644
--- a/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
+++ b/lldb/test/Shell/Commands/command-disassemble-aarch64-extensions.s
@@ -17,7 +17,7 @@ fn:
   crc32b w0, w0, w0                     // AEK_CRC
   // AEK_CRYPTO enables a combination of other features
   smin x0, x0, #0                       // AEK_CSSC
-  sysp	#0, c8, c0, #0, x0, x1          // AEK_D128
+  sysp	#0, c2, c0, #0, x0, x1          // AEK_D128
   sdot v0.2s, v1.8b, v2.8b              // AEK_DOTPROD
   fmmla z0.s, z1.s, z2.s                // AEK_F32MM
   fmmla z0.d, z1.d, z2.d                // AEK_F64MM
@@ -72,7 +72,7 @@ lbl:
 # CHECK-NEXT: brb    iall
 # CHECK-NEXT: crc32b w0, w0, w0
 # CHECK-NEXT: smin   x0, x0, #0
-# CHECK-NEXT: sysp   #0x0, c8, c0, #0x0, x0, x1
+# CHECK-NEXT: sysp   #0x0, c2, c0, #0x0, x0, x1
 # CHECK-NEXT: sdot   v0.2s, v1.8b, v2.8b
 # CHECK-NEXT: fmmla  z0.s, z1.s, z2.s
 # CHECK-NEXT: fmmla  z0.d, z1.d, z2.d
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 5de1c17f40db9..209d630d361b4 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -951,7 +951,6 @@ def Imm0_1Operand : AsmImmRange<0, 1>;
 def Imm1_1Operand : AsmImmRange<1, 1>;
 def Imm0_3Operand : AsmImmRange<0, 3>;
 def Imm1_3Operand : AsmImmRange<1, 3>;
-def Imm0_6Operand : AsmImmRange<0, 6>;
 def Imm0_7Operand : AsmImmRange<0, 7>;
 def Imm1_7Operand : AsmImmRange<1, 7>;
 def Imm0_15Operand : AsmImmRange<0, 15>;
@@ -1185,13 +1184,6 @@ def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
   let ParserMatchClass = Imm0_15Operand;
 }
 
-// imm0_6 predicate - True if the immediate is in the range [0,6]
-def imm0_6 : Operand<i64>, ImmLeaf<i64, [{
-  return ((uint64_t)Imm) < 7;
-}]> {
-  let ParserMatchClass = Imm0_6Operand;
-}
-
 // imm0_7 predicate - True if the immediate is in the range [0,7]
 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
   return ((uint64_t)Imm) < 8;
@@ -2126,36 +2118,20 @@ class MSRpstateImm0_1
   let DecoderNamespace = "Fallback";
 }
 
-// SYS and SYSL generic system instructions.
-class SysCRAsmOperand<int Low, int High> : AsmOperandClass {
-  let Name = "SysCR" # Low # "_" # High;
+// SYS, SYSL and SYSP generic system instructions.
+def SysCRAsmOperand : AsmOperandClass {
+  let Name = "SysCR";
   let RenderMethod = "addSysCROperands";
   let ParserMethod = "tryParseSysCROperand";
-  let PredicateMethod = "isSysCRInRange<" # Low # "," # High # ">";
-  let DiagnosticType = "InvalidSysCR" # Low # "_" # High;
+  let PredicateMethod = "isSysCRInRange<0,15>";
+  let DiagnosticType = "InvalidSysCR0_15";
 }
 
-def SysCRm0_7AsmOperand : SysCRAsmOperand<0, 7>;
-def SysCRn8_9AsmOperand : SysCRAsmOperand<8, 9>;
-def SysCR0_15AsmOperand : SysCRAsmOperand<0, 15>;
-
 def sys_cr_op : Operand<i32>, TImmLeaf<i32, [{
   return ((uint32_t)Imm) < 16;
 }]> {
   let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCR0_15AsmOperand;
-  let OperandType = "OPERAND_IMMEDIATE";
-}
-
-def sysp_crn_op : Operand<i32> {
-  let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRn8_9AsmOperand;
-  let OperandType = "OPERAND_IMMEDIATE";
-}
-
-def sysp_crm_op : Operand<i32> {
-  let PrintMethod = "printSysCROperand";
-  let ParserMatchClass = SysCRm0_7AsmOperand;
+  let ParserMatchClass = SysCRAsmOperand;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
@@ -13345,8 +13321,7 @@ class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inpu
 }
 class SystemPXtI<bit L, string asm> :
   BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
-  (ins imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm, imm0_7:$op2,
-       SyspPairOperand:$Rt)>;
+  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, SyspPairOperand:$Rt)>;
 
 //----------------------------------------------------------------------------
 // 2023 Armv9.5 Extensions
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index c4c167a2ad3ba..f080c26500651 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -11598,8 +11598,7 @@ def SYSPxt  : SystemPXtI<0, "sysp"> {
 }
 
 def : InstAlias<"sysp $op1, $Cn, $Cm, $op2",
-                (SYSPxt imm0_6:$op1, sysp_crn_op:$Cn, sysp_crm_op:$Cm,
-                        imm0_7:$op2, XZR)>;
+                (SYSPxt imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XZR)>;
 
 //---
 // 128-bit System Registers (FEAT_SYSREG128)
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index df68ef3718c44..43182b9975331 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -6256,8 +6256,6 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "immediate must be an integer in range [0, 1].");
   case Match_InvalidImm0_3:
     return Error(Loc, "immediate must be an integer in range [0, 3].");
-  case Match_InvalidImm0_6:
-    return Error(Loc, "immediate must be an integer in range [0, 6].");
   case Match_InvalidImm0_7:
     return Error(Loc, "immediate must be an integer in range [0, 7].");
   case Match_InvalidImm0_15:
@@ -6282,10 +6280,6 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
     return Error(Loc, "immediate must be an integer in range [1, 64].");
   case Match_InvalidImmM1_62:
     return Error(Loc, "immediate must be an integer in range [-1, 62].");
-  case Match_InvalidSysCR0_7:
-    return Error(Loc, "expected cN operand where 0 <= N <= 7");
-  case Match_InvalidSysCR8_9:
-    return Error(Loc, "expected cN operand where 8 <= N <= 9");
   case Match_InvalidSysCR0_15:
     return Error(Loc, "expected cN operand where 0 <= N <= 15");
   case Match_InvalidMemoryIndexedRange2UImm0:
@@ -7052,7 +7046,6 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidImm0_0:
   case Match_InvalidImm0_1:
   case Match_InvalidImm0_3:
-  case Match_InvalidImm0_6:
   case Match_InvalidImm0_7:
   case Match_InvalidImm0_15:
   case Match_InvalidImm0_31:
@@ -7065,8 +7058,6 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidImm1_32:
   case Match_InvalidImm1_64:
   case Match_InvalidImmM1_62:
-  case Match_InvalidSysCR0_7:
-  case Match_InvalidSysCR8_9:
   case Match_InvalidSysCR0_15:
   case Match_InvalidMemoryIndexedRange2UImm0:
   case Match_InvalidMemoryIndexedRange2UImm1:
@@ -8727,12 +8718,12 @@ ParseStatus AArch64AsmParser::tryParseConsecutiveGPRSeqPair(
   SMLoc E = getLoc();
   MCRegister SecondReg;
   Res = tryParseScalarRegister(SecondReg);
-  // SYSP accepts either no register pair or `xzr, xzr`. The omitted form
-  // is changed to `xzr, xzr` during assembly.
   if (!Res.isSuccess())
     return Error(E, IsXZRPair ? "expected second xzr in xzr/xzr register pair"
                               : SecondRegExpected);
 
+  // For SYSP, Rt == 31 denotes the optional-pair default. If the explicit
+  // pair starts with xzr, the derived second register must be xzr too.
   if (IsXZRPair) {
     if (!XRegClass.contains(SecondReg) || SecondReg != AArch64::XZR)
       return Error(E, "expected second xzr in xzr/xzr register pair");
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index eeba5563b9f96..df5778b95f3e7 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1407,9 +1407,6 @@ static DecodeStatus DecodeSyspInstruction(MCInst &Inst, uint32_t insn,
   unsigned op2 = fieldFromInstruction(insn, 5, 3);
   unsigned Rt = fieldFromInstruction(insn, 0, 5);
 
-  if (op1 > 6 || (CRn != 8 && CRn != 9) || CRm > 7)
-    return Fail;
-
   Inst.addOperand(MCOperand::createImm(op1));
   Inst.addOperand(MCOperand::createImm(CRn));
   Inst.addOperand(MCOperand::createImm(CRm));
diff --git a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
index 498f090762764..25c4ab7119ab3 100644
--- a/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9-sysp-diagnostics.s
@@ -7,35 +7,33 @@
 // registers with 128-bit formats (op0, op1, Cn, Cm, op2)
 // For sysp, op0 is 0
 
-sysp #0, c8, c0, #0, x0, x2
+sysp #0, c2, c0, #0, x0, x2
 // ERRORS: error: expected second odd register of a consecutive 64-bit register pair
-sysp #4, c8, c4, #1, x1, x2
+sysp #4, c2, c0, #1, x1, x2
 // ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
-sysp #4, c8, c4, #1, x2, x4
+sysp #4, c2, c0, #1, x2, x4
 // ERRORS: error: expected second odd register of a consecutive 64-bit register pair
-sysp #0, c8, c0, #0, x29, x31
+sysp #0, c2, c0, #0, x29, x31
 // ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
-sysp #0, c8, c0, #0, x30, x30
+sysp #0, c2, c0, #0, x30, x30
 // ERRORS: error: expected second odd register of a consecutive 64-bit register pair
-sysp #0, c8, c0, #0, x31, x0
+sysp #0, c2, c0, #0, x31, x0
 // ERRORS: error: expected second xzr in xzr/xzr register pair
-sysp #4, c8, c4, #1, xzr, x1
+sysp #4, c2, c0, #1, xzr, x1
 // ERRORS: error: expected second xzr in xzr/xzr register pair
-sysp #0, c8, c0, #0, xzr, x30
+sysp #0, c2, c0, #0, xzr, x30
 // ERRORS: error: expected second xzr in xzr/xzr register pair
-sysp #0, c8, c0, #0, w0, w1
+sysp #0, c2, c0, #0, w0, w1
 // ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
-sysp #7, c8, c0, #0, x0, x1
-// ERRORS: error: immediate must be an integer in range [0, 6].
-sysp #0, c7, c0, #0, x0, x1
-// ERRORS: error: expected cN operand where 8 <= N <= 9
-sysp #0, c10, c0, #0, x0, x1
-// ERRORS: error: expected cN operand where 8 <= N <= 9
-sysp #0, c8, c8, #0, x0, x1
-// ERRORS: error: expected cN operand where 0 <= N <= 7
-sysp #0, c8, c0, #8, x0, x1
+sysp #8, c2, c0, #0, x0, x1
 // ERRORS: error: immediate must be an integer in range [0, 7].
-sysp #0, c8, c0, #0, xzr,
+sysp #0, c16, c0, #0, x0, x1
+// ERRORS: error: Expected cN operand where 0 <= N <= 15
+sysp #0, c2, c16, #0, x0, x1
+// ERRORS: error: Expected cN operand where 0 <= N <= 15
+sysp #0, c2, c0, #8, x0, x1
+// ERRORS: error: immediate must be an integer in range [0, 7].
+sysp #0, c2, c0, #0, xzr,
 // ERRORS: error: expected second xzr in xzr/xzr register pair
 
 tlbip RVAE3IS
@@ -49,7 +47,7 @@ tlbip IPAS2E1, x4, x8
 tlbip RVAE3, x11, x11
 // ERRORS: error: expected xzr/xzr or the first even register of a consecutive 64-bit register pair
 
-sysp #0, c8, c0, #0, x0
+sysp #0, c2, c0, #0, x0
 // ERRORS: error: expected comma
-sysp #0, c8, c0, #0, xzr
+sysp #0, c2, c0, #0, xzr
 // ERRORS: error: expected comma
diff --git a/llvm/test/MC/AArch64/armv9a-sysp.s b/llvm/test/MC/AArch64/armv9a-sysp.s
index c01e83c92fcfd..463f98a770cd2 100644
--- a/llvm/test/MC/AArch64/armv9a-sysp.s
+++ b/llvm/test/MC/AArch64/armv9a-sysp.s
@@ -13,154 +13,166 @@
 // registers with 128-bit formats (op0, op1, Cn, Cm, op2)
 // For sysp, op0 is 0
 
-sysp #0, c8, c0, #0, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x0, x1// TTBR0_EL1     3  0  2  0  0
+// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #1, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #1, x0, x1
-// CHECK-ENCODING: encoding: [0x20,0x80,0x48,0xd5]
+sysp #0, c2, c0, #1, x0, x1// TTBR1_EL1     3  0  2  0  1
+// CHECK-INST: sysp #0, c2, c0, #1, x0, x1
+// CHECK-ENCODING: encoding: [0x20,0x20,0x48,0xd5]
 
-sysp #0, c9, c0, #0, x0, x1
-// CHECK-INST: sysp #0, c9, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x90,0x48,0xd5]
+sysp #0, c7, c4, #0, x0, x1// PAR_EL1       3  0  7  4  0
+// CHECK-INST: sysp #0, c7, c4, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x74,0x48,0xd5]
 
-sysp #0, c8, c4, #0, x0, x1
-// CHECK-INST: sysp #0, c8, c4, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x84,0x48,0xd5]
+sysp #0, c13, c0, #3, x0, x1         // RCWSMASK_EL1  3  0 13  0  3
+// CHECK-INST: sysp #0, c13, c0, #3, x0, x1
+// CHECK-ENCODING: encoding: [0x60,0xd0,0x48,0xd5]
 
-sysp #0, c8, c0, #3, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #3, x0, x1
-// CHECK-ENCODING: encoding: [0x60,0x80,0x48,0xd5]
+sysp #0, c13, c0, #6, x0, x1         // RCWMASK_EL1   3  0 13  0  6
+// CHECK-INST: sysp #0, c13, c0, #6, x0, x1
+// CHECK-ENCODING: encoding: [0xc0,0xd0,0x48,0xd5]
 
-sysp #0, c8, c0, #6, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #6, x0, x1
-// CHECK-ENCODING: encoding: [0xc0,0x80,0x48,0xd5]
+sysp #4, c2, c0, #0, x0, x1// TTBR0_EL2     3  4  2  0  0
+// CHECK-INST: sysp #4, c2, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x20,0x4c,0xd5]
 
-sysp #4, c8, c0, #0, x0, x1
-// CHECK-INST: sysp #4, c8, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x80,0x4c,0xd5]
+sysp #4, c2, c0, #1, x0, x1// TTBR1_EL2     3  4  2  0  1
+// CHECK-INST: sysp #4, c2, c0, #1, x0, x1
+// CHECK-ENCODING: encoding: [0x20,0x20,0x4c,0xd5]
 
-sysp #4, c8, c0, #3, x0, x1
-// CHECK-INST: sysp #4, c8, c0, #3, x0, x1
-// CHECK-ENCODING: encoding: [0x60,0x80,0x4c,0xd5]
+sysp #4, c2, c1, #0, x0, x1// VTTBR_EL2     3  4  2  1  0
+// CHECK-INST: sysp #4, c2, c1, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x21,0x4c,0xd5]
 
-sysp #4, c8, c1, #0, x0, x1
-// CHECK-INST: sysp #4, c8, c1, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x81,0x4c,0xd5]
+sysp #7, c2, c0, #0, x0, x1
+// CHECK-INST: sysp #7, c2, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x20,0x4f,0xd5]
 
-sysp #0, c8, c0, #0, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x80,0x48,0xd5]
+sysp #0, c0, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c0, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x00,0x48,0xd5]
 
-sysp #0, c8, c0, #1, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #1, x0, x1
-// CHECK-ENCODING: encoding: [0x20,0x80,0x48,0xd5]
+sysp #0, c15, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c15, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0xf0,0x48,0xd5]
 
-sysp #0, c8, c4, #0, x0, x1
-// CHECK-INST: sysp #0, c8, c4, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x84,0x48,0xd5]
+sysp #0, c2, c15, #0, x0, x1
+// CHECK-INST: sysp #0, c2, c15, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x2f,0x48,0xd5]
 
-sysp #0, c8, c0, #3, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #3, x0, x1
-// CHECK-ENCODING: encoding: [0x60,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #6, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #6, x0, x1
-// CHECK-ENCODING: encoding: [0xc0,0x80,0x48,0xd5]
+sysp #0, c2, c0, #1, x0, x1
+// CHECK-INST: sysp #0, c2, c0, #1, x0, x1
+// CHECK-ENCODING: encoding: [0x20,0x20,0x48,0xd5]
 
-sysp #4, c8, c0, #0, x0, x1
-// CHECK-INST: sysp #4, c8, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x80,0x4c,0xd5]
+sysp #0, c7, c4, #0, x0, x1
+// CHECK-INST: sysp #0, c7, c4, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x74,0x48,0xd5]
 
-sysp #4, c8, c0, #3, x0, x1
-// CHECK-INST: sysp #4, c8, c0, #3, x0, x1
-// CHECK-ENCODING: encoding: [0x60,0x80,0x4c,0xd5]
+sysp #0, c13, c0, #3, x0, x1
+// CHECK-INST: sysp #0, c13, c0, #3, x0, x1
+// CHECK-ENCODING: encoding: [0x60,0xd0,0x48,0xd5]
 
-sysp #4, c8, c1, #0, x0, x1
-// CHECK-INST: sysp #4, c8, c1, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x81,0x4c,0xd5]
+sysp #0, c13, c0, #6, x0, x1
+// CHECK-INST: sysp #0, c13, c0, #6, x0, x1
+// CHECK-ENCODING: encoding: [0xc0,0xd0,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x0, x1
-// CHECK-INST: sysp #0, c8, c0, #0, x0, x1
-// CHECK-ENCODING: encoding: [0x00,0x80,0x48,0xd5]
+sysp #4, c2, c0, #0, x0, x1
+// CHECK-INST: sysp #4, c2, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x20,0x4c,0xd5]
 
-sysp #0, c8, c0, #0, x2, x3
-// CHECK-INST: sysp #0, c8, c0, #0, x2, x3
-// CHECK-ENCODING: encoding: [0x02,0x80,0x48,0xd5]
+sysp #4, c2, c0, #1, x0, x1
+// CHECK-INST: sysp #4, c2, c0, #1, x0, x1
+// CHECK-ENCODING: encoding: [0x20,0x20,0x4c,0xd5]
 
-sysp #0, c8, c0, #0, x4, x5
-// CHECK-INST: sysp #0, c8, c0, #0, x4, x5
-// CHECK-ENCODING: encoding: [0x04,0x80,0x48,0xd5]
+sysp #4, c2, c1, #0, x0, x1
+// CHECK-INST: sysp #4, c2, c1, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x21,0x4c,0xd5]
 
-sysp #0, c8, c0, #0, x6, x7
-// CHECK-INST: sysp #0, c8, c0, #0, x6, x7
-// CHECK-ENCODING: encoding: [0x06,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x0, x1
+// CHECK-INST: sysp #0, c2, c0, #0, x0, x1
+// CHECK-ENCODING: encoding: [0x00,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x8, x9
-// CHECK-INST: sysp #0, c8, c0, #0, x8, x9
-// CHECK-ENCODING: encoding: [0x08,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x2, x3
+// CHECK-INST: sysp #0, c2, c0, #0, x2, x3
+// CHECK-ENCODING: encoding: [0x02,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x10, x11
-// CHECK-INST: sysp #0, c8, c0, #0, x10, x11
-// CHECK-ENCODING: encoding: [0x0a,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x4, x5
+// CHECK-INST: sysp #0, c2, c0, #0, x4, x5
+// CHECK-ENCODING: encoding: [0x04,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x12, x13
-// CHECK-INST: sysp #0, c8, c0, #0, x12, x13
-// CHECK-ENCODING: encoding: [0x0c,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x6, x7
+// CHECK-INST: sysp #0, c2, c0, #0, x6, x7
+// CHECK-ENCODING: encoding: [0x06,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x14, x15
-// CHECK-INST: sysp #0, c8, c0, #0, x14, x15
-// CHECK-ENCODING: encoding: [0x0e,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x8, x9
+// CHECK-INST: sysp #0, c2, c0, #0, x8, x9
+// CHECK-ENCODING: encoding: [0x08,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x16, x17
-// CHECK-INST: sysp #0, c8, c0, #0, x16, x17
-// CHECK-ENCODING: encoding: [0x10,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x10, x11
+// CHECK-INST: sysp #0, c2, c0, #0, x10, x11
+// CHECK-ENCODING: encoding: [0x0a,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x18, x19
-// CHECK-INST: sysp #0, c8, c0, #0, x18, x19
-// CHECK-ENCODING: encoding: [0x12,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x12, x13
+// CHECK-INST: sysp #0, c2, c0, #0, x12, x13
+// CHECK-ENCODING: encoding: [0x0c,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x20, x21
-// CHECK-INST: sysp #0, c8, c0, #0, x20, x21
-// CHECK-ENCODING: encoding: [0x14,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x14, x15
+// CHECK-INST: sysp #0, c2, c0, #0, x14, x15
+// CHECK-ENCODING: encoding: [0x0e,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x22, x23
-// CHECK-INST: sysp #0, c8, c0, #0, x22, x23
-// CHECK-ENCODING: encoding: [0x16,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x16, x17
+// CHECK-INST: sysp #0, c2, c0, #0, x16, x17
+// CHECK-ENCODING: encoding: [0x10,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x24, x25
-// CHECK-INST: sysp #0, c8, c0, #0, x24, x25
-// CHECK-ENCODING: encoding: [0x18,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x18, x19
+// CHECK-INST: sysp #0, c2, c0, #0, x18, x19
+// CHECK-ENCODING: encoding: [0x12,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x26, x27
-// CHECK-INST: sysp #0, c8, c0, #0, x26, x27
-// CHECK-ENCODING: encoding: [0x1a,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x20, x21
+// CHECK-INST: sysp #0, c2, c0, #0, x20, x21
+// CHECK-ENCODING: encoding: [0x14,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x28, x29
-// CHECK-INST: sysp #0, c8, c0, #0, x28, x29
-// CHECK-ENCODING: encoding: [0x1c,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x22, x23
+// CHECK-INST: sysp #0, c2, c0, #0, x22, x23
+// CHECK-ENCODING: encoding: [0x16,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x30, x31
-// CHECK-INST: sysp #0, c8, c0, #0, x30, xzr
-// CHECK-ENCODING: encoding: [0x1e,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x24, x25
+// CHECK-INST: sysp #0, c2, c0, #0, x24, x25
+// CHECK-ENCODING: encoding: [0x18,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x31, x31
-// CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x26, x27
+// CHECK-INST: sysp #0, c2, c0, #0, x26, x27
+// CHECK-ENCODING: encoding: [0x1a,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, xzr, xzr
-// CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x28, x29
+// CHECK-INST: sysp #0, c2, c0, #0, x28, x29
+// CHECK-ENCODING: encoding: [0x1c,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, x31, xzr
-// CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x30, x31
+// CHECK-INST: sysp #0, c2, c0, #0, x30, xzr
+// CHECK-ENCODING: encoding: [0x1e,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0, xzr, x31
-// CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, x31, x31
+// CHECK-INST: sysp #0, c2, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
 
-sysp #0, c8, c0, #0
-// CHECK-INST: sysp #0, c8, c0, #0
-// CHECK-ENCODING: encoding: [0x1f,0x80,0x48,0xd5]
+sysp #0, c2, c0, #0, xzr, xzr
+// CHECK-INST: sysp #0, c2, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+
+sysp #0, c2, c0, #0, x31, xzr
+// CHECK-INST: sysp #0, c2, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+
+sysp #0, c2, c0, #0, xzr, x31
+// CHECK-INST: sysp #0, c2, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]
+
+sysp #0, c2, c0, #0
+// CHECK-INST: sysp #0, c2, c0, #0
+// CHECK-ENCODING: encoding: [0x1f,0x20,0x48,0xd5]



More information about the llvm-commits mailing list