]> git.proxmox.com Git - mirror_qemu.git/blob - target/riscv/insn_trans/trans_rvbf16.c.inc
Merge tag 'pull-qapi-2023-07-10' of https://repo.or.cz/qemu/armbru into staging
[mirror_qemu.git] / target / riscv / insn_trans / trans_rvbf16.c.inc
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
37 static 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, cpu_env, src1);
47 gen_set_fpr_hs(ctx, a->rd, dest);
48 mark_fs_dirty(ctx);
49 return true;
50 }
51
52 static 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, cpu_env, src1);
62 gen_set_fpr_hs(ctx, a->rd, dest);
63 mark_fs_dirty(ctx);
64 return true;
65 }
66
67 static 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 TCGLabel *over = gen_new_label();
75
76 gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
77 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
78 tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
79
80 data = FIELD_DP32(data, VDATA, VM, a->vm);
81 data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
82 data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
83 data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
84 tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
85 vreg_ofs(ctx, a->rs2), cpu_env,
86 ctx->cfg_ptr->vlen / 8,
87 ctx->cfg_ptr->vlen / 8, data,
88 gen_helper_vfncvtbf16_f_f_w);
89 mark_vs_dirty(ctx);
90 gen_set_label(over);
91 return true;
92 }
93 return false;
94 }
95
96 static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a)
97 {
98 REQUIRE_FPU;
99 REQUIRE_ZVFBFMIN(ctx);
100
101 if (opfv_widen_check(ctx, a) && (ctx->sew == MO_16)) {
102 uint32_t data = 0;
103 TCGLabel *over = gen_new_label();
104
105 gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
106 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
107 tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
108
109 data = FIELD_DP32(data, VDATA, VM, a->vm);
110 data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
111 data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
112 data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
113 tcg_gen_gvec_3_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
114 vreg_ofs(ctx, a->rs2), cpu_env,
115 ctx->cfg_ptr->vlen / 8,
116 ctx->cfg_ptr->vlen / 8, data,
117 gen_helper_vfwcvtbf16_f_f_v);
118 mark_vs_dirty(ctx);
119 gen_set_label(over);
120 return true;
121 }
122 return false;
123 }
124
125 static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a)
126 {
127 REQUIRE_FPU;
128 REQUIRE_ZVFBFWMA(ctx);
129
130 if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) &&
131 vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) {
132 uint32_t data = 0;
133 TCGLabel *over = gen_new_label();
134
135 gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
136 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
137 tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
138
139 data = FIELD_DP32(data, VDATA, VM, a->vm);
140 data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
141 data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
142 data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
143 tcg_gen_gvec_4_ptr(vreg_ofs(ctx, a->rd), vreg_ofs(ctx, 0),
144 vreg_ofs(ctx, a->rs1),
145 vreg_ofs(ctx, a->rs2), cpu_env,
146 ctx->cfg_ptr->vlen / 8,
147 ctx->cfg_ptr->vlen / 8, data,
148 gen_helper_vfwmaccbf16_vv);
149 mark_vs_dirty(ctx);
150 gen_set_label(over);
151 return true;
152 }
153 return false;
154 }
155
156 static bool trans_vfwmaccbf16_vf(DisasContext *ctx, arg_vfwmaccbf16_vf *a)
157 {
158 REQUIRE_FPU;
159 REQUIRE_ZVFBFWMA(ctx);
160
161 if (require_rvv(ctx) && (ctx->sew == MO_16) && vext_check_isa_ill(ctx) &&
162 vext_check_ds(ctx, a->rd, a->rs2, a->vm)) {
163 uint32_t data = 0;
164
165 gen_set_rm(ctx, RISCV_FRM_DYN);
166 data = FIELD_DP32(data, VDATA, VM, a->vm);
167 data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul);
168 data = FIELD_DP32(data, VDATA, VTA, ctx->vta);
169 data = FIELD_DP32(data, VDATA, VMA, ctx->vma);
170 return opfvf_trans(a->rd, a->rs1, a->rs2, data,
171 gen_helper_vfwmaccbf16_vf, ctx);
172 }
173
174 return false;
175 }