[llvm] [RISCV] Correct disassembly of cm.push/pop for RVE. (PR #133816)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 31 16:00:32 PDT 2025


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/133816

We shouldn't disassemble any encoding that refers to registers x16-x31 with RV32E.

>From 1579880810ae0b99fc195e0d37716b4f48c39c0a Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 31 Mar 2025 15:19:47 -0700
Subject: [PATCH] [RISCV] Correct disassembly of cm.push/pop for RVE.

We shouldn't disassemble any encoding that refers to registers
x16-x31 with RV32E.
---
 .../RISCV/Disassembler/RISCVDisassembler.cpp  | 14 +++++++------
 llvm/test/MC/RISCV/rv32e-xqccmp-invalid.s     | 21 +++++++++++++++++++
 llvm/test/MC/RISCV/rv32e-zcmp-invalid.s       | 18 ++++++++++++++++
 llvm/test/MC/RISCV/rv64e-xqccmp-invalid.s     | 21 +++++++++++++++++++
 llvm/test/MC/RISCV/rv64e-zcmp-invalid.s       | 18 ++++++++++++++++
 5 files changed, 86 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/MC/RISCV/rv32e-xqccmp-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv32e-zcmp-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv64e-xqccmp-invalid.s
 create mode 100644 llvm/test/MC/RISCV/rv64e-zcmp-invalid.s

diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index b22a4a7246c23..d8fa12391692d 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -505,10 +505,10 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
                                         const MCDisassembler *Decoder);
 
 static DecodeStatus decodeZcmpRlist(MCInst &Inst, uint32_t Imm,
-                                    uint64_t Address, const void *Decoder);
+                                    uint64_t Address, const MCDisassembler *Decoder);
 
 static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
-                                        uint64_t Address, const void *Decoder);
+                                        uint64_t Address, const MCDisassembler *Decoder);
 
 static DecodeStatus decodeZcmpSpimm(MCInst &Inst, uint32_t Imm,
                                     uint64_t Address, const void *Decoder);
@@ -618,16 +618,18 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
 }
 
 static DecodeStatus decodeZcmpRlist(MCInst &Inst, uint32_t Imm,
-                                    uint64_t Address, const void *Decoder) {
-  if (Imm < RISCVZC::RA)
+                                    uint64_t Address, const MCDisassembler *Decoder) {
+  bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureStdExtE);
+  if (Imm < RISCVZC::RA || (IsRVE && Imm >= RISCVZC::RA_S0_S2))
     return MCDisassembler::Fail;
   Inst.addOperand(MCOperand::createImm(Imm));
   return MCDisassembler::Success;
 }
 
 static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
-                                        uint64_t Address, const void *Decoder) {
-  if (Imm < RISCVZC::RA_S0)
+                                        uint64_t Address, const MCDisassembler *Decoder) {
+  bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureStdExtE);
+  if (Imm < RISCVZC::RA_S0 || (IsRVE && Imm >= RISCVZC::RA_S0_S2))
     return MCDisassembler::Fail;
   Inst.addOperand(MCOperand::createImm(Imm));
   return MCDisassembler::Success;
