get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2224359/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2224359,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2224359/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260417104652.17857-3-xiaoou@iscas.ac.cn/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260417104652.17857-3-xiaoou@iscas.ac.cn>",
    "list_archive_url": null,
    "date": "2026-04-17T10:46:39",
    "name": "[02/14] target/riscv: rvp: add arithmetic instructions, including saturating and non-saturating operations",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "cb3b9a6352170c88dc5c813076ebd47fe39c1272",
    "submitter": {
        "id": 89843,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/89843/?format=api",
        "name": "Molly Chen",
        "email": "xiaoou@iscas.ac.cn"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260417104652.17857-3-xiaoou@iscas.ac.cn/mbox/",
    "series": [
        {
            "id": 500307,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/500307/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=500307",
            "date": "2026-04-17T10:46:37",
            "name": "target/riscv: add support for RISC-V P extension (v0.20 draft)",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/500307/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2224359/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2224359/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)",
        "Received": [
            "from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fxs6T3lDZz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 20:48:01 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wDgjG-00012H-Od; Fri, 17 Apr 2026 06:47:18 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <xiaoou@iscas.ac.cn>)\n id 1wDgjF-000121-Jp; Fri, 17 Apr 2026 06:47:17 -0400",
            "from smtp21.cstnet.cn ([159.226.251.21] helo=cstnet.cn)\n by eggs.gnu.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256)\n (Exim 4.90_1) (envelope-from <xiaoou@iscas.ac.cn>)\n id 1wDgjA-0007ub-Jw; Fri, 17 Apr 2026 06:47:17 -0400",
            "from Huawei.localdomain (unknown [36.110.52.2])\n by APP-01 (Coremail) with SMTP id qwCowAB3H2ulD+JpLDmSDQ--.804S4;\n Fri, 17 Apr 2026 18:47:07 +0800 (CST)"
        ],
        "From": "Molly Chen <xiaoou@iscas.ac.cn>",
        "To": "palmer@dabbelt.com, alistair.francis@wdc.com, liwei1518@gmail.com,\n daniel.barboza@oss.qualcomm.com, zhiwei_liu@linux.alibaba.com,\n chao.liu.zevorn@gmail.com",
        "Cc": "xiaoou@iscas.ac.cn,\n\tqemu-riscv@nongnu.org,\n\tqemu-devel@nongnu.org",
        "Subject": "[PATCH 02/14] target/riscv: rvp: add arithmetic instructions,\n including saturating and non-saturating operations",
        "Date": "Fri, 17 Apr 2026 18:46:39 +0800",
        "Message-Id": "<20260417104652.17857-3-xiaoou@iscas.ac.cn>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20260417104652.17857-1-xiaoou@iscas.ac.cn>",
        "References": "<20260417104652.17857-1-xiaoou@iscas.ac.cn>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-CM-TRANSID": "qwCowAB3H2ulD+JpLDmSDQ--.804S4",
        "X-Coremail-Antispam": "1UD129KBjvAXoWDGryrZryDtFyfXryrCr43GFg_yoWrtF13Wo\n W7Gw4rAr1xJr13u3s3uw48XFWDZFW29a1kJr4F9r4Duas7Wr1xKr1UJwn5Za1rJr45KrWf\n XFZaqFn8Jas3Cr9rn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3\n AaLaJ3UjIYCTnIWjp_UUUYM7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva\n j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r15M28IrcIa0x\n kI8VCY1x0267AKxVW8JVW5JwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC\n jcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJw\n A2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS\n 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2\n IY67AKxVWUXVWUAwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0\n Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY1x0262kKe7AKxVWUtVW8Zw\n CF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j\n 6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64\n vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_\n Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0x\n vEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUYJmUUUUUU=",
        "X-Originating-IP": "[36.110.52.2]",
        "X-CM-SenderInfo": "50ld003x6l2u1dvotugofq/",
        "Received-SPF": "pass client-ip=159.226.251.21; envelope-from=xiaoou@iscas.ac.cn;\n helo=cstnet.cn",
        "X-Spam_score_int": "-21",
        "X-Spam_score": "-2.2",
        "X-Spam_bar": "--",
        "X-Spam_report": "(-2.2 / 5.0 requ) BAYES_00=-1.9, HK_RANDOM_ENVFROM=0.998,\n HK_RANDOM_FROM=0.998, RCVD_IN_DNSWL_MED=-2.3,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no",
        "X-Spam_action": "no action",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "qemu development <qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "Signed-off-by: Molly Chen <xiaoou@iscas.ac.cn>\n---\n target/riscv/helper.h                   |   40 +\n target/riscv/insn32.decode              |   65 ++\n target/riscv/insn_trans/trans_rvp.c.inc |  564 ++++++++++++\n target/riscv/meson.build                |    3 +-\n target/riscv/psimd_helper.c             | 1069 +++++++++++++++++++++++\n target/riscv/translate.c                |    1 +\n 6 files changed, 1741 insertions(+), 1 deletion(-)\n create mode 100644 target/riscv/insn_trans/trans_rvp.c.inc\n create mode 100644 target/riscv/psimd_helper.c",
    "diff": "diff --git a/target/riscv/helper.h b/target/riscv/helper.h\nindex 54d2331966..76bc6583fb 100644\n--- a/target/riscv/helper.h\n+++ b/target/riscv/helper.h\n@@ -1351,3 +1351,43 @@ DEF_HELPER_4(vsm4r_vs, void, ptr, ptr, env, i32)\n #ifndef CONFIG_USER_ONLY\n DEF_HELPER_1(ssamoswap_disabled, void, env)\n #endif\n+\n+/* Packed SIMD */\n+DEF_HELPER_3(padd_b, tl, env, tl, tl)\n+DEF_HELPER_3(padd_h, tl, env, tl, tl)\n+DEF_HELPER_3(padd_w, i64, env, i64, i64)\n+DEF_HELPER_3(padd_bs, tl, env, tl, tl)\n+DEF_HELPER_3(padd_hs, tl, env, tl, tl)\n+DEF_HELPER_3(padd_ws, i64, env, i64, i64)\n+DEF_HELPER_3(psub_b, tl, env, tl, tl)\n+DEF_HELPER_3(psub_h, tl, env, tl, tl)\n+DEF_HELPER_3(psub_w, i64, env, i64, i64)\n+DEF_HELPER_3(psh1add_h, tl, env, tl, tl)\n+DEF_HELPER_3(psh1add_w, i64, env, i64, i64)\n+DEF_HELPER_3(pssh1sadd_h, tl, env, tl, tl)\n+DEF_HELPER_3(pssh1sadd_w, i64, env, i64, i64)\n+DEF_HELPER_3(ssh1sadd, i32, env, i32, i32)\n+DEF_HELPER_3(psadd_b, tl, env, tl, tl)\n+DEF_HELPER_3(psadd_h, tl, env, tl, tl)\n+DEF_HELPER_3(psadd_w, i64, env, i64, i64)\n+DEF_HELPER_3(psaddu_b, tl, env, tl, tl)\n+DEF_HELPER_3(psaddu_h, tl, env, tl, tl)\n+DEF_HELPER_3(psaddu_w, i64, env, i64, i64)\n+DEF_HELPER_3(sadd, i32, env, i32, i32)\n+DEF_HELPER_3(saddu, i32, env, i32, i32)\n+DEF_HELPER_3(pssub_b, tl, env, tl, tl)\n+DEF_HELPER_3(pssub_h, tl, env, tl, tl)\n+DEF_HELPER_3(pssub_w, i64, env, i64, i64)\n+DEF_HELPER_3(pssubu_b, tl, env, tl, tl)\n+DEF_HELPER_3(pssubu_h, tl, env, tl, tl)\n+DEF_HELPER_3(pssubu_w, i64, env, i64, i64)\n+DEF_HELPER_3(ssub, i32, env, i32, i32)\n+DEF_HELPER_3(ssubu, i32, env, i32, i32)\n+DEF_HELPER_3(psati_h, tl, env, tl, tl)\n+DEF_HELPER_3(pusati_h, tl, env, tl, tl)\n+DEF_HELPER_3(psati_w, i64, env, i64, i64)\n+DEF_HELPER_3(pusati_w, i64, env, i64, i64)\n+DEF_HELPER_3(sati_32, i32, env, i32, i32)\n+DEF_HELPER_3(usati_32, i32, env, i32, i32)\n+DEF_HELPER_3(sati_64, i64, env, i64, i64)\n+DEF_HELPER_3(usati_64, i64, env, i64, i64)\ndiff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode\nindex 6e35c4b1e6..6043eb39cf 100644\n--- a/target/riscv/insn32.decode\n+++ b/target/riscv/insn32.decode\n@@ -40,6 +40,9 @@\n %imm_z6   26:1 15:5\n %imm_mop5 30:1 26:2 20:2\n %imm_mop3 30:1 26:2\n+%imm_p_ui16 20:4\n+%imm_p_ui32 20:5\n+%imm_p_ui64 20:6\n \n # Argument sets:\n &empty\n@@ -105,6 +108,10 @@\n @mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1\n @mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2\n \n+@p_ui16 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui16 %rs1 %rd\n+@p_ui32 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui32 %rs1 %rd\n+@p_ui64 ..... .... ... ..... ... ..... ....... &i imm=%imm_p_ui64 %rs1 %rd\n+\n # Formats 64:\n @sh5     .......  ..... .....  ... ..... ....... &shift  shamt=%sh5      %rs1 %rd\n \n@@ -1084,3 +1091,61 @@ sb_aqrl  00111 . . ..... ..... 000 ..... 0101111 @atom_st\n sh_aqrl  00111 . . ..... ..... 001 ..... 0101111 @atom_st\n sw_aqrl  00111 . . ..... ..... 010 ..... 0101111 @atom_st\n sd_aqrl  00111 . . ..... ..... 011 ..... 0101111 @atom_st\n+\n+\n+# *** P Experimental Extension Version v018 ***\n+# Arithmetic Operations(Non-Saturating and Saturating)\n+padd_b     1000010 ..... ..... 000 ..... 0111011 @r\n+padd_h     1000000 ..... ..... 000 ..... 0111011 @r\n+padd_w     1000001 ..... ..... 000 ..... 0111011 @r\n+padd_bs    1001110 ..... ..... 010 ..... 0011011 @r\n+padd_hs    1001100 ..... ..... 010 ..... 0011011 @r\n+padd_ws    1001101 ..... ..... 010 ..... 0011011 @r\n+psub_b     1100010 ..... ..... 000 ..... 0111011 @r\n+psub_h     1100000 ..... ..... 000 ..... 0111011 @r\n+psub_w     1100001 ..... ..... 000 ..... 0111011 @r\n+psh1add_h  1010000 ..... ..... 010 ..... 0111011 @r\n+psh1add_w  1010001 ..... ..... 010 ..... 0111011 @r\n+pssh1sadd_h   1011000 ..... ..... 010 ..... 0111011 @r\n+{\n+  ssh1sadd    1011001 ..... ..... 010 ..... 0111011 @r\n+  pssh1sadd_w 1011001 ..... ..... 010 ..... 0111011 @r\n+}\n+psadd_b    1001010 ..... ..... 000 ..... 0111011 @r\n+psadd_h    1001000 ..... ..... 000 ..... 0111011 @r\n+{\n+  sadd     1001001 ..... ..... 000 ..... 0111011 @r\n+  psadd_w  1001001 ..... ..... 000 ..... 0111011 @r\n+}\n+psaddu_b   1011010 ..... ..... 000 ..... 0111011 @r\n+psaddu_h   1011000 ..... ..... 000 ..... 0111011 @r\n+{\n+  saddu    1011001 ..... ..... 000 ..... 0111011 @r\n+  psaddu_w 1011001 ..... ..... 000 ..... 0111011 @r\n+}\n+pssub_b    1101010 ..... ..... 000 ..... 0111011 @r\n+pssub_h    1101000 ..... ..... 000 ..... 0111011 @r\n+{\n+  ssub     1101001 ..... ..... 000 ..... 0111011 @r\n+  pssub_w  1101001 ..... ..... 000 ..... 0111011 @r\n+}\n+pssubu_b   1111010 ..... ..... 000 ..... 0111011 @r\n+pssubu_h   1111000 ..... ..... 000 ..... 0111011 @r\n+{\n+  ssubu      1111001 ..... ..... 000 ..... 0111011 @r\n+  pssubu_w   1111001 ..... ..... 000 ..... 0111011 @r\n+}\n+psati_h    11100 001.... ..... 100 ..... 0011011 @p_ui16\n+pusati_h   10100 001.... ..... 100 ..... 0011011 @p_ui16\n+{\n+  sati_32    11100 01..... ..... 100 ..... 0011011 @p_ui32\n+  psati_w      11100 01..... ..... 100 ..... 0011011 @p_ui32\n+}\n+{\n+  usati_32   10100 01..... ..... 100 ..... 0011011 @p_ui32\n+  pusati_w     10100 01..... ..... 100 ..... 0011011 @p_ui32\n+}\n+\n+sati_64    111001 ...... ..... 100 ..... 0011011 @p_ui64\n+usati_64   101001 ...... ..... 100 ..... 0011011 @p_ui64\n+\ndiff --git a/target/riscv/insn_trans/trans_rvp.c.inc b/target/riscv/insn_trans/trans_rvp.c.inc\nnew file mode 100644\nindex 0000000000..6f7246b563\n--- /dev/null\n+++ b/target/riscv/insn_trans/trans_rvp.c.inc\n@@ -0,0 +1,564 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/* RISC-V translation routines for the P Standard Extensions. */\n+/* Copyright (c) 2026 ISRC ISCAS. */\n+\n+#define GEN_SIMD_TRANS(NAME)                                \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+   REQUIRE_EXT(ctx, RVP);                                   \\\n+   TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);              \\\n+   TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);              \\\n+   TCGv dest = dest_gpr(ctx, a->rd);                        \\\n+   gen_helper_##NAME(dest, tcg_env, src1, src2);            \\\n+   return true;                                             \\\n+}\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_32(NAME)                             \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a)  \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1, src2);           \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_32(NAME)                             \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a)  \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_64(NAME)                             \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a)  \\\n+{                                                           \\\n+   REQUIRE_64BIT(ctx);                                      \\\n+   return true;                                             \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_64(NAME)                             \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a)  \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1, src2);           \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#define GEN_SIMD_TRANS_ACC(NAME)                            \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    TCGv t = tcg_temp_new();                                \\\n+    gen_helper_##NAME(t, tcg_env, src1, src2, dest);        \\\n+    gen_set_gpr(ctx, a->rd, t);                             \\\n+    return true;                                            \\\n+}\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_ACC_32(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    TCGv t = tcg_temp_new();                                \\\n+    gen_helper_##NAME(t, tcg_env, src1, src2, dest);        \\\n+    gen_set_gpr(ctx, a->rd, t);                             \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_ACC_32(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_ACC_64(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_ACC_64(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    TCGv t = tcg_temp_new();                                \\\n+    gen_helper_##NAME(t, tcg_env, src1, src2, dest);        \\\n+    gen_set_gpr(ctx, a->rd, t);                             \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#define GEN_SIMD_TRANS_R1(NAME)                             \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1);                 \\\n+    gen_set_gpr(ctx, a->rd, dest);                          \\\n+    return true;                                            \\\n+}\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_R1_64(NAME)                          \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_R1_64(NAME)                          \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1);                 \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#define GEN_SIMD_TRANS_IMM(NAME)                            \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv imm = tcg_constant_tl(a->imm);                     \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1, imm);            \\\n+    return true;                                            \\\n+}\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_IMM_32(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                   \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv imm = tcg_constant_tl(a->imm);                     \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1, imm);            \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_IMM_32(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_IMM_64(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_IMM_64(NAME)                         \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_64BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                   \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv imm = tcg_constant_tl(a->imm);                     \\\n+    TCGv dest = dest_gpr(ctx, a->rd);                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1, imm);            \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_1(NAME)                     \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv_i32 src1 = get_gpr(ctx, a->rs1, EXT_NONE);         \\\n+    TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE);         \\\n+    TCGv_i64 t = tcg_temp_new_i64();                        \\\n+    gen_helper_##NAME(t, tcg_env, src1, src2);              \\\n+    set_pair_regs(ctx, (a->rd) * 2, t);                       \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_1(NAME)                     \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_2(INSN, HELPER)                \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)    \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    REQUIRE_EXT(ctx, RVP);                                     \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);          \\\n+    TCGv src2_0 = get_gpr(ctx, (a->rs2) * 2, EXT_NONE);          \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                    \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);        \\\n+    TCGv src2_1 = get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE);        \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                  \\\n+    gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2_0);      \\\n+    gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2_1);      \\\n+    return true;                                               \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_2(INSN, HELPER)                \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)    \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    return true;                                               \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_3(INSN, HELPER)                \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)    \\\n+{                                                              \\\n+    REQUIRE_EXT(ctx, RVP);                                     \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);          \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                    \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);        \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                  \\\n+    TCGv src2   = get_gpr(ctx, a->rs2, EXT_NONE);              \\\n+    gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2);        \\\n+    gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2);        \\\n+    return true;                                               \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_3(INSN, HELPER)                \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)    \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    return true;                                               \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_DW(INSN, HELPER)               \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)     \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    REQUIRE_EXT(ctx, RVP);                                     \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);          \\\n+    TCGv src2_0 = get_gpr(ctx, (a->rs2) * 2, EXT_NONE);          \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                    \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);        \\\n+    TCGv src2_1 = get_gpr(ctx, (a->rs2) * 2 + 1, EXT_NONE);        \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                  \\\n+    gen_helper_##HELPER(dest_0, tcg_env, src1_0, src2_0);      \\\n+    gen_helper_##HELPER(dest_1, tcg_env, src1_1, src2_1);      \\\n+    return true;                                               \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_DW(INSN, HELPER)               \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)     \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    return true;                                               \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_DW_IMM(INSN, HELPER)           \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)     \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    REQUIRE_EXT(ctx, RVP);                                     \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);          \\\n+    TCGv imm_0 = tcg_constant_tl(a->imm);                      \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                    \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);        \\\n+    TCGv imm_1 = tcg_constant_tl(a->imm);                      \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                  \\\n+    gen_helper_##HELPER(dest_0, tcg_env, src1_0, imm_0);       \\\n+    gen_helper_##HELPER(dest_1, tcg_env, src1_1, imm_1);       \\\n+    return true;                                               \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_DW_IMM(INSN, HELPER)           \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)     \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    return true;                                               \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_DW_IMM_2(INSN, HELPER)         \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)     \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    REQUIRE_EXT(ctx, RVP);                                     \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);          \\\n+    TCGv imm_0 = tcg_constant_tl(a->imm);                      \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                    \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);        \\\n+    TCGv imm_1 = tcg_constant_tl(a->imm);                      \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                  \\\n+    gen_helper_##HELPER##_32(dest_0, tcg_env, src1_0, imm_0);  \\\n+    gen_helper_##HELPER##_32(dest_1, tcg_env, src1_1, imm_1);  \\\n+    return true;                                               \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_DW_IMM_2(INSN, HELPER)         \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)     \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    return true;                                               \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_5(INSN, HELPER)                \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)    \\\n+{                                                              \\\n+    REQUIRE_EXT(ctx, RVP);                                     \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);          \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                    \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);        \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                  \\\n+    gen_helper_##HELPER(dest_0, tcg_env, src1_0);              \\\n+    gen_helper_##HELPER(dest_1, tcg_env, src1_1);              \\\n+    gen_set_gpr(ctx, (a->rd) * 2, dest_0);                       \\\n+    gen_set_gpr(ctx, (a->rd) * 2 + 1, dest_1);                     \\\n+    return true;                                               \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_5(INSN, HELPER)                \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)    \\\n+{                                                              \\\n+    REQUIRE_32BIT(ctx);                                        \\\n+    return true;                                               \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_IMM(NAME)                   \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv_i32 imm = tcg_constant_i32(a->imm);                \\\n+    TCGv_i64 t = tcg_temp_new_i64();                        \\\n+    gen_helper_##NAME(t, tcg_env, src1, imm);               \\\n+    set_pair_regs(ctx, (a->rd) * 2, t);                       \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_IMM(NAME)                   \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_IMM_2(INSN, HELPER)          \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)  \\\n+{                                                            \\\n+    REQUIRE_32BIT(ctx);                                      \\\n+    REQUIRE_EXT(ctx, RVP);                                   \\\n+    TCGv src1_0 = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);        \\\n+    TCGv imm_0 = tcg_constant_tl(a->imm);                    \\\n+    TCGv dest_0 = dest_gpr(ctx, (a->rd) * 2);                  \\\n+    TCGv src1_1 = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);      \\\n+    TCGv imm_1 = tcg_constant_tl(a->imm);                    \\\n+    TCGv dest_1 = dest_gpr(ctx, (a->rd) * 2 + 1);                \\\n+    gen_helper_##HELPER(dest_0, tcg_env, src1_0, imm_0);     \\\n+    gen_helper_##HELPER(dest_1, tcg_env, src1_1, imm_1);     \\\n+    return true;                                             \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_IMM_2(INSN, HELPER)          \\\n+static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a)  \\\n+{                                                            \\\n+    REQUIRE_32BIT(ctx);                                      \\\n+    return true;                                             \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_ACC_REG_PAIR_1(NAME)                 \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);             \\\n+    TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);             \\\n+    TCGv_i64 t = tcg_temp_new_i64();                        \\\n+    if (a->rd == 0) {                                         \\\n+        tcg_gen_movi_i64(t, 0);                             \\\n+    } else {                                                  \\\n+        get_pair_regs(ctx, t, (a->rd) * 2);                   \\\n+    }                                                       \\\n+    gen_helper_##NAME(t, tcg_env, src1, src2, t);           \\\n+    set_pair_regs(ctx, (a->rd) * 2, t);                       \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_ACC_REG_PAIR_1(NAME)                 \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME)               \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    REQUIRE_EXT(ctx, RVP);                                  \\\n+    TCGv_i32 src1_l;                                        \\\n+    TCGv_i32 src1_h;                                        \\\n+    TCGv_i32 src2 = get_gpr(ctx, a->rs2, EXT_NONE);         \\\n+    TCGv_i32 dest = dest_gpr(ctx, a->rd);                   \\\n+    if (a->rs1 == 0) {                                        \\\n+        src1_l = tcg_temp_new_i32();                        \\\n+        src1_h = tcg_temp_new_i32();                        \\\n+        tcg_gen_movi_i32(src1_l, 0);                        \\\n+        tcg_gen_movi_i32(src1_h, 0);                        \\\n+    } else {                                                  \\\n+        src1_l = get_gpr(ctx, (a->rs1) * 2, EXT_NONE);        \\\n+        src1_h = get_gpr(ctx, (a->rs1) * 2 + 1, EXT_NONE);      \\\n+    }                                                       \\\n+    gen_helper_##NAME(dest, tcg_env, src1_l, src1_h, src2); \\\n+    return true;                                            \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_REG_PAIR_PREDSUM(NAME)               \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                           \\\n+    REQUIRE_32BIT(ctx);                                     \\\n+    return true;                                            \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_PN_OP_IMM(NAME)                     \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                          \\\n+    REQUIRE_32BIT(ctx);                                    \\\n+    REQUIRE_EXT(ctx, RVP);                                 \\\n+    TCGv_i64 s1 = tcg_temp_new_i64();                      \\\n+    if (a->rs1 == 0) {                                     \\\n+        tcg_gen_mov_i64(s1, 0);                            \\\n+    } else {                                               \\\n+        get_pair_regs(ctx, s1, a->rs1 * 2);                \\\n+    }                                                      \\\n+    TCGv shamt = tcg_constant_tl(a->imm);                  \\\n+    TCGv_i32 dest = dest_gpr(ctx, a->rd);                  \\\n+    gen_helper_##NAME(dest, tcg_env, s1, shamt);           \\\n+    return true;                                           \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_PN_OP_IMM(NAME)                     \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                          \\\n+    REQUIRE_32BIT(ctx);                                    \\\n+    return true;                                           \\\n+}\n+#endif\n+\n+#if defined(TARGET_RISCV32)\n+#define GEN_SIMD_TRANS_PN_OP_REG(NAME)                     \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                          \\\n+    REQUIRE_32BIT(ctx);                                    \\\n+    REQUIRE_EXT(ctx, RVP);                                 \\\n+    TCGv_i64 s1 = tcg_temp_new_i64();                      \\\n+    if (a->rs1 == 0) {                                     \\\n+        tcg_gen_mov_i64(s1, 0);                            \\\n+    } else {                                               \\\n+        get_pair_regs(ctx, s1, a->rs1 * 2);                \\\n+    }                                                      \\\n+    TCGv_i32 rs2 = get_gpr(ctx, a->rs2, EXT_NONE);         \\\n+    TCGv_i32 dest = dest_gpr(ctx, a->rd);                  \\\n+    gen_helper_##NAME(dest, tcg_env, s1, rs2);             \\\n+    return true;                                           \\\n+}\n+#else\n+#define GEN_SIMD_TRANS_PN_OP_REG(NAME)                     \\\n+static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \\\n+{                                                          \\\n+    REQUIRE_32BIT(ctx);                                    \\\n+    return true;                                           \\\n+}\n+#endif\n+\n+GEN_SIMD_TRANS(padd_b)\n+GEN_SIMD_TRANS(padd_h)\n+GEN_SIMD_TRANS_64(padd_w)\n+GEN_SIMD_TRANS(padd_bs)\n+GEN_SIMD_TRANS(padd_hs)\n+GEN_SIMD_TRANS_64(padd_ws)\n+GEN_SIMD_TRANS(psub_b)\n+GEN_SIMD_TRANS(psub_h)\n+GEN_SIMD_TRANS_64(psub_w)\n+GEN_SIMD_TRANS(psh1add_h)\n+GEN_SIMD_TRANS_64(psh1add_w)\n+GEN_SIMD_TRANS(pssh1sadd_h)\n+GEN_SIMD_TRANS_64(pssh1sadd_w)\n+GEN_SIMD_TRANS_32(ssh1sadd)\n+GEN_SIMD_TRANS(psadd_b)\n+GEN_SIMD_TRANS(psadd_h)\n+GEN_SIMD_TRANS_64(psadd_w)\n+GEN_SIMD_TRANS(psaddu_b)\n+GEN_SIMD_TRANS(psaddu_h)\n+GEN_SIMD_TRANS_64(psaddu_w)\n+GEN_SIMD_TRANS_32(sadd)\n+GEN_SIMD_TRANS_32(saddu)\n+GEN_SIMD_TRANS(pssub_b)\n+GEN_SIMD_TRANS(pssub_h)\n+GEN_SIMD_TRANS_64(pssub_w)\n+GEN_SIMD_TRANS(pssubu_b)\n+GEN_SIMD_TRANS(pssubu_h)\n+GEN_SIMD_TRANS_64(pssubu_w)\n+GEN_SIMD_TRANS_32(ssub)\n+GEN_SIMD_TRANS_32(ssubu)\n+GEN_SIMD_TRANS_IMM(psati_h)\n+GEN_SIMD_TRANS_IMM(pusati_h)\n+GEN_SIMD_TRANS_IMM_64(psati_w)\n+GEN_SIMD_TRANS_IMM_64(pusati_w)\n+GEN_SIMD_TRANS_IMM_32(sati_32)\n+GEN_SIMD_TRANS_IMM_32(usati_32)\n+GEN_SIMD_TRANS_IMM_64(sati_64)\n+GEN_SIMD_TRANS_IMM_64(usati_64)\ndiff --git a/target/riscv/meson.build b/target/riscv/meson.build\nindex 79f36abd63..45ed7f8d8a 100644\n--- a/target/riscv/meson.build\n+++ b/target/riscv/meson.build\n@@ -28,7 +28,8 @@ riscv_ss.add(files(\n   'm128_helper.c',\n   'crypto_helper.c',\n   'zce_helper.c',\n-  'vcrypto_helper.c'\n+  'vcrypto_helper.c',\n+  'psimd_helper.c'\n ))\n \n riscv_system_ss = ss.source_set()\ndiff --git a/target/riscv/psimd_helper.c b/target/riscv/psimd_helper.c\nnew file mode 100644\nindex 0000000000..a754ee3b5e\n--- /dev/null\n+++ b/target/riscv/psimd_helper.c\n@@ -0,0 +1,1069 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/* RISC-V Packed SIMD Extension Helpers for QEMU. */\n+/* Copyright (C) 2026 ISRC ISCAS. */\n+\n+#include \"qemu/osdep.h\"\n+#include \"cpu.h\"\n+#include \"qemu/host-utils.h\"\n+#include \"exec/helper-proto.h\"\n+#include \"fpu/softfloat.h\"\n+#include \"internals.h\"\n+\n+\n+/* Helper macros */\n+\n+/* Element count calculations */\n+#define ELEMS_B(target) (sizeof(target) * 8 / 8)    /* byte elements count */\n+#define ELEMS_H(target) (sizeof(target) * 8 / 16)\n+#define ELEMS_W(target) (sizeof(target) * 8 / 32)   /* word elements count */\n+\n+/* Element extraction macros - unsigned to avoid sign extension */\n+#define EXTRACT8(val, idx)  (((val) >> ((idx) * 8)) & 0xFF)\n+#define EXTRACT16(val, idx) (((val) >> ((idx) * 16)) & 0xFFFF)\n+#define EXTRACT32(val, idx) (((val) >> ((idx) * 32)) & 0xFFFFFFFF)\n+\n+/* Element insertion macros */\n+#define INSERT8(val, res, idx) \\\n+    ((val) | ((target_ulong)(uint8_t)(res) << ((idx) * 8)))\n+#define INSERT16(val, res, idx) \\\n+    ((val) | ((target_ulong)(uint16_t)(res) << ((idx) * 16)))\n+#define INSERT32(val, res, idx) \\\n+    ((val) | ((target_ulong)(uint32_t)(res) << ((idx) * 32)))\n+\n+/* Saturation constants */\n+static const int8_t   SAT_MAX_B = 127;\n+static const int8_t   SAT_MIN_B = -128;\n+static const int16_t  SAT_MAX_H = 32767;\n+static const int16_t  SAT_MIN_H = -32768;\n+static const int32_t  SAT_MAX_W = 2147483647;\n+static const int32_t  SAT_MIN_W = -2147483648LL;\n+static const uint8_t  USAT_MAX_B = 255;\n+static const uint16_t USAT_MAX_H = 65535;\n+static const uint32_t USAT_MAX_W = 4294967295U;\n+\n+\n+/* Saturation helper functions */\n+\n+/**\n+ * Signed saturation for 8-bit elements\n+ * Returns saturated value and sets *sat if saturation occurred\n+ */\n+static inline int8_t signed_saturate_b(int32_t val, int *sat)\n+{\n+    if (val > SAT_MAX_B) {\n+        *sat = 1;\n+        return SAT_MAX_B;\n+    }\n+    if (val < SAT_MIN_B) {\n+        *sat = 1;\n+        return SAT_MIN_B;\n+    }\n+    return (int8_t)val;\n+}\n+\n+/**\n+ * Signed saturation for 16-bit elements\n+ */\n+static inline int16_t signed_saturate_h(int32_t val, int *sat)\n+{\n+    if (val > SAT_MAX_H) {\n+        *sat = 1;\n+        return SAT_MAX_H;\n+    }\n+    if (val < SAT_MIN_H) {\n+        *sat = 1;\n+        return SAT_MIN_H;\n+    }\n+    return (int16_t)val;\n+}\n+\n+/**\n+ * Signed saturation for 32-bit elements\n+ */\n+static inline int32_t signed_saturate_w(int64_t val, int *sat)\n+{\n+    if (val > SAT_MAX_W) {\n+        *sat = 1;\n+        return SAT_MAX_W;\n+    }\n+    if (val < SAT_MIN_W) {\n+        *sat = 1;\n+        return SAT_MIN_W;\n+    }\n+    return (int32_t)val;\n+}\n+\n+/**\n+ * Unsigned saturation for 8-bit elements\n+ */\n+static inline uint8_t unsigned_saturate_b(uint32_t val, int *sat)\n+{\n+    if (val > USAT_MAX_B) {\n+        *sat = 1;\n+        return USAT_MAX_B;\n+    }\n+    return (uint8_t)val;\n+}\n+\n+/**\n+ * Unsigned saturation for 16-bit elements\n+ */\n+static inline uint16_t unsigned_saturate_h(uint32_t val, int *sat)\n+{\n+    if (val > USAT_MAX_H) {\n+        *sat = 1;\n+        return USAT_MAX_H;\n+    }\n+    return (uint16_t)val;\n+}\n+\n+/**\n+ * Unsigned saturation for 32-bit elements\n+ */\n+static inline uint32_t unsigned_saturate_w(uint64_t val, int *sat)\n+{\n+    if (val > USAT_MAX_W) {\n+        *sat = 1;\n+        return USAT_MAX_W;\n+    }\n+    return (uint32_t)val;\n+}\n+\n+/* Basic addition operations (non-saturating) */\n+\n+/**\n+ * PADD.B - Packed 8-bit addition\n+ * For each byte: rd[i] = rs1[i] + rs2[i] (modular)\n+ */\n+target_ulong HELPER(padd_b)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint8_t e1 = EXTRACT8(rs1, i);\n+        uint8_t e2 = EXTRACT8(rs2, i);\n+        uint8_t res = e1 + e2;\n+        rd = INSERT8(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PADD.H - Packed 16-bit addition\n+ * For each halfword: rd[i] = rs1[i] + rs2[i] (modular)\n+ */\n+target_ulong HELPER(padd_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint16_t e1 = EXTRACT16(rs1, i);\n+        uint16_t e2 = EXTRACT16(rs2, i);\n+        uint16_t res = e1 + e2;\n+        rd = INSERT16(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PADD.W - Packed 32-bit addition (RV64 only)\n+ * For each word: rd[i] = rs1[i] + rs2[i] (modular)\n+ */\n+uint64_t HELPER(padd_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;  /* 2 words in 64-bit */\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint32_t e1 = EXTRACT32(rs1, i);\n+        uint32_t e2 = EXTRACT32(rs2, i);\n+        uint32_t res = e1 + e2;\n+        rd = INSERT32(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PADD.BS - Packed 8-bit addition with scalar second operand\n+ * For each byte: rd[i] = rs1[i] + rs2[0] (modular)\n+ */\n+target_ulong HELPER(padd_bs)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+    uint8_t e2 = EXTRACT8(rs2, 0);  /* Scalar, take least significant byte */\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint8_t e1 = EXTRACT8(rs1, i);\n+        uint8_t res = e1 + e2;\n+        rd = INSERT8(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PADD.HS - Packed 16-bit addition with scalar second operand\n+ * For each halfword: rd[i] = rs1[i] + rs2[0] (modular)\n+ */\n+target_ulong HELPER(padd_hs)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    uint16_t e2 = EXTRACT16(rs2, 0);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint16_t e1 = EXTRACT16(rs1, i);\n+        uint16_t res = e1 + e2;\n+        rd = INSERT16(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PADD.WS - Packed 32-bit addition with scalar second operand (RV64 only)\n+ * For each word: rd[i] = rs1[i] + rs2[0] (modular)\n+ */\n+uint64_t HELPER(padd_ws)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    uint32_t e2 = EXTRACT32(rs2, 0);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint32_t e1 = EXTRACT32(rs1, i);\n+        uint32_t res = e1 + e2;\n+        rd = INSERT32(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+\n+/* Basic subtraction operations (non-saturating) */\n+\n+/**\n+ * PSUB.B - Packed 8-bit subtraction\n+ * For each byte: rd[i] = rs1[i] - rs2[i] (modular)\n+ */\n+target_ulong HELPER(psub_b)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint8_t e1 = EXTRACT8(rs1, i);\n+        uint8_t e2 = EXTRACT8(rs2, i);\n+        uint8_t res = e1 - e2;\n+        rd = INSERT8(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSUB.H - Packed 16-bit subtraction\n+ * For each halfword: rd[i] = rs1[i] - rs2[i] (modular)\n+ */\n+target_ulong HELPER(psub_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint16_t e1 = EXTRACT16(rs1, i);\n+        uint16_t e2 = EXTRACT16(rs2, i);\n+        uint16_t res = e1 - e2;\n+        rd = INSERT16(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSUB.W - Packed 32-bit subtraction (RV64 only)\n+ * For each word: rd[i] = rs1[i] - rs2[i] (modular)\n+ */\n+uint64_t HELPER(psub_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint32_t e1 = EXTRACT32(rs1, i);\n+        uint32_t e2 = EXTRACT32(rs2, i);\n+        uint32_t res = e1 - e2;\n+        rd = INSERT32(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/* Shift-left-by-one and add operations */\n+\n+/**\n+ * PSH1ADD.H - Shift left by 1 and add (16-bit)\n+ * For each halfword: rd[i] = (rs1[i] << 1) + rs2[i]\n+ */\n+target_ulong HELPER(psh1add_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint16_t e1 = EXTRACT16(rs1, i);\n+        uint16_t e2 = EXTRACT16(rs2, i);\n+        uint16_t res = (e1 << 1) + e2;\n+        rd = INSERT16(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSH1ADD.W - Shift left by 1 and add (32-bit, RV64 only)\n+ * For each word: rd[i] = (rs1[i] << 1) + rs2[i]\n+ */\n+uint64_t HELPER(psh1add_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint32_t e1 = EXTRACT32(rs1, i);\n+        uint32_t e2 = EXTRACT32(rs2, i);\n+        uint32_t res = (e1 << 1) + e2;\n+        rd = INSERT32(rd, res, i);\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSH1SADD.H - Saturating shift left by 1 and saturating add (16-bit)\n+ * For each halfword: rd[i] = sat16(sat16(rs1[i] << 1) + rs2[i])\n+ */\n+target_ulong HELPER(pssh1sadd_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int16_t e1 = (int16_t)EXTRACT16(rs1, i);\n+        int16_t e2 = (int16_t)EXTRACT16(rs2, i);\n+        int32_t shifted;\n+\n+        /* Check if shift-left-1 would overflow */\n+        if (e1 > 0x3FFF || e1 < -0x4000) {\n+            shifted = (e1 < 0) ? 0xFFFF8000LL : 0x7FFF;\n+            sat = 1;\n+        } else {\n+            shifted = e1 << 1;\n+        }\n+\n+        int32_t sum = shifted + e2;\n+        int16_t res = signed_saturate_h(sum, &sat);\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSH1SADD.W - Saturating shift left by 1 and add\n+ * with saturation (32-bit, RV64 only)\n+ * For each word: rd[i] = sat32(sat32(rs1[i] << 1) + rs2[i])\n+ */\n+uint64_t HELPER(pssh1sadd_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int32_t e1 = (int32_t)EXTRACT32(rs1, i);\n+        int32_t e2 = (int32_t)EXTRACT32(rs2, i);\n+        int64_t shifted;\n+\n+        /* Check if shift-left-1 would overflow */\n+        if (e1 > 0x3FFFFFFF || e1 < -0x40000000) {\n+            shifted = (e1 < 0) ? 0xFFFFFFFF80000000LL : 0x7FFFFFFF;\n+            sat = 1;\n+        } else {\n+            shifted = (int64_t)e1 << 1;\n+        }\n+\n+        int64_t sum = shifted + e2;\n+        int32_t res = signed_saturate_w(sum, &sat);\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * SSH1SADD - 32-bit scalar saturating shift left by 1 and saturating add\n+ */\n+uint32_t HELPER(ssh1sadd)(CPURISCVState *env,\n+                     uint32_t rs1, uint32_t rs2)\n+{\n+    int32_t a = (int32_t)rs1;\n+    int32_t b = (int32_t)rs2;\n+    int64_t shifted;\n+    int sat = 0;\n+\n+    /* Check if shift-left-1 would overflow */\n+    if (a > 0x3FFFFFFF || a < -0x40000000) {\n+        shifted = (a < 0) ? 0xFFFFFFFF80000000LL : 0x7FFFFFFF;\n+        sat = 1;\n+    } else {\n+        shifted = (int64_t)a << 1;\n+    }\n+\n+    int64_t sum = shifted + b;\n+    int32_t res = signed_saturate_w(sum, &sat);\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint32_t)res;\n+}\n+\n+/* Saturating addition operations */\n+\n+/**\n+ * PSADD.B - Packed 8-bit signed saturating addition\n+ * For each byte: rd[i] = sat8(rs1[i] + rs2[i])\n+ */\n+target_ulong HELPER(psadd_b)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int8_t e1 = (int8_t)EXTRACT8(rs1, i);\n+        int8_t e2 = (int8_t)EXTRACT8(rs2, i);\n+        int32_t sum = (int32_t)e1 + (int32_t)e2;\n+        int8_t res = signed_saturate_b(sum, &sat);\n+        rd = INSERT8(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSADD.H - Packed 16-bit signed saturating addition\n+ * For each halfword: rd[i] = sat16(rs1[i] + rs2[i])\n+ */\n+target_ulong HELPER(psadd_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int16_t e1 = (int16_t)EXTRACT16(rs1, i);\n+        int16_t e2 = (int16_t)EXTRACT16(rs2, i);\n+        int32_t sum = (int32_t)e1 + (int32_t)e2;\n+        int16_t res = signed_saturate_h(sum, &sat);\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSADD.W - Packed 32-bit signed saturating addition (RV64 only)\n+ * For each word: rd[i] = sat32(rs1[i] + rs2[i])\n+ */\n+uint64_t HELPER(psadd_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int32_t e1 = (int32_t)EXTRACT32(rs1, i);\n+        int32_t e2 = (int32_t)EXTRACT32(rs2, i);\n+        int64_t sum = (int64_t)e1 + (int64_t)e2;\n+        int32_t res = signed_saturate_w(sum, &sat);\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSADDU.B - Packed 8-bit unsigned saturating addition\n+ * For each byte: rd[i] = usat8(rs1[i] + rs2[i])\n+ */\n+target_ulong HELPER(psaddu_b)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint8_t e1 = EXTRACT8(rs1, i);\n+        uint8_t e2 = EXTRACT8(rs2, i);\n+        uint32_t sum = (uint32_t)e1 + (uint32_t)e2;\n+        uint8_t res = unsigned_saturate_b(sum, &sat);\n+        rd = INSERT8(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSADDU.H - Packed 16-bit unsigned saturating addition\n+ * For each halfword: rd[i] = usat16(rs1[i] + rs2[i])\n+ */\n+target_ulong HELPER(psaddu_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint16_t e1 = EXTRACT16(rs1, i);\n+        uint16_t e2 = EXTRACT16(rs2, i);\n+        uint32_t sum = (uint32_t)e1 + (uint32_t)e2;\n+        uint16_t res = unsigned_saturate_h(sum, &sat);\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSADDU.W - Packed 32-bit unsigned saturating addition (RV64 only)\n+ * For each word: rd[i] = usat32(rs1[i] + rs2[i])\n+ */\n+uint64_t HELPER(psaddu_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint32_t e1 = EXTRACT32(rs1, i);\n+        uint32_t e2 = EXTRACT32(rs2, i);\n+        uint64_t sum = (uint64_t)e1 + (uint64_t)e2;\n+        uint32_t res = unsigned_saturate_w(sum, &sat);\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * SADD - 32-bit signed saturating addition\n+ */\n+uint32_t HELPER(sadd)(CPURISCVState *env,\n+                     uint32_t rs1, uint32_t rs2)\n+{\n+    int32_t a = (int32_t)rs1;\n+    int32_t b = (int32_t)rs2;\n+    int64_t sum = (int64_t)a + (int64_t)b;\n+    int sat = 0;\n+    int32_t res = signed_saturate_w(sum, &sat);\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint32_t)res;\n+}\n+\n+/**\n+ * SADDU - 32-bit unsigned saturating addition\n+ */\n+uint32_t HELPER(saddu)(CPURISCVState *env,\n+                     uint32_t rs1, uint32_t rs2)\n+{\n+    uint32_t a = rs1;\n+    uint32_t b = rs2;\n+    uint64_t sum = (uint64_t)a + (uint64_t)b;\n+    int sat = 0;\n+    uint32_t res = unsigned_saturate_w(sum, &sat);\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return res;\n+}\n+\n+/* Saturating subtraction operations */\n+\n+/**\n+ * PSSUB.B - Packed 8-bit signed saturating subtraction\n+ * For each byte: rd[i] = sat8(rs1[i] - rs2[i])\n+ */\n+target_ulong HELPER(pssub_b)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int8_t e1 = (int8_t)EXTRACT8(rs1, i);\n+        int8_t e2 = (int8_t)EXTRACT8(rs2, i);\n+        int32_t diff = (int32_t)e1 - (int32_t)e2;\n+        int8_t res = signed_saturate_b(diff, &sat);\n+        rd = INSERT8(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSUB.H - Packed 16-bit signed saturating subtraction\n+ * For each halfword: rd[i] = sat16(rs1[i] - rs2[i])\n+ */\n+target_ulong HELPER(pssub_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int16_t e1 = (int16_t)EXTRACT16(rs1, i);\n+        int16_t e2 = (int16_t)EXTRACT16(rs2, i);\n+        int32_t diff = (int32_t)e1 - (int32_t)e2;\n+        int16_t res = signed_saturate_h(diff, &sat);\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSUB.W - Packed 32-bit signed saturating subtraction (RV64 only)\n+ * For each word: rd[i] = sat32(rs1[i] - rs2[i])\n+ */\n+uint64_t HELPER(pssub_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int32_t e1 = (int32_t)EXTRACT32(rs1, i);\n+        int32_t e2 = (int32_t)EXTRACT32(rs2, i);\n+        int64_t diff = (int64_t)e1 - (int64_t)e2;\n+        int32_t res = signed_saturate_w(diff, &sat);\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSUBU.B - Packed 8-bit unsigned saturating subtraction\n+ * For each byte: rd[i] = usat8(rs1[i] - rs2[i])\n+ */\n+target_ulong HELPER(pssubu_b)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_B(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint8_t e1 = EXTRACT8(rs1, i);\n+        uint8_t e2 = EXTRACT8(rs2, i);\n+        uint32_t diff = e1 - e2;  /* Unsigned subtraction may underflow */\n+        uint8_t res = unsigned_saturate_b(diff, &sat);\n+        rd = INSERT8(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSUBU.H - Packed 16-bit unsigned saturating subtraction\n+ * For each halfword: rd[i] = usat16(rs1[i] - rs2[i])\n+ */\n+target_ulong HELPER(pssubu_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong rs2)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint16_t e1 = EXTRACT16(rs1, i);\n+        uint16_t e2 = EXTRACT16(rs2, i);\n+        uint32_t diff = e1 - e2;\n+        uint16_t res = unsigned_saturate_h(diff, &sat);\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSSUBU.W - Packed 32-bit unsigned saturating subtraction (RV64 only)\n+ * For each word: rd[i] = usat32(rs1[i] - rs2[i])\n+ */\n+uint64_t HELPER(pssubu_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t rs2)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        uint32_t e1 = EXTRACT32(rs1, i);\n+        uint32_t e2 = EXTRACT32(rs2, i);\n+        uint32_t res = (e1 >= e2) ? (e1 - e2) : 0;\n+        if (e1 < e2) {\n+            sat = 1;\n+        }\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * SSUB - 32-bit signed saturating subtraction\n+ */\n+uint32_t HELPER(ssub)(CPURISCVState *env,\n+                     uint32_t rs1, uint32_t rs2)\n+{\n+    int32_t a = (int32_t)rs1;\n+    int32_t b = (int32_t)rs2;\n+    int64_t diff = (int64_t)a - (int64_t)b;\n+    int sat = 0;\n+    int32_t res = signed_saturate_w(diff, &sat);\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint32_t)res;\n+}\n+\n+/**\n+ * SSUBU - 32-bit unsigned saturating subtraction\n+ */\n+uint32_t HELPER(ssubu)(CPURISCVState *env,\n+                     uint32_t rs1, uint32_t rs2)\n+{\n+    uint32_t a = rs1;\n+    uint32_t b = rs2;\n+    uint64_t diff = (uint64_t)a - (uint64_t)b;\n+    int sat = 0;\n+    uint32_t res = unsigned_saturate_w(diff, &sat);\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return res;\n+}\n+\n+/* Saturation instructions (SAT, USAT) */\n+\n+/**\n+ * PSATI.H - Packed 16-bit signed saturate to immediate bit-width\n+ * For each halfword: rd[i] = sat(rs1[i], imm+1 bits)\n+ */\n+target_ulong HELPER(psati_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong imm)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    int range = (imm & 0x0F) + 1;  /* imm specifies bits-1 */\n+    int64_t max = (1LL << (range - 1)) - 1;\n+    int64_t min = -(1LL << (range - 1));\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int16_t e1 = (int16_t)EXTRACT16(rs1, i);\n+        int16_t res;\n+\n+        if (e1 > max) {\n+            res = max;\n+            sat = 1;\n+        } else if (e1 < min) {\n+            res = min;\n+            sat = 1;\n+        } else {\n+            res = e1;\n+        }\n+\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PUSATI.H - Packed 16-bit unsigned saturate to immediate bit-width\n+ * For each halfword: rd[i] = usat(rs1[i], imm bits)\n+ */\n+target_ulong HELPER(pusati_h)(CPURISCVState *env,\n+                          target_ulong rs1, target_ulong imm)\n+{\n+    target_ulong rd = 0;\n+    int elems = ELEMS_H(rd);\n+    uint32_t max = (1U << imm) - 1;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int16_t e1 = (int16_t)EXTRACT16(rs1, i);\n+        int16_t res;\n+\n+        if (e1 < 0) {\n+            res = 0;\n+            sat = 1;\n+        } else if ((uint16_t)e1 > max) {\n+            res = max;\n+            sat = 1;\n+        } else {\n+            res = e1;\n+        }\n+\n+        rd = INSERT16(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PSATI.W - Packed 32-bit signed saturate to immediate bit-width (RV64 only)\n+ * For each word: rd[i] = sat(rs1[i], imm+1 bits)\n+ */\n+uint64_t HELPER(psati_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t imm)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    int range = (imm & 0x1F) + 1;\n+    int64_t max = (1LL << (range - 1)) - 1;\n+    int64_t min = -(1LL << (range - 1));\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int32_t e1 = (int32_t)EXTRACT32(rs1, i);\n+        int32_t res;\n+\n+        if (e1 > max) {\n+            res = max;\n+            sat = 1;\n+        } else if (e1 < min) {\n+            res = min;\n+            sat = 1;\n+        } else {\n+            res = e1;\n+        }\n+\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * PUSATI.W - Packed 32-bit unsigned saturate to immediate bit-width (RV64 only)\n+ * For each word: rd[i] = usat(rs1[i], imm bits)\n+ */\n+uint64_t HELPER(pusati_w)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t imm)\n+{\n+    uint64_t rd = 0;\n+    int elems = 2;\n+    uint64_t max = (1ULL << imm) - 1;\n+    int sat = 0;\n+\n+    for (int i = 0; i < elems; i++) {\n+        int32_t e1 = (int32_t)EXTRACT32(rs1, i);\n+        int32_t res;\n+\n+        if (e1 < 0) {\n+            res = 0;\n+            sat = 1;\n+        } else if ((uint32_t)e1 > max) {\n+            res = max;\n+            sat = 1;\n+        } else {\n+            res = e1;\n+        }\n+\n+        rd = INSERT32(rd, res, i);\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return rd;\n+}\n+\n+/**\n+ * SATI_32 - 32-bit scalar signed saturation with immediate range\n+ */\n+uint32_t HELPER(sati_32)(CPURISCVState *env,\n+                         uint32_t rs1, uint32_t imm)\n+{\n+    int32_t a = (int32_t)rs1;\n+    int range = (imm & 0x1F) + 1;  /* imm specifies bits-1 */\n+    int64_t max = (1LL << (range - 1)) - 1;\n+    int64_t min = -(1LL << (range - 1));\n+    int sat = 0;\n+\n+    if (a > max) {\n+        a = max;\n+        sat = 1;\n+    } else if (a < min) {\n+        a = min;\n+        sat = 1;\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint32_t)a;\n+}\n+\n+/**\n+ * USATI_32 - 32-bit scalar unsigned saturation with immediate range\n+ */\n+uint32_t HELPER(usati_32)(CPURISCVState *env,\n+                          uint32_t rs1, uint32_t imm)\n+{\n+    int32_t a = (int32_t)rs1;\n+    uint32_t max = (1U << imm) - 1;\n+    int sat = 0;\n+\n+    if (a < 0) {\n+        a = 0;\n+        sat = 1;\n+    } else if ((uint32_t)a > max) {\n+        a = max;\n+        sat = 1;\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint32_t)a;\n+}\n+\n+/**\n+ * SATI_64 - 64-bit scalar signed saturation with immediate range\n+ */\n+uint64_t HELPER(sati_64)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t imm)\n+{\n+    int64_t a = (int64_t)rs1;\n+    int range = (imm & 0x3F) + 1;\n+    int64_t max = (1LL << (range - 1)) - 1;\n+    int64_t min = -(1LL << (range - 1));\n+    int sat = 0;\n+\n+    if (a > max) {\n+        a = max;\n+        sat = 1;\n+    } else if (a < min) {\n+        a = min;\n+        sat = 1;\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint64_t)a;\n+}\n+\n+/**\n+ * USATI_64 - 64-bit scalar unsigned saturation with immediate range\n+ */\n+uint64_t HELPER(usati_64)(CPURISCVState *env,\n+                     uint64_t rs1, uint64_t imm)\n+{\n+    int64_t a = (int64_t)rs1;\n+    uint64_t max = (1ULL << imm) - 1;\n+    int sat = 0;\n+\n+    if (a < 0) {\n+        a = 0;\n+        sat = 1;\n+    } else if ((uint64_t)a > max) {\n+        a = max;\n+        sat = 1;\n+    }\n+\n+    if (sat) {\n+        env->vxsat = 1;\n+    }\n+    return (uint64_t)a;\n+}\ndiff --git a/target/riscv/translate.c b/target/riscv/translate.c\nindex 81087e0a5d..de3ec7a7ec 100644\n--- a/target/riscv/translate.c\n+++ b/target/riscv/translate.c\n@@ -1206,6 +1206,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)\n #include \"insn_trans/trans_rvh.c.inc\"\n #include \"insn_trans/trans_rvv.c.inc\"\n #include \"insn_trans/trans_rvb.c.inc\"\n+#include \"insn_trans/trans_rvp.c.inc\"\n #include \"insn_trans/trans_rvzicond.c.inc\"\n #include \"insn_trans/trans_rvzacas.c.inc\"\n #include \"insn_trans/trans_rvzabha.c.inc\"\n",
    "prefixes": [
        "02/14"
    ]
}