@@ -1271,3 +1271,12 @@ DEF_HELPER_3(pkbb16, tl, env, tl, tl)
DEF_HELPER_3(pkbt16, tl, env, tl, tl)
DEF_HELPER_3(pktt16, tl, env, tl, tl)
DEF_HELPER_3(pktb16, tl, env, tl, tl)
+
+DEF_HELPER_3(smmul, tl, env, tl, tl)
+DEF_HELPER_3(smmul_u, tl, env, tl, tl)
+DEF_HELPER_4(kmmac, tl, env, tl, tl, tl)
+DEF_HELPER_4(kmmac_u, tl, env, tl, tl, tl)
+DEF_HELPER_4(kmmsb, tl, env, tl, tl, tl)
+DEF_HELPER_4(kmmsb_u, tl, env, tl, tl, tl)
+DEF_HELPER_3(kwmmul, tl, env, tl, tl)
+DEF_HELPER_3(kwmmul_u, tl, env, tl, tl)
@@ -874,3 +874,12 @@ pkbb16 0000111 ..... ..... 001 ..... 1110111 @r
pkbt16 0001111 ..... ..... 001 ..... 1110111 @r
pktt16 0010111 ..... ..... 001 ..... 1110111 @r
pktb16 0011111 ..... ..... 001 ..... 1110111 @r
+
+smmul 0100000 ..... ..... 001 ..... 1110111 @r
+smmul_u 0101000 ..... ..... 001 ..... 1110111 @r
+kmmac 0110000 ..... ..... 001 ..... 1110111 @r
+kmmac_u 0111000 ..... ..... 001 ..... 1110111 @r
+kmmsb 0100001 ..... ..... 001 ..... 1110111 @r
+kmmsb_u 0101001 ..... ..... 001 ..... 1110111 @r
+kwmmul 0110001 ..... ..... 001 ..... 1110111 @r
+kwmmul_u 0111001 ..... ..... 001 ..... 1110111 @r
@@ -369,3 +369,47 @@ GEN_RVP_R_OOL(pkbb16);
GEN_RVP_R_OOL(pkbt16);
GEN_RVP_R_OOL(pktt16);
GEN_RVP_R_OOL(pktb16);
+
+/* Most Significant Word “32x32” Multiply & Add Instructions */
+GEN_RVP_R_OOL(smmul);
+GEN_RVP_R_OOL(smmul_u);
+
+/* Function to accumulate destination register */
+static inline bool r_acc_ool(DisasContext *ctx, arg_r *a,
+ void (* fn)(TCGv, TCGv_ptr, TCGv, TCGv, TCGv))
+{
+ TCGv src1, src2, src3, dst;
+ if (!has_ext(ctx, RVP)) {
+ return false;
+ }
+
+ src1 = tcg_temp_new();
+ src2 = tcg_temp_new();
+ src3 = tcg_temp_new();
+ dst = tcg_temp_new();
+
+ gen_get_gpr(src1, a->rs1);
+ gen_get_gpr(src2, a->rs2);
+ gen_get_gpr(src3, a->rd);
+ fn(dst, cpu_env, src1, src2, src3);
+ gen_set_gpr(a->rd, dst);
+
+ tcg_temp_free(src1);
+ tcg_temp_free(src2);
+ tcg_temp_free(src3);
+ tcg_temp_free(dst);
+ return true;
+}
+
+#define GEN_RVP_R_ACC_OOL(NAME) \
+static bool trans_##NAME(DisasContext *s, arg_r *a) \
+{ \
+ return r_acc_ool(s, a, gen_helper_##NAME); \
+}
+
+GEN_RVP_R_ACC_OOL(kmmac);
+GEN_RVP_R_ACC_OOL(kmmac_u);
+GEN_RVP_R_ACC_OOL(kmmsb);
+GEN_RVP_R_ACC_OOL(kmmsb_u);
+GEN_RVP_R_OOL(kwmmul);
+GEN_RVP_R_OOL(kwmmul_u);
@@ -1359,3 +1359,112 @@ static inline void do_pktb16(CPURISCVState *env, void *vd, void *va,
}
RVPR(pktb16, 2, 2);
+
+/* Most Significant Word “32x32” Multiply & Add Instructions */
+static inline void do_smmul(CPURISCVState *env, void *vd, void *va,
+ void *vb, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb;
+ d[i] = (int64_t)a[i] * b[i] >> 32;
+}
+
+RVPR(smmul, 1, 4);
+
+static inline void do_smmul_u(CPURISCVState *env, void *vd, void *va,
+ void *vb, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb;
+ d[i] = ((int64_t)a[i] * b[i] + (uint32_t)INT32_MIN) >> 32;
+}
+
+RVPR(smmul_u, 1, 4);
+
+typedef void PackedFn4i(CPURISCVState *, void *, void *,
+ void *, void *, uint8_t);
+
+static inline target_ulong
+rvpr_acc(CPURISCVState *env, target_ulong a,
+ target_ulong b, target_ulong c,
+ uint8_t step, uint8_t size, PackedFn4i *fn)
+{
+ int i, passes = sizeof(target_ulong) / size;
+ target_ulong result = 0;
+
+ for (i = 0; i < passes; i += step) {
+ fn(env, &result, &a, &b, &c, i);
+ }
+ return result;
+}
+
+#define RVPR_ACC(NAME, STEP, SIZE) \
+target_ulong HELPER(NAME)(CPURISCVState *env, target_ulong a, \
+ target_ulong b, target_ulong c) \
+{ \
+ return rvpr_acc(env, a, b, c, STEP, SIZE, (PackedFn4i *)do_##NAME);\
+}
+
+static inline void do_kmmac(CPURISCVState *env, void *vd, void *va,
+ void *vb, void *vc, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb, *c = vc;
+ d[i] = sadd32(env, 0, ((int64_t)a[i] * b[i]) >> 32, c[i]);
+}
+
+RVPR_ACC(kmmac, 1, 4);
+
+static inline void do_kmmac_u(CPURISCVState *env, void *vd, void *va,
+ void *vb, void *vc, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb, *c = vc;
+ d[i] = sadd32(env, 0, ((int64_t)a[i] * b[i] +
+ (uint32_t)INT32_MIN) >> 32, c[i]);
+}
+
+RVPR_ACC(kmmac_u, 1, 4);
+
+static inline void do_kmmsb(CPURISCVState *env, void *vd, void *va,
+ void *vb, void *vc, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb, *c = vc;
+ d[i] = ssub32(env, 0, c[i], (int64_t)a[i] * b[i] >> 32);
+}
+
+RVPR_ACC(kmmsb, 1, 4);
+
+static inline void do_kmmsb_u(CPURISCVState *env, void *vd, void *va,
+ void *vb, void *vc, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb, *c = vc;
+ d[i] = ssub32(env, 0, c[i], ((int64_t)a[i] * b[i] +
+ (uint32_t)INT32_MIN) >> 32);
+}
+
+RVPR_ACC(kmmsb_u, 1, 4);
+
+static inline void do_kwmmul(CPURISCVState *env, void *vd, void *va,
+ void *vb, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb;
+ if (a[i] == INT32_MIN && b[i] == INT32_MIN) {
+ env->vxsat = 0x1;
+ d[i] = INT32_MAX;
+ } else {
+ d[i] = (int64_t)a[i] * b[i] >> 31;
+ }
+}
+
+RVPR(kwmmul, 1, 4);
+
+static inline void do_kwmmul_u(CPURISCVState *env, void *vd, void *va,
+ void *vb, uint8_t i)
+{
+ int32_t *d = vd, *a = va, *b = vb;
+ if (a[i] == INT32_MIN && b[i] == INT32_MIN) {
+ env->vxsat = 0x1;
+ d[i] = INT32_MAX;
+ } else {
+ d[i] = ((int64_t)a[i] * b[i] + (1ull << 30)) >> 31;
+ }
+}
+
+RVPR(kwmmul_u, 1, 4);
Always contain a 32x32 multiplification and the most significant word can be used as the result, or an operand for an add or subtract operation with rounding or saturation. Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com> --- target/riscv/helper.h | 9 ++ target/riscv/insn32.decode | 9 ++ target/riscv/insn_trans/trans_rvp.c.inc | 44 ++++++++++ target/riscv/packed_helper.c | 109 ++++++++++++++++++++++++ 4 files changed, 171 insertions(+)