@@ -925,6 +925,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false),
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
+ DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false),
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
@@ -445,6 +445,7 @@ struct RISCVCPUConfig {
bool ext_xtheadbs;
bool ext_xtheadcmo;
bool ext_xtheadcondmov;
+ bool ext_xtheadmac;
bool ext_xtheadsync;
bool ext_XVentanaCondOps;
@@ -217,3 +217,70 @@ static bool trans_th_mvnez(DisasContext *ctx, arg_th_mveqz *a)
{
return gen_th_condmove(ctx, a, TCG_COND_NE);
}
+
+static bool gen_th_mac(DisasContext *ctx, arg_r *a,
+ void (*accumulate_func)(TCGv, TCGv, TCGv),
+ void (*extend_operand_func)(TCGv, TCGv))
+{
+ TCGv dest = dest_gpr(ctx, a->rd);
+ TCGv src0 = get_gpr(ctx, a->rd, EXT_NONE);
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+ TCGv tmp = tcg_temp_new();
+
+ if (extend_operand_func) {
+ TCGv tmp2 = tcg_temp_new();
+ extend_operand_func(tmp, src1);
+ extend_operand_func(tmp2, src2);
+ tcg_gen_mul_tl(tmp, tmp, tmp2);
+ tcg_temp_free(tmp2);
+ } else {
+ tcg_gen_mul_tl(tmp, src1, src2);
+ }
+
+ accumulate_func(dest, src0, tmp);
+ gen_set_gpr(ctx, a->rd, dest);
+ tcg_temp_free(tmp);
+
+ return true;
+}
+
+/* th.mula: "rd = rd + rs1 * rs2" */
+static bool trans_th_mula(DisasContext *ctx, arg_th_mula *a)
+{
+ return gen_th_mac(ctx, a, tcg_gen_add_tl, NULL);
+}
+
+/* th.mulah: "rd = sext.w(rd + sext.w(rs1[15:0]) * sext.w(rs2[15:0]))" */
+static bool trans_th_mulah(DisasContext *ctx, arg_th_mulah *a)
+{
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_add_tl, tcg_gen_ext16s_tl);
+}
+
+/* th.mulaw: "rd = sext.w(rd + rs1 * rs2)" */
+static bool trans_th_mulaw(DisasContext *ctx, arg_th_mulaw *a)
+{
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_add_tl, NULL);
+}
+
+/* th.muls: "rd = rd - rs1 * rs2" */
+static bool trans_th_muls(DisasContext *ctx, arg_th_muls *a)
+{
+ return gen_th_mac(ctx, a, tcg_gen_sub_tl, NULL);
+}
+
+/* th.mulsh: "rd = sext.w(rd - sext.w(rs1[15:0]) * sext.w(rs2[15:0]))" */
+static bool trans_th_mulsh(DisasContext *ctx, arg_th_mulsh *a)
+{
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_sub_tl, tcg_gen_ext16s_tl);
+}
+
+/* th.mulsw: "rd = sext.w(rd - rs1 * rs2)" */
+static bool trans_th_mulsw(DisasContext *ctx, arg_th_mulsw *a)
+{
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_sub_tl, NULL);
+}
@@ -7,6 +7,7 @@ gen = [
decodetree.process('xtheadbs.decode', extra_args: '--static-decode=decode_xtheadbs'),
decodetree.process('xtheadcmo.decode', extra_args: '--static-decode=decode_xtheadcmo'),
decodetree.process('xtheadcondmov.decode', extra_args: '--static-decode=decode_xtheadcondmov'),
+ decodetree.process('xtheadmac.decode', extra_args: '--static-decode=decode_xtheadmac'),
decodetree.process('xtheadsync.decode', extra_args: '--static-decode=decode_xtheadsync'),
decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
]
@@ -137,6 +137,7 @@ MATERIALISE_EXT_PREDICATE(xtheadbb)
MATERIALISE_EXT_PREDICATE(xtheadbs)
MATERIALISE_EXT_PREDICATE(xtheadcmo)
MATERIALISE_EXT_PREDICATE(xtheadcondmov);
+MATERIALISE_EXT_PREDICATE(xtheadmac);
MATERIALISE_EXT_PREDICATE(xtheadsync)
MATERIALISE_EXT_PREDICATE(XVentanaCondOps)
@@ -729,6 +730,7 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm)
#include "decode-xtheadbs.c.inc"
#include "decode-xtheadcmo.c.inc"
#include "decode-xtheadcondmov.c.inc"
+#include "decode-xtheadmac.c.inc"
#include "decode-xtheadsync.c.inc"
#include "decode-XVentanaCondOps.c.inc"
@@ -1055,6 +1057,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
{ has_xtheadbs_p, decode_xtheadbs },
{ has_xtheadcmo_p, decode_xtheadcmo },
{ has_xtheadcondmov_p, decode_xtheadcondmov },
+ { has_xtheadmac_p, decode_xtheadmac },
{ has_xtheadsync_p, decode_xtheadsync },
{ has_XVentanaCondOps_p, decode_XVentanaCodeOps },
};
new file mode 100644
@@ -0,0 +1,30 @@
+#
+# RISC-V instruction decode for the XTheadMac extension
+#
+# Copyright (c) 2022 Christoph Muellner, christoph.muellner@vrull.eu
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# The XTheadMac extension provides multiply-accumulate instructions.
+#
+# It is documented in
+# https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.0.0/xthead-2022-09-05-2.0.0.pdf
+
+# Fields
+%rs2 20:5
+%rs1 15:5
+%rd 7:5
+
+# Argument sets
+&r rd rs1 rs2 !extern
+
+# Formats:
+@r ..... .. ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
+
+# T-Head conditional move instructions
+th_mula 00100 00 ..... ..... 001 ..... 0001011 @r
+th_mulah 00101 00 ..... ..... 001 ..... 0001011 @r
+th_mulaw 00100 10 ..... ..... 001 ..... 0001011 @r
+th_muls 00100 01 ..... ..... 001 ..... 0001011 @r
+th_mulsh 00101 01 ..... ..... 001 ..... 0001011 @r
+th_mulsw 00100 11 ..... ..... 001 ..... 0001011 @r