This series adds support for the RISC-V Packed SIMD (P) extension for
RV32 and RV64.
The P extension defines packed-SIMD fixed-point operations intended for
DSP workloads such as multimedia and signal processing. These
instructions operate on packed subword elements in general-purpose
registers, with register-pair forms for wider operands on RV32.
The implementation targets the V0.21 development draft of the RISC-V P
extension specification:
https://github.com/riscv/riscv-p-spec
The local riscv-p-spec reference checkout is at commit:
71b78d2c8d1d41cc01a036d75dc001920b8ac22e
P support is enabled with the experimental x-p CPU property. The series
includes instruction decoding and translation, helpers, extension-state
handling, and the specification-defined control of vxsat. The focus
remains functional correctness and instruction coverage; performance
optimization is left for future work.
This revision adds in-tree TCG tests for RV32 and RV64 and addresses the
review feedback on helper reuse, register overlap, shift semantics, and
code readability. It also fixes additional issues found while testing,
including zero register-pair handling and RV64 SHLR rounding.
Thanks to Daniel Henrique Barboza, Nutty Liu, Chao Liu, and Max Chou for
their reviews and suggestions.
Changes in v3:
- Add descriptive commit messages explaining the purpose and behavior
of the patches, and document helper macro definitions, including
their interfaces and arithmetic semantics.
- Add RV32 and RV64 assembly tests under tests/tcg/riscv, with shared
test macros and integration into the TCG test Makefiles. Cover
arithmetic, shifts, multiplication, narrowing, saturation, register
overlap, and zero register-pair operands. The tests are freestanding
Linux-user programs and do not require a target libc. Set PSIMD_CC
to a P-capable Clang to build them; the assembler options use
rv32gp0p21 and rv64gp0p21. Enable previously disabled tests using the
P v0.21 mnemonics and update signed saturation immediate operands.
- Correct register-controlled packed byte and halfword shifts to use
the low five bits of rs2. Share the signed saturating/rounding shift
implementation between scalar and packed forms: psshar_hs,
psshar_ws, and sshar are all generated by GEN_PSIMD_VAR_SSHAR.
Return zero for oversized SSHAR/SHAR right shifts, and widen
rounding arithmetic before adding the rounding bit.
- Clamp unsigned rounding right shifts to the element width so that
the source MSB still participates in rounding for oversized shifts.
Apply this to PSSHLR/SSHLR and RV64 SHLR. Use a wider intermediate
for SHLR to preserve the carry when rounding UINT64_MAX right by
one bit, and add regression tests for these cases.
- Fix RV32 register-pair operations when the destination overlaps
the scalar source by completing both results before writeback.
Treat a zero register-pair selector as {x0, x0}, suppress both
destination writes for a zero pair, and preserve vxsat side effects.
Use tcg_gen_movi_i64() to initialize a zero source in narrowing
translations, with a dedicated regression test.
- Avoid undefined behavior in helper arithmetic by using unsigned
operations where wraparound is intended and wider intermediates
where needed. Handle oversized left shifts explicitly and handle
zero shifts in SLX/SRX without shifting by the operand width.
- Correct the RV32 REV encoding, reject unavailable translations
instead of accepting them without an operation, and fix lane
selection in PMQWACC.H and PMQRWACC.H.
- Reuse qemu/bitops.h extract64() for lane extraction, correct
misleading helper comments, and align macro continuation characters.
Testing:
The P extension TCG tests were built with LLVM/Clang 24.0.0git
(/opt/llvm/bin/clang), llvm-project commit:
96295a1412f9afbee9d4a3c2701e83f5a529a9cc
Built qemu-riscv32, qemu-riscv64, qemu-system-riscv32, and
qemu-system-riscv64 successfully. Both P extension TCG suites pass
with the new regression cases:
make -C build/tests/tcg/riscv32-linux-user \
PSIMD_CC=/opt/llvm/bin/clang run-psimd-rv32
make -C build/tests/tcg/riscv64-linux-user \
PSIMD_CC=/opt/llvm/bin/clang run-psimd-rv64
The test targets enable x-p, zmmul, zba, and zbb on the corresponding
rv32 or rv64 CPU. The P-aware compiler path is configurable through
PSIMD_CC.
Changes in v2:
- Refactored translation and helper code using macros for common
implementation patterns.
- Consolidated P extension prerequisite checks in
riscv_cpu_validate_p().
- Removed the Zbkb dependency to match the specification.
- Added the specification-defined vxsat control mechanism.
Previous versions:
v2: https://lists.nongnu.org/archive/html/qemu-riscv/2026-07/msg00697.html
v1: https://lists.nongnu.org/archive/html/qemu-riscv/2026-04/msg00301.html
Feedback on the implementation and tests would be appreciated.
Co-authored-by: Yin Zhang <zhangyin2018@iscas.ac.cn>
Co-authored-by: Dajun Huang <djhuang_1@std.uestc.edu.cn>
Co-authored-by: Zhiyuan Yang <zhiyuan.plct@isrc.iscas.ac.cn>
Molly Chen (19):
target/riscv: Add packed SIMD extension state
target/riscv: Add packed SIMD helper framework
target/riscv: Add packed SIMD arithmetic instructions
target/riscv: Add packed SIMD averaging and rounding instructions
target/riscv: Add packed SIMD absolute, difference, compare and mask
instructions
target/riscv: Add packed SIMD shift instructions
target/riscv: Add packed SIMD exchange instructions
target/riscv: Add packed SIMD horizontal reduction instructions
target/riscv: Add packed SIMD pack, merge and count-leading
instructions
target/riscv: Add packed SIMD pure multiplication instructions
target/riscv: Add packed SIMD multiply-accumulate instructions
target/riscv: Add packed SIMD Q-format multiplication instructions
target/riscv: Add packed SIMD Q-format MAC instructions
target/riscv: Add packed SIMD two-way multiply-add/subtract
instructions
target/riscv: Add packed SIMD four-way multiply-add instructions
target/riscv: Add packed SIMD load-replicate instructions
target/riscv: Add packed SIMD RV32 only instructions
target/riscv: Remove Zbkb dependency from P extension to align with
the spec
tests/tcg/riscv: Add tests for the P extension
target/riscv/cpu.c | 5 +-
target/riscv/cpu.h | 8 +
target/riscv/cpu_bits.h | 2 +
target/riscv/helper.h | 529 +++
target/riscv/insn32.decode | 830 +++++
target/riscv/machine.c | 19 +
target/riscv/tcg/csr.c | 39 +-
target/riscv/tcg/insn_trans/trans_rvb.c.inc | 4 +-
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 1439 ++++++++
target/riscv/tcg/meson.build | 3 +-
target/riscv/tcg/psimd_helper.c | 3536 +++++++++++++++++++
target/riscv/tcg/tcg-cpu.c | 46 +
target/riscv/tcg/translate.c | 6 +
tests/tcg/riscv/psimd-common.S | 1105 ++++++
tests/tcg/riscv/psimd-rv32.S | 1256 +++++++
tests/tcg/riscv/psimd-rv64.S | 578 +++
tests/tcg/riscv/psimd-test-macros.inc | 952 +++++
tests/tcg/riscv32/Makefile.target | 30 +
tests/tcg/riscv64/Makefile.target | 25 +
19 files changed, 10406 insertions(+), 6 deletions(-)
create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
create mode 100644 target/riscv/tcg/psimd_helper.c
create mode 100644 tests/tcg/riscv/psimd-common.S
create mode 100644 tests/tcg/riscv/psimd-rv32.S
create mode 100644 tests/tcg/riscv/psimd-rv64.S
create mode 100644 tests/tcg/riscv/psimd-test-macros.inc
create mode 100644 tests/tcg/riscv32/Makefile.target
base-commit: b23a62773a7856299cbb3782e64968b6a92c792f
--
2.34.1