xref: /openbmc/qemu/target/riscv/insn_trans/trans_rvbf16.c.inc (revision be6e117a8363734bb65f80299cbdcbe602b71f8e)
1/*
2 * RISC-V translation routines for the BF16 Standard Extensions.
3 *
4 * Copyright (c) 2020-2023 PLCT Lab
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#define REQUIRE_ZFBFMIN(ctx) do { \
20    if (!ctx->cfg_ptr->ext_zfbfmin) { \
21        return false; \
22    } \
23} while (0)
24
25#define REQUIRE_ZVFBFMIN(ctx) do { \
26    if (!ctx->cfg_ptr->ext_zvfbfmin) { \
27        return false; \
28    } \
29} while (0)
30
31#define REQUIRE_ZVFBFWMA(ctx) do { \
32    if (!ctx->cfg_ptr->ext_zvfbfwma) { \
33        return false; \
34    } \
35} while (0)
36
37static bool trans_fcvt_bf16_s(DisasContext *ctx, arg_fcvt_bf16_s *a)
38{
39    REQUIRE_FPU;
40    REQUIRE_ZFBFMIN(ctx);
41
42    TCGv_i64 dest = dest_fpr(ctx, a->rd);
43    TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
44
45    gen_set_rm(ctx, a->rm);
46    gen_helper_fcvt_bf16_s(dest, tcg_env, src1);
47    gen_set_fpr_hs(ctx, a->rd, dest);
48    mark_fs_dirty(ctx);
49    return true;
50}
51
52static bool trans_fcvt_s_bf16(DisasContext *ctx, arg_fcvt_s_bf16 *a)
53{
54    REQUIRE_FPU;
55    REQUIRE_ZFBFMIN(ctx);
56
57    TCGv_i64 dest = dest_fpr(ctx, a->rd);
58    TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
59
60    gen_set_rm(ctx, a->rm);
61    gen_helper_fcvt_s_bf16(dest, tcg_env, src1);
62    gen_set_fpr_hs(ctx, a->rd, dest);
63    mark_fs_dirty(ctx);
64    return true;
65}
66
67static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a)
68{
69    REQUIRE_FPU;
70    REQUIRE_ZVFBFMIN(ctx);
71
72    if (opfv_narrow_check(ctx, a) && (ctx->sew == MO_16)) {
73        uint32_t data = 0;
74
75        gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
76
77        data = FIELD_DP32(data, VDATA, VM, a->vm);
78        data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
79        data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
80        data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
81        tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
82                           vreg_ofs(ctx, a->rs2), tcg_env,
83                           ctx->cfg_ptr->vlenb,
84                           ctx->cfg_ptr->vlenb, data,
85                           gen_helper_vfncvtbf16_f_f_w);
86        finalize_rvv_inst(ctx);
87        return true;
88    }
89    return false;
90}
91
92static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a)
93{
94    REQUIRE_FPU;
95    REQUIRE_ZVFBFMIN(ctx);
96
97    if (opfv_widen_check(ctx, a) && (ctx->sew == MO_16)) {
98        uint32_t data = 0;
99
100        gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
101
102        data = FIELD_DP32(data, VDATA, VM, a->vm);
103        data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
104        data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
105        data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
106        tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
107                           vreg_ofs(ctx, a->rs2), tcg_env,
108                           ctx->cfg_ptr->vlenb,
109                           ctx->cfg_ptr->vlenb, data,
110                           gen_helper_vfwcvtbf16_f_f_v);
111        finalize_rvv_inst(ctx);
112        return true;
113    }
114    return false;
115}
116
117static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a)
118{
119    REQUIRE_FPU;
120    REQUIRE_ZVFBFWMA(ctx);
121
122    uint8_t sew = ctx->sew;
123    if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) &&
124        vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm) &&
125        vext_check_input_eew(ctx, a->rd, sew + 1, a->rs1, sew, a->vm) &&
126        vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
127        uint32_t data = 0;
128
129        gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
130
131        data = FIELD_DP32(data, VDATA, VM, a->vm);
132        data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
133        data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
134        data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
135        tcg_gen_gvec_4_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
136                           vreg_ofs(ctx, a->rs1),
137                           vreg_ofs(ctx, a->rs2), tcg_env,
138                           ctx->cfg_ptr->vlenb,
139                           ctx->cfg_ptr->vlenb, data,
140                           gen_helper_vfwmaccbf16_vv);
141        finalize_rvv_inst(ctx);
142        return true;
143    }
144    return false;
145}
146
147static bool trans_vfwmaccbf16_vf(DisasContext *ctx, arg_vfwmaccbf16_vf *a)
148{
149    REQUIRE_FPU;
150    REQUIRE_ZVFBFWMA(ctx);
151
152    uint8_t sew = ctx->sew;
153    if (require_rvv(ctx) && (ctx->sew == MO_16) && vext_check_isa_ill(ctx) &&
154        vext_check_ds(ctx, a->rd, a->rs2, a->vm) &&
155        vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
156        uint32_t data = 0;
157
158        gen_set_rm(ctx, RISCV_FRM_DYN);
159        data = FIELD_DP32(data, VDATA, VM, a->vm);
160        data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
161        data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
162        data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
163        return opfvf_trans(a->rd, a->rs1, a->rs2, data,
164                           gen_helper_vfwmaccbf16_vf, ctx);
165    }
166
167    return false;
168}
169