* [PATCH v2 01/18] target/riscv: Add packed SIMD extension state
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
@ 2026-07-17 10:06 ` Molly Chen
2026-07-26 19:32 ` Daniel Henrique Barboza
` (2 more replies)
2026-07-17 10:06 ` [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework Molly Chen
` (18 subsequent siblings)
19 siblings, 3 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:06 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel, Yin Zhang, Dajun Huang,
Zhiyuan Yang
Model vxsat with separate Vector/Zve and P-only control paths. When
Zve* is present, vxsat follows mstatus.VS/vsstatus.VS; when P is
implemented without Zve*, stateen0.VXSAT controls access instead.
Record the P-only stateen result in TB flags so cached translations
preserve both instruction legality and the illegal-vs-virtual exception
class.
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>
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/cpu.c | 5 ++--
target/riscv/cpu.h | 8 +++++++
target/riscv/cpu_bits.h | 2 ++
target/riscv/machine.c | 19 +++++++++++++++
target/riscv/tcg/csr.c | 39 +++++++++++++++++++++++++++++--
target/riscv/tcg/tcg-cpu.c | 48 ++++++++++++++++++++++++++++++++++++++
6 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5a82e6563bf..c9e6c83a491 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -46,7 +46,7 @@
/* RISC-V CPU definitions */
static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
- RVC, RVS, RVU, RVH, RVG, RVB, 0};
+ RVC, RVS, RVU, RVH, RVG, RVB, RVP, 0};
#define RISCV_CPU_MVENDORID 0
#define RISCV_CPU_MIMPID 0
/*
@@ -1489,7 +1489,8 @@ static const MISAExtInfo misa_ext_info_arr[] = {
MISA_EXT_INFO(RVH, "h", "Hypervisor"),
MISA_EXT_INFO(RVV, "v", "Vector operations"),
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
- MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)"),
+ MISA_EXT_INFO(RVP, "x-p", "Packed-SIMD instructions")
};
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c9dfa7daff2..75cfb16d846 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -70,6 +70,7 @@ typedef struct CPUArchState CPURISCVState;
#define RVG RV('G')
#define RVB RV('B')
#define RVX RV('X')
+#define RVP RV('P')
extern const uint32_t misa_bits[];
const char *riscv_get_misa_ext_name(uint32_t bit);
@@ -742,6 +743,13 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32)
FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1)
FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1)
+FIELD(EXT_TB_FLAGS, P_VXSAT_EXCP, 34, 2)
+
+enum {
+ P_VXSAT_EXCP_NONE,
+ P_VXSAT_EXCP_ILLEGAL,
+ P_VXSAT_EXCP_VIRTUAL,
+};
#ifdef TARGET_RISCV32
#define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 3f146a43fe4..fa7bf60f4fc 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -355,6 +355,8 @@
#define SMSTATEEN0_CS (1ULL << 0)
#define SMSTATEEN0_FCSR (1ULL << 1)
#define SMSTATEEN0_JVT (1ULL << 2)
+/* Packed-SIMD draft: enable access to vxsat when misa.V = 0. */
+#define SMSTATEEN0_VXSAT (1ULL << 3)
#define SMSTATEEN0_CTR (1ULL << 54)
#define SMSTATEEN0_P1P13 (1ULL << 56)
#define SMSTATEEN0_HSCONTXT (1ULL << 57)
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 0ab613a2980..a9cd7e4c1cc 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -158,6 +158,24 @@ static const VMStateDescription vmstate_vector = {
}
};
+static bool p_vxsat_needed(void *opaque)
+{
+ RISCVCPU *cpu = opaque;
+
+ return riscv_has_ext(&cpu->env, RVP) && !cpu->cfg.ext_zve32x;
+}
+
+static const VMStateDescription vmstate_p_vxsat = {
+ .name = "cpu/p-vxsat",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = p_vxsat_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT8(env.vxsat, RISCVCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool pointermasking_needed(void *opaque)
{
return false;
@@ -518,6 +536,7 @@ const VMStateDescription vmstate_riscv_cpu = {
&vmstate_pmp,
&vmstate_hyper,
&vmstate_vector,
+ &vmstate_p_vxsat,
&vmstate_pointermasking,
&vmstate_rv128,
#ifdef CONFIG_KVM
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index 36f2004bc56..e809997f52e 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -109,6 +109,24 @@ static RISCVException vs(CPURISCVState *env, int csrno)
return RISCV_EXCP_ILLEGAL_INST;
}
+/* vxsat is also architectural state when P is implemented without Zve*. */
+static RISCVException vxsat(CPURISCVState *env, int csrno)
+{
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
+ return vs(env, csrno);
+ }
+
+ if (riscv_has_ext(env, RVP)) {
+#if !defined(CONFIG_USER_ONLY)
+ return smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
+#else
+ return RISCV_EXCP_NONE;
+#endif
+ }
+
+ return RISCV_EXCP_ILLEGAL_INST;
+}
+
static RISCVException ctr(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
@@ -1013,7 +1031,12 @@ static RISCVException write_vxsat(CPURISCVState *env, int csrno,
target_ulong val, uintptr_t ra)
{
#if !defined(CONFIG_USER_ONLY)
- env->mstatus |= MSTATUS_VS;
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
+ env->mstatus |= MSTATUS_VS;
+ if (env->virt_enabled) {
+ env->mstatus_hs |= MSTATUS_VS;
+ }
+ }
#endif
env->vxsat = val & BIT(0);
return RISCV_EXCP_NONE;
@@ -3494,6 +3517,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
target_ulong new_val, uintptr_t ra)
{
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ wr_mask |= SMSTATEEN0_VXSAT;
+ }
if (!riscv_has_ext(env, RVF)) {
wr_mask |= SMSTATEEN0_FCSR;
}
@@ -3617,6 +3644,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
{
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ wr_mask |= SMSTATEEN0_VXSAT;
+ }
+
if (!riscv_has_ext(env, RVF)) {
wr_mask |= SMSTATEEN0_FCSR;
}
@@ -3746,6 +3777,10 @@ static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
{
uint64_t wr_mask = 0;
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ wr_mask |= SMSTATEEN0_VXSAT;
+ }
+
if (!riscv_has_ext(env, RVF)) {
wr_mask |= SMSTATEEN0_FCSR;
}
@@ -5916,7 +5951,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr },
/* Vector CSRs */
[CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart },
- [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat },
+ [CSR_VXSAT] = { "vxsat", vxsat, read_vxsat, write_vxsat },
[CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm },
[CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr },
[CSR_VL] = { "vl", vs, read_vl },
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 4af5cd9c731..1665583accf 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -160,6 +160,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
fs = EXT_STATUS_DIRTY;
vs = EXT_STATUS_DIRTY;
#else
+ RISCVException p_vxsat_excp;
+
flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
flags |= riscv_env_mmu_index(env, 0);
@@ -182,6 +184,23 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
}
+ /*
+ * Without Zve*, all P instructions in the OP-32 and OP-IMM-32
+ * spaces are controlled by stateen0.VXSAT. Preserve the exception
+ * class in the TB flags so translated code can distinguish an illegal
+ * instruction from a virtual-instruction exception.
+ */
+ p_vxsat_excp = smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ if (p_vxsat_excp == RISCV_EXCP_VIRT_INSTRUCTION_FAULT) {
+ ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
+ P_VXSAT_EXCP_VIRTUAL);
+ } else if (p_vxsat_excp != RISCV_EXCP_NONE) {
+ ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
+ P_VXSAT_EXCP_ILLEGAL);
+ }
+ }
+
if (cpu->cfg.debug && !icount_enabled()) {
flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
}
@@ -530,6 +549,28 @@ static void riscv_cpu_validate_b(RISCVCPU *cpu)
}
}
+static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
+{
+ CPURISCVState *env = &cpu->env;
+
+ if (!riscv_has_ext(env, RVP)) {
+ return;
+ }
+
+ if (riscv_cpu_mxl(env) != MXL_RV32 &&
+ riscv_cpu_mxl(env) != MXL_RV64) {
+ error_setg(errp, "P extension requires RV32 or RV64");
+ return;
+ }
+
+ if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
+ cpu->cfg.ext_zbkb)) {
+ error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
+ "extensions");
+ return;
+ }
+}
+
/*
* Check consistency between chosen extensions while setting
* cpu->cfg accordingly.
@@ -612,6 +653,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
return;
}
+ riscv_cpu_validate_p(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
@@ -1414,6 +1461,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
MISA_CFG(RVV, false),
MISA_CFG(RVG, false),
MISA_CFG(RVB, false),
+ MISA_CFG(RVP, false),
};
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* Re: [PATCH v2 01/18] target/riscv: Add packed SIMD extension state
2026-07-17 10:06 ` [PATCH v2 01/18] target/riscv: Add packed SIMD extension state Molly Chen
@ 2026-07-26 19:32 ` Daniel Henrique Barboza
2026-07-27 6:13 ` Nutty.Liu
2026-07-29 8:43 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Daniel Henrique Barboza @ 2026-07-26 19:32 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel, Yin Zhang, Dajun Huang, Zhiyuan Yang
On 7/17/2026 7:06 AM, Molly Chen wrote:
> Model vxsat with separate Vector/Zve and P-only control paths. When
> Zve* is present, vxsat follows mstatus.VS/vsstatus.VS; when P is
> implemented without Zve*, stateen0.VXSAT controls access instead.
>
> Record the P-only stateen result in TB flags so cached translations
> preserve both instruction legality and the illegal-vs-virtual exception
> class.
>
> 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>
>
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> target/riscv/cpu.c | 5 ++--
> target/riscv/cpu.h | 8 +++++++
> target/riscv/cpu_bits.h | 2 ++
> target/riscv/machine.c | 19 +++++++++++++++
> target/riscv/tcg/csr.c | 39 +++++++++++++++++++++++++++++--
> target/riscv/tcg/tcg-cpu.c | 48 ++++++++++++++++++++++++++++++++++++++
> 6 files changed, 117 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 5a82e6563bf..c9e6c83a491 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -46,7 +46,7 @@
> /* RISC-V CPU definitions */
> static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
> const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
> - RVC, RVS, RVU, RVH, RVG, RVB, 0};
> + RVC, RVS, RVU, RVH, RVG, RVB, RVP, 0};
> #define RISCV_CPU_MVENDORID 0
> #define RISCV_CPU_MIMPID 0
> /*
> @@ -1489,7 +1489,8 @@ static const MISAExtInfo misa_ext_info_arr[] = {
> MISA_EXT_INFO(RVH, "h", "Hypervisor"),
> MISA_EXT_INFO(RVV, "v", "Vector operations"),
> MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
> - MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
> + MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)"),
> + MISA_EXT_INFO(RVP, "x-p", "Packed-SIMD instructions")
> };
>
> static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index c9dfa7daff2..75cfb16d846 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -70,6 +70,7 @@ typedef struct CPUArchState CPURISCVState;
> #define RVG RV('G')
> #define RVB RV('B')
> #define RVX RV('X')
> +#define RVP RV('P')
>
> extern const uint32_t misa_bits[];
> const char *riscv_get_misa_ext_name(uint32_t bit);
> @@ -742,6 +743,13 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
> FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32)
> FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1)
> FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1)
> +FIELD(EXT_TB_FLAGS, P_VXSAT_EXCP, 34, 2)
> +
> +enum {
> + P_VXSAT_EXCP_NONE,
> + P_VXSAT_EXCP_ILLEGAL,
> + P_VXSAT_EXCP_VIRTUAL,
> +};
>
> #ifdef TARGET_RISCV32
> #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 3f146a43fe4..fa7bf60f4fc 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -355,6 +355,8 @@
> #define SMSTATEEN0_CS (1ULL << 0)
> #define SMSTATEEN0_FCSR (1ULL << 1)
> #define SMSTATEEN0_JVT (1ULL << 2)
> +/* Packed-SIMD draft: enable access to vxsat when misa.V = 0. */
> +#define SMSTATEEN0_VXSAT (1ULL << 3)
> #define SMSTATEEN0_CTR (1ULL << 54)
> #define SMSTATEEN0_P1P13 (1ULL << 56)
> #define SMSTATEEN0_HSCONTXT (1ULL << 57)
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 0ab613a2980..a9cd7e4c1cc 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -158,6 +158,24 @@ static const VMStateDescription vmstate_vector = {
> }
> };
>
> +static bool p_vxsat_needed(void *opaque)
> +{
> + RISCVCPU *cpu = opaque;
> +
> + return riscv_has_ext(&cpu->env, RVP) && !cpu->cfg.ext_zve32x;
> +}
> +
> +static const VMStateDescription vmstate_p_vxsat = {
> + .name = "cpu/p-vxsat",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = p_vxsat_needed,
> + .fields = (const VMStateField[]) {
> + VMSTATE_UINT8(env.vxsat, RISCVCPU),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static bool pointermasking_needed(void *opaque)
> {
> return false;
> @@ -518,6 +536,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> &vmstate_pmp,
> &vmstate_hyper,
> &vmstate_vector,
> + &vmstate_p_vxsat,
> &vmstate_pointermasking,
> &vmstate_rv128,
> #ifdef CONFIG_KVM
> diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
> index 36f2004bc56..e809997f52e 100644
> --- a/target/riscv/tcg/csr.c
> +++ b/target/riscv/tcg/csr.c
> @@ -109,6 +109,24 @@ static RISCVException vs(CPURISCVState *env, int csrno)
> return RISCV_EXCP_ILLEGAL_INST;
> }
>
> +/* vxsat is also architectural state when P is implemented without Zve*. */
> +static RISCVException vxsat(CPURISCVState *env, int csrno)
> +{
> + if (riscv_cpu_cfg(env)->ext_zve32x) {
> + return vs(env, csrno);
> + }
> +
> + if (riscv_has_ext(env, RVP)) {
> +#if !defined(CONFIG_USER_ONLY)
> + return smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
> +#else
> + return RISCV_EXCP_NONE;
> +#endif
> + }
> +
> + return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> static RISCVException ctr(CPURISCVState *env, int csrno)
> {
> #if !defined(CONFIG_USER_ONLY)
> @@ -1013,7 +1031,12 @@ static RISCVException write_vxsat(CPURISCVState *env, int csrno,
> target_ulong val, uintptr_t ra)
> {
> #if !defined(CONFIG_USER_ONLY)
> - env->mstatus |= MSTATUS_VS;
> + if (riscv_cpu_cfg(env)->ext_zve32x) {
> + env->mstatus |= MSTATUS_VS;
> + if (env->virt_enabled) {
> + env->mstatus_hs |= MSTATUS_VS;
> + }
> + }
> #endif
> env->vxsat = val & BIT(0);
> return RISCV_EXCP_NONE;
> @@ -3494,6 +3517,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
> target_ulong new_val, uintptr_t ra)
> {
> uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
> +
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -3617,6 +3644,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
> {
> uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
>
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> +
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -3746,6 +3777,10 @@ static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
> {
> uint64_t wr_mask = 0;
>
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> +
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -5916,7 +5951,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr },
> /* Vector CSRs */
> [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart },
> - [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat },
> + [CSR_VXSAT] = { "vxsat", vxsat, read_vxsat, write_vxsat },
> [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm },
> [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr },
> [CSR_VL] = { "vl", vs, read_vl },
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 4af5cd9c731..1665583accf 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -160,6 +160,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
> fs = EXT_STATUS_DIRTY;
> vs = EXT_STATUS_DIRTY;
> #else
> + RISCVException p_vxsat_excp;
> +
> flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
>
> flags |= riscv_env_mmu_index(env, 0);
> @@ -182,6 +184,23 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
> ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
> }
>
> + /*
> + * Without Zve*, all P instructions in the OP-32 and OP-IMM-32
> + * spaces are controlled by stateen0.VXSAT. Preserve the exception
> + * class in the TB flags so translated code can distinguish an illegal
> + * instruction from a virtual-instruction exception.
> + */
> + p_vxsat_excp = smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + if (p_vxsat_excp == RISCV_EXCP_VIRT_INSTRUCTION_FAULT) {
> + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
> + P_VXSAT_EXCP_VIRTUAL);
> + } else if (p_vxsat_excp != RISCV_EXCP_NONE) {
> + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
> + P_VXSAT_EXCP_ILLEGAL);
> + }
> + }
> +
> if (cpu->cfg.debug && !icount_enabled()) {
> flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
> }
> @@ -530,6 +549,28 @@ static void riscv_cpu_validate_b(RISCVCPU *cpu)
> }
> }
>
> +static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
> +{
> + CPURISCVState *env = &cpu->env;
> +
> + if (!riscv_has_ext(env, RVP)) {
> + return;
> + }
> +
> + if (riscv_cpu_mxl(env) != MXL_RV32 &&
> + riscv_cpu_mxl(env) != MXL_RV64) {
> + error_setg(errp, "P extension requires RV32 or RV64");
> + return;
> + }
> +
> + if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
> + cpu->cfg.ext_zbkb)) {
> + error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
> + "extensions");
> + return;
> + }
> +}
> +
> /*
> * Check consistency between chosen extensions while setting
> * cpu->cfg accordingly.
> @@ -612,6 +653,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
> return;
> }
>
> + riscv_cpu_validate_p(cpu, &local_err);
> + if (local_err != NULL) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
> if (local_err != NULL) {
> error_propagate(errp, local_err);
> @@ -1414,6 +1461,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
> MISA_CFG(RVV, false),
> MISA_CFG(RVG, false),
> MISA_CFG(RVB, false),
> + MISA_CFG(RVP, false),
> };
>
> /*
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 01/18] target/riscv: Add packed SIMD extension state
2026-07-17 10:06 ` [PATCH v2 01/18] target/riscv: Add packed SIMD extension state Molly Chen
2026-07-26 19:32 ` Daniel Henrique Barboza
@ 2026-07-27 6:13 ` Nutty.Liu
2026-07-29 8:43 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Nutty.Liu @ 2026-07-27 6:13 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, daniel.barboza,
zhiwei_liu, chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel, Yin Zhang, Dajun Huang, Zhiyuan Yang
On 7/17/2026 6:06 PM, Molly Chen wrote:
> Model vxsat with separate Vector/Zve and P-only control paths. When
> Zve* is present, vxsat follows mstatus.VS/vsstatus.VS; when P is
> implemented without Zve*, stateen0.VXSAT controls access instead.
>
> Record the P-only stateen result in TB flags so cached translations
> preserve both instruction legality and the illegal-vs-virtual exception
> class.
>
> 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>
>
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> ---
> target/riscv/cpu.c | 5 ++--
> target/riscv/cpu.h | 8 +++++++
> target/riscv/cpu_bits.h | 2 ++
> target/riscv/machine.c | 19 +++++++++++++++
> target/riscv/tcg/csr.c | 39 +++++++++++++++++++++++++++++--
> target/riscv/tcg/tcg-cpu.c | 48 ++++++++++++++++++++++++++++++++++++++
> 6 files changed, 117 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 5a82e6563bf..c9e6c83a491 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -46,7 +46,7 @@
> /* RISC-V CPU definitions */
> static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
> const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
> - RVC, RVS, RVU, RVH, RVG, RVB, 0};
> + RVC, RVS, RVU, RVH, RVG, RVB, RVP, 0};
> #define RISCV_CPU_MVENDORID 0
> #define RISCV_CPU_MIMPID 0
> /*
> @@ -1489,7 +1489,8 @@ static const MISAExtInfo misa_ext_info_arr[] = {
> MISA_EXT_INFO(RVH, "h", "Hypervisor"),
> MISA_EXT_INFO(RVV, "v", "Vector operations"),
> MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
> - MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
> + MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)"),
> + MISA_EXT_INFO(RVP, "x-p", "Packed-SIMD instructions")
> };
>
> static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index c9dfa7daff2..75cfb16d846 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -70,6 +70,7 @@ typedef struct CPUArchState CPURISCVState;
> #define RVG RV('G')
> #define RVB RV('B')
> #define RVX RV('X')
> +#define RVP RV('P')
>
> extern const uint32_t misa_bits[];
> const char *riscv_get_misa_ext_name(uint32_t bit);
> @@ -742,6 +743,13 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
> FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32)
> FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1)
> FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1)
> +FIELD(EXT_TB_FLAGS, P_VXSAT_EXCP, 34, 2)
> +
> +enum {
> + P_VXSAT_EXCP_NONE,
> + P_VXSAT_EXCP_ILLEGAL,
> + P_VXSAT_EXCP_VIRTUAL,
> +};
>
> #ifdef TARGET_RISCV32
> #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 3f146a43fe4..fa7bf60f4fc 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -355,6 +355,8 @@
> #define SMSTATEEN0_CS (1ULL << 0)
> #define SMSTATEEN0_FCSR (1ULL << 1)
> #define SMSTATEEN0_JVT (1ULL << 2)
> +/* Packed-SIMD draft: enable access to vxsat when misa.V = 0. */
> +#define SMSTATEEN0_VXSAT (1ULL << 3)
> #define SMSTATEEN0_CTR (1ULL << 54)
> #define SMSTATEEN0_P1P13 (1ULL << 56)
> #define SMSTATEEN0_HSCONTXT (1ULL << 57)
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 0ab613a2980..a9cd7e4c1cc 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -158,6 +158,24 @@ static const VMStateDescription vmstate_vector = {
> }
> };
>
> +static bool p_vxsat_needed(void *opaque)
> +{
> + RISCVCPU *cpu = opaque;
> +
> + return riscv_has_ext(&cpu->env, RVP) && !cpu->cfg.ext_zve32x;
> +}
> +
> +static const VMStateDescription vmstate_p_vxsat = {
> + .name = "cpu/p-vxsat",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = p_vxsat_needed,
> + .fields = (const VMStateField[]) {
> + VMSTATE_UINT8(env.vxsat, RISCVCPU),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static bool pointermasking_needed(void *opaque)
> {
> return false;
> @@ -518,6 +536,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> &vmstate_pmp,
> &vmstate_hyper,
> &vmstate_vector,
> + &vmstate_p_vxsat,
> &vmstate_pointermasking,
> &vmstate_rv128,
> #ifdef CONFIG_KVM
> diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
> index 36f2004bc56..e809997f52e 100644
> --- a/target/riscv/tcg/csr.c
> +++ b/target/riscv/tcg/csr.c
> @@ -109,6 +109,24 @@ static RISCVException vs(CPURISCVState *env, int csrno)
> return RISCV_EXCP_ILLEGAL_INST;
> }
>
> +/* vxsat is also architectural state when P is implemented without Zve*. */
> +static RISCVException vxsat(CPURISCVState *env, int csrno)
> +{
> + if (riscv_cpu_cfg(env)->ext_zve32x) {
> + return vs(env, csrno);
> + }
> +
> + if (riscv_has_ext(env, RVP)) {
> +#if !defined(CONFIG_USER_ONLY)
> + return smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
> +#else
> + return RISCV_EXCP_NONE;
> +#endif
> + }
> +
> + return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> static RISCVException ctr(CPURISCVState *env, int csrno)
> {
> #if !defined(CONFIG_USER_ONLY)
> @@ -1013,7 +1031,12 @@ static RISCVException write_vxsat(CPURISCVState *env, int csrno,
> target_ulong val, uintptr_t ra)
> {
> #if !defined(CONFIG_USER_ONLY)
> - env->mstatus |= MSTATUS_VS;
> + if (riscv_cpu_cfg(env)->ext_zve32x) {
> + env->mstatus |= MSTATUS_VS;
> + if (env->virt_enabled) {
> + env->mstatus_hs |= MSTATUS_VS;
> + }
> + }
> #endif
> env->vxsat = val & BIT(0);
> return RISCV_EXCP_NONE;
> @@ -3494,6 +3517,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
> target_ulong new_val, uintptr_t ra)
> {
> uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
> +
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -3617,6 +3644,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
> {
> uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
>
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> +
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -3746,6 +3777,10 @@ static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
> {
> uint64_t wr_mask = 0;
>
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> +
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -5916,7 +5951,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr },
> /* Vector CSRs */
> [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart },
> - [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat },
> + [CSR_VXSAT] = { "vxsat", vxsat, read_vxsat, write_vxsat },
> [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm },
> [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr },
> [CSR_VL] = { "vl", vs, read_vl },
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 4af5cd9c731..1665583accf 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -160,6 +160,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
> fs = EXT_STATUS_DIRTY;
> vs = EXT_STATUS_DIRTY;
> #else
> + RISCVException p_vxsat_excp;
> +
> flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
>
> flags |= riscv_env_mmu_index(env, 0);
> @@ -182,6 +184,23 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
> ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
> }
>
> + /*
> + * Without Zve*, all P instructions in the OP-32 and OP-IMM-32
> + * spaces are controlled by stateen0.VXSAT. Preserve the exception
> + * class in the TB flags so translated code can distinguish an illegal
> + * instruction from a virtual-instruction exception.
> + */
> + p_vxsat_excp = smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + if (p_vxsat_excp == RISCV_EXCP_VIRT_INSTRUCTION_FAULT) {
> + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
> + P_VXSAT_EXCP_VIRTUAL);
> + } else if (p_vxsat_excp != RISCV_EXCP_NONE) {
> + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
> + P_VXSAT_EXCP_ILLEGAL);
> + }
> + }
> +
> if (cpu->cfg.debug && !icount_enabled()) {
> flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
> }
> @@ -530,6 +549,28 @@ static void riscv_cpu_validate_b(RISCVCPU *cpu)
> }
> }
>
> +static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
> +{
> + CPURISCVState *env = &cpu->env;
> +
> + if (!riscv_has_ext(env, RVP)) {
> + return;
> + }
> +
> + if (riscv_cpu_mxl(env) != MXL_RV32 &&
> + riscv_cpu_mxl(env) != MXL_RV64) {
> + error_setg(errp, "P extension requires RV32 or RV64");
> + return;
> + }
> +
> + if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
> + cpu->cfg.ext_zbkb)) {
> + error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
> + "extensions");
> + return;
> + }
> +}
> +
> /*
> * Check consistency between chosen extensions while setting
> * cpu->cfg accordingly.
> @@ -612,6 +653,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
> return;
> }
>
> + riscv_cpu_validate_p(cpu, &local_err);
> + if (local_err != NULL) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
> if (local_err != NULL) {
> error_propagate(errp, local_err);
> @@ -1414,6 +1461,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
> MISA_CFG(RVV, false),
> MISA_CFG(RVG, false),
> MISA_CFG(RVB, false),
> + MISA_CFG(RVP, false),
> };
>
> /*
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 01/18] target/riscv: Add packed SIMD extension state
2026-07-17 10:06 ` [PATCH v2 01/18] target/riscv: Add packed SIMD extension state Molly Chen
2026-07-26 19:32 ` Daniel Henrique Barboza
2026-07-27 6:13 ` Nutty.Liu
@ 2026-07-29 8:43 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Chao Liu @ 2026-07-29 8:43 UTC (permalink / raw)
To: Molly Chen
Cc: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
Chao Liu, qemu-riscv, qemu-devel, Yin Zhang, Dajun Huang,
Zhiyuan Yang
On Fri, Jul 17, 2026 at 10:06:54AM +0800, Molly Chen wrote:
> Model vxsat with separate Vector/Zve and P-only control paths. When
> Zve* is present, vxsat follows mstatus.VS/vsstatus.VS; when P is
> implemented without Zve*, stateen0.VXSAT controls access instead.
>
> Record the P-only stateen result in TB flags so cached translations
> preserve both instruction legality and the illegal-vs-virtual exception
> class.
>
> 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>
>
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Thanks,
Chao
> ---
> target/riscv/cpu.c | 5 ++--
> target/riscv/cpu.h | 8 +++++++
> target/riscv/cpu_bits.h | 2 ++
> target/riscv/machine.c | 19 +++++++++++++++
> target/riscv/tcg/csr.c | 39 +++++++++++++++++++++++++++++--
> target/riscv/tcg/tcg-cpu.c | 48 ++++++++++++++++++++++++++++++++++++++
> 6 files changed, 117 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 5a82e6563bf..c9e6c83a491 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -46,7 +46,7 @@
> /* RISC-V CPU definitions */
> static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
> const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
> - RVC, RVS, RVU, RVH, RVG, RVB, 0};
> + RVC, RVS, RVU, RVH, RVG, RVB, RVP, 0};
> #define RISCV_CPU_MVENDORID 0
> #define RISCV_CPU_MIMPID 0
> /*
> @@ -1489,7 +1489,8 @@ static const MISAExtInfo misa_ext_info_arr[] = {
> MISA_EXT_INFO(RVH, "h", "Hypervisor"),
> MISA_EXT_INFO(RVV, "v", "Vector operations"),
> MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
> - MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
> + MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)"),
> + MISA_EXT_INFO(RVP, "x-p", "Packed-SIMD instructions")
> };
>
> static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index c9dfa7daff2..75cfb16d846 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -70,6 +70,7 @@ typedef struct CPUArchState CPURISCVState;
> #define RVG RV('G')
> #define RVB RV('B')
> #define RVX RV('X')
> +#define RVP RV('P')
>
> extern const uint32_t misa_bits[];
> const char *riscv_get_misa_ext_name(uint32_t bit);
> @@ -742,6 +743,13 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
> FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32)
> FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1)
> FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1)
> +FIELD(EXT_TB_FLAGS, P_VXSAT_EXCP, 34, 2)
> +
> +enum {
> + P_VXSAT_EXCP_NONE,
> + P_VXSAT_EXCP_ILLEGAL,
> + P_VXSAT_EXCP_VIRTUAL,
> +};
>
> #ifdef TARGET_RISCV32
> #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 3f146a43fe4..fa7bf60f4fc 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -355,6 +355,8 @@
> #define SMSTATEEN0_CS (1ULL << 0)
> #define SMSTATEEN0_FCSR (1ULL << 1)
> #define SMSTATEEN0_JVT (1ULL << 2)
> +/* Packed-SIMD draft: enable access to vxsat when misa.V = 0. */
> +#define SMSTATEEN0_VXSAT (1ULL << 3)
> #define SMSTATEEN0_CTR (1ULL << 54)
> #define SMSTATEEN0_P1P13 (1ULL << 56)
> #define SMSTATEEN0_HSCONTXT (1ULL << 57)
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 0ab613a2980..a9cd7e4c1cc 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -158,6 +158,24 @@ static const VMStateDescription vmstate_vector = {
> }
> };
>
> +static bool p_vxsat_needed(void *opaque)
> +{
> + RISCVCPU *cpu = opaque;
> +
> + return riscv_has_ext(&cpu->env, RVP) && !cpu->cfg.ext_zve32x;
> +}
> +
> +static const VMStateDescription vmstate_p_vxsat = {
> + .name = "cpu/p-vxsat",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = p_vxsat_needed,
> + .fields = (const VMStateField[]) {
> + VMSTATE_UINT8(env.vxsat, RISCVCPU),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static bool pointermasking_needed(void *opaque)
> {
> return false;
> @@ -518,6 +536,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> &vmstate_pmp,
> &vmstate_hyper,
> &vmstate_vector,
> + &vmstate_p_vxsat,
> &vmstate_pointermasking,
> &vmstate_rv128,
> #ifdef CONFIG_KVM
> diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
> index 36f2004bc56..e809997f52e 100644
> --- a/target/riscv/tcg/csr.c
> +++ b/target/riscv/tcg/csr.c
> @@ -109,6 +109,24 @@ static RISCVException vs(CPURISCVState *env, int csrno)
> return RISCV_EXCP_ILLEGAL_INST;
> }
>
> +/* vxsat is also architectural state when P is implemented without Zve*. */
> +static RISCVException vxsat(CPURISCVState *env, int csrno)
> +{
> + if (riscv_cpu_cfg(env)->ext_zve32x) {
> + return vs(env, csrno);
> + }
> +
> + if (riscv_has_ext(env, RVP)) {
> +#if !defined(CONFIG_USER_ONLY)
> + return smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
> +#else
> + return RISCV_EXCP_NONE;
> +#endif
> + }
> +
> + return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> static RISCVException ctr(CPURISCVState *env, int csrno)
> {
> #if !defined(CONFIG_USER_ONLY)
> @@ -1013,7 +1031,12 @@ static RISCVException write_vxsat(CPURISCVState *env, int csrno,
> target_ulong val, uintptr_t ra)
> {
> #if !defined(CONFIG_USER_ONLY)
> - env->mstatus |= MSTATUS_VS;
> + if (riscv_cpu_cfg(env)->ext_zve32x) {
> + env->mstatus |= MSTATUS_VS;
> + if (env->virt_enabled) {
> + env->mstatus_hs |= MSTATUS_VS;
> + }
> + }
> #endif
> env->vxsat = val & BIT(0);
> return RISCV_EXCP_NONE;
> @@ -3494,6 +3517,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
> target_ulong new_val, uintptr_t ra)
> {
> uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
> +
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -3617,6 +3644,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
> {
> uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
>
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> +
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -3746,6 +3777,10 @@ static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
> {
> uint64_t wr_mask = 0;
>
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + wr_mask |= SMSTATEEN0_VXSAT;
> + }
> +
> if (!riscv_has_ext(env, RVF)) {
> wr_mask |= SMSTATEEN0_FCSR;
> }
> @@ -5916,7 +5951,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr },
> /* Vector CSRs */
> [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart },
> - [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat },
> + [CSR_VXSAT] = { "vxsat", vxsat, read_vxsat, write_vxsat },
> [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm },
> [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr },
> [CSR_VL] = { "vl", vs, read_vl },
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 4af5cd9c731..1665583accf 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -160,6 +160,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
> fs = EXT_STATUS_DIRTY;
> vs = EXT_STATUS_DIRTY;
> #else
> + RISCVException p_vxsat_excp;
> +
> flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
>
> flags |= riscv_env_mmu_index(env, 0);
> @@ -182,6 +184,23 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
> ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
> }
>
> + /*
> + * Without Zve*, all P instructions in the OP-32 and OP-IMM-32
> + * spaces are controlled by stateen0.VXSAT. Preserve the exception
> + * class in the TB flags so translated code can distinguish an illegal
> + * instruction from a virtual-instruction exception.
> + */
> + p_vxsat_excp = smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
> + if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
> + if (p_vxsat_excp == RISCV_EXCP_VIRT_INSTRUCTION_FAULT) {
> + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
> + P_VXSAT_EXCP_VIRTUAL);
> + } else if (p_vxsat_excp != RISCV_EXCP_NONE) {
> + ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
> + P_VXSAT_EXCP_ILLEGAL);
> + }
> + }
> +
> if (cpu->cfg.debug && !icount_enabled()) {
> flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
> }
> @@ -530,6 +549,28 @@ static void riscv_cpu_validate_b(RISCVCPU *cpu)
> }
> }
>
> +static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
> +{
> + CPURISCVState *env = &cpu->env;
> +
> + if (!riscv_has_ext(env, RVP)) {
> + return;
> + }
> +
> + if (riscv_cpu_mxl(env) != MXL_RV32 &&
> + riscv_cpu_mxl(env) != MXL_RV64) {
> + error_setg(errp, "P extension requires RV32 or RV64");
> + return;
> + }
> +
> + if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
> + cpu->cfg.ext_zbkb)) {
> + error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
> + "extensions");
> + return;
> + }
> +}
> +
> /*
> * Check consistency between chosen extensions while setting
> * cpu->cfg accordingly.
> @@ -612,6 +653,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
> return;
> }
>
> + riscv_cpu_validate_p(cpu, &local_err);
> + if (local_err != NULL) {
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
> if (local_err != NULL) {
> error_propagate(errp, local_err);
> @@ -1414,6 +1461,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
> MISA_CFG(RVV, false),
> MISA_CFG(RVG, false),
> MISA_CFG(RVB, false),
> + MISA_CFG(RVP, false),
> };
>
> /*
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
2026-07-17 10:06 ` [PATCH v2 01/18] target/riscv: Add packed SIMD extension state Molly Chen
@ 2026-07-17 10:06 ` Molly Chen
2026-07-26 19:53 ` Daniel Henrique Barboza
` (2 more replies)
2026-07-17 10:06 ` [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions Molly Chen
` (17 subsequent siblings)
19 siblings, 3 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:06 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/tcg/meson.build | 3 +-
target/riscv/tcg/psimd_helper.c | 1656 +++++++++++++++++++++++++++++++
2 files changed, 1658 insertions(+), 1 deletion(-)
create mode 100644 target/riscv/tcg/psimd_helper.c
diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
index a05ab642f41..cc438d7c0d2 100644
--- a/target/riscv/tcg/meson.build
+++ b/target/riscv/tcg/meson.build
@@ -15,7 +15,8 @@ riscv_ss.add(files(
'vcrypto_helper.c',
'vector_helper.c',
'vector_internals.c',
- 'zce_helper.c'))
+ 'zce_helper.c',
+ 'psimd_helper.c'))
riscv_system_ss.add(files(
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
new file mode 100644
index 00000000000..2948bbb2a86
--- /dev/null
+++ b/target/riscv/tcg/psimd_helper.c
@@ -0,0 +1,1656 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* RISC-V Packed SIMD Extension Helpers for QEMU. */
+/* Copyright (C) 2026 ISRC ISCAS. */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "fpu/softfloat.h"
+#include "internals.h"
+
+
+/* Helper macros */
+
+/* Element count calculations */
+#define ELEMS_B(target) (sizeof(target) * 8 / 8) /* byte elements count */
+#define ELEMS_H(target) (sizeof(target) * 8 / 16)
+#define ELEMS_W(target) (sizeof(target) * 8 / 32) /* word elements count */
+#define ELEMS_D(target) (sizeof(target) * 8 / 64)
+
+/* Element extraction macros - unsigned to avoid sign extension */
+#define EXTRACT8(val, idx) (((val) >> ((idx) * 8)) & 0xFF)
+#define EXTRACT16(val, idx) (((val) >> ((idx) * 16)) & 0xFFFF)
+#define EXTRACT32(val, idx) (((val) >> ((idx) * 32)) & 0xFFFFFFFF)
+#define EXTRACT64(val, idx) (((val) >> ((idx) * 64)) & 0xFFFFFFFFFFFFFFFFULL)
+
+/* Element insertion macros */
+#define INSERT8(val, res, idx) \
+ ((val) | ((target_ulong)(uint8_t)(res) << ((idx) * 8)))
+#define INSERT16(val, res, idx) \
+ ((val) | ((target_ulong)(uint16_t)(res) << ((idx) * 16)))
+#define INSERT32(val, res, idx) \
+ ((val) | ((target_ulong)(uint32_t)(res) << ((idx) * 32)))
+#define INSERT32_64(val, res, idx) \
+ ((val) | ((uint64_t)(uint32_t)(res) << ((idx) * 32)))
+#define INSERT64(val, res, idx) \
+ ((val) | ((uint64_t)(res) << ((idx) * 64)))
+
+/* Saturation constants */
+static const int8_t SAT_MAX_B = 127;
+static const int8_t SAT_MIN_B = -128;
+static const int16_t SAT_MAX_H = 32767;
+static const int16_t SAT_MIN_H = -32768;
+static const int32_t SAT_MAX_W = 2147483647;
+static const int32_t SAT_MIN_W = -2147483648LL;
+static const uint8_t USAT_MAX_B = 255;
+static const uint16_t USAT_MAX_H = 65535;
+static const uint32_t USAT_MAX_W = 4294967295U;
+
+
+/* Saturation helper functions */
+
+/**
+ * Signed saturation for 8-bit elements
+ * Returns saturated value and sets *sat if saturation occurred
+ */
+static inline int8_t signed_saturate_b(int32_t val, int *sat)
+{
+ if (val > SAT_MAX_B) {
+ *sat = 1;
+ return SAT_MAX_B;
+ }
+ if (val < SAT_MIN_B) {
+ *sat = 1;
+ return SAT_MIN_B;
+ }
+ return (int8_t)val;
+}
+
+/**
+ * Signed saturation for 16-bit elements
+ */
+static inline int16_t signed_saturate_h(int32_t val, int *sat)
+{
+ if (val > SAT_MAX_H) {
+ *sat = 1;
+ return SAT_MAX_H;
+ }
+ if (val < SAT_MIN_H) {
+ *sat = 1;
+ return SAT_MIN_H;
+ }
+ return (int16_t)val;
+}
+
+/**
+ * Signed saturation for 32-bit elements
+ */
+static inline int32_t signed_saturate_w(int64_t val, int *sat)
+{
+ if (val > SAT_MAX_W) {
+ *sat = 1;
+ return SAT_MAX_W;
+ }
+ if (val < SAT_MIN_W) {
+ *sat = 1;
+ return SAT_MIN_W;
+ }
+ return (int32_t)val;
+}
+
+/**
+ * Unsigned saturation for 8-bit elements
+ */
+static inline uint8_t unsigned_saturate_b(uint32_t val, int *sat)
+{
+ if (val > USAT_MAX_B) {
+ *sat = 1;
+ return USAT_MAX_B;
+ }
+ return (uint8_t)val;
+}
+
+/**
+ * Unsigned saturation for 16-bit elements
+ */
+static inline uint16_t unsigned_saturate_h(uint32_t val, int *sat)
+{
+ if (val > USAT_MAX_H) {
+ *sat = 1;
+ return USAT_MAX_H;
+ }
+ return (uint16_t)val;
+}
+
+/**
+ * Unsigned saturation for 32-bit elements
+ */
+static inline uint32_t unsigned_saturate_w(uint64_t val, int *sat)
+{
+ if (val > USAT_MAX_W) {
+ *sat = 1;
+ return USAT_MAX_W;
+ }
+ return (uint32_t)val;
+}
+
+static inline target_ulong psimd_abdsumu_b(target_ulong rs1,
+ target_ulong rs2,
+ target_ulong sum)
+{
+ int elems = ELEMS_B(rs1);
+
+ for (int i = 0; i < elems; i++) {
+ uint8_t e1 = EXTRACT8(rs1, i);
+ uint8_t e2 = EXTRACT8(rs2, i);
+ uint8_t diff = (e1 > e2) ? (e1 - e2) : (e2 - e1);
+ sum += diff;
+ }
+
+ return sum;
+}
+
+#define PSIMD_DO_ADD(N, M) ((N) + (M))
+#define PSIMD_DO_SUB(N, M) ((N) - (M))
+#define PSIMD_DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
+#define PSIMD_DO_EQ_MASK(N, M) ((N) == (M) ? -1 : 0)
+#define PSIMD_DO_LT_MASK(N, M) ((N) < (M) ? -1 : 0)
+#define PSIMD_DO_MIN(N, M) ((N) < (M) ? (N) : (M))
+#define PSIMD_DO_MAX(N, M) ((N) > (M) ? (N) : (M))
+#define PSIMD_DO_SLL(N, M) ((N) << (M))
+#define PSIMD_DO_SRL(N, M) ((N) >> (M))
+#define PSIMD_DO_SRA(N, M) ((N) >> (M))
+
+#define GEN_PSIMD_BINOP(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
+ ELEMS, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ STYPE e1 = (STYPE)EXTRACT(rs1, i); \
+ STYPE e2 = (STYPE)EXTRACT(rs2, i); \
+ DTYPE res = (DTYPE)OP(e1, e2); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_BINOP_SCALAR(NAME, RTYPE, ETYPE, EXTRACT, INSERT, \
+ ELEMS, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, 0); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res = OP(e1, e2); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SHIFTOP(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
+ ELEMS, SHMASK, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ uint8_t shamt = rs2 & (SHMASK); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ STYPE e1 = (STYPE)EXTRACT(rs1, i); \
+ DTYPE res = (DTYPE)OP(e1, shamt); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SAT_SHIFTOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, SHMASK, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ uint8_t shamt = rs2 & (SHMASK); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ WTYPE shifted = (WTYPE)e1 << shamt; \
+ ETYPE res = SAT_FN(shifted, &sat); \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_ROUND_SRAI(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, SHMASK) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ uint8_t shamt = rs2 & (SHMASK); \
+ \
+ if (shamt == 0) { \
+ return rs1; \
+ } \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ WTYPE rounded = (((WTYPE)e1 >> (shamt - 1)) + 1) >> 1; \
+ rd = INSERT(rd, (ETYPE)rounded, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SAT_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, OP, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
+ WTYPE val = OP((WTYPE)e1, (WTYPE)e2); \
+ ETYPE res = SAT_FN(val, &sat); \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_USUB_SAT(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
+ ETYPE res = (e1 >= e2) ? (e1 - e2) : 0; \
+ if (e1 < e2) { \
+ sat = 1; \
+ } \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_AVG_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ WTYPE e1 = (WTYPE)(ETYPE)EXTRACT(rs1, i); \
+ WTYPE e2 = (WTYPE)(ETYPE)EXTRACT(rs2, i); \
+ ETYPE res = (ETYPE)(OP(e1, e2) >> 1); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SHADD(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
+ SHAMT) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
+ ETYPE res = (e1 << (SHAMT)) + e2; \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SAT_SHADD(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, SHAMT, SH_MIN, SH_MAX, SAT_MIN, \
+ SAT_MAX, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
+ WTYPE shifted; \
+ \
+ if (e1 > (SH_MAX) || e1 < (SH_MIN)) { \
+ shifted = (e1 < 0) ? (SAT_MIN) : (SAT_MAX); \
+ sat = 1; \
+ } else { \
+ shifted = (WTYPE)e1 << (SHAMT); \
+ } \
+ \
+ WTYPE sum = shifted + e2; \
+ ETYPE res = SAT_FN(sum, &sat); \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SATI(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, IMMMASK) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE imm) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int range = (imm & (IMMMASK)) + 1; \
+ WTYPE max = ((WTYPE)1 << (range - 1)) - 1; \
+ WTYPE min = -((WTYPE)1 << (range - 1)); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (e1 > max) { \
+ res = max; \
+ sat = 1; \
+ } else if (e1 < min) { \
+ res = min; \
+ sat = 1; \
+ } else { \
+ res = e1; \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_USATI(NAME, RTYPE, ETYPE, UTYPE, WTYPE, EXTRACT, \
+ INSERT, ELEMS, ONE) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE imm) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ WTYPE max = ((WTYPE)(ONE) << imm) - 1; \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (e1 < 0) { \
+ res = 0; \
+ sat = 1; \
+ } else if ((UTYPE)e1 > max) { \
+ res = max; \
+ sat = 1; \
+ } else { \
+ res = e1; \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_ABS(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
+ MINVAL, MAXVAL) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (e1 == (MINVAL)) { \
+ res = (MAXVAL); \
+ sat = 1; \
+ } else if (e1 < 0) { \
+ res = -e1; \
+ } else { \
+ res = e1; \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_SCALAR_ABS(NAME, RTYPE, STYPE, UTYPE) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
+{ \
+ STYPE value = (STYPE)rs1; \
+ UTYPE result = (UTYPE)value; \
+ \
+ if (value < 0) { \
+ result = (UTYPE)0 - result; \
+ } \
+ return (RTYPE)(STYPE)result; \
+}
+
+#define GEN_PSIMD_VAR_SSHA(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, BITS, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ int8_t shamt = (int8_t)(rs2 & 0xff); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (shamt >= 0) { \
+ WTYPE shifted = (WTYPE)e1 << shamt; \
+ res = SAT_FN(shifted, &sat); \
+ } else { \
+ int right = -shamt; \
+ if (right >= (BITS)) { \
+ res = (e1 < 0) ? -1 : 0; \
+ } else { \
+ res = e1 >> right; \
+ } \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_VAR_SSHAR(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, BITS, SAT_MIN, SAT_MAX, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ int8_t shamt = (int8_t)(rs2 & 0xff); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (shamt >= 0) { \
+ if (shamt >= (BITS)) { \
+ if (e1 == 0) { \
+ res = 0; \
+ } else if (e1 > 0) { \
+ res = (SAT_MAX); \
+ sat = 1; \
+ } else { \
+ res = (SAT_MIN); \
+ sat = 1; \
+ } \
+ } else { \
+ WTYPE shifted = (WTYPE)e1 * ((WTYPE)1 << shamt); \
+ res = SAT_FN(shifted, &sat); \
+ } \
+ } else { \
+ int right = -shamt; \
+ if (right >= (BITS)) { \
+ res = 0; \
+ } else { \
+ WTYPE rounded = ((e1 >> (right - 1)) + 1) >> 1; \
+ res = (ETYPE)rounded; \
+ } \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_VAR_USHL(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, BITS, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ int8_t shamt = (int8_t)(rs2 & 0xff); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (shamt >= 0) { \
+ WTYPE shifted = (shamt >= (BITS)) ? \
+ ((WTYPE)e1 << (BITS)) : \
+ ((WTYPE)e1 << shamt); \
+ res = SAT_FN(shifted, &sat); \
+ } else { \
+ int right = -shamt; \
+ if (right >= (BITS)) { \
+ res = 0; \
+ } else { \
+ res = e1 >> right; \
+ } \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_VAR_USHLR(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
+ ELEMS, BITS, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ int8_t shamt = (int8_t)(rs2 & 0xff); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE res; \
+ \
+ if (shamt >= 0) { \
+ WTYPE shifted = (shamt >= (BITS)) ? \
+ ((WTYPE)e1 << (BITS)) : \
+ ((WTYPE)e1 << shamt); \
+ res = SAT_FN(shifted, &sat); \
+ } else { \
+ int right = -shamt; \
+ if (right > (BITS)) { \
+ res = 0; \
+ } else { \
+ WTYPE rounded = ((WTYPE)e1 >> (right - 1)) + 1; \
+ res = (ETYPE)(rounded >> 1); \
+ } \
+ } \
+ \
+ rd = INSERT(rd, res, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define PSIMD_DO_SRA64(A, B) ((A) >> (B))
+#define PSIMD_DO_RNDSRA64(A, B) \
+ ((int64_t)((((__int128_t)(A) >> ((B) - 1)) + 1) >> 1))
+
+#define GEN_PSIMD_VAR_SRA64(NAME, RIGHT_OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
+{ \
+ int64_t a = (int64_t)rs1; \
+ int8_t shamt = (int8_t)(rs2 & 0xff); \
+ \
+ if (shamt >= 0) { \
+ return (uint64_t)(a << shamt); \
+ } \
+ \
+ int right = -shamt; \
+ if (right >= 64) { \
+ return (a < 0) ? (uint64_t)-1 : 0; \
+ } \
+ return (uint64_t)RIGHT_OP(a, right); \
+}
+
+#define PSIMD_DO_SRL64(A, B) (((B) >= 64) ? 0 : ((A) >> (B)))
+#define PSIMD_DO_RNDSRL64(A, B) \
+ (((B) > 64) ? 0 : ((((A) >> ((B) - 1)) + 1) >> 1))
+
+#define GEN_PSIMD_VAR_SRL64(NAME, RIGHT_OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
+{ \
+ int8_t shamt = (int8_t)(rs2 & 0xff); \
+ \
+ if (shamt < 0) { \
+ return RIGHT_OP(rs1, -shamt); \
+ } \
+ return (shamt >= 64) ? 0 : (rs1 << shamt); \
+}
+
+#define GEN_PSIMD_XPAIR_BINOP(NAME, RTYPE, ETYPE, EXTRACT, INSERT, \
+ ELEMS, OP_LO, OP_HI) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i += 2) { \
+ ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
+ ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
+ ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
+ ETYPE res_lo = OP_LO(s1_lo, s2_hi); \
+ ETYPE res_hi = OP_HI(s1_hi, s2_lo); \
+ rd = INSERT(rd, res_lo, i); \
+ rd = INSERT(rd, res_hi, i + 1); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_XPAIR_SAT_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, \
+ INSERT, ELEMS, OP_LO, OP_HI, SAT_FN) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i += 2) { \
+ ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
+ ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
+ ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
+ WTYPE val_lo = OP_LO((WTYPE)s1_lo, (WTYPE)s2_hi); \
+ WTYPE val_hi = OP_HI((WTYPE)s1_hi, (WTYPE)s2_lo); \
+ ETYPE res_lo = SAT_FN(val_lo, &sat); \
+ ETYPE res_hi = SAT_FN(val_hi, &sat); \
+ rd = INSERT(rd, res_lo, i); \
+ rd = INSERT(rd, res_hi, i + 1); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_XPAIR_AVG_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, \
+ INSERT, ELEMS, OP_LO, OP_HI) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i += 2) { \
+ ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
+ ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
+ ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
+ ETYPE res_lo = (ETYPE)(OP_LO((WTYPE)s1_lo, (WTYPE)s2_hi) >> 1); \
+ ETYPE res_hi = (ETYPE)(OP_HI((WTYPE)s1_hi, (WTYPE)s2_lo) >> 1); \
+ rd = INSERT(rd, res_lo, i); \
+ rd = INSERT(rd, res_hi, i + 1); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_REDSUM(NAME, RTYPE, SUMTYPE, ETYPE, EXTRACT, ELEMS, \
+ INIT) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ SUMTYPE sum = (INIT); \
+ int elems = ELEMS(rs1); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ sum += e1; \
+ } \
+ \
+ return (RTYPE)sum; \
+}
+
+#define PSIMD_PAIR_LO(V, MASK, SHIFT) ((V) & (MASK))
+#define PSIMD_PAIR_HI(V, MASK, SHIFT) (((V) >> (SHIFT)) & (MASK))
+
+#define GEN_PSIMD_PAIR_PACK(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
+ MASK, SHIFT, HI_SEL, LO_SEL) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = EXTRACT(rs1, i); \
+ ETYPE e2 = EXTRACT(rs2, i); \
+ ETYPE res = (HI_SEL(e2, MASK, SHIFT) << (SHIFT)) | \
+ LO_SEL(e1, MASK, SHIFT); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_PAIR_WORD(NAME, RS1_IDX, RS2_IDX) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
+{ \
+ uint32_t e1 = EXTRACT32(rs1, RS1_IDX); \
+ uint32_t e2 = EXTRACT32(rs2, RS2_IDX); \
+ \
+ return ((uint64_t)e2 << 32) | e1; \
+}
+
+#define GEN_PSIMD_SIGN_EXTEND(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
+ ELEMS, SCALE) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ STYPE e1 = (STYPE)EXTRACT(rs1, i * (SCALE)); \
+ rd = INSERT(rd, (DTYPE)e1, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_ZIP(NAME, ETYPE, EXTRACT, ELEMS, BITS, START) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = EXTRACT(rs1, (START) - i); \
+ ETYPE e2 = EXTRACT(rs2, (START) - i); \
+ rd = (rd << (2 * (BITS))) | ((uint64_t)e2 << (BITS)) | e1; \
+ } \
+ \
+ return rd; \
+}
+
+#define GEN_PSIMD_UNZIP(NAME, EXTRACT, ELEMS, BITS, OFFSET) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ uint64_t e1 = (uint64_t)EXTRACT(rs1, 2 * i + (OFFSET)) << \
+ ((BITS) * i); \
+ uint64_t e2 = (uint64_t)EXTRACT(rs2, 2 * i + (OFFSET)) << \
+ (32 + (BITS) * i); \
+ rd = rd | e2 | e1; \
+ } \
+ \
+ return rd; \
+}
+
+#define GEN_PSIMD_BIT_SELECT(NAME, MASK, TRUE_VAL, FALSE_VAL) \
+target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong rs1, \
+ target_ulong rs2, target_ulong rd) \
+{ \
+ return (~(MASK) & (FALSE_VAL)) | ((MASK) & (TRUE_VAL)); \
+}
+
+#define GEN_PSIMD_NCLIP_PACK(NAME, ITYPE, OTYPE, EXTRACT, INSERT, ELEMS, \
+ SAT_FN) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ int sat = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ITYPE lo = (ITYPE)EXTRACT(rs1, i); \
+ ITYPE hi = (ITYPE)EXTRACT(rs2, i); \
+ OTYPE res_lo = SAT_FN(lo, &sat); \
+ OTYPE res_hi = SAT_FN(hi, &sat); \
+ \
+ rd = (uint64_t)INSERT(rd, res_lo, i); \
+ rd = (uint64_t)INSERT(rd, res_hi, i + (ELEMS)); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_CLS(NAME, RTYPE, UTYPE, CLRSB) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
+{ \
+ return CLRSB((UTYPE)rs1); \
+}
+
+#define PSIMD_MUL_S32(A, B) ((int32_t)(A) * (int32_t)(B))
+#define PSIMD_MUL_SU16(A, B) ((int16_t)(A) * (uint16_t)(B))
+#define PSIMD_MUL_SU32(A, B) ((int32_t)(A) * (uint32_t)(B))
+#define PSIMD_MUL_U32(A, B) ((uint32_t)(A) * (uint32_t)(B))
+#define PSIMD_MUL_S64(A, B) ((int64_t)(A) * (int64_t)(B))
+#define PSIMD_MUL_SU64(A, B) ((int64_t)(A) * (uint64_t)(B))
+#define PSIMD_MUL_U64(A, B) ((uint64_t)(A) * (uint64_t)(B))
+
+#define GEN_PSIMD_MUL_HIGH(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, HTYPE, \
+ EXTRACT, INSERT, ELEMS, SHIFT, ROUND, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
+ PTYPE prod = OP(e1, e2) + (ROUND); \
+ HTYPE high = (HTYPE)(prod >> (SHIFT)); \
+ rd = INSERT(rd, high, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_MUL_HIGH_SEL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
+ HTYPE, EXTRACT1, EXTRACT2, INSERT, ELEMS, \
+ SCALE, OFFSET, SHIFT, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT1(rs1, i); \
+ E2TYPE e2 = (E2TYPE)EXTRACT2(rs2, i * (SCALE) + (OFFSET)); \
+ PTYPE prod = OP(e1, e2); \
+ HTYPE high = (HTYPE)(prod >> (SHIFT)); \
+ rd = INSERT(rd, high, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_MUL_ELEM_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
+ OTYPE, EXTRACT, INSERT, ELEMS, SCALE, \
+ OFFSET1, OFFSET2, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
+ PTYPE mul = OP(e1, e2); \
+ rd = INSERT(rd, (OTYPE)mul, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_MUL_ELEM_SCALAR(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
+ EXTRACT, OFFSET1, OFFSET2, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, OFFSET1); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, OFFSET2); \
+ PTYPE mul = OP(e1, e2); \
+ \
+ return (RTYPE)mul; \
+}
+
+#define GEN_PSIMD_MUL_HIGH_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
+ HTYPE, OTYPE, EXTRACT, INSERT, ELEMS, \
+ SHIFT, ROUND, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
+ DTYPE d = (DTYPE)EXTRACT(dest, i); \
+ PTYPE prod = OP(e1, e2) + (ROUND); \
+ HTYPE high = (HTYPE)(prod >> (SHIFT)); \
+ OTYPE res = (OTYPE)(high + d); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_MUL_HIGH_ACC_SEL(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
+ PTYPE, HTYPE, OTYPE, EXTRACT1, \
+ EXTRACT2, INSERT, ELEMS, SCALE, \
+ OFFSET, SHIFT, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT1(rs1, i); \
+ E2TYPE e2 = (E2TYPE)EXTRACT2(rs2, i * (SCALE) + (OFFSET)); \
+ DTYPE d = (DTYPE)EXTRACT1(dest, i); \
+ PTYPE prod = OP(e1, e2); \
+ HTYPE high = (HTYPE)(prod >> (SHIFT)); \
+ OTYPE res = (OTYPE)(high + d); \
+ rd = INSERT(rd, res, i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_MUL_ACC_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
+ PTYPE, OTYPE, EXTRACT, EXTRACTD, \
+ INSERT, ELEMS, SCALE, OFFSET1, \
+ OFFSET2, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE mul = OP(e1, e2); \
+ rd = INSERT(rd, (OTYPE)(d + mul), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_QMUL(NAME, RTYPE, ETYPE, PTYPE, OTYPE, EXTRACT, INSERT, \
+ ELEMS, SHIFT, ROUND, MINVAL, MAXVAL) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
+ OTYPE result; \
+ \
+ if ((e1 == (ETYPE)(MINVAL)) && (e2 == (ETYPE)(MINVAL))) { \
+ sat = 1; \
+ result = (OTYPE)(MAXVAL); \
+ } else { \
+ PTYPE prod = (PTYPE)e1 * (PTYPE)e2 + (ROUND); \
+ result = (OTYPE)(prod >> (SHIFT)); \
+ } \
+ rd = INSERT(rd, result, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_QMUL_ACC_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
+ PTYPE, STYPE, OTYPE, EXTRACT, \
+ EXTRACTD, INSERT, ELEMS, SCALE, \
+ OFFSET1, OFFSET2, SHIFT, ROUND, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE prod = OP(e1, e2) + (ROUND); \
+ STYPE scaled = (STYPE)(((__int128_t)prod) >> (SHIFT)); \
+ rd = INSERT(rd, (OTYPE)(d + scaled), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_Q2ADD(NAME, RTYPE, ETYPE, PTYPE, STYPE, OTYPE, EXTRACT, \
+ INSERT, ELEMS, SCALE, SHIFT, ROUND, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE s1_0 = (ETYPE)EXTRACT(rs1, i * (SCALE)); \
+ ETYPE s1_1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + 1); \
+ ETYPE s2_0 = (ETYPE)EXTRACT(rs2, i * (SCALE)); \
+ ETYPE s2_1 = (ETYPE)EXTRACT(rs2, i * (SCALE) + 1); \
+ PTYPE prod0 = OP(s1_0, s2_0) + (ROUND); \
+ PTYPE prod1 = OP(s1_1, s2_1) + (ROUND); \
+ STYPE scaled0 = (STYPE)(((__int128_t)prod0) >> (SHIFT)); \
+ STYPE scaled1 = (STYPE)(((__int128_t)prod1) >> (SHIFT)); \
+ rd = INSERT(rd, (OTYPE)(scaled0 + scaled1), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_Q2ADDA(NAME, RTYPE, ETYPE, DTYPE, PTYPE, STYPE, OTYPE, \
+ EXTRACT, EXTRACTD, INSERT, ELEMS, SCALE, \
+ SHIFT, ROUND, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ ETYPE s1_0 = (ETYPE)EXTRACT(rs1, i * (SCALE)); \
+ ETYPE s1_1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + 1); \
+ ETYPE s2_0 = (ETYPE)EXTRACT(rs2, i * (SCALE)); \
+ ETYPE s2_1 = (ETYPE)EXTRACT(rs2, i * (SCALE) + 1); \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE prod0 = OP(s1_0, s2_0) + (ROUND); \
+ PTYPE prod1 = OP(s1_1, s2_1) + (ROUND); \
+ STYPE scaled0 = (STYPE)(((__int128_t)prod0) >> (SHIFT)); \
+ STYPE scaled1 = (STYPE)(((__int128_t)prod1) >> (SHIFT)); \
+ rd = INSERT(rd, (OTYPE)(d + scaled0 + scaled1), i); \
+ } \
+ return rd; \
+}
+
+#define PSIMD_COMB_ADD(D, A, B) ((D) + (A) + (B))
+#define PSIMD_COMB_SUB(D, A, B) ((D) + (A) - (B))
+
+#define GEN_PSIMD_2WAY_MUL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, OTYPE, \
+ EXTRACT, INSERT, ELEMS, SCALE, OFFSET10, \
+ OFFSET11, OFFSET20, OFFSET21, OP, COMBINE) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET10)); \
+ E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET11)); \
+ E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET20)); \
+ E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET21)); \
+ PTYPE prod0 = OP(s1_0, s2_0); \
+ PTYPE prod1 = OP(s1_1, s2_1); \
+ rd = INSERT(rd, (OTYPE)COMBINE(0, prod0, prod1), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_2WAY_SAT_MUL(NAME, OFFSET10, OFFSET11, OFFSET20, \
+ OFFSET21) \
+target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong rs1, \
+ target_ulong rs2) \
+{ \
+ target_ulong rd = 0; \
+ int sat = 0; \
+ \
+ for (int i = 0; i < ELEMS_W(rd); i++) { \
+ int16_t s1_0 = (int16_t)EXTRACT16(rs1, i * 2 + (OFFSET10)); \
+ int16_t s1_1 = (int16_t)EXTRACT16(rs1, i * 2 + (OFFSET11)); \
+ int16_t s2_0 = (int16_t)EXTRACT16(rs2, i * 2 + (OFFSET20)); \
+ int16_t s2_1 = (int16_t)EXTRACT16(rs2, i * 2 + (OFFSET21)); \
+ uint32_t result; \
+ \
+ if (s1_0 == INT16_MIN && s1_1 == INT16_MIN && \
+ s2_0 == INT16_MIN && s2_1 == INT16_MIN) { \
+ result = INT32_MAX; \
+ sat = 1; \
+ } else { \
+ int32_t prod0 = (int32_t)s1_0 * s2_0; \
+ int32_t prod1 = (int32_t)s1_1 * s2_1; \
+ result = (uint32_t)(prod0 + prod1); \
+ } \
+ rd = INSERT32(rd, result, i); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_2WAY_MUL_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
+ OTYPE, EXTRACT, EXTRACTD, INSERT, ELEMS, \
+ SCALE, OFFSET10, OFFSET11, OFFSET20, \
+ OFFSET21, OP, COMBINE) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET10)); \
+ E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET11)); \
+ E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET20)); \
+ E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET21)); \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE prod0 = OP(s1_0, s2_0); \
+ PTYPE prod1 = OP(s1_1, s2_1); \
+ rd = INSERT(rd, (OTYPE)COMBINE(d, prod0, prod1), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_4WAY_MUL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, OTYPE, \
+ EXTRACT, INSERT, ELEMS, SCALE, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ PTYPE prod0 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE)), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE))); \
+ PTYPE prod1 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 1), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE) + 1)); \
+ PTYPE prod2 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 2), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE) + 2)); \
+ PTYPE prod3 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 3), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE) + 3)); \
+ rd = INSERT(rd, (OTYPE)(prod0 + prod1 + prod2 + prod3), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_4WAY_MUL_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
+ OTYPE, EXTRACT, EXTRACTD, INSERT, ELEMS, \
+ SCALE, OP) \
+RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
+{ \
+ RTYPE rd = 0; \
+ int elems = ELEMS(rd); \
+ \
+ for (int i = 0; i < elems; i++) { \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE prod0 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE)), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE))); \
+ PTYPE prod1 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 1), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE) + 1)); \
+ PTYPE prod2 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 2), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE) + 2)); \
+ PTYPE prod3 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 3), \
+ (E2TYPE)EXTRACT(rs2, i * (SCALE) + 3)); \
+ rd = INSERT(rd, (OTYPE)(d + prod0 + prod1 + prod2 + prod3), i); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_WIDEN_BINOP(NAME, ETYPE, WTYPE, OTYPE, ELEMS, IBITS, \
+ OBITS, IMASK, OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
+ ETYPE e2 = (ETYPE)((rs2 >> (i * (IBITS))) & (IMASK)); \
+ WTYPE res = OP((WTYPE)0, (WTYPE)e1, (WTYPE)e2); \
+ rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_WIDEN_BINOP_ACC(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
+ IBITS, OBITS, IMASK, OMASK, OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
+ uint64_t dest) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
+ ETYPE e2 = (ETYPE)((rs2 >> (i * (IBITS))) & (IMASK)); \
+ WTYPE acc = (WTYPE)((dest >> (i * (OBITS))) & (OMASK)); \
+ WTYPE res = OP(acc, (WTYPE)e1, (WTYPE)e2); \
+ rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_WIDEN_MUL(NAME, E1TYPE, E2TYPE, PTYPE, OTYPE, ELEMS, \
+ EXTRACT, OBITS, OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
+ PTYPE prod = OP(e1, e2); \
+ rd |= ((uint64_t)(OTYPE)prod) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_WIDEN_MUL_ACC(NAME, E1TYPE, E2TYPE, DTYPE, PTYPE, \
+ OTYPE, ELEMS, EXTRACT, EXTRACTD, OBITS, \
+ OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
+ uint64_t dest) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
+ E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE prod = OP(e1, e2); \
+ rd |= ((uint64_t)(OTYPE)(d + prod)) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_WIDEN_QMUL_ACC(NAME, ETYPE, DTYPE, PTYPE, STYPE, \
+ OTYPE, ELEMS, EXTRACT, EXTRACTD, SCALE, \
+ OFFSET, SHIFT, ROUND, OBITS, OP) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
+ uint64_t dest) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET)); \
+ ETYPE e2 = (ETYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET)); \
+ DTYPE d = (DTYPE)EXTRACTD(dest, i); \
+ PTYPE prod = OP(e1, e2) + (ROUND); \
+ STYPE scaled = (STYPE)(((__int128_t)prod) >> (SHIFT)); \
+ rd |= ((uint64_t)(OTYPE)(d + scaled)) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_DW_2WAY_MUL(NAME, E1TYPE, E2TYPE, PTYPE, EXTRACT, \
+ OFFSET10, OFFSET11, OFFSET20, OFFSET21, \
+ OP, COMBINE) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
+{ \
+ E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, OFFSET10); \
+ E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, OFFSET11); \
+ E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, OFFSET20); \
+ E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, OFFSET21); \
+ PTYPE prod0 = OP(s1_0, s2_0); \
+ PTYPE prod1 = OP(s1_1, s2_1); \
+ \
+ return (uint64_t)COMBINE(0, prod0, prod1); \
+}
+
+#define GEN_PSIMD_DW_2WAY_MUL_ACC(NAME, E1TYPE, E2TYPE, DTYPE, PTYPE, \
+ EXTRACT, OFFSET10, OFFSET11, OFFSET20, \
+ OFFSET21, OP, COMBINE) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
+ uint64_t dest) \
+{ \
+ E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, OFFSET10); \
+ E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, OFFSET11); \
+ E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, OFFSET20); \
+ E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, OFFSET21); \
+ DTYPE d = (DTYPE)dest; \
+ PTYPE prod0 = OP(s1_0, s2_0); \
+ PTYPE prod1 = OP(s1_1, s2_1); \
+ \
+ return (uint64_t)COMBINE(d, prod0, prod1); \
+}
+
+#define GEN_PSIMD_WIDEN_SHIFT(NAME, ETYPE, WTYPE, OTYPE, ELEMS, IBITS, \
+ OBITS, IMASK, SHMASK) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ uint8_t shamt = rs2 & (SHMASK); \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
+ WTYPE res = (WTYPE)e1 << shamt; \
+ rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_DW_ZIP(NAME, EXTRACT, ELEMS, STRIDE, BITS) \
+uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
+{ \
+ uint64_t rd = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ uint64_t e1 = (uint64_t)EXTRACT(rs1, i) << ((STRIDE) * i); \
+ uint64_t e2 = (uint64_t)EXTRACT(rs2, i) \
+ << ((STRIDE) * i + (BITS)); \
+ rd |= e2 | e1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_DW_REDSUM(NAME, SUMTYPE, INITTYPE, ETYPE, EXTRACT, \
+ ELEMS) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1_lo, \
+ uint32_t rs1_hi, uint32_t rs2) \
+{ \
+ SUMTYPE sum = (INITTYPE)rs2; \
+ uint64_t s1 = ((uint64_t)rs1_hi << 32) | rs1_lo; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ sum += (ETYPE)EXTRACT(s1, i); \
+ } \
+ return (uint32_t)sum; \
+}
+
+#define GEN_PSIMD_NARROW_SRL(NAME, ETYPE, OTYPE, ELEMS, IBITS, OBITS, \
+ IMASK, SHMASK) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ OTYPE result = (OTYPE)(e1 >> shift); \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NARROW_SRA_PACK(NAME, ETYPE, STYPE, OTYPE, ELEMS, \
+ IBITS, OBITS, IMASK, SHMASK) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ STYPE shx = (STYPE)e1 >> shift; \
+ OTYPE result = (OTYPE)shx; \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NARROW_RNDSRA_PACK(NAME, ETYPE, STYPE, OTYPE, ELEMS, \
+ IBITS, OBITS, IMASK, SHMASK, RMASK) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ STYPE e1_s = (STYPE)e1; \
+ uint64_t shx = (((uint64_t)e1_s << 1) >> shift) & (RMASK); \
+ OTYPE result = (OTYPE)((shx + 1) >> 1); \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NCLIP_SIGNED_PACK(NAME, ETYPE, STYPE, CTYPE, OTYPE, \
+ ELEMS, IBITS, OBITS, IMASK, SHMASK, \
+ MIN, MAX, MIN_RES, MAX_RES) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ CTYPE shx = (CTYPE)((STYPE)e1 >> shift); \
+ OTYPE result; \
+ \
+ if (shx < (MIN)) { \
+ sat = 1; \
+ result = (MIN_RES); \
+ } else if (shx > (MAX)) { \
+ sat = 1; \
+ result = (MAX_RES); \
+ } else { \
+ result = (OTYPE)shx; \
+ } \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NCLIPR_SIGNED_PACK(NAME, ETYPE, STYPE, CTYPE, OTYPE, \
+ ELEMS, IBITS, OBITS, IMASK, SHMASK, \
+ RMASK, MIN, MAX, MIN_RES, MAX_RES) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ STYPE e1_s = (STYPE)e1; \
+ uint64_t shx = (((uint64_t)e1_s << 1) >> shift) & (RMASK); \
+ CTYPE round_shx = (CTYPE)((shx + 1) >> 1); \
+ OTYPE result; \
+ \
+ if (round_shx < (MIN)) { \
+ sat = 1; \
+ result = (MIN_RES); \
+ } else if (round_shx > (MAX)) { \
+ sat = 1; \
+ result = (MAX_RES); \
+ } else { \
+ result = (OTYPE)round_shx; \
+ } \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NCLIP_UNSIGNED_PACK(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
+ IBITS, OBITS, IMASK, SHMASK, MAX) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ WTYPE shx = (WTYPE)e1 >> shift; \
+ OTYPE result; \
+ \
+ if (shx > (MAX)) { \
+ sat = 1; \
+ result = (OTYPE)(MAX); \
+ } else { \
+ result = (OTYPE)shx; \
+ } \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NCLIPR_UNSIGNED_PACK(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
+ IBITS, OBITS, IMASK, SHMASK, MAX) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint32_t rd = 0; \
+ uint8_t shift = shamt & (SHMASK); \
+ int sat = 0; \
+ \
+ for (int i = 0; i < (ELEMS); i++) { \
+ ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
+ WTYPE shx = ((WTYPE)e1 << 1) >> shift; \
+ WTYPE round_shx = (shx + 1) >> 1; \
+ OTYPE result; \
+ \
+ if (round_shx > (MAX)) { \
+ sat = 1; \
+ result = (OTYPE)(MAX); \
+ } else { \
+ result = (OTYPE)round_shx; \
+ } \
+ rd |= ((uint32_t)result) << (i * (OBITS)); \
+ } \
+ \
+ if (sat) { \
+ env->vxsat = 1; \
+ } \
+ return rd; \
+}
+
+#define GEN_PSIMD_NARROW_SRA(NAME) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
+ __int128_t s1_s96 = (s1_s128 << 32) >> 32; \
+ \
+ return (uint32_t)(s1_s96 >> (shamt & 0x3F)) & 0xFFFFFFFF; \
+}
+
+#define GEN_PSIMD_NARROW_RNDSRA(NAME) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
+ __int128_t s1_s96 = (s1_s128 << 32) >> 32; \
+ __uint128_t shx_97bit = ((__uint128_t)s1_s96 << 1); \
+ uint64_t shx = (uint64_t)(shx_97bit >> (shamt & 0x3F)) & 0x1FFFFFFFF; \
+ \
+ return (uint32_t)((shx + 1) >> 1); \
+}
+
+#define GEN_PSIMD_NARROW_ALIAS(NAME, TARGET) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ return HELPER(TARGET)(env, s1, shamt); \
+}
+
+typedef struct {
+ __uint128_t low;
+ uint8_t high;
+} PsImdUint129;
+
+static inline PsImdUint129 psimd_uint129_lshift1(__int128_t val)
+{
+ PsImdUint129 result;
+ __uint128_t uval = (__uint128_t)val;
+
+ result.low = uval << 1;
+ result.high = (uval >> 127) & 0x1;
+ return result;
+}
+
+static inline PsImdUint129 psimd_uint129_rshift(PsImdUint129 val,
+ uint32_t shamt)
+{
+ PsImdUint129 result;
+
+ if (shamt == 0) {
+ return val;
+ } else if (shamt >= 129) {
+ result.low = 0;
+ result.high = 0;
+ } else if (shamt == 128) {
+ result.low = val.high;
+ result.high = 0;
+ } else {
+ result.low = (val.low >> shamt) |
+ ((__uint128_t)val.high << (128 - shamt));
+ result.high = val.high >> shamt;
+ }
+ return result;
+}
+
+#define GEN_PSIMD_NCLIP(NAME) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
+ int64_t shx = (int64_t)(s1_s128 >> (shamt & 0x3F)); \
+ \
+ if (shx < -2147483648LL) { \
+ env->vxsat = 1; \
+ return 0x80000000U; \
+ } else if (shx > 2147483647LL) { \
+ env->vxsat = 1; \
+ return 0x7FFFFFFFU; \
+ } else { \
+ return (uint32_t)(shx & 0xFFFFFFFF); \
+ } \
+}
+
+#define GEN_PSIMD_NCLIPR(NAME) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
+ PsImdUint129 shx_129bit = psimd_uint129_lshift1(s1_s128); \
+ PsImdUint129 shx = psimd_uint129_rshift(shx_129bit, shamt & 0x3F); \
+ int64_t round_shx = (int64_t)((shx.low + 1) >> 1); \
+ \
+ if (round_shx < -2147483648LL) { \
+ env->vxsat = 1; \
+ return 0x80000000U; \
+ } else if (round_shx > 2147483647LL) { \
+ env->vxsat = 1; \
+ return 0x7FFFFFFFU; \
+ } else { \
+ return (uint32_t)round_shx; \
+ } \
+}
+
+#define GEN_PSIMD_NCLIPU(NAME) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ uint64_t shx = s1 >> (shamt & 0x3F); \
+ \
+ if (shx > 4294967295ULL) { \
+ env->vxsat = 1; \
+ return 0xFFFFFFFFU; \
+ } else { \
+ return (uint32_t)(shx & 0xFFFFFFFF); \
+ } \
+}
+
+#define GEN_PSIMD_NCLIPRU(NAME) \
+uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
+{ \
+ __uint128_t shx_65bit = (__uint128_t)s1 << 1; \
+ __uint128_t shx = shx_65bit >> (shamt & 0x3F); \
+ uint64_t round_shx = (shx + 1) >> 1; \
+ \
+ if (round_shx > 4294967295ULL) { \
+ env->vxsat = 1; \
+ return 0xFFFFFFFFU; \
+ } else { \
+ return (uint32_t)(round_shx & 0xFFFFFFFF); \
+ } \
+}
+
+/* Basic addition operations (non-saturating) */
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* Re: [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework
2026-07-17 10:06 ` [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework Molly Chen
@ 2026-07-26 19:53 ` Daniel Henrique Barboza
2026-07-27 6:16 ` Nutty.Liu
2026-07-29 9:01 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Daniel Henrique Barboza @ 2026-07-26 19:53 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel
On 7/17/2026 7:06 AM, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
> ---
There might be some code reduction opportunities in these helpers but
I'm afraid it'll come at a cost of readability. I think this is fine
for now.
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> target/riscv/tcg/meson.build | 3 +-
> target/riscv/tcg/psimd_helper.c | 1656 +++++++++++++++++++++++++++++++
> 2 files changed, 1658 insertions(+), 1 deletion(-)
> create mode 100644 target/riscv/tcg/psimd_helper.c
>
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> index a05ab642f41..cc438d7c0d2 100644
> --- a/target/riscv/tcg/meson.build
> +++ b/target/riscv/tcg/meson.build
> @@ -15,7 +15,8 @@ riscv_ss.add(files(
> 'vcrypto_helper.c',
> 'vector_helper.c',
> 'vector_internals.c',
> - 'zce_helper.c'))
> + 'zce_helper.c',
> + 'psimd_helper.c'))
>
>
> riscv_system_ss.add(files(
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> new file mode 100644
> index 00000000000..2948bbb2a86
> --- /dev/null
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -0,0 +1,1656 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* RISC-V Packed SIMD Extension Helpers for QEMU. */
> +/* Copyright (C) 2026 ISRC ISCAS. */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "qemu/host-utils.h"
> +#include "exec/helper-proto.h"
> +#include "fpu/softfloat.h"
> +#include "internals.h"
> +
> +
> +/* Helper macros */
> +
> +/* Element count calculations */
> +#define ELEMS_B(target) (sizeof(target) * 8 / 8) /* byte elements count */
> +#define ELEMS_H(target) (sizeof(target) * 8 / 16)
> +#define ELEMS_W(target) (sizeof(target) * 8 / 32) /* word elements count */
> +#define ELEMS_D(target) (sizeof(target) * 8 / 64)
> +
> +/* Element extraction macros - unsigned to avoid sign extension */
> +#define EXTRACT8(val, idx) (((val) >> ((idx) * 8)) & 0xFF)
> +#define EXTRACT16(val, idx) (((val) >> ((idx) * 16)) & 0xFFFF)
> +#define EXTRACT32(val, idx) (((val) >> ((idx) * 32)) & 0xFFFFFFFF)
> +#define EXTRACT64(val, idx) (((val) >> ((idx) * 64)) & 0xFFFFFFFFFFFFFFFFULL)
> +
> +/* Element insertion macros */
> +#define INSERT8(val, res, idx) \
> + ((val) | ((target_ulong)(uint8_t)(res) << ((idx) * 8)))
> +#define INSERT16(val, res, idx) \
> + ((val) | ((target_ulong)(uint16_t)(res) << ((idx) * 16)))
> +#define INSERT32(val, res, idx) \
> + ((val) | ((target_ulong)(uint32_t)(res) << ((idx) * 32)))
> +#define INSERT32_64(val, res, idx) \
> + ((val) | ((uint64_t)(uint32_t)(res) << ((idx) * 32)))
> +#define INSERT64(val, res, idx) \
> + ((val) | ((uint64_t)(res) << ((idx) * 64)))
> +
> +/* Saturation constants */
> +static const int8_t SAT_MAX_B = 127;
> +static const int8_t SAT_MIN_B = -128;
> +static const int16_t SAT_MAX_H = 32767;
> +static const int16_t SAT_MIN_H = -32768;
> +static const int32_t SAT_MAX_W = 2147483647;
> +static const int32_t SAT_MIN_W = -2147483648LL;
> +static const uint8_t USAT_MAX_B = 255;
> +static const uint16_t USAT_MAX_H = 65535;
> +static const uint32_t USAT_MAX_W = 4294967295U;
> +
> +
> +/* Saturation helper functions */
> +
> +/**
> + * Signed saturation for 8-bit elements
> + * Returns saturated value and sets *sat if saturation occurred
> + */
> +static inline int8_t signed_saturate_b(int32_t val, int *sat)
> +{
> + if (val > SAT_MAX_B) {
> + *sat = 1;
> + return SAT_MAX_B;
> + }
> + if (val < SAT_MIN_B) {
> + *sat = 1;
> + return SAT_MIN_B;
> + }
> + return (int8_t)val;
> +}
> +
> +/**
> + * Signed saturation for 16-bit elements
> + */
> +static inline int16_t signed_saturate_h(int32_t val, int *sat)
> +{
> + if (val > SAT_MAX_H) {
> + *sat = 1;
> + return SAT_MAX_H;
> + }
> + if (val < SAT_MIN_H) {
> + *sat = 1;
> + return SAT_MIN_H;
> + }
> + return (int16_t)val;
> +}
> +
> +/**
> + * Signed saturation for 32-bit elements
> + */
> +static inline int32_t signed_saturate_w(int64_t val, int *sat)
> +{
> + if (val > SAT_MAX_W) {
> + *sat = 1;
> + return SAT_MAX_W;
> + }
> + if (val < SAT_MIN_W) {
> + *sat = 1;
> + return SAT_MIN_W;
> + }
> + return (int32_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 8-bit elements
> + */
> +static inline uint8_t unsigned_saturate_b(uint32_t val, int *sat)
> +{
> + if (val > USAT_MAX_B) {
> + *sat = 1;
> + return USAT_MAX_B;
> + }
> + return (uint8_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 16-bit elements
> + */
> +static inline uint16_t unsigned_saturate_h(uint32_t val, int *sat)
> +{
> + if (val > USAT_MAX_H) {
> + *sat = 1;
> + return USAT_MAX_H;
> + }
> + return (uint16_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 32-bit elements
> + */
> +static inline uint32_t unsigned_saturate_w(uint64_t val, int *sat)
> +{
> + if (val > USAT_MAX_W) {
> + *sat = 1;
> + return USAT_MAX_W;
> + }
> + return (uint32_t)val;
> +}
> +
> +static inline target_ulong psimd_abdsumu_b(target_ulong rs1,
> + target_ulong rs2,
> + target_ulong sum)
> +{
> + int elems = ELEMS_B(rs1);
> +
> + for (int i = 0; i < elems; i++) {
> + uint8_t e1 = EXTRACT8(rs1, i);
> + uint8_t e2 = EXTRACT8(rs2, i);
> + uint8_t diff = (e1 > e2) ? (e1 - e2) : (e2 - e1);
> + sum += diff;
> + }
> +
> + return sum;
> +}
> +
> +#define PSIMD_DO_ADD(N, M) ((N) + (M))
> +#define PSIMD_DO_SUB(N, M) ((N) - (M))
> +#define PSIMD_DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
> +#define PSIMD_DO_EQ_MASK(N, M) ((N) == (M) ? -1 : 0)
> +#define PSIMD_DO_LT_MASK(N, M) ((N) < (M) ? -1 : 0)
> +#define PSIMD_DO_MIN(N, M) ((N) < (M) ? (N) : (M))
> +#define PSIMD_DO_MAX(N, M) ((N) > (M) ? (N) : (M))
> +#define PSIMD_DO_SLL(N, M) ((N) << (M))
> +#define PSIMD_DO_SRL(N, M) ((N) >> (M))
> +#define PSIMD_DO_SRA(N, M) ((N) >> (M))
> +
> +#define GEN_PSIMD_BINOP(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
> + ELEMS, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + STYPE e1 = (STYPE)EXTRACT(rs1, i); \
> + STYPE e2 = (STYPE)EXTRACT(rs2, i); \
> + DTYPE res = (DTYPE)OP(e1, e2); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_BINOP_SCALAR(NAME, RTYPE, ETYPE, EXTRACT, INSERT, \
> + ELEMS, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, 0); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res = OP(e1, e2); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SHIFTOP(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
> + ELEMS, SHMASK, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + STYPE e1 = (STYPE)EXTRACT(rs1, i); \
> + DTYPE res = (DTYPE)OP(e1, shamt); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SAT_SHIFTOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, SHMASK, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + WTYPE shifted = (WTYPE)e1 << shamt; \
> + ETYPE res = SAT_FN(shifted, &sat); \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_ROUND_SRAI(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, SHMASK) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + if (shamt == 0) { \
> + return rs1; \
> + } \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + WTYPE rounded = (((WTYPE)e1 >> (shamt - 1)) + 1) >> 1; \
> + rd = INSERT(rd, (ETYPE)rounded, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SAT_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, OP, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + WTYPE val = OP((WTYPE)e1, (WTYPE)e2); \
> + ETYPE res = SAT_FN(val, &sat); \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_USUB_SAT(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE res = (e1 >= e2) ? (e1 - e2) : 0; \
> + if (e1 < e2) { \
> + sat = 1; \
> + } \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_AVG_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + WTYPE e1 = (WTYPE)(ETYPE)EXTRACT(rs1, i); \
> + WTYPE e2 = (WTYPE)(ETYPE)EXTRACT(rs2, i); \
> + ETYPE res = (ETYPE)(OP(e1, e2) >> 1); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SHADD(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
> + SHAMT) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE res = (e1 << (SHAMT)) + e2; \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SAT_SHADD(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, SHAMT, SH_MIN, SH_MAX, SAT_MIN, \
> + SAT_MAX, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + WTYPE shifted; \
> + \
> + if (e1 > (SH_MAX) || e1 < (SH_MIN)) { \
> + shifted = (e1 < 0) ? (SAT_MIN) : (SAT_MAX); \
> + sat = 1; \
> + } else { \
> + shifted = (WTYPE)e1 << (SHAMT); \
> + } \
> + \
> + WTYPE sum = shifted + e2; \
> + ETYPE res = SAT_FN(sum, &sat); \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SATI(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, IMMMASK) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE imm) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int range = (imm & (IMMMASK)) + 1; \
> + WTYPE max = ((WTYPE)1 << (range - 1)) - 1; \
> + WTYPE min = -((WTYPE)1 << (range - 1)); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (e1 > max) { \
> + res = max; \
> + sat = 1; \
> + } else if (e1 < min) { \
> + res = min; \
> + sat = 1; \
> + } else { \
> + res = e1; \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_USATI(NAME, RTYPE, ETYPE, UTYPE, WTYPE, EXTRACT, \
> + INSERT, ELEMS, ONE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE imm) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + WTYPE max = ((WTYPE)(ONE) << imm) - 1; \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (e1 < 0) { \
> + res = 0; \
> + sat = 1; \
> + } else if ((UTYPE)e1 > max) { \
> + res = max; \
> + sat = 1; \
> + } else { \
> + res = e1; \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_ABS(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
> + MINVAL, MAXVAL) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (e1 == (MINVAL)) { \
> + res = (MAXVAL); \
> + sat = 1; \
> + } else if (e1 < 0) { \
> + res = -e1; \
> + } else { \
> + res = e1; \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SCALAR_ABS(NAME, RTYPE, STYPE, UTYPE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + STYPE value = (STYPE)rs1; \
> + UTYPE result = (UTYPE)value; \
> + \
> + if (value < 0) { \
> + result = (UTYPE)0 - result; \
> + } \
> + return (RTYPE)(STYPE)result; \
> +}
> +
> +#define GEN_PSIMD_VAR_SSHA(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + WTYPE shifted = (WTYPE)e1 << shamt; \
> + res = SAT_FN(shifted, &sat); \
> + } else { \
> + int right = -shamt; \
> + if (right >= (BITS)) { \
> + res = (e1 < 0) ? -1 : 0; \
> + } else { \
> + res = e1 >> right; \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_VAR_SSHAR(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_MIN, SAT_MAX, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + if (shamt >= (BITS)) { \
> + if (e1 == 0) { \
> + res = 0; \
> + } else if (e1 > 0) { \
> + res = (SAT_MAX); \
> + sat = 1; \
> + } else { \
> + res = (SAT_MIN); \
> + sat = 1; \
> + } \
> + } else { \
> + WTYPE shifted = (WTYPE)e1 * ((WTYPE)1 << shamt); \
> + res = SAT_FN(shifted, &sat); \
> + } \
> + } else { \
> + int right = -shamt; \
> + if (right >= (BITS)) { \
> + res = 0; \
> + } else { \
> + WTYPE rounded = ((e1 >> (right - 1)) + 1) >> 1; \
> + res = (ETYPE)rounded; \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_VAR_USHL(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + WTYPE shifted = (shamt >= (BITS)) ? \
> + ((WTYPE)e1 << (BITS)) : \
> + ((WTYPE)e1 << shamt); \
> + res = SAT_FN(shifted, &sat); \
> + } else { \
> + int right = -shamt; \
> + if (right >= (BITS)) { \
> + res = 0; \
> + } else { \
> + res = e1 >> right; \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_VAR_USHLR(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + WTYPE shifted = (shamt >= (BITS)) ? \
> + ((WTYPE)e1 << (BITS)) : \
> + ((WTYPE)e1 << shamt); \
> + res = SAT_FN(shifted, &sat); \
> + } else { \
> + int right = -shamt; \
> + if (right > (BITS)) { \
> + res = 0; \
> + } else { \
> + WTYPE rounded = ((WTYPE)e1 >> (right - 1)) + 1; \
> + res = (ETYPE)(rounded >> 1); \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define PSIMD_DO_SRA64(A, B) ((A) >> (B))
> +#define PSIMD_DO_RNDSRA64(A, B) \
> + ((int64_t)((((__int128_t)(A) >> ((B) - 1)) + 1) >> 1))
> +
> +#define GEN_PSIMD_VAR_SRA64(NAME, RIGHT_OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + int64_t a = (int64_t)rs1; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + if (shamt >= 0) { \
> + return (uint64_t)(a << shamt); \
> + } \
> + \
> + int right = -shamt; \
> + if (right >= 64) { \
> + return (a < 0) ? (uint64_t)-1 : 0; \
> + } \
> + return (uint64_t)RIGHT_OP(a, right); \
> +}
> +
> +#define PSIMD_DO_SRL64(A, B) (((B) >= 64) ? 0 : ((A) >> (B)))
> +#define PSIMD_DO_RNDSRL64(A, B) \
> + (((B) > 64) ? 0 : ((((A) >> ((B) - 1)) + 1) >> 1))
> +
> +#define GEN_PSIMD_VAR_SRL64(NAME, RIGHT_OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + if (shamt < 0) { \
> + return RIGHT_OP(rs1, -shamt); \
> + } \
> + return (shamt >= 64) ? 0 : (rs1 << shamt); \
> +}
> +
> +#define GEN_PSIMD_XPAIR_BINOP(NAME, RTYPE, ETYPE, EXTRACT, INSERT, \
> + ELEMS, OP_LO, OP_HI) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i += 2) { \
> + ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
> + ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
> + ETYPE res_lo = OP_LO(s1_lo, s2_hi); \
> + ETYPE res_hi = OP_HI(s1_hi, s2_lo); \
> + rd = INSERT(rd, res_lo, i); \
> + rd = INSERT(rd, res_hi, i + 1); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_XPAIR_SAT_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, \
> + INSERT, ELEMS, OP_LO, OP_HI, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i += 2) { \
> + ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
> + ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
> + WTYPE val_lo = OP_LO((WTYPE)s1_lo, (WTYPE)s2_hi); \
> + WTYPE val_hi = OP_HI((WTYPE)s1_hi, (WTYPE)s2_lo); \
> + ETYPE res_lo = SAT_FN(val_lo, &sat); \
> + ETYPE res_hi = SAT_FN(val_hi, &sat); \
> + rd = INSERT(rd, res_lo, i); \
> + rd = INSERT(rd, res_hi, i + 1); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_XPAIR_AVG_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, \
> + INSERT, ELEMS, OP_LO, OP_HI) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i += 2) { \
> + ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
> + ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
> + ETYPE res_lo = (ETYPE)(OP_LO((WTYPE)s1_lo, (WTYPE)s2_hi) >> 1); \
> + ETYPE res_hi = (ETYPE)(OP_HI((WTYPE)s1_hi, (WTYPE)s2_lo) >> 1); \
> + rd = INSERT(rd, res_lo, i); \
> + rd = INSERT(rd, res_hi, i + 1); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_REDSUM(NAME, RTYPE, SUMTYPE, ETYPE, EXTRACT, ELEMS, \
> + INIT) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + SUMTYPE sum = (INIT); \
> + int elems = ELEMS(rs1); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + sum += e1; \
> + } \
> + \
> + return (RTYPE)sum; \
> +}
> +
> +#define PSIMD_PAIR_LO(V, MASK, SHIFT) ((V) & (MASK))
> +#define PSIMD_PAIR_HI(V, MASK, SHIFT) (((V) >> (SHIFT)) & (MASK))
> +
> +#define GEN_PSIMD_PAIR_PACK(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
> + MASK, SHIFT, HI_SEL, LO_SEL) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = EXTRACT(rs1, i); \
> + ETYPE e2 = EXTRACT(rs2, i); \
> + ETYPE res = (HI_SEL(e2, MASK, SHIFT) << (SHIFT)) | \
> + LO_SEL(e1, MASK, SHIFT); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_PAIR_WORD(NAME, RS1_IDX, RS2_IDX) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint32_t e1 = EXTRACT32(rs1, RS1_IDX); \
> + uint32_t e2 = EXTRACT32(rs2, RS2_IDX); \
> + \
> + return ((uint64_t)e2 << 32) | e1; \
> +}
> +
> +#define GEN_PSIMD_SIGN_EXTEND(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
> + ELEMS, SCALE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + STYPE e1 = (STYPE)EXTRACT(rs1, i * (SCALE)); \
> + rd = INSERT(rd, (DTYPE)e1, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_ZIP(NAME, ETYPE, EXTRACT, ELEMS, BITS, START) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = EXTRACT(rs1, (START) - i); \
> + ETYPE e2 = EXTRACT(rs2, (START) - i); \
> + rd = (rd << (2 * (BITS))) | ((uint64_t)e2 << (BITS)) | e1; \
> + } \
> + \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_UNZIP(NAME, EXTRACT, ELEMS, BITS, OFFSET) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + uint64_t e1 = (uint64_t)EXTRACT(rs1, 2 * i + (OFFSET)) << \
> + ((BITS) * i); \
> + uint64_t e2 = (uint64_t)EXTRACT(rs2, 2 * i + (OFFSET)) << \
> + (32 + (BITS) * i); \
> + rd = rd | e2 | e1; \
> + } \
> + \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_BIT_SELECT(NAME, MASK, TRUE_VAL, FALSE_VAL) \
> +target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong rs1, \
> + target_ulong rs2, target_ulong rd) \
> +{ \
> + return (~(MASK) & (FALSE_VAL)) | ((MASK) & (TRUE_VAL)); \
> +}
> +
> +#define GEN_PSIMD_NCLIP_PACK(NAME, ITYPE, OTYPE, EXTRACT, INSERT, ELEMS, \
> + SAT_FN) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ITYPE lo = (ITYPE)EXTRACT(rs1, i); \
> + ITYPE hi = (ITYPE)EXTRACT(rs2, i); \
> + OTYPE res_lo = SAT_FN(lo, &sat); \
> + OTYPE res_hi = SAT_FN(hi, &sat); \
> + \
> + rd = (uint64_t)INSERT(rd, res_lo, i); \
> + rd = (uint64_t)INSERT(rd, res_hi, i + (ELEMS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_CLS(NAME, RTYPE, UTYPE, CLRSB) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + return CLRSB((UTYPE)rs1); \
> +}
> +
> +#define PSIMD_MUL_S32(A, B) ((int32_t)(A) * (int32_t)(B))
> +#define PSIMD_MUL_SU16(A, B) ((int16_t)(A) * (uint16_t)(B))
> +#define PSIMD_MUL_SU32(A, B) ((int32_t)(A) * (uint32_t)(B))
> +#define PSIMD_MUL_U32(A, B) ((uint32_t)(A) * (uint32_t)(B))
> +#define PSIMD_MUL_S64(A, B) ((int64_t)(A) * (int64_t)(B))
> +#define PSIMD_MUL_SU64(A, B) ((int64_t)(A) * (uint64_t)(B))
> +#define PSIMD_MUL_U64(A, B) ((uint64_t)(A) * (uint64_t)(B))
> +
> +#define GEN_PSIMD_MUL_HIGH(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, HTYPE, \
> + EXTRACT, INSERT, ELEMS, SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + rd = INSERT(rd, high, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_HIGH_SEL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
> + HTYPE, EXTRACT1, EXTRACT2, INSERT, ELEMS, \
> + SCALE, OFFSET, SHIFT, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT1(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT2(rs2, i * (SCALE) + (OFFSET)); \
> + PTYPE prod = OP(e1, e2); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + rd = INSERT(rd, high, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_ELEM_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
> + OTYPE, EXTRACT, INSERT, ELEMS, SCALE, \
> + OFFSET1, OFFSET2, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
> + PTYPE mul = OP(e1, e2); \
> + rd = INSERT(rd, (OTYPE)mul, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_ELEM_SCALAR(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
> + EXTRACT, OFFSET1, OFFSET2, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, OFFSET1); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, OFFSET2); \
> + PTYPE mul = OP(e1, e2); \
> + \
> + return (RTYPE)mul; \
> +}
> +
> +#define GEN_PSIMD_MUL_HIGH_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + HTYPE, OTYPE, EXTRACT, INSERT, ELEMS, \
> + SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + DTYPE d = (DTYPE)EXTRACT(dest, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + OTYPE res = (OTYPE)(high + d); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_HIGH_ACC_SEL(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
> + PTYPE, HTYPE, OTYPE, EXTRACT1, \
> + EXTRACT2, INSERT, ELEMS, SCALE, \
> + OFFSET, SHIFT, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT1(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT2(rs2, i * (SCALE) + (OFFSET)); \
> + DTYPE d = (DTYPE)EXTRACT1(dest, i); \
> + PTYPE prod = OP(e1, e2); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + OTYPE res = (OTYPE)(high + d); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_ACC_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
> + PTYPE, OTYPE, EXTRACT, EXTRACTD, \
> + INSERT, ELEMS, SCALE, OFFSET1, \
> + OFFSET2, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE mul = OP(e1, e2); \
> + rd = INSERT(rd, (OTYPE)(d + mul), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_QMUL(NAME, RTYPE, ETYPE, PTYPE, OTYPE, EXTRACT, INSERT, \
> + ELEMS, SHIFT, ROUND, MINVAL, MAXVAL) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + OTYPE result; \
> + \
> + if ((e1 == (ETYPE)(MINVAL)) && (e2 == (ETYPE)(MINVAL))) { \
> + sat = 1; \
> + result = (OTYPE)(MAXVAL); \
> + } else { \
> + PTYPE prod = (PTYPE)e1 * (PTYPE)e2 + (ROUND); \
> + result = (OTYPE)(prod >> (SHIFT)); \
> + } \
> + rd = INSERT(rd, result, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_QMUL_ACC_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
> + PTYPE, STYPE, OTYPE, EXTRACT, \
> + EXTRACTD, INSERT, ELEMS, SCALE, \
> + OFFSET1, OFFSET2, SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + STYPE scaled = (STYPE)(((__int128_t)prod) >> (SHIFT)); \
> + rd = INSERT(rd, (OTYPE)(d + scaled), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_Q2ADD(NAME, RTYPE, ETYPE, PTYPE, STYPE, OTYPE, EXTRACT, \
> + INSERT, ELEMS, SCALE, SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE s1_0 = (ETYPE)EXTRACT(rs1, i * (SCALE)); \
> + ETYPE s1_1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + 1); \
> + ETYPE s2_0 = (ETYPE)EXTRACT(rs2, i * (SCALE)); \
> + ETYPE s2_1 = (ETYPE)EXTRACT(rs2, i * (SCALE) + 1); \
> + PTYPE prod0 = OP(s1_0, s2_0) + (ROUND); \
> + PTYPE prod1 = OP(s1_1, s2_1) + (ROUND); \
> + STYPE scaled0 = (STYPE)(((__int128_t)prod0) >> (SHIFT)); \
> + STYPE scaled1 = (STYPE)(((__int128_t)prod1) >> (SHIFT)); \
> + rd = INSERT(rd, (OTYPE)(scaled0 + scaled1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_Q2ADDA(NAME, RTYPE, ETYPE, DTYPE, PTYPE, STYPE, OTYPE, \
> + EXTRACT, EXTRACTD, INSERT, ELEMS, SCALE, \
> + SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE s1_0 = (ETYPE)EXTRACT(rs1, i * (SCALE)); \
> + ETYPE s1_1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + 1); \
> + ETYPE s2_0 = (ETYPE)EXTRACT(rs2, i * (SCALE)); \
> + ETYPE s2_1 = (ETYPE)EXTRACT(rs2, i * (SCALE) + 1); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod0 = OP(s1_0, s2_0) + (ROUND); \
> + PTYPE prod1 = OP(s1_1, s2_1) + (ROUND); \
> + STYPE scaled0 = (STYPE)(((__int128_t)prod0) >> (SHIFT)); \
> + STYPE scaled1 = (STYPE)(((__int128_t)prod1) >> (SHIFT)); \
> + rd = INSERT(rd, (OTYPE)(d + scaled0 + scaled1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define PSIMD_COMB_ADD(D, A, B) ((D) + (A) + (B))
> +#define PSIMD_COMB_SUB(D, A, B) ((D) + (A) - (B))
> +
> +#define GEN_PSIMD_2WAY_MUL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, OTYPE, \
> + EXTRACT, INSERT, ELEMS, SCALE, OFFSET10, \
> + OFFSET11, OFFSET20, OFFSET21, OP, COMBINE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET10)); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET11)); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET20)); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET21)); \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + rd = INSERT(rd, (OTYPE)COMBINE(0, prod0, prod1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_2WAY_SAT_MUL(NAME, OFFSET10, OFFSET11, OFFSET20, \
> + OFFSET21) \
> +target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong rs1, \
> + target_ulong rs2) \
> +{ \
> + target_ulong rd = 0; \
> + int sat = 0; \
> + \
> + for (int i = 0; i < ELEMS_W(rd); i++) { \
> + int16_t s1_0 = (int16_t)EXTRACT16(rs1, i * 2 + (OFFSET10)); \
> + int16_t s1_1 = (int16_t)EXTRACT16(rs1, i * 2 + (OFFSET11)); \
> + int16_t s2_0 = (int16_t)EXTRACT16(rs2, i * 2 + (OFFSET20)); \
> + int16_t s2_1 = (int16_t)EXTRACT16(rs2, i * 2 + (OFFSET21)); \
> + uint32_t result; \
> + \
> + if (s1_0 == INT16_MIN && s1_1 == INT16_MIN && \
> + s2_0 == INT16_MIN && s2_1 == INT16_MIN) { \
> + result = INT32_MAX; \
> + sat = 1; \
> + } else { \
> + int32_t prod0 = (int32_t)s1_0 * s2_0; \
> + int32_t prod1 = (int32_t)s1_1 * s2_1; \
> + result = (uint32_t)(prod0 + prod1); \
> + } \
> + rd = INSERT32(rd, result, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_2WAY_MUL_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + OTYPE, EXTRACT, EXTRACTD, INSERT, ELEMS, \
> + SCALE, OFFSET10, OFFSET11, OFFSET20, \
> + OFFSET21, OP, COMBINE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET10)); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET11)); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET20)); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET21)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + rd = INSERT(rd, (OTYPE)COMBINE(d, prod0, prod1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_4WAY_MUL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, OTYPE, \
> + EXTRACT, INSERT, ELEMS, SCALE, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + PTYPE prod0 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE)), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE))); \
> + PTYPE prod1 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 1), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 1)); \
> + PTYPE prod2 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 2), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 2)); \
> + PTYPE prod3 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 3), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 3)); \
> + rd = INSERT(rd, (OTYPE)(prod0 + prod1 + prod2 + prod3), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_4WAY_MUL_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + OTYPE, EXTRACT, EXTRACTD, INSERT, ELEMS, \
> + SCALE, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod0 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE)), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE))); \
> + PTYPE prod1 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 1), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 1)); \
> + PTYPE prod2 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 2), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 2)); \
> + PTYPE prod3 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 3), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 3)); \
> + rd = INSERT(rd, (OTYPE)(d + prod0 + prod1 + prod2 + prod3), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_BINOP(NAME, ETYPE, WTYPE, OTYPE, ELEMS, IBITS, \
> + OBITS, IMASK, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
> + ETYPE e2 = (ETYPE)((rs2 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE res = OP((WTYPE)0, (WTYPE)e1, (WTYPE)e2); \
> + rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_BINOP_ACC(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, OMASK, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
> + ETYPE e2 = (ETYPE)((rs2 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE acc = (WTYPE)((dest >> (i * (OBITS))) & (OMASK)); \
> + WTYPE res = OP(acc, (WTYPE)e1, (WTYPE)e2); \
> + rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_MUL(NAME, E1TYPE, E2TYPE, PTYPE, OTYPE, ELEMS, \
> + EXTRACT, OBITS, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + PTYPE prod = OP(e1, e2); \
> + rd |= ((uint64_t)(OTYPE)prod) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_MUL_ACC(NAME, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + OTYPE, ELEMS, EXTRACT, EXTRACTD, OBITS, \
> + OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod = OP(e1, e2); \
> + rd |= ((uint64_t)(OTYPE)(d + prod)) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_QMUL_ACC(NAME, ETYPE, DTYPE, PTYPE, STYPE, \
> + OTYPE, ELEMS, EXTRACT, EXTRACTD, SCALE, \
> + OFFSET, SHIFT, ROUND, OBITS, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET)); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + STYPE scaled = (STYPE)(((__int128_t)prod) >> (SHIFT)); \
> + rd |= ((uint64_t)(OTYPE)(d + scaled)) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_DW_2WAY_MUL(NAME, E1TYPE, E2TYPE, PTYPE, EXTRACT, \
> + OFFSET10, OFFSET11, OFFSET20, OFFSET21, \
> + OP, COMBINE) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, OFFSET10); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, OFFSET11); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, OFFSET20); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, OFFSET21); \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + \
> + return (uint64_t)COMBINE(0, prod0, prod1); \
> +}
> +
> +#define GEN_PSIMD_DW_2WAY_MUL_ACC(NAME, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + EXTRACT, OFFSET10, OFFSET11, OFFSET20, \
> + OFFSET21, OP, COMBINE) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, OFFSET10); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, OFFSET11); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, OFFSET20); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, OFFSET21); \
> + DTYPE d = (DTYPE)dest; \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + \
> + return (uint64_t)COMBINE(d, prod0, prod1); \
> +}
> +
> +#define GEN_PSIMD_WIDEN_SHIFT(NAME, ETYPE, WTYPE, OTYPE, ELEMS, IBITS, \
> + OBITS, IMASK, SHMASK) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE res = (WTYPE)e1 << shamt; \
> + rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_DW_ZIP(NAME, EXTRACT, ELEMS, STRIDE, BITS) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + uint64_t e1 = (uint64_t)EXTRACT(rs1, i) << ((STRIDE) * i); \
> + uint64_t e2 = (uint64_t)EXTRACT(rs2, i) \
> + << ((STRIDE) * i + (BITS)); \
> + rd |= e2 | e1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_DW_REDSUM(NAME, SUMTYPE, INITTYPE, ETYPE, EXTRACT, \
> + ELEMS) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1_lo, \
> + uint32_t rs1_hi, uint32_t rs2) \
> +{ \
> + SUMTYPE sum = (INITTYPE)rs2; \
> + uint64_t s1 = ((uint64_t)rs1_hi << 32) | rs1_lo; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + sum += (ETYPE)EXTRACT(s1, i); \
> + } \
> + return (uint32_t)sum; \
> +}
> +
> +#define GEN_PSIMD_NARROW_SRL(NAME, ETYPE, OTYPE, ELEMS, IBITS, OBITS, \
> + IMASK, SHMASK) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + OTYPE result = (OTYPE)(e1 >> shift); \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NARROW_SRA_PACK(NAME, ETYPE, STYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + STYPE shx = (STYPE)e1 >> shift; \
> + OTYPE result = (OTYPE)shx; \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NARROW_RNDSRA_PACK(NAME, ETYPE, STYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK, RMASK) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + STYPE e1_s = (STYPE)e1; \
> + uint64_t shx = (((uint64_t)e1_s << 1) >> shift) & (RMASK); \
> + OTYPE result = (OTYPE)((shx + 1) >> 1); \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIP_SIGNED_PACK(NAME, ETYPE, STYPE, CTYPE, OTYPE, \
> + ELEMS, IBITS, OBITS, IMASK, SHMASK, \
> + MIN, MAX, MIN_RES, MAX_RES) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + CTYPE shx = (CTYPE)((STYPE)e1 >> shift); \
> + OTYPE result; \
> + \
> + if (shx < (MIN)) { \
> + sat = 1; \
> + result = (MIN_RES); \
> + } else if (shx > (MAX)) { \
> + sat = 1; \
> + result = (MAX_RES); \
> + } else { \
> + result = (OTYPE)shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIPR_SIGNED_PACK(NAME, ETYPE, STYPE, CTYPE, OTYPE, \
> + ELEMS, IBITS, OBITS, IMASK, SHMASK, \
> + RMASK, MIN, MAX, MIN_RES, MAX_RES) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + STYPE e1_s = (STYPE)e1; \
> + uint64_t shx = (((uint64_t)e1_s << 1) >> shift) & (RMASK); \
> + CTYPE round_shx = (CTYPE)((shx + 1) >> 1); \
> + OTYPE result; \
> + \
> + if (round_shx < (MIN)) { \
> + sat = 1; \
> + result = (MIN_RES); \
> + } else if (round_shx > (MAX)) { \
> + sat = 1; \
> + result = (MAX_RES); \
> + } else { \
> + result = (OTYPE)round_shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIP_UNSIGNED_PACK(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK, MAX) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE shx = (WTYPE)e1 >> shift; \
> + OTYPE result; \
> + \
> + if (shx > (MAX)) { \
> + sat = 1; \
> + result = (OTYPE)(MAX); \
> + } else { \
> + result = (OTYPE)shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIPR_UNSIGNED_PACK(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK, MAX) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE shx = ((WTYPE)e1 << 1) >> shift; \
> + WTYPE round_shx = (shx + 1) >> 1; \
> + OTYPE result; \
> + \
> + if (round_shx > (MAX)) { \
> + sat = 1; \
> + result = (OTYPE)(MAX); \
> + } else { \
> + result = (OTYPE)round_shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NARROW_SRA(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + __int128_t s1_s96 = (s1_s128 << 32) >> 32; \
> + \
> + return (uint32_t)(s1_s96 >> (shamt & 0x3F)) & 0xFFFFFFFF; \
> +}
> +
> +#define GEN_PSIMD_NARROW_RNDSRA(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + __int128_t s1_s96 = (s1_s128 << 32) >> 32; \
> + __uint128_t shx_97bit = ((__uint128_t)s1_s96 << 1); \
> + uint64_t shx = (uint64_t)(shx_97bit >> (shamt & 0x3F)) & 0x1FFFFFFFF; \
> + \
> + return (uint32_t)((shx + 1) >> 1); \
> +}
> +
> +#define GEN_PSIMD_NARROW_ALIAS(NAME, TARGET) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + return HELPER(TARGET)(env, s1, shamt); \
> +}
> +
> +typedef struct {
> + __uint128_t low;
> + uint8_t high;
> +} PsImdUint129;
> +
> +static inline PsImdUint129 psimd_uint129_lshift1(__int128_t val)
> +{
> + PsImdUint129 result;
> + __uint128_t uval = (__uint128_t)val;
> +
> + result.low = uval << 1;
> + result.high = (uval >> 127) & 0x1;
> + return result;
> +}
> +
> +static inline PsImdUint129 psimd_uint129_rshift(PsImdUint129 val,
> + uint32_t shamt)
> +{
> + PsImdUint129 result;
> +
> + if (shamt == 0) {
> + return val;
> + } else if (shamt >= 129) {
> + result.low = 0;
> + result.high = 0;
> + } else if (shamt == 128) {
> + result.low = val.high;
> + result.high = 0;
> + } else {
> + result.low = (val.low >> shamt) |
> + ((__uint128_t)val.high << (128 - shamt));
> + result.high = val.high >> shamt;
> + }
> + return result;
> +}
> +
> +#define GEN_PSIMD_NCLIP(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + int64_t shx = (int64_t)(s1_s128 >> (shamt & 0x3F)); \
> + \
> + if (shx < -2147483648LL) { \
> + env->vxsat = 1; \
> + return 0x80000000U; \
> + } else if (shx > 2147483647LL) { \
> + env->vxsat = 1; \
> + return 0x7FFFFFFFU; \
> + } else { \
> + return (uint32_t)(shx & 0xFFFFFFFF); \
> + } \
> +}
> +
> +#define GEN_PSIMD_NCLIPR(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + PsImdUint129 shx_129bit = psimd_uint129_lshift1(s1_s128); \
> + PsImdUint129 shx = psimd_uint129_rshift(shx_129bit, shamt & 0x3F); \
> + int64_t round_shx = (int64_t)((shx.low + 1) >> 1); \
> + \
> + if (round_shx < -2147483648LL) { \
> + env->vxsat = 1; \
> + return 0x80000000U; \
> + } else if (round_shx > 2147483647LL) { \
> + env->vxsat = 1; \
> + return 0x7FFFFFFFU; \
> + } else { \
> + return (uint32_t)round_shx; \
> + } \
> +}
> +
> +#define GEN_PSIMD_NCLIPU(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint64_t shx = s1 >> (shamt & 0x3F); \
> + \
> + if (shx > 4294967295ULL) { \
> + env->vxsat = 1; \
> + return 0xFFFFFFFFU; \
> + } else { \
> + return (uint32_t)(shx & 0xFFFFFFFF); \
> + } \
> +}
> +
> +#define GEN_PSIMD_NCLIPRU(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __uint128_t shx_65bit = (__uint128_t)s1 << 1; \
> + __uint128_t shx = shx_65bit >> (shamt & 0x3F); \
> + uint64_t round_shx = (shx + 1) >> 1; \
> + \
> + if (round_shx > 4294967295ULL) { \
> + env->vxsat = 1; \
> + return 0xFFFFFFFFU; \
> + } else { \
> + return (uint32_t)(round_shx & 0xFFFFFFFF); \
> + } \
> +}
> +
> +/* Basic addition operations (non-saturating) */
> +
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework
2026-07-17 10:06 ` [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework Molly Chen
2026-07-26 19:53 ` Daniel Henrique Barboza
@ 2026-07-27 6:16 ` Nutty.Liu
2026-07-29 9:01 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Nutty.Liu @ 2026-07-27 6:16 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, daniel.barboza,
zhiwei_liu, chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel
On 7/17/2026 6:06 PM, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
It would be better to add some description for this series.
Otherwise,
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> ---
> target/riscv/tcg/meson.build | 3 +-
> target/riscv/tcg/psimd_helper.c | 1656 +++++++++++++++++++++++++++++++
> 2 files changed, 1658 insertions(+), 1 deletion(-)
> create mode 100644 target/riscv/tcg/psimd_helper.c
>
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> index a05ab642f41..cc438d7c0d2 100644
> --- a/target/riscv/tcg/meson.build
> +++ b/target/riscv/tcg/meson.build
> @@ -15,7 +15,8 @@ riscv_ss.add(files(
> 'vcrypto_helper.c',
> 'vector_helper.c',
> 'vector_internals.c',
> - 'zce_helper.c'))
> + 'zce_helper.c',
> + 'psimd_helper.c'))
>
>
> riscv_system_ss.add(files(
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> new file mode 100644
> index 00000000000..2948bbb2a86
> --- /dev/null
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -0,0 +1,1656 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* RISC-V Packed SIMD Extension Helpers for QEMU. */
> +/* Copyright (C) 2026 ISRC ISCAS. */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "qemu/host-utils.h"
> +#include "exec/helper-proto.h"
> +#include "fpu/softfloat.h"
> +#include "internals.h"
> +
> +
> +/* Helper macros */
> +
> +/* Element count calculations */
> +#define ELEMS_B(target) (sizeof(target) * 8 / 8) /* byte elements count */
> +#define ELEMS_H(target) (sizeof(target) * 8 / 16)
> +#define ELEMS_W(target) (sizeof(target) * 8 / 32) /* word elements count */
> +#define ELEMS_D(target) (sizeof(target) * 8 / 64)
> +
> +/* Element extraction macros - unsigned to avoid sign extension */
> +#define EXTRACT8(val, idx) (((val) >> ((idx) * 8)) & 0xFF)
> +#define EXTRACT16(val, idx) (((val) >> ((idx) * 16)) & 0xFFFF)
> +#define EXTRACT32(val, idx) (((val) >> ((idx) * 32)) & 0xFFFFFFFF)
> +#define EXTRACT64(val, idx) (((val) >> ((idx) * 64)) & 0xFFFFFFFFFFFFFFFFULL)
> +
> +/* Element insertion macros */
> +#define INSERT8(val, res, idx) \
> + ((val) | ((target_ulong)(uint8_t)(res) << ((idx) * 8)))
> +#define INSERT16(val, res, idx) \
> + ((val) | ((target_ulong)(uint16_t)(res) << ((idx) * 16)))
> +#define INSERT32(val, res, idx) \
> + ((val) | ((target_ulong)(uint32_t)(res) << ((idx) * 32)))
> +#define INSERT32_64(val, res, idx) \
> + ((val) | ((uint64_t)(uint32_t)(res) << ((idx) * 32)))
> +#define INSERT64(val, res, idx) \
> + ((val) | ((uint64_t)(res) << ((idx) * 64)))
> +
> +/* Saturation constants */
> +static const int8_t SAT_MAX_B = 127;
> +static const int8_t SAT_MIN_B = -128;
> +static const int16_t SAT_MAX_H = 32767;
> +static const int16_t SAT_MIN_H = -32768;
> +static const int32_t SAT_MAX_W = 2147483647;
> +static const int32_t SAT_MIN_W = -2147483648LL;
> +static const uint8_t USAT_MAX_B = 255;
> +static const uint16_t USAT_MAX_H = 65535;
> +static const uint32_t USAT_MAX_W = 4294967295U;
> +
> +
> +/* Saturation helper functions */
> +
> +/**
> + * Signed saturation for 8-bit elements
> + * Returns saturated value and sets *sat if saturation occurred
> + */
> +static inline int8_t signed_saturate_b(int32_t val, int *sat)
> +{
> + if (val > SAT_MAX_B) {
> + *sat = 1;
> + return SAT_MAX_B;
> + }
> + if (val < SAT_MIN_B) {
> + *sat = 1;
> + return SAT_MIN_B;
> + }
> + return (int8_t)val;
> +}
> +
> +/**
> + * Signed saturation for 16-bit elements
> + */
> +static inline int16_t signed_saturate_h(int32_t val, int *sat)
> +{
> + if (val > SAT_MAX_H) {
> + *sat = 1;
> + return SAT_MAX_H;
> + }
> + if (val < SAT_MIN_H) {
> + *sat = 1;
> + return SAT_MIN_H;
> + }
> + return (int16_t)val;
> +}
> +
> +/**
> + * Signed saturation for 32-bit elements
> + */
> +static inline int32_t signed_saturate_w(int64_t val, int *sat)
> +{
> + if (val > SAT_MAX_W) {
> + *sat = 1;
> + return SAT_MAX_W;
> + }
> + if (val < SAT_MIN_W) {
> + *sat = 1;
> + return SAT_MIN_W;
> + }
> + return (int32_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 8-bit elements
> + */
> +static inline uint8_t unsigned_saturate_b(uint32_t val, int *sat)
> +{
> + if (val > USAT_MAX_B) {
> + *sat = 1;
> + return USAT_MAX_B;
> + }
> + return (uint8_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 16-bit elements
> + */
> +static inline uint16_t unsigned_saturate_h(uint32_t val, int *sat)
> +{
> + if (val > USAT_MAX_H) {
> + *sat = 1;
> + return USAT_MAX_H;
> + }
> + return (uint16_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 32-bit elements
> + */
> +static inline uint32_t unsigned_saturate_w(uint64_t val, int *sat)
> +{
> + if (val > USAT_MAX_W) {
> + *sat = 1;
> + return USAT_MAX_W;
> + }
> + return (uint32_t)val;
> +}
> +
> +static inline target_ulong psimd_abdsumu_b(target_ulong rs1,
> + target_ulong rs2,
> + target_ulong sum)
> +{
> + int elems = ELEMS_B(rs1);
> +
> + for (int i = 0; i < elems; i++) {
> + uint8_t e1 = EXTRACT8(rs1, i);
> + uint8_t e2 = EXTRACT8(rs2, i);
> + uint8_t diff = (e1 > e2) ? (e1 - e2) : (e2 - e1);
> + sum += diff;
> + }
> +
> + return sum;
> +}
> +
> +#define PSIMD_DO_ADD(N, M) ((N) + (M))
> +#define PSIMD_DO_SUB(N, M) ((N) - (M))
> +#define PSIMD_DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
> +#define PSIMD_DO_EQ_MASK(N, M) ((N) == (M) ? -1 : 0)
> +#define PSIMD_DO_LT_MASK(N, M) ((N) < (M) ? -1 : 0)
> +#define PSIMD_DO_MIN(N, M) ((N) < (M) ? (N) : (M))
> +#define PSIMD_DO_MAX(N, M) ((N) > (M) ? (N) : (M))
> +#define PSIMD_DO_SLL(N, M) ((N) << (M))
> +#define PSIMD_DO_SRL(N, M) ((N) >> (M))
> +#define PSIMD_DO_SRA(N, M) ((N) >> (M))
> +
> +#define GEN_PSIMD_BINOP(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
> + ELEMS, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + STYPE e1 = (STYPE)EXTRACT(rs1, i); \
> + STYPE e2 = (STYPE)EXTRACT(rs2, i); \
> + DTYPE res = (DTYPE)OP(e1, e2); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_BINOP_SCALAR(NAME, RTYPE, ETYPE, EXTRACT, INSERT, \
> + ELEMS, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, 0); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res = OP(e1, e2); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SHIFTOP(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
> + ELEMS, SHMASK, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + STYPE e1 = (STYPE)EXTRACT(rs1, i); \
> + DTYPE res = (DTYPE)OP(e1, shamt); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SAT_SHIFTOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, SHMASK, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + WTYPE shifted = (WTYPE)e1 << shamt; \
> + ETYPE res = SAT_FN(shifted, &sat); \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_ROUND_SRAI(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, SHMASK) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + if (shamt == 0) { \
> + return rs1; \
> + } \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + WTYPE rounded = (((WTYPE)e1 >> (shamt - 1)) + 1) >> 1; \
> + rd = INSERT(rd, (ETYPE)rounded, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SAT_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, OP, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + WTYPE val = OP((WTYPE)e1, (WTYPE)e2); \
> + ETYPE res = SAT_FN(val, &sat); \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_USUB_SAT(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE res = (e1 >= e2) ? (e1 - e2) : 0; \
> + if (e1 < e2) { \
> + sat = 1; \
> + } \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_AVG_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + WTYPE e1 = (WTYPE)(ETYPE)EXTRACT(rs1, i); \
> + WTYPE e2 = (WTYPE)(ETYPE)EXTRACT(rs2, i); \
> + ETYPE res = (ETYPE)(OP(e1, e2) >> 1); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SHADD(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
> + SHAMT) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE res = (e1 << (SHAMT)) + e2; \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SAT_SHADD(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, SHAMT, SH_MIN, SH_MAX, SAT_MIN, \
> + SAT_MAX, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + WTYPE shifted; \
> + \
> + if (e1 > (SH_MAX) || e1 < (SH_MIN)) { \
> + shifted = (e1 < 0) ? (SAT_MIN) : (SAT_MAX); \
> + sat = 1; \
> + } else { \
> + shifted = (WTYPE)e1 << (SHAMT); \
> + } \
> + \
> + WTYPE sum = shifted + e2; \
> + ETYPE res = SAT_FN(sum, &sat); \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SATI(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, IMMMASK) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE imm) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int range = (imm & (IMMMASK)) + 1; \
> + WTYPE max = ((WTYPE)1 << (range - 1)) - 1; \
> + WTYPE min = -((WTYPE)1 << (range - 1)); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (e1 > max) { \
> + res = max; \
> + sat = 1; \
> + } else if (e1 < min) { \
> + res = min; \
> + sat = 1; \
> + } else { \
> + res = e1; \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_USATI(NAME, RTYPE, ETYPE, UTYPE, WTYPE, EXTRACT, \
> + INSERT, ELEMS, ONE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE imm) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + WTYPE max = ((WTYPE)(ONE) << imm) - 1; \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (e1 < 0) { \
> + res = 0; \
> + sat = 1; \
> + } else if ((UTYPE)e1 > max) { \
> + res = max; \
> + sat = 1; \
> + } else { \
> + res = e1; \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_ABS(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
> + MINVAL, MAXVAL) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (e1 == (MINVAL)) { \
> + res = (MAXVAL); \
> + sat = 1; \
> + } else if (e1 < 0) { \
> + res = -e1; \
> + } else { \
> + res = e1; \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_SCALAR_ABS(NAME, RTYPE, STYPE, UTYPE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + STYPE value = (STYPE)rs1; \
> + UTYPE result = (UTYPE)value; \
> + \
> + if (value < 0) { \
> + result = (UTYPE)0 - result; \
> + } \
> + return (RTYPE)(STYPE)result; \
> +}
> +
> +#define GEN_PSIMD_VAR_SSHA(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + WTYPE shifted = (WTYPE)e1 << shamt; \
> + res = SAT_FN(shifted, &sat); \
> + } else { \
> + int right = -shamt; \
> + if (right >= (BITS)) { \
> + res = (e1 < 0) ? -1 : 0; \
> + } else { \
> + res = e1 >> right; \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_VAR_SSHAR(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_MIN, SAT_MAX, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + if (shamt >= (BITS)) { \
> + if (e1 == 0) { \
> + res = 0; \
> + } else if (e1 > 0) { \
> + res = (SAT_MAX); \
> + sat = 1; \
> + } else { \
> + res = (SAT_MIN); \
> + sat = 1; \
> + } \
> + } else { \
> + WTYPE shifted = (WTYPE)e1 * ((WTYPE)1 << shamt); \
> + res = SAT_FN(shifted, &sat); \
> + } \
> + } else { \
> + int right = -shamt; \
> + if (right >= (BITS)) { \
> + res = 0; \
> + } else { \
> + WTYPE rounded = ((e1 >> (right - 1)) + 1) >> 1; \
> + res = (ETYPE)rounded; \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_VAR_USHL(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + WTYPE shifted = (shamt >= (BITS)) ? \
> + ((WTYPE)e1 << (BITS)) : \
> + ((WTYPE)e1 << shamt); \
> + res = SAT_FN(shifted, &sat); \
> + } else { \
> + int right = -shamt; \
> + if (right >= (BITS)) { \
> + res = 0; \
> + } else { \
> + res = e1 >> right; \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_VAR_USHLR(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, INSERT, \
> + ELEMS, BITS, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE res; \
> + \
> + if (shamt >= 0) { \
> + WTYPE shifted = (shamt >= (BITS)) ? \
> + ((WTYPE)e1 << (BITS)) : \
> + ((WTYPE)e1 << shamt); \
> + res = SAT_FN(shifted, &sat); \
> + } else { \
> + int right = -shamt; \
> + if (right > (BITS)) { \
> + res = 0; \
> + } else { \
> + WTYPE rounded = ((WTYPE)e1 >> (right - 1)) + 1; \
> + res = (ETYPE)(rounded >> 1); \
> + } \
> + } \
> + \
> + rd = INSERT(rd, res, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define PSIMD_DO_SRA64(A, B) ((A) >> (B))
> +#define PSIMD_DO_RNDSRA64(A, B) \
> + ((int64_t)((((__int128_t)(A) >> ((B) - 1)) + 1) >> 1))
> +
> +#define GEN_PSIMD_VAR_SRA64(NAME, RIGHT_OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + int64_t a = (int64_t)rs1; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + if (shamt >= 0) { \
> + return (uint64_t)(a << shamt); \
> + } \
> + \
> + int right = -shamt; \
> + if (right >= 64) { \
> + return (a < 0) ? (uint64_t)-1 : 0; \
> + } \
> + return (uint64_t)RIGHT_OP(a, right); \
> +}
> +
> +#define PSIMD_DO_SRL64(A, B) (((B) >= 64) ? 0 : ((A) >> (B)))
> +#define PSIMD_DO_RNDSRL64(A, B) \
> + (((B) > 64) ? 0 : ((((A) >> ((B) - 1)) + 1) >> 1))
> +
> +#define GEN_PSIMD_VAR_SRL64(NAME, RIGHT_OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + if (shamt < 0) { \
> + return RIGHT_OP(rs1, -shamt); \
> + } \
> + return (shamt >= 64) ? 0 : (rs1 << shamt); \
> +}
> +
> +#define GEN_PSIMD_XPAIR_BINOP(NAME, RTYPE, ETYPE, EXTRACT, INSERT, \
> + ELEMS, OP_LO, OP_HI) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i += 2) { \
> + ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
> + ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
> + ETYPE res_lo = OP_LO(s1_lo, s2_hi); \
> + ETYPE res_hi = OP_HI(s1_hi, s2_lo); \
> + rd = INSERT(rd, res_lo, i); \
> + rd = INSERT(rd, res_hi, i + 1); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_XPAIR_SAT_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, \
> + INSERT, ELEMS, OP_LO, OP_HI, SAT_FN) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i += 2) { \
> + ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
> + ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
> + WTYPE val_lo = OP_LO((WTYPE)s1_lo, (WTYPE)s2_hi); \
> + WTYPE val_hi = OP_HI((WTYPE)s1_hi, (WTYPE)s2_lo); \
> + ETYPE res_lo = SAT_FN(val_lo, &sat); \
> + ETYPE res_hi = SAT_FN(val_hi, &sat); \
> + rd = INSERT(rd, res_lo, i); \
> + rd = INSERT(rd, res_hi, i + 1); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_XPAIR_AVG_BINOP(NAME, RTYPE, ETYPE, WTYPE, EXTRACT, \
> + INSERT, ELEMS, OP_LO, OP_HI) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i += 2) { \
> + ETYPE s1_lo = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE s1_hi = (ETYPE)EXTRACT(rs1, i + 1); \
> + ETYPE s2_lo = (ETYPE)EXTRACT(rs2, i); \
> + ETYPE s2_hi = (ETYPE)EXTRACT(rs2, i + 1); \
> + ETYPE res_lo = (ETYPE)(OP_LO((WTYPE)s1_lo, (WTYPE)s2_hi) >> 1); \
> + ETYPE res_hi = (ETYPE)(OP_HI((WTYPE)s1_hi, (WTYPE)s2_lo) >> 1); \
> + rd = INSERT(rd, res_lo, i); \
> + rd = INSERT(rd, res_hi, i + 1); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_REDSUM(NAME, RTYPE, SUMTYPE, ETYPE, EXTRACT, ELEMS, \
> + INIT) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + SUMTYPE sum = (INIT); \
> + int elems = ELEMS(rs1); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + sum += e1; \
> + } \
> + \
> + return (RTYPE)sum; \
> +}
> +
> +#define PSIMD_PAIR_LO(V, MASK, SHIFT) ((V) & (MASK))
> +#define PSIMD_PAIR_HI(V, MASK, SHIFT) (((V) >> (SHIFT)) & (MASK))
> +
> +#define GEN_PSIMD_PAIR_PACK(NAME, RTYPE, ETYPE, EXTRACT, INSERT, ELEMS, \
> + MASK, SHIFT, HI_SEL, LO_SEL) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = EXTRACT(rs1, i); \
> + ETYPE e2 = EXTRACT(rs2, i); \
> + ETYPE res = (HI_SEL(e2, MASK, SHIFT) << (SHIFT)) | \
> + LO_SEL(e1, MASK, SHIFT); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_PAIR_WORD(NAME, RS1_IDX, RS2_IDX) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint32_t e1 = EXTRACT32(rs1, RS1_IDX); \
> + uint32_t e2 = EXTRACT32(rs2, RS2_IDX); \
> + \
> + return ((uint64_t)e2 << 32) | e1; \
> +}
> +
> +#define GEN_PSIMD_SIGN_EXTEND(NAME, RTYPE, STYPE, DTYPE, EXTRACT, INSERT, \
> + ELEMS, SCALE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + STYPE e1 = (STYPE)EXTRACT(rs1, i * (SCALE)); \
> + rd = INSERT(rd, (DTYPE)e1, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_ZIP(NAME, ETYPE, EXTRACT, ELEMS, BITS, START) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = EXTRACT(rs1, (START) - i); \
> + ETYPE e2 = EXTRACT(rs2, (START) - i); \
> + rd = (rd << (2 * (BITS))) | ((uint64_t)e2 << (BITS)) | e1; \
> + } \
> + \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_UNZIP(NAME, EXTRACT, ELEMS, BITS, OFFSET) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + uint64_t e1 = (uint64_t)EXTRACT(rs1, 2 * i + (OFFSET)) << \
> + ((BITS) * i); \
> + uint64_t e2 = (uint64_t)EXTRACT(rs2, 2 * i + (OFFSET)) << \
> + (32 + (BITS) * i); \
> + rd = rd | e2 | e1; \
> + } \
> + \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_BIT_SELECT(NAME, MASK, TRUE_VAL, FALSE_VAL) \
> +target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong rs1, \
> + target_ulong rs2, target_ulong rd) \
> +{ \
> + return (~(MASK) & (FALSE_VAL)) | ((MASK) & (TRUE_VAL)); \
> +}
> +
> +#define GEN_PSIMD_NCLIP_PACK(NAME, ITYPE, OTYPE, EXTRACT, INSERT, ELEMS, \
> + SAT_FN) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ITYPE lo = (ITYPE)EXTRACT(rs1, i); \
> + ITYPE hi = (ITYPE)EXTRACT(rs2, i); \
> + OTYPE res_lo = SAT_FN(lo, &sat); \
> + OTYPE res_hi = SAT_FN(hi, &sat); \
> + \
> + rd = (uint64_t)INSERT(rd, res_lo, i); \
> + rd = (uint64_t)INSERT(rd, res_hi, i + (ELEMS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_CLS(NAME, RTYPE, UTYPE, CLRSB) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + return CLRSB((UTYPE)rs1); \
> +}
> +
> +#define PSIMD_MUL_S32(A, B) ((int32_t)(A) * (int32_t)(B))
> +#define PSIMD_MUL_SU16(A, B) ((int16_t)(A) * (uint16_t)(B))
> +#define PSIMD_MUL_SU32(A, B) ((int32_t)(A) * (uint32_t)(B))
> +#define PSIMD_MUL_U32(A, B) ((uint32_t)(A) * (uint32_t)(B))
> +#define PSIMD_MUL_S64(A, B) ((int64_t)(A) * (int64_t)(B))
> +#define PSIMD_MUL_SU64(A, B) ((int64_t)(A) * (uint64_t)(B))
> +#define PSIMD_MUL_U64(A, B) ((uint64_t)(A) * (uint64_t)(B))
> +
> +#define GEN_PSIMD_MUL_HIGH(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, HTYPE, \
> + EXTRACT, INSERT, ELEMS, SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + rd = INSERT(rd, high, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_HIGH_SEL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
> + HTYPE, EXTRACT1, EXTRACT2, INSERT, ELEMS, \
> + SCALE, OFFSET, SHIFT, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT1(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT2(rs2, i * (SCALE) + (OFFSET)); \
> + PTYPE prod = OP(e1, e2); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + rd = INSERT(rd, high, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_ELEM_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
> + OTYPE, EXTRACT, INSERT, ELEMS, SCALE, \
> + OFFSET1, OFFSET2, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
> + PTYPE mul = OP(e1, e2); \
> + rd = INSERT(rd, (OTYPE)mul, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_ELEM_SCALAR(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, \
> + EXTRACT, OFFSET1, OFFSET2, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, OFFSET1); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, OFFSET2); \
> + PTYPE mul = OP(e1, e2); \
> + \
> + return (RTYPE)mul; \
> +}
> +
> +#define GEN_PSIMD_MUL_HIGH_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + HTYPE, OTYPE, EXTRACT, INSERT, ELEMS, \
> + SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + DTYPE d = (DTYPE)EXTRACT(dest, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + OTYPE res = (OTYPE)(high + d); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_HIGH_ACC_SEL(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
> + PTYPE, HTYPE, OTYPE, EXTRACT1, \
> + EXTRACT2, INSERT, ELEMS, SCALE, \
> + OFFSET, SHIFT, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT1(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT2(rs2, i * (SCALE) + (OFFSET)); \
> + DTYPE d = (DTYPE)EXTRACT1(dest, i); \
> + PTYPE prod = OP(e1, e2); \
> + HTYPE high = (HTYPE)(prod >> (SHIFT)); \
> + OTYPE res = (OTYPE)(high + d); \
> + rd = INSERT(rd, res, i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_MUL_ACC_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
> + PTYPE, OTYPE, EXTRACT, EXTRACTD, \
> + INSERT, ELEMS, SCALE, OFFSET1, \
> + OFFSET2, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE mul = OP(e1, e2); \
> + rd = INSERT(rd, (OTYPE)(d + mul), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_QMUL(NAME, RTYPE, ETYPE, PTYPE, OTYPE, EXTRACT, INSERT, \
> + ELEMS, SHIFT, ROUND, MINVAL, MAXVAL) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i); \
> + OTYPE result; \
> + \
> + if ((e1 == (ETYPE)(MINVAL)) && (e2 == (ETYPE)(MINVAL))) { \
> + sat = 1; \
> + result = (OTYPE)(MAXVAL); \
> + } else { \
> + PTYPE prod = (PTYPE)e1 * (PTYPE)e2 + (ROUND); \
> + result = (OTYPE)(prod >> (SHIFT)); \
> + } \
> + rd = INSERT(rd, result, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_QMUL_ACC_INDEXED(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, \
> + PTYPE, STYPE, OTYPE, EXTRACT, \
> + EXTRACTD, INSERT, ELEMS, SCALE, \
> + OFFSET1, OFFSET2, SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET1)); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET2)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + STYPE scaled = (STYPE)(((__int128_t)prod) >> (SHIFT)); \
> + rd = INSERT(rd, (OTYPE)(d + scaled), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_Q2ADD(NAME, RTYPE, ETYPE, PTYPE, STYPE, OTYPE, EXTRACT, \
> + INSERT, ELEMS, SCALE, SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE s1_0 = (ETYPE)EXTRACT(rs1, i * (SCALE)); \
> + ETYPE s1_1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + 1); \
> + ETYPE s2_0 = (ETYPE)EXTRACT(rs2, i * (SCALE)); \
> + ETYPE s2_1 = (ETYPE)EXTRACT(rs2, i * (SCALE) + 1); \
> + PTYPE prod0 = OP(s1_0, s2_0) + (ROUND); \
> + PTYPE prod1 = OP(s1_1, s2_1) + (ROUND); \
> + STYPE scaled0 = (STYPE)(((__int128_t)prod0) >> (SHIFT)); \
> + STYPE scaled1 = (STYPE)(((__int128_t)prod1) >> (SHIFT)); \
> + rd = INSERT(rd, (OTYPE)(scaled0 + scaled1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_Q2ADDA(NAME, RTYPE, ETYPE, DTYPE, PTYPE, STYPE, OTYPE, \
> + EXTRACT, EXTRACTD, INSERT, ELEMS, SCALE, \
> + SHIFT, ROUND, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + ETYPE s1_0 = (ETYPE)EXTRACT(rs1, i * (SCALE)); \
> + ETYPE s1_1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + 1); \
> + ETYPE s2_0 = (ETYPE)EXTRACT(rs2, i * (SCALE)); \
> + ETYPE s2_1 = (ETYPE)EXTRACT(rs2, i * (SCALE) + 1); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod0 = OP(s1_0, s2_0) + (ROUND); \
> + PTYPE prod1 = OP(s1_1, s2_1) + (ROUND); \
> + STYPE scaled0 = (STYPE)(((__int128_t)prod0) >> (SHIFT)); \
> + STYPE scaled1 = (STYPE)(((__int128_t)prod1) >> (SHIFT)); \
> + rd = INSERT(rd, (OTYPE)(d + scaled0 + scaled1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define PSIMD_COMB_ADD(D, A, B) ((D) + (A) + (B))
> +#define PSIMD_COMB_SUB(D, A, B) ((D) + (A) - (B))
> +
> +#define GEN_PSIMD_2WAY_MUL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, OTYPE, \
> + EXTRACT, INSERT, ELEMS, SCALE, OFFSET10, \
> + OFFSET11, OFFSET20, OFFSET21, OP, COMBINE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET10)); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET11)); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET20)); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET21)); \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + rd = INSERT(rd, (OTYPE)COMBINE(0, prod0, prod1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_2WAY_SAT_MUL(NAME, OFFSET10, OFFSET11, OFFSET20, \
> + OFFSET21) \
> +target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong rs1, \
> + target_ulong rs2) \
> +{ \
> + target_ulong rd = 0; \
> + int sat = 0; \
> + \
> + for (int i = 0; i < ELEMS_W(rd); i++) { \
> + int16_t s1_0 = (int16_t)EXTRACT16(rs1, i * 2 + (OFFSET10)); \
> + int16_t s1_1 = (int16_t)EXTRACT16(rs1, i * 2 + (OFFSET11)); \
> + int16_t s2_0 = (int16_t)EXTRACT16(rs2, i * 2 + (OFFSET20)); \
> + int16_t s2_1 = (int16_t)EXTRACT16(rs2, i * 2 + (OFFSET21)); \
> + uint32_t result; \
> + \
> + if (s1_0 == INT16_MIN && s1_1 == INT16_MIN && \
> + s2_0 == INT16_MIN && s2_1 == INT16_MIN) { \
> + result = INT32_MAX; \
> + sat = 1; \
> + } else { \
> + int32_t prod0 = (int32_t)s1_0 * s2_0; \
> + int32_t prod1 = (int32_t)s1_1 * s2_1; \
> + result = (uint32_t)(prod0 + prod1); \
> + } \
> + rd = INSERT32(rd, result, i); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_2WAY_MUL_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + OTYPE, EXTRACT, EXTRACTD, INSERT, ELEMS, \
> + SCALE, OFFSET10, OFFSET11, OFFSET20, \
> + OFFSET21, OP, COMBINE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET10)); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET11)); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET20)); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET21)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + rd = INSERT(rd, (OTYPE)COMBINE(d, prod0, prod1), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_4WAY_MUL(NAME, RTYPE, E1TYPE, E2TYPE, PTYPE, OTYPE, \
> + EXTRACT, INSERT, ELEMS, SCALE, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + PTYPE prod0 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE)), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE))); \
> + PTYPE prod1 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 1), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 1)); \
> + PTYPE prod2 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 2), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 2)); \
> + PTYPE prod3 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 3), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 3)); \
> + rd = INSERT(rd, (OTYPE)(prod0 + prod1 + prod2 + prod3), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_4WAY_MUL_ACC(NAME, RTYPE, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + OTYPE, EXTRACT, EXTRACTD, INSERT, ELEMS, \
> + SCALE, OP) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1, RTYPE rs2, RTYPE dest) \
> +{ \
> + RTYPE rd = 0; \
> + int elems = ELEMS(rd); \
> + \
> + for (int i = 0; i < elems; i++) { \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod0 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE)), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE))); \
> + PTYPE prod1 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 1), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 1)); \
> + PTYPE prod2 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 2), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 2)); \
> + PTYPE prod3 = OP((E1TYPE)EXTRACT(rs1, i * (SCALE) + 3), \
> + (E2TYPE)EXTRACT(rs2, i * (SCALE) + 3)); \
> + rd = INSERT(rd, (OTYPE)(d + prod0 + prod1 + prod2 + prod3), i); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_BINOP(NAME, ETYPE, WTYPE, OTYPE, ELEMS, IBITS, \
> + OBITS, IMASK, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
> + ETYPE e2 = (ETYPE)((rs2 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE res = OP((WTYPE)0, (WTYPE)e1, (WTYPE)e2); \
> + rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_BINOP_ACC(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, OMASK, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
> + ETYPE e2 = (ETYPE)((rs2 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE acc = (WTYPE)((dest >> (i * (OBITS))) & (OMASK)); \
> + WTYPE res = OP(acc, (WTYPE)e1, (WTYPE)e2); \
> + rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_MUL(NAME, E1TYPE, E2TYPE, PTYPE, OTYPE, ELEMS, \
> + EXTRACT, OBITS, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + PTYPE prod = OP(e1, e2); \
> + rd |= ((uint64_t)(OTYPE)prod) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_MUL_ACC(NAME, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + OTYPE, ELEMS, EXTRACT, EXTRACTD, OBITS, \
> + OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + E1TYPE e1 = (E1TYPE)EXTRACT(rs1, i); \
> + E2TYPE e2 = (E2TYPE)EXTRACT(rs2, i); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod = OP(e1, e2); \
> + rd |= ((uint64_t)(OTYPE)(d + prod)) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_WIDEN_QMUL_ACC(NAME, ETYPE, DTYPE, PTYPE, STYPE, \
> + OTYPE, ELEMS, EXTRACT, EXTRACTD, SCALE, \
> + OFFSET, SHIFT, ROUND, OBITS, OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)EXTRACT(rs1, i * (SCALE) + (OFFSET)); \
> + ETYPE e2 = (ETYPE)EXTRACT(rs2, i * (SCALE) + (OFFSET)); \
> + DTYPE d = (DTYPE)EXTRACTD(dest, i); \
> + PTYPE prod = OP(e1, e2) + (ROUND); \
> + STYPE scaled = (STYPE)(((__int128_t)prod) >> (SHIFT)); \
> + rd |= ((uint64_t)(OTYPE)(d + scaled)) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_DW_2WAY_MUL(NAME, E1TYPE, E2TYPE, PTYPE, EXTRACT, \
> + OFFSET10, OFFSET11, OFFSET20, OFFSET21, \
> + OP, COMBINE) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, OFFSET10); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, OFFSET11); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, OFFSET20); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, OFFSET21); \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + \
> + return (uint64_t)COMBINE(0, prod0, prod1); \
> +}
> +
> +#define GEN_PSIMD_DW_2WAY_MUL_ACC(NAME, E1TYPE, E2TYPE, DTYPE, PTYPE, \
> + EXTRACT, OFFSET10, OFFSET11, OFFSET20, \
> + OFFSET21, OP, COMBINE) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, \
> + uint64_t dest) \
> +{ \
> + E1TYPE s1_0 = (E1TYPE)EXTRACT(rs1, OFFSET10); \
> + E1TYPE s1_1 = (E1TYPE)EXTRACT(rs1, OFFSET11); \
> + E2TYPE s2_0 = (E2TYPE)EXTRACT(rs2, OFFSET20); \
> + E2TYPE s2_1 = (E2TYPE)EXTRACT(rs2, OFFSET21); \
> + DTYPE d = (DTYPE)dest; \
> + PTYPE prod0 = OP(s1_0, s2_0); \
> + PTYPE prod1 = OP(s1_1, s2_1); \
> + \
> + return (uint64_t)COMBINE(d, prod0, prod1); \
> +}
> +
> +#define GEN_PSIMD_WIDEN_SHIFT(NAME, ETYPE, WTYPE, OTYPE, ELEMS, IBITS, \
> + OBITS, IMASK, SHMASK) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + uint8_t shamt = rs2 & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((rs1 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE res = (WTYPE)e1 << shamt; \
> + rd |= ((uint64_t)(OTYPE)res) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_DW_ZIP(NAME, EXTRACT, ELEMS, STRIDE, BITS) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1, uint32_t rs2) \
> +{ \
> + uint64_t rd = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + uint64_t e1 = (uint64_t)EXTRACT(rs1, i) << ((STRIDE) * i); \
> + uint64_t e2 = (uint64_t)EXTRACT(rs2, i) \
> + << ((STRIDE) * i + (BITS)); \
> + rd |= e2 | e1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_DW_REDSUM(NAME, SUMTYPE, INITTYPE, ETYPE, EXTRACT, \
> + ELEMS) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint32_t rs1_lo, \
> + uint32_t rs1_hi, uint32_t rs2) \
> +{ \
> + SUMTYPE sum = (INITTYPE)rs2; \
> + uint64_t s1 = ((uint64_t)rs1_hi << 32) | rs1_lo; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + sum += (ETYPE)EXTRACT(s1, i); \
> + } \
> + return (uint32_t)sum; \
> +}
> +
> +#define GEN_PSIMD_NARROW_SRL(NAME, ETYPE, OTYPE, ELEMS, IBITS, OBITS, \
> + IMASK, SHMASK) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + OTYPE result = (OTYPE)(e1 >> shift); \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NARROW_SRA_PACK(NAME, ETYPE, STYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + STYPE shx = (STYPE)e1 >> shift; \
> + OTYPE result = (OTYPE)shx; \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NARROW_RNDSRA_PACK(NAME, ETYPE, STYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK, RMASK) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + STYPE e1_s = (STYPE)e1; \
> + uint64_t shx = (((uint64_t)e1_s << 1) >> shift) & (RMASK); \
> + OTYPE result = (OTYPE)((shx + 1) >> 1); \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIP_SIGNED_PACK(NAME, ETYPE, STYPE, CTYPE, OTYPE, \
> + ELEMS, IBITS, OBITS, IMASK, SHMASK, \
> + MIN, MAX, MIN_RES, MAX_RES) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + CTYPE shx = (CTYPE)((STYPE)e1 >> shift); \
> + OTYPE result; \
> + \
> + if (shx < (MIN)) { \
> + sat = 1; \
> + result = (MIN_RES); \
> + } else if (shx > (MAX)) { \
> + sat = 1; \
> + result = (MAX_RES); \
> + } else { \
> + result = (OTYPE)shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIPR_SIGNED_PACK(NAME, ETYPE, STYPE, CTYPE, OTYPE, \
> + ELEMS, IBITS, OBITS, IMASK, SHMASK, \
> + RMASK, MIN, MAX, MIN_RES, MAX_RES) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + STYPE e1_s = (STYPE)e1; \
> + uint64_t shx = (((uint64_t)e1_s << 1) >> shift) & (RMASK); \
> + CTYPE round_shx = (CTYPE)((shx + 1) >> 1); \
> + OTYPE result; \
> + \
> + if (round_shx < (MIN)) { \
> + sat = 1; \
> + result = (MIN_RES); \
> + } else if (round_shx > (MAX)) { \
> + sat = 1; \
> + result = (MAX_RES); \
> + } else { \
> + result = (OTYPE)round_shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIP_UNSIGNED_PACK(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK, MAX) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE shx = (WTYPE)e1 >> shift; \
> + OTYPE result; \
> + \
> + if (shx > (MAX)) { \
> + sat = 1; \
> + result = (OTYPE)(MAX); \
> + } else { \
> + result = (OTYPE)shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NCLIPR_UNSIGNED_PACK(NAME, ETYPE, WTYPE, OTYPE, ELEMS, \
> + IBITS, OBITS, IMASK, SHMASK, MAX) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint32_t rd = 0; \
> + uint8_t shift = shamt & (SHMASK); \
> + int sat = 0; \
> + \
> + for (int i = 0; i < (ELEMS); i++) { \
> + ETYPE e1 = (ETYPE)((s1 >> (i * (IBITS))) & (IMASK)); \
> + WTYPE shx = ((WTYPE)e1 << 1) >> shift; \
> + WTYPE round_shx = (shx + 1) >> 1; \
> + OTYPE result; \
> + \
> + if (round_shx > (MAX)) { \
> + sat = 1; \
> + result = (OTYPE)(MAX); \
> + } else { \
> + result = (OTYPE)round_shx; \
> + } \
> + rd |= ((uint32_t)result) << (i * (OBITS)); \
> + } \
> + \
> + if (sat) { \
> + env->vxsat = 1; \
> + } \
> + return rd; \
> +}
> +
> +#define GEN_PSIMD_NARROW_SRA(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + __int128_t s1_s96 = (s1_s128 << 32) >> 32; \
> + \
> + return (uint32_t)(s1_s96 >> (shamt & 0x3F)) & 0xFFFFFFFF; \
> +}
> +
> +#define GEN_PSIMD_NARROW_RNDSRA(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + __int128_t s1_s96 = (s1_s128 << 32) >> 32; \
> + __uint128_t shx_97bit = ((__uint128_t)s1_s96 << 1); \
> + uint64_t shx = (uint64_t)(shx_97bit >> (shamt & 0x3F)) & 0x1FFFFFFFF; \
> + \
> + return (uint32_t)((shx + 1) >> 1); \
> +}
> +
> +#define GEN_PSIMD_NARROW_ALIAS(NAME, TARGET) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + return HELPER(TARGET)(env, s1, shamt); \
> +}
> +
> +typedef struct {
> + __uint128_t low;
> + uint8_t high;
> +} PsImdUint129;
> +
> +static inline PsImdUint129 psimd_uint129_lshift1(__int128_t val)
> +{
> + PsImdUint129 result;
> + __uint128_t uval = (__uint128_t)val;
> +
> + result.low = uval << 1;
> + result.high = (uval >> 127) & 0x1;
> + return result;
> +}
> +
> +static inline PsImdUint129 psimd_uint129_rshift(PsImdUint129 val,
> + uint32_t shamt)
> +{
> + PsImdUint129 result;
> +
> + if (shamt == 0) {
> + return val;
> + } else if (shamt >= 129) {
> + result.low = 0;
> + result.high = 0;
> + } else if (shamt == 128) {
> + result.low = val.high;
> + result.high = 0;
> + } else {
> + result.low = (val.low >> shamt) |
> + ((__uint128_t)val.high << (128 - shamt));
> + result.high = val.high >> shamt;
> + }
> + return result;
> +}
> +
> +#define GEN_PSIMD_NCLIP(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + int64_t shx = (int64_t)(s1_s128 >> (shamt & 0x3F)); \
> + \
> + if (shx < -2147483648LL) { \
> + env->vxsat = 1; \
> + return 0x80000000U; \
> + } else if (shx > 2147483647LL) { \
> + env->vxsat = 1; \
> + return 0x7FFFFFFFU; \
> + } else { \
> + return (uint32_t)(shx & 0xFFFFFFFF); \
> + } \
> +}
> +
> +#define GEN_PSIMD_NCLIPR(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __int128_t s1_s128 = (__int128_t)((int64_t)s1); \
> + PsImdUint129 shx_129bit = psimd_uint129_lshift1(s1_s128); \
> + PsImdUint129 shx = psimd_uint129_rshift(shx_129bit, shamt & 0x3F); \
> + int64_t round_shx = (int64_t)((shx.low + 1) >> 1); \
> + \
> + if (round_shx < -2147483648LL) { \
> + env->vxsat = 1; \
> + return 0x80000000U; \
> + } else if (round_shx > 2147483647LL) { \
> + env->vxsat = 1; \
> + return 0x7FFFFFFFU; \
> + } else { \
> + return (uint32_t)round_shx; \
> + } \
> +}
> +
> +#define GEN_PSIMD_NCLIPU(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + uint64_t shx = s1 >> (shamt & 0x3F); \
> + \
> + if (shx > 4294967295ULL) { \
> + env->vxsat = 1; \
> + return 0xFFFFFFFFU; \
> + } else { \
> + return (uint32_t)(shx & 0xFFFFFFFF); \
> + } \
> +}
> +
> +#define GEN_PSIMD_NCLIPRU(NAME) \
> +uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
> +{ \
> + __uint128_t shx_65bit = (__uint128_t)s1 << 1; \
> + __uint128_t shx = shx_65bit >> (shamt & 0x3F); \
> + uint64_t round_shx = (shx + 1) >> 1; \
> + \
> + if (round_shx > 4294967295ULL) { \
> + env->vxsat = 1; \
> + return 0xFFFFFFFFU; \
> + } else { \
> + return (uint32_t)(round_shx & 0xFFFFFFFF); \
> + } \
> +}
> +
> +/* Basic addition operations (non-saturating) */
> +
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework
2026-07-17 10:06 ` [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework Molly Chen
2026-07-26 19:53 ` Daniel Henrique Barboza
2026-07-27 6:16 ` Nutty.Liu
@ 2026-07-29 9:01 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Chao Liu @ 2026-07-29 9:01 UTC (permalink / raw)
To: Molly Chen
Cc: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
Chao Liu, qemu-riscv, qemu-devel
On Fri, Jul 17, 2026 at 10:06:55AM +0800, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
> ---
> target/riscv/tcg/meson.build | 3 +-
> target/riscv/tcg/psimd_helper.c | 1656 +++++++++++++++++++++++++++++++
> 2 files changed, 1658 insertions(+), 1 deletion(-)
> create mode 100644 target/riscv/tcg/psimd_helper.c
>
> diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build
> index a05ab642f41..cc438d7c0d2 100644
> --- a/target/riscv/tcg/meson.build
> +++ b/target/riscv/tcg/meson.build
> @@ -15,7 +15,8 @@ riscv_ss.add(files(
> 'vcrypto_helper.c',
> 'vector_helper.c',
> 'vector_internals.c',
> - 'zce_helper.c'))
> + 'zce_helper.c',
> + 'psimd_helper.c'))
>
>
> riscv_system_ss.add(files(
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> new file mode 100644
> index 00000000000..2948bbb2a86
> --- /dev/null
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -0,0 +1,1656 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* RISC-V Packed SIMD Extension Helpers for QEMU. */
> +/* Copyright (C) 2026 ISRC ISCAS. */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "qemu/host-utils.h"
> +#include "exec/helper-proto.h"
> +#include "fpu/softfloat.h"
> +#include "internals.h"
> +
> +
> +/* Helper macros */
> +
> +/* Element count calculations */
> +#define ELEMS_B(target) (sizeof(target) * 8 / 8) /* byte elements count */
> +#define ELEMS_H(target) (sizeof(target) * 8 / 16)
> +#define ELEMS_W(target) (sizeof(target) * 8 / 32) /* word elements count */
> +#define ELEMS_D(target) (sizeof(target) * 8 / 64)
> +
> +/* Element extraction macros - unsigned to avoid sign extension */
> +#define EXTRACT8(val, idx) (((val) >> ((idx) * 8)) & 0xFF)
> +#define EXTRACT16(val, idx) (((val) >> ((idx) * 16)) & 0xFFFF)
> +#define EXTRACT32(val, idx) (((val) >> ((idx) * 32)) & 0xFFFFFFFF)
> +#define EXTRACT64(val, idx) (((val) >> ((idx) * 64)) & 0xFFFFFFFFFFFFFFFFULL)
> +
QEMU has the generator bit-operation helper macros. I believe you don't need to
define them again, so you can just follow this header file path.
path: include/qemu/bitops.h
```
extract8(value, start, length)
extract16(value, start, length)
extract32(value, start, length)
extract64(value, start, length)
sextract32(value, start, length)
sextract64(value, start, length)
```
So we can redefine these helper macros like this:
```
#define EXTRACT_B(val, idx) extract64((val), (idx) * 8, 8)
#define EXTRACT_H(val, idx) extract64((val), (idx) * 16, 16)
#define EXTRACT_W(val, idx) extract64((val), (idx) * 32, 32)
#define EXTRACT_D(val, idx) extract64((val), (idx) * 64, 64)
```
> +/* Element insertion macros */
> +#define INSERT8(val, res, idx) \
> + ((val) | ((target_ulong)(uint8_t)(res) << ((idx) * 8)))
> +#define INSERT16(val, res, idx) \
> + ((val) | ((target_ulong)(uint16_t)(res) << ((idx) * 16)))
> +#define INSERT32(val, res, idx) \
> + ((val) | ((target_ulong)(uint32_t)(res) << ((idx) * 32)))
> +#define INSERT32_64(val, res, idx) \
> + ((val) | ((uint64_t)(uint32_t)(res) << ((idx) * 32)))
> +#define INSERT64(val, res, idx) \
> + ((val) | ((uint64_t)(res) << ((idx) * 64)))
> +
> +/* Saturation constants */
> +static const int8_t SAT_MAX_B = 127;
> +static const int8_t SAT_MIN_B = -128;
> +static const int16_t SAT_MAX_H = 32767;
> +static const int16_t SAT_MIN_H = -32768;
> +static const int32_t SAT_MAX_W = 2147483647;
> +static const int32_t SAT_MIN_W = -2147483648LL;
> +static const uint8_t USAT_MAX_B = 255;
> +static const uint16_t USAT_MAX_H = 65535;
> +static const uint32_t USAT_MAX_W = 4294967295U;
> +
> +
> +/* Saturation helper functions */
> +
> +/**
> + * Signed saturation for 8-bit elements
> + * Returns saturated value and sets *sat if saturation occurred
> + */
This helper function has some comments that explain what it does.
I believe we don't need these explanations if the function name is
already clear.
The other helper functions below are similar. I think we only need
to add comments when it's necessary to explain the reasoning behind
why we're doing something.
d> +static inline int8_t signed_saturate_b(int32_t val, int *sat)
> +{
> + if (val > SAT_MAX_B) {
> + *sat = 1;
> + return SAT_MAX_B;
> + }
> + if (val < SAT_MIN_B) {
> + *sat = 1;
> + return SAT_MIN_B;
> + }
> + return (int8_t)val;
> +}
> +
> +/**
> + * Signed saturation for 16-bit elements
> + */
> +static inline int16_t signed_saturate_h(int32_t val, int *sat)
> +{
> + if (val > SAT_MAX_H) {
> + *sat = 1;
> + return SAT_MAX_H;
> + }
> + if (val < SAT_MIN_H) {
> + *sat = 1;
> + return SAT_MIN_H;
> + }
> + return (int16_t)val;
> +}
> +
> +/**
> + * Signed saturation for 32-bit elements
> + */
> +static inline int32_t signed_saturate_w(int64_t val, int *sat)
> +{
> + if (val > SAT_MAX_W) {
> + *sat = 1;
> + return SAT_MAX_W;
> + }
> + if (val < SAT_MIN_W) {
> + *sat = 1;
> + return SAT_MIN_W;
> + }
> + return (int32_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 8-bit elements
> + */
> +static inline uint8_t unsigned_saturate_b(uint32_t val, int *sat)
> +{
> + if (val > USAT_MAX_B) {
> + *sat = 1;
> + return USAT_MAX_B;
> + }
> + return (uint8_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 16-bit elements
> + */
> +static inline uint16_t unsigned_saturate_h(uint32_t val, int *sat)
> +{
> + if (val > USAT_MAX_H) {
> + *sat = 1;
> + return USAT_MAX_H;
> + }
> + return (uint16_t)val;
> +}
> +
> +/**
> + * Unsigned saturation for 32-bit elements
> + */
> +static inline uint32_t unsigned_saturate_w(uint64_t val, int *sat)
> +{
> + if (val > USAT_MAX_W) {
> + *sat = 1;
> + return USAT_MAX_W;
> + }
> + return (uint32_t)val;
> +}
> +
> +static inline target_ulong psimd_abdsumu_b(target_ulong rs1,
> + target_ulong rs2,
> + target_ulong sum)
> +{
> + int elems = ELEMS_B(rs1);
> +
> + for (int i = 0; i < elems; i++) {
> + uint8_t e1 = EXTRACT8(rs1, i);
> + uint8_t e2 = EXTRACT8(rs2, i);
> + uint8_t diff = (e1 > e2) ? (e1 - e2) : (e2 - e1);
> + sum += diff;
> + }
> +
> + return sum;
> +}
> +
> +#define PSIMD_DO_ADD(N, M) ((N) + (M))
> +#define PSIMD_DO_SUB(N, M) ((N) - (M))
> +#define PSIMD_DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
> +#define PSIMD_DO_EQ_MASK(N, M) ((N) == (M) ? -1 : 0)
> +#define PSIMD_DO_LT_MASK(N, M) ((N) < (M) ? -1 : 0)
> +#define PSIMD_DO_MIN(N, M) ((N) < (M) ? (N) : (M))
> +#define PSIMD_DO_MAX(N, M) ((N) > (M) ? (N) : (M))
> +#define PSIMD_DO_SLL(N, M) ((N) << (M))
> +#define PSIMD_DO_SRL(N, M) ((N) >> (M))
> +#define PSIMD_DO_SRA(N, M) ((N) >> (M))
> +
[...]
> +
> +#define GEN_PSIMD_SCALAR_ABS(NAME, RTYPE, STYPE, UTYPE) \
> +RTYPE HELPER(NAME)(CPURISCVState *env, RTYPE rs1) \
> +{ \
> + STYPE value = (STYPE)rs1; \
> + UTYPE result = (UTYPE)value; \
> + \
> + if (value < 0) { \
> + result = (UTYPE)0 - result; \
> + } \
> + return (RTYPE)(STYPE)result; \
> +}
The '\' for the column widths aren't aligned here. It would
look much better if we could align them consistently throughout.
[...]
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + int64_t a = (int64_t)rs1; \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + if (shamt >= 0) { \
> + return (uint64_t)(a << shamt); \
> + } \
> + \
> + int right = -shamt; \
> + if (right >= 64) { \
> + return (a < 0) ? (uint64_t)-1 : 0; \
> + } \
> + return (uint64_t)RIGHT_OP(a, right); \
> +}
There are similar alignment issues here.
> +
> +#define PSIMD_DO_SRL64(A, B) (((B) >= 64) ? 0 : ((A) >> (B)))
> +#define PSIMD_DO_RNDSRL64(A, B) \
> + (((B) > 64) ? 0 : ((((A) >> ((B) - 1)) + 1) >> 1))
> +
> +#define GEN_PSIMD_VAR_SRL64(NAME, RIGHT_OP) \
> +uint64_t HELPER(NAME)(CPURISCVState *env, uint64_t rs1, uint64_t rs2) \
> +{ \
> + int8_t shamt = (int8_t)(rs2 & 0xff); \
> + \
> + if (shamt < 0) { \
> + return RIGHT_OP(rs1, -shamt); \
> + } \
> + return (shamt >= 64) ? 0 : (rs1 << shamt); \
> +}
> +
Same here.You can check again for the patches.
Thanks,
Chao
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
2026-07-17 10:06 ` [PATCH v2 01/18] target/riscv: Add packed SIMD extension state Molly Chen
2026-07-17 10:06 ` [PATCH v2 02/18] target/riscv: Add packed SIMD helper framework Molly Chen
@ 2026-07-17 10:06 ` Molly Chen
2026-07-26 22:05 ` Daniel Henrique Barboza
` (2 more replies)
2026-07-17 10:06 ` [PATCH v2 04/18] target/riscv: Add packed SIMD averaging and rounding instructions Molly Chen
` (16 subsequent siblings)
19 siblings, 3 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:06 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 41 ++
target/riscv/insn32.decode | 63 +++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 547 ++++++++++++++++++++
target/riscv/tcg/psimd_helper.c | 114 ++++
target/riscv/tcg/translate.c | 4 +
5 files changed, 769 insertions(+)
create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 542b7c264fc..eebb2febd95 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1358,3 +1358,44 @@ DEF_HELPER_1(ssamoswap_disabled, void, env)
/* Zalrsc SC write probe */
DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl)
+
+/* Packed SIMD */
+/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
+DEF_HELPER_3(padd_b, tl, env, tl, tl)
+DEF_HELPER_3(padd_h, tl, env, tl, tl)
+DEF_HELPER_3(padd_w, i64, env, i64, i64)
+DEF_HELPER_3(padd_bs, tl, env, tl, tl)
+DEF_HELPER_3(padd_hs, tl, env, tl, tl)
+DEF_HELPER_3(padd_ws, i64, env, i64, i64)
+DEF_HELPER_3(psub_b, tl, env, tl, tl)
+DEF_HELPER_3(psub_h, tl, env, tl, tl)
+DEF_HELPER_3(psub_w, i64, env, i64, i64)
+DEF_HELPER_3(psh1add_h, tl, env, tl, tl)
+DEF_HELPER_3(psh1add_w, i64, env, i64, i64)
+DEF_HELPER_3(pssh1sadd_h, tl, env, tl, tl)
+DEF_HELPER_3(pssh1sadd_w, i64, env, i64, i64)
+DEF_HELPER_3(ssh1sadd, i32, env, i32, i32)
+DEF_HELPER_3(psadd_b, tl, env, tl, tl)
+DEF_HELPER_3(psadd_h, tl, env, tl, tl)
+DEF_HELPER_3(psadd_w, i64, env, i64, i64)
+DEF_HELPER_3(psaddu_b, tl, env, tl, tl)
+DEF_HELPER_3(psaddu_h, tl, env, tl, tl)
+DEF_HELPER_3(psaddu_w, i64, env, i64, i64)
+DEF_HELPER_3(sadd, i32, env, i32, i32)
+DEF_HELPER_3(saddu, i32, env, i32, i32)
+DEF_HELPER_3(pssub_b, tl, env, tl, tl)
+DEF_HELPER_3(pssub_h, tl, env, tl, tl)
+DEF_HELPER_3(pssub_w, i64, env, i64, i64)
+DEF_HELPER_3(pssubu_b, tl, env, tl, tl)
+DEF_HELPER_3(pssubu_h, tl, env, tl, tl)
+DEF_HELPER_3(pssubu_w, i64, env, i64, i64)
+DEF_HELPER_3(ssub, i32, env, i32, i32)
+DEF_HELPER_3(ssubu, i32, env, i32, i32)
+DEF_HELPER_3(psati_h, tl, env, tl, tl)
+DEF_HELPER_3(pusati_h, tl, env, tl, tl)
+DEF_HELPER_3(psati_w, i64, env, i64, i64)
+DEF_HELPER_3(pusati_w, i64, env, i64, i64)
+DEF_HELPER_3(sati_32, i32, env, i32, i32)
+DEF_HELPER_3(usati_32, i32, env, i32, i32)
+DEF_HELPER_3(sati_64, i64, env, i64, i64)
+DEF_HELPER_3(usati_64, i64, env, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 21272fdb504..8da13669d73 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -40,6 +40,9 @@
%imm_z6 26:1 15:5
%imm_mop5 30:1 26:2 20:2
%imm_mop3 30:1 26:2
+%imm_p_ui16 20:4
+%imm_p_ui32 20:5
+%imm_p_ui64 20:6
# Argument sets:
&empty
@@ -60,6 +63,7 @@
&k_aes shamt rs2 rs1 rd
&mop5 imm rd rs1
&mop3 imm rd rs1 rs2
+&p_ui imm rs1 rd
# Formats 32:
@r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
@@ -105,6 +109,10 @@
@mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1
@mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2
+@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd
+@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd
+@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd
+
# Formats 64:
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
@@ -1084,3 +1092,58 @@ sb_aqrl 00111 . . ..... ..... 000 ..... 0101111 @atom_st
sh_aqrl 00111 . . ..... ..... 001 ..... 0101111 @atom_st
sw_aqrl 00111 . . ..... ..... 010 ..... 0101111 @atom_st
sd_aqrl 00111 . . ..... ..... 011 ..... 0101111 @atom_st
+
+# *** P Experimental Extension Version v020 ***
+# Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating)
+padd_b 1000010 ..... ..... 000 ..... 0111011 @r
+padd_h 1000000 ..... ..... 000 ..... 0111011 @r
+padd_w 1000001 ..... ..... 000 ..... 0111011 @r
+padd_bs 1001110 ..... ..... 010 ..... 0011011 @r
+padd_hs 1001100 ..... ..... 010 ..... 0011011 @r
+padd_ws 1001101 ..... ..... 010 ..... 0011011 @r
+psub_b 1100010 ..... ..... 000 ..... 0111011 @r
+psub_h 1100000 ..... ..... 000 ..... 0111011 @r
+psub_w 1100001 ..... ..... 000 ..... 0111011 @r
+psh1add_h 1010000 ..... ..... 010 ..... 0111011 @r
+psh1add_w 1010001 ..... ..... 010 ..... 0111011 @r
+pssh1sadd_h 1011000 ..... ..... 010 ..... 0111011 @r
+{
+ ssh1sadd 1011001 ..... ..... 010 ..... 0111011 @r
+ pssh1sadd_w 1011001 ..... ..... 010 ..... 0111011 @r
+}
+psadd_b 1001010 ..... ..... 000 ..... 0111011 @r
+psadd_h 1001000 ..... ..... 000 ..... 0111011 @r
+{
+ sadd 1001001 ..... ..... 000 ..... 0111011 @r
+ psadd_w 1001001 ..... ..... 000 ..... 0111011 @r
+}
+psaddu_b 1011010 ..... ..... 000 ..... 0111011 @r
+psaddu_h 1011000 ..... ..... 000 ..... 0111011 @r
+{
+ saddu 1011001 ..... ..... 000 ..... 0111011 @r
+ psaddu_w 1011001 ..... ..... 000 ..... 0111011 @r
+}
+pssub_b 1101010 ..... ..... 000 ..... 0111011 @r
+pssub_h 1101000 ..... ..... 000 ..... 0111011 @r
+{
+ ssub 1101001 ..... ..... 000 ..... 0111011 @r
+ pssub_w 1101001 ..... ..... 000 ..... 0111011 @r
+}
+pssubu_b 1111010 ..... ..... 000 ..... 0111011 @r
+pssubu_h 1111000 ..... ..... 000 ..... 0111011 @r
+{
+ ssubu 1111001 ..... ..... 000 ..... 0111011 @r
+ pssubu_w 1111001 ..... ..... 000 ..... 0111011 @r
+}
+psati_h 11100 001.... ..... 100 ..... 0011011 @p_ui16
+pusati_h 10100 001.... ..... 100 ..... 0011011 @p_ui16
+{
+ sati_32 11100 01..... ..... 100 ..... 0011011 @p_ui32
+ psati_w 11100 01..... ..... 100 ..... 0011011 @p_ui32
+}
+{
+ usati_32 10100 01..... ..... 100 ..... 0011011 @p_ui32
+ pusati_w 10100 01..... ..... 100 ..... 0011011 @p_ui32
+}
+sati_64 111001 ...... ..... 100 ..... 0011011 @p_ui64
+usati_64 101001 ...... ..... 100 ..... 0011011 @p_ui64
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
new file mode 100644
index 00000000000..056ccfb486e
--- /dev/null
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -0,0 +1,547 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* RISC-V translation routines for the P Standard Extensions. */
+/* Copyright (c) 2026 ISRC ISCAS. */
+
+/* Save a 64 bit data in src to dst and dst + 1 */
+
+static bool require_rvp(DisasContext *ctx)
+{
+ uint32_t opcode = ctx->opcode & 0x7f;
+
+ if (!has_ext(ctx, RVP)) {
+ return false;
+ }
+
+ /*
+ * P_VXSAT_EXCP is encoded in the TB flags only when P is implemented
+ * without Zve*, where stateen0.VXSAT controls the whole OP-32 and
+ * OP-IMM-32 P instruction spaces. When Zve* is present, this field
+ * remains NONE and vxsat access is checked by the VS path instead.
+ */
+ if ((opcode == 0x3b || opcode == 0x1b) &&
+ ctx->p_vxsat_excp != P_VXSAT_EXCP_NONE) {
+ ctx->virt_inst_excp =
+ ctx->p_vxsat_excp == P_VXSAT_EXCP_VIRTUAL;
+ return false;
+ }
+
+ return true;
+}
+
+static bool prepare_rvp_vxsat(DisasContext *ctx)
+{
+ if (!ctx->cfg_ptr->ext_zve32x) {
+ return true;
+ }
+
+ if (ctx->mstatus_vs == EXT_STATUS_DISABLED) {
+ return false;
+ }
+
+ mark_vs_dirty(ctx);
+ return true;
+}
+
+#define REQUIRE_RVP(ctx) do { \
+ if (!require_rvp(ctx)) { \
+ return false; \
+ } \
+} while (0)
+
+#define GEN_SIMD_TRANS_BODY(NAME, VXSAT) \
+do { \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
+ TCGv dest = dest_gpr(ctx, a->rd); \
+ gen_helper_##NAME(dest, tcg_env, src1, src2); \
+ gen_set_gpr(ctx, a->rd, dest); \
+ return true; \
+} while (0)
+
+#define GEN_SIMD_TRANS_UNAVAILABLE_32(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS_UNAVAILABLE_64(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_BODY(NAME, false); \
+}
+
+#define GEN_SIMD_TRANS_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_BODY(NAME, true); \
+}
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_32(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ GEN_SIMD_TRANS_BODY(NAME, false); \
+}
+#define GEN_SIMD_TRANS_32_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ GEN_SIMD_TRANS_BODY(NAME, true); \
+}
+#else
+#define GEN_SIMD_TRANS_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#define GEN_SIMD_TRANS_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#define GEN_SIMD_TRANS_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#else
+#define GEN_SIMD_TRANS_64(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_BODY(NAME, false); \
+}
+#define GEN_SIMD_TRANS_64_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_BODY(NAME, true); \
+}
+#endif
+
+#define GEN_SIMD_TRANS_ACC_BODY(NAME, VXSAT) \
+do { \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
+ TCGv dest = dest_gpr(ctx, a->rd); \
+ TCGv t = tcg_temp_new(); \
+ gen_helper_##NAME(t, tcg_env, src1, src2, dest); \
+ gen_set_gpr(ctx, a->rd, t); \
+ return true; \
+} while (0)
+
+#define GEN_SIMD_TRANS_ACC(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
+}
+
+#define GEN_SIMD_TRANS_ACC_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_ACC_BODY(NAME, true); \
+}
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_ACC_32(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
+}
+#else
+#define GEN_SIMD_TRANS_ACC_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_ACC_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#else
+#define GEN_SIMD_TRANS_ACC_64(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
+}
+#endif
+
+#define GEN_SIMD_TRANS_R1_BODY(NAME, VXSAT) \
+do { \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv dest = dest_gpr(ctx, a->rd); \
+ gen_helper_##NAME(dest, tcg_env, src1); \
+ gen_set_gpr(ctx, a->rd, dest); \
+ return true; \
+} while (0)
+
+#define GEN_SIMD_TRANS_R1(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_R1_BODY(NAME, false); \
+}
+
+#define GEN_SIMD_TRANS_R1_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_R1_BODY(NAME, true); \
+}
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_R1_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#else
+#define GEN_SIMD_TRANS_R1_64(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_R1_BODY(NAME, false); \
+}
+#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_R1_BODY(NAME, true); \
+}
+#endif
+
+#define GEN_SIMD_TRANS_IMM_BODY(NAME, VXSAT) \
+do { \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv imm = tcg_constant_tl(a->imm); \
+ TCGv dest = dest_gpr(ctx, a->rd); \
+ gen_helper_##NAME(dest, tcg_env, src1, imm); \
+ gen_set_gpr(ctx, a->rd, dest); \
+ return true; \
+} while (0)
+
+#define GEN_SIMD_TRANS_IMM(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
+}
+
+#define GEN_SIMD_TRANS_IMM_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
+}
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_IMM_32(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
+}
+#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
+}
+#else
+#define GEN_SIMD_TRANS_IMM_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_IMM_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
+#else
+#define GEN_SIMD_TRANS_IMM_64(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
+}
+#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_64BIT(ctx); \
+ GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
+}
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, SRC2) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv_i32 src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv_i32 src2 = SRC2; \
+ TCGv_i64 t = tcg_temp_new_i64(); \
+ gen_helper_##NAME(t, tcg_env, src1, src2); \
+ set_pair_regs(ctx, (a->rd) * 2, t); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) \
+ GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE))
+
+#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) \
+ GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, tcg_constant_i32(a->imm))
+#else
+#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, SRC2_0, SRC2_1, VXSAT) \
+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
+ TCGv src2_0 = SRC2_0; \
+ TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
+ TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
+ TCGv src2_1 = SRC2_1; \
+ TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
+ gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2_0); \
+ gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2_1); \
+ gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
+ gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
+ get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
+ get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), false)
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
+ get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
+ get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), true)
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
+ tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), false)
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
+ tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), true)
+#else
+#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, VXSAT) \
+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
+ TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
+ TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
+ TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
+ gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2); \
+ gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2); \
+ gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
+ gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, false)
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, true)
+#else
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, VXSAT) \
+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
+{ \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
+ TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
+ TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
+ TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
+ gen_helper_##HELPER(dest_0, tcg_env, src1_0); \
+ gen_helper_##HELPER(dest_1, tcg_env, src1_1); \
+ gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
+ gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, false)
+
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, true)
+#else
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
+ GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
+ TCGv_i64 t = tcg_temp_new_i64(); \
+ if (a->rd == 0) { \
+ tcg_gen_movi_i64(t, 0); \
+ } else { \
+ get_pair_regs(ctx, t, (a->rd) * 2); \
+ } \
+ gen_helper_##NAME(t, tcg_env, src1, src2, t); \
+ set_pair_regs(ctx, (a->rd) * 2, t); \
+ return true; \
+}
+#else
+#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv_i32 src1_l; \
+ TCGv_i32 src1_h; \
+ TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
+ TCGv_i32 dest = dest_gpr(ctx, a->rd); \
+ if (a->rs1 == 0) { \
+ src1_l = tcg_temp_new_i32(); \
+ src1_h = tcg_temp_new_i32(); \
+ tcg_gen_movi_i32(src1_l, 0); \
+ tcg_gen_movi_i32(src1_h, 0); \
+ } else { \
+ src1_l = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
+ src1_h = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
+ } \
+ gen_helper_##NAME(dest, tcg_env, src1_l, src1_h, src2); \
+ gen_set_gpr(ctx, a->rd, dest); \
+ return true; \
+}
+#else
+#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+#if defined(TARGET_RISCV32)
+#define GEN_SIMD_TRANS_PN_OP(NAME, SRC2, VXSAT) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
+ return false; \
+ } \
+ TCGv_i64 s1 = tcg_temp_new_i64(); \
+ if (a->rs1 == 0) { \
+ tcg_gen_mov_i64(s1, 0); \
+ } else { \
+ get_pair_regs(ctx, s1, a->rs1 * 2); \
+ } \
+ TCGv src2 = SRC2; \
+ TCGv dest = dest_gpr(ctx, a->rd); \
+ gen_helper_##NAME(dest, tcg_env, s1, src2); \
+ gen_set_gpr(ctx, a->rd, dest); \
+ return true; \
+}
+
+#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) \
+ GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), false)
+
+#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) \
+ GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), true)
+
+#define GEN_SIMD_TRANS_PN_OP_REG(NAME) \
+ GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), false)
+
+#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) \
+ GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), true)
+#else
+#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#define GEN_SIMD_TRANS_PN_OP_REG(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
+#endif
+
+/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
+GEN_SIMD_TRANS(padd_b)
+GEN_SIMD_TRANS(padd_h)
+GEN_SIMD_TRANS_64(padd_w)
+GEN_SIMD_TRANS(padd_bs)
+GEN_SIMD_TRANS(padd_hs)
+GEN_SIMD_TRANS_64(padd_ws)
+GEN_SIMD_TRANS(psub_b)
+GEN_SIMD_TRANS(psub_h)
+GEN_SIMD_TRANS_64(psub_w)
+GEN_SIMD_TRANS(psh1add_h)
+GEN_SIMD_TRANS_64(psh1add_w)
+GEN_SIMD_TRANS_VXSAT(pssh1sadd_h)
+GEN_SIMD_TRANS_64_VXSAT(pssh1sadd_w)
+GEN_SIMD_TRANS_32_VXSAT(ssh1sadd)
+GEN_SIMD_TRANS_VXSAT(psadd_b)
+GEN_SIMD_TRANS_VXSAT(psadd_h)
+GEN_SIMD_TRANS_64_VXSAT(psadd_w)
+GEN_SIMD_TRANS_VXSAT(psaddu_b)
+GEN_SIMD_TRANS_VXSAT(psaddu_h)
+GEN_SIMD_TRANS_64_VXSAT(psaddu_w)
+GEN_SIMD_TRANS_32_VXSAT(sadd)
+GEN_SIMD_TRANS_32_VXSAT(saddu)
+GEN_SIMD_TRANS_VXSAT(pssub_b)
+GEN_SIMD_TRANS_VXSAT(pssub_h)
+GEN_SIMD_TRANS_64_VXSAT(pssub_w)
+GEN_SIMD_TRANS_VXSAT(pssubu_b)
+GEN_SIMD_TRANS_VXSAT(pssubu_h)
+GEN_SIMD_TRANS_64_VXSAT(pssubu_w)
+GEN_SIMD_TRANS_32_VXSAT(ssub)
+GEN_SIMD_TRANS_32_VXSAT(ssubu)
+GEN_SIMD_TRANS_IMM_VXSAT(psati_h)
+GEN_SIMD_TRANS_IMM_VXSAT(pusati_h)
+GEN_SIMD_TRANS_IMM_64_VXSAT(psati_w)
+GEN_SIMD_TRANS_IMM_64_VXSAT(pusati_w)
+GEN_SIMD_TRANS_IMM_32_VXSAT(sati_32)
+GEN_SIMD_TRANS_IMM_32_VXSAT(usati_32)
+GEN_SIMD_TRANS_IMM_64_VXSAT(sati_64)
+GEN_SIMD_TRANS_IMM_64_VXSAT(usati_64)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 2948bbb2a86..52c58e0287e 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -1654,3 +1654,117 @@ uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
/* Basic addition operations (non-saturating) */
+GEN_PSIMD_BINOP(padd_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
+GEN_PSIMD_BINOP(padd_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
+GEN_PSIMD_BINOP(padd_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
+
+GEN_PSIMD_BINOP_SCALAR(padd_bs, target_ulong, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
+GEN_PSIMD_BINOP_SCALAR(padd_hs, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
+GEN_PSIMD_BINOP_SCALAR(padd_ws, uint64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
+
+/* Basic subtraction operations (non-saturating) */
+
+GEN_PSIMD_BINOP(psub_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
+GEN_PSIMD_BINOP(psub_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
+GEN_PSIMD_BINOP(psub_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
+
+/* Shift-left-by-one and add operations */
+
+GEN_PSIMD_SHADD(psh1add_h, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 1)
+GEN_PSIMD_SHADD(psh1add_w, uint64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 1)
+
+GEN_PSIMD_SAT_SHADD(pssh1sadd_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 1, -0x4000, 0x3fff,
+ SAT_MIN_H, SAT_MAX_H, signed_saturate_h)
+GEN_PSIMD_SAT_SHADD(pssh1sadd_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
+ 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
+
+GEN_PSIMD_SAT_SHADD(ssh1sadd, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
+ 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
+
+/* Saturating addition operations */
+
+GEN_PSIMD_SAT_BINOP(psadd_b, target_ulong, int8_t, int32_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
+ signed_saturate_b)
+GEN_PSIMD_SAT_BINOP(psadd_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
+ signed_saturate_h)
+GEN_PSIMD_SAT_BINOP(psadd_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
+ signed_saturate_w)
+
+GEN_PSIMD_SAT_BINOP(psaddu_b, target_ulong, uint8_t, uint32_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
+ unsigned_saturate_b)
+GEN_PSIMD_SAT_BINOP(psaddu_h, target_ulong, uint16_t, uint32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
+ unsigned_saturate_h)
+GEN_PSIMD_SAT_BINOP(psaddu_w, uint64_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
+ unsigned_saturate_w)
+
+GEN_PSIMD_SAT_BINOP(sadd, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
+ signed_saturate_w)
+GEN_PSIMD_SAT_BINOP(saddu, uint32_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
+ unsigned_saturate_w)
+
+/* Saturating subtraction operations */
+
+GEN_PSIMD_SAT_BINOP(pssub_b, target_ulong, int8_t, int32_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB,
+ signed_saturate_b)
+GEN_PSIMD_SAT_BINOP(pssub_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB,
+ signed_saturate_h)
+GEN_PSIMD_SAT_BINOP(pssub_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
+ signed_saturate_w)
+
+GEN_PSIMD_USUB_SAT(pssubu_b, target_ulong, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B)
+GEN_PSIMD_USUB_SAT(pssubu_h, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H)
+GEN_PSIMD_USUB_SAT(pssubu_w, uint64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W)
+
+GEN_PSIMD_SAT_BINOP(ssub, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
+ signed_saturate_w)
+GEN_PSIMD_USUB_SAT(ssubu, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W)
+
+/* Saturation instructions (SAT, USAT) */
+
+GEN_PSIMD_SATI(psati_h, target_ulong, int16_t, int64_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f)
+GEN_PSIMD_USATI(pusati_h, target_ulong, int16_t, uint16_t, uint32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 1U)
+GEN_PSIMD_SATI(psati_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f)
+GEN_PSIMD_USATI(pusati_w, uint64_t, int32_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 1ULL)
+GEN_PSIMD_SATI(sati_32, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f)
+GEN_PSIMD_USATI(usati_32, uint32_t, int32_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 1U)
+GEN_PSIMD_SATI(sati_64, uint64_t, int64_t, int64_t,
+ EXTRACT64, INSERT64, ELEMS_D, 0x3f)
+GEN_PSIMD_USATI(usati_64, uint64_t, int64_t, uint64_t, uint64_t,
+ EXTRACT64, INSERT64, ELEMS_D, 1ULL)
+
diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
index 9684dbe7528..0df9d4190f1 100644
--- a/target/riscv/tcg/translate.c
+++ b/target/riscv/tcg/translate.c
@@ -103,6 +103,7 @@ typedef struct DisasContext {
bool vstart_eq_zero;
bool vl_eq_vlmax;
bool altfmt;
+ uint8_t p_vxsat_excp;
CPUState *cs;
TCGv zero;
/* actual address width */
@@ -1199,6 +1200,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
#include "insn_trans/trans_rvh.c.inc"
#include "insn_trans/trans_rvv.c.inc"
#include "insn_trans/trans_rvb.c.inc"
+#include "insn_trans/trans_rvp.c.inc"
#include "insn_trans/trans_rvzicond.c.inc"
#include "insn_trans/trans_rvzacas.c.inc"
#include "insn_trans/trans_rvzabha.c.inc"
@@ -1333,6 +1335,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
ctx->altfmt = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, ALTFMT);
+ ctx->p_vxsat_excp = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS,
+ P_VXSAT_EXCP);
ctx->misa_mxl_max = mcc->def->misa_mxl_max;
ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* Re: [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions
2026-07-17 10:06 ` [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions Molly Chen
@ 2026-07-26 22:05 ` Daniel Henrique Barboza
2026-07-29 6:17 ` Nutty.Liu
2026-07-29 9:27 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Daniel Henrique Barboza @ 2026-07-26 22:05 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel
On 7/17/2026 7:06 AM, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> target/riscv/helper.h | 41 ++
> target/riscv/insn32.decode | 63 +++
> target/riscv/tcg/insn_trans/trans_rvp.c.inc | 547 ++++++++++++++++++++
> target/riscv/tcg/psimd_helper.c | 114 ++++
> target/riscv/tcg/translate.c | 4 +
> 5 files changed, 769 insertions(+)
> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 542b7c264fc..eebb2febd95 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1358,3 +1358,44 @@ DEF_HELPER_1(ssamoswap_disabled, void, env)
>
> /* Zalrsc SC write probe */
> DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl)
> +
> +/* Packed SIMD */
> +/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
> +DEF_HELPER_3(padd_b, tl, env, tl, tl)
> +DEF_HELPER_3(padd_h, tl, env, tl, tl)
> +DEF_HELPER_3(padd_w, i64, env, i64, i64)
> +DEF_HELPER_3(padd_bs, tl, env, tl, tl)
> +DEF_HELPER_3(padd_hs, tl, env, tl, tl)
> +DEF_HELPER_3(padd_ws, i64, env, i64, i64)
> +DEF_HELPER_3(psub_b, tl, env, tl, tl)
> +DEF_HELPER_3(psub_h, tl, env, tl, tl)
> +DEF_HELPER_3(psub_w, i64, env, i64, i64)
> +DEF_HELPER_3(psh1add_h, tl, env, tl, tl)
> +DEF_HELPER_3(psh1add_w, i64, env, i64, i64)
> +DEF_HELPER_3(pssh1sadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssh1sadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(ssh1sadd, i32, env, i32, i32)
> +DEF_HELPER_3(psadd_b, tl, env, tl, tl)
> +DEF_HELPER_3(psadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(psadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(psaddu_b, tl, env, tl, tl)
> +DEF_HELPER_3(psaddu_h, tl, env, tl, tl)
> +DEF_HELPER_3(psaddu_w, i64, env, i64, i64)
> +DEF_HELPER_3(sadd, i32, env, i32, i32)
> +DEF_HELPER_3(saddu, i32, env, i32, i32)
> +DEF_HELPER_3(pssub_b, tl, env, tl, tl)
> +DEF_HELPER_3(pssub_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssub_w, i64, env, i64, i64)
> +DEF_HELPER_3(pssubu_b, tl, env, tl, tl)
> +DEF_HELPER_3(pssubu_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssubu_w, i64, env, i64, i64)
> +DEF_HELPER_3(ssub, i32, env, i32, i32)
> +DEF_HELPER_3(ssubu, i32, env, i32, i32)
> +DEF_HELPER_3(psati_h, tl, env, tl, tl)
> +DEF_HELPER_3(pusati_h, tl, env, tl, tl)
> +DEF_HELPER_3(psati_w, i64, env, i64, i64)
> +DEF_HELPER_3(pusati_w, i64, env, i64, i64)
> +DEF_HELPER_3(sati_32, i32, env, i32, i32)
> +DEF_HELPER_3(usati_32, i32, env, i32, i32)
> +DEF_HELPER_3(sati_64, i64, env, i64, i64)
> +DEF_HELPER_3(usati_64, i64, env, i64, i64)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 21272fdb504..8da13669d73 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -40,6 +40,9 @@
> %imm_z6 26:1 15:5
> %imm_mop5 30:1 26:2 20:2
> %imm_mop3 30:1 26:2
> +%imm_p_ui16 20:4
> +%imm_p_ui32 20:5
> +%imm_p_ui64 20:6
>
> # Argument sets:
> &empty
> @@ -60,6 +63,7 @@
> &k_aes shamt rs2 rs1 rd
> &mop5 imm rd rs1
> &mop3 imm rd rs1 rs2
> +&p_ui imm rs1 rd
>
> # Formats 32:
> @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
> @@ -105,6 +109,10 @@
> @mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1
> @mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2
>
> +@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd
> +@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd
> +@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd
> +
> # Formats 64:
> @sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
>
> @@ -1084,3 +1092,58 @@ sb_aqrl 00111 . . ..... ..... 000 ..... 0101111 @atom_st
> sh_aqrl 00111 . . ..... ..... 001 ..... 0101111 @atom_st
> sw_aqrl 00111 . . ..... ..... 010 ..... 0101111 @atom_st
> sd_aqrl 00111 . . ..... ..... 011 ..... 0101111 @atom_st
> +
> +# *** P Experimental Extension Version v020 ***
> +# Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating)
> +padd_b 1000010 ..... ..... 000 ..... 0111011 @r
> +padd_h 1000000 ..... ..... 000 ..... 0111011 @r
> +padd_w 1000001 ..... ..... 000 ..... 0111011 @r
> +padd_bs 1001110 ..... ..... 010 ..... 0011011 @r
> +padd_hs 1001100 ..... ..... 010 ..... 0011011 @r
> +padd_ws 1001101 ..... ..... 010 ..... 0011011 @r
> +psub_b 1100010 ..... ..... 000 ..... 0111011 @r
> +psub_h 1100000 ..... ..... 000 ..... 0111011 @r
> +psub_w 1100001 ..... ..... 000 ..... 0111011 @r
> +psh1add_h 1010000 ..... ..... 010 ..... 0111011 @r
> +psh1add_w 1010001 ..... ..... 010 ..... 0111011 @r
> +pssh1sadd_h 1011000 ..... ..... 010 ..... 0111011 @r
> +{
> + ssh1sadd 1011001 ..... ..... 010 ..... 0111011 @r
> + pssh1sadd_w 1011001 ..... ..... 010 ..... 0111011 @r
> +}
> +psadd_b 1001010 ..... ..... 000 ..... 0111011 @r
> +psadd_h 1001000 ..... ..... 000 ..... 0111011 @r
> +{
> + sadd 1001001 ..... ..... 000 ..... 0111011 @r
> + psadd_w 1001001 ..... ..... 000 ..... 0111011 @r
> +}
> +psaddu_b 1011010 ..... ..... 000 ..... 0111011 @r
> +psaddu_h 1011000 ..... ..... 000 ..... 0111011 @r
> +{
> + saddu 1011001 ..... ..... 000 ..... 0111011 @r
> + psaddu_w 1011001 ..... ..... 000 ..... 0111011 @r
> +}
> +pssub_b 1101010 ..... ..... 000 ..... 0111011 @r
> +pssub_h 1101000 ..... ..... 000 ..... 0111011 @r
> +{
> + ssub 1101001 ..... ..... 000 ..... 0111011 @r
> + pssub_w 1101001 ..... ..... 000 ..... 0111011 @r
> +}
> +pssubu_b 1111010 ..... ..... 000 ..... 0111011 @r
> +pssubu_h 1111000 ..... ..... 000 ..... 0111011 @r
> +{
> + ssubu 1111001 ..... ..... 000 ..... 0111011 @r
> + pssubu_w 1111001 ..... ..... 000 ..... 0111011 @r
> +}
> +psati_h 11100 001.... ..... 100 ..... 0011011 @p_ui16
> +pusati_h 10100 001.... ..... 100 ..... 0011011 @p_ui16
> +{
> + sati_32 11100 01..... ..... 100 ..... 0011011 @p_ui32
> + psati_w 11100 01..... ..... 100 ..... 0011011 @p_ui32
> +}
> +{
> + usati_32 10100 01..... ..... 100 ..... 0011011 @p_ui32
> + pusati_w 10100 01..... ..... 100 ..... 0011011 @p_ui32
> +}
> +sati_64 111001 ...... ..... 100 ..... 0011011 @p_ui64
> +usati_64 101001 ...... ..... 100 ..... 0011011 @p_ui64
> diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> new file mode 100644
> index 00000000000..056ccfb486e
> --- /dev/null
> +++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> @@ -0,0 +1,547 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* RISC-V translation routines for the P Standard Extensions. */
> +/* Copyright (c) 2026 ISRC ISCAS. */
> +
> +/* Save a 64 bit data in src to dst and dst + 1 */
> +
> +static bool require_rvp(DisasContext *ctx)
> +{
> + uint32_t opcode = ctx->opcode & 0x7f;
> +
> + if (!has_ext(ctx, RVP)) {
> + return false;
> + }
> +
> + /*
> + * P_VXSAT_EXCP is encoded in the TB flags only when P is implemented
> + * without Zve*, where stateen0.VXSAT controls the whole OP-32 and
> + * OP-IMM-32 P instruction spaces. When Zve* is present, this field
> + * remains NONE and vxsat access is checked by the VS path instead.
> + */
> + if ((opcode == 0x3b || opcode == 0x1b) &&
> + ctx->p_vxsat_excp != P_VXSAT_EXCP_NONE) {
> + ctx->virt_inst_excp =
> + ctx->p_vxsat_excp == P_VXSAT_EXCP_VIRTUAL;
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool prepare_rvp_vxsat(DisasContext *ctx)
> +{
> + if (!ctx->cfg_ptr->ext_zve32x) {
> + return true;
> + }
> +
> + if (ctx->mstatus_vs == EXT_STATUS_DISABLED) {
> + return false;
> + }
> +
> + mark_vs_dirty(ctx);
> + return true;
> +}
> +
> +#define REQUIRE_RVP(ctx) do { \
> + if (!require_rvp(ctx)) { \
> + return false; \
> + } \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_UNAVAILABLE_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_UNAVAILABLE_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_32_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_ACC_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + TCGv t = tcg_temp_new(); \
> + gen_helper_##NAME(t, tcg_env, src1, src2, dest); \
> + gen_set_gpr(ctx, a->rd, t); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_ACC(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_ACC_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_ACC_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_ACC_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_ACC_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_ACC_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_R1_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_R1(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_R1_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_R1_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_R1_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_R1_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_R1_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_R1_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_R1_BODY(NAME, true); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_IMM_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv imm = tcg_constant_tl(a->imm); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1, imm); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_IMM(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_IMM_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_IMM_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_IMM_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_IMM_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_IMM_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, SRC2) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv_i32 src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv_i32 src2 = SRC2; \
> + TCGv_i64 t = tcg_temp_new_i64(); \
> + gen_helper_##NAME(t, tcg_env, src1, src2); \
> + set_pair_regs(ctx, (a->rd) * 2, t); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) \
> + GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE))
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) \
> + GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, tcg_constant_i32(a->imm))
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, SRC2_0, SRC2_1, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv src2_0 = SRC2_0; \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv src2_1 = SRC2_1; \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2_0); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2_1); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
> + get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
> + get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), true)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv_i64 t = tcg_temp_new_i64(); \
> + if (a->rd == 0) { \
> + tcg_gen_movi_i64(t, 0); \
> + } else { \
> + get_pair_regs(ctx, t, (a->rd) * 2); \
> + } \
> + gen_helper_##NAME(t, tcg_env, src1, src2, t); \
> + set_pair_regs(ctx, (a->rd) * 2, t); \
> + return true; \
> +}
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv_i32 src1_l; \
> + TCGv_i32 src1_h; \
> + TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv_i32 dest = dest_gpr(ctx, a->rd); \
> + if (a->rs1 == 0) { \
> + src1_l = tcg_temp_new_i32(); \
> + src1_h = tcg_temp_new_i32(); \
> + tcg_gen_movi_i32(src1_l, 0); \
> + tcg_gen_movi_i32(src1_h, 0); \
> + } else { \
> + src1_l = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + src1_h = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + } \
> + gen_helper_##NAME(dest, tcg_env, src1_l, src1_h, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +}
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_PN_OP(NAME, SRC2, VXSAT) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv_i64 s1 = tcg_temp_new_i64(); \
> + if (a->rs1 == 0) { \
> + tcg_gen_mov_i64(s1, 0); \
> + } else { \
> + get_pair_regs(ctx, s1, a->rs1 * 2); \
> + } \
> + TCGv src2 = SRC2; \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, s1, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), false)
> +
> +#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), true)
> +
> +#define GEN_SIMD_TRANS_PN_OP_REG(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), false)
> +
> +#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), true)
> +#else
> +#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_REG(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
> +GEN_SIMD_TRANS(padd_b)
> +GEN_SIMD_TRANS(padd_h)
> +GEN_SIMD_TRANS_64(padd_w)
> +GEN_SIMD_TRANS(padd_bs)
> +GEN_SIMD_TRANS(padd_hs)
> +GEN_SIMD_TRANS_64(padd_ws)
> +GEN_SIMD_TRANS(psub_b)
> +GEN_SIMD_TRANS(psub_h)
> +GEN_SIMD_TRANS_64(psub_w)
> +GEN_SIMD_TRANS(psh1add_h)
> +GEN_SIMD_TRANS_64(psh1add_w)
> +GEN_SIMD_TRANS_VXSAT(pssh1sadd_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssh1sadd_w)
> +GEN_SIMD_TRANS_32_VXSAT(ssh1sadd)
> +GEN_SIMD_TRANS_VXSAT(psadd_b)
> +GEN_SIMD_TRANS_VXSAT(psadd_h)
> +GEN_SIMD_TRANS_64_VXSAT(psadd_w)
> +GEN_SIMD_TRANS_VXSAT(psaddu_b)
> +GEN_SIMD_TRANS_VXSAT(psaddu_h)
> +GEN_SIMD_TRANS_64_VXSAT(psaddu_w)
> +GEN_SIMD_TRANS_32_VXSAT(sadd)
> +GEN_SIMD_TRANS_32_VXSAT(saddu)
> +GEN_SIMD_TRANS_VXSAT(pssub_b)
> +GEN_SIMD_TRANS_VXSAT(pssub_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssub_w)
> +GEN_SIMD_TRANS_VXSAT(pssubu_b)
> +GEN_SIMD_TRANS_VXSAT(pssubu_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssubu_w)
> +GEN_SIMD_TRANS_32_VXSAT(ssub)
> +GEN_SIMD_TRANS_32_VXSAT(ssubu)
> +GEN_SIMD_TRANS_IMM_VXSAT(psati_h)
> +GEN_SIMD_TRANS_IMM_VXSAT(pusati_h)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(psati_w)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(pusati_w)
> +GEN_SIMD_TRANS_IMM_32_VXSAT(sati_32)
> +GEN_SIMD_TRANS_IMM_32_VXSAT(usati_32)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(sati_64)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(usati_64)
> +
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> index 2948bbb2a86..52c58e0287e 100644
> --- a/target/riscv/tcg/psimd_helper.c
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -1654,3 +1654,117 @@ uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
>
> /* Basic addition operations (non-saturating) */
>
> +GEN_PSIMD_BINOP(padd_b, target_ulong, uint8_t, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP(padd_h, target_ulong, uint16_t, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP(padd_w, uint64_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +GEN_PSIMD_BINOP_SCALAR(padd_bs, target_ulong, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP_SCALAR(padd_hs, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP_SCALAR(padd_ws, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +/* Basic subtraction operations (non-saturating) */
> +
> +GEN_PSIMD_BINOP(psub_b, target_ulong, uint8_t, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
> +GEN_PSIMD_BINOP(psub_h, target_ulong, uint16_t, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
> +GEN_PSIMD_BINOP(psub_w, uint64_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +
> +/* Shift-left-by-one and add operations */
> +
> +GEN_PSIMD_SHADD(psh1add_h, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1)
> +GEN_PSIMD_SHADD(psh1add_w, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1)
> +
> +GEN_PSIMD_SAT_SHADD(pssh1sadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1, -0x4000, 0x3fff,
> + SAT_MIN_H, SAT_MAX_H, signed_saturate_h)
> +GEN_PSIMD_SAT_SHADD(pssh1sadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
> + 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
> +
> +GEN_PSIMD_SAT_SHADD(ssh1sadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
> + 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
> +
> +/* Saturating addition operations */
> +
> +GEN_PSIMD_SAT_BINOP(psadd_b, target_ulong, int8_t, int32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
> + signed_saturate_b)
> +GEN_PSIMD_SAT_BINOP(psadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
> + signed_saturate_h)
> +GEN_PSIMD_SAT_BINOP(psadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + signed_saturate_w)
> +
> +GEN_PSIMD_SAT_BINOP(psaddu_b, target_ulong, uint8_t, uint32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
> + unsigned_saturate_b)
> +GEN_PSIMD_SAT_BINOP(psaddu_h, target_ulong, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
> + unsigned_saturate_h)
> +GEN_PSIMD_SAT_BINOP(psaddu_w, uint64_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + unsigned_saturate_w)
> +
> +GEN_PSIMD_SAT_BINOP(sadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + signed_saturate_w)
> +GEN_PSIMD_SAT_BINOP(saddu, uint32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + unsigned_saturate_w)
> +
> +/* Saturating subtraction operations */
> +
> +GEN_PSIMD_SAT_BINOP(pssub_b, target_ulong, int8_t, int32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB,
> + signed_saturate_b)
> +GEN_PSIMD_SAT_BINOP(pssub_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB,
> + signed_saturate_h)
> +GEN_PSIMD_SAT_BINOP(pssub_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
> + signed_saturate_w)
> +
> +GEN_PSIMD_USUB_SAT(pssubu_b, target_ulong, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B)
> +GEN_PSIMD_USUB_SAT(pssubu_h, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H)
> +GEN_PSIMD_USUB_SAT(pssubu_w, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W)
> +
> +GEN_PSIMD_SAT_BINOP(ssub, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
> + signed_saturate_w)
> +GEN_PSIMD_USUB_SAT(ssubu, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W)
> +
> +/* Saturation instructions (SAT, USAT) */
> +
> +GEN_PSIMD_SATI(psati_h, target_ulong, int16_t, int64_t,
> + EXTRACT16, INSERT16, ELEMS_H, 0x0f)
> +GEN_PSIMD_USATI(pusati_h, target_ulong, int16_t, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1U)
> +GEN_PSIMD_SATI(psati_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 0x1f)
> +GEN_PSIMD_USATI(pusati_w, uint64_t, int32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1ULL)
> +GEN_PSIMD_SATI(sati_32, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 0x1f)
> +GEN_PSIMD_USATI(usati_32, uint32_t, int32_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1U)
> +GEN_PSIMD_SATI(sati_64, uint64_t, int64_t, int64_t,
> + EXTRACT64, INSERT64, ELEMS_D, 0x3f)
> +GEN_PSIMD_USATI(usati_64, uint64_t, int64_t, uint64_t, uint64_t,
> + EXTRACT64, INSERT64, ELEMS_D, 1ULL)
> +
> diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
> index 9684dbe7528..0df9d4190f1 100644
> --- a/target/riscv/tcg/translate.c
> +++ b/target/riscv/tcg/translate.c
> @@ -103,6 +103,7 @@ typedef struct DisasContext {
> bool vstart_eq_zero;
> bool vl_eq_vlmax;
> bool altfmt;
> + uint8_t p_vxsat_excp;
> CPUState *cs;
> TCGv zero;
> /* actual address width */
> @@ -1199,6 +1200,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
> #include "insn_trans/trans_rvh.c.inc"
> #include "insn_trans/trans_rvv.c.inc"
> #include "insn_trans/trans_rvb.c.inc"
> +#include "insn_trans/trans_rvp.c.inc"
> #include "insn_trans/trans_rvzicond.c.inc"
> #include "insn_trans/trans_rvzacas.c.inc"
> #include "insn_trans/trans_rvzabha.c.inc"
> @@ -1333,6 +1335,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
> ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
> ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
> ctx->altfmt = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, ALTFMT);
> + ctx->p_vxsat_excp = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS,
> + P_VXSAT_EXCP);
> ctx->misa_mxl_max = mcc->def->misa_mxl_max;
> ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
> ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions
2026-07-17 10:06 ` [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions Molly Chen
2026-07-26 22:05 ` Daniel Henrique Barboza
@ 2026-07-29 6:17 ` Nutty.Liu
2026-07-29 9:27 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Nutty.Liu @ 2026-07-29 6:17 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, daniel.barboza,
zhiwei_liu, chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel
On 7/17/2026 6:06 PM, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> ---
> target/riscv/helper.h | 41 ++
> target/riscv/insn32.decode | 63 +++
> target/riscv/tcg/insn_trans/trans_rvp.c.inc | 547 ++++++++++++++++++++
> target/riscv/tcg/psimd_helper.c | 114 ++++
> target/riscv/tcg/translate.c | 4 +
> 5 files changed, 769 insertions(+)
> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 542b7c264fc..eebb2febd95 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1358,3 +1358,44 @@ DEF_HELPER_1(ssamoswap_disabled, void, env)
>
> /* Zalrsc SC write probe */
> DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl)
> +
> +/* Packed SIMD */
> +/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
> +DEF_HELPER_3(padd_b, tl, env, tl, tl)
> +DEF_HELPER_3(padd_h, tl, env, tl, tl)
> +DEF_HELPER_3(padd_w, i64, env, i64, i64)
> +DEF_HELPER_3(padd_bs, tl, env, tl, tl)
> +DEF_HELPER_3(padd_hs, tl, env, tl, tl)
> +DEF_HELPER_3(padd_ws, i64, env, i64, i64)
> +DEF_HELPER_3(psub_b, tl, env, tl, tl)
> +DEF_HELPER_3(psub_h, tl, env, tl, tl)
> +DEF_HELPER_3(psub_w, i64, env, i64, i64)
> +DEF_HELPER_3(psh1add_h, tl, env, tl, tl)
> +DEF_HELPER_3(psh1add_w, i64, env, i64, i64)
> +DEF_HELPER_3(pssh1sadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssh1sadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(ssh1sadd, i32, env, i32, i32)
> +DEF_HELPER_3(psadd_b, tl, env, tl, tl)
> +DEF_HELPER_3(psadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(psadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(psaddu_b, tl, env, tl, tl)
> +DEF_HELPER_3(psaddu_h, tl, env, tl, tl)
> +DEF_HELPER_3(psaddu_w, i64, env, i64, i64)
> +DEF_HELPER_3(sadd, i32, env, i32, i32)
> +DEF_HELPER_3(saddu, i32, env, i32, i32)
> +DEF_HELPER_3(pssub_b, tl, env, tl, tl)
> +DEF_HELPER_3(pssub_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssub_w, i64, env, i64, i64)
> +DEF_HELPER_3(pssubu_b, tl, env, tl, tl)
> +DEF_HELPER_3(pssubu_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssubu_w, i64, env, i64, i64)
> +DEF_HELPER_3(ssub, i32, env, i32, i32)
> +DEF_HELPER_3(ssubu, i32, env, i32, i32)
> +DEF_HELPER_3(psati_h, tl, env, tl, tl)
> +DEF_HELPER_3(pusati_h, tl, env, tl, tl)
> +DEF_HELPER_3(psati_w, i64, env, i64, i64)
> +DEF_HELPER_3(pusati_w, i64, env, i64, i64)
> +DEF_HELPER_3(sati_32, i32, env, i32, i32)
> +DEF_HELPER_3(usati_32, i32, env, i32, i32)
> +DEF_HELPER_3(sati_64, i64, env, i64, i64)
> +DEF_HELPER_3(usati_64, i64, env, i64, i64)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 21272fdb504..8da13669d73 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -40,6 +40,9 @@
> %imm_z6 26:1 15:5
> %imm_mop5 30:1 26:2 20:2
> %imm_mop3 30:1 26:2
> +%imm_p_ui16 20:4
> +%imm_p_ui32 20:5
> +%imm_p_ui64 20:6
>
> # Argument sets:
> &empty
> @@ -60,6 +63,7 @@
> &k_aes shamt rs2 rs1 rd
> &mop5 imm rd rs1
> &mop3 imm rd rs1 rs2
> +&p_ui imm rs1 rd
>
> # Formats 32:
> @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
> @@ -105,6 +109,10 @@
> @mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1
> @mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2
>
> +@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd
> +@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd
> +@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd
> +
> # Formats 64:
> @sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
>
> @@ -1084,3 +1092,58 @@ sb_aqrl 00111 . . ..... ..... 000 ..... 0101111 @atom_st
> sh_aqrl 00111 . . ..... ..... 001 ..... 0101111 @atom_st
> sw_aqrl 00111 . . ..... ..... 010 ..... 0101111 @atom_st
> sd_aqrl 00111 . . ..... ..... 011 ..... 0101111 @atom_st
> +
> +# *** P Experimental Extension Version v020 ***
> +# Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating)
> +padd_b 1000010 ..... ..... 000 ..... 0111011 @r
> +padd_h 1000000 ..... ..... 000 ..... 0111011 @r
> +padd_w 1000001 ..... ..... 000 ..... 0111011 @r
> +padd_bs 1001110 ..... ..... 010 ..... 0011011 @r
> +padd_hs 1001100 ..... ..... 010 ..... 0011011 @r
> +padd_ws 1001101 ..... ..... 010 ..... 0011011 @r
> +psub_b 1100010 ..... ..... 000 ..... 0111011 @r
> +psub_h 1100000 ..... ..... 000 ..... 0111011 @r
> +psub_w 1100001 ..... ..... 000 ..... 0111011 @r
> +psh1add_h 1010000 ..... ..... 010 ..... 0111011 @r
> +psh1add_w 1010001 ..... ..... 010 ..... 0111011 @r
> +pssh1sadd_h 1011000 ..... ..... 010 ..... 0111011 @r
> +{
> + ssh1sadd 1011001 ..... ..... 010 ..... 0111011 @r
> + pssh1sadd_w 1011001 ..... ..... 010 ..... 0111011 @r
> +}
> +psadd_b 1001010 ..... ..... 000 ..... 0111011 @r
> +psadd_h 1001000 ..... ..... 000 ..... 0111011 @r
> +{
> + sadd 1001001 ..... ..... 000 ..... 0111011 @r
> + psadd_w 1001001 ..... ..... 000 ..... 0111011 @r
> +}
> +psaddu_b 1011010 ..... ..... 000 ..... 0111011 @r
> +psaddu_h 1011000 ..... ..... 000 ..... 0111011 @r
> +{
> + saddu 1011001 ..... ..... 000 ..... 0111011 @r
> + psaddu_w 1011001 ..... ..... 000 ..... 0111011 @r
> +}
> +pssub_b 1101010 ..... ..... 000 ..... 0111011 @r
> +pssub_h 1101000 ..... ..... 000 ..... 0111011 @r
> +{
> + ssub 1101001 ..... ..... 000 ..... 0111011 @r
> + pssub_w 1101001 ..... ..... 000 ..... 0111011 @r
> +}
> +pssubu_b 1111010 ..... ..... 000 ..... 0111011 @r
> +pssubu_h 1111000 ..... ..... 000 ..... 0111011 @r
> +{
> + ssubu 1111001 ..... ..... 000 ..... 0111011 @r
> + pssubu_w 1111001 ..... ..... 000 ..... 0111011 @r
> +}
> +psati_h 11100 001.... ..... 100 ..... 0011011 @p_ui16
> +pusati_h 10100 001.... ..... 100 ..... 0011011 @p_ui16
> +{
> + sati_32 11100 01..... ..... 100 ..... 0011011 @p_ui32
> + psati_w 11100 01..... ..... 100 ..... 0011011 @p_ui32
> +}
> +{
> + usati_32 10100 01..... ..... 100 ..... 0011011 @p_ui32
> + pusati_w 10100 01..... ..... 100 ..... 0011011 @p_ui32
> +}
> +sati_64 111001 ...... ..... 100 ..... 0011011 @p_ui64
> +usati_64 101001 ...... ..... 100 ..... 0011011 @p_ui64
> diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> new file mode 100644
> index 00000000000..056ccfb486e
> --- /dev/null
> +++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> @@ -0,0 +1,547 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* RISC-V translation routines for the P Standard Extensions. */
> +/* Copyright (c) 2026 ISRC ISCAS. */
> +
> +/* Save a 64 bit data in src to dst and dst + 1 */
> +
> +static bool require_rvp(DisasContext *ctx)
> +{
> + uint32_t opcode = ctx->opcode & 0x7f;
> +
> + if (!has_ext(ctx, RVP)) {
> + return false;
> + }
> +
> + /*
> + * P_VXSAT_EXCP is encoded in the TB flags only when P is implemented
> + * without Zve*, where stateen0.VXSAT controls the whole OP-32 and
> + * OP-IMM-32 P instruction spaces. When Zve* is present, this field
> + * remains NONE and vxsat access is checked by the VS path instead.
> + */
> + if ((opcode == 0x3b || opcode == 0x1b) &&
> + ctx->p_vxsat_excp != P_VXSAT_EXCP_NONE) {
> + ctx->virt_inst_excp =
> + ctx->p_vxsat_excp == P_VXSAT_EXCP_VIRTUAL;
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool prepare_rvp_vxsat(DisasContext *ctx)
> +{
> + if (!ctx->cfg_ptr->ext_zve32x) {
> + return true;
> + }
> +
> + if (ctx->mstatus_vs == EXT_STATUS_DISABLED) {
> + return false;
> + }
> +
> + mark_vs_dirty(ctx);
> + return true;
> +}
> +
> +#define REQUIRE_RVP(ctx) do { \
> + if (!require_rvp(ctx)) { \
> + return false; \
> + } \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_UNAVAILABLE_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_UNAVAILABLE_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_32_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_ACC_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + TCGv t = tcg_temp_new(); \
> + gen_helper_##NAME(t, tcg_env, src1, src2, dest); \
> + gen_set_gpr(ctx, a->rd, t); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_ACC(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_ACC_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_ACC_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_ACC_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_ACC_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_ACC_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_R1_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_R1(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_R1_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_R1_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_R1_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_R1_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_R1_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_R1_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_R1_BODY(NAME, true); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_IMM_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv imm = tcg_constant_tl(a->imm); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1, imm); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_IMM(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_IMM_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_IMM_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_IMM_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_IMM_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_IMM_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, SRC2) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv_i32 src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv_i32 src2 = SRC2; \
> + TCGv_i64 t = tcg_temp_new_i64(); \
> + gen_helper_##NAME(t, tcg_env, src1, src2); \
> + set_pair_regs(ctx, (a->rd) * 2, t); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) \
> + GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE))
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) \
> + GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, tcg_constant_i32(a->imm))
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, SRC2_0, SRC2_1, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv src2_0 = SRC2_0; \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv src2_1 = SRC2_1; \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2_0); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2_1); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
> + get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
> + get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), true)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv_i64 t = tcg_temp_new_i64(); \
> + if (a->rd == 0) { \
> + tcg_gen_movi_i64(t, 0); \
> + } else { \
> + get_pair_regs(ctx, t, (a->rd) * 2); \
> + } \
> + gen_helper_##NAME(t, tcg_env, src1, src2, t); \
> + set_pair_regs(ctx, (a->rd) * 2, t); \
> + return true; \
> +}
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv_i32 src1_l; \
> + TCGv_i32 src1_h; \
> + TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv_i32 dest = dest_gpr(ctx, a->rd); \
> + if (a->rs1 == 0) { \
> + src1_l = tcg_temp_new_i32(); \
> + src1_h = tcg_temp_new_i32(); \
> + tcg_gen_movi_i32(src1_l, 0); \
> + tcg_gen_movi_i32(src1_h, 0); \
> + } else { \
> + src1_l = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + src1_h = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + } \
> + gen_helper_##NAME(dest, tcg_env, src1_l, src1_h, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +}
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_PN_OP(NAME, SRC2, VXSAT) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv_i64 s1 = tcg_temp_new_i64(); \
> + if (a->rs1 == 0) { \
> + tcg_gen_mov_i64(s1, 0); \
> + } else { \
> + get_pair_regs(ctx, s1, a->rs1 * 2); \
> + } \
> + TCGv src2 = SRC2; \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, s1, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), false)
> +
> +#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), true)
> +
> +#define GEN_SIMD_TRANS_PN_OP_REG(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), false)
> +
> +#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), true)
> +#else
> +#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_REG(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
> +GEN_SIMD_TRANS(padd_b)
> +GEN_SIMD_TRANS(padd_h)
> +GEN_SIMD_TRANS_64(padd_w)
> +GEN_SIMD_TRANS(padd_bs)
> +GEN_SIMD_TRANS(padd_hs)
> +GEN_SIMD_TRANS_64(padd_ws)
> +GEN_SIMD_TRANS(psub_b)
> +GEN_SIMD_TRANS(psub_h)
> +GEN_SIMD_TRANS_64(psub_w)
> +GEN_SIMD_TRANS(psh1add_h)
> +GEN_SIMD_TRANS_64(psh1add_w)
> +GEN_SIMD_TRANS_VXSAT(pssh1sadd_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssh1sadd_w)
> +GEN_SIMD_TRANS_32_VXSAT(ssh1sadd)
> +GEN_SIMD_TRANS_VXSAT(psadd_b)
> +GEN_SIMD_TRANS_VXSAT(psadd_h)
> +GEN_SIMD_TRANS_64_VXSAT(psadd_w)
> +GEN_SIMD_TRANS_VXSAT(psaddu_b)
> +GEN_SIMD_TRANS_VXSAT(psaddu_h)
> +GEN_SIMD_TRANS_64_VXSAT(psaddu_w)
> +GEN_SIMD_TRANS_32_VXSAT(sadd)
> +GEN_SIMD_TRANS_32_VXSAT(saddu)
> +GEN_SIMD_TRANS_VXSAT(pssub_b)
> +GEN_SIMD_TRANS_VXSAT(pssub_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssub_w)
> +GEN_SIMD_TRANS_VXSAT(pssubu_b)
> +GEN_SIMD_TRANS_VXSAT(pssubu_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssubu_w)
> +GEN_SIMD_TRANS_32_VXSAT(ssub)
> +GEN_SIMD_TRANS_32_VXSAT(ssubu)
> +GEN_SIMD_TRANS_IMM_VXSAT(psati_h)
> +GEN_SIMD_TRANS_IMM_VXSAT(pusati_h)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(psati_w)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(pusati_w)
> +GEN_SIMD_TRANS_IMM_32_VXSAT(sati_32)
> +GEN_SIMD_TRANS_IMM_32_VXSAT(usati_32)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(sati_64)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(usati_64)
> +
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> index 2948bbb2a86..52c58e0287e 100644
> --- a/target/riscv/tcg/psimd_helper.c
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -1654,3 +1654,117 @@ uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
>
> /* Basic addition operations (non-saturating) */
>
> +GEN_PSIMD_BINOP(padd_b, target_ulong, uint8_t, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP(padd_h, target_ulong, uint16_t, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP(padd_w, uint64_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +GEN_PSIMD_BINOP_SCALAR(padd_bs, target_ulong, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP_SCALAR(padd_hs, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP_SCALAR(padd_ws, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +/* Basic subtraction operations (non-saturating) */
> +
> +GEN_PSIMD_BINOP(psub_b, target_ulong, uint8_t, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
> +GEN_PSIMD_BINOP(psub_h, target_ulong, uint16_t, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
> +GEN_PSIMD_BINOP(psub_w, uint64_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +
> +/* Shift-left-by-one and add operations */
> +
> +GEN_PSIMD_SHADD(psh1add_h, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1)
> +GEN_PSIMD_SHADD(psh1add_w, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1)
> +
> +GEN_PSIMD_SAT_SHADD(pssh1sadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1, -0x4000, 0x3fff,
> + SAT_MIN_H, SAT_MAX_H, signed_saturate_h)
> +GEN_PSIMD_SAT_SHADD(pssh1sadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
> + 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
> +
> +GEN_PSIMD_SAT_SHADD(ssh1sadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
> + 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
> +
> +/* Saturating addition operations */
> +
> +GEN_PSIMD_SAT_BINOP(psadd_b, target_ulong, int8_t, int32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
> + signed_saturate_b)
> +GEN_PSIMD_SAT_BINOP(psadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
> + signed_saturate_h)
> +GEN_PSIMD_SAT_BINOP(psadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + signed_saturate_w)
> +
> +GEN_PSIMD_SAT_BINOP(psaddu_b, target_ulong, uint8_t, uint32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
> + unsigned_saturate_b)
> +GEN_PSIMD_SAT_BINOP(psaddu_h, target_ulong, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
> + unsigned_saturate_h)
> +GEN_PSIMD_SAT_BINOP(psaddu_w, uint64_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + unsigned_saturate_w)
> +
> +GEN_PSIMD_SAT_BINOP(sadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + signed_saturate_w)
> +GEN_PSIMD_SAT_BINOP(saddu, uint32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + unsigned_saturate_w)
> +
> +/* Saturating subtraction operations */
> +
> +GEN_PSIMD_SAT_BINOP(pssub_b, target_ulong, int8_t, int32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB,
> + signed_saturate_b)
> +GEN_PSIMD_SAT_BINOP(pssub_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB,
> + signed_saturate_h)
> +GEN_PSIMD_SAT_BINOP(pssub_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
> + signed_saturate_w)
> +
> +GEN_PSIMD_USUB_SAT(pssubu_b, target_ulong, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B)
> +GEN_PSIMD_USUB_SAT(pssubu_h, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H)
> +GEN_PSIMD_USUB_SAT(pssubu_w, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W)
> +
> +GEN_PSIMD_SAT_BINOP(ssub, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
> + signed_saturate_w)
> +GEN_PSIMD_USUB_SAT(ssubu, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W)
> +
> +/* Saturation instructions (SAT, USAT) */
> +
> +GEN_PSIMD_SATI(psati_h, target_ulong, int16_t, int64_t,
> + EXTRACT16, INSERT16, ELEMS_H, 0x0f)
> +GEN_PSIMD_USATI(pusati_h, target_ulong, int16_t, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1U)
> +GEN_PSIMD_SATI(psati_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 0x1f)
> +GEN_PSIMD_USATI(pusati_w, uint64_t, int32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1ULL)
> +GEN_PSIMD_SATI(sati_32, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 0x1f)
> +GEN_PSIMD_USATI(usati_32, uint32_t, int32_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1U)
> +GEN_PSIMD_SATI(sati_64, uint64_t, int64_t, int64_t,
> + EXTRACT64, INSERT64, ELEMS_D, 0x3f)
> +GEN_PSIMD_USATI(usati_64, uint64_t, int64_t, uint64_t, uint64_t,
> + EXTRACT64, INSERT64, ELEMS_D, 1ULL)
> +
> diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
> index 9684dbe7528..0df9d4190f1 100644
> --- a/target/riscv/tcg/translate.c
> +++ b/target/riscv/tcg/translate.c
> @@ -103,6 +103,7 @@ typedef struct DisasContext {
> bool vstart_eq_zero;
> bool vl_eq_vlmax;
> bool altfmt;
> + uint8_t p_vxsat_excp;
> CPUState *cs;
> TCGv zero;
> /* actual address width */
> @@ -1199,6 +1200,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
> #include "insn_trans/trans_rvh.c.inc"
> #include "insn_trans/trans_rvv.c.inc"
> #include "insn_trans/trans_rvb.c.inc"
> +#include "insn_trans/trans_rvp.c.inc"
> #include "insn_trans/trans_rvzicond.c.inc"
> #include "insn_trans/trans_rvzacas.c.inc"
> #include "insn_trans/trans_rvzabha.c.inc"
> @@ -1333,6 +1335,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
> ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
> ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
> ctx->altfmt = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, ALTFMT);
> + ctx->p_vxsat_excp = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS,
> + P_VXSAT_EXCP);
> ctx->misa_mxl_max = mcc->def->misa_mxl_max;
> ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
> ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions
2026-07-17 10:06 ` [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions Molly Chen
2026-07-26 22:05 ` Daniel Henrique Barboza
2026-07-29 6:17 ` Nutty.Liu
@ 2026-07-29 9:27 ` Chao Liu
2 siblings, 0 replies; 34+ messages in thread
From: Chao Liu @ 2026-07-29 9:27 UTC (permalink / raw)
To: Molly Chen
Cc: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
Chao Liu, qemu-riscv, qemu-devel
On Fri, Jul 17, 2026 at 10:06:56AM +0800, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
I think we need to add a commit body to explain what the patch does.
Thanks,
Chao
> ---
> target/riscv/helper.h | 41 ++
> target/riscv/insn32.decode | 63 +++
> target/riscv/tcg/insn_trans/trans_rvp.c.inc | 547 ++++++++++++++++++++
> target/riscv/tcg/psimd_helper.c | 114 ++++
> target/riscv/tcg/translate.c | 4 +
> 5 files changed, 769 insertions(+)
> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 542b7c264fc..eebb2febd95 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1358,3 +1358,44 @@ DEF_HELPER_1(ssamoswap_disabled, void, env)
>
> /* Zalrsc SC write probe */
> DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl)
> +
> +/* Packed SIMD */
> +/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
> +DEF_HELPER_3(padd_b, tl, env, tl, tl)
> +DEF_HELPER_3(padd_h, tl, env, tl, tl)
> +DEF_HELPER_3(padd_w, i64, env, i64, i64)
> +DEF_HELPER_3(padd_bs, tl, env, tl, tl)
> +DEF_HELPER_3(padd_hs, tl, env, tl, tl)
> +DEF_HELPER_3(padd_ws, i64, env, i64, i64)
> +DEF_HELPER_3(psub_b, tl, env, tl, tl)
> +DEF_HELPER_3(psub_h, tl, env, tl, tl)
> +DEF_HELPER_3(psub_w, i64, env, i64, i64)
> +DEF_HELPER_3(psh1add_h, tl, env, tl, tl)
> +DEF_HELPER_3(psh1add_w, i64, env, i64, i64)
> +DEF_HELPER_3(pssh1sadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssh1sadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(ssh1sadd, i32, env, i32, i32)
> +DEF_HELPER_3(psadd_b, tl, env, tl, tl)
> +DEF_HELPER_3(psadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(psadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(psaddu_b, tl, env, tl, tl)
> +DEF_HELPER_3(psaddu_h, tl, env, tl, tl)
> +DEF_HELPER_3(psaddu_w, i64, env, i64, i64)
> +DEF_HELPER_3(sadd, i32, env, i32, i32)
> +DEF_HELPER_3(saddu, i32, env, i32, i32)
> +DEF_HELPER_3(pssub_b, tl, env, tl, tl)
> +DEF_HELPER_3(pssub_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssub_w, i64, env, i64, i64)
> +DEF_HELPER_3(pssubu_b, tl, env, tl, tl)
> +DEF_HELPER_3(pssubu_h, tl, env, tl, tl)
> +DEF_HELPER_3(pssubu_w, i64, env, i64, i64)
> +DEF_HELPER_3(ssub, i32, env, i32, i32)
> +DEF_HELPER_3(ssubu, i32, env, i32, i32)
> +DEF_HELPER_3(psati_h, tl, env, tl, tl)
> +DEF_HELPER_3(pusati_h, tl, env, tl, tl)
> +DEF_HELPER_3(psati_w, i64, env, i64, i64)
> +DEF_HELPER_3(pusati_w, i64, env, i64, i64)
> +DEF_HELPER_3(sati_32, i32, env, i32, i32)
> +DEF_HELPER_3(usati_32, i32, env, i32, i32)
> +DEF_HELPER_3(sati_64, i64, env, i64, i64)
> +DEF_HELPER_3(usati_64, i64, env, i64, i64)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 21272fdb504..8da13669d73 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -40,6 +40,9 @@
> %imm_z6 26:1 15:5
> %imm_mop5 30:1 26:2 20:2
> %imm_mop3 30:1 26:2
> +%imm_p_ui16 20:4
> +%imm_p_ui32 20:5
> +%imm_p_ui64 20:6
>
> # Argument sets:
> &empty
> @@ -60,6 +63,7 @@
> &k_aes shamt rs2 rs1 rd
> &mop5 imm rd rs1
> &mop3 imm rd rs1 rs2
> +&p_ui imm rs1 rd
>
> # Formats 32:
> @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
> @@ -105,6 +109,10 @@
> @mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1
> @mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2
>
> +@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd
> +@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd
> +@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd
> +
> # Formats 64:
> @sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
>
> @@ -1084,3 +1092,58 @@ sb_aqrl 00111 . . ..... ..... 000 ..... 0101111 @atom_st
> sh_aqrl 00111 . . ..... ..... 001 ..... 0101111 @atom_st
> sw_aqrl 00111 . . ..... ..... 010 ..... 0101111 @atom_st
> sd_aqrl 00111 . . ..... ..... 011 ..... 0101111 @atom_st
> +
> +# *** P Experimental Extension Version v020 ***
> +# Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating)
> +padd_b 1000010 ..... ..... 000 ..... 0111011 @r
> +padd_h 1000000 ..... ..... 000 ..... 0111011 @r
> +padd_w 1000001 ..... ..... 000 ..... 0111011 @r
> +padd_bs 1001110 ..... ..... 010 ..... 0011011 @r
> +padd_hs 1001100 ..... ..... 010 ..... 0011011 @r
> +padd_ws 1001101 ..... ..... 010 ..... 0011011 @r
> +psub_b 1100010 ..... ..... 000 ..... 0111011 @r
> +psub_h 1100000 ..... ..... 000 ..... 0111011 @r
> +psub_w 1100001 ..... ..... 000 ..... 0111011 @r
> +psh1add_h 1010000 ..... ..... 010 ..... 0111011 @r
> +psh1add_w 1010001 ..... ..... 010 ..... 0111011 @r
> +pssh1sadd_h 1011000 ..... ..... 010 ..... 0111011 @r
> +{
> + ssh1sadd 1011001 ..... ..... 010 ..... 0111011 @r
> + pssh1sadd_w 1011001 ..... ..... 010 ..... 0111011 @r
> +}
> +psadd_b 1001010 ..... ..... 000 ..... 0111011 @r
> +psadd_h 1001000 ..... ..... 000 ..... 0111011 @r
> +{
> + sadd 1001001 ..... ..... 000 ..... 0111011 @r
> + psadd_w 1001001 ..... ..... 000 ..... 0111011 @r
> +}
> +psaddu_b 1011010 ..... ..... 000 ..... 0111011 @r
> +psaddu_h 1011000 ..... ..... 000 ..... 0111011 @r
> +{
> + saddu 1011001 ..... ..... 000 ..... 0111011 @r
> + psaddu_w 1011001 ..... ..... 000 ..... 0111011 @r
> +}
> +pssub_b 1101010 ..... ..... 000 ..... 0111011 @r
> +pssub_h 1101000 ..... ..... 000 ..... 0111011 @r
> +{
> + ssub 1101001 ..... ..... 000 ..... 0111011 @r
> + pssub_w 1101001 ..... ..... 000 ..... 0111011 @r
> +}
> +pssubu_b 1111010 ..... ..... 000 ..... 0111011 @r
> +pssubu_h 1111000 ..... ..... 000 ..... 0111011 @r
> +{
> + ssubu 1111001 ..... ..... 000 ..... 0111011 @r
> + pssubu_w 1111001 ..... ..... 000 ..... 0111011 @r
> +}
> +psati_h 11100 001.... ..... 100 ..... 0011011 @p_ui16
> +pusati_h 10100 001.... ..... 100 ..... 0011011 @p_ui16
> +{
> + sati_32 11100 01..... ..... 100 ..... 0011011 @p_ui32
> + psati_w 11100 01..... ..... 100 ..... 0011011 @p_ui32
> +}
> +{
> + usati_32 10100 01..... ..... 100 ..... 0011011 @p_ui32
> + pusati_w 10100 01..... ..... 100 ..... 0011011 @p_ui32
> +}
> +sati_64 111001 ...... ..... 100 ..... 0011011 @p_ui64
> +usati_64 101001 ...... ..... 100 ..... 0011011 @p_ui64
> diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> new file mode 100644
> index 00000000000..056ccfb486e
> --- /dev/null
> +++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> @@ -0,0 +1,547 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* RISC-V translation routines for the P Standard Extensions. */
> +/* Copyright (c) 2026 ISRC ISCAS. */
> +
> +/* Save a 64 bit data in src to dst and dst + 1 */
> +
> +static bool require_rvp(DisasContext *ctx)
> +{
> + uint32_t opcode = ctx->opcode & 0x7f;
> +
> + if (!has_ext(ctx, RVP)) {
> + return false;
> + }
> +
> + /*
> + * P_VXSAT_EXCP is encoded in the TB flags only when P is implemented
> + * without Zve*, where stateen0.VXSAT controls the whole OP-32 and
> + * OP-IMM-32 P instruction spaces. When Zve* is present, this field
> + * remains NONE and vxsat access is checked by the VS path instead.
> + */
> + if ((opcode == 0x3b || opcode == 0x1b) &&
> + ctx->p_vxsat_excp != P_VXSAT_EXCP_NONE) {
> + ctx->virt_inst_excp =
> + ctx->p_vxsat_excp == P_VXSAT_EXCP_VIRTUAL;
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool prepare_rvp_vxsat(DisasContext *ctx)
> +{
> + if (!ctx->cfg_ptr->ext_zve32x) {
> + return true;
> + }
> +
> + if (ctx->mstatus_vs == EXT_STATUS_DISABLED) {
> + return false;
> + }
> +
> + mark_vs_dirty(ctx);
> + return true;
> +}
> +
> +#define REQUIRE_RVP(ctx) do { \
> + if (!require_rvp(ctx)) { \
> + return false; \
> + } \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_UNAVAILABLE_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_UNAVAILABLE_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_32_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_BODY(NAME, true); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_ACC_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + TCGv t = tcg_temp_new(); \
> + gen_helper_##NAME(t, tcg_env, src1, src2, dest); \
> + gen_set_gpr(ctx, a->rd, t); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_ACC(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_ACC_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_ACC_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_ACC_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_ACC_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_ACC_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_ACC_BODY(NAME, false); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_R1_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_R1(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_R1_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_R1_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_R1_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_R1_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_R1_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_R1_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_R1_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_R1_BODY(NAME, true); \
> +}
> +#endif
> +
> +#define GEN_SIMD_TRANS_IMM_BODY(NAME, VXSAT) \
> +do { \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv imm = tcg_constant_tl(a->imm); \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, src1, imm); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +} while (0)
> +
> +#define GEN_SIMD_TRANS_IMM(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +
> +#define GEN_SIMD_TRANS_IMM_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_IMM_32(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +#else
> +#define GEN_SIMD_TRANS_IMM_32(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_IMM_32_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_IMM_64(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_64(NAME)
> +#else
> +#define GEN_SIMD_TRANS_IMM_64(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, false); \
> +}
> +#define GEN_SIMD_TRANS_IMM_64_VXSAT(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_64BIT(ctx); \
> + GEN_SIMD_TRANS_IMM_BODY(NAME, true); \
> +}
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, SRC2) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv_i32 src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv_i32 src2 = SRC2; \
> + TCGv_i64 t = tcg_temp_new_i64(); \
> + gen_helper_##NAME(t, tcg_env, src1, src2); \
> + set_pair_regs(ctx, (a->rd) * 2, t); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) \
> + GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE))
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) \
> + GEN_SIMD_TRANS_REG_PAIR_SCALAR_OP(NAME, tcg_constant_i32(a->imm))
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, SRC2_0, SRC2_1, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv src2_0 = SRC2_0; \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv src2_1 = SRC2_1; \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2_0); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2_1); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
> + get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + get_gpr(ctx, (a->rs2) * 2, EXT_NONE), \
> + get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE), true)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_OP(INSN, HELPER, \
> + tcg_constant_tl(a->imm), tcg_constant_tl(a->imm), true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_OP(INSN, HELPER, true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, VXSAT) \
> +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \
> +{ \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
> + TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
> + gen_helper_##HELPER(dest_0, tcg_env, src1_0); \
> + gen_helper_##HELPER(dest_1, tcg_env, src1_1); \
> + gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
> + gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, false)
> +
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_OP(INSN, HELPER, true)
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#define GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(INSN, HELPER) \
> + GEN_SIMD_TRANS_UNAVAILABLE_32(INSN)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
> + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv_i64 t = tcg_temp_new_i64(); \
> + if (a->rd == 0) { \
> + tcg_gen_movi_i64(t, 0); \
> + } else { \
> + get_pair_regs(ctx, t, (a->rd) * 2); \
> + } \
> + gen_helper_##NAME(t, tcg_env, src1, src2, t); \
> + set_pair_regs(ctx, (a->rd) * 2, t); \
> + return true; \
> +}
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_ACC(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + TCGv_i32 src1_l; \
> + TCGv_i32 src1_h; \
> + TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
> + TCGv_i32 dest = dest_gpr(ctx, a->rd); \
> + if (a->rs1 == 0) { \
> + src1_l = tcg_temp_new_i32(); \
> + src1_h = tcg_temp_new_i32(); \
> + tcg_gen_movi_i32(src1_l, 0); \
> + tcg_gen_movi_i32(src1_h, 0); \
> + } else { \
> + src1_l = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
> + src1_h = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
> + } \
> + gen_helper_##NAME(dest, tcg_env, src1_l, src1_h, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +}
> +#else
> +#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +#if defined(TARGET_RISCV32)
> +#define GEN_SIMD_TRANS_PN_OP(NAME, SRC2, VXSAT) \
> +static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
> +{ \
> + REQUIRE_32BIT(ctx); \
> + REQUIRE_RVP(ctx); \
> + if (VXSAT && !prepare_rvp_vxsat(ctx)) { \
> + return false; \
> + } \
> + TCGv_i64 s1 = tcg_temp_new_i64(); \
> + if (a->rs1 == 0) { \
> + tcg_gen_mov_i64(s1, 0); \
> + } else { \
> + get_pair_regs(ctx, s1, a->rs1 * 2); \
> + } \
> + TCGv src2 = SRC2; \
> + TCGv dest = dest_gpr(ctx, a->rd); \
> + gen_helper_##NAME(dest, tcg_env, s1, src2); \
> + gen_set_gpr(ctx, a->rd, dest); \
> + return true; \
> +}
> +
> +#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), false)
> +
> +#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, tcg_constant_tl(a->imm), true)
> +
> +#define GEN_SIMD_TRANS_PN_OP_REG(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), false)
> +
> +#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) \
> + GEN_SIMD_TRANS_PN_OP(NAME, get_gpr(ctx, a->rs2, EXT_NONE), true)
> +#else
> +#define GEN_SIMD_TRANS_PN_OP_IMM(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_REG(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#define GEN_SIMD_TRANS_PN_OP_REG_VXSAT(NAME) GEN_SIMD_TRANS_UNAVAILABLE_32(NAME)
> +#endif
> +
> +/* Packed SIMD - Arithmetic Operations(Non-Saturating and Saturating) */
> +GEN_SIMD_TRANS(padd_b)
> +GEN_SIMD_TRANS(padd_h)
> +GEN_SIMD_TRANS_64(padd_w)
> +GEN_SIMD_TRANS(padd_bs)
> +GEN_SIMD_TRANS(padd_hs)
> +GEN_SIMD_TRANS_64(padd_ws)
> +GEN_SIMD_TRANS(psub_b)
> +GEN_SIMD_TRANS(psub_h)
> +GEN_SIMD_TRANS_64(psub_w)
> +GEN_SIMD_TRANS(psh1add_h)
> +GEN_SIMD_TRANS_64(psh1add_w)
> +GEN_SIMD_TRANS_VXSAT(pssh1sadd_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssh1sadd_w)
> +GEN_SIMD_TRANS_32_VXSAT(ssh1sadd)
> +GEN_SIMD_TRANS_VXSAT(psadd_b)
> +GEN_SIMD_TRANS_VXSAT(psadd_h)
> +GEN_SIMD_TRANS_64_VXSAT(psadd_w)
> +GEN_SIMD_TRANS_VXSAT(psaddu_b)
> +GEN_SIMD_TRANS_VXSAT(psaddu_h)
> +GEN_SIMD_TRANS_64_VXSAT(psaddu_w)
> +GEN_SIMD_TRANS_32_VXSAT(sadd)
> +GEN_SIMD_TRANS_32_VXSAT(saddu)
> +GEN_SIMD_TRANS_VXSAT(pssub_b)
> +GEN_SIMD_TRANS_VXSAT(pssub_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssub_w)
> +GEN_SIMD_TRANS_VXSAT(pssubu_b)
> +GEN_SIMD_TRANS_VXSAT(pssubu_h)
> +GEN_SIMD_TRANS_64_VXSAT(pssubu_w)
> +GEN_SIMD_TRANS_32_VXSAT(ssub)
> +GEN_SIMD_TRANS_32_VXSAT(ssubu)
> +GEN_SIMD_TRANS_IMM_VXSAT(psati_h)
> +GEN_SIMD_TRANS_IMM_VXSAT(pusati_h)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(psati_w)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(pusati_w)
> +GEN_SIMD_TRANS_IMM_32_VXSAT(sati_32)
> +GEN_SIMD_TRANS_IMM_32_VXSAT(usati_32)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(sati_64)
> +GEN_SIMD_TRANS_IMM_64_VXSAT(usati_64)
> +
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> index 2948bbb2a86..52c58e0287e 100644
> --- a/target/riscv/tcg/psimd_helper.c
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -1654,3 +1654,117 @@ uint32_t HELPER(NAME)(CPURISCVState *env, uint64_t s1, uint32_t shamt) \
>
> /* Basic addition operations (non-saturating) */
>
> +GEN_PSIMD_BINOP(padd_b, target_ulong, uint8_t, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP(padd_h, target_ulong, uint16_t, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP(padd_w, uint64_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +GEN_PSIMD_BINOP_SCALAR(padd_bs, target_ulong, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP_SCALAR(padd_hs, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_BINOP_SCALAR(padd_ws, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +/* Basic subtraction operations (non-saturating) */
> +
> +GEN_PSIMD_BINOP(psub_b, target_ulong, uint8_t, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
> +GEN_PSIMD_BINOP(psub_h, target_ulong, uint16_t, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
> +GEN_PSIMD_BINOP(psub_w, uint64_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +
> +/* Shift-left-by-one and add operations */
> +
> +GEN_PSIMD_SHADD(psh1add_h, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1)
> +GEN_PSIMD_SHADD(psh1add_w, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1)
> +
> +GEN_PSIMD_SAT_SHADD(pssh1sadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1, -0x4000, 0x3fff,
> + SAT_MIN_H, SAT_MAX_H, signed_saturate_h)
> +GEN_PSIMD_SAT_SHADD(pssh1sadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
> + 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
> +
> +GEN_PSIMD_SAT_SHADD(ssh1sadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1, -0x40000000,
> + 0x3fffffff, SAT_MIN_W, SAT_MAX_W, signed_saturate_w)
> +
> +/* Saturating addition operations */
> +
> +GEN_PSIMD_SAT_BINOP(psadd_b, target_ulong, int8_t, int32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
> + signed_saturate_b)
> +GEN_PSIMD_SAT_BINOP(psadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
> + signed_saturate_h)
> +GEN_PSIMD_SAT_BINOP(psadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + signed_saturate_w)
> +
> +GEN_PSIMD_SAT_BINOP(psaddu_b, target_ulong, uint8_t, uint32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD,
> + unsigned_saturate_b)
> +GEN_PSIMD_SAT_BINOP(psaddu_h, target_ulong, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD,
> + unsigned_saturate_h)
> +GEN_PSIMD_SAT_BINOP(psaddu_w, uint64_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + unsigned_saturate_w)
> +
> +GEN_PSIMD_SAT_BINOP(sadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + signed_saturate_w)
> +GEN_PSIMD_SAT_BINOP(saddu, uint32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD,
> + unsigned_saturate_w)
> +
> +/* Saturating subtraction operations */
> +
> +GEN_PSIMD_SAT_BINOP(pssub_b, target_ulong, int8_t, int32_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB,
> + signed_saturate_b)
> +GEN_PSIMD_SAT_BINOP(pssub_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB,
> + signed_saturate_h)
> +GEN_PSIMD_SAT_BINOP(pssub_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
> + signed_saturate_w)
> +
> +GEN_PSIMD_USUB_SAT(pssubu_b, target_ulong, uint8_t,
> + EXTRACT8, INSERT8, ELEMS_B)
> +GEN_PSIMD_USUB_SAT(pssubu_h, target_ulong, uint16_t,
> + EXTRACT16, INSERT16, ELEMS_H)
> +GEN_PSIMD_USUB_SAT(pssubu_w, uint64_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W)
> +
> +GEN_PSIMD_SAT_BINOP(ssub, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB,
> + signed_saturate_w)
> +GEN_PSIMD_USUB_SAT(ssubu, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W)
> +
> +/* Saturation instructions (SAT, USAT) */
> +
> +GEN_PSIMD_SATI(psati_h, target_ulong, int16_t, int64_t,
> + EXTRACT16, INSERT16, ELEMS_H, 0x0f)
> +GEN_PSIMD_USATI(pusati_h, target_ulong, int16_t, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, 1U)
> +GEN_PSIMD_SATI(psati_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 0x1f)
> +GEN_PSIMD_USATI(pusati_w, uint64_t, int32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1ULL)
> +GEN_PSIMD_SATI(sati_32, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, 0x1f)
> +GEN_PSIMD_USATI(usati_32, uint32_t, int32_t, uint32_t, uint32_t,
> + EXTRACT32, INSERT32, ELEMS_W, 1U)
> +GEN_PSIMD_SATI(sati_64, uint64_t, int64_t, int64_t,
> + EXTRACT64, INSERT64, ELEMS_D, 0x3f)
> +GEN_PSIMD_USATI(usati_64, uint64_t, int64_t, uint64_t, uint64_t,
> + EXTRACT64, INSERT64, ELEMS_D, 1ULL)
> +
> diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
> index 9684dbe7528..0df9d4190f1 100644
> --- a/target/riscv/tcg/translate.c
> +++ b/target/riscv/tcg/translate.c
> @@ -103,6 +103,7 @@ typedef struct DisasContext {
> bool vstart_eq_zero;
> bool vl_eq_vlmax;
> bool altfmt;
> + uint8_t p_vxsat_excp;
> CPUState *cs;
> TCGv zero;
> /* actual address width */
> @@ -1199,6 +1200,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
> #include "insn_trans/trans_rvh.c.inc"
> #include "insn_trans/trans_rvv.c.inc"
> #include "insn_trans/trans_rvb.c.inc"
> +#include "insn_trans/trans_rvp.c.inc"
> #include "insn_trans/trans_rvzicond.c.inc"
> #include "insn_trans/trans_rvzacas.c.inc"
> #include "insn_trans/trans_rvzabha.c.inc"
> @@ -1333,6 +1335,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
> ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
> ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
> ctx->altfmt = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS, ALTFMT);
> + ctx->p_vxsat_excp = FIELD_EX64(ext_tb_flags, EXT_TB_FLAGS,
> + P_VXSAT_EXCP);
> ctx->misa_mxl_max = mcc->def->misa_mxl_max;
> ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
> ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v2 04/18] target/riscv: Add packed SIMD averaging and rounding instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (2 preceding siblings ...)
2026-07-17 10:06 ` [PATCH v2 03/18] target/riscv: Add packed SIMD arithmetic instructions Molly Chen
@ 2026-07-17 10:06 ` Molly Chen
2026-07-27 18:58 ` Daniel Henrique Barboza
2026-07-17 10:06 ` [PATCH v2 05/18] target/riscv: Add packed SIMD absolute, difference, compare and mask instructions Molly Chen
` (15 subsequent siblings)
19 siblings, 1 reply; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:06 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 18 ++++++++++
target/riscv/insn32.decode | 26 ++++++++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 18 ++++++++++
target/riscv/tcg/psimd_helper.c | 40 +++++++++++++++++++++
4 files changed, 102 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index eebb2febd95..7256f776ae6 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1399,3 +1399,21 @@ DEF_HELPER_3(sati_32, i32, env, i32, i32)
DEF_HELPER_3(usati_32, i32, env, i32, i32)
DEF_HELPER_3(sati_64, i64, env, i64, i64)
DEF_HELPER_3(usati_64, i64, env, i64, i64)
+
+/* Packed SIMD - Averaging and Rounding Operations */
+DEF_HELPER_3(paadd_b, tl, env, tl, tl)
+DEF_HELPER_3(paadd_h, tl, env, tl, tl)
+DEF_HELPER_3(paadd_w, i64, env, i64, i64)
+DEF_HELPER_3(paaddu_b, tl, env, tl, tl)
+DEF_HELPER_3(paaddu_h, tl, env, tl, tl)
+DEF_HELPER_3(paaddu_w, i64, env, i64, i64)
+DEF_HELPER_3(aadd, i32, env, i32, i32)
+DEF_HELPER_3(aaddu, i32, env, i32, i32)
+DEF_HELPER_3(pasub_b, tl, env, tl, tl)
+DEF_HELPER_3(pasub_h, tl, env, tl, tl)
+DEF_HELPER_3(pasub_w, i64, env, i64, i64)
+DEF_HELPER_3(pasubu_b, tl, env, tl, tl)
+DEF_HELPER_3(pasubu_h, tl, env, tl, tl)
+DEF_HELPER_3(pasubu_w, i64, env, i64, i64)
+DEF_HELPER_3(asub, i32, env, i32, i32)
+DEF_HELPER_3(asubu, i32, env, i32, i32)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 8da13669d73..005cc055b8a 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1147,3 +1147,29 @@ pusati_h 10100 001.... ..... 100 ..... 0011011 @p_ui16
}
sati_64 111001 ...... ..... 100 ..... 0011011 @p_ui64
usati_64 101001 ...... ..... 100 ..... 0011011 @p_ui64
+
+# Packed SIMD - Averaging and Rounding Operations
+paadd_b 1001110 ..... ..... 000 ..... 0111011 @r
+paadd_h 1001100 ..... ..... 000 ..... 0111011 @r
+{
+ aadd 1001101 ..... ..... 000 ..... 0111011 @r
+ paadd_w 1001101 ..... ..... 000 ..... 0111011 @r
+}
+paaddu_b 1011110 ..... ..... 000 ..... 0111011 @r
+paaddu_h 1011100 ..... ..... 000 ..... 0111011 @r
+{
+ aaddu 1011101 ..... ..... 000 ..... 0111011 @r
+ paaddu_w 1011101 ..... ..... 000 ..... 0111011 @r
+}
+pasub_b 1101110 ..... ..... 000 ..... 0111011 @r
+pasub_h 1101100 ..... ..... 000 ..... 0111011 @r
+{
+ asub 1101101 ..... ..... 000 ..... 0111011 @r
+ pasub_w 1101101 ..... ..... 000 ..... 0111011 @r
+}
+pasubu_b 1111110 ..... ..... 000 ..... 0111011 @r
+pasubu_h 1111100 ..... ..... 000 ..... 0111011 @r
+{
+ asubu 1111101 ..... ..... 000 ..... 0111011 @r
+ pasubu_w 1111101 ..... ..... 000 ..... 0111011 @r
+}
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 056ccfb486e..43c59aef182 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -545,3 +545,21 @@ GEN_SIMD_TRANS_IMM_32_VXSAT(usati_32)
GEN_SIMD_TRANS_IMM_64_VXSAT(sati_64)
GEN_SIMD_TRANS_IMM_64_VXSAT(usati_64)
+/* Packed SIMD - Averaging and Rounding Operations */
+GEN_SIMD_TRANS(paadd_b)
+GEN_SIMD_TRANS(paadd_h)
+GEN_SIMD_TRANS_64(paadd_w)
+GEN_SIMD_TRANS(paaddu_b)
+GEN_SIMD_TRANS(paaddu_h)
+GEN_SIMD_TRANS_64(paaddu_w)
+GEN_SIMD_TRANS_32(aadd)
+GEN_SIMD_TRANS_32(aaddu)
+GEN_SIMD_TRANS(pasub_b)
+GEN_SIMD_TRANS(pasub_h)
+GEN_SIMD_TRANS_64(pasub_w)
+GEN_SIMD_TRANS(pasubu_b)
+GEN_SIMD_TRANS(pasubu_h)
+GEN_SIMD_TRANS_64(pasubu_w)
+GEN_SIMD_TRANS_32(asub)
+GEN_SIMD_TRANS_32(asubu)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 52c58e0287e..162041a8f18 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -1768,3 +1768,43 @@ GEN_PSIMD_SATI(sati_64, uint64_t, int64_t, int64_t,
GEN_PSIMD_USATI(usati_64, uint64_t, int64_t, uint64_t, uint64_t,
EXTRACT64, INSERT64, ELEMS_D, 1ULL)
+/* Averaging Operations (non-saturating) */
+
+GEN_PSIMD_AVG_BINOP(paadd_b, target_ulong, int8_t, int16_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
+GEN_PSIMD_AVG_BINOP(paadd_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
+GEN_PSIMD_AVG_BINOP(paadd_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
+
+GEN_PSIMD_AVG_BINOP(paaddu_b, target_ulong, uint8_t, uint16_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
+GEN_PSIMD_AVG_BINOP(paaddu_h, target_ulong, uint16_t, uint32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
+GEN_PSIMD_AVG_BINOP(paaddu_w, uint64_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
+
+GEN_PSIMD_AVG_BINOP(aadd, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
+GEN_PSIMD_AVG_BINOP(aaddu, uint32_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
+
+GEN_PSIMD_AVG_BINOP(pasub_b, target_ulong, int8_t, int16_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
+GEN_PSIMD_AVG_BINOP(pasub_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
+GEN_PSIMD_AVG_BINOP(pasub_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
+
+GEN_PSIMD_AVG_BINOP(pasubu_b, target_ulong, uint8_t, uint16_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
+GEN_PSIMD_AVG_BINOP(pasubu_h, target_ulong, uint16_t, uint32_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
+GEN_PSIMD_AVG_BINOP(pasubu_w, uint64_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
+
+GEN_PSIMD_AVG_BINOP(asub, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
+GEN_PSIMD_AVG_BINOP(asubu, uint32_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* Re: [PATCH v2 04/18] target/riscv: Add packed SIMD averaging and rounding instructions
2026-07-17 10:06 ` [PATCH v2 04/18] target/riscv: Add packed SIMD averaging and rounding instructions Molly Chen
@ 2026-07-27 18:58 ` Daniel Henrique Barboza
0 siblings, 0 replies; 34+ messages in thread
From: Daniel Henrique Barboza @ 2026-07-27 18:58 UTC (permalink / raw)
To: Molly Chen, palmer, alistair.francis, liwei1518, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: qemu-riscv, qemu-devel
On 7/17/2026 7:06 AM, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> target/riscv/helper.h | 18 ++++++++++
> target/riscv/insn32.decode | 26 ++++++++++++++
> target/riscv/tcg/insn_trans/trans_rvp.c.inc | 18 ++++++++++
> target/riscv/tcg/psimd_helper.c | 40 +++++++++++++++++++++
> 4 files changed, 102 insertions(+)
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index eebb2febd95..7256f776ae6 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1399,3 +1399,21 @@ DEF_HELPER_3(sati_32, i32, env, i32, i32)
> DEF_HELPER_3(usati_32, i32, env, i32, i32)
> DEF_HELPER_3(sati_64, i64, env, i64, i64)
> DEF_HELPER_3(usati_64, i64, env, i64, i64)
> +
> +/* Packed SIMD - Averaging and Rounding Operations */
> +DEF_HELPER_3(paadd_b, tl, env, tl, tl)
> +DEF_HELPER_3(paadd_h, tl, env, tl, tl)
> +DEF_HELPER_3(paadd_w, i64, env, i64, i64)
> +DEF_HELPER_3(paaddu_b, tl, env, tl, tl)
> +DEF_HELPER_3(paaddu_h, tl, env, tl, tl)
> +DEF_HELPER_3(paaddu_w, i64, env, i64, i64)
> +DEF_HELPER_3(aadd, i32, env, i32, i32)
> +DEF_HELPER_3(aaddu, i32, env, i32, i32)
> +DEF_HELPER_3(pasub_b, tl, env, tl, tl)
> +DEF_HELPER_3(pasub_h, tl, env, tl, tl)
> +DEF_HELPER_3(pasub_w, i64, env, i64, i64)
> +DEF_HELPER_3(pasubu_b, tl, env, tl, tl)
> +DEF_HELPER_3(pasubu_h, tl, env, tl, tl)
> +DEF_HELPER_3(pasubu_w, i64, env, i64, i64)
> +DEF_HELPER_3(asub, i32, env, i32, i32)
> +DEF_HELPER_3(asubu, i32, env, i32, i32)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 8da13669d73..005cc055b8a 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -1147,3 +1147,29 @@ pusati_h 10100 001.... ..... 100 ..... 0011011 @p_ui16
> }
> sati_64 111001 ...... ..... 100 ..... 0011011 @p_ui64
> usati_64 101001 ...... ..... 100 ..... 0011011 @p_ui64
> +
> +# Packed SIMD - Averaging and Rounding Operations
> +paadd_b 1001110 ..... ..... 000 ..... 0111011 @r
> +paadd_h 1001100 ..... ..... 000 ..... 0111011 @r
> +{
> + aadd 1001101 ..... ..... 000 ..... 0111011 @r
> + paadd_w 1001101 ..... ..... 000 ..... 0111011 @r
> +}
> +paaddu_b 1011110 ..... ..... 000 ..... 0111011 @r
> +paaddu_h 1011100 ..... ..... 000 ..... 0111011 @r
> +{
> + aaddu 1011101 ..... ..... 000 ..... 0111011 @r
> + paaddu_w 1011101 ..... ..... 000 ..... 0111011 @r
> +}
> +pasub_b 1101110 ..... ..... 000 ..... 0111011 @r
> +pasub_h 1101100 ..... ..... 000 ..... 0111011 @r
> +{
> + asub 1101101 ..... ..... 000 ..... 0111011 @r
> + pasub_w 1101101 ..... ..... 000 ..... 0111011 @r
> +}
> +pasubu_b 1111110 ..... ..... 000 ..... 0111011 @r
> +pasubu_h 1111100 ..... ..... 000 ..... 0111011 @r
> +{
> + asubu 1111101 ..... ..... 000 ..... 0111011 @r
> + pasubu_w 1111101 ..... ..... 000 ..... 0111011 @r
> +}
> diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> index 056ccfb486e..43c59aef182 100644
> --- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> +++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> @@ -545,3 +545,21 @@ GEN_SIMD_TRANS_IMM_32_VXSAT(usati_32)
> GEN_SIMD_TRANS_IMM_64_VXSAT(sati_64)
> GEN_SIMD_TRANS_IMM_64_VXSAT(usati_64)
>
> +/* Packed SIMD - Averaging and Rounding Operations */
> +GEN_SIMD_TRANS(paadd_b)
> +GEN_SIMD_TRANS(paadd_h)
> +GEN_SIMD_TRANS_64(paadd_w)
> +GEN_SIMD_TRANS(paaddu_b)
> +GEN_SIMD_TRANS(paaddu_h)
> +GEN_SIMD_TRANS_64(paaddu_w)
> +GEN_SIMD_TRANS_32(aadd)
> +GEN_SIMD_TRANS_32(aaddu)
> +GEN_SIMD_TRANS(pasub_b)
> +GEN_SIMD_TRANS(pasub_h)
> +GEN_SIMD_TRANS_64(pasub_w)
> +GEN_SIMD_TRANS(pasubu_b)
> +GEN_SIMD_TRANS(pasubu_h)
> +GEN_SIMD_TRANS_64(pasubu_w)
> +GEN_SIMD_TRANS_32(asub)
> +GEN_SIMD_TRANS_32(asubu)
> +
> diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
> index 52c58e0287e..162041a8f18 100644
> --- a/target/riscv/tcg/psimd_helper.c
> +++ b/target/riscv/tcg/psimd_helper.c
> @@ -1768,3 +1768,43 @@ GEN_PSIMD_SATI(sati_64, uint64_t, int64_t, int64_t,
> GEN_PSIMD_USATI(usati_64, uint64_t, int64_t, uint64_t, uint64_t,
> EXTRACT64, INSERT64, ELEMS_D, 1ULL)
>
> +/* Averaging Operations (non-saturating) */
> +
> +GEN_PSIMD_AVG_BINOP(paadd_b, target_ulong, int8_t, int16_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_AVG_BINOP(paadd_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_AVG_BINOP(paadd_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +GEN_PSIMD_AVG_BINOP(paaddu_b, target_ulong, uint8_t, uint16_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ADD)
> +GEN_PSIMD_AVG_BINOP(paaddu_h, target_ulong, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ADD)
> +GEN_PSIMD_AVG_BINOP(paaddu_w, uint64_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +GEN_PSIMD_AVG_BINOP(aadd, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +GEN_PSIMD_AVG_BINOP(aaddu, uint32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_ADD)
> +
> +GEN_PSIMD_AVG_BINOP(pasub_b, target_ulong, int8_t, int16_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
> +GEN_PSIMD_AVG_BINOP(pasub_h, target_ulong, int16_t, int32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
> +GEN_PSIMD_AVG_BINOP(pasub_w, uint64_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +
> +GEN_PSIMD_AVG_BINOP(pasubu_b, target_ulong, uint8_t, uint16_t,
> + EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_SUB)
> +GEN_PSIMD_AVG_BINOP(pasubu_h, target_ulong, uint16_t, uint32_t,
> + EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_SUB)
> +GEN_PSIMD_AVG_BINOP(pasubu_w, uint64_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +
> +GEN_PSIMD_AVG_BINOP(asub, uint32_t, int32_t, int64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +GEN_PSIMD_AVG_BINOP(asubu, uint32_t, uint32_t, uint64_t,
> + EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
> +
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v2 05/18] target/riscv: Add packed SIMD absolute, difference, compare and mask instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (3 preceding siblings ...)
2026-07-17 10:06 ` [PATCH v2 04/18] target/riscv: Add packed SIMD averaging and rounding instructions Molly Chen
@ 2026-07-17 10:06 ` Molly Chen
2026-07-17 10:06 ` [PATCH v2 06/18] target/riscv: Add packed SIMD shift instructions Molly Chen
` (14 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:06 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 38 +++++++++
target/riscv/insn32.decode | 44 ++++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 38 +++++++++
target/riscv/tcg/psimd_helper.c | 95 +++++++++++++++++++++
4 files changed, 215 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 7256f776ae6..1628ca119ac 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1417,3 +1417,41 @@ DEF_HELPER_3(pasubu_h, tl, env, tl, tl)
DEF_HELPER_3(pasubu_w, i64, env, i64, i64)
DEF_HELPER_3(asub, i32, env, i32, i32)
DEF_HELPER_3(asubu, i32, env, i32, i32)
+
+/* Packed SIMD - Absolute Value and Difference Operations */
+DEF_HELPER_2(psabs_b, tl, env, tl)
+DEF_HELPER_2(psabs_h, tl, env, tl)
+DEF_HELPER_2(abs, tl, env, tl)
+DEF_HELPER_2(absw, i64, env, i64)
+DEF_HELPER_3(pabd_b, tl, env, tl, tl)
+DEF_HELPER_3(pabdu_b, tl, env, tl, tl)
+DEF_HELPER_3(pabd_h, tl, env, tl, tl)
+DEF_HELPER_3(pabdu_h, tl, env, tl, tl)
+DEF_HELPER_3(pabdsumu_b, tl, env, tl, tl)
+DEF_HELPER_4(pabdsumau_b, tl, env, tl, tl, tl)
+
+/* Packed SIMD - Comparison and Mask Generation Operations */
+DEF_HELPER_3(pmseq_b, tl, env, tl, tl)
+DEF_HELPER_3(pmslt_b, tl, env, tl, tl)
+DEF_HELPER_3(pmsltu_b, tl, env, tl, tl)
+DEF_HELPER_3(pmin_b, tl, env, tl, tl)
+DEF_HELPER_3(pminu_b, tl, env, tl, tl)
+DEF_HELPER_3(pmax_b, tl, env, tl, tl)
+DEF_HELPER_3(pmaxu_b, tl, env, tl, tl)
+DEF_HELPER_3(pmseq_h, tl, env, tl, tl)
+DEF_HELPER_3(pmslt_h, tl, env, tl, tl)
+DEF_HELPER_3(pmsltu_h, tl, env, tl, tl)
+DEF_HELPER_3(pmin_h, tl, env, tl, tl)
+DEF_HELPER_3(pminu_h, tl, env, tl, tl)
+DEF_HELPER_3(pmax_h, tl, env, tl, tl)
+DEF_HELPER_3(pmaxu_h, tl, env, tl, tl)
+DEF_HELPER_3(pmseq_w, i64, env, i64, i64)
+DEF_HELPER_3(pmslt_w, i64, env, i64, i64)
+DEF_HELPER_3(pmsltu_w, i64, env, i64, i64)
+DEF_HELPER_3(pmin_w, i64, env, i64, i64)
+DEF_HELPER_3(pminu_w, i64, env, i64, i64)
+DEF_HELPER_3(pmax_w, i64, env, i64, i64)
+DEF_HELPER_3(pmaxu_w, i64, env, i64, i64)
+DEF_HELPER_3(mseq, i32, env, i32, i32)
+DEF_HELPER_3(mslt, i32, env, i32, i32)
+DEF_HELPER_3(msltu, i32, env, i32, i32)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 005cc055b8a..0c60f2eac7a 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1173,3 +1173,47 @@ pasubu_h 1111100 ..... ..... 000 ..... 0111011 @r
asubu 1111101 ..... ..... 000 ..... 0111011 @r
pasubu_w 1111101 ..... ..... 000 ..... 0111011 @r
}
+
+# Packed SIMD - Absolute Value and Difference Operations
+psabs_b 1110010 00111 ..... 010 ..... 0011011 @r2
+psabs_h 1110000 00111 ..... 010 ..... 0011011 @r2
+abs 01100 0000111 ..... 001 ..... 0010011 @r2
+absw 01100 0000111 ..... 001 ..... 0011011 @r2
+pabd_b 1100110 ..... ..... 000 ..... 0111011 @r
+pabdu_b 1110110 ..... ..... 000 ..... 0111011 @r
+pabd_h 1100100 ..... ..... 000 ..... 0111011 @r
+pabdu_h 1110100 ..... ..... 000 ..... 0111011 @r
+pabdsumu_b 1011010 ..... ..... 001 ..... 0111011 @r
+pabdsumau_b 1011110 ..... ..... 001 ..... 0111011 @r
+
+# Packed SIMD - Comparison and Mask Generation Operations
+pmseq_b 1100010 ..... ..... 110 ..... 0111011 @r
+pmslt_b 1101010 ..... ..... 110 ..... 0111011 @r
+pmsltu_b 1101110 ..... ..... 110 ..... 0111011 @r
+pmin_b 1110010 ..... ..... 110 ..... 0111011 @r
+pminu_b 1110110 ..... ..... 110 ..... 0111011 @r
+pmax_b 1111010 ..... ..... 110 ..... 0111011 @r
+pmaxu_b 1111110 ..... ..... 110 ..... 0111011 @r
+pmseq_h 1100000 ..... ..... 110 ..... 0111011 @r
+pmslt_h 1101000 ..... ..... 110 ..... 0111011 @r
+pmsltu_h 1101100 ..... ..... 110 ..... 0111011 @r
+pmin_h 1110000 ..... ..... 110 ..... 0111011 @r
+pminu_h 1110100 ..... ..... 110 ..... 0111011 @r
+pmax_h 1111000 ..... ..... 110 ..... 0111011 @r
+pmaxu_h 1111100 ..... ..... 110 ..... 0111011 @r
+{
+ mseq 1100001 ..... ..... 110 ..... 0111011 @r
+ pmseq_w 1100001 ..... ..... 110 ..... 0111011 @r
+}
+{
+ mslt 1101001 ..... ..... 110 ..... 0111011 @r
+ pmslt_w 1101001 ..... ..... 110 ..... 0111011 @r
+}
+{
+ msltu 1101101 ..... ..... 110 ..... 0111011 @r
+ pmsltu_w 1101101 ..... ..... 110 ..... 0111011 @r
+}
+pmin_w 1110001 ..... ..... 110 ..... 0111011 @r
+pminu_w 1110101 ..... ..... 110 ..... 0111011 @r
+pmax_w 1111001 ..... ..... 110 ..... 0111011 @r
+pmaxu_w 1111101 ..... ..... 110 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 43c59aef182..2ad8e818ba5 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -563,3 +563,41 @@ GEN_SIMD_TRANS_64(pasubu_w)
GEN_SIMD_TRANS_32(asub)
GEN_SIMD_TRANS_32(asubu)
+/* Packed SIMD - Absolute Value and Difference Operations */
+GEN_SIMD_TRANS_R1_VXSAT(psabs_b)
+GEN_SIMD_TRANS_R1_VXSAT(psabs_h)
+GEN_SIMD_TRANS_R1(abs)
+GEN_SIMD_TRANS_R1_64(absw)
+GEN_SIMD_TRANS(pabd_b)
+GEN_SIMD_TRANS(pabdu_b)
+GEN_SIMD_TRANS(pabd_h)
+GEN_SIMD_TRANS(pabdu_h)
+GEN_SIMD_TRANS(pabdsumu_b)
+GEN_SIMD_TRANS_ACC(pabdsumau_b)
+
+/* Packed SIMD - Comparison and Mask Generation Operations */
+GEN_SIMD_TRANS(pmseq_b)
+GEN_SIMD_TRANS(pmslt_b)
+GEN_SIMD_TRANS(pmsltu_b)
+GEN_SIMD_TRANS(pmin_b)
+GEN_SIMD_TRANS(pminu_b)
+GEN_SIMD_TRANS(pmax_b)
+GEN_SIMD_TRANS(pmaxu_b)
+GEN_SIMD_TRANS(pmseq_h)
+GEN_SIMD_TRANS(pmslt_h)
+GEN_SIMD_TRANS(pmsltu_h)
+GEN_SIMD_TRANS(pmin_h)
+GEN_SIMD_TRANS(pminu_h)
+GEN_SIMD_TRANS(pmax_h)
+GEN_SIMD_TRANS(pmaxu_h)
+GEN_SIMD_TRANS_64(pmseq_w)
+GEN_SIMD_TRANS_64(pmslt_w)
+GEN_SIMD_TRANS_64(pmsltu_w)
+GEN_SIMD_TRANS_64(pmin_w)
+GEN_SIMD_TRANS_64(pminu_w)
+GEN_SIMD_TRANS_64(pmax_w)
+GEN_SIMD_TRANS_64(pmaxu_w)
+GEN_SIMD_TRANS_32(mseq)
+GEN_SIMD_TRANS_32(mslt)
+GEN_SIMD_TRANS_32(msltu)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 162041a8f18..034afe5a054 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -1808,3 +1808,98 @@ GEN_PSIMD_AVG_BINOP(asub, uint32_t, int32_t, int64_t,
GEN_PSIMD_AVG_BINOP(asubu, uint32_t, uint32_t, uint64_t,
EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_SUB)
+/* Absolute value operations */
+
+GEN_PSIMD_ABS(psabs_b, target_ulong, int8_t,
+ EXTRACT8, INSERT8, ELEMS_B, INT8_MIN, INT8_MAX)
+GEN_PSIMD_ABS(psabs_h, target_ulong, int16_t,
+ EXTRACT16, INSERT16, ELEMS_H, INT16_MIN, INT16_MAX)
+
+GEN_PSIMD_SCALAR_ABS(abs, target_ulong, target_long, target_ulong)
+GEN_PSIMD_SCALAR_ABS(absw, uint64_t, int32_t, uint32_t)
+
+/* Absolute difference operations */
+
+GEN_PSIMD_BINOP(pabd_b, target_ulong, int8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ABD)
+GEN_PSIMD_BINOP(pabdu_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_ABD)
+GEN_PSIMD_BINOP(pabd_h, target_ulong, int16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ABD)
+GEN_PSIMD_BINOP(pabdu_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_ABD)
+
+/**
+ * PABDSUMU.B - Sum of unsigned absolute differences
+ * Returns sum(|rs1[i] - rs2[i]|) for all bytes
+ */
+target_ulong HELPER(pabdsumu_b)(CPURISCVState *env,
+ target_ulong rs1, target_ulong rs2)
+{
+ return psimd_abdsumu_b(rs1, rs2, 0);
+}
+
+/**
+ * PABDSUMAU.B - Accumulated sum of unsigned absolute differences
+ * rd = rd + sum(|rs1[i] - rs2[i]|)
+ */
+target_ulong HELPER(pabdsumau_b)(CPURISCVState *env, target_ulong rs1,
+ target_ulong rs2, target_ulong rd)
+{
+ return psimd_abdsumu_b(rs1, rs2, rd);
+}
+
+/* Comparison operations (producing masks) */
+
+GEN_PSIMD_BINOP(pmseq_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_EQ_MASK)
+GEN_PSIMD_BINOP(pmslt_b, target_ulong, int8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(pmsltu_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(pmin_b, target_ulong, int8_t, int8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_MIN)
+GEN_PSIMD_BINOP(pminu_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_MIN)
+GEN_PSIMD_BINOP(pmax_b, target_ulong, int8_t, int8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_MAX)
+GEN_PSIMD_BINOP(pmaxu_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, PSIMD_DO_MAX)
+
+GEN_PSIMD_BINOP(pmseq_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_EQ_MASK)
+GEN_PSIMD_BINOP(pmslt_h, target_ulong, int16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(pmsltu_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(pmin_h, target_ulong, int16_t, int16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_MIN)
+GEN_PSIMD_BINOP(pminu_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_MIN)
+GEN_PSIMD_BINOP(pmax_h, target_ulong, int16_t, int16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_MAX)
+GEN_PSIMD_BINOP(pmaxu_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, PSIMD_DO_MAX)
+
+GEN_PSIMD_BINOP(pmseq_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_EQ_MASK)
+GEN_PSIMD_BINOP(pmslt_w, uint64_t, int32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(pmsltu_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(pmin_w, uint64_t, int32_t, int32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_MIN)
+GEN_PSIMD_BINOP(pminu_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_MIN)
+GEN_PSIMD_BINOP(pmax_w, uint64_t, int32_t, int32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_MAX)
+GEN_PSIMD_BINOP(pmaxu_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_MAX)
+
+GEN_PSIMD_BINOP(mseq, uint32_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_EQ_MASK)
+GEN_PSIMD_BINOP(mslt, uint32_t, int32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_LT_MASK)
+GEN_PSIMD_BINOP(msltu, uint32_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_LT_MASK)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 06/18] target/riscv: Add packed SIMD shift instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (4 preceding siblings ...)
2026-07-17 10:06 ` [PATCH v2 05/18] target/riscv: Add packed SIMD absolute, difference, compare and mask instructions Molly Chen
@ 2026-07-17 10:06 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 07/18] target/riscv: Add packed SIMD exchange instructions Molly Chen
` (13 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:06 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 43 ++++++
target/riscv/insn32.decode | 57 ++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 43 ++++++
target/riscv/tcg/psimd_helper.c | 149 ++++++++++++++++++++
4 files changed, 292 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 1628ca119ac..d72323890f6 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1455,3 +1455,46 @@ DEF_HELPER_3(pmaxu_w, i64, env, i64, i64)
DEF_HELPER_3(mseq, i32, env, i32, i32)
DEF_HELPER_3(mslt, i32, env, i32, i32)
DEF_HELPER_3(msltu, i32, env, i32, i32)
+
+/* Packed SIMD - Shift Operations */
+DEF_HELPER_3(pslli_b, tl, env, tl, tl)
+DEF_HELPER_3(psll_bs, tl, env, tl, tl)
+DEF_HELPER_3(pslli_h, tl, env, tl, tl)
+DEF_HELPER_3(psll_hs, tl, env, tl, tl)
+DEF_HELPER_3(pslli_w, i64, env, i64, i64)
+DEF_HELPER_3(psll_ws, i64, env, i64, i64)
+DEF_HELPER_3(psrli_b, tl, env, tl, tl)
+DEF_HELPER_3(psrl_bs, tl, env, tl, tl)
+DEF_HELPER_3(psrli_h, tl, env, tl, tl)
+DEF_HELPER_3(psrl_hs, tl, env, tl, tl)
+DEF_HELPER_3(psrli_w, i64, env, i64, i64)
+DEF_HELPER_3(psrl_ws, i64, env, i64, i64)
+DEF_HELPER_3(psrai_b, tl, env, tl, tl)
+DEF_HELPER_3(psra_bs, tl, env, tl, tl)
+DEF_HELPER_3(psrai_h, tl, env, tl, tl)
+DEF_HELPER_3(psra_hs, tl, env, tl, tl)
+DEF_HELPER_3(psrai_w, i64, env, i64, i64)
+DEF_HELPER_3(psra_ws, i64, env, i64, i64)
+DEF_HELPER_3(psslai_h, tl, env, tl, tl)
+DEF_HELPER_3(psslai_w, i64, env, i64, i64)
+DEF_HELPER_3(sslai, i32, env, i32, i32)
+DEF_HELPER_3(psrari_h, tl, env, tl, tl)
+DEF_HELPER_3(psrari_w, i64, env, i64, i64)
+DEF_HELPER_3(srari_32, i32, env, i32, i32)
+DEF_HELPER_3(srari_64, i64, env, i64, i64)
+DEF_HELPER_3(pssha_hs, tl, env, tl, tl)
+DEF_HELPER_3(pssha_ws, i64, env, i64, i64)
+DEF_HELPER_3(psshar_hs, tl, env, tl, tl)
+DEF_HELPER_3(psshar_ws, i64, env, i64, i64)
+DEF_HELPER_3(ssha, i32, env, i32, i32)
+DEF_HELPER_3(sshar, i32, env, i32, i32)
+DEF_HELPER_3(sha, i64, env, i64, i64)
+DEF_HELPER_3(shar, i64, env, i64, i64)
+DEF_HELPER_3(psshl_hs, tl, env, tl, tl)
+DEF_HELPER_3(psshlr_hs, tl, env, tl, tl)
+DEF_HELPER_3(psshl_ws, i64, env, i64, i64)
+DEF_HELPER_3(psshlr_ws, i64, env, i64, i64)
+DEF_HELPER_3(sshl, i32, env, i32, i32)
+DEF_HELPER_3(sshlr, i32, env, i32, i32)
+DEF_HELPER_3(shl, i64, env, i64, i64)
+DEF_HELPER_3(shlr, i64, env, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 0c60f2eac7a..fb029bb512f 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -40,6 +40,7 @@
%imm_z6 26:1 15:5
%imm_mop5 30:1 26:2 20:2
%imm_mop3 30:1 26:2
+%imm_p_ui8 20:3
%imm_p_ui16 20:4
%imm_p_ui32 20:5
%imm_p_ui64 20:6
@@ -109,6 +110,7 @@
@mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1
@mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2
+@p_ui8 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui8 %rs1 %rd
@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd
@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd
@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd
@@ -1217,3 +1219,58 @@ pmin_w 1110001 ..... ..... 110 ..... 0111011 @r
pminu_w 1110101 ..... ..... 110 ..... 0111011 @r
pmax_w 1111001 ..... ..... 110 ..... 0111011 @r
pmaxu_w 1111101 ..... ..... 110 ..... 0111011 @r
+
+# Packed SIMD - Shift Operations
+pslli_b 10000 0001... ..... 010 ..... 0011011 @p_ui8
+psll_bs 1000110 ..... ..... 010 ..... 0011011 @r
+pslli_h 10000 001.... ..... 010 ..... 0011011 @p_ui16
+psll_hs 1000100 ..... ..... 010 ..... 0011011 @r
+pslli_w 10000 01..... ..... 010 ..... 0011011 @p_ui32
+psll_ws 1000101 ..... ..... 010 ..... 0011011 @r
+psrli_b 10000 0001... ..... 100 ..... 0011011 @p_ui8
+psrl_bs 1000110 ..... ..... 100 ..... 0011011 @r
+psrli_h 10000 001.... ..... 100 ..... 0011011 @p_ui16
+psrl_hs 1000100 ..... ..... 100 ..... 0011011 @r
+psrli_w 10000 01..... ..... 100 ..... 0011011 @p_ui32
+psrl_ws 1000101 ..... ..... 100 ..... 0011011 @r
+psrai_b 11000 0001... ..... 100 ..... 0011011 @p_ui8
+psra_bs 1100110 ..... ..... 100 ..... 0011011 @r
+psrai_h 11000 001.... ..... 100 ..... 0011011 @p_ui16
+psra_hs 1100100 ..... ..... 100 ..... 0011011 @r
+psrai_w 11000 01..... ..... 100 ..... 0011011 @p_ui32
+psra_ws 1100101 ..... ..... 100 ..... 0011011 @r
+psslai_h 11010 001.... ..... 010 ..... 0011011 @p_ui16
+{
+ sslai 11010 01..... ..... 010 ..... 0011011 @p_ui32
+ psslai_w 11010 01..... ..... 010 ..... 0011011 @p_ui32
+}
+psrari_h 11010 001.... ..... 100 ..... 0011011 @p_ui16
+{
+ srari_32 11010 01..... ..... 100 ..... 0011011 @p_ui32
+ psrari_w 11010 01..... ..... 100 ..... 0011011 @p_ui32
+}
+srari_64 110101 ...... ..... 100 ..... 0011011 @p_ui64
+pssha_hs 1110100 ..... ..... 010 ..... 0011011 @r
+{
+ ssha 1110101 ..... ..... 010 ..... 0011011 @r
+ pssha_ws 1110101 ..... ..... 010 ..... 0011011 @r
+}
+psshar_hs 1111100 ..... ..... 010 ..... 0011011 @r
+{
+ sshar 1111101 ..... ..... 010 ..... 0011011 @r
+ psshar_ws 1111101 ..... ..... 010 ..... 0011011 @r
+}
+sha 1110111 ..... ..... 010 ..... 0011011 @r
+shar 1111111 ..... ..... 010 ..... 0011011 @r
+psshl_hs 1010100 ..... ..... 010 ..... 0011011 @r
+psshlr_hs 1011100 ..... ..... 010 ..... 0011011 @r
+{
+ psshl_ws 1010101 ..... ..... 010 ..... 0011011 @r
+ sshl 1010101 ..... ..... 010 ..... 0011011 @r
+}
+{
+ psshlr_ws 1011101 ..... ..... 010 ..... 0011011 @r
+ sshlr 1011101 ..... ..... 010 ..... 0011011 @r
+}
+shl 1010111 ..... ..... 010 ..... 0011011 @r
+shlr 1011111 ..... ..... 010 ..... 0011011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 2ad8e818ba5..fb82760a60c 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -601,3 +601,46 @@ GEN_SIMD_TRANS_32(mseq)
GEN_SIMD_TRANS_32(mslt)
GEN_SIMD_TRANS_32(msltu)
+/* Packed SIMD - Shift Operations */
+GEN_SIMD_TRANS_IMM(pslli_b)
+GEN_SIMD_TRANS(psll_bs)
+GEN_SIMD_TRANS_IMM(pslli_h)
+GEN_SIMD_TRANS(psll_hs)
+GEN_SIMD_TRANS_IMM_64(pslli_w)
+GEN_SIMD_TRANS_64(psll_ws)
+GEN_SIMD_TRANS_IMM(psrli_b)
+GEN_SIMD_TRANS(psrl_bs)
+GEN_SIMD_TRANS_IMM(psrli_h)
+GEN_SIMD_TRANS(psrl_hs)
+GEN_SIMD_TRANS_IMM_64(psrli_w)
+GEN_SIMD_TRANS_64(psrl_ws)
+GEN_SIMD_TRANS_IMM(psrai_b)
+GEN_SIMD_TRANS(psra_bs)
+GEN_SIMD_TRANS_IMM(psrai_h)
+GEN_SIMD_TRANS(psra_hs)
+GEN_SIMD_TRANS_IMM_64(psrai_w)
+GEN_SIMD_TRANS_64(psra_ws)
+GEN_SIMD_TRANS_IMM_VXSAT(psslai_h)
+GEN_SIMD_TRANS_IMM_64_VXSAT(psslai_w)
+GEN_SIMD_TRANS_IMM_32_VXSAT(sslai)
+GEN_SIMD_TRANS_IMM(psrari_h)
+GEN_SIMD_TRANS_IMM_64(psrari_w)
+GEN_SIMD_TRANS_IMM_32(srari_32)
+GEN_SIMD_TRANS_IMM_64(srari_64)
+GEN_SIMD_TRANS_VXSAT(pssha_hs)
+GEN_SIMD_TRANS_64_VXSAT(pssha_ws)
+GEN_SIMD_TRANS_VXSAT(psshar_hs)
+GEN_SIMD_TRANS_64_VXSAT(psshar_ws)
+GEN_SIMD_TRANS_32_VXSAT(ssha)
+GEN_SIMD_TRANS_32_VXSAT(sshar)
+GEN_SIMD_TRANS_64(sha)
+GEN_SIMD_TRANS_64(shar)
+GEN_SIMD_TRANS_VXSAT(psshl_hs)
+GEN_SIMD_TRANS_VXSAT(psshlr_hs)
+GEN_SIMD_TRANS_64_VXSAT(psshl_ws)
+GEN_SIMD_TRANS_64_VXSAT(psshlr_ws)
+GEN_SIMD_TRANS_32_VXSAT(sshl)
+GEN_SIMD_TRANS_32_VXSAT(sshlr)
+GEN_SIMD_TRANS_64(shl)
+GEN_SIMD_TRANS_64(shlr)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 034afe5a054..8b106a336f5 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -1903,3 +1903,152 @@ GEN_PSIMD_BINOP(mslt, uint32_t, int32_t, uint32_t,
GEN_PSIMD_BINOP(msltu, uint32_t, uint32_t, uint32_t,
EXTRACT32, INSERT32, ELEMS_W, PSIMD_DO_LT_MASK)
+/* Shift operations (immediate and register) */
+
+GEN_PSIMD_SHIFTOP(pslli_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, 0x07, PSIMD_DO_SLL)
+GEN_PSIMD_SHIFTOP(psll_bs, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, 0x07, PSIMD_DO_SLL)
+GEN_PSIMD_SHIFTOP(pslli_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f, PSIMD_DO_SLL)
+GEN_PSIMD_SHIFTOP(psll_hs, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f, PSIMD_DO_SLL)
+GEN_PSIMD_SHIFTOP(pslli_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f, PSIMD_DO_SLL)
+GEN_PSIMD_SHIFTOP(psll_ws, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f, PSIMD_DO_SLL)
+
+GEN_PSIMD_SHIFTOP(psrli_b, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, 0x07, PSIMD_DO_SRL)
+GEN_PSIMD_SHIFTOP(psrl_bs, target_ulong, uint8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, 0x07, PSIMD_DO_SRL)
+GEN_PSIMD_SHIFTOP(psrli_h, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f, PSIMD_DO_SRL)
+GEN_PSIMD_SHIFTOP(psrl_hs, target_ulong, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f, PSIMD_DO_SRL)
+GEN_PSIMD_SHIFTOP(psrli_w, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f, PSIMD_DO_SRL)
+GEN_PSIMD_SHIFTOP(psrl_ws, uint64_t, uint32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f, PSIMD_DO_SRL)
+
+GEN_PSIMD_SHIFTOP(psrai_b, target_ulong, int8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, 0x07, PSIMD_DO_SRA)
+GEN_PSIMD_SHIFTOP(psra_bs, target_ulong, int8_t, uint8_t,
+ EXTRACT8, INSERT8, ELEMS_B, 0x07, PSIMD_DO_SRA)
+GEN_PSIMD_SHIFTOP(psrai_h, target_ulong, int16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f, PSIMD_DO_SRA)
+GEN_PSIMD_SHIFTOP(psra_hs, target_ulong, int16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f, PSIMD_DO_SRA)
+GEN_PSIMD_SHIFTOP(psrai_w, uint64_t, int32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f, PSIMD_DO_SRA)
+GEN_PSIMD_SHIFTOP(psra_ws, uint64_t, int32_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f, PSIMD_DO_SRA)
+
+/* Saturating shift operations */
+
+GEN_PSIMD_SAT_SHIFTOP(psslai_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f,
+ signed_saturate_h)
+GEN_PSIMD_SAT_SHIFTOP(psslai_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f,
+ signed_saturate_w)
+
+GEN_PSIMD_SAT_SHIFTOP(sslai, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f,
+ signed_saturate_w)
+
+/* Rounding shift operations */
+
+GEN_PSIMD_ROUND_SRAI(psrari_h, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x0f)
+GEN_PSIMD_ROUND_SRAI(psrari_w, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f)
+
+GEN_PSIMD_ROUND_SRAI(srari_32, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x1f)
+
+/**
+ * SRARI_64 - 64-bit scalar arithmetic shift right with rounding
+ */
+uint64_t HELPER(srari_64)(CPURISCVState *env, uint64_t rs1, uint64_t imm)
+{
+ int64_t a = (int64_t)rs1;
+ uint8_t shamt = imm & 0x3F;
+
+ if (shamt == 0) {
+ return rs1;
+ }
+
+ return (uint64_t)(((a >> (shamt - 1)) + 1) >> 1);
+}
+
+/* Variable shift operations (with saturation and rounding) */
+
+GEN_PSIMD_VAR_SSHA(pssha_hs, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 16, signed_saturate_h)
+GEN_PSIMD_VAR_SSHA(pssha_ws, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, signed_saturate_w)
+
+GEN_PSIMD_VAR_SSHAR(psshar_hs, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 16, SAT_MIN_H, SAT_MAX_H,
+ signed_saturate_h)
+GEN_PSIMD_VAR_SSHAR(psshar_ws, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, SAT_MIN_W, SAT_MAX_W,
+ signed_saturate_w)
+
+GEN_PSIMD_VAR_SSHA(ssha, uint32_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, signed_saturate_w)
+
+/**
+ * SSHAR - 32-bit scalar variable shift with rounding and saturation
+ */
+uint32_t HELPER(sshar)(CPURISCVState *env, uint32_t rs1, uint32_t rs2)
+{
+ int32_t a = (int32_t)rs1;
+ int8_t shamt = (int8_t)(rs2 & 0xFF);
+ int sat = 0;
+ int32_t res;
+
+ if (shamt >= 0) {
+ int64_t shifted = (int64_t)a << shamt;
+ res = signed_saturate_w(shifted, &sat);
+ } else {
+ int right = -shamt;
+ if (right >= 32) {
+ res = (a < 0) ? -1 : 0;
+ } else {
+ int64_t rounded = ((a >> (right - 1)) + 1) >> 1;
+ res = (int32_t)rounded;
+ }
+ }
+
+ if (sat) {
+ env->vxsat = 1;
+ }
+ return (uint32_t)res;
+}
+
+GEN_PSIMD_VAR_SRA64(sha, PSIMD_DO_SRA64)
+GEN_PSIMD_VAR_SRA64(shar, PSIMD_DO_RNDSRA64)
+
+GEN_PSIMD_VAR_USHL(psshl_hs, target_ulong, uint16_t, uint32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 16, unsigned_saturate_h)
+
+GEN_PSIMD_VAR_USHLR(psshlr_hs, target_ulong, uint16_t, uint32_t,
+ EXTRACT16, INSERT16, ELEMS_H, 16, unsigned_saturate_h)
+
+GEN_PSIMD_VAR_USHL(psshl_ws, uint64_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, unsigned_saturate_w)
+
+GEN_PSIMD_VAR_USHLR(psshlr_ws, uint64_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, unsigned_saturate_w)
+
+GEN_PSIMD_VAR_USHL(sshl, uint32_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, unsigned_saturate_w)
+
+GEN_PSIMD_VAR_USHLR(sshlr, uint32_t, uint32_t, uint64_t,
+ EXTRACT32, INSERT32, ELEMS_W, 32, unsigned_saturate_w)
+
+GEN_PSIMD_VAR_SRL64(shl, PSIMD_DO_SRL64)
+GEN_PSIMD_VAR_SRL64(shlr, PSIMD_DO_RNDSRL64)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 07/18] target/riscv: Add packed SIMD exchange instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (5 preceding siblings ...)
2026-07-17 10:06 ` [PATCH v2 06/18] target/riscv: Add packed SIMD shift instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 08/18] target/riscv: Add packed SIMD horizontal reduction instructions Molly Chen
` (12 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 14 +++++++
target/riscv/insn32.decode | 14 +++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 14 +++++++
target/riscv/tcg/psimd_helper.c | 44 +++++++++++++++++++++
4 files changed, 86 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index d72323890f6..d0b13cf3c6a 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1498,3 +1498,17 @@ DEF_HELPER_3(sshl, i32, env, i32, i32)
DEF_HELPER_3(sshlr, i32, env, i32, i32)
DEF_HELPER_3(shl, i64, env, i64, i64)
DEF_HELPER_3(shlr, i64, env, i64, i64)
+
+/* Packed SIMD - Exchange Operations */
+DEF_HELPER_3(pas_hx, tl, env, tl, tl)
+DEF_HELPER_3(psa_hx, tl, env, tl, tl)
+DEF_HELPER_3(psas_hx, tl, env, tl, tl)
+DEF_HELPER_3(pssa_hx, tl, env, tl, tl)
+DEF_HELPER_3(paas_hx, tl, env, tl, tl)
+DEF_HELPER_3(pasa_hx, tl, env, tl, tl)
+DEF_HELPER_3(pas_wx, i64, env, i64, i64)
+DEF_HELPER_3(psa_wx, i64, env, i64, i64)
+DEF_HELPER_3(psas_wx, i64, env, i64, i64)
+DEF_HELPER_3(pssa_wx, i64, env, i64, i64)
+DEF_HELPER_3(paas_wx, i64, env, i64, i64)
+DEF_HELPER_3(pasa_wx, i64, env, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index fb029bb512f..e331ba6a38c 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1274,3 +1274,17 @@ psshlr_hs 1011100 ..... ..... 010 ..... 0011011 @r
}
shl 1010111 ..... ..... 010 ..... 0011011 @r
shlr 1011111 ..... ..... 010 ..... 0011011 @r
+
+# Packed SIMD - Exchange Operations
+pas_hx 1000000 ..... ..... 110 ..... 0111011 @r
+psa_hx 1000010 ..... ..... 110 ..... 0111011 @r
+psas_hx 1001000 ..... ..... 110 ..... 0111011 @r
+pssa_hx 1001010 ..... ..... 110 ..... 0111011 @r
+paas_hx 1001100 ..... ..... 110 ..... 0111011 @r
+pasa_hx 1001110 ..... ..... 110 ..... 0111011 @r
+pas_wx 1000001 ..... ..... 110 ..... 0111011 @r
+psa_wx 1000011 ..... ..... 110 ..... 0111011 @r
+psas_wx 1001001 ..... ..... 110 ..... 0111011 @r
+pssa_wx 1001011 ..... ..... 110 ..... 0111011 @r
+paas_wx 1001101 ..... ..... 110 ..... 0111011 @r
+pasa_wx 1001111 ..... ..... 110 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index fb82760a60c..61e1fb8d816 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -644,3 +644,17 @@ GEN_SIMD_TRANS_32_VXSAT(sshlr)
GEN_SIMD_TRANS_64(shl)
GEN_SIMD_TRANS_64(shlr)
+/* Packed SIMD - Exchange Operations */
+GEN_SIMD_TRANS(pas_hx)
+GEN_SIMD_TRANS(psa_hx)
+GEN_SIMD_TRANS_VXSAT(psas_hx)
+GEN_SIMD_TRANS_VXSAT(pssa_hx)
+GEN_SIMD_TRANS(paas_hx)
+GEN_SIMD_TRANS(pasa_hx)
+GEN_SIMD_TRANS_64(pas_wx)
+GEN_SIMD_TRANS_64(psa_wx)
+GEN_SIMD_TRANS_64_VXSAT(psas_wx)
+GEN_SIMD_TRANS_64_VXSAT(pssa_wx)
+GEN_SIMD_TRANS_64(paas_wx)
+GEN_SIMD_TRANS_64(pasa_wx)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 8b106a336f5..ccc43b2dda0 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2052,3 +2052,47 @@ GEN_PSIMD_VAR_USHLR(sshlr, uint32_t, uint32_t, uint64_t,
GEN_PSIMD_VAR_SRL64(shl, PSIMD_DO_SRL64)
GEN_PSIMD_VAR_SRL64(shlr, PSIMD_DO_RNDSRL64)
+/* Exchange operations (AS/SA/AS/SA with X suffix) */
+
+GEN_PSIMD_XPAIR_BINOP(pas_hx, target_ulong, int16_t,
+ EXTRACT16, INSERT16, ELEMS_H,
+ PSIMD_DO_SUB, PSIMD_DO_ADD)
+GEN_PSIMD_XPAIR_BINOP(psa_hx, target_ulong, int16_t,
+ EXTRACT16, INSERT16, ELEMS_H,
+ PSIMD_DO_ADD, PSIMD_DO_SUB)
+
+GEN_PSIMD_XPAIR_SAT_BINOP(psas_hx, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H,
+ PSIMD_DO_SUB, PSIMD_DO_ADD, signed_saturate_h)
+GEN_PSIMD_XPAIR_SAT_BINOP(pssa_hx, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H,
+ PSIMD_DO_ADD, PSIMD_DO_SUB, signed_saturate_h)
+
+GEN_PSIMD_XPAIR_AVG_BINOP(paas_hx, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H,
+ PSIMD_DO_SUB, PSIMD_DO_ADD)
+GEN_PSIMD_XPAIR_AVG_BINOP(pasa_hx, target_ulong, int16_t, int32_t,
+ EXTRACT16, INSERT16, ELEMS_H,
+ PSIMD_DO_ADD, PSIMD_DO_SUB)
+
+GEN_PSIMD_XPAIR_BINOP(pas_wx, uint64_t, int32_t,
+ EXTRACT32, INSERT32, ELEMS_W,
+ PSIMD_DO_SUB, PSIMD_DO_ADD)
+GEN_PSIMD_XPAIR_BINOP(psa_wx, uint64_t, int32_t,
+ EXTRACT32, INSERT32, ELEMS_W,
+ PSIMD_DO_ADD, PSIMD_DO_SUB)
+
+GEN_PSIMD_XPAIR_SAT_BINOP(psas_wx, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W,
+ PSIMD_DO_SUB, PSIMD_DO_ADD, signed_saturate_w)
+GEN_PSIMD_XPAIR_SAT_BINOP(pssa_wx, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W,
+ PSIMD_DO_ADD, PSIMD_DO_SUB, signed_saturate_w)
+
+GEN_PSIMD_XPAIR_AVG_BINOP(paas_wx, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W,
+ PSIMD_DO_SUB, PSIMD_DO_ADD)
+GEN_PSIMD_XPAIR_AVG_BINOP(pasa_wx, uint64_t, int32_t, int64_t,
+ EXTRACT32, INSERT32, ELEMS_W,
+ PSIMD_DO_ADD, PSIMD_DO_SUB)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 08/18] target/riscv: Add packed SIMD horizontal reduction instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (6 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 07/18] target/riscv: Add packed SIMD exchange instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 09/18] target/riscv: Add packed SIMD pack, merge and count-leading instructions Molly Chen
` (11 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 8 ++++++++
target/riscv/insn32.decode | 8 ++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 8 ++++++++
target/riscv/tcg/psimd_helper.c | 15 +++++++++++++++
4 files changed, 39 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index d0b13cf3c6a..5fe650c5d71 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1512,3 +1512,11 @@ DEF_HELPER_3(psas_wx, i64, env, i64, i64)
DEF_HELPER_3(pssa_wx, i64, env, i64, i64)
DEF_HELPER_3(paas_wx, i64, env, i64, i64)
DEF_HELPER_3(pasa_wx, i64, env, i64, i64)
+
+/* Packed SIMD - Horizontal Reduction Operations */
+DEF_HELPER_3(predsum_bs, tl, env, tl, tl)
+DEF_HELPER_3(predsumu_bs, tl, env, tl, tl)
+DEF_HELPER_3(predsum_hs, tl, env, tl, tl)
+DEF_HELPER_3(predsumu_hs, tl, env, tl, tl)
+DEF_HELPER_3(predsum_ws, i64, env, i64, i64)
+DEF_HELPER_3(predsumu_ws, i64, env, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index e331ba6a38c..9d0f5c48b6d 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1288,3 +1288,11 @@ psas_wx 1001001 ..... ..... 110 ..... 0111011 @r
pssa_wx 1001011 ..... ..... 110 ..... 0111011 @r
paas_wx 1001101 ..... ..... 110 ..... 0111011 @r
pasa_wx 1001111 ..... ..... 110 ..... 0111011 @r
+
+# Packed SIMD - Horizontal Reduction Operations
+predsum_bs 1001110 ..... ..... 100 ..... 0011011 @r
+predsumu_bs 1011110 ..... ..... 100 ..... 0011011 @r
+predsum_hs 1001100 ..... ..... 100 ..... 0011011 @r
+predsumu_hs 1011100 ..... ..... 100 ..... 0011011 @r
+predsum_ws 1001101 ..... ..... 100 ..... 0011011 @r
+predsumu_ws 1011101 ..... ..... 100 ..... 0011011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 61e1fb8d816..9f2ae9da1d1 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -658,3 +658,11 @@ GEN_SIMD_TRANS_64_VXSAT(pssa_wx)
GEN_SIMD_TRANS_64(paas_wx)
GEN_SIMD_TRANS_64(pasa_wx)
+/* Packed SIMD - Horizontal Reduction Operations */
+GEN_SIMD_TRANS(predsum_bs)
+GEN_SIMD_TRANS(predsumu_bs)
+GEN_SIMD_TRANS(predsum_hs)
+GEN_SIMD_TRANS(predsumu_hs)
+GEN_SIMD_TRANS_64(predsum_ws)
+GEN_SIMD_TRANS_64(predsumu_ws)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index ccc43b2dda0..0acf0414bf9 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2096,3 +2096,18 @@ GEN_PSIMD_XPAIR_AVG_BINOP(pasa_wx, uint64_t, int32_t, int64_t,
EXTRACT32, INSERT32, ELEMS_W,
PSIMD_DO_ADD, PSIMD_DO_SUB)
+/* Horizontal sum operations */
+
+GEN_PSIMD_REDSUM(predsum_bs, target_ulong, int64_t, int8_t,
+ EXTRACT8, ELEMS_B, (int64_t)(int32_t)rs2)
+GEN_PSIMD_REDSUM(predsumu_bs, target_ulong, uint64_t, uint8_t,
+ EXTRACT8, ELEMS_B, rs2)
+GEN_PSIMD_REDSUM(predsum_hs, target_ulong, int64_t, int16_t,
+ EXTRACT16, ELEMS_H, (int64_t)(int32_t)rs2)
+GEN_PSIMD_REDSUM(predsumu_hs, target_ulong, uint64_t, uint16_t,
+ EXTRACT16, ELEMS_H, rs2)
+GEN_PSIMD_REDSUM(predsum_ws, uint64_t, int64_t, int32_t,
+ EXTRACT32, ELEMS_W, (int64_t)rs2)
+GEN_PSIMD_REDSUM(predsumu_ws, uint64_t, uint64_t, uint32_t,
+ EXTRACT32, ELEMS_W, rs2)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 09/18] target/riscv: Add packed SIMD pack, merge and count-leading instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (7 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 08/18] target/riscv: Add packed SIMD horizontal reduction instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 10/18] target/riscv: Add packed SIMD multiplication instructions Molly Chen
` (10 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 41 ++++++
target/riscv/insn32.decode | 41 ++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 41 ++++++
target/riscv/tcg/psimd_helper.c | 148 ++++++++++++++++++++
4 files changed, 271 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 5fe650c5d71..f83af437d40 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1520,3 +1520,44 @@ DEF_HELPER_3(predsum_hs, tl, env, tl, tl)
DEF_HELPER_3(predsumu_hs, tl, env, tl, tl)
DEF_HELPER_3(predsum_ws, i64, env, i64, i64)
DEF_HELPER_3(predsumu_ws, i64, env, i64, i64)
+
+/* Packed SIMD - Pack, Unpack, and Merge Operations */
+DEF_HELPER_3(ppaire_b, tl, env, tl, tl)
+DEF_HELPER_3(ppaireo_b, tl, env, tl, tl)
+DEF_HELPER_3(ppairoe_b, tl, env, tl, tl)
+DEF_HELPER_3(ppairo_b, tl, env, tl, tl)
+DEF_HELPER_3(ppaire_h, i64, env, i64, i64)
+DEF_HELPER_3(ppaireo_h, tl, env, tl, tl)
+DEF_HELPER_3(ppairoe_h, tl, env, tl, tl)
+DEF_HELPER_3(ppairo_h, tl, env, tl, tl)
+DEF_HELPER_3(ppaireo_w, i64, env, i64, i64)
+DEF_HELPER_3(ppairoe_w, i64, env, i64, i64)
+DEF_HELPER_3(ppairo_w, i64, env, i64, i64)
+DEF_HELPER_2(psext_h_b, tl, env, tl)
+DEF_HELPER_2(psext_w_b, i64, env, i64)
+DEF_HELPER_2(psext_w_h, i64, env, i64)
+DEF_HELPER_2(rev, tl, env, tl)
+DEF_HELPER_2(rev16, i64, env, i64)
+DEF_HELPER_3(zip8p, i64, env, i64, i64)
+DEF_HELPER_3(zip8hp, i64, env, i64, i64)
+DEF_HELPER_3(unzip8p, i64, env, i64, i64)
+DEF_HELPER_3(unzip8hp, i64, env, i64, i64)
+DEF_HELPER_3(zip16p, i64, env, i64, i64)
+DEF_HELPER_3(zip16hp, i64, env, i64, i64)
+DEF_HELPER_3(unzip16p, i64, env, i64, i64)
+DEF_HELPER_3(unzip16hp, i64, env, i64, i64)
+DEF_HELPER_4(slx, tl, env, tl, tl, tl)
+DEF_HELPER_4(srx, tl, env, tl, tl, tl)
+DEF_HELPER_4(mvm, tl, env, tl, tl, tl)
+DEF_HELPER_4(mvmn, tl, env, tl, tl, tl)
+DEF_HELPER_4(merge, tl, env, tl, tl, tl)
+DEF_HELPER_3(pnclipp_b, i64, env, i64, i64)
+DEF_HELPER_3(pnclipup_b, i64, env, i64, i64)
+DEF_HELPER_3(pnclipp_h, i64, env, i64, i64)
+DEF_HELPER_3(pnclipup_h, i64, env, i64, i64)
+DEF_HELPER_3(pnclipp_w, i64, env, i64, i64)
+DEF_HELPER_3(pnclipup_w, i64, env, i64, i64)
+
+/* Packed SIMD - Count Leading Operations */
+DEF_HELPER_2(cls, tl, env, tl)
+DEF_HELPER_2(clsw, i64, env, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 9d0f5c48b6d..14dab4cb641 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1296,3 +1296,44 @@ predsum_hs 1001100 ..... ..... 100 ..... 0011011 @r
predsumu_hs 1011100 ..... ..... 100 ..... 0011011 @r
predsum_ws 1001101 ..... ..... 100 ..... 0011011 @r
predsumu_ws 1011101 ..... ..... 100 ..... 0011011 @r
+
+# Packed SIMD - Pack, Unpack, and Merge Operations
+ppaire_b 1000000 ..... ..... 100 ..... 0111011 @r
+ppaireo_b 1001000 ..... ..... 100 ..... 0111011 @r
+ppairoe_b 1010000 ..... ..... 100 ..... 0111011 @r
+ppairo_b 1011000 ..... ..... 100 ..... 0111011 @r
+ppaireo_h 1001001 ..... ..... 100 ..... 0111011 @r
+ppairoe_h 1010001 ..... ..... 100 ..... 0111011 @r
+ppairo_h 1011001 ..... ..... 100 ..... 0111011 @r
+ppaire_h 1000001 ..... ..... 100 ..... 0111011 @r
+ppaireo_w 1001011 ..... ..... 100 ..... 0111011 @r
+ppairoe_w 1010011 ..... ..... 100 ..... 0111011 @r
+ppairo_w 1011011 ..... ..... 100 ..... 0111011 @r
+psext_h_b 1110000 00100 ..... 010 ..... 0011011 @r2
+psext_w_b 1110001 00100 ..... 010 ..... 0011011 @r2
+psext_w_h 1110001 00101 ..... 010 ..... 0011011 @r2
+rev 01101 0111111 ..... 101 ..... 0010011 @r2
+rev16 01101 0110000 ..... 101 ..... 0010011 @r2
+zip8p 1111000 ..... ..... 010 ..... 0111011 @r
+zip8hp 1111010 ..... ..... 010 ..... 0111011 @r
+unzip8p 1110000 ..... ..... 010 ..... 0111011 @r
+unzip8hp 1110010 ..... ..... 010 ..... 0111011 @r
+zip16p 1111001 ..... ..... 010 ..... 0111011 @r
+zip16hp 1111011 ..... ..... 010 ..... 0111011 @r
+unzip16p 1110001 ..... ..... 010 ..... 0111011 @r
+unzip16hp 1110011 ..... ..... 010 ..... 0111011 @r
+slx 1000111 ..... ..... 001 ..... 0111011 @r
+srx 1010111 ..... ..... 001 ..... 0111011 @r
+mvm 1010100 ..... ..... 001 ..... 0111011 @r
+mvmn 1010101 ..... ..... 001 ..... 0111011 @r
+merge 1010110 ..... ..... 001 ..... 0111011 @r
+pnclipp_b 1100000 ..... ..... 010 ..... 0111011 @r
+pnclipup_b 1000000 ..... ..... 010 ..... 0111011 @r
+pnclipp_h 1100001 ..... ..... 010 ..... 0111011 @r
+pnclipup_h 1000001 ..... ..... 010 ..... 0111011 @r
+pnclipp_w 1100011 ..... ..... 010 ..... 0111011 @r
+pnclipup_w 1000011 ..... ..... 010 ..... 0111011 @r
+
+# Packed SIMD - Count Leading Operations
+cls 01100 0000011 ..... 001 ..... 0010011 @r2
+clsw 01100 0000011 ..... 001 ..... 0011011 @r2
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 9f2ae9da1d1..486184eeaf3 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -666,3 +666,44 @@ GEN_SIMD_TRANS(predsumu_hs)
GEN_SIMD_TRANS_64(predsum_ws)
GEN_SIMD_TRANS_64(predsumu_ws)
+/* Packed SIMD - Pack, Unpack, and Merge Operations */
+GEN_SIMD_TRANS(ppaire_b)
+GEN_SIMD_TRANS(ppaireo_b)
+GEN_SIMD_TRANS(ppairoe_b)
+GEN_SIMD_TRANS(ppairo_b)
+GEN_SIMD_TRANS_64(ppaire_h)
+GEN_SIMD_TRANS(ppaireo_h)
+GEN_SIMD_TRANS(ppairoe_h)
+GEN_SIMD_TRANS(ppairo_h)
+GEN_SIMD_TRANS_64(ppaireo_w)
+GEN_SIMD_TRANS_64(ppairoe_w)
+GEN_SIMD_TRANS_64(ppairo_w)
+GEN_SIMD_TRANS_R1(psext_h_b)
+GEN_SIMD_TRANS_R1_64(psext_w_b)
+GEN_SIMD_TRANS_R1_64(psext_w_h)
+GEN_SIMD_TRANS_R1(rev)
+GEN_SIMD_TRANS_R1_64(rev16)
+GEN_SIMD_TRANS_64(zip8p)
+GEN_SIMD_TRANS_64(zip8hp)
+GEN_SIMD_TRANS_64(unzip8p)
+GEN_SIMD_TRANS_64(unzip8hp)
+GEN_SIMD_TRANS_64(zip16p)
+GEN_SIMD_TRANS_64(zip16hp)
+GEN_SIMD_TRANS_64(unzip16p)
+GEN_SIMD_TRANS_64(unzip16hp)
+GEN_SIMD_TRANS_ACC(slx)
+GEN_SIMD_TRANS_ACC(srx)
+GEN_SIMD_TRANS_ACC(mvm)
+GEN_SIMD_TRANS_ACC(mvmn)
+GEN_SIMD_TRANS_ACC(merge)
+GEN_SIMD_TRANS_64_VXSAT(pnclipp_b)
+GEN_SIMD_TRANS_64_VXSAT(pnclipup_b)
+GEN_SIMD_TRANS_64_VXSAT(pnclipp_h)
+GEN_SIMD_TRANS_64_VXSAT(pnclipup_h)
+GEN_SIMD_TRANS_64_VXSAT(pnclipp_w)
+GEN_SIMD_TRANS_64_VXSAT(pnclipup_w)
+
+/* Packed SIMD - Count Leading Operations */
+GEN_SIMD_TRANS_R1(cls)
+GEN_SIMD_TRANS_R1_64(clsw)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 0acf0414bf9..99f11f084f2 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2111,3 +2111,151 @@ GEN_PSIMD_REDSUM(predsum_ws, uint64_t, int64_t, int32_t,
GEN_PSIMD_REDSUM(predsumu_ws, uint64_t, uint64_t, uint32_t,
EXTRACT32, ELEMS_W, rs2)
+/* Packing/unpacking operations */
+
+GEN_PSIMD_PAIR_PACK(ppaire_b, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x00ff, 8,
+ PSIMD_PAIR_LO, PSIMD_PAIR_LO)
+GEN_PSIMD_PAIR_PACK(ppaireo_b, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x00ff, 8,
+ PSIMD_PAIR_HI, PSIMD_PAIR_LO)
+GEN_PSIMD_PAIR_PACK(ppairoe_b, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x00ff, 8,
+ PSIMD_PAIR_LO, PSIMD_PAIR_HI)
+GEN_PSIMD_PAIR_PACK(ppairo_b, target_ulong, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 0x00ff, 8,
+ PSIMD_PAIR_HI, PSIMD_PAIR_HI)
+
+GEN_PSIMD_PAIR_PACK(ppaire_h, uint64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x0000ffff, 16,
+ PSIMD_PAIR_LO, PSIMD_PAIR_LO)
+GEN_PSIMD_PAIR_PACK(ppaireo_h, target_ulong, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x0000ffff, 16,
+ PSIMD_PAIR_HI, PSIMD_PAIR_LO)
+GEN_PSIMD_PAIR_PACK(ppairoe_h, target_ulong, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x0000ffff, 16,
+ PSIMD_PAIR_LO, PSIMD_PAIR_HI)
+GEN_PSIMD_PAIR_PACK(ppairo_h, target_ulong, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 0x0000ffff, 16,
+ PSIMD_PAIR_HI, PSIMD_PAIR_HI)
+
+GEN_PSIMD_PAIR_WORD(ppaireo_w, 0, 1)
+GEN_PSIMD_PAIR_WORD(ppairoe_w, 1, 0)
+GEN_PSIMD_PAIR_WORD(ppairo_w, 1, 1)
+
+GEN_PSIMD_SIGN_EXTEND(psext_h_b, target_ulong, int8_t, int16_t,
+ EXTRACT8, INSERT16, ELEMS_H, 2)
+GEN_PSIMD_SIGN_EXTEND(psext_w_b, uint64_t, int8_t, int32_t,
+ EXTRACT8, INSERT32, ELEMS_W, 4)
+GEN_PSIMD_SIGN_EXTEND(psext_w_h, uint64_t, int16_t, int32_t,
+ EXTRACT16, INSERT32, ELEMS_W, 2)
+
+/**
+ * REV - Reverse all bits
+ */
+target_ulong HELPER(rev)(CPURISCVState *env, target_ulong rs1)
+{
+ target_ulong rd = 0;
+
+ for (int i = 0; i < TARGET_LONG_BITS; i++) {
+ rd = (rd << 1) | (rs1 & 1);
+ rs1 >>= 1;
+ }
+
+ return rd;
+}
+
+/**
+ * REV16 - Reverse 16-bit chunks (RV64 only)
+ */
+uint64_t HELPER(rev16)(CPURISCVState *env, uint64_t rs1)
+{
+ uint64_t rd = 0;
+
+ for (int i = 0; i < 4; i++) {
+ uint16_t chunk = EXTRACT16(rs1, i);
+ rd = (rd << 16) | chunk;
+ }
+
+ return rd;
+}
+
+GEN_PSIMD_ZIP(zip8p, uint8_t, EXTRACT8, 4, 8, 3)
+GEN_PSIMD_ZIP(zip8hp, uint8_t, EXTRACT8, 4, 8, 7)
+GEN_PSIMD_UNZIP(unzip8p, EXTRACT8, 4, 8, 0)
+GEN_PSIMD_UNZIP(unzip8hp, EXTRACT8, 4, 8, 1)
+
+GEN_PSIMD_ZIP(zip16p, uint16_t, EXTRACT16, 2, 16, 1)
+GEN_PSIMD_ZIP(zip16hp, uint16_t, EXTRACT16, 2, 16, 3)
+GEN_PSIMD_UNZIP(unzip16p, EXTRACT16, 2, 16, 0)
+GEN_PSIMD_UNZIP(unzip16hp, EXTRACT16, 2, 16, 1)
+
+/* Merge and mask operations */
+
+/**
+ * SLX - Shift left extended (concatenate rd and rs1, shift left, take upper)
+ */
+target_ulong HELPER(slx)(CPURISCVState *env, target_ulong rs1,
+ target_ulong rs2, target_ulong rd)
+{
+ int shamt = (TARGET_LONG_BITS == 32) ? (rs2 & 0x1F) : (rs2 & 0x3F);
+ target_ulong xrs1 = 0;
+ target_ulong xrd = 0;
+
+ if (shamt <= TARGET_LONG_BITS) {
+ xrs1 = rs1 >> (TARGET_LONG_BITS - shamt);
+ xrd = (rd << shamt) + xrs1;
+ } else {
+ xrd = rs1 << (shamt - TARGET_LONG_BITS);
+ }
+
+ return xrd;
+}
+
+/**
+ * SRX - Shift right extended (concatenate rs1 and rd, shift right, take lower)
+ */
+target_ulong HELPER(srx)(CPURISCVState *env, target_ulong rs1,
+ target_ulong rs2, target_ulong rd)
+{
+ int shamt = (TARGET_LONG_BITS == 32) ? (rs2 & 0x1F) : (rs2 & 0x3F);
+ target_ulong xrs1 = 0;
+ target_ulong xrd = 0;
+
+ if (shamt <= TARGET_LONG_BITS) {
+ xrs1 = rs1 << (TARGET_LONG_BITS - shamt);
+ xrd = (rd >> shamt) + xrs1;
+ } else {
+ xrd = rs1 >> (shamt - TARGET_LONG_BITS);
+ }
+
+ return xrd;
+}
+
+GEN_PSIMD_BIT_SELECT(mvm, rs2, rs1, rd)
+GEN_PSIMD_BIT_SELECT(mvmn, rs2, rd, rs1)
+GEN_PSIMD_BIT_SELECT(merge, rd, rs2, rs1)
+
+GEN_PSIMD_NCLIP_PACK(pnclipp_b, int16_t, int8_t,
+ EXTRACT16, INSERT8, 4, signed_saturate_b)
+GEN_PSIMD_NCLIP_PACK(pnclipup_b, uint16_t, uint8_t,
+ EXTRACT16, INSERT8, 4, unsigned_saturate_b)
+GEN_PSIMD_NCLIP_PACK(pnclipp_h, int32_t, int16_t,
+ EXTRACT32, INSERT16, 2, signed_saturate_h)
+GEN_PSIMD_NCLIP_PACK(pnclipup_h, uint32_t, uint16_t,
+ EXTRACT32, INSERT16, 2, unsigned_saturate_h)
+GEN_PSIMD_NCLIP_PACK(pnclipp_w, int64_t, int32_t,
+ EXTRACT64, INSERT32_64, 1, signed_saturate_w)
+GEN_PSIMD_NCLIP_PACK(pnclipup_w, uint64_t, uint32_t,
+ EXTRACT64, INSERT32_64, 1, unsigned_saturate_w)
+
+/* Count leading operations */
+
+#if TARGET_LONG_BITS == 64
+GEN_PSIMD_CLS(cls, target_ulong, uint64_t, clrsb64)
+#else
+GEN_PSIMD_CLS(cls, target_ulong, uint32_t, clrsb32)
+#endif
+
+GEN_PSIMD_CLS(clsw, uint64_t, uint32_t, clrsb32)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 10/18] target/riscv: Add packed SIMD multiplication instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (8 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 09/18] target/riscv: Add packed SIMD pack, merge and count-leading instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 11/18] target/riscv: Add packed SIMD multiply-accumulate instructions Molly Chen
` (9 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 63 +++++++
target/riscv/insn32.decode | 93 ++++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 63 +++++++
target/riscv/tcg/psimd_helper.c | 184 ++++++++++++++++++++
4 files changed, 403 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index f83af437d40..f06f40b1284 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1561,3 +1561,66 @@ DEF_HELPER_3(pnclipup_w, i64, env, i64, i64)
/* Packed SIMD - Count Leading Operations */
DEF_HELPER_2(cls, tl, env, tl)
DEF_HELPER_2(clsw, i64, env, i64)
+
+/* Packed SIMD - Pure Multiplication Operations */
+DEF_HELPER_3(pmulh_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulhsu_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulhu_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulhr_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulhrsu_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulhru_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulh_w, i64, env, i64, i64)
+DEF_HELPER_3(pmulhr_w, i64, env, i64, i64)
+DEF_HELPER_3(pmulhsu_w, i64, env, i64, i64)
+DEF_HELPER_3(pmulhrsu_w, i64, env, i64, i64)
+DEF_HELPER_3(pmulhu_w, i64, env, i64, i64)
+DEF_HELPER_3(pmulhru_w, i64, env, i64, i64)
+DEF_HELPER_3(mulhr, i32, env, i32, i32)
+DEF_HELPER_3(mulhrsu, i32, env, i32, i32)
+DEF_HELPER_3(mulhru, i32, env, i32, i32)
+DEF_HELPER_3(pmulh_h_b0, tl, env, tl, tl)
+DEF_HELPER_3(pmulh_h_b1, tl, env, tl, tl)
+DEF_HELPER_3(pmulhsu_h_b0, tl, env, tl, tl)
+DEF_HELPER_3(pmulhsu_h_b1, tl, env, tl, tl)
+DEF_HELPER_3(mulh_h0, i32, env, i32, i32)
+DEF_HELPER_3(mulh_h1, i32, env, i32, i32)
+DEF_HELPER_3(mulhsu_h0, i32, env, i32, i32)
+DEF_HELPER_3(mulhsu_h1, i32, env, i32, i32)
+DEF_HELPER_3(pmulh_w_h0, i64, env, i64, i64)
+DEF_HELPER_3(pmulh_w_h1, i64, env, i64, i64)
+DEF_HELPER_3(pmulhsu_w_h0, i64, env, i64, i64)
+DEF_HELPER_3(pmulhsu_w_h1, i64, env, i64, i64)
+DEF_HELPER_3(pmul_h_b00, tl, env, tl, tl)
+DEF_HELPER_3(pmul_h_b01, tl, env, tl, tl)
+DEF_HELPER_3(pmul_h_b11, tl, env, tl, tl)
+DEF_HELPER_3(pmulsu_h_b00, tl, env, tl, tl)
+DEF_HELPER_3(pmulsu_h_b11, tl, env, tl, tl)
+DEF_HELPER_3(pmulu_h_b00, tl, env, tl, tl)
+DEF_HELPER_3(pmulu_h_b01, tl, env, tl, tl)
+DEF_HELPER_3(pmulu_h_b11, tl, env, tl, tl)
+DEF_HELPER_3(pmul_w_h00, i64, env, i64, i64)
+DEF_HELPER_3(pmul_w_h01, i64, env, i64, i64)
+DEF_HELPER_3(pmul_w_h11, i64, env, i64, i64)
+DEF_HELPER_3(pmulsu_w_h00, i64, env, i64, i64)
+DEF_HELPER_3(pmulsu_w_h11, i64, env, i64, i64)
+DEF_HELPER_3(pmulu_w_h00, i64, env, i64, i64)
+DEF_HELPER_3(pmulu_w_h01, i64, env, i64, i64)
+DEF_HELPER_3(pmulu_w_h11, i64, env, i64, i64)
+DEF_HELPER_3(pm2sadd_h, tl, env, tl, tl)
+DEF_HELPER_3(pm2sadd_hx, tl, env, tl, tl)
+DEF_HELPER_3(mul_h00, i32, env, i32, i32)
+DEF_HELPER_3(mul_h01, i32, env, i32, i32)
+DEF_HELPER_3(mul_h11, i32, env, i32, i32)
+DEF_HELPER_3(mulsu_h00, i32, env, i32, i32)
+DEF_HELPER_3(mulsu_h11, i32, env, i32, i32)
+DEF_HELPER_3(mulu_h00, i32, env, i32, i32)
+DEF_HELPER_3(mulu_h01, i32, env, i32, i32)
+DEF_HELPER_3(mulu_h11, i32, env, i32, i32)
+DEF_HELPER_3(mul_w00, i64, env, i64, i64)
+DEF_HELPER_3(mul_w01, i64, env, i64, i64)
+DEF_HELPER_3(mul_w11, i64, env, i64, i64)
+DEF_HELPER_3(mulsu_w00, i64, env, i64, i64)
+DEF_HELPER_3(mulsu_w11, i64, env, i64, i64)
+DEF_HELPER_3(mulu_w00, i64, env, i64, i64)
+DEF_HELPER_3(mulu_w01, i64, env, i64, i64)
+DEF_HELPER_3(mulu_w11, i64, env, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 14dab4cb641..cc0cc35fe24 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1337,3 +1337,96 @@ pnclipup_w 1000011 ..... ..... 010 ..... 0111011 @r
# Packed SIMD - Count Leading Operations
cls 01100 0000011 ..... 001 ..... 0010011 @r2
clsw 01100 0000011 ..... 001 ..... 0011011 @r2
+
+# Packed SIMD - Pure Multiplication Operations
+pmulh_h 10000 00 ..... ..... 111 ..... 0111011 @r
+pmulhsu_h 11000 00 ..... ..... 111 ..... 0111011 @r
+pmulhu_h 10010 00 ..... ..... 111 ..... 0111011 @r
+pmulhr_h 10000 10 ..... ..... 111 ..... 0111011 @r
+pmulhrsu_h 11000 10 ..... ..... 111 ..... 0111011 @r
+pmulhru_h 10010 10 ..... ..... 111 ..... 0111011 @r
+pmulh_w 10000 01 ..... ..... 111 ..... 0111011 @r
+{
+ mulhr 10000 11 ..... ..... 111 ..... 0111011 @r
+ pmulhr_w 10000 11 ..... ..... 111 ..... 0111011 @r
+}
+pmulhsu_w 11000 01 ..... ..... 111 ..... 0111011 @r
+{
+ mulhrsu 11000 11 ..... ..... 111 ..... 0111011 @r
+ pmulhrsu_w 11000 11 ..... ..... 111 ..... 0111011 @r
+}
+pmulhu_w 10010 01 ..... ..... 111 ..... 0111011 @r
+{
+ mulhru 10010 11 ..... ..... 111 ..... 0111011 @r
+ pmulhru_w 10010 11 ..... ..... 111 ..... 0111011 @r
+}
+pmulh_h_b0 10100 00 ..... ..... 111 ..... 0111011 @r
+pmulh_h_b1 10110 00 ..... ..... 111 ..... 0111011 @r
+pmulhsu_h_b0 10100 10 ..... ..... 111 ..... 0111011 @r
+pmulhsu_h_b1 10110 10 ..... ..... 111 ..... 0111011 @r
+{
+ mulh_h0 10100 01 ..... ..... 111 ..... 0111011 @r
+ pmulh_w_h0 10100 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mulh_h1 10110 01 ..... ..... 111 ..... 0111011 @r
+ pmulh_w_h1 10110 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mulhsu_h0 10100 11 ..... ..... 111 ..... 0111011 @r
+ pmulhsu_w_h0 10100 11 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mulhsu_h1 10110 11 ..... ..... 111 ..... 0111011 @r
+ pmulhsu_w_h1 10110 11 ..... ..... 111 ..... 0111011 @r
+}
+pmul_h_b00 10000 00 ..... ..... 011 ..... 0111011 @r
+pmul_h_b01 10010 00 ..... ..... 001 ..... 0111011 @r
+pmul_h_b11 10010 00 ..... ..... 011 ..... 0111011 @r
+pmulsu_h_b00 11100 00 ..... ..... 011 ..... 0111011 @r
+pmulsu_h_b11 11110 00 ..... ..... 011 ..... 0111011 @r
+pmulu_h_b00 10100 00 ..... ..... 011 ..... 0111011 @r
+pmulu_h_b01 10110 00 ..... ..... 001 ..... 0111011 @r
+pmulu_h_b11 10110 00 ..... ..... 011 ..... 0111011 @r
+{
+ mul_h00 10000 01 ..... ..... 011 ..... 0111011 @r
+ pmul_w_h00 10000 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ mul_h01 10010 01 ..... ..... 001 ..... 0111011 @r
+ pmul_w_h01 10010 01 ..... ..... 001 ..... 0111011 @r
+}
+{
+ mul_h11 10010 01 ..... ..... 011 ..... 0111011 @r
+ pmul_w_h11 10010 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ mulsu_h00 11100 01 ..... ..... 011 ..... 0111011 @r
+ pmulsu_w_h00 11100 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ mulsu_h11 11110 01 ..... ..... 011 ..... 0111011 @r
+ pmulsu_w_h11 11110 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ mulu_h00 10100 01 ..... ..... 011 ..... 0111011 @r
+ pmulu_w_h00 10100 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ mulu_h01 10110 01 ..... ..... 001 ..... 0111011 @r
+ pmulu_w_h01 10110 01 ..... ..... 001 ..... 0111011 @r
+}
+{
+ mulu_h11 10110 01 ..... ..... 011 ..... 0111011 @r
+ pmulu_w_h11 10110 01 ..... ..... 011 ..... 0111011 @r
+}
+pm2sadd_h 11000 10 ..... ..... 101 ..... 0111011 @r
+pm2sadd_hx 11010 10 ..... ..... 101 ..... 0111011 @r
+mul_w00 10000 11 ..... ..... 011 ..... 0111011 @r
+mul_w01 10010 11 ..... ..... 001 ..... 0111011 @r
+mul_w11 10010 11 ..... ..... 011 ..... 0111011 @r
+mulsu_w00 11100 11 ..... ..... 011 ..... 0111011 @r
+mulsu_w11 11110 11 ..... ..... 011 ..... 0111011 @r
+mulu_w00 10100 11 ..... ..... 011 ..... 0111011 @r
+mulu_w01 10110 11 ..... ..... 001 ..... 0111011 @r
+mulu_w11 10110 11 ..... ..... 011 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 486184eeaf3..7edea099d01 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -707,3 +707,66 @@ GEN_SIMD_TRANS_64_VXSAT(pnclipup_w)
GEN_SIMD_TRANS_R1(cls)
GEN_SIMD_TRANS_R1_64(clsw)
+/* Packed SIMD - Pure Multiplication Operations */
+GEN_SIMD_TRANS(pmulh_h)
+GEN_SIMD_TRANS(pmulhsu_h)
+GEN_SIMD_TRANS(pmulhu_h)
+GEN_SIMD_TRANS(pmulhr_h)
+GEN_SIMD_TRANS(pmulhrsu_h)
+GEN_SIMD_TRANS(pmulhru_h)
+GEN_SIMD_TRANS_64(pmulh_w)
+GEN_SIMD_TRANS_64(pmulhr_w)
+GEN_SIMD_TRANS_64(pmulhsu_w)
+GEN_SIMD_TRANS_64(pmulhrsu_w)
+GEN_SIMD_TRANS_64(pmulhu_w)
+GEN_SIMD_TRANS_64(pmulhru_w)
+GEN_SIMD_TRANS_32(mulhr)
+GEN_SIMD_TRANS_32(mulhrsu)
+GEN_SIMD_TRANS_32(mulhru)
+GEN_SIMD_TRANS(pmulh_h_b0)
+GEN_SIMD_TRANS(pmulh_h_b1)
+GEN_SIMD_TRANS(pmulhsu_h_b0)
+GEN_SIMD_TRANS(pmulhsu_h_b1)
+GEN_SIMD_TRANS_32(mulh_h0)
+GEN_SIMD_TRANS_32(mulh_h1)
+GEN_SIMD_TRANS_32(mulhsu_h0)
+GEN_SIMD_TRANS_32(mulhsu_h1)
+GEN_SIMD_TRANS_64(pmulh_w_h0)
+GEN_SIMD_TRANS_64(pmulh_w_h1)
+GEN_SIMD_TRANS_64(pmulhsu_w_h0)
+GEN_SIMD_TRANS_64(pmulhsu_w_h1)
+GEN_SIMD_TRANS(pmul_h_b00)
+GEN_SIMD_TRANS(pmul_h_b01)
+GEN_SIMD_TRANS(pmul_h_b11)
+GEN_SIMD_TRANS(pmulsu_h_b00)
+GEN_SIMD_TRANS(pmulsu_h_b11)
+GEN_SIMD_TRANS(pmulu_h_b00)
+GEN_SIMD_TRANS(pmulu_h_b01)
+GEN_SIMD_TRANS(pmulu_h_b11)
+GEN_SIMD_TRANS_64(pmul_w_h00)
+GEN_SIMD_TRANS_64(pmul_w_h01)
+GEN_SIMD_TRANS_64(pmul_w_h11)
+GEN_SIMD_TRANS_64(pmulsu_w_h00)
+GEN_SIMD_TRANS_64(pmulsu_w_h11)
+GEN_SIMD_TRANS_64(pmulu_w_h00)
+GEN_SIMD_TRANS_64(pmulu_w_h01)
+GEN_SIMD_TRANS_64(pmulu_w_h11)
+GEN_SIMD_TRANS_VXSAT(pm2sadd_h)
+GEN_SIMD_TRANS_VXSAT(pm2sadd_hx)
+GEN_SIMD_TRANS_32(mul_h00)
+GEN_SIMD_TRANS_32(mul_h01)
+GEN_SIMD_TRANS_32(mul_h11)
+GEN_SIMD_TRANS_32(mulsu_h00)
+GEN_SIMD_TRANS_32(mulsu_h11)
+GEN_SIMD_TRANS_32(mulu_h00)
+GEN_SIMD_TRANS_32(mulu_h01)
+GEN_SIMD_TRANS_32(mulu_h11)
+GEN_SIMD_TRANS_64(mul_w00)
+GEN_SIMD_TRANS_64(mul_w01)
+GEN_SIMD_TRANS_64(mul_w11)
+GEN_SIMD_TRANS_64(mulsu_w00)
+GEN_SIMD_TRANS_64(mulsu_w11)
+GEN_SIMD_TRANS_64(mulu_w00)
+GEN_SIMD_TRANS_64(mulu_w01)
+GEN_SIMD_TRANS_64(mulu_w11)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 99f11f084f2..5be8fe257f8 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2259,3 +2259,187 @@ GEN_PSIMD_CLS(cls, target_ulong, uint32_t, clrsb32)
GEN_PSIMD_CLS(clsw, uint64_t, uint32_t, clrsb32)
+/* Pure multiplication operations */
+
+GEN_PSIMD_MUL_HIGH(pmulh_h, target_ulong, int16_t, int16_t, int32_t,
+ uint16_t, EXTRACT16, INSERT16, ELEMS_H, 16, 0,
+ PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH(pmulhsu_h, target_ulong, int16_t, uint16_t, int32_t,
+ uint16_t, EXTRACT16, INSERT16, ELEMS_H, 16, 0,
+ PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_HIGH(pmulhu_h, target_ulong, uint16_t, uint16_t, uint32_t,
+ uint16_t, EXTRACT16, INSERT16, ELEMS_H, 16, 0,
+ PSIMD_MUL_U32)
+GEN_PSIMD_MUL_HIGH(pmulhr_h, target_ulong, int16_t, int16_t, int32_t,
+ uint16_t, EXTRACT16, INSERT16, ELEMS_H, 16, 1 << 15,
+ PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH(pmulhrsu_h, target_ulong, int16_t, uint16_t, int32_t,
+ uint16_t, EXTRACT16, INSERT16, ELEMS_H, 16, 1 << 15,
+ PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_HIGH(pmulhru_h, target_ulong, uint16_t, uint16_t, uint32_t,
+ uint16_t, EXTRACT16, INSERT16, ELEMS_H, 16, 1 << 15,
+ PSIMD_MUL_U32)
+
+GEN_PSIMD_MUL_HIGH(pmulh_w, uint64_t, int32_t, int32_t, int64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH(pmulhr_w, uint64_t, int32_t, int32_t, int64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 1LL << 31,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH(pmulhsu_w, uint64_t, int32_t, uint32_t, int64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 0,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH(pmulhrsu_w, uint64_t, int32_t, uint32_t, int64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 1LL << 31,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH(pmulhu_w, uint64_t, uint32_t, uint32_t, uint64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 0,
+ PSIMD_MUL_U64)
+GEN_PSIMD_MUL_HIGH(pmulhru_w, uint64_t, uint32_t, uint32_t, uint64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 1LL << 31,
+ PSIMD_MUL_U64)
+
+GEN_PSIMD_MUL_HIGH(mulhr, uint32_t, int32_t, int32_t, int64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 1LL << 31,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH(mulhrsu, uint32_t, int32_t, uint32_t, int64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 1LL << 31,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH(mulhru, uint32_t, uint32_t, uint32_t, uint64_t,
+ uint32_t, EXTRACT32, INSERT32, ELEMS_W, 32, 1LL << 31,
+ PSIMD_MUL_U64)
+
+GEN_PSIMD_MUL_HIGH_SEL(pmulh_h_b0, target_ulong, int16_t, int8_t,
+ int32_t, uint16_t, EXTRACT16, EXTRACT8, INSERT16,
+ ELEMS_H, 2, 0, 8, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH_SEL(pmulh_h_b1, target_ulong, int16_t, int8_t,
+ int32_t, uint16_t, EXTRACT16, EXTRACT8, INSERT16,
+ ELEMS_H, 2, 1, 8, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH_SEL(pmulhsu_h_b0, target_ulong, int16_t, uint8_t,
+ int32_t, uint16_t, EXTRACT16, EXTRACT8, INSERT16,
+ ELEMS_H, 2, 0, 8, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_HIGH_SEL(pmulhsu_h_b1, target_ulong, int16_t, uint8_t,
+ int32_t, uint16_t, EXTRACT16, EXTRACT8, INSERT16,
+ ELEMS_H, 2, 1, 8, PSIMD_MUL_SU32)
+
+GEN_PSIMD_MUL_HIGH_SEL(mulh_h0, uint32_t, int32_t, int16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 0, 0, 16, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_SEL(mulh_h1, uint32_t, int32_t, int16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 0, 1, 16, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_SEL(mulhsu_h0, uint32_t, int32_t, uint16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 0, 0, 16, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_SEL(mulhsu_h1, uint32_t, int32_t, uint16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 0, 1, 16, PSIMD_MUL_SU64)
+
+GEN_PSIMD_MUL_HIGH_SEL(pmulh_w_h0, uint64_t, int32_t, int16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 2, 0, 16, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_SEL(pmulh_w_h1, uint64_t, int32_t, int16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 2, 1, 16, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_SEL(pmulhsu_w_h0, uint64_t, int32_t, uint16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 2, 0, 16, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_SEL(pmulhsu_w_h1, uint64_t, int32_t, uint16_t,
+ int64_t, uint32_t, EXTRACT32, EXTRACT16, INSERT32,
+ ELEMS_W, 2, 1, 16, PSIMD_MUL_SU64)
+
+GEN_PSIMD_MUL_ELEM_INDEXED(pmul_h_b00, target_ulong, int8_t, int8_t,
+ int16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 0, 0, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmul_h_b01, target_ulong, int8_t, int8_t,
+ int16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 0, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmul_h_b11, target_ulong, int8_t, int8_t,
+ int16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 1, 1, PSIMD_MUL_S32)
+
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulsu_h_b00, target_ulong, int8_t, uint8_t,
+ int16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 0, 0, PSIMD_MUL_SU16)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulsu_h_b11, target_ulong, int8_t, uint8_t,
+ int16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 1, 1, PSIMD_MUL_SU16)
+
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulu_h_b00, target_ulong, uint8_t, uint8_t,
+ uint16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 0, 0, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulu_h_b01, target_ulong, uint8_t, uint8_t,
+ uint16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 0, 1, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulu_h_b11, target_ulong, uint8_t, uint8_t,
+ uint16_t, uint16_t, EXTRACT8, INSERT16, ELEMS_H,
+ 2, 1, 1, PSIMD_MUL_U32)
+
+GEN_PSIMD_MUL_ELEM_INDEXED(pmul_w_h00, uint64_t, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 0, 0, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmul_w_h01, uint64_t, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 0, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmul_w_h11, uint64_t, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 1, 1, PSIMD_MUL_S32)
+
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulsu_w_h00, uint64_t, int16_t, uint16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 0, 0, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulsu_w_h11, uint64_t, int16_t, uint16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 1, 1, PSIMD_MUL_SU32)
+
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulu_w_h00, uint64_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 0, 0, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulu_w_h01, uint64_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 0, 1, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ELEM_INDEXED(pmulu_w_h11, uint64_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W,
+ 2, 1, 1, PSIMD_MUL_U32)
+
+GEN_PSIMD_2WAY_SAT_MUL(pm2sadd_h, 0, 1, 0, 1)
+GEN_PSIMD_2WAY_SAT_MUL(pm2sadd_hx, 0, 1, 1, 0)
+
+GEN_PSIMD_MUL_ELEM_SCALAR(mul_h00, uint32_t, int16_t, int16_t,
+ int32_t, EXTRACT16, 0, 0, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ELEM_SCALAR(mul_h01, uint32_t, int16_t, int16_t,
+ int32_t, EXTRACT16, 0, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ELEM_SCALAR(mul_h11, uint32_t, int16_t, int16_t,
+ int32_t, EXTRACT16, 1, 1, PSIMD_MUL_S32)
+
+GEN_PSIMD_MUL_ELEM_SCALAR(mulsu_h00, uint32_t, int16_t, uint16_t,
+ int32_t, EXTRACT16, 0, 0, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_ELEM_SCALAR(mulsu_h11, uint32_t, int16_t, uint16_t,
+ int32_t, EXTRACT16, 1, 1, PSIMD_MUL_SU32)
+
+GEN_PSIMD_MUL_ELEM_SCALAR(mulu_h00, uint32_t, uint16_t, uint16_t,
+ uint32_t, EXTRACT16, 0, 0, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ELEM_SCALAR(mulu_h01, uint32_t, uint16_t, uint16_t,
+ uint32_t, EXTRACT16, 0, 1, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ELEM_SCALAR(mulu_h11, uint32_t, uint16_t, uint16_t,
+ uint32_t, EXTRACT16, 1, 1, PSIMD_MUL_U32)
+
+GEN_PSIMD_MUL_ELEM_SCALAR(mul_w00, uint64_t, int32_t, int32_t,
+ int64_t, EXTRACT32, 0, 0, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_ELEM_SCALAR(mul_w01, uint64_t, int32_t, int32_t,
+ int64_t, EXTRACT32, 0, 1, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_ELEM_SCALAR(mul_w11, uint64_t, int32_t, int32_t,
+ int64_t, EXTRACT32, 1, 1, PSIMD_MUL_S64)
+
+GEN_PSIMD_MUL_ELEM_SCALAR(mulsu_w00, uint64_t, int32_t, uint32_t,
+ int64_t, EXTRACT32, 0, 0, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_ELEM_SCALAR(mulsu_w11, uint64_t, int32_t, uint32_t,
+ int64_t, EXTRACT32, 1, 1, PSIMD_MUL_SU64)
+
+GEN_PSIMD_MUL_ELEM_SCALAR(mulu_w00, uint64_t, uint32_t, uint32_t,
+ uint64_t, EXTRACT32, 0, 0, PSIMD_MUL_U64)
+GEN_PSIMD_MUL_ELEM_SCALAR(mulu_w01, uint64_t, uint32_t, uint32_t,
+ uint64_t, EXTRACT32, 0, 1, PSIMD_MUL_U64)
+GEN_PSIMD_MUL_ELEM_SCALAR(mulu_w11, uint64_t, uint32_t, uint32_t,
+ uint64_t, EXTRACT32, 1, 1, PSIMD_MUL_U64)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 11/18] target/riscv: Add packed SIMD multiply-accumulate instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (9 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 10/18] target/riscv: Add packed SIMD multiplication instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 12/18] target/riscv: Add packed SIMD Q-format multiplication instructions Molly Chen
` (8 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 56 ++++++
target/riscv/insn32.decode | 92 +++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 56 ++++++
target/riscv/tcg/psimd_helper.c | 195 ++++++++++++++++++++
4 files changed, 399 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index f06f40b1284..48604d91a79 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1624,3 +1624,59 @@ DEF_HELPER_3(mulsu_w11, i64, env, i64, i64)
DEF_HELPER_3(mulu_w00, i64, env, i64, i64)
DEF_HELPER_3(mulu_w01, i64, env, i64, i64)
DEF_HELPER_3(mulu_w11, i64, env, i64, i64)
+
+/* Packed SIMD - Multiply-Accumulate Operations */
+DEF_HELPER_4(pmhacc_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhaccsu_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhaccu_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhracc_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhraccsu_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhraccu_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhacc_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhracc_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhaccsu_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhraccsu_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhaccu_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhraccu_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(mhacc, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhracc, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhaccsu, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhraccsu, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhaccu, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhraccu, i32, env, i32, i32, i32)
+DEF_HELPER_4(pmhacc_h_b0, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhacc_h_b1, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhaccsu_h_b0, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmhaccsu_h_b1, tl, env, tl, tl, tl)
+DEF_HELPER_4(mhacc_h0, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhacc_h1, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhaccsu_h0, i32, env, i32, i32, i32)
+DEF_HELPER_4(mhaccsu_h1, i32, env, i32, i32, i32)
+DEF_HELPER_4(pmhacc_w_h0, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhacc_w_h1, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhaccsu_w_h0, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmhaccsu_w_h1, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmacc_w_h00, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmacc_w_h01, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmacc_w_h11, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmaccsu_w_h00, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmaccsu_w_h11, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmaccu_w_h00, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmaccu_w_h01, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmaccu_w_h11, i64, env, i64, i64, i64)
+DEF_HELPER_4(macc_h00, i32, env, i32, i32, i32)
+DEF_HELPER_4(macc_h01, i32, env, i32, i32, i32)
+DEF_HELPER_4(macc_h11, i32, env, i32, i32, i32)
+DEF_HELPER_4(maccsu_h00, i32, env, i32, i32, i32)
+DEF_HELPER_4(maccsu_h11, i32, env, i32, i32, i32)
+DEF_HELPER_4(maccu_h00, i32, env, i32, i32, i32)
+DEF_HELPER_4(maccu_h01, i32, env, i32, i32, i32)
+DEF_HELPER_4(maccu_h11, i32, env, i32, i32, i32)
+DEF_HELPER_4(macc_w00, i64, env, i64, i64, i64)
+DEF_HELPER_4(macc_w01, i64, env, i64, i64, i64)
+DEF_HELPER_4(macc_w11, i64, env, i64, i64, i64)
+DEF_HELPER_4(maccsu_w00, i64, env, i64, i64, i64)
+DEF_HELPER_4(maccsu_w11, i64, env, i64, i64, i64)
+DEF_HELPER_4(maccu_w00, i64, env, i64, i64, i64)
+DEF_HELPER_4(maccu_w01, i64, env, i64, i64, i64)
+DEF_HELPER_4(maccu_w11, i64, env, i64, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index cc0cc35fe24..a9b407e43e2 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1430,3 +1430,95 @@ mulsu_w11 11110 11 ..... ..... 011 ..... 0111011 @r
mulu_w00 10100 11 ..... ..... 011 ..... 0111011 @r
mulu_w01 10110 11 ..... ..... 001 ..... 0111011 @r
mulu_w11 10110 11 ..... ..... 011 ..... 0111011 @r
+
+# Packed SIMD - Multiply-Accumulate Operations
+pmhacc_h 10001 00 ..... ..... 111 ..... 0111011 @r
+pmhaccsu_h 11001 00 ..... ..... 111 ..... 0111011 @r
+pmhaccu_h 10011 00 ..... ..... 111 ..... 0111011 @r
+pmhracc_h 10001 10 ..... ..... 111 ..... 0111011 @r
+pmhraccsu_h 11001 10 ..... ..... 111 ..... 0111011 @r
+pmhraccu_h 10011 10 ..... ..... 111 ..... 0111011 @r
+{
+ mhacc 10001 01 ..... ..... 111 ..... 0111011 @r
+ pmhacc_w 10001 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhracc 10001 11 ..... ..... 111 ..... 0111011 @r
+ pmhracc_w 10001 11 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhaccsu 11001 01 ..... ..... 111 ..... 0111011 @r
+ pmhaccsu_w 11001 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhraccsu 11001 11 ..... ..... 111 ..... 0111011 @r
+ pmhraccsu_w 11001 11 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhaccu 10011 01 ..... ..... 111 ..... 0111011 @r
+ pmhaccu_w 10011 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhraccu 10011 11 ..... ..... 111 ..... 0111011 @r
+ pmhraccu_w 10011 11 ..... ..... 111 ..... 0111011 @r
+}
+pmhacc_h_b0 10101 00 ..... ..... 111 ..... 0111011 @r
+pmhacc_h_b1 10111 00 ..... ..... 111 ..... 0111011 @r
+pmhaccsu_h_b0 10101 10 ..... ..... 111 ..... 0111011 @r
+pmhaccsu_h_b1 10111 10 ..... ..... 111 ..... 0111011 @r
+{
+ mhacc_h0 10101 01 ..... ..... 111 ..... 0111011 @r
+ pmhacc_w_h0 10101 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhacc_h1 10111 01 ..... ..... 111 ..... 0111011 @r
+ pmhacc_w_h1 10111 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhaccsu_h0 10101 11 ..... ..... 111 ..... 0111011 @r
+ pmhaccsu_w_h0 10101 11 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mhaccsu_h1 10111 11 ..... ..... 111 ..... 0111011 @r
+ pmhaccsu_w_h1 10111 11 ..... ..... 111 ..... 0111011 @r
+}
+{
+ macc_h00 10001 01 ..... ..... 011 ..... 0111011 @r
+ pmacc_w_h00 10001 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ macc_h01 10011 01 ..... ..... 001 ..... 0111011 @r
+ pmacc_w_h01 10011 01 ..... ..... 001 ..... 0111011 @r
+}
+{
+ macc_h11 10011 01 ..... ..... 011 ..... 0111011 @r
+ pmacc_w_h11 10011 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ maccsu_h00 11101 01 ..... ..... 011 ..... 0111011 @r
+ pmaccsu_w_h00 11101 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ maccsu_h11 11111 01 ..... ..... 011 ..... 0111011 @r
+ pmaccsu_w_h11 11111 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ maccu_h00 10101 01 ..... ..... 011 ..... 0111011 @r
+ pmaccu_w_h00 10101 01 ..... ..... 011 ..... 0111011 @r
+}
+{
+ maccu_h01 10111 01 ..... ..... 001 ..... 0111011 @r
+ pmaccu_w_h01 10111 01 ..... ..... 001 ..... 0111011 @r
+}
+{
+ maccu_h11 10111 01 ..... ..... 011 ..... 0111011 @r
+ pmaccu_w_h11 10111 01 ..... ..... 011 ..... 0111011 @r
+}
+macc_w00 10001 11 ..... ..... 011 ..... 0111011 @r
+macc_w01 10011 11 ..... ..... 001 ..... 0111011 @r
+macc_w11 10011 11 ..... ..... 011 ..... 0111011 @r
+maccsu_w00 11101 11 ..... ..... 011 ..... 0111011 @r
+maccsu_w11 11111 11 ..... ..... 011 ..... 0111011 @r
+maccu_w00 10101 11 ..... ..... 011 ..... 0111011 @r
+maccu_w01 10111 11 ..... ..... 001 ..... 0111011 @r
+maccu_w11 10111 11 ..... ..... 011 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 7edea099d01..5a30c49016f 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -770,3 +770,59 @@ GEN_SIMD_TRANS_64(mulu_w00)
GEN_SIMD_TRANS_64(mulu_w01)
GEN_SIMD_TRANS_64(mulu_w11)
+/* Packed SIMD - Multiply-Accumulate Operations */
+GEN_SIMD_TRANS_ACC(pmhacc_h)
+GEN_SIMD_TRANS_ACC(pmhaccsu_h)
+GEN_SIMD_TRANS_ACC(pmhaccu_h)
+GEN_SIMD_TRANS_ACC(pmhracc_h)
+GEN_SIMD_TRANS_ACC(pmhraccsu_h)
+GEN_SIMD_TRANS_ACC(pmhraccu_h)
+GEN_SIMD_TRANS_ACC_64(pmhacc_w)
+GEN_SIMD_TRANS_ACC_64(pmhracc_w)
+GEN_SIMD_TRANS_ACC_64(pmhaccsu_w)
+GEN_SIMD_TRANS_ACC_64(pmhraccsu_w)
+GEN_SIMD_TRANS_ACC_64(pmhaccu_w)
+GEN_SIMD_TRANS_ACC_64(pmhraccu_w)
+GEN_SIMD_TRANS_ACC_32(mhacc)
+GEN_SIMD_TRANS_ACC_32(mhracc)
+GEN_SIMD_TRANS_ACC_32(mhaccsu)
+GEN_SIMD_TRANS_ACC_32(mhraccsu)
+GEN_SIMD_TRANS_ACC_32(mhaccu)
+GEN_SIMD_TRANS_ACC_32(mhraccu)
+GEN_SIMD_TRANS_ACC(pmhacc_h_b0)
+GEN_SIMD_TRANS_ACC(pmhacc_h_b1)
+GEN_SIMD_TRANS_ACC(pmhaccsu_h_b0)
+GEN_SIMD_TRANS_ACC(pmhaccsu_h_b1)
+GEN_SIMD_TRANS_ACC_32(mhacc_h0)
+GEN_SIMD_TRANS_ACC_32(mhacc_h1)
+GEN_SIMD_TRANS_ACC_32(mhaccsu_h0)
+GEN_SIMD_TRANS_ACC_32(mhaccsu_h1)
+GEN_SIMD_TRANS_ACC_64(pmhacc_w_h0)
+GEN_SIMD_TRANS_ACC_64(pmhacc_w_h1)
+GEN_SIMD_TRANS_ACC_64(pmhaccsu_w_h0)
+GEN_SIMD_TRANS_ACC_64(pmhaccsu_w_h1)
+GEN_SIMD_TRANS_ACC_64(pmacc_w_h00)
+GEN_SIMD_TRANS_ACC_64(pmacc_w_h01)
+GEN_SIMD_TRANS_ACC_64(pmacc_w_h11)
+GEN_SIMD_TRANS_ACC_64(pmaccsu_w_h00)
+GEN_SIMD_TRANS_ACC_64(pmaccsu_w_h11)
+GEN_SIMD_TRANS_ACC_64(pmaccu_w_h00)
+GEN_SIMD_TRANS_ACC_64(pmaccu_w_h01)
+GEN_SIMD_TRANS_ACC_64(pmaccu_w_h11)
+GEN_SIMD_TRANS_ACC_32(macc_h00)
+GEN_SIMD_TRANS_ACC_32(macc_h01)
+GEN_SIMD_TRANS_ACC_32(macc_h11)
+GEN_SIMD_TRANS_ACC_32(maccsu_h00)
+GEN_SIMD_TRANS_ACC_32(maccsu_h11)
+GEN_SIMD_TRANS_ACC_32(maccu_h00)
+GEN_SIMD_TRANS_ACC_32(maccu_h01)
+GEN_SIMD_TRANS_ACC_32(maccu_h11)
+GEN_SIMD_TRANS_ACC_64(macc_w00)
+GEN_SIMD_TRANS_ACC_64(macc_w01)
+GEN_SIMD_TRANS_ACC_64(macc_w11)
+GEN_SIMD_TRANS_ACC_64(maccsu_w00)
+GEN_SIMD_TRANS_ACC_64(maccsu_w11)
+GEN_SIMD_TRANS_ACC_64(maccu_w00)
+GEN_SIMD_TRANS_ACC_64(maccu_w01)
+GEN_SIMD_TRANS_ACC_64(maccu_w11)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 5be8fe257f8..91a3aac3ebb 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2443,3 +2443,198 @@ GEN_PSIMD_MUL_ELEM_SCALAR(mulu_w01, uint64_t, uint32_t, uint32_t,
GEN_PSIMD_MUL_ELEM_SCALAR(mulu_w11, uint64_t, uint32_t, uint32_t,
uint64_t, EXTRACT32, 1, 1, PSIMD_MUL_U64)
+/* Multiply-Accumulate Operations */
+
+GEN_PSIMD_MUL_HIGH_ACC(pmhacc_h, target_ulong, int16_t, int16_t, int16_t,
+ int32_t, int16_t, uint16_t, EXTRACT16, INSERT16,
+ ELEMS_H, 16, 0, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH_ACC(pmhaccsu_h, target_ulong, int16_t, uint16_t, int16_t,
+ int32_t, int16_t, uint16_t, EXTRACT16, INSERT16,
+ ELEMS_H, 16, 0, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_HIGH_ACC(pmhaccu_h, target_ulong, uint16_t, uint16_t, uint16_t,
+ uint32_t, uint16_t, uint16_t, EXTRACT16, INSERT16,
+ ELEMS_H, 16, 0, PSIMD_MUL_U32)
+GEN_PSIMD_MUL_HIGH_ACC(pmhracc_h, target_ulong, int16_t, int16_t, int16_t,
+ int32_t, int16_t, uint16_t, EXTRACT16, INSERT16,
+ ELEMS_H, 16, 1 << 15, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH_ACC(pmhraccsu_h, target_ulong, int16_t, uint16_t, int16_t,
+ int32_t, int16_t, uint16_t, EXTRACT16, INSERT16,
+ ELEMS_H, 16, 1 << 15, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_HIGH_ACC(pmhraccu_h, target_ulong, uint16_t, uint16_t,
+ uint16_t, uint32_t, uint16_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 16, 1 << 15,
+ PSIMD_MUL_U32)
+
+GEN_PSIMD_MUL_HIGH_ACC(pmhacc_w, uint64_t, int32_t, int32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 0, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC(pmhracc_w, uint64_t, int32_t, int32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 1LL << 31, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC(pmhaccsu_w, uint64_t, int32_t, uint32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 0, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_ACC(pmhraccsu_w, uint64_t, int32_t, uint32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 1LL << 31, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_ACC(pmhaccu_w, uint64_t, uint32_t, uint32_t, uint32_t,
+ uint64_t, uint32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 0, PSIMD_MUL_U64)
+GEN_PSIMD_MUL_HIGH_ACC(pmhraccu_w, uint64_t, uint32_t, uint32_t, uint32_t,
+ uint64_t, uint32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 1LL << 31, PSIMD_MUL_U64)
+
+GEN_PSIMD_MUL_HIGH_ACC(mhacc, uint32_t, int32_t, int32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 0, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC(mhracc, uint32_t, int32_t, int32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 1LL << 31, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC(mhaccsu, uint32_t, int32_t, uint32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 0, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_ACC(mhraccsu, uint32_t, int32_t, uint32_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 1LL << 31, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_ACC(mhaccu, uint32_t, uint32_t, uint32_t, uint32_t,
+ uint64_t, uint32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 0, PSIMD_MUL_U64)
+GEN_PSIMD_MUL_HIGH_ACC(mhraccu, uint32_t, uint32_t, uint32_t, uint32_t,
+ uint64_t, uint32_t, uint32_t, EXTRACT32, INSERT32,
+ ELEMS_W, 32, 1LL << 31, PSIMD_MUL_U64)
+
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhacc_h_b0, target_ulong, int16_t, int8_t,
+ int16_t, int32_t, int16_t, uint16_t, EXTRACT16,
+ EXTRACT8, INSERT16, ELEMS_H, 2, 0, 8,
+ PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhacc_h_b1, target_ulong, int16_t, int8_t,
+ int16_t, int32_t, int16_t, uint16_t, EXTRACT16,
+ EXTRACT8, INSERT16, ELEMS_H, 2, 1, 8,
+ PSIMD_MUL_S32)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhaccsu_h_b0, target_ulong, int16_t, uint8_t,
+ int16_t, int32_t, int16_t, uint16_t, EXTRACT16,
+ EXTRACT8, INSERT16, ELEMS_H, 2, 0, 8,
+ PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhaccsu_h_b1, target_ulong, int16_t, uint8_t,
+ int16_t, int32_t, int16_t, uint16_t, EXTRACT16,
+ EXTRACT8, INSERT16, ELEMS_H, 2, 1, 8,
+ PSIMD_MUL_SU32)
+
+GEN_PSIMD_MUL_HIGH_ACC_SEL(mhacc_h0, uint32_t, int32_t, int16_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 0, 0, 16,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(mhacc_h1, uint32_t, int32_t, int16_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 0, 1, 16,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(mhaccsu_h0, uint32_t, int32_t, uint16_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 0, 0, 16,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(mhaccsu_h1, uint32_t, int32_t, uint16_t, int32_t,
+ int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 0, 1, 16,
+ PSIMD_MUL_SU64)
+
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhacc_w_h0, uint64_t, int32_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 2, 0, 16,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhacc_w_h1, uint64_t, int32_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 2, 1, 16,
+ PSIMD_MUL_S64)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhaccsu_w_h0, uint64_t, int32_t, uint16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 2, 0, 16,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_HIGH_ACC_SEL(pmhaccsu_w_h1, uint64_t, int32_t, uint16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT32,
+ EXTRACT16, INSERT32, ELEMS_W, 2, 1, 16,
+ PSIMD_MUL_SU64)
+
+GEN_PSIMD_MUL_ACC_INDEXED(pmacc_w_h00, uint64_t, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 0, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmacc_w_h01, uint64_t, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmacc_w_h11, uint64_t, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 1, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmaccsu_w_h00, uint64_t, int16_t, uint16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 0, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmaccsu_w_h11, uint64_t, int16_t, uint16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 1, 1, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmaccu_w_h00, uint64_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 0, 0,
+ PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmaccu_w_h01, uint64_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 0, 1,
+ PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ACC_INDEXED(pmaccu_w_h11, uint64_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 1, 1,
+ PSIMD_MUL_U32)
+
+GEN_PSIMD_MUL_ACC_INDEXED(macc_h00, uint32_t, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 0, 0, 0, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ACC_INDEXED(macc_h01, uint32_t, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 0, 0, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ACC_INDEXED(macc_h11, uint32_t, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 0, 1, 1, PSIMD_MUL_S32)
+GEN_PSIMD_MUL_ACC_INDEXED(maccsu_h00, uint32_t, int16_t, uint16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 0, 0, 0, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_ACC_INDEXED(maccsu_h11, uint32_t, int16_t, uint16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 0, 1, 1, PSIMD_MUL_SU32)
+GEN_PSIMD_MUL_ACC_INDEXED(maccu_h00, uint32_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 0, 0,
+ PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ACC_INDEXED(maccu_h01, uint32_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 0, 1,
+ PSIMD_MUL_U32)
+GEN_PSIMD_MUL_ACC_INDEXED(maccu_h11, uint32_t, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 1, 1,
+ PSIMD_MUL_U32)
+
+GEN_PSIMD_MUL_ACC_INDEXED(macc_w00, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 0, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_ACC_INDEXED(macc_w01, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_ACC_INDEXED(macc_w11, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 1, 1, PSIMD_MUL_S64)
+GEN_PSIMD_MUL_ACC_INDEXED(maccsu_w00, uint64_t, int32_t, uint32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 0, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_ACC_INDEXED(maccsu_w11, uint64_t, int32_t, uint32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 1, 1, PSIMD_MUL_SU64)
+GEN_PSIMD_MUL_ACC_INDEXED(maccu_w00, uint64_t, uint32_t, uint32_t,
+ uint64_t, uint64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 0, 0,
+ PSIMD_MUL_U64)
+GEN_PSIMD_MUL_ACC_INDEXED(maccu_w01, uint64_t, uint32_t, uint32_t,
+ uint64_t, uint64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 0, 1,
+ PSIMD_MUL_U64)
+GEN_PSIMD_MUL_ACC_INDEXED(maccu_w11, uint64_t, uint32_t, uint32_t,
+ uint64_t, uint64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 1, 1,
+ PSIMD_MUL_U64)
+
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 12/18] target/riscv: Add packed SIMD Q-format multiplication instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (10 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 11/18] target/riscv: Add packed SIMD multiply-accumulate instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 13/18] target/riscv: Add packed SIMD Q-format MAC instructions Molly Chen
` (7 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 8 ++++++++
target/riscv/insn32.decode | 12 ++++++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 8 ++++++++
target/riscv/tcg/psimd_helper.c | 17 +++++++++++++++++
4 files changed, 45 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 48604d91a79..638c7b0629d 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1680,3 +1680,11 @@ DEF_HELPER_4(maccsu_w11, i64, env, i64, i64, i64)
DEF_HELPER_4(maccu_w00, i64, env, i64, i64, i64)
DEF_HELPER_4(maccu_w01, i64, env, i64, i64, i64)
DEF_HELPER_4(maccu_w11, i64, env, i64, i64, i64)
+
+/* Packed SIMD - Q-Format Multiplication Operations */
+DEF_HELPER_3(pmulq_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulqr_h, tl, env, tl, tl)
+DEF_HELPER_3(pmulq_w, i64, env, i64, i64)
+DEF_HELPER_3(pmulqr_w, i64, env, i64, i64)
+DEF_HELPER_3(mulq, i32, env, i32, i32)
+DEF_HELPER_3(mulqr, i32, env, i32, i32)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index a9b407e43e2..9c50a4dbf52 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1522,3 +1522,15 @@ maccsu_w11 11111 11 ..... ..... 011 ..... 0111011 @r
maccu_w00 10101 11 ..... ..... 011 ..... 0111011 @r
maccu_w01 10111 11 ..... ..... 001 ..... 0111011 @r
maccu_w11 10111 11 ..... ..... 011 ..... 0111011 @r
+
+# Packed SIMD - Q-Format Multiplication Operations
+pmulq_h 11010 00 ..... ..... 111 ..... 0111011 @r
+pmulqr_h 11010 10 ..... ..... 111 ..... 0111011 @r
+{
+ mulq 11010 01 ..... ..... 111 ..... 0111011 @r
+ pmulq_w 11010 01 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mulqr 11010 11 ..... ..... 111 ..... 0111011 @r
+ pmulqr_w 11010 11 ..... ..... 111 ..... 0111011 @r
+}
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 5a30c49016f..3535f71de88 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -826,3 +826,11 @@ GEN_SIMD_TRANS_ACC_64(maccu_w00)
GEN_SIMD_TRANS_ACC_64(maccu_w01)
GEN_SIMD_TRANS_ACC_64(maccu_w11)
+/* Packed SIMD - Q-Format Multiplication Operations */
+GEN_SIMD_TRANS_VXSAT(pmulq_h)
+GEN_SIMD_TRANS_VXSAT(pmulqr_h)
+GEN_SIMD_TRANS_64_VXSAT(pmulq_w)
+GEN_SIMD_TRANS_64_VXSAT(pmulqr_w)
+GEN_SIMD_TRANS_32_VXSAT(mulq)
+GEN_SIMD_TRANS_32_VXSAT(mulqr)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 91a3aac3ebb..11ca17576be 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2638,3 +2638,20 @@ GEN_PSIMD_MUL_ACC_INDEXED(maccu_w11, uint64_t, uint32_t, uint32_t,
EXTRACT64, INSERT64, ELEMS_D, 0, 1, 1,
PSIMD_MUL_U64)
+/* Q-Format Multiplication Operations */
+
+GEN_PSIMD_QMUL(pmulq_h, target_ulong, int16_t, int32_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 15, 0, INT16_MIN, INT16_MAX)
+GEN_PSIMD_QMUL(pmulqr_h, target_ulong, int16_t, int32_t, uint16_t,
+ EXTRACT16, INSERT16, ELEMS_H, 15, 1 << 14, INT16_MIN,
+ INT16_MAX)
+GEN_PSIMD_QMUL(pmulq_w, uint64_t, int32_t, int64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 31, 0, INT32_MIN, INT32_MAX)
+GEN_PSIMD_QMUL(pmulqr_w, uint64_t, int32_t, int64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 31, 1LL << 30, INT32_MIN,
+ INT32_MAX)
+GEN_PSIMD_QMUL(mulq, uint32_t, int32_t, int64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 31, 0, INT32_MIN, INT32_MAX)
+GEN_PSIMD_QMUL(mulqr, uint32_t, int32_t, int64_t, uint32_t,
+ EXTRACT32, INSERT32, ELEMS_W, 31, 1LL << 30, INT32_MIN,
+ INT32_MAX)
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 13/18] target/riscv: Add packed SIMD Q-format MAC instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (11 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 12/18] target/riscv: Add packed SIMD Q-format multiplication instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 14/18] target/riscv: Add packed SIMD two-way " Molly Chen
` (6 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 20 ++++++
target/riscv/insn32.decode | 32 +++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 20 ++++++
target/riscv/tcg/psimd_helper.c | 78 +++++++++++++++++++++
4 files changed, 150 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 638c7b0629d..9568a7f91c4 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1688,3 +1688,23 @@ DEF_HELPER_3(pmulq_w, i64, env, i64, i64)
DEF_HELPER_3(pmulqr_w, i64, env, i64, i64)
DEF_HELPER_3(mulq, i32, env, i32, i32)
DEF_HELPER_3(mulqr, i32, env, i32, i32)
+
+/* Packed SIMD - Q-Format Multiply-Accumulate Operations */
+DEF_HELPER_4(mqacc_h00, i32, env, i32, i32, i32)
+DEF_HELPER_4(mqacc_h01, i32, env, i32, i32, i32)
+DEF_HELPER_4(mqacc_h11, i32, env, i32, i32, i32)
+DEF_HELPER_4(mqracc_h00, i32, env, i32, i32, i32)
+DEF_HELPER_4(mqracc_h01, i32, env, i32, i32, i32)
+DEF_HELPER_4(mqracc_h11, i32, env, i32, i32, i32)
+DEF_HELPER_4(mqacc_w00, i64, env, i64, i64, i64)
+DEF_HELPER_4(mqacc_w01, i64, env, i64, i64, i64)
+DEF_HELPER_4(mqacc_w11, i64, env, i64, i64, i64)
+DEF_HELPER_4(mqracc_w00, i64, env, i64, i64, i64)
+DEF_HELPER_4(mqracc_w01, i64, env, i64, i64, i64)
+DEF_HELPER_4(mqracc_w11, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqacc_w_h00, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqacc_w_h01, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqacc_w_h11, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqracc_w_h00, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqracc_w_h01, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqracc_w_h11, i64, env, i64, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 9c50a4dbf52..e2af5f83965 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1534,3 +1534,35 @@ pmulqr_h 11010 10 ..... ..... 111 ..... 0111011 @r
mulqr 11010 11 ..... ..... 111 ..... 0111011 @r
pmulqr_w 11010 11 ..... ..... 111 ..... 0111011 @r
}
+
+# Packed SIMD - Q-Format Multiply-Accumulate Operations
+{
+ mqacc_h00 11101 00 ..... ..... 111 ..... 0111011 @r
+ pmqacc_w_h00 11101 00 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mqacc_h01 11111 00 ..... ..... 101 ..... 0111011 @r
+ pmqacc_w_h01 11111 00 ..... ..... 101 ..... 0111011 @r
+}
+{
+ mqacc_h11 11111 00 ..... ..... 111 ..... 0111011 @r
+ pmqacc_w_h11 11111 00 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mqracc_h00 11101 10 ..... ..... 111 ..... 0111011 @r
+ pmqracc_w_h00 11101 10 ..... ..... 111 ..... 0111011 @r
+}
+{
+ mqracc_h01 11111 10 ..... ..... 101 ..... 0111011 @r
+ pmqracc_w_h01 11111 10 ..... ..... 101 ..... 0111011 @r
+}
+{
+ mqracc_h11 11111 10 ..... ..... 111 ..... 0111011 @r
+ pmqracc_w_h11 11111 10 ..... ..... 111 ..... 0111011 @r
+}
+mqacc_w00 11101 01 ..... ..... 111 ..... 0111011 @r
+mqacc_w01 11111 01 ..... ..... 101 ..... 0111011 @r
+mqacc_w11 11111 01 ..... ..... 111 ..... 0111011 @r
+mqracc_w00 11101 11 ..... ..... 111 ..... 0111011 @r
+mqracc_w01 11111 11 ..... ..... 101 ..... 0111011 @r
+mqracc_w11 11111 11 ..... ..... 111 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 3535f71de88..cec18255a1e 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -834,3 +834,23 @@ GEN_SIMD_TRANS_64_VXSAT(pmulqr_w)
GEN_SIMD_TRANS_32_VXSAT(mulq)
GEN_SIMD_TRANS_32_VXSAT(mulqr)
+/* Packed SIMD - Q-Format Multiply-Accumulate Operations */
+GEN_SIMD_TRANS_ACC_32(mqacc_h00)
+GEN_SIMD_TRANS_ACC_32(mqacc_h01)
+GEN_SIMD_TRANS_ACC_32(mqacc_h11)
+GEN_SIMD_TRANS_ACC_32(mqracc_h00)
+GEN_SIMD_TRANS_ACC_32(mqracc_h01)
+GEN_SIMD_TRANS_ACC_32(mqracc_h11)
+GEN_SIMD_TRANS_ACC_64(mqacc_w00)
+GEN_SIMD_TRANS_ACC_64(mqacc_w01)
+GEN_SIMD_TRANS_ACC_64(mqacc_w11)
+GEN_SIMD_TRANS_ACC_64(mqracc_w00)
+GEN_SIMD_TRANS_ACC_64(mqracc_w01)
+GEN_SIMD_TRANS_ACC_64(mqracc_w11)
+GEN_SIMD_TRANS_ACC_64(pmqacc_w_h00)
+GEN_SIMD_TRANS_ACC_64(pmqacc_w_h01)
+GEN_SIMD_TRANS_ACC_64(pmqacc_w_h11)
+GEN_SIMD_TRANS_ACC_64(pmqracc_w_h00)
+GEN_SIMD_TRANS_ACC_64(pmqracc_w_h01)
+GEN_SIMD_TRANS_ACC_64(pmqracc_w_h11)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index 11ca17576be..ecdb20bbb58 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2655,3 +2655,81 @@ GEN_PSIMD_QMUL(mulq, uint32_t, int32_t, int64_t, uint32_t,
GEN_PSIMD_QMUL(mulqr, uint32_t, int32_t, int64_t, uint32_t,
EXTRACT32, INSERT32, ELEMS_W, 31, 1LL << 30, INT32_MIN,
INT32_MAX)
+
+
+/* Q-Format Multiply-Accumulate Operations */
+
+GEN_PSIMD_QMUL_ACC_INDEXED(mqacc_h00, uint32_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 0, 0, 15, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqacc_h01, uint32_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 0, 1, 15, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqacc_h11, uint32_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 1, 1, 15, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqracc_h00, uint32_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 0, 0, 15,
+ 1LL << 14, PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqracc_h01, uint32_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 0, 1, 15,
+ 1LL << 14, PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqracc_h11, uint32_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 0, 1, 1, 15,
+ 1LL << 14, PSIMD_MUL_S64)
+
+GEN_PSIMD_QMUL_ACC_INDEXED(mqacc_w00, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, int64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 0, 0, 31, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqacc_w01, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, int64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 0, 1, 31, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqacc_w11, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, int64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 1, 1, 31, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqracc_w00, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, int64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 0, 0, 31,
+ 1LL << 30, PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqracc_w01, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, int64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 0, 1, 31,
+ 1LL << 30, PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(mqracc_w11, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, int64_t, uint64_t, EXTRACT32,
+ EXTRACT64, INSERT64, ELEMS_D, 0, 1, 1, 31,
+ 1LL << 30, PSIMD_MUL_S64)
+
+GEN_PSIMD_QMUL_ACC_INDEXED(pmqacc_w_h00, uint64_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 0, 0, 15, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(pmqacc_w_h01, uint64_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 0, 1, 15, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(pmqacc_w_h11, uint64_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 1, 1, 15, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(pmqracc_w_h00, uint64_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 0, 0, 15,
+ 1LL << 14, PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(pmqracc_w_h01, uint64_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 0, 1, 15,
+ 1LL << 14, PSIMD_MUL_S64)
+GEN_PSIMD_QMUL_ACC_INDEXED(pmqracc_w_h11, uint64_t, int16_t, int16_t,
+ int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
+ EXTRACT32, INSERT32, ELEMS_W, 2, 1, 1, 15,
+ 1LL << 14, PSIMD_MUL_S64)
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 14/18] target/riscv: Add packed SIMD two-way MAC instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (12 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 13/18] target/riscv: Add packed SIMD Q-format MAC instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 15/18] target/riscv: Add packed SIMD four-way " Molly Chen
` (5 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 34 ++++++
target/riscv/insn32.decode | 34 ++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 34 ++++++
target/riscv/tcg/psimd_helper.c | 116 ++++++++++++++++++++
4 files changed, 218 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 9568a7f91c4..b0743d19177 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1708,3 +1708,37 @@ DEF_HELPER_4(pmqacc_w_h11, i64, env, i64, i64, i64)
DEF_HELPER_4(pmqracc_w_h00, i64, env, i64, i64, i64)
DEF_HELPER_4(pmqracc_w_h01, i64, env, i64, i64, i64)
DEF_HELPER_4(pmqracc_w_h11, i64, env, i64, i64, i64)
+
+/* Packed SIMD - Two-Way Multiply and Accumulate Operations */
+DEF_HELPER_3(pmq2add_h, tl, env, tl, tl)
+DEF_HELPER_3(pmqr2add_h, tl, env, tl, tl)
+DEF_HELPER_4(pmq2adda_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pmqr2adda_h, tl, env, tl, tl, tl)
+DEF_HELPER_3(pmq2add_w, i64, env, i64, i64)
+DEF_HELPER_3(pmqr2add_w, i64, env, i64, i64)
+DEF_HELPER_4(pmq2adda_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pmqr2adda_w, i64, env, i64, i64, i64)
+DEF_HELPER_3(pm2add_h, tl, env, tl, tl)
+DEF_HELPER_3(pm2addsu_h, tl, env, tl, tl)
+DEF_HELPER_3(pm2addu_h, tl, env, tl, tl)
+DEF_HELPER_3(pm2add_hx, tl, env, tl, tl)
+DEF_HELPER_3(pm2sub_h, tl, env, tl, tl)
+DEF_HELPER_3(pm2sub_hx, tl, env, tl, tl)
+DEF_HELPER_4(pm2adda_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm2addasu_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm2addau_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm2adda_hx, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm2suba_h, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm2suba_hx, tl, env, tl, tl, tl)
+DEF_HELPER_3(pm2add_w, i64, env, i64, i64)
+DEF_HELPER_3(pm2addsu_w, i64, env, i64, i64)
+DEF_HELPER_3(pm2addu_w, i64, env, i64, i64)
+DEF_HELPER_3(pm2add_wx, i64, env, i64, i64)
+DEF_HELPER_3(pm2sub_w, i64, env, i64, i64)
+DEF_HELPER_3(pm2sub_wx, i64, env, i64, i64)
+DEF_HELPER_4(pm2adda_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm2addasu_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm2addau_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm2adda_wx, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm2suba_w, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm2suba_wx, i64, env, i64, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index e2af5f83965..1c8bdde25c2 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1566,3 +1566,37 @@ mqacc_w11 11111 01 ..... ..... 111 ..... 0111011 @r
mqracc_w00 11101 11 ..... ..... 111 ..... 0111011 @r
mqracc_w01 11111 11 ..... ..... 101 ..... 0111011 @r
mqracc_w11 11111 11 ..... ..... 111 ..... 0111011 @r
+
+# Packed SIMD - Two-Way Multiply and Accumulate Operations
+pmq2add_h 10110 00 ..... ..... 101 ..... 0111011 @r
+pmqr2add_h 10110 10 ..... ..... 101 ..... 0111011 @r
+pmq2adda_h 10111 00 ..... ..... 101 ..... 0111011 @r
+pmqr2adda_h 10111 10 ..... ..... 101 ..... 0111011 @r
+pmq2add_w 10110 01 ..... ..... 101 ..... 0111011 @r
+pmqr2add_w 10110 11 ..... ..... 101 ..... 0111011 @r
+pmq2adda_w 10111 01 ..... ..... 101 ..... 0111011 @r
+pmqr2adda_w 10111 11 ..... ..... 101 ..... 0111011 @r
+pm2add_h 10000 00 ..... ..... 101 ..... 0111011 @r
+pm2addsu_h 11100 00 ..... ..... 101 ..... 0111011 @r
+pm2addu_h 10100 00 ..... ..... 101 ..... 0111011 @r
+pm2add_hx 10010 00 ..... ..... 101 ..... 0111011 @r
+pm2sub_h 11000 00 ..... ..... 101 ..... 0111011 @r
+pm2sub_hx 11010 00 ..... ..... 101 ..... 0111011 @r
+pm2adda_h 10001 00 ..... ..... 101 ..... 0111011 @r
+pm2addasu_h 11101 00 ..... ..... 101 ..... 0111011 @r
+pm2addau_h 10101 00 ..... ..... 101 ..... 0111011 @r
+pm2adda_hx 10011 00 ..... ..... 101 ..... 0111011 @r
+pm2suba_h 11001 00 ..... ..... 101 ..... 0111011 @r
+pm2suba_hx 11011 00 ..... ..... 101 ..... 0111011 @r
+pm2add_w 10000 01 ..... ..... 101 ..... 0111011 @r
+pm2addsu_w 11100 01 ..... ..... 101 ..... 0111011 @r
+pm2addu_w 10100 01 ..... ..... 101 ..... 0111011 @r
+pm2add_wx 10010 01 ..... ..... 101 ..... 0111011 @r
+pm2sub_w 11000 01 ..... ..... 101 ..... 0111011 @r
+pm2sub_wx 11010 01 ..... ..... 101 ..... 0111011 @r
+pm2adda_w 10001 01 ..... ..... 101 ..... 0111011 @r
+pm2addasu_w 11101 01 ..... ..... 101 ..... 0111011 @r
+pm2addau_w 10101 01 ..... ..... 101 ..... 0111011 @r
+pm2adda_wx 10011 01 ..... ..... 101 ..... 0111011 @r
+pm2suba_w 11001 01 ..... ..... 101 ..... 0111011 @r
+pm2suba_wx 11011 01 ..... ..... 101 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index cec18255a1e..cf670b144c3 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -854,3 +854,37 @@ GEN_SIMD_TRANS_ACC_64(pmqracc_w_h00)
GEN_SIMD_TRANS_ACC_64(pmqracc_w_h01)
GEN_SIMD_TRANS_ACC_64(pmqracc_w_h11)
+/* Packed SIMD - Two-Way Multiply and Accumulate Operations */
+GEN_SIMD_TRANS(pmq2add_h)
+GEN_SIMD_TRANS(pmqr2add_h)
+GEN_SIMD_TRANS_ACC(pmq2adda_h)
+GEN_SIMD_TRANS_ACC(pmqr2adda_h)
+GEN_SIMD_TRANS_64(pmq2add_w)
+GEN_SIMD_TRANS_64(pmqr2add_w)
+GEN_SIMD_TRANS_ACC_64(pmq2adda_w)
+GEN_SIMD_TRANS_ACC_64(pmqr2adda_w)
+GEN_SIMD_TRANS(pm2add_h)
+GEN_SIMD_TRANS(pm2addsu_h)
+GEN_SIMD_TRANS(pm2addu_h)
+GEN_SIMD_TRANS(pm2add_hx)
+GEN_SIMD_TRANS(pm2sub_h)
+GEN_SIMD_TRANS(pm2sub_hx)
+GEN_SIMD_TRANS_ACC(pm2adda_h)
+GEN_SIMD_TRANS_ACC(pm2addasu_h)
+GEN_SIMD_TRANS_ACC(pm2addau_h)
+GEN_SIMD_TRANS_ACC(pm2adda_hx)
+GEN_SIMD_TRANS_ACC(pm2suba_h)
+GEN_SIMD_TRANS_ACC(pm2suba_hx)
+GEN_SIMD_TRANS_64(pm2add_w)
+GEN_SIMD_TRANS_64(pm2addsu_w)
+GEN_SIMD_TRANS_64(pm2addu_w)
+GEN_SIMD_TRANS_64(pm2add_wx)
+GEN_SIMD_TRANS_64(pm2sub_w)
+GEN_SIMD_TRANS_64(pm2sub_wx)
+GEN_SIMD_TRANS_ACC_64(pm2adda_w)
+GEN_SIMD_TRANS_ACC_64(pm2addasu_w)
+GEN_SIMD_TRANS_ACC_64(pm2addau_w)
+GEN_SIMD_TRANS_ACC_64(pm2adda_wx)
+GEN_SIMD_TRANS_ACC_64(pm2suba_w)
+GEN_SIMD_TRANS_ACC_64(pm2suba_wx)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index ecdb20bbb58..bad04937b54 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2733,3 +2733,119 @@ GEN_PSIMD_QMUL_ACC_INDEXED(pmqracc_w_h11, uint64_t, int16_t, int16_t,
int32_t, int64_t, int32_t, uint32_t, EXTRACT16,
EXTRACT32, INSERT32, ELEMS_W, 2, 1, 1, 15,
1LL << 14, PSIMD_MUL_S64)
+
+/* Two-Way Multiply and Accumulate Operations */
+
+GEN_PSIMD_Q2ADD(pmq2add_h, target_ulong, int16_t, int32_t, int64_t,
+ uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2, 15, 0,
+ PSIMD_MUL_S32)
+GEN_PSIMD_Q2ADD(pmqr2add_h, target_ulong, int16_t, int32_t, int64_t,
+ uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2, 15, 1LL << 14,
+ PSIMD_MUL_S32)
+GEN_PSIMD_Q2ADDA(pmq2adda_h, target_ulong, int16_t, int32_t, int32_t,
+ int64_t, uint32_t, EXTRACT16, EXTRACT32, INSERT32,
+ ELEMS_W, 2, 15, 0, PSIMD_MUL_S32)
+GEN_PSIMD_Q2ADDA(pmqr2adda_h, target_ulong, int16_t, int32_t, int32_t,
+ int64_t, uint32_t, EXTRACT16, EXTRACT32, INSERT32,
+ ELEMS_W, 2, 15, 1LL << 14, PSIMD_MUL_S32)
+
+GEN_PSIMD_Q2ADD(pmq2add_w, uint64_t, int32_t, int64_t, int64_t,
+ uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0, 31, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_Q2ADD(pmqr2add_w, uint64_t, int32_t, int64_t, int64_t,
+ uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0, 31, 1LL << 30,
+ PSIMD_MUL_S64)
+GEN_PSIMD_Q2ADDA(pmq2adda_w, uint64_t, int32_t, int64_t, int64_t,
+ int64_t, uint64_t, EXTRACT32, EXTRACT64, INSERT64,
+ ELEMS_D, 0, 31, 0, PSIMD_MUL_S64)
+GEN_PSIMD_Q2ADDA(pmqr2adda_w, uint64_t, int32_t, int64_t, int64_t,
+ int64_t, uint64_t, EXTRACT32, EXTRACT64, INSERT64,
+ ELEMS_D, 0, 31, 1LL << 30, PSIMD_MUL_S64)
+
+GEN_PSIMD_2WAY_MUL(pm2add_h, target_ulong, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2,
+ 0, 1, 0, 1, PSIMD_MUL_S32, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2addsu_h, target_ulong, int16_t, uint16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2,
+ 0, 1, 0, 1, PSIMD_MUL_SU32, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2addu_h, target_ulong, uint16_t, uint16_t,
+ uint32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2,
+ 0, 1, 0, 1, PSIMD_MUL_U32, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2add_hx, target_ulong, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2,
+ 0, 1, 1, 0, PSIMD_MUL_S32, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2sub_h, target_ulong, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2,
+ 0, 1, 0, 1, PSIMD_MUL_S32, PSIMD_COMB_SUB)
+GEN_PSIMD_2WAY_MUL(pm2sub_hx, target_ulong, int16_t, int16_t,
+ int32_t, uint32_t, EXTRACT16, INSERT32, ELEMS_W, 2,
+ 0, 1, 1, 0, PSIMD_MUL_S32, PSIMD_COMB_SUB)
+
+GEN_PSIMD_2WAY_MUL_ACC(pm2adda_h, target_ulong, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, 0, 1, PSIMD_MUL_S32,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2addasu_h, target_ulong, int16_t, uint16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, 0, 1, PSIMD_MUL_SU32,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2addau_h, target_ulong, uint16_t, uint16_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, 0, 1, PSIMD_MUL_U32,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2adda_hx, target_ulong, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, 1, 0, PSIMD_MUL_S32,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2suba_h, target_ulong, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, 0, 1, PSIMD_MUL_S32,
+ PSIMD_COMB_SUB)
+GEN_PSIMD_2WAY_MUL_ACC(pm2suba_hx, target_ulong, int16_t, int16_t,
+ int32_t, int32_t, uint32_t, EXTRACT16, EXTRACT32,
+ INSERT32, ELEMS_W, 2, 0, 1, 1, 0, PSIMD_MUL_S32,
+ PSIMD_COMB_SUB)
+
+GEN_PSIMD_2WAY_MUL(pm2add_w, uint64_t, int32_t, int32_t,
+ int64_t, uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0,
+ 0, 1, 0, 1, PSIMD_MUL_S64, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2addsu_w, uint64_t, int32_t, uint32_t,
+ int64_t, uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0,
+ 0, 1, 0, 1, PSIMD_MUL_SU64, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2addu_w, uint64_t, uint32_t, uint32_t,
+ uint64_t, uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0,
+ 0, 1, 0, 1, PSIMD_MUL_U64, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2add_wx, uint64_t, int32_t, int32_t,
+ int64_t, uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0,
+ 0, 1, 1, 0, PSIMD_MUL_S64, PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL(pm2sub_w, uint64_t, int32_t, int32_t,
+ int64_t, uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0,
+ 0, 1, 0, 1, PSIMD_MUL_S64, PSIMD_COMB_SUB)
+GEN_PSIMD_2WAY_MUL(pm2sub_wx, uint64_t, int32_t, int32_t,
+ int64_t, uint64_t, EXTRACT32, INSERT64, ELEMS_D, 0,
+ 0, 1, 1, 0, PSIMD_MUL_S64, PSIMD_COMB_SUB)
+
+GEN_PSIMD_2WAY_MUL_ACC(pm2adda_w, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, 0, 1, PSIMD_MUL_S64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2addasu_w, uint64_t, int32_t, uint32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, 0, 1, PSIMD_MUL_SU64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2addau_w, uint64_t, uint32_t, uint32_t,
+ uint64_t, uint64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, 0, 1, PSIMD_MUL_U64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2adda_wx, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, 1, 0, PSIMD_MUL_S64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_2WAY_MUL_ACC(pm2suba_w, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, 0, 1, PSIMD_MUL_S64,
+ PSIMD_COMB_SUB)
+GEN_PSIMD_2WAY_MUL_ACC(pm2suba_wx, uint64_t, int32_t, int32_t,
+ int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
+ INSERT64, ELEMS_D, 0, 0, 1, 1, 0, PSIMD_MUL_S64,
+ PSIMD_COMB_SUB)
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 15/18] target/riscv: Add packed SIMD four-way MAC instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (13 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 14/18] target/riscv: Add packed SIMD two-way " Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 16/18] target/riscv: Add packed SIMD load-replicate instructions Molly Chen
` (4 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 14 +++++++
target/riscv/insn32.decode | 14 +++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 14 +++++++
target/riscv/tcg/psimd_helper.c | 41 +++++++++++++++++++++
4 files changed, 83 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index b0743d19177..fb95a9f71b5 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1742,3 +1742,17 @@ DEF_HELPER_4(pm2addau_w, i64, env, i64, i64, i64)
DEF_HELPER_4(pm2adda_wx, i64, env, i64, i64, i64)
DEF_HELPER_4(pm2suba_w, i64, env, i64, i64, i64)
DEF_HELPER_4(pm2suba_wx, i64, env, i64, i64, i64)
+
+/* Packed SIMD - Four-Way Multiply and Accumulate Operations */
+DEF_HELPER_3(pm4add_b, tl, env, tl, tl)
+DEF_HELPER_3(pm4addsu_b, tl, env, tl, tl)
+DEF_HELPER_3(pm4addu_b, tl, env, tl, tl)
+DEF_HELPER_4(pm4adda_b, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm4addasu_b, tl, env, tl, tl, tl)
+DEF_HELPER_4(pm4addau_b, tl, env, tl, tl, tl)
+DEF_HELPER_3(pm4add_h, i64, env, i64, i64)
+DEF_HELPER_3(pm4addsu_h, i64, env, i64, i64)
+DEF_HELPER_3(pm4addu_h, i64, env, i64, i64)
+DEF_HELPER_4(pm4adda_h, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm4addasu_h, i64, env, i64, i64, i64)
+DEF_HELPER_4(pm4addau_h, i64, env, i64, i64, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 1c8bdde25c2..8720fedb592 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1600,3 +1600,17 @@ pm2addau_w 10101 01 ..... ..... 101 ..... 0111011 @r
pm2adda_wx 10011 01 ..... ..... 101 ..... 0111011 @r
pm2suba_w 11001 01 ..... ..... 101 ..... 0111011 @r
pm2suba_wx 11011 01 ..... ..... 101 ..... 0111011 @r
+
+# Packed SIMD - Four-Way Multiply and Accumulate Operations
+pm4add_b 10000 10 ..... ..... 101 ..... 0111011 @r
+pm4addsu_b 11100 10 ..... ..... 101 ..... 0111011 @r
+pm4addu_b 10100 10 ..... ..... 101 ..... 0111011 @r
+pm4adda_b 10001 10 ..... ..... 101 ..... 0111011 @r
+pm4addasu_b 11101 10 ..... ..... 101 ..... 0111011 @r
+pm4addau_b 10101 10 ..... ..... 101 ..... 0111011 @r
+pm4add_h 10000 11 ..... ..... 101 ..... 0111011 @r
+pm4addsu_h 11100 11 ..... ..... 101 ..... 0111011 @r
+pm4addu_h 10100 11 ..... ..... 101 ..... 0111011 @r
+pm4adda_h 10001 11 ..... ..... 101 ..... 0111011 @r
+pm4addasu_h 11101 11 ..... ..... 101 ..... 0111011 @r
+pm4addau_h 10101 11 ..... ..... 101 ..... 0111011 @r
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index cf670b144c3..6c344a66dc8 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -888,3 +888,17 @@ GEN_SIMD_TRANS_ACC_64(pm2adda_wx)
GEN_SIMD_TRANS_ACC_64(pm2suba_w)
GEN_SIMD_TRANS_ACC_64(pm2suba_wx)
+/* Packed SIMD - Four-Way Multiply and Accumulate Operations */
+GEN_SIMD_TRANS(pm4add_b)
+GEN_SIMD_TRANS(pm4addsu_b)
+GEN_SIMD_TRANS(pm4addu_b)
+GEN_SIMD_TRANS_ACC(pm4adda_b)
+GEN_SIMD_TRANS_ACC(pm4addasu_b)
+GEN_SIMD_TRANS_ACC(pm4addau_b)
+GEN_SIMD_TRANS_64(pm4add_h)
+GEN_SIMD_TRANS_64(pm4addsu_h)
+GEN_SIMD_TRANS_64(pm4addu_h)
+GEN_SIMD_TRANS_ACC_64(pm4adda_h)
+GEN_SIMD_TRANS_ACC_64(pm4addasu_h)
+GEN_SIMD_TRANS_ACC_64(pm4addau_h)
+
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index bad04937b54..e7c7e554938 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2849,3 +2849,44 @@ GEN_PSIMD_2WAY_MUL_ACC(pm2suba_wx, uint64_t, int32_t, int32_t,
int64_t, int64_t, uint64_t, EXTRACT32, EXTRACT64,
INSERT64, ELEMS_D, 0, 0, 1, 1, 0, PSIMD_MUL_S64,
PSIMD_COMB_SUB)
+
+
+/* Four-Way Multiply and Accumulate Operations */
+
+GEN_PSIMD_4WAY_MUL(pm4add_b, target_ulong, int8_t, int8_t,
+ int32_t, uint32_t, EXTRACT8, INSERT32, ELEMS_W, 4,
+ PSIMD_MUL_S32)
+GEN_PSIMD_4WAY_MUL(pm4addsu_b, target_ulong, int8_t, uint8_t,
+ int32_t, uint32_t, EXTRACT8, INSERT32, ELEMS_W, 4,
+ PSIMD_MUL_SU32)
+GEN_PSIMD_4WAY_MUL(pm4addu_b, target_ulong, uint8_t, uint8_t,
+ uint32_t, uint32_t, EXTRACT8, INSERT32, ELEMS_W, 4,
+ PSIMD_MUL_U32)
+GEN_PSIMD_4WAY_MUL_ACC(pm4adda_b, target_ulong, int8_t, int8_t,
+ int32_t, int32_t, uint32_t, EXTRACT8, EXTRACT32,
+ INSERT32, ELEMS_W, 4, PSIMD_MUL_S32)
+GEN_PSIMD_4WAY_MUL_ACC(pm4addasu_b, target_ulong, int8_t, uint8_t,
+ int32_t, int32_t, uint32_t, EXTRACT8, EXTRACT32,
+ INSERT32, ELEMS_W, 4, PSIMD_MUL_SU32)
+GEN_PSIMD_4WAY_MUL_ACC(pm4addau_b, target_ulong, uint8_t, uint8_t,
+ uint32_t, uint32_t, uint32_t, EXTRACT8, EXTRACT32,
+ INSERT32, ELEMS_W, 4, PSIMD_MUL_U32)
+
+GEN_PSIMD_4WAY_MUL(pm4add_h, uint64_t, int16_t, int16_t,
+ int64_t, uint64_t, EXTRACT16, INSERT64, ELEMS_D, 0,
+ PSIMD_MUL_S64)
+GEN_PSIMD_4WAY_MUL(pm4addsu_h, uint64_t, int16_t, uint16_t,
+ int64_t, uint64_t, EXTRACT16, INSERT64, ELEMS_D, 0,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_4WAY_MUL(pm4addu_h, uint64_t, uint16_t, uint16_t,
+ uint64_t, uint64_t, EXTRACT16, INSERT64, ELEMS_D, 0,
+ PSIMD_MUL_U64)
+GEN_PSIMD_4WAY_MUL_ACC(pm4adda_h, uint64_t, int16_t, int16_t,
+ int64_t, int64_t, uint64_t, EXTRACT16, EXTRACT64,
+ INSERT64, ELEMS_D, 0, PSIMD_MUL_S64)
+GEN_PSIMD_4WAY_MUL_ACC(pm4addasu_h, uint64_t, int16_t, uint16_t,
+ int64_t, int64_t, uint64_t, EXTRACT16, EXTRACT64,
+ INSERT64, ELEMS_D, 0, PSIMD_MUL_SU64)
+GEN_PSIMD_4WAY_MUL_ACC(pm4addau_h, uint64_t, uint16_t, uint16_t,
+ uint64_t, uint64_t, uint64_t, EXTRACT16, EXTRACT64,
+ INSERT64, ELEMS_D, 0, PSIMD_MUL_U64)
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 16/18] target/riscv: Add packed SIMD load-replicate instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (14 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 15/18] target/riscv: Add packed SIMD four-way " Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 17/18] target/riscv: Add packed SIMD RV32 only instructions Molly Chen
` (3 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/insn32.decode | 16 ++++++++++++++
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 24 +++++++++++++++++++++
target/riscv/tcg/translate.c | 2 ++
3 files changed, 42 insertions(+)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 8720fedb592..403e17e439d 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -44,6 +44,10 @@
%imm_p_ui16 20:4
%imm_p_ui32 20:5
%imm_p_ui64 20:6
+%imm_p_l1 16:8
+%imm_p_l2 15:s1 16:9
+%imm_p_l3 15:s9 24:1 !function=ex_shift_6
+%imm_p_l4 15:s9 24:1 !function=ex_shift_22
# Argument sets:
&empty
@@ -53,6 +57,7 @@
&r rd rs1 rs2
&r2 rd rs1
&r2_s rs1 rs2
+&p_l imm rd
&s imm rs1 rs2
&u imm rd
&shift shamt rs1 rd
@@ -114,6 +119,10 @@
@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd
@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd
@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd
+@p_l1 ........ ........ .... ..... ....... &p_l imm=%imm_p_l1 %rd
+@p_l2 ....... .......... ... ..... ....... &p_l imm=%imm_p_l2 %rd
+@p_l3 ....... .......... ... ..... ....... &p_l imm=%imm_p_l3 %rd
+@p_l4 ....... .......... ... ..... ....... &p_l imm=%imm_p_l4 %rd
# Formats 64:
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
@@ -1614,3 +1623,10 @@ pm4addu_h 10100 11 ..... ..... 101 ..... 0111011 @r
pm4adda_h 10001 11 ..... ..... 101 ..... 0111011 @r
pm4addasu_h 11101 11 ..... ..... 101 ..... 0111011 @r
pm4addau_h 10101 11 ..... ..... 101 ..... 0111011 @r
+
+# Packed SIMD - Load and Replicate instructions
+pli_b 10110100 ........ 0010 ..... 0011011 @p_l1
+pli_h 1011000 .......... 010 ..... 0011011 @p_l2
+plui_h 1111000 .......... 010 ..... 0011011 @p_l3
+pli_w 1011001 ..... ..... 010 ..... 0011011 @p_l2
+plui_w 1111001 ..... ..... 010 ..... 0011011 @p_l4
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 6c344a66dc8..4d5fc230d2e 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -902,3 +902,27 @@ GEN_SIMD_TRANS_ACC_64(pm4adda_h)
GEN_SIMD_TRANS_ACC_64(pm4addasu_h)
GEN_SIMD_TRANS_ACC_64(pm4addau_h)
+#define GEN_PLI(NAME, PRE_REQ, IMM_TYPE, LIMIT, SHIFT, ADDEND) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ PRE_REQ \
+ REQUIRE_RVP(ctx); \
+ int i = 1; \
+ IMM_TYPE imm = a->imm; \
+ while (i < (LIMIT)) { \
+ imm = (imm << (SHIFT)) + (ADDEND); \
+ i++; \
+ } \
+ gen_set_gpri(ctx, a->rd, imm); \
+ return true; \
+}
+
+GEN_PLI(pli_b, , target_long, TARGET_LONG_SIZE, 8, a->imm)
+GEN_PLI(pli_h, , target_long, TARGET_LONG_SIZE / 2, 16,
+ a->imm & 0xFFFF)
+GEN_PLI(plui_h, , target_long, TARGET_LONG_SIZE / 2, 16,
+ a->imm & 0xFFFF)
+GEN_PLI(pli_w, REQUIRE_64BIT(ctx); , int64_t, TARGET_LONG_SIZE / 4, 32,
+ a->imm & 0xFFFFFFFF)
+GEN_PLI(plui_w, REQUIRE_64BIT(ctx); , int64_t, TARGET_LONG_SIZE / 4, 32,
+ a->imm & 0xFFFFFFFF)
diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
index 0df9d4190f1..668ec3120af 100644
--- a/target/riscv/tcg/translate.c
+++ b/target/riscv/tcg/translate.c
@@ -790,7 +790,9 @@ EX_SH(1)
EX_SH(2)
EX_SH(3)
EX_SH(4)
+EX_SH(6)
EX_SH(12)
+EX_SH(22)
#define REQUIRE_EXT(ctx, ext) do { \
if (!has_ext(ctx, ext)) { \
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 17/18] target/riscv: Add packed SIMD RV32 only instructions
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (15 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 16/18] target/riscv: Add packed SIMD load-replicate instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-07-17 10:07 ` [PATCH v2 18/18] target/riscv: Remove Zbkb dependency from P extension to align with the spec Molly Chen
` (2 subsequent siblings)
19 siblings, 0 replies; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/helper.h | 131 ++++++
target/riscv/insn32.decode | 285 +++++++++++-
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 461 ++++++++++++++++++++
target/riscv/tcg/psimd_helper.c | 273 ++++++++++++
4 files changed, 1149 insertions(+), 1 deletion(-)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index fb95a9f71b5..78e6f17be82 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -1756,3 +1756,134 @@ DEF_HELPER_3(pm4addu_h, i64, env, i64, i64)
DEF_HELPER_4(pm4adda_h, i64, env, i64, i64, i64)
DEF_HELPER_4(pm4addasu_h, i64, env, i64, i64, i64)
DEF_HELPER_4(pm4addau_h, i64, env, i64, i64, i64)
+
+/* Packed SIMD - Double-Width Operations (RV32 only, register pairs) */
+DEF_HELPER_3(pwadd_b, i64, env, i32, i32)
+DEF_HELPER_4(pwadda_b, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwaddu_b, i64, env, i32, i32)
+DEF_HELPER_4(pwaddau_b, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwsub_b, i64, env, i32, i32)
+DEF_HELPER_4(pwsuba_b, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwsubu_b, i64, env, i32, i32)
+DEF_HELPER_4(pwsubau_b, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwslli_b, i64, env, i32, i32)
+DEF_HELPER_3(pwsll_bs, i64, env, i32, i32)
+DEF_HELPER_3(pwslai_b, i64, env, i32, i32)
+DEF_HELPER_3(pwsla_bs, i64, env, i32, i32)
+
+DEF_HELPER_3(pwadd_h, i64, env, i32, i32)
+DEF_HELPER_4(pwadda_h, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwaddu_h, i64, env, i32, i32)
+DEF_HELPER_4(pwaddau_h, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwsub_h, i64, env, i32, i32)
+DEF_HELPER_4(pwsuba_h, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwsubu_h, i64, env, i32, i32)
+DEF_HELPER_4(pwsubau_h, i64, env, i32, i32, i64)
+DEF_HELPER_3(pwslli_h, i64, env, i32, i32)
+DEF_HELPER_3(pwsll_hs, i64, env, i32, i32)
+DEF_HELPER_3(pwslai_h, i64, env, i32, i32)
+DEF_HELPER_3(pwsla_hs, i64, env, i32, i32)
+
+DEF_HELPER_3(wadd, i64, env, i32, i32)
+DEF_HELPER_4(wadda, i64, env, i32, i32, i64)
+DEF_HELPER_3(waddu, i64, env, i32, i32)
+DEF_HELPER_4(waddau, i64, env, i32, i32, i64)
+DEF_HELPER_3(wsub, i64, env, i32, i32)
+DEF_HELPER_4(wsuba, i64, env, i32, i32, i64)
+DEF_HELPER_3(wsubu, i64, env, i32, i32)
+DEF_HELPER_4(wsubau, i64, env, i32, i32, i64)
+DEF_HELPER_3(wslli, i64, env, i32, i32)
+DEF_HELPER_3(wsll, i64, env, i32, i32)
+DEF_HELPER_3(wslai, i64, env, i32, i32)
+DEF_HELPER_3(wsla, i64, env, i32, i32)
+
+DEF_HELPER_3(wzip8p, i64, env, i32, i32)
+DEF_HELPER_3(wzip16p, i64, env, i32, i32)
+
+DEF_HELPER_4(predsum_dbs, i32, env, i32, i32, i32)
+DEF_HELPER_4(predsumu_dbs, i32, env, i32, i32, i32)
+DEF_HELPER_4(predsum_dhs, i32, env, i32, i32, i32)
+DEF_HELPER_4(predsumu_dhs, i32, env, i32, i32, i32)
+
+DEF_HELPER_3(pnsrli_b, i32, env, i64, i32)
+DEF_HELPER_3(pnsrai_b, i32, env, i64, i32)
+DEF_HELPER_3(pnsrari_b, i32, env, i64, i32)
+DEF_HELPER_3(pnclipi_b, i32, env, i64, i32)
+DEF_HELPER_3(pnclipri_b, i32, env, i64, i32)
+DEF_HELPER_3(pnclipiu_b, i32, env, i64, i32)
+DEF_HELPER_3(pnclipriu_b, i32, env, i64, i32)
+DEF_HELPER_3(pnsrl_bs, i32, env, i64, i32)
+DEF_HELPER_3(pnsra_bs, i32, env, i64, i32)
+DEF_HELPER_3(pnsrar_bs, i32, env, i64, i32)
+DEF_HELPER_3(pnclip_bs, i32, env, i64, i32)
+DEF_HELPER_3(pnclipr_bs, i32, env, i64, i32)
+DEF_HELPER_3(pnclipu_bs, i32, env, i64, i32)
+DEF_HELPER_3(pnclipru_bs, i32, env, i64, i32)
+
+DEF_HELPER_3(pnsrli_h, i32, env, i64, i32)
+DEF_HELPER_3(pnsrai_h, i32, env, i64, i32)
+DEF_HELPER_3(pnsrari_h, i32, env, i64, i32)
+DEF_HELPER_3(pnclipi_h, i32, env, i64, i32)
+DEF_HELPER_3(pnclipri_h, i32, env, i64, i32)
+DEF_HELPER_3(pnclipiu_h, i32, env, i64, i32)
+DEF_HELPER_3(pnclipriu_h, i32, env, i64, i32)
+DEF_HELPER_3(pnsrl_hs, i32, env, i64, i32)
+DEF_HELPER_3(pnsra_hs, i32, env, i64, i32)
+DEF_HELPER_3(pnsrar_hs, i32, env, i64, i32)
+DEF_HELPER_3(pnclip_hs, i32, env, i64, i32)
+DEF_HELPER_3(pnclipr_hs, i32, env, i64, i32)
+DEF_HELPER_3(pnclipu_hs, i32, env, i64, i32)
+DEF_HELPER_3(pnclipru_hs, i32, env, i64, i32)
+
+DEF_HELPER_3(nsrli, i32, env, i64, i32)
+DEF_HELPER_3(nsrai, i32, env, i64, i32)
+DEF_HELPER_3(nsrari, i32, env, i64, i32)
+DEF_HELPER_3(nclipi, i32, env, i64, i32)
+DEF_HELPER_3(nclipri, i32, env, i64, i32)
+DEF_HELPER_3(nclipiu, i32, env, i64, i32)
+DEF_HELPER_3(nclipriu, i32, env, i64, i32)
+DEF_HELPER_3(nsrl, i32, env, i64, i32)
+DEF_HELPER_3(nsra, i32, env, i64, i32)
+DEF_HELPER_3(nsrar, i32, env, i64, i32)
+DEF_HELPER_3(nclip, i32, env, i64, i32)
+DEF_HELPER_3(nclipr, i32, env, i64, i32)
+DEF_HELPER_3(nclipu, i32, env, i64, i32)
+DEF_HELPER_3(nclipru, i32, env, i64, i32)
+
+DEF_HELPER_4(pmqwacc_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pmqrwacc_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(mqwacc, i64, env, i32, i32, i64)
+DEF_HELPER_4(mqrwacc, i64, env, i32, i32, i64)
+
+DEF_HELPER_3(pwmul_b, i64, env, i32, i32)
+DEF_HELPER_3(pwmulsu_b, i64, env, i32, i32)
+DEF_HELPER_3(pwmulu_b, i64, env, i32, i32)
+DEF_HELPER_3(pwmul_h, i64, env, i32, i32)
+DEF_HELPER_3(pwmulsu_h, i64, env, i32, i32)
+DEF_HELPER_3(pwmulu_h, i64, env, i32, i32)
+
+DEF_HELPER_4(pwmacc_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pwmaccsu_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pwmaccu_h, i64, env, i32, i32, i64)
+
+DEF_HELPER_3(wmul, i64, env, i32, i32)
+DEF_HELPER_3(wmulsu, i64, env, i32, i32)
+DEF_HELPER_3(wmulu, i64, env, i32, i32)
+
+DEF_HELPER_4(wmacc, i64, env, i32, i32, i64)
+DEF_HELPER_4(wmaccsu, i64, env, i32, i32, i64)
+DEF_HELPER_4(wmaccu, i64, env, i32, i32, i64)
+
+DEF_HELPER_3(pm2wadd_h, i64, env, i32, i32)
+DEF_HELPER_3(pm2waddsu_h, i64, env, i32, i32)
+DEF_HELPER_3(pm2waddu_h, i64, env, i32, i32)
+DEF_HELPER_3(pm2wadd_hx, i64, env, i32, i32)
+DEF_HELPER_4(pm2wadda_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pm2waddasu_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pm2waddau_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pm2wadda_hx, i64, env, i32, i32, i64)
+
+DEF_HELPER_3(pm2wsub_h, i64, env, i32, i32)
+DEF_HELPER_3(pm2wsub_hx, i64, env, i32, i32)
+DEF_HELPER_4(pm2wsuba_h, i64, env, i32, i32, i64)
+DEF_HELPER_4(pm2wsuba_hx, i64, env, i32, i32, i64)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 403e17e439d..a477b812fd6 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -23,6 +23,9 @@
%rd 7:5
%sh5 20:5
%sh6 20:6
+%rs2_p 21:4
+%rs1_p 16:4
+%rd_p 8:4
%sh7 20:7
%csr 20:12
@@ -57,7 +60,6 @@
&r rd rs1 rs2
&r2 rd rs1
&r2_s rs1 rs2
-&p_l imm rd
&s imm rs1 rs2
&u imm rd
&shift shamt rs1 rd
@@ -69,6 +71,7 @@
&k_aes shamt rs2 rs1 rd
&mop5 imm rd rs1
&mop3 imm rd rs1 rs2
+&p_l imm rd
&p_ui imm rs1 rd
# Formats 32:
@@ -102,6 +105,11 @@
@r2_zimm11 . zimm:11 ..... ... ..... ....... %rs1 %rd
@r2_zimm10 .. zimm:10 ..... ... ..... ....... %rs1 %rd
@r2_s ....... ..... ..... ... ..... ....... %rs2 %rs1
+@r_p_1 ....... ..... ..... ... ..... ....... &r %rs2 %rs1 rd=%rd_p
+@r_p_2 ....... ..... ..... ... ..... ....... &r rs2=%rs2_p rs1=%rs1_p rd=%rd_p
+@r_p_3 ....... ..... ..... ... ..... ....... &r %rs2 rs1=%rs1_p rd=%rd_p
+@r_p_4 ....... ..... ..... ... ..... ....... &r %rs2 rs1=%rs1_p %rd
+@r2_p ....... ..... ..... ... ..... ....... &r2 rs1=%rs1_p rd=%rd_p
@hfence_gvma ....... ..... ..... ... ..... ....... %rs2 %rs1
@hfence_vvma ....... ..... ..... ... ..... ....... %rs2 %rs1
@@ -123,6 +131,18 @@
@p_l2 ....... .......... ... ..... ....... &p_l imm=%imm_p_l2 %rd
@p_l3 ....... .......... ... ..... ....... &p_l imm=%imm_p_l3 %rd
@p_l4 ....... .......... ... ..... ....... &p_l imm=%imm_p_l4 %rd
+@p_l1_p ........ ........ .... ..... ....... &p_l imm=%imm_p_l1 rd=%rd_p
+@p_l2_p ........ ........ .... ..... ....... &p_l imm=%imm_p_l2 rd=%rd_p
+@p_l3_p ....... .......... ... ..... ....... &p_l imm=%imm_p_l3 rd=%rd_p
+@p_ui8_p ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui8 rs1=%rs1_p rd=%rd_p
+@p_ui16_p ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui16 %rs1 rd=%rd_p
+@p_ui16_p_2 ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui16 rs1=%rs1_p rd=%rd_p
+@p_ui16_p_3 ..... .... ... .... .... ..... ....... &p_ui imm=%imm_p_ui16 rs1=%rs1_p %rd
+@p_ui32_p ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui32 %rs1 rd=%rd_p
+@p_ui32_p_2 ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui32 rs1=%rs1_p rd=%rd_p
+@p_ui32_p_3 ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui32 rs1=%rs1_p %rd
+@p_ui64_p ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui64 %rs1 rd=%rd_p
+@p_ui64_p_2 ..... .... ... ..... ... ..... ....... &p_ui imm=%imm_p_ui64 rs1=%rs1_p %rd
# Formats 64:
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
@@ -1630,3 +1650,266 @@ pli_h 1011000 .......... 010 ..... 0011011 @p_l2
plui_h 1111000 .......... 010 ..... 0011011 @p_l3
pli_w 1011001 ..... ..... 010 ..... 0011011 @p_l2
plui_w 1111001 ..... ..... 010 ..... 0011011 @p_l4
+
+# Packed SIMD - Double-Width Operations (RV32 only, register pairs)
+# register-pair destination
+pwadd_b 0000010 ..... ..... 010 .... 10011011 @r_p_1
+pwadda_b 0000110 ..... ..... 010 .... 10011011 @r_p_1
+pwaddu_b 0001010 ..... ..... 010 .... 10011011 @r_p_1
+pwaddau_b 0001110 ..... ..... 010 .... 10011011 @r_p_1
+pwsub_b 0100010 ..... ..... 010 .... 10011011 @r_p_1
+pwsuba_b 0100110 ..... ..... 010 .... 10011011 @r_p_1
+pwsubu_b 0101010 ..... ..... 010 .... 10011011 @r_p_1
+pwsubau_b 0101110 ..... ..... 010 .... 10011011 @r_p_1
+pwslli_b 00000 001.... ..... 010 .... 00011011 @p_ui16_p
+pwsll_bs 0000100 ..... ..... 010 .... 00011011 @r_p_1
+pwslai_b 01000 001.... ..... 010 .... 00011011 @p_ui16_p
+pwsla_bs 0100100 ..... ..... 010 .... 00011011 @r_p_1
+
+pwadd_h 0000000 ..... ..... 010 .... 10011011 @r_p_1
+pwadda_h 0000100 ..... ..... 010 .... 10011011 @r_p_1
+pwaddu_h 0001000 ..... ..... 010 .... 10011011 @r_p_1
+pwaddau_h 0001100 ..... ..... 010 .... 10011011 @r_p_1
+pwsub_h 0100000 ..... ..... 010 .... 10011011 @r_p_1
+pwsuba_h 0100100 ..... ..... 010 .... 10011011 @r_p_1
+pwsubu_h 0101000 ..... ..... 010 .... 10011011 @r_p_1
+pwsubau_h 0101100 ..... ..... 010 .... 10011011 @r_p_1
+pwslli_h 00000 01..... ..... 010 .... 00011011 @p_ui32_p
+pwsll_hs 0000101 ..... ..... 010 .... 00011011 @r_p_1
+pwslai_h 01000 01..... ..... 010 .... 00011011 @p_ui32_p
+pwsla_hs 0100101 ..... ..... 010 .... 00011011 @r_p_1
+
+wadd 0000001 ..... ..... 010 .... 10011011 @r_p_1
+wadda 0000101 ..... ..... 010 .... 10011011 @r_p_1
+waddu 0001001 ..... ..... 010 .... 10011011 @r_p_1
+waddau 0001101 ..... ..... 010 .... 10011011 @r_p_1
+wsub 0100001 ..... ..... 010 .... 10011011 @r_p_1
+wsuba 0100101 ..... ..... 010 .... 10011011 @r_p_1
+wsubu 0101001 ..... ..... 010 .... 10011011 @r_p_1
+wsubau 0101101 ..... ..... 010 .... 10011011 @r_p_1
+wslli 00000 1...... ..... 010 .... 00011011 @p_ui64_p
+wsll 0000111 ..... ..... 010 .... 00011011 @r_p_1
+wslai 01000 1...... ..... 010 .... 00011011 @p_ui64_p
+wsla 0100111 ..... ..... 010 .... 00011011 @r_p_1
+
+wzip8p 0111100 ..... ..... 010 .... 00011011 @r_p_1
+wzip16p 0111101 ..... ..... 010 .... 00011011 @r_p_1
+
+#register-pair operands
+pli_db 00110100 ........ 0010 .... 00011011 @p_l1_p
+padd_db 1000010 .... 0 .... 0110 .... 00011011 @r_p_2
+psub_db 1100010 .... 0 .... 0110 .... 00011011 @r_p_2
+psadd_db 1001010 .... 0 .... 0110 .... 00011011 @r_p_2
+psaddu_db 1011010 .... 0 .... 0110 .... 00011011 @r_p_2
+pssub_db 1101010 .... 0 .... 0110 .... 00011011 @r_p_2
+pssubu_db 1111010 .... 0 .... 0110 .... 00011011 @r_p_2
+paadd_db 1001110 .... 0 .... 0110 .... 00011011 @r_p_2
+paaddu_db 1011110 .... 0 .... 0110 .... 00011011 @r_p_2
+pasub_db 1101110 .... 0 .... 0110 .... 00011011 @r_p_2
+pasubu_db 1111110 .... 0 .... 0110 .... 00011011 @r_p_2
+pabd_db 1100110 .... 0 .... 0110 .... 00011011 @r_p_2
+pabdu_db 1110110 .... 0 .... 0110 .... 00011011 @r_p_2
+psabs_db 0110010 00111 .... 0110 .... 00011011 @r2_p
+pli_dh 0011000 .......... 010 .... 00011011 @p_l2_p
+plui_dh 0111000 .......... 010 .... 00011011 @p_l3_p
+padd_dh 1000000 .... 0 .... 0110 .... 00011011 @r_p_2
+psub_dh 1100000 .... 0 .... 0110 .... 00011011 @r_p_2
+psadd_dh 1001000 .... 0 .... 0110 .... 00011011 @r_p_2
+psaddu_dh 1011000 .... 0 .... 0110 .... 00011011 @r_p_2
+pssub_dh 1101000 .... 0 .... 0110 .... 00011011 @r_p_2
+pssubu_dh 1111000 .... 0 .... 0110 .... 00011011 @r_p_2
+paadd_dh 1001100 .... 0 .... 0110 .... 00011011 @r_p_2
+paaddu_dh 1011100 .... 0 .... 0110 .... 00011011 @r_p_2
+pasub_dh 1101100 .... 0 .... 0110 .... 00011011 @r_p_2
+pasubu_dh 1111100 .... 0 .... 0110 .... 00011011 @r_p_2
+psh1add_dh 1010000 .... 1 .... 0110 .... 00011011 @r_p_2
+pssh1sadd_dh 1011000 .... 1 .... 0110 .... 00011011 @r_p_2
+pas_dhx 1000000 .... 1 .... 1110 .... 00011011 @r_p_2
+psa_dhx 1000010 .... 1 .... 1110 .... 00011011 @r_p_2
+psas_dhx 1001000 .... 1 .... 1110 .... 00011011 @r_p_2
+pssa_dhx 1001010 .... 1 .... 1110 .... 00011011 @r_p_2
+paas_dhx 1001100 .... 1 .... 1110 .... 00011011 @r_p_2
+pasa_dhx 1001110 .... 1 .... 1110 .... 00011011 @r_p_2
+pabd_dh 1100100 .... 0 .... 0110 .... 00011011 @r_p_2
+pabdu_dh 1110100 .... 0 .... 0110 .... 00011011 @r_p_2
+psabs_dh 0110000 00111 .... 0110 .... 00011011 @r2_p
+padd_dw 1000001 .... 0 .... 0110 .... 00011011 @r_p_2
+psub_dw 1100001 .... 0 .... 0110 .... 00011011 @r_p_2
+psadd_dw 1001001 .... 0 .... 0110 .... 00011011 @r_p_2
+psaddu_dw 1011001 .... 0 .... 0110 .... 00011011 @r_p_2
+pssub_dw 1101001 .... 0 .... 0110 .... 00011011 @r_p_2
+pssubu_dw 1111001 .... 0 .... 0110 .... 00011011 @r_p_2
+paadd_dw 1001101 .... 0 .... 0110 .... 00011011 @r_p_2
+paaddu_dw 1011101 .... 0 .... 0110 .... 00011011 @r_p_2
+pasub_dw 1101101 .... 0 .... 0110 .... 00011011 @r_p_2
+pasubu_dw 1111101 .... 0 .... 0110 .... 00011011 @r_p_2
+psh1add_dw 1010001 .... 1 .... 0110 .... 00011011 @r_p_2
+pssh1sadd_dw 1011001 .... 1 .... 0110 .... 00011011 @r_p_2
+addd_p 1000011 .... 0 .... 0110 .... 00011011 @r_p_2
+subd_p 1100011 .... 0 .... 0110 .... 00011011 @r_p_2
+
+# register-pair first source only
+predsum_dbs 0001110 ..... .... 0100 ..... 0011011 @r_p_4
+predsumu_dbs 0011110 ..... .... 0100 ..... 0011011 @r_p_4
+predsum_dhs 0001100 ..... .... 0100 ..... 0011011 @r_p_4
+predsumu_dhs 0011100 ..... .... 0100 ..... 0011011 @r_p_4
+
+# register-pair operands
+pslli_db 00000 0001... .... 0110 .... 00011011 @p_ui8_p
+psrli_db 00000 0001... .... 1110 .... 00011011 @p_ui8_p
+psrai_db 01000 0001... .... 1110 .... 00011011 @p_ui8_p
+pmin_db 1110010 .... 1 .... 1110 .... 00011011 @r_p_2
+pminu_db 1110110 .... 1 .... 1110 .... 00011011 @r_p_2
+pmax_db 1111010 .... 1 .... 1110 .... 00011011 @r_p_2
+pmaxu_db 1111110 .... 1 .... 1110 .... 00011011 @r_p_2
+pmseq_db 1100010 .... 1 .... 1110 .... 00011011 @r_p_2
+pmslt_db 1101010 .... 1 .... 1110 .... 00011011 @r_p_2
+pmsltu_db 1101110 .... 1 .... 1110 .... 00011011 @r_p_2
+psext_dh_b 0110000 00100 .... 0110 .... 00011011 @r2_p
+psati_dh 01100 001.... .... 1110 .... 00011011 @p_ui16_p_2
+pusati_dh 00100 001.... .... 1110 .... 00011011 @p_ui16_p_2
+pslli_dh 00000 001.... .... 0110 .... 00011011 @p_ui16_p_2
+psrli_dh 00000 001.... .... 1110 .... 00011011 @p_ui16_p_2
+psrai_dh 01000 001.... .... 1110 .... 00011011 @p_ui16_p_2
+psslai_dh 01010 001.... .... 0110 .... 00011011 @p_ui16_p_2
+psrari_dh 01010 001.... .... 1110 .... 00011011 @p_ui16_p_2
+pmin_dh 1110000 .... 1 .... 1110 .... 00011011 @r_p_2
+pminu_dh 1110100 .... 1 .... 1110 .... 00011011 @r_p_2
+pmax_dh 1111000 .... 1 .... 1110 .... 00011011 @r_p_2
+pmaxu_dh 1111100 .... 1 .... 1110 .... 00011011 @r_p_2
+pmseq_dh 1100000 .... 1 .... 1110 .... 00011011 @r_p_2
+pmslt_dh 1101000 .... 1 .... 1110 .... 00011011 @r_p_2
+pmsltu_dh 1101100 .... 1 .... 1110 .... 00011011 @r_p_2
+psext_dw_b 0110001 00100 .... 0110 .... 00011011 @r2_p
+psext_dw_h 0110001 00101 .... 0110 .... 00011011 @r2_p
+psati_dw 01100 01..... .... 1110 .... 00011011 @p_ui32_p_2
+pusati_dw 00100 01..... .... 1110 .... 00011011 @p_ui32_p_2
+pslli_dw 00000 01..... .... 0110 .... 00011011 @p_ui32_p_2
+psrli_dw 00000 01..... .... 1110 .... 00011011 @p_ui32_p_2
+psrai_dw 01000 01..... .... 1110 .... 00011011 @p_ui32_p_2
+psslai_dw 01010 01..... .... 0110 .... 00011011 @p_ui32_p_2
+psrari_dw 01010 01..... .... 1110 .... 00011011 @p_ui32_p_2
+pmin_dw 1110001 .... 1 .... 1110 .... 00011011 @r_p_2
+pminu_dw 1110101 .... 1 .... 1110 .... 00011011 @r_p_2
+pmax_dw 1111001 .... 1 .... 1110 .... 00011011 @r_p_2
+pmaxu_dw 1111101 .... 1 .... 1110 .... 00011011 @r_p_2
+pmseq_dw 1100001 .... 1 .... 1110 .... 00011011 @r_p_2
+pmslt_dw 1101001 .... 1 .... 1110 .... 00011011 @r_p_2
+pmsltu_dw 1101101 .... 1 .... 1110 .... 00011011 @r_p_2
+
+# register-pair first source and dest
+padd_dbs 0001110 ..... .... 0110 .... 00011011 @r_p_3
+psll_dbs 0000110 ..... .... 0110 .... 00011011 @r_p_3
+psrl_dbs 0000110 ..... .... 1110 .... 00011011 @r_p_3
+psra_dbs 0100110 ..... .... 1110 .... 00011011 @r_p_3
+padd_dhs 0001100 ..... .... 0110 .... 00011011 @r_p_3
+psll_dhs 0000100 ..... .... 0110 .... 00011011 @r_p_3
+psrl_dhs 0000100 ..... .... 1110 .... 00011011 @r_p_3
+psra_dhs 0100100 ..... .... 1110 .... 00011011 @r_p_3
+pssha_dhs 0110100 ..... .... 0110 .... 00011011 @r_p_3
+psshar_dhs 0111100 ..... .... 0110 .... 00011011 @r_p_3
+psshl_dhs 0010100 ..... .... 0110 .... 00011011 @r_p_3
+psshlr_dhs 0011100 ..... .... 0110 .... 00011011 @r_p_3
+padd_dws 0001101 ..... .... 0110 .... 00011011 @r_p_3
+psll_dws 0000101 ..... .... 0110 .... 00011011 @r_p_3
+psrl_dws 0000101 ..... .... 1110 .... 00011011 @r_p_3
+psra_dws 0100101 ..... .... 1110 .... 00011011 @r_p_3
+pssha_dws 0110101 ..... .... 0110 .... 00011011 @r_p_3
+psshar_dws 0111101 ..... .... 0110 .... 00011011 @r_p_3
+psshl_dws 0010101 ..... .... 0110 .... 00011011 @r_p_3
+psshlr_dws 0011101 ..... .... 0110 .... 00011011 @r_p_3
+
+# register-pair operands
+ppaire_db 1000000 .... 0 .... 1110 .... 00011011 @r_p_2
+ppaireo_db 1001000 .... 0 .... 1110 .... 00011011 @r_p_2
+ppairoe_db 1010000 .... 0 .... 1110 .... 00011011 @r_p_2
+ppairo_db 1011000 .... 0 .... 1110 .... 00011011 @r_p_2
+ppaire_dh 1000001 .... 0 .... 1110 .... 00011011 @r_p_2
+ppaireo_dh 1001001 .... 0 .... 1110 .... 00011011 @r_p_2
+ppairoe_dh 1010001 .... 0 .... 1110 .... 00011011 @r_p_2
+ppairo_dh 1011001 .... 0 .... 1110 .... 00011011 @r_p_2
+
+#register-pair first source only
+pnsrli_b 00000 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnsrai_b 01000 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnsrari_b 01010 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnclipi_b 01100 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnclipri_b 01110 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnclipiu_b 00100 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnclipriu_b 00110 001.... .... 1100 ..... 0011011 @p_ui16_p_3
+pnsrl_bs 00001 00 ..... .... 1100 ..... 0011011 @r_p_4
+pnsra_bs 01001 00 ..... .... 1100 ..... 0011011 @r_p_4
+pnsrar_bs 01011 00 ..... .... 1100 ..... 0011011 @r_p_4
+pnclip_bs 01101 00 ..... .... 1100 ..... 0011011 @r_p_4
+pnclipr_bs 01111 00 ..... .... 1100 ..... 0011011 @r_p_4
+pnclipu_bs 00101 00 ..... .... 1100 ..... 0011011 @r_p_4
+pnclipru_bs 00111 00 ..... .... 1100 ..... 0011011 @r_p_4
+
+pnsrli_h 00000 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnsrai_h 01000 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnsrari_h 01010 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnclipi_h 01100 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnclipri_h 01110 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnclipiu_h 00100 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnclipriu_h 00110 01..... .... 1100 ..... 0011011 @p_ui32_p_3
+pnsrl_hs 00001 01 ..... .... 1100 ..... 0011011 @r_p_4
+pnsra_hs 01001 01 ..... .... 1100 ..... 0011011 @r_p_4
+pnsrar_hs 01011 01 ..... .... 1100 ..... 0011011 @r_p_4
+pnclip_hs 01101 01 ..... .... 1100 ..... 0011011 @r_p_4
+pnclipr_hs 01111 01 ..... .... 1100 ..... 0011011 @r_p_4
+pnclipu_hs 00101 01 ..... .... 1100 ..... 0011011 @r_p_4
+pnclipru_hs 00111 01 ..... .... 1100 ..... 0011011 @r_p_4
+
+nsrli 00000 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nsrai 01000 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nsrari 01010 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nclipi 01100 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nclipri 01110 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nclipiu 00100 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nclipriu 00110 1...... .... 1100 ..... 0011011 @p_ui64_p_2
+nsrl 00001 11 ..... .... 1100 ..... 0011011 @r_p_4
+nsra 01001 11 ..... .... 1100 ..... 0011011 @r_p_4
+nsrar 01011 11 ..... .... 1100 ..... 0011011 @r_p_4
+nclip 01101 11 ..... .... 1100 ..... 0011011 @r_p_4
+nclipr 01111 11 ..... .... 1100 ..... 0011011 @r_p_4
+nclipu 00101 11 ..... .... 1100 ..... 0011011 @r_p_4
+nclipru 00111 11 ..... .... 1100 ..... 0011011 @r_p_4
+
+# register-pair multiply
+pmqwacc_h 01111 00 ..... ..... 010 .... 10011011 @r_p_1
+pmqrwacc_h 01111 10 ..... ..... 010 .... 10011011 @r_p_1
+mqwacc 01111 01 ..... ..... 010 .... 10011011 @r_p_1
+mqrwacc 01111 11 ..... ..... 010 .... 10011011 @r_p_1
+
+pwmul_b 00100 10 ..... ..... 010 .... 10011011 @r_p_1
+pwmulsu_b 01100 10 ..... ..... 010 .... 10011011 @r_p_1
+pwmulu_b 00110 10 ..... ..... 010 .... 10011011 @r_p_1
+
+pwmul_h 00100 00 ..... ..... 010 .... 10011011 @r_p_1
+pwmulsu_h 01100 00 ..... ..... 010 .... 10011011 @r_p_1
+pwmulu_h 00110 00 ..... ..... 010 .... 10011011 @r_p_1
+pwmacc_h 00101 00 ..... ..... 010 .... 10011011 @r_p_1
+pwmaccsu_h 01101 00 ..... ..... 010 .... 10011011 @r_p_1
+pwmaccu_h 00111 00 ..... ..... 010 .... 10011011 @r_p_1
+
+wmul 00100 01 ..... ..... 010 .... 10011011 @r_p_1
+wmulsu 01100 01 ..... ..... 010 .... 10011011 @r_p_1
+wmulu 00110 01 ..... ..... 010 .... 10011011 @r_p_1
+wmacc 00101 01 ..... ..... 010 .... 10011011 @r_p_1
+wmaccsu 01101 01 ..... ..... 010 .... 10011011 @r_p_1
+wmaccu 00111 01 ..... ..... 010 .... 10011011 @r_p_1
+
+pm2wadd_h 00000 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2waddsu_h 01100 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2waddu_h 00100 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2wadd_hx 00010 11 ..... ..... 010 .... 10011011 @r_p_1
+
+pm2wadda_h 00001 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2waddasu_h 01101 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2waddau_h 00101 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2wadda_hx 00011 11 ..... ..... 010 .... 10011011 @r_p_1
+
+pm2wsub_h 01000 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2wsub_hx 01010 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2wsuba_h 01001 11 ..... ..... 010 .... 10011011 @r_p_1
+pm2wsuba_hx 01011 11 ..... ..... 010 .... 10011011 @r_p_1
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index 4d5fc230d2e..e33e0ec110a 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -3,6 +3,36 @@
/* Copyright (c) 2026 ISRC ISCAS. */
/* Save a 64 bit data in src to dst and dst + 1 */
+static void set_pair_regs(DisasContext *ctx, int dst, TCGv_i64 src)
+{
+#if defined(TARGET_RISCV32)
+ TCGv_i64 tl_64 = tcg_temp_new_i64();
+ TCGv_i64 th_64 = tcg_temp_new_i64();
+ TCGv_i32 tl_32 = tcg_temp_new_i32();
+ TCGv_i32 th_32 = tcg_temp_new_i32();
+ tcg_gen_extract_i64(tl_64, src, 0, 32);
+ tcg_gen_extract_i64(th_64, src, 32, 32);
+ tcg_gen_trunc_i64_tl(tl_32, tl_64);
+ tcg_gen_trunc_i64_tl(th_32, th_64);
+ gen_set_gpr(ctx, dst, tl_32);
+ gen_set_gpr(ctx, dst + 1, th_32);
+# else
+ gen_set_gpr(ctx, dst, src);
+#endif
+}
+
+/* Concat two 32 bit data in src and src + 1 to dst */
+static void get_pair_regs(DisasContext *ctx, TCGv_i64 dst, int src)
+{
+#if defined(TARGET_RISCV32)
+ TCGv t1 = get_gpr(ctx, src, EXT_NONE);
+ TCGv t2 = get_gpr(ctx, src + 1, EXT_NONE);
+ tcg_gen_concat_i32_i64(dst, t1, t2);
+#else
+ TCGv t1 = get_gpr(ctx, src, EXT_NONE);
+ tcg_gen_mov_tl(dst, t1);
+#endif
+}
static bool require_rvp(DisasContext *ctx)
{
@@ -902,6 +932,241 @@ GEN_SIMD_TRANS_ACC_64(pm4adda_h)
GEN_SIMD_TRANS_ACC_64(pm4addasu_h)
GEN_SIMD_TRANS_ACC_64(pm4addau_h)
+/* Packed SIMD - Double-Width Operations (RV32 only, register pairs) */
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwadd_b)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwadda_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwaddu_b)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwaddau_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsub_b)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwsuba_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsubu_b)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwsubau_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(pwslli_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsll_bs)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(pwslai_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsla_bs)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwadd_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwadda_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwaddu_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwaddau_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsub_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwsuba_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsubu_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwsubau_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(pwslli_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsll_hs)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(pwslai_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwsla_hs)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wadd)
+GEN_SIMD_TRANS_REG_PAIR_ACC(wadda)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(waddu)
+GEN_SIMD_TRANS_REG_PAIR_ACC(waddau)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wsub)
+GEN_SIMD_TRANS_REG_PAIR_ACC(wsuba)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wsubu)
+GEN_SIMD_TRANS_REG_PAIR_ACC(wsubau)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(wslli)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wsll)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR_IMM(wslai)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wsla)
+
+GEN_SIMD_TRANS_REG_PAIR_LANE(padd_db, padd_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(psub_db, psub_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psadd_db, psadd_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psaddu_db, psaddu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssub_db, pssub_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssubu_db, pssubu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paadd_db, paadd_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paaddu_db, paaddu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasub_db, pasub_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasubu_db, pasubu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pabd_db, pabd_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pabdu_db, pabdu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(psabs_db, psabs_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(padd_dh, padd_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(psub_dh, psub_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psadd_dh, psadd_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psaddu_dh, psaddu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssub_dh, pssub_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssubu_dh, pssubu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paadd_dh, paadd_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paaddu_dh, paaddu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasub_dh, pasub_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasubu_dh, pasubu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(psh1add_dh, psh1add_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssh1sadd_dh, pssh1sadd_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pas_dhx, pas_hx)
+GEN_SIMD_TRANS_REG_PAIR_LANE(psa_dhx, psa_hx)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psas_dhx, psas_hx)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssa_dhx, pssa_hx)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paas_dhx, paas_hx)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasa_dhx, pasa_hx)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pabd_dh, pabd_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pabdu_dh, pabdu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY_VXSAT(psabs_dh, psabs_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psadd_dw, sadd)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(psaddu_dw, saddu)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssub_dw, ssub)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssubu_dw, ssubu)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paadd_dw, aadd)
+GEN_SIMD_TRANS_REG_PAIR_LANE(paaddu_dw, aaddu)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasub_dw, asub)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pasubu_dw, asubu)
+GEN_SIMD_TRANS_REG_PAIR_LANE_VXSAT(pssh1sadd_dw, ssh1sadd)
+
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(pslli_db, pslli_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(psrli_db, psrli_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(psrai_db, psrai_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmin_db, pmin_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pminu_db, pminu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmax_db, pmax_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmaxu_db, pmaxu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmseq_db, pmseq_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmslt_db, pmslt_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmsltu_db, pmsltu_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_UNARY(psext_dh_b, psext_h_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(psati_dh, psati_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(pusati_dh, pusati_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(pslli_dh, pslli_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(psrli_dh, psrli_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(psrai_dh, psrai_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(psslai_dh, psslai_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(psrari_dh, psrari_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmin_dh, pmin_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pminu_dh, pminu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmax_dh, pmax_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmaxu_dh, pmaxu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmseq_dh, pmseq_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmslt_dh, pmslt_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmsltu_dh, pmsltu_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(psati_dw, sati_32)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(pusati_dw, usati_32)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM_VXSAT(psslai_dw, sslai)
+GEN_SIMD_TRANS_REG_PAIR_LANE_IMM(psrari_dw, srari_32)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmseq_dw, mseq)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmslt_dw, mslt)
+GEN_SIMD_TRANS_REG_PAIR_LANE(pmsltu_dw, msltu)
+
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(padd_dbs, padd_bs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(psll_dbs, psll_bs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(psrl_dbs, psrl_bs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(psra_dbs, psra_bs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(padd_dhs, padd_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(psll_dhs, psll_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(psrl_dhs, psrl_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR(psra_dhs, psra_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(pssha_dhs, pssha_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(psshar_dhs, psshar_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(psshl_dhs, psshl_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(psshlr_dhs, psshlr_hs)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(pssha_dws, ssha)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(psshar_dws, sshar)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(psshl_dws, sshl)
+GEN_SIMD_TRANS_REG_PAIR_LANE_SCALAR_VXSAT(psshlr_dws, sshlr)
+
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppairo_db, ppairo_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppairo_dh, ppairo_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppaire_db, ppaire_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppaireo_db, ppaireo_b)
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppaireo_dh, ppaireo_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppairoe_dh, ppairoe_h)
+GEN_SIMD_TRANS_REG_PAIR_LANE(ppairoe_db, ppairoe_b)
+
+GEN_SIMD_TRANS_REG_PAIR_PREDSUM(predsum_dbs)
+GEN_SIMD_TRANS_REG_PAIR_PREDSUM(predsumu_dbs)
+GEN_SIMD_TRANS_REG_PAIR_PREDSUM(predsum_dhs)
+GEN_SIMD_TRANS_REG_PAIR_PREDSUM(predsumu_dhs)
+
+GEN_SIMD_TRANS_PN_OP_IMM(pnsrli_b)
+GEN_SIMD_TRANS_PN_OP_IMM(pnsrai_b)
+GEN_SIMD_TRANS_PN_OP_IMM(pnsrari_b)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipi_b)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipri_b)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipiu_b)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipriu_b)
+
+GEN_SIMD_TRANS_PN_OP_IMM(pnsrli_h)
+GEN_SIMD_TRANS_PN_OP_IMM(pnsrai_h)
+GEN_SIMD_TRANS_PN_OP_IMM(pnsrari_h)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipi_h)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipri_h)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipiu_h)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(pnclipriu_h)
+
+GEN_SIMD_TRANS_PN_OP_IMM(nsrli)
+GEN_SIMD_TRANS_PN_OP_IMM(nsrai)
+GEN_SIMD_TRANS_PN_OP_IMM(nsrari)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(nclipi)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(nclipri)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(nclipiu)
+GEN_SIMD_TRANS_PN_OP_IMM_VXSAT(nclipriu)
+
+GEN_SIMD_TRANS_PN_OP_REG(pnsrl_bs)
+GEN_SIMD_TRANS_PN_OP_REG(pnsra_bs)
+GEN_SIMD_TRANS_PN_OP_REG(pnsrar_bs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclip_bs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclipr_bs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclipu_bs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclipru_bs)
+
+GEN_SIMD_TRANS_PN_OP_REG(pnsrl_hs)
+GEN_SIMD_TRANS_PN_OP_REG(pnsra_hs)
+GEN_SIMD_TRANS_PN_OP_REG(pnsrar_hs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclip_hs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclipr_hs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclipu_hs)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(pnclipru_hs)
+
+GEN_SIMD_TRANS_PN_OP_REG(nsrl)
+GEN_SIMD_TRANS_PN_OP_REG(nsra)
+GEN_SIMD_TRANS_PN_OP_REG(nsrar)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(nclip)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(nclipr)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(nclipu)
+GEN_SIMD_TRANS_PN_OP_REG_VXSAT(nclipru)
+
+GEN_SIMD_TRANS_REG_PAIR_ACC(pmqwacc_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pmqrwacc_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(mqwacc)
+GEN_SIMD_TRANS_REG_PAIR_ACC(mqrwacc)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwmul_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwmulsu_b)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwmulu_b)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwmul_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwmulsu_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pwmulu_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwmacc_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwmaccsu_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pwmaccu_h)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wmul)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wmulsu)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(wmulu)
+
+GEN_SIMD_TRANS_REG_PAIR_ACC(wmacc)
+GEN_SIMD_TRANS_REG_PAIR_ACC(wmaccsu)
+GEN_SIMD_TRANS_REG_PAIR_ACC(wmaccu)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pm2wadd_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pm2waddsu_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pm2waddu_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pm2wadd_hx)
+
+GEN_SIMD_TRANS_REG_PAIR_ACC(pm2wadda_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pm2waddasu_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pm2waddau_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pm2wadda_hx)
+
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pm2wsub_h)
+GEN_SIMD_TRANS_REG_PAIR_SCALAR(pm2wsub_hx)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pm2wsuba_h)
+GEN_SIMD_TRANS_REG_PAIR_ACC(pm2wsuba_hx)
+
#define GEN_PLI(NAME, PRE_REQ, IMM_TYPE, LIMIT, SHIFT, ADDEND) \
static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
{ \
@@ -917,6 +1182,21 @@ static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
return true; \
}
+#define GEN_PLI_D(NAME, IMM_TYPE, LIMIT, SHIFT, ADDEND) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_RVP(ctx); \
+ int i = 1; \
+ IMM_TYPE imm = a->imm; \
+ while (i < (LIMIT)) { \
+ imm = (imm << (SHIFT)) + (ADDEND); \
+ i++; \
+ } \
+ gen_set_gpri(ctx, (a->rd) * 2, imm); \
+ gen_set_gpri(ctx, (a->rd) * 2 + 1, imm); \
+ return true; \
+}
+
GEN_PLI(pli_b, , target_long, TARGET_LONG_SIZE, 8, a->imm)
GEN_PLI(pli_h, , target_long, TARGET_LONG_SIZE / 2, 16,
a->imm & 0xFFFF)
@@ -926,3 +1206,184 @@ GEN_PLI(pli_w, REQUIRE_64BIT(ctx); , int64_t, TARGET_LONG_SIZE / 4, 32,
a->imm & 0xFFFFFFFF)
GEN_PLI(plui_w, REQUIRE_64BIT(ctx); , int64_t, TARGET_LONG_SIZE / 4, 32,
a->imm & 0xFFFFFFFF)
+GEN_PLI_D(pli_db, target_long, TARGET_LONG_SIZE, 8, a->imm)
+GEN_PLI_D(pli_dh, target_long, TARGET_LONG_SIZE / 2, 16,
+ a->imm & 0xFFFF)
+GEN_PLI_D(plui_dh, target_long, TARGET_LONG_SIZE / 2, 16,
+ a->imm & 0xFFFF)
+
+#define GEN_DW_LANE_BINOP(NAME, OP) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
+ TCGv src2_0 = get_gpr(ctx, (a->rs2) * 2, EXT_NONE); \
+ TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
+ TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
+ TCGv src2_1 = get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE); \
+ TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
+ OP(dest_0, src1_0, src2_0); \
+ OP(dest_1, src1_1, src2_1); \
+ gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
+ gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
+ return true; \
+}
+
+GEN_DW_LANE_BINOP(padd_dw, tcg_gen_add_tl)
+GEN_DW_LANE_BINOP(psub_dw, tcg_gen_sub_tl)
+GEN_DW_LANE_BINOP(psh1add_dw, gen_sh1add)
+
+/* Verify rd is not zero register for wzip8p and wzip16p. */
+#if defined(TARGET_RISCV32)
+#define GEN_WZIP_P(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv_i32 src1 = get_gpr(ctx, a->rs1, EXT_NONE); \
+ TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE); \
+ TCGv_i64 t = tcg_temp_new_i64(); \
+ if (a->rd == 0) { \
+ return true; \
+ } else { \
+ get_pair_regs(ctx, t, (a->rd) * 2); \
+ } \
+ gen_helper_##NAME(t, tcg_env, src1, src2); \
+ set_pair_regs(ctx, (a->rd) * 2, t); \
+ return true; \
+}
+#else
+#define GEN_WZIP_P(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ return true; \
+}
+#endif
+
+GEN_WZIP_P(wzip8p)
+GEN_WZIP_P(wzip16p)
+
+#define GEN_PAIR_I64_BINOP(NAME, OP) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv_i64 src1 = tcg_temp_new_i64(); \
+ TCGv_i64 src2 = tcg_temp_new_i64(); \
+ TCGv_i64 dest = tcg_temp_new_i64(); \
+ get_pair_regs(ctx, src1, (a->rs1) * 2); \
+ get_pair_regs(ctx, src2, (a->rs2) * 2); \
+ get_pair_regs(ctx, dest, (a->rd) * 2); \
+ OP(dest, src1, src2); \
+ set_pair_regs(ctx, (a->rd) * 2, dest); \
+ return true; \
+}
+
+GEN_PAIR_I64_BINOP(addd_p, tcg_gen_add_i64)
+GEN_PAIR_I64_BINOP(subd_p, tcg_gen_sub_i64)
+
+#define GEN_DW_EXT(NAME, OP) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2); \
+ TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE); \
+ TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1); \
+ TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE); \
+ OP(dest_0, src1_0); \
+ gen_set_gpr(ctx, (a->rd) * 2, dest_0); \
+ OP(dest_1, src1_1); \
+ gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1); \
+ return true; \
+}
+
+GEN_DW_EXT(psext_dw_b, tcg_gen_ext8s_tl)
+GEN_DW_EXT(psext_dw_h, tcg_gen_ext16s_tl)
+
+#define GEN_DW_SHIFT_IMM(NAME, OP) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ arg_shift a0, a1; \
+ a0.rd = (a->rd) * 2; \
+ a0.rs1 = (a->rs1) * 2; \
+ a0.shamt = a->imm; \
+ a1.rd = (a->rd) * 2 + 1; \
+ a1.rs1 = (a->rs1) * 2 + 1; \
+ a1.shamt = a->imm; \
+ gen_shift_imm_fn(ctx, &a0, EXT_NONE, OP, NULL); \
+ gen_shift_imm_fn(ctx, &a1, EXT_NONE, OP, NULL); \
+ return true; \
+}
+
+#define GEN_DW_SHIFT_IMM_PER_OL(NAME, OP, OP_OL) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ arg_shift a0, a1; \
+ a0.rd = (a->rd) * 2; \
+ a0.rs1 = (a->rs1) * 2; \
+ a0.shamt = a->imm; \
+ a1.rd = (a->rd) * 2 + 1; \
+ a1.rs1 = (a->rs1) * 2 + 1; \
+ a1.shamt = a->imm; \
+ gen_shift_imm_fn_per_ol(ctx, &a0, EXT_NONE, OP, OP_OL, NULL); \
+ gen_shift_imm_fn_per_ol(ctx, &a1, EXT_NONE, OP, OP_OL, NULL); \
+ return true; \
+}
+
+GEN_DW_SHIFT_IMM(pslli_dw, tcg_gen_shli_tl)
+GEN_DW_SHIFT_IMM_PER_OL(psrli_dw, tcg_gen_shri_tl, gen_srliw)
+GEN_DW_SHIFT_IMM_PER_OL(psrai_dw, tcg_gen_sari_tl, gen_sraiw)
+
+#define GEN_DW_PAIR_ARITH(NAME, EXTRA_REQ, EXT, OP) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ EXTRA_REQ \
+ arg_r a0, a1; \
+ a0.rd = (a->rd) * 2; \
+ a0.rs1 = (a->rs1) * 2; \
+ a0.rs2 = (a->rs2) * 2; \
+ a1.rd = (a->rd) * 2 + 1; \
+ a1.rs1 = (a->rs1) * 2 + 1; \
+ a1.rs2 = (a->rs2) * 2 + 1; \
+ gen_arith(ctx, &a0, EXT, OP, NULL); \
+ gen_arith(ctx, &a1, EXT, OP, NULL); \
+ return true; \
+}
+
+GEN_DW_PAIR_ARITH(pmin_dw, REQUIRE_ZBB(ctx); , EXT_SIGN, tcg_gen_smin_tl)
+GEN_DW_PAIR_ARITH(pminu_dw, REQUIRE_ZBB(ctx); , EXT_SIGN, tcg_gen_umin_tl)
+GEN_DW_PAIR_ARITH(pmax_dw, REQUIRE_ZBB(ctx); , EXT_SIGN, tcg_gen_smax_tl)
+GEN_DW_PAIR_ARITH(pmaxu_dw, REQUIRE_ZBB(ctx); , EXT_SIGN, tcg_gen_umax_tl)
+
+#define GEN_DWS_REG_OP(NAME, GEN, EXT, OP) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \
+{ \
+ REQUIRE_32BIT(ctx); \
+ REQUIRE_RVP(ctx); \
+ arg_r a0, a1; \
+ a0.rd = (a->rd) * 2; \
+ a0.rs1 = (a->rs1) * 2; \
+ a0.rs2 = a->rs2; \
+ a1.rd = (a->rd) * 2 + 1; \
+ a1.rs1 = (a->rs1) * 2 + 1; \
+ a1.rs2 = a->rs2; \
+ GEN(ctx, &a0, EXT, OP, NULL); \
+ GEN(ctx, &a1, EXT, OP, NULL); \
+ return true; \
+}
+
+GEN_DWS_REG_OP(padd_dws, gen_arith, EXT_NONE, tcg_gen_add_tl)
+GEN_DWS_REG_OP(psll_dws, gen_shift, EXT_NONE, tcg_gen_shl_tl)
+GEN_DWS_REG_OP(psrl_dws, gen_shift, EXT_ZERO, tcg_gen_shr_tl)
+GEN_DWS_REG_OP(psra_dws, gen_shift, EXT_SIGN, tcg_gen_sar_tl)
+
+GEN_DW_PAIR_ARITH(ppaire_dh, REQUIRE_ZBKB(ctx); , EXT_NONE, gen_pack)
diff --git a/target/riscv/tcg/psimd_helper.c b/target/riscv/tcg/psimd_helper.c
index e7c7e554938..c69adae10cc 100644
--- a/target/riscv/tcg/psimd_helper.c
+++ b/target/riscv/tcg/psimd_helper.c
@@ -2890,3 +2890,276 @@ GEN_PSIMD_4WAY_MUL_ACC(pm4addasu_h, uint64_t, int16_t, uint16_t,
GEN_PSIMD_4WAY_MUL_ACC(pm4addau_h, uint64_t, uint16_t, uint16_t,
uint64_t, uint64_t, uint64_t, EXTRACT16, EXTRACT64,
INSERT64, ELEMS_D, 0, PSIMD_MUL_U64)
+
+/* Double-Width Operations (RV32 only, register pairs) */
+
+GEN_PSIMD_WIDEN_BINOP(pwadd_b, int8_t, int16_t, uint16_t,
+ 4, 8, 16, 0xFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwadda_b, int8_t, int16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0xFFFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP(pwaddu_b, uint8_t, uint16_t, uint16_t,
+ 4, 8, 16, 0xFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwaddau_b, uint8_t, uint16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0xFFFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP(pwsub_b, int8_t, int16_t, uint16_t,
+ 4, 8, 16, 0xFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwsuba_b, int8_t, int16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0xFFFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP(pwsubu_b, uint8_t, uint16_t, uint16_t,
+ 4, 8, 16, 0xFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwsubau_b, uint8_t, uint16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0xFFFF, PSIMD_COMB_SUB)
+
+GEN_PSIMD_WIDEN_SHIFT(pwslli_b, uint8_t, uint16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0x0F)
+GEN_PSIMD_WIDEN_SHIFT(pwsll_bs, uint8_t, uint16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0x1F)
+GEN_PSIMD_WIDEN_SHIFT(pwslai_b, int8_t, int16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0x0F)
+GEN_PSIMD_WIDEN_SHIFT(pwsla_bs, int8_t, int16_t, uint16_t,
+ 4, 8, 16, 0xFF, 0x1F)
+
+GEN_PSIMD_WIDEN_BINOP(pwadd_h, int16_t, int32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwadda_h, int16_t, int32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0xFFFFFFFFULL,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP(pwaddu_h, uint16_t, uint32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwaddau_h, uint16_t, uint32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0xFFFFFFFFULL,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP(pwsub_h, int16_t, int32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwsuba_h, int16_t, int32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0xFFFFFFFFULL,
+ PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP(pwsubu_h, uint16_t, uint32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP_ACC(pwsubau_h, uint16_t, uint32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0xFFFFFFFFULL,
+ PSIMD_COMB_SUB)
+
+GEN_PSIMD_WIDEN_SHIFT(pwslli_h, uint16_t, uint32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0x1F)
+GEN_PSIMD_WIDEN_SHIFT(pwsll_hs, uint16_t, uint32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0x1F)
+GEN_PSIMD_WIDEN_SHIFT(pwslai_h, int16_t, int32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0x1F)
+GEN_PSIMD_WIDEN_SHIFT(pwsla_hs, int16_t, int32_t, uint32_t,
+ 2, 16, 32, 0xFFFF, 0x1F)
+
+GEN_PSIMD_WIDEN_BINOP(wadd, int32_t, int64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP_ACC(wadda, int32_t, int64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFULL,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP(waddu, uint32_t, uint64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP_ACC(waddau, uint32_t, uint64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFULL,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_WIDEN_BINOP(wsub, int32_t, int64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP_ACC(wsuba, int32_t, int64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFULL,
+ PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP(wsubu, uint32_t, uint64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, PSIMD_COMB_SUB)
+GEN_PSIMD_WIDEN_BINOP_ACC(wsubau, uint32_t, uint64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFULL,
+ PSIMD_COMB_SUB)
+
+GEN_PSIMD_WIDEN_SHIFT(wslli, uint32_t, uint64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0x3F)
+GEN_PSIMD_WIDEN_SHIFT(wsll, uint32_t, uint64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0x3F)
+GEN_PSIMD_WIDEN_SHIFT(wslai, int32_t, int64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0x3F)
+GEN_PSIMD_WIDEN_SHIFT(wsla, int32_t, int64_t, uint64_t,
+ 1, 32, 64, 0xFFFFFFFF, 0x3F)
+
+GEN_PSIMD_DW_ZIP(wzip8p, EXTRACT8, 4, 16, 8)
+GEN_PSIMD_DW_ZIP(wzip16p, EXTRACT16, 2, 32, 16)
+
+GEN_PSIMD_DW_REDSUM(predsum_dbs, int64_t, int32_t, int8_t, EXTRACT8, 8)
+GEN_PSIMD_DW_REDSUM(predsumu_dbs, uint64_t, uint32_t, uint8_t, EXTRACT8, 8)
+GEN_PSIMD_DW_REDSUM(predsum_dhs, int64_t, int32_t, int16_t, EXTRACT16, 4)
+GEN_PSIMD_DW_REDSUM(predsumu_dhs, uint64_t, uint32_t, uint16_t, EXTRACT16, 4)
+
+
+/* Narrowing Operations (RV32 only, register pair sources) */
+
+GEN_PSIMD_NARROW_SRL(pnsrli_b, uint16_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x0F)
+GEN_PSIMD_NARROW_SRL(pnsrl_bs, uint16_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x1F)
+GEN_PSIMD_NARROW_SRA_PACK(pnsrai_b, int16_t, int32_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x0F)
+GEN_PSIMD_NARROW_SRA_PACK(pnsra_bs, int16_t, int32_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x1F)
+GEN_PSIMD_NARROW_RNDSRA_PACK(pnsrari_b, int16_t, int32_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x0F, 0x1FF)
+GEN_PSIMD_NARROW_RNDSRA_PACK(pnsrar_bs, int16_t, int32_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x1F, 0x1FF)
+GEN_PSIMD_NCLIP_SIGNED_PACK(pnclipi_b, int16_t, int32_t, int16_t,
+ uint8_t, 4, 16, 8, 0xFFFF, 0x0F,
+ -128, 127, 0x80, 0x7F)
+GEN_PSIMD_NCLIPR_SIGNED_PACK(pnclipri_b, int16_t, int32_t, int16_t,
+ uint8_t, 4, 16, 8, 0xFFFF, 0x0F, 0x1FFFF,
+ -128, 127, 0x80, 0x7F)
+GEN_PSIMD_NCLIP_UNSIGNED_PACK(pnclipiu_b, uint16_t, uint16_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x0F, 0x00FF)
+GEN_PSIMD_NCLIPR_UNSIGNED_PACK(pnclipriu_b, uint16_t, uint32_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x0F, 0x00FF)
+GEN_PSIMD_NCLIP_SIGNED_PACK(pnclip_bs, int16_t, int32_t, int16_t,
+ uint8_t, 4, 16, 8, 0xFFFF, 0x1F,
+ -128, 127, 0x80, 0x7F)
+GEN_PSIMD_NCLIPR_SIGNED_PACK(pnclipr_bs, int16_t, int32_t, int16_t,
+ uint8_t, 4, 16, 8, 0xFFFF, 0x1F, 0x1FFFF,
+ -128, 127, 0x80, 0x7F)
+GEN_PSIMD_NCLIP_UNSIGNED_PACK(pnclipu_bs, uint16_t, uint32_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x1F, 0x00FF)
+GEN_PSIMD_NCLIPR_UNSIGNED_PACK(pnclipru_bs, uint16_t, uint64_t, uint8_t,
+ 4, 16, 8, 0xFFFF, 0x1F, 0x00FF)
+
+GEN_PSIMD_NARROW_SRL(pnsrli_h, uint32_t, uint16_t,
+ 2, 32, 16, 0xFFFFFFFFULL, 0x1F)
+GEN_PSIMD_NARROW_SRA_PACK(pnsrai_h, int32_t, int64_t, uint16_t,
+ 2, 32, 16, 0xFFFFFFFFULL, 0x1F)
+GEN_PSIMD_NARROW_RNDSRA_PACK(pnsrari_h, int32_t, int64_t, uint16_t,
+ 2, 32, 16, 0xFFFFFFFFULL, 0x1F, 0x1FFFF)
+
+GEN_PSIMD_NARROW_SRL(pnsrl_hs, uint32_t, uint16_t,
+ 2, 32, 16, 0xFFFFFFFFULL, 0x1F)
+
+GEN_PSIMD_NARROW_ALIAS(pnsra_hs, pnsrai_h)
+GEN_PSIMD_NARROW_ALIAS(pnsrar_hs, pnsrari_h)
+
+GEN_PSIMD_NCLIP_SIGNED_PACK(pnclip_hs, int32_t, int64_t, int32_t,
+ uint16_t, 2, 32, 16, 0xFFFFFFFFULL, 0x1F,
+ -32768, 32767, 0x8000, 0x7FFF)
+GEN_PSIMD_NCLIPR_SIGNED_PACK(pnclipr_hs, int32_t, int64_t, int32_t,
+ uint16_t, 2, 32, 16, 0xFFFFFFFFULL, 0x1F,
+ 0x1FFFFFFFF, -32768, 32767, 0x8000, 0x7FFF)
+
+GEN_PSIMD_NARROW_ALIAS(pnclipi_h, pnclip_hs)
+GEN_PSIMD_NARROW_ALIAS(pnclipri_h, pnclipr_hs)
+
+GEN_PSIMD_NCLIP_UNSIGNED_PACK(pnclipu_hs, uint32_t, uint32_t, uint16_t,
+ 2, 32, 16, 0xFFFFFFFFULL, 0x1F, 0xFFFF)
+GEN_PSIMD_NCLIPR_UNSIGNED_PACK(pnclipru_hs, uint32_t, uint64_t, uint16_t,
+ 2, 32, 16, 0xFFFFFFFFULL, 0x1F, 0xFFFF)
+
+GEN_PSIMD_NARROW_ALIAS(pnclipiu_h, pnclipu_hs)
+GEN_PSIMD_NARROW_ALIAS(pnclipriu_h, pnclipru_hs)
+
+GEN_PSIMD_NARROW_SRL(nsrli, uint64_t, uint32_t,
+ 1, 64, 32, 0xFFFFFFFFFFFFFFFFULL, 0x3F)
+
+GEN_PSIMD_NARROW_SRA(nsrai)
+GEN_PSIMD_NARROW_RNDSRA(nsrari)
+
+GEN_PSIMD_NARROW_SRL(nsrl, uint64_t, uint32_t,
+ 1, 64, 32, 0xFFFFFFFFFFFFFFFFULL, 0x3F)
+
+GEN_PSIMD_NARROW_SRA(nsra)
+GEN_PSIMD_NARROW_RNDSRA(nsrar)
+
+GEN_PSIMD_NCLIP(nclipi)
+GEN_PSIMD_NCLIPR(nclipri)
+GEN_PSIMD_NCLIPU(nclipiu)
+GEN_PSIMD_NCLIPRU(nclipriu)
+
+GEN_PSIMD_NCLIP(nclip)
+GEN_PSIMD_NCLIPR(nclipr)
+GEN_PSIMD_NCLIPU(nclipu)
+GEN_PSIMD_NCLIPRU(nclipru)
+
+/* Multiplication with Even-Odd Register Pairs as Destination (RV32 only) */
+
+GEN_PSIMD_WIDEN_QMUL_ACC(pmqwacc_h, int16_t, int32_t, int64_t,
+ int32_t, uint32_t, 2, EXTRACT16, EXTRACT32,
+ 2, 0, 15, 0, 32, PSIMD_MUL_S64)
+GEN_PSIMD_WIDEN_QMUL_ACC(pmqrwacc_h, int16_t, int32_t, int64_t,
+ int32_t, uint32_t, 2, EXTRACT16, EXTRACT32,
+ 2, 0, 15, 1LL << 14, 32, PSIMD_MUL_S64)
+
+GEN_PSIMD_WIDEN_MUL(pwmul_b, int8_t, int8_t, int16_t, uint16_t,
+ 4, EXTRACT8, 16, PSIMD_MUL_S32)
+GEN_PSIMD_WIDEN_MUL(pwmulsu_b, int8_t, uint8_t, int16_t, uint16_t,
+ 4, EXTRACT8, 16, PSIMD_MUL_SU16)
+GEN_PSIMD_WIDEN_MUL(pwmulu_b, uint8_t, uint8_t, uint16_t, uint16_t,
+ 4, EXTRACT8, 16, PSIMD_MUL_U32)
+GEN_PSIMD_WIDEN_MUL(pwmul_h, int16_t, int16_t, int32_t, uint32_t,
+ 2, EXTRACT16, 32, PSIMD_MUL_S32)
+GEN_PSIMD_WIDEN_MUL(pwmulsu_h, int16_t, uint16_t, int32_t, uint32_t,
+ 2, EXTRACT16, 32, PSIMD_MUL_SU32)
+GEN_PSIMD_WIDEN_MUL(pwmulu_h, uint16_t, uint16_t, uint32_t, uint32_t,
+ 2, EXTRACT16, 32, PSIMD_MUL_U32)
+
+GEN_PSIMD_WIDEN_MUL_ACC(pwmacc_h, int16_t, int16_t, int32_t,
+ int32_t, uint32_t, 2, EXTRACT16, EXTRACT32, 32,
+ PSIMD_MUL_S32)
+GEN_PSIMD_WIDEN_MUL_ACC(pwmaccsu_h, int16_t, uint16_t, int32_t,
+ int32_t, uint32_t, 2, EXTRACT16, EXTRACT32, 32,
+ PSIMD_MUL_SU32)
+GEN_PSIMD_WIDEN_MUL_ACC(pwmaccu_h, uint16_t, uint16_t, uint32_t,
+ uint32_t, uint32_t, 2, EXTRACT16, EXTRACT32, 32,
+ PSIMD_MUL_U32)
+
+GEN_PSIMD_WIDEN_QMUL_ACC(mqwacc, int32_t, int64_t, int64_t,
+ int64_t, uint64_t, 1, EXTRACT32, EXTRACT64,
+ 0, 0, 31, 0, 64, PSIMD_MUL_S64)
+GEN_PSIMD_WIDEN_QMUL_ACC(mqrwacc, int32_t, int64_t, int64_t,
+ int64_t, uint64_t, 1, EXTRACT32, EXTRACT64,
+ 0, 0, 31, 1LL << 30, 64, PSIMD_MUL_S64)
+
+GEN_PSIMD_WIDEN_MUL(wmul, int32_t, int32_t, int64_t, uint64_t,
+ 1, EXTRACT32, 64, PSIMD_MUL_S64)
+GEN_PSIMD_WIDEN_MUL(wmulsu, int32_t, uint32_t, int64_t, uint64_t,
+ 1, EXTRACT32, 64, PSIMD_MUL_SU64)
+GEN_PSIMD_WIDEN_MUL(wmulu, uint32_t, uint32_t, uint64_t, uint64_t,
+ 1, EXTRACT32, 64, PSIMD_MUL_U64)
+
+GEN_PSIMD_WIDEN_MUL_ACC(wmacc, int32_t, int32_t, int64_t,
+ int64_t, uint64_t, 1, EXTRACT32, EXTRACT64, 64,
+ PSIMD_MUL_S64)
+GEN_PSIMD_WIDEN_MUL_ACC(wmaccsu, int32_t, uint32_t, int64_t,
+ int64_t, uint64_t, 1, EXTRACT32, EXTRACT64, 64,
+ PSIMD_MUL_SU64)
+GEN_PSIMD_WIDEN_MUL_ACC(wmaccu, uint32_t, uint32_t, uint64_t,
+ uint64_t, uint64_t, 1, EXTRACT32, EXTRACT64, 64,
+ PSIMD_MUL_U64)
+
+GEN_PSIMD_DW_2WAY_MUL(pm2wadd_h, int16_t, int16_t, int64_t,
+ EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_S64, PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL(pm2waddsu_h, int16_t, uint16_t, int64_t,
+ EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_SU64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL(pm2waddu_h, uint16_t, uint16_t, uint64_t,
+ EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_U64, PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL_ACC(pm2wadda_h, int16_t, int16_t, int64_t, int64_t,
+ EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_S64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL_ACC(pm2waddasu_h, int16_t, uint16_t, int64_t,
+ int64_t, EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_SU64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL_ACC(pm2waddau_h, uint16_t, uint16_t, uint64_t,
+ uint64_t, EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_U64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL(pm2wadd_hx, int16_t, int16_t, int64_t,
+ EXTRACT16, 0, 1, 1, 0, PSIMD_MUL_S64, PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL_ACC(pm2wadda_hx, int16_t, int16_t, int64_t, int64_t,
+ EXTRACT16, 0, 1, 1, 0, PSIMD_MUL_S64,
+ PSIMD_COMB_ADD)
+GEN_PSIMD_DW_2WAY_MUL(pm2wsub_h, int16_t, int16_t, int64_t,
+ EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_S64, PSIMD_COMB_SUB)
+GEN_PSIMD_DW_2WAY_MUL(pm2wsub_hx, int16_t, int16_t, int64_t,
+ EXTRACT16, 0, 1, 1, 0, PSIMD_MUL_S64, PSIMD_COMB_SUB)
+GEN_PSIMD_DW_2WAY_MUL_ACC(pm2wsuba_h, int16_t, int16_t, int64_t, int64_t,
+ EXTRACT16, 0, 1, 0, 1, PSIMD_MUL_S64,
+ PSIMD_COMB_SUB)
+GEN_PSIMD_DW_2WAY_MUL_ACC(pm2wsuba_hx, int16_t, int16_t, int64_t, int64_t,
+ EXTRACT16, 0, 1, 1, 0, PSIMD_MUL_S64,
+ PSIMD_COMB_SUB)
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* [PATCH v2 18/18] target/riscv: Remove Zbkb dependency from P extension to align with the spec
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (16 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 17/18] target/riscv: Add packed SIMD RV32 only instructions Molly Chen
@ 2026-07-17 10:07 ` Molly Chen
2026-08-03 2:26 ` Chao Liu
2026-07-29 8:43 ` [PATCH v2 00/18] target/riscv: Add support for RISC-V P Chao Liu
2026-07-29 9:32 ` Chao Liu
19 siblings, 1 reply; 34+ messages in thread
From: Molly Chen @ 2026-07-17 10:07 UTC (permalink / raw)
To: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, Chao Liu
Cc: xiaoou, qemu-riscv, qemu-devel
Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
---
target/riscv/tcg/insn_trans/trans_rvb.c.inc | 4 +++-
target/riscv/tcg/insn_trans/trans_rvp.c.inc | 2 +-
target/riscv/tcg/tcg-cpu.c | 6 ++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/target/riscv/tcg/insn_trans/trans_rvb.c.inc b/target/riscv/tcg/insn_trans/trans_rvb.c.inc
index e4dcc7c9913..af53eb4fe4b 100644
--- a/target/riscv/tcg/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvb.c.inc
@@ -527,7 +527,9 @@ static bool trans_brev8(DisasContext *ctx, arg_brev8 *a)
static bool trans_pack(DisasContext *ctx, arg_pack *a)
{
- REQUIRE_ZBKB(ctx);
+ if (!has_ext(ctx, RVP) && !ctx->cfg_ptr->ext_zbkb) {
+ return false;
+ }
return gen_arith(ctx, a, EXT_NONE, gen_pack, NULL);
}
diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
index e33e0ec110a..8c5b52ca970 100644
--- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
+++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
@@ -1386,4 +1386,4 @@ GEN_DWS_REG_OP(psll_dws, gen_shift, EXT_NONE, tcg_gen_shl_tl)
GEN_DWS_REG_OP(psrl_dws, gen_shift, EXT_ZERO, tcg_gen_shr_tl)
GEN_DWS_REG_OP(psra_dws, gen_shift, EXT_SIGN, tcg_gen_sar_tl)
-GEN_DW_PAIR_ARITH(ppaire_dh, REQUIRE_ZBKB(ctx); , EXT_NONE, gen_pack)
+GEN_DW_PAIR_ARITH(ppaire_dh, , EXT_NONE, gen_pack)
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 1665583accf..36b0196a626 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -563,10 +563,8 @@ static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
return;
}
- if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
- cpu->cfg.ext_zbkb)) {
- error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
- "extensions");
+ if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb)) {
+ error_setg(errp, "P extension requires zmmul, zba and zbb extensions");
return;
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 34+ messages in thread* Re: [PATCH v2 18/18] target/riscv: Remove Zbkb dependency from P extension to align with the spec
2026-07-17 10:07 ` [PATCH v2 18/18] target/riscv: Remove Zbkb dependency from P extension to align with the spec Molly Chen
@ 2026-08-03 2:26 ` Chao Liu
0 siblings, 0 replies; 34+ messages in thread
From: Chao Liu @ 2026-08-03 2:26 UTC (permalink / raw)
To: Molly Chen
Cc: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
chao.liu.zevorn, qemu-riscv, qemu-devel
On Fri, Jul 17, 2026 at 10:07:11AM +0800, Molly Chen wrote:
> Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Thanks,
Chao
> ---
> target/riscv/tcg/insn_trans/trans_rvb.c.inc | 4 +++-
> target/riscv/tcg/insn_trans/trans_rvp.c.inc | 2 +-
> target/riscv/tcg/tcg-cpu.c | 6 ++----
> 3 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/target/riscv/tcg/insn_trans/trans_rvb.c.inc b/target/riscv/tcg/insn_trans/trans_rvb.c.inc
> index e4dcc7c9913..af53eb4fe4b 100644
> --- a/target/riscv/tcg/insn_trans/trans_rvb.c.inc
> +++ b/target/riscv/tcg/insn_trans/trans_rvb.c.inc
> @@ -527,7 +527,9 @@ static bool trans_brev8(DisasContext *ctx, arg_brev8 *a)
>
> static bool trans_pack(DisasContext *ctx, arg_pack *a)
> {
> - REQUIRE_ZBKB(ctx);
> + if (!has_ext(ctx, RVP) && !ctx->cfg_ptr->ext_zbkb) {
> + return false;
> + }
> return gen_arith(ctx, a, EXT_NONE, gen_pack, NULL);
> }
>
> diff --git a/target/riscv/tcg/insn_trans/trans_rvp.c.inc b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> index e33e0ec110a..8c5b52ca970 100644
> --- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> +++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc
> @@ -1386,4 +1386,4 @@ GEN_DWS_REG_OP(psll_dws, gen_shift, EXT_NONE, tcg_gen_shl_tl)
> GEN_DWS_REG_OP(psrl_dws, gen_shift, EXT_ZERO, tcg_gen_shr_tl)
> GEN_DWS_REG_OP(psra_dws, gen_shift, EXT_SIGN, tcg_gen_sar_tl)
>
> -GEN_DW_PAIR_ARITH(ppaire_dh, REQUIRE_ZBKB(ctx); , EXT_NONE, gen_pack)
> +GEN_DW_PAIR_ARITH(ppaire_dh, , EXT_NONE, gen_pack)
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 1665583accf..36b0196a626 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -563,10 +563,8 @@ static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
> return;
> }
>
> - if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
> - cpu->cfg.ext_zbkb)) {
> - error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
> - "extensions");
> + if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb)) {
> + error_setg(errp, "P extension requires zmmul, zba and zbb extensions");
> return;
> }
> }
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 00/18] target/riscv: Add support for RISC-V P
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (17 preceding siblings ...)
2026-07-17 10:07 ` [PATCH v2 18/18] target/riscv: Remove Zbkb dependency from P extension to align with the spec Molly Chen
@ 2026-07-29 8:43 ` Chao Liu
2026-07-29 9:32 ` Chao Liu
19 siblings, 0 replies; 34+ messages in thread
From: Chao Liu @ 2026-07-29 8:43 UTC (permalink / raw)
To: Molly Chen
Cc: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
qemu-riscv, qemu-devel
Hi Molly,
On Fri, Jul 17, 2026 at 10:06:53AM +0800, Molly Chen wrote:
> This series adds support for the RISC-V Packed SIMD (P) extension.
>
> The P extension defines packed-SIMD fixed-point operations intended
> for DSP-style workloads such as multimedia and signal processing.
> These instructions operate on packed subword elements within
> general-purpose registers (GPRs).
>
> The implementation follows the current development draft of the
> specification (v0.20):
>
> https://github.com/riscv/riscv-p-spec/
> or
> https://www.jhauser.us/RISCV/ext-P/
>
> Compared with v1, this version reduces implementation boilerplate by
> defining and reusing helper macros for common patterns in
> trans_rvp.c.inc and psimd_helper.c. It also consolidates the P
> extension prerequisite validation in riscv_cpu_validate_p().
>
> The Zbkb dependency has been removed to align the implementation with
> the current specification. This version also implements the
> specification-defined control of vxsat, which was missing from v1.
>
> All instructions have been functionally tested using the following
> test suite:
>
> https://github.com/mollybuild/qemu-riscv-test-uart
I believe we need to add some TCG test cases for the patches if
the latest compiler supports the P extension, we can add some cases
similar to your repo.
Thanks,
Chao
>
> The implementation focuses on functional correctness and ISA
> coverage. Performance optimizations were not considered at this
> stage.
>
> Feedback on the implementation details would be highly appreciated.
>
> Tested with:
>
> - ninja -C build test
> - make -C build check-qtest-riscv32
> - make -C build check-qtest-riscv64
> - Functional tests for all P extension instructions using
> qemu-riscv-test-uart
>
> No regressions or test failures were observed.
>
> ---
> Changes in v2:
>
> - Refactored trans_rvp.c.inc and psimd_helper.c by defining and
> reusing helper macros for common implementation patterns, reducing
> boilerplate and overall code size.
> - Moved the P extension prerequisite checks into
> riscv_cpu_validate_p().
> - Removed the Zbkb dependency to align with the current
> specification.
> - Added the specification-defined vxsat control mechanism, which was
> missing from v1.
>
> v1:
> https://lists.nongnu.org/archive/html/qemu-riscv/2026-04/msg00301.html
>
> Molly Chen (18):
> 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 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 MAC instructions
> target/riscv: Add packed SIMD four-way MAC 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
>
> 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 | 829 +++++
> 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 | 1389 ++++++++
> target/riscv/tcg/meson.build | 3 +-
> target/riscv/tcg/psimd_helper.c | 3165 +++++++++++++++++++
> target/riscv/tcg/tcg-cpu.c | 46 +
> target/riscv/tcg/translate.c | 6 +
> 13 files changed, 6038 insertions(+), 6 deletions(-)
> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
> create mode 100644 target/riscv/tcg/psimd_helper.c
>
>
> base-commit: 8fb307591625731060d399aca42373c02c7cb040
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 00/18] target/riscv: Add support for RISC-V P
2026-07-17 10:06 [PATCH v2 00/18] target/riscv: Add support for RISC-V P Molly Chen
` (18 preceding siblings ...)
2026-07-29 8:43 ` [PATCH v2 00/18] target/riscv: Add support for RISC-V P Chao Liu
@ 2026-07-29 9:32 ` Chao Liu
2026-08-05 18:36 ` Daniel Henrique Barboza
19 siblings, 1 reply; 34+ messages in thread
From: Chao Liu @ 2026-07-29 9:32 UTC (permalink / raw)
To: Molly Chen
Cc: palmer, alistair.francis, liwei1518, daniel.barboza, zhiwei_liu,
qemu-riscv, qemu-devel
On Fri, Jul 17, 2026 at 10:06:53AM +0800, Molly Chen wrote:
> This series adds support for the RISC-V Packed SIMD (P) extension.
>
> The P extension defines packed-SIMD fixed-point operations intended
> for DSP-style workloads such as multimedia and signal processing.
> These instructions operate on packed subword elements within
> general-purpose registers (GPRs).
>
> The implementation follows the current development draft of the
> specification (v0.20):
>
> https://github.com/riscv/riscv-p-spec/
> or
> https://www.jhauser.us/RISCV/ext-P/
>
> Compared with v1, this version reduces implementation boilerplate by
> defining and reusing helper macros for common patterns in
> trans_rvp.c.inc and psimd_helper.c. It also consolidates the P
> extension prerequisite validation in riscv_cpu_validate_p().
>
> The Zbkb dependency has been removed to align the implementation with
> the current specification. This version also implements the
> specification-defined control of vxsat, which was missing from v1.
>
> All instructions have been functionally tested using the following
> test suite:
>
> https://github.com/mollybuild/qemu-riscv-test-uart
>
> The implementation focuses on functional correctness and ISA
> coverage. Performance optimizations were not considered at this
> stage.
>
> Feedback on the implementation details would be highly appreciated.
>
> Tested with:
>
> - ninja -C build test
> - make -C build check-qtest-riscv32
> - make -C build check-qtest-riscv64
> - Functional tests for all P extension instructions using
> qemu-riscv-test-uart
>
> No regressions or test failures were observed.
>
> ---
> Changes in v2:
>
> - Refactored trans_rvp.c.inc and psimd_helper.c by defining and
> reusing helper macros for common implementation patterns, reducing
> boilerplate and overall code size.
> - Moved the P extension prerequisite checks into
> riscv_cpu_validate_p().
> - Removed the Zbkb dependency to align with the current
> specification.
> - Added the specification-defined vxsat control mechanism, which was
> missing from v1.
>
This patch set is a significant improvement over v1. I think there are still
a few common issues we can address together:
1. The line break characters '\' in the helper macros we defined need to be space-aligned.
2. Every patch is currently missing a commit body.
I think these changes are quite necessary.
Thanks,
Chao
> v1:
> https://lists.nongnu.org/archive/html/qemu-riscv/2026-04/msg00301.html
>
> Molly Chen (18):
> 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 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 MAC instructions
> target/riscv: Add packed SIMD four-way MAC 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
>
> 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 | 829 +++++
> 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 | 1389 ++++++++
> target/riscv/tcg/meson.build | 3 +-
> target/riscv/tcg/psimd_helper.c | 3165 +++++++++++++++++++
> target/riscv/tcg/tcg-cpu.c | 46 +
> target/riscv/tcg/translate.c | 6 +
> 13 files changed, 6038 insertions(+), 6 deletions(-)
> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
> create mode 100644 target/riscv/tcg/psimd_helper.c
>
>
> base-commit: 8fb307591625731060d399aca42373c02c7cb040
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 34+ messages in thread* Re: [PATCH v2 00/18] target/riscv: Add support for RISC-V P
2026-07-29 9:32 ` Chao Liu
@ 2026-08-05 18:36 ` Daniel Henrique Barboza
2026-08-11 7:54 ` MOLLY CHEN
0 siblings, 1 reply; 34+ messages in thread
From: Daniel Henrique Barboza @ 2026-08-05 18:36 UTC (permalink / raw)
To: Chao Liu, Molly Chen
Cc: palmer, alistair.francis, liwei1518, zhiwei_liu, qemu-riscv,
qemu-devel
On 7/29/2026 6:32 AM, Chao Liu wrote:
> On Fri, Jul 17, 2026 at 10:06:53AM +0800, Molly Chen wrote:
>> This series adds support for the RISC-V Packed SIMD (P) extension.
>>
>> The P extension defines packed-SIMD fixed-point operations intended
>> for DSP-style workloads such as multimedia and signal processing.
>> These instructions operate on packed subword elements within
>> general-purpose registers (GPRs).
>>
>> The implementation follows the current development draft of the
>> specification (v0.20):
>>
>> https://github.com/riscv/riscv-p-spec/
>> or
>> https://www.jhauser.us/RISCV/ext-P/
>>
>> Compared with v1, this version reduces implementation boilerplate by
>> defining and reusing helper macros for common patterns in
>> trans_rvp.c.inc and psimd_helper.c. It also consolidates the P
>> extension prerequisite validation in riscv_cpu_validate_p().
>>
>> The Zbkb dependency has been removed to align the implementation with
>> the current specification. This version also implements the
>> specification-defined control of vxsat, which was missing from v1.
>>
>> All instructions have been functionally tested using the following
>> test suite:
>>
>> https://github.com/mollybuild/qemu-riscv-test-uart
>>
>> The implementation focuses on functional correctness and ISA
>> coverage. Performance optimizations were not considered at this
>> stage.
>>
>> Feedback on the implementation details would be highly appreciated.
>>
>> Tested with:
>>
>> - ninja -C build test
>> - make -C build check-qtest-riscv32
>> - make -C build check-qtest-riscv64
>> - Functional tests for all P extension instructions using
>> qemu-riscv-test-uart
>>
>> No regressions or test failures were observed.
>>
>> ---
>> Changes in v2:
>>
>> - Refactored trans_rvp.c.inc and psimd_helper.c by defining and
>> reusing helper macros for common implementation patterns, reducing
>> boilerplate and overall code size.
>> - Moved the P extension prerequisite checks into
>> riscv_cpu_validate_p().
>> - Removed the Zbkb dependency to align with the current
>> specification.
>> - Added the specification-defined vxsat control mechanism, which was
>> missing from v1.
>>
> This patch set is a significant improvement over v1. I think there are still
> a few common issues we can address together:
v2 is a huge improvement indeed. v1 had 11k lines, v2 cut those by half due to
the smart use of helpers.
>
> 1. The line break characters '\' in the helper macros we defined need to be space-aligned.
> 2. Every patch is currently missing a commit body.
>
> I think these changes are quite necessary.
Yeah, having a commit message allows us to make fewer guesses when reviewing code.
E.g. the usage of __int128t__ macros and the choice of some rounding formulas. We
can make review assumptions and hope all is fine, but it's not ideal.
And, as Chao mentioned in his other reply, having test cases will be helpful to
assert that everything being added here is sane. In particular with the amount
of lines we're adding here.
Cheers,
Daniel
>
> Thanks,
> Chao
>> v1:
>> https://lists.nongnu.org/archive/html/qemu-riscv/2026-04/msg00301.html
>>
>> Molly Chen (18):
>> 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 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 MAC instructions
>> target/riscv: Add packed SIMD four-way MAC 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
>>
>> 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 | 829 +++++
>> 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 | 1389 ++++++++
>> target/riscv/tcg/meson.build | 3 +-
>> target/riscv/tcg/psimd_helper.c | 3165 +++++++++++++++++++
>> target/riscv/tcg/tcg-cpu.c | 46 +
>> target/riscv/tcg/translate.c | 6 +
>> 13 files changed, 6038 insertions(+), 6 deletions(-)
>> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
>> create mode 100644 target/riscv/tcg/psimd_helper.c
>>
>>
>> base-commit: 8fb307591625731060d399aca42373c02c7cb040
>> --
>> 2.34.1
>>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v2 00/18] target/riscv: Add support for RISC-V P
2026-08-05 18:36 ` Daniel Henrique Barboza
@ 2026-08-11 7:54 ` MOLLY CHEN
0 siblings, 0 replies; 34+ messages in thread
From: MOLLY CHEN @ 2026-08-11 7:54 UTC (permalink / raw)
To: Daniel Henrique Barboza, Chao Liu, nutty.liu
Cc: palmer, alistair.francis, liwei1518, zhiwei_liu, qemu-riscv,
qemu-devel
[-- Attachment #1: Type: text/plain, Size: 6650 bytes --]
Thanks Daniel,Chao and Nutty for the review.
I’ll address these issues in v3 by:
* adding a descriptive commit body to each patch and comments
for functions that need further explanation;
* aligning the continuation backslashes in the helper macros;
* reusing the existing |EXTRACT*|definitions in patch 02/18 instead of
introducing duplicate definitions; and
* investigating the addition of P-extension test cases to the QEMU TCG
test suite, depending on the available toolchain support.
I’ll also document these changes in the v3 cover letter.
Best regards,
Molly
在 2026/8/6 2:36, Daniel Henrique Barboza 写道:
>
>
> On 7/29/2026 6:32 AM, Chao Liu wrote:
>> On Fri, Jul 17, 2026 at 10:06:53AM +0800, Molly Chen wrote:
>>> This series adds support for the RISC-V Packed SIMD (P) extension.
>>>
>>> The P extension defines packed-SIMD fixed-point operations intended
>>> for DSP-style workloads such as multimedia and signal processing.
>>> These instructions operate on packed subword elements within
>>> general-purpose registers (GPRs).
>>>
>>> The implementation follows the current development draft of the
>>> specification (v0.20):
>>>
>>> https://github.com/riscv/riscv-p-spec/
>>> or
>>> https://www.jhauser.us/RISCV/ext-P/
>>>
>>> Compared with v1, this version reduces implementation boilerplate by
>>> defining and reusing helper macros for common patterns in
>>> trans_rvp.c.inc and psimd_helper.c. It also consolidates the P
>>> extension prerequisite validation in riscv_cpu_validate_p().
>>>
>>> The Zbkb dependency has been removed to align the implementation with
>>> the current specification. This version also implements the
>>> specification-defined control of vxsat, which was missing from v1.
>>>
>>> All instructions have been functionally tested using the following
>>> test suite:
>>>
>>> https://github.com/mollybuild/qemu-riscv-test-uart
>>>
>>> The implementation focuses on functional correctness and ISA
>>> coverage. Performance optimizations were not considered at this
>>> stage.
>>>
>>> Feedback on the implementation details would be highly appreciated.
>>>
>>> Tested with:
>>>
>>> - ninja -C build test
>>> - make -C build check-qtest-riscv32
>>> - make -C build check-qtest-riscv64
>>> - Functional tests for all P extension instructions using
>>> qemu-riscv-test-uart
>>>
>>> No regressions or test failures were observed.
>>>
>>> ---
>>> Changes in v2:
>>>
>>> - Refactored trans_rvp.c.inc and psimd_helper.c by defining and
>>> reusing helper macros for common implementation patterns, reducing
>>> boilerplate and overall code size.
>>> - Moved the P extension prerequisite checks into
>>> riscv_cpu_validate_p().
>>> - Removed the Zbkb dependency to align with the current
>>> specification.
>>> - Added the specification-defined vxsat control mechanism, which was
>>> missing from v1.
>>>
>> This patch set is a significant improvement over v1. I think there
>> are still
>> a few common issues we can address together:
>
> v2 is a huge improvement indeed. v1 had 11k lines, v2 cut those by
> half due to
> the smart use of helpers.
>
>>
>> 1. The line break characters '\' in the helper macros we defined need
>> to be space-aligned.
>> 2. Every patch is currently missing a commit body.
>>
>> I think these changes are quite necessary.
>
> Yeah, having a commit message allows us to make fewer guesses when
> reviewing code.
> E.g. the usage of __int128t__ macros and the choice of some rounding
> formulas. We
> can make review assumptions and hope all is fine, but it's not ideal.
>
> And, as Chao mentioned in his other reply, having test cases will be
> helpful to
> assert that everything being added here is sane. In particular with
> the amount
> of lines we're adding here.
>
>
> Cheers,
> Daniel
>
>>
>> Thanks,
>> Chao
>>> v1:
>>> https://lists.nongnu.org/archive/html/qemu-riscv/2026-04/msg00301.html
>>>
>>> Molly Chen (18):
>>> 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 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 MAC instructions
>>> target/riscv: Add packed SIMD four-way MAC 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
>>>
>>> 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 | 829 +++++
>>> 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 | 1389 ++++++++
>>> target/riscv/tcg/meson.build | 3 +-
>>> target/riscv/tcg/psimd_helper.c | 3165
>>> +++++++++++++++++++
>>> target/riscv/tcg/tcg-cpu.c | 46 +
>>> target/riscv/tcg/translate.c | 6 +
>>> 13 files changed, 6038 insertions(+), 6 deletions(-)
>>> create mode 100644 target/riscv/tcg/insn_trans/trans_rvp.c.inc
>>> create mode 100644 target/riscv/tcg/psimd_helper.c
>>>
>>>
>>> base-commit: 8fb307591625731060d399aca42373c02c7cb040
>>> --
>>> 2.34.1
>>>
[-- Attachment #2: Type: text/html, Size: 10969 bytes --]
^ permalink raw reply [flat|nested] 34+ messages in thread