Implement packed pairing, sign-extension, reversal, zip and unzip, shift-and-merge, narrowing clipping, and count-leading-sign operations. Cover the supported element widths and signed and unsigned clipping variants. Add the associated decode entries, translators and helpers.
Note that the narrowing clipping instructions combine elements from two source registers and clamp each result to the destination element range. They set vxsat when saturation occurs. Signed-off-by: Molly Chen <[email protected]> --- target/riscv/helper.h | 41 ++++++ target/riscv/insn32.decode | 42 ++++++ target/riscv/tcg/insn_trans/trans_rvp.c.inc | 57 ++++++++ target/riscv/tcg/psimd_helper.c | 152 ++++++++++++++++++++ 4 files changed, 292 insertions(+) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 824779f05d0..55d95c6eb6d 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -1519,3 +1519,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 3f8314d382b..38210bb4934 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -1298,3 +1298,45 @@ 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_32 01101 0011111 ..... 101 ..... 0010011 @r2 +rev_64 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 726707b2956..2c9a34b9a7e 100644 --- a/target/riscv/tcg/insn_trans/trans_rvp.c.inc +++ b/target/riscv/tcg/insn_trans/trans_rvp.c.inc @@ -672,3 +672,60 @@ GEN_SIMD_TRANS(predsum_hs) 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) +#if defined(TARGET_RISCV32) +static bool trans_rev_32(DisasContext *ctx, arg_rev_32 * a) +{ + REQUIRE_32BIT(ctx); + GEN_SIMD_TRANS_R1_BODY(rev, false); +} + +GEN_SIMD_TRANS_UNAVAILABLE_64(rev_64) +#else +GEN_SIMD_TRANS_UNAVAILABLE_32(rev_32) + +static bool trans_rev_64(DisasContext *ctx, arg_rev_64 * a) +{ + REQUIRE_64BIT(ctx); + GEN_SIMD_TRANS_R1_BODY(rev, false); +} +#endif +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 397efa66aeb..f883596fe49 100644 --- a/target/riscv/tcg/psimd_helper.c +++ b/target/riscv/tcg/psimd_helper.c @@ -2477,3 +2477,155 @@ 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) + +/* 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 the bit order of the full XLEN-wide value + */ +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 the order of 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 == 0) { + xrd = rd; + } else 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 == 0) { + xrd = rd; + } else 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
