target/arm: Implement bfloat widening fma (vector)
This is BFMLAL{B,T} for both AArch64 AdvSIMD and SVE, and VFMA{B,T}.BF16 for AArch32 NEON. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210525225817.400336-10-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
81266a1f58
commit
5693887f2e
@ -1010,6 +1010,9 @@ DEF_HELPER_FLAGS_5(gvec_bfdot_idx, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_5(gvec_bfmmla, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_6(gvec_bfmlal, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, i32)
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
#include "helper-a64.h"
|
||||
#include "helper-sve.h"
|
||||
|
@ -70,6 +70,9 @@ VUSMMLA 1111 1100 1.10 .... .... 1100 .1.0 .... \
|
||||
VMMLA_b16 1111 1100 0.00 .... .... 1100 .1.0 .... \
|
||||
vm=%vm_dp vn=%vn_dp vd=%vd_dp
|
||||
|
||||
VFMA_b16 1111 110 0 0.11 .... .... 1000 . q:1 . 1 .... \
|
||||
vm=%vm_dp vn=%vn_dp vd=%vd_dp
|
||||
|
||||
VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
|
||||
vn=%vn_dp vd=%vd_dp size=1
|
||||
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
|
||||
|
@ -1627,6 +1627,9 @@ FMLALT_zzzw 01100100 10 1 ..... 10 0 00 1 ..... ..... @rda_rn_rm_e0
|
||||
FMLSLB_zzzw 01100100 10 1 ..... 10 1 00 0 ..... ..... @rda_rn_rm_e0
|
||||
FMLSLT_zzzw 01100100 10 1 ..... 10 1 00 1 ..... ..... @rda_rn_rm_e0
|
||||
|
||||
BFMLALB_zzzw 01100100 11 1 ..... 10 0 00 0 ..... ..... @rda_rn_rm_e0
|
||||
BFMLALT_zzzw 01100100 11 1 ..... 10 0 00 1 ..... ..... @rda_rn_rm_e0
|
||||
|
||||
### SVE2 floating-point bfloat16 dot-product
|
||||
BFDOT_zzzz 01100100 01 1 ..... 10 0 00 0 ..... ..... @rda_rn_rm_e0
|
||||
|
||||
|
@ -12242,9 +12242,10 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
|
||||
}
|
||||
feature = dc_isar_feature(aa64_bf16, s);
|
||||
break;
|
||||
case 0x1f: /* BFDOT */
|
||||
case 0x1f:
|
||||
switch (size) {
|
||||
case 1:
|
||||
case 1: /* BFDOT */
|
||||
case 3: /* BFMLAL{B,T} */
|
||||
feature = dc_isar_feature(aa64_bf16, s);
|
||||
break;
|
||||
default:
|
||||
@ -12338,11 +12339,15 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
|
||||
case 0xd: /* BFMMLA */
|
||||
gen_gvec_op4_ool(s, is_q, rd, rn, rm, rd, 0, gen_helper_gvec_bfmmla);
|
||||
return;
|
||||
case 0xf: /* BFDOT */
|
||||
case 0xf:
|
||||
switch (size) {
|
||||
case 1:
|
||||
case 1: /* BFDOT */
|
||||
gen_gvec_op4_ool(s, is_q, rd, rn, rm, rd, 0, gen_helper_gvec_bfdot);
|
||||
break;
|
||||
case 3: /* BFMLAL{B,T} */
|
||||
gen_gvec_op4_fpst(s, 1, rd, rn, rm, rd, false, is_q,
|
||||
gen_helper_gvec_bfmlal);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -4135,3 +4135,12 @@ static bool trans_VMMLA_b16(DisasContext *s, arg_VMMLA_b16 *a)
|
||||
return do_neon_ddda(s, 7, a->vd, a->vn, a->vm, 0,
|
||||
gen_helper_gvec_bfmmla);
|
||||
}
|
||||
|
||||
static bool trans_VFMA_b16(DisasContext *s, arg_VFMA_b16 *a)
|
||||
{
|
||||
if (!dc_isar_feature(aa32_bf16, s)) {
|
||||
return false;
|
||||
}
|
||||
return do_neon_ddda_fpst(s, 7, a->vd, a->vn, a->vm, a->q, FPST_STD,
|
||||
gen_helper_gvec_bfmlal);
|
||||
}
|
||||
|
@ -8689,3 +8689,33 @@ static bool trans_BFMMLA(DisasContext *s, arg_rrrr_esz *a)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_BFMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel)
|
||||
{
|
||||
if (!dc_isar_feature(aa64_sve_bf16, s)) {
|
||||
return false;
|
||||
}
|
||||
if (sve_access_check(s)) {
|
||||
TCGv_ptr status = fpstatus_ptr(FPST_FPCR);
|
||||
unsigned vsz = vec_full_reg_size(s);
|
||||
|
||||
tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
|
||||
vec_full_reg_offset(s, a->rn),
|
||||
vec_full_reg_offset(s, a->rm),
|
||||
vec_full_reg_offset(s, a->ra),
|
||||
status, vsz, vsz, sel,
|
||||
gen_helper_gvec_bfmlal);
|
||||
tcg_temp_free_ptr(status);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_BFMLALB_zzzw(DisasContext *s, arg_rrrr_esz *a)
|
||||
{
|
||||
return do_BFMLAL_zzzw(s, a, false);
|
||||
}
|
||||
|
||||
static bool trans_BFMLALT_zzzw(DisasContext *s, arg_rrrr_esz *a)
|
||||
{
|
||||
return do_BFMLAL_zzzw(s, a, true);
|
||||
}
|
||||
|
@ -2512,3 +2512,19 @@ void HELPER(gvec_bfmmla)(void *vd, void *vn, void *vm, void *va, uint32_t desc)
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
void HELPER(gvec_bfmlal)(void *vd, void *vn, void *vm, void *va,
|
||||
void *stat, uint32_t desc)
|
||||
{
|
||||
intptr_t i, opr_sz = simd_oprsz(desc);
|
||||
intptr_t sel = simd_data(desc);
|
||||
float32 *d = vd, *a = va;
|
||||
bfloat16 *n = vn, *m = vm;
|
||||
|
||||
for (i = 0; i < opr_sz / 4; ++i) {
|
||||
float32 nn = n[H2(i * 2 + sel)] << 16;
|
||||
float32 mm = m[H2(i * 2 + sel)] << 16;
|
||||
d[H4(i)] = float32_muladd(nn, mm, a[H4(i)], 0, stat);
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user