diff --git a/llvm/test/MC/RISCV/rv32e-xqccmp-invalid.s b/llvm/test/MC/RISCV/rv32e-xqccmp-invalid.s
new file mode 100644
index 0000000000000..6c3ef3000e77e
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32e-xqccmp-invalid.s
@@ -0,0 +1,21 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+e,+experimental-xqccmp < %s 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+experimental-xqccmp < %s \
+# RUN:     | llvm-objdump --mattr=+e,+experimental-xqccmp -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-DIS %s
+
+# Perform a simple check that registers x16-x31 (and the equivalent ABI names)
+# are rejected for RV32E, when both assembling and disassembling.
+
+
+# CHECK-DIS: b872 <unknown>
+# CHECK: :[[@LINE+1]]:19: error: invalid register
+qc.cm.push {ra,s0-s2}, -16
+# CHECK-DIS: be72 <unknown>
+# CHECK: :[[@LINE+1]]:21: error: invalid register
+qc.cm.popret {ra,s0-s2}, 16
+# CHECK-DIS: ba72 <unknown>
+# CHECK: :[[@LINE+1]]:21: error: register list must end with '}'
+qc.cm.pop {x1, x8-x9, x18}, 16
+# CHECK-DIS: b972 <unknown>
+# CHECK: :[[@LINE+1]]:24: error: register list must end with '}'
+qc.cm.pushfp {x1, x8-x9, x18}, -16
diff --git a/llvm/test/MC/RISCV/rv32e-zcmp-invalid.s b/llvm/test/MC/RISCV/rv32e-zcmp-invalid.s
new file mode 100644
index 0000000000000..eaf6b350c2341
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32e-zcmp-invalid.s
@@ -0,0 +1,18 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+e,+zcmp < %s 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zcmp < %s \
+# RUN:     | llvm-objdump --mattr=+e,+zcmp -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-DIS %s
+
+# Perform a simple check that registers x16-x31 (and the equivalent ABI names)
+# are rejected for RV32E, when both assembling and disassembling.
+
+
+# CHECK-DIS: b872 <unknown>
+# CHECK: :[[@LINE+1]]:16: error: invalid register
+cm.push {ra,s0-s2}, -16
+# CHECK-DIS: be72 <unknown>
+# CHECK: :[[@LINE+1]]:18: error: invalid register
+cm.popret {ra,s0-s2}, 16
+# CHECK-DIS: ba72 <unknown>
+# CHECK: :[[@LINE+1]]:18: error: register list must end with '}'
+cm.pop {x1, x8-x9, x18}, 16
diff --git a/llvm/test/MC/RISCV/rv64e-xqccmp-invalid.s b/llvm/test/MC/RISCV/rv64e-xqccmp-invalid.s
new file mode 100644
index 0000000000000..f34ce83448070
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64e-xqccmp-invalid.s
@@ -0,0 +1,21 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+e,+experimental-xqccmp < %s 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+experimental-xqccmp < %s \
+# RUN:     | llvm-objdump --mattr=+e,+experimental-xqccmp -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-DIS %s
+
+# Perform a simple check that registers x16-x31 (and the equivalent ABI names)
+# are rejected for RV64E, when both assembling and disassembling.
+
+
+# CHECK-DIS: b872 <unknown>
+# CHECK: :[[@LINE+1]]:19: error: invalid register
+qc.cm.push {ra,s0-s2}, -32
+# CHECK-DIS: be72 <unknown>
+# CHECK: :[[@LINE+1]]:21: error: invalid register
+qc.cm.popret {ra,s0-s2}, 32
+# CHECK-DIS: ba72 <unknown>
+# CHECK: :[[@LINE+1]]:21: error: register list must end with '}'
+qc.cm.pop {x1, x8-x9, x18}, 32
+# CHECK-DIS: b972 <unknown>
+# CHECK: :[[@LINE+1]]:24: error: register list must end with '}'
+qc.cm.pushfp {x1, x8-x9, x18}, -32
diff --git a/llvm/test/MC/RISCV/rv64e-zcmp-invalid.s b/llvm/test/MC/RISCV/rv64e-zcmp-invalid.s
new file mode 100644
index 0000000000000..e99721d96a17c
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64e-zcmp-invalid.s
@@ -0,0 +1,18 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+e,+zcmp < %s 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zcmp < %s \
+# RUN:     | llvm-objdump --mattr=+e,+zcmp -M no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-DIS %s
+
+# Perform a simple check that registers x16-x31 (and the equivalent ABI names)
+# are rejected for RV64E, when both assembling and disassembling.
+
+
+# CHECK-DIS: b872 <unknown>
+# CHECK: :[[@LINE+1]]:16: error: invalid register
+cm.push {ra,s0-s2}, -32
+# CHECK-DIS: be72 <unknown>
+# CHECK: :[[@LINE+1]]:18: error: invalid register
+cm.popret {ra,s0-s2}, 32
+# CHECK-DIS: ba72 <unknown>
+# CHECK: :[[@LINE+1]]:18: error: register list must end with '}'
+cm.pop {x1, x8-x9, x18}, 32



More information about the llvm-commits mailing list