target/arm: Pass separate addend to FCMLA helpers
For SVE, we potentially have a 4th argument coming from the movprfx instruction. Currently we do not optimize movprfx, so the problem is not visible. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210525010358.152808-51-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
bc2bd6974e
commit
636ddeb15c
@ -629,16 +629,16 @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
|
||||
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fcmlah, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fcmlas, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_6(gvec_fcmlad, TCG_CALL_NO_RWG,
|
||||
void, ptr, ptr, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(neon_paddh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(neon_pmaxh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
|
@ -694,6 +694,23 @@ static void gen_gvec_op4_ool(DisasContext *s, bool is_q, int rd, int rn,
|
||||
is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand a 4-operand + fpstatus pointer + simd data value operation using
|
||||
* an out-of-line helper.
|
||||
*/
|
||||
static void gen_gvec_op4_fpst(DisasContext *s, bool is_q, int rd, int rn,
|
||||
int rm, int ra, bool is_fp16, int data,
|
||||
gen_helper_gvec_4_ptr *fn)
|
||||
{
|
||||
TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR);
|
||||
tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, rd),
|
||||
vec_full_reg_offset(s, rn),
|
||||
vec_full_reg_offset(s, rm),
|
||||
vec_full_reg_offset(s, ra), fpst,
|
||||
is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
|
||||
tcg_temp_free_ptr(fpst);
|
||||
}
|
||||
|
||||
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
|
||||
* than the 32 bit equivalent.
|
||||
*/
|
||||
@ -12205,15 +12222,15 @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
|
||||
rot = extract32(opcode, 0, 2);
|
||||
switch (size) {
|
||||
case 1:
|
||||
gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
|
||||
gen_gvec_op4_fpst(s, is_q, rd, rn, rm, rd, true, rot,
|
||||
gen_helper_gvec_fcmlah);
|
||||
break;
|
||||
case 2:
|
||||
gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
|
||||
gen_gvec_op4_fpst(s, is_q, rd, rn, rm, rd, false, rot,
|
||||
gen_helper_gvec_fcmlas);
|
||||
break;
|
||||
case 3:
|
||||
gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
|
||||
gen_gvec_op4_fpst(s, is_q, rd, rn, rm, rd, false, rot,
|
||||
gen_helper_gvec_fcmlad);
|
||||
break;
|
||||
default:
|
||||
@ -13464,9 +13481,10 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
|
||||
{
|
||||
int rot = extract32(insn, 13, 2);
|
||||
int data = (index << 2) | rot;
|
||||
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
|
||||
tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, rd),
|
||||
vec_full_reg_offset(s, rn),
|
||||
vec_full_reg_offset(s, rm), fpst,
|
||||
vec_full_reg_offset(s, rm),
|
||||
vec_full_reg_offset(s, rd), fpst,
|
||||
is_q ? 16 : 8, vec_full_reg_size(s), data,
|
||||
size == MO_64
|
||||
? gen_helper_gvec_fcmlas_idx
|
||||
|
@ -155,7 +155,7 @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
|
||||
{
|
||||
int opr_sz;
|
||||
TCGv_ptr fpst;
|
||||
gen_helper_gvec_3_ptr *fn_gvec_ptr;
|
||||
gen_helper_gvec_4_ptr *fn_gvec_ptr;
|
||||
|
||||
if (!dc_isar_feature(aa32_vcma, s)
|
||||
|| (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
|
||||
@ -180,9 +180,10 @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
|
||||
fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
|
||||
fn_gvec_ptr = (a->size == MO_16) ?
|
||||
gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas;
|
||||
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
|
||||
tcg_gen_gvec_4_ptr(vfp_reg_offset(1, a->vd),
|
||||
vfp_reg_offset(1, a->vn),
|
||||
vfp_reg_offset(1, a->vm),
|
||||
vfp_reg_offset(1, a->vd),
|
||||
fpst, opr_sz, opr_sz, a->rot,
|
||||
fn_gvec_ptr);
|
||||
tcg_temp_free_ptr(fpst);
|
||||
@ -293,7 +294,7 @@ static bool trans_VFML(DisasContext *s, arg_VFML *a)
|
||||
|
||||
static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
|
||||
{
|
||||
gen_helper_gvec_3_ptr *fn_gvec_ptr;
|
||||
gen_helper_gvec_4_ptr *fn_gvec_ptr;
|
||||
int opr_sz;
|
||||
TCGv_ptr fpst;
|
||||
|
||||
@ -322,9 +323,10 @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
|
||||
gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx;
|
||||
opr_sz = (1 + a->q) * 8;
|
||||
fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
|
||||
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
|
||||
tcg_gen_gvec_4_ptr(vfp_reg_offset(1, a->vd),
|
||||
vfp_reg_offset(1, a->vn),
|
||||
vfp_reg_offset(1, a->vm),
|
||||
vfp_reg_offset(1, a->vd),
|
||||
fpst, opr_sz, opr_sz,
|
||||
(a->index << 2) | a->rot, fn_gvec_ptr);
|
||||
tcg_temp_free_ptr(fpst);
|
||||
|
@ -4383,7 +4383,7 @@ static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a)
|
||||
|
||||
static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a)
|
||||
{
|
||||
static gen_helper_gvec_3_ptr * const fns[2] = {
|
||||
static gen_helper_gvec_4_ptr * const fns[2] = {
|
||||
gen_helper_gvec_fcmlah_idx,
|
||||
gen_helper_gvec_fcmlas_idx,
|
||||
};
|
||||
@ -4393,9 +4393,10 @@ static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a)
|
||||
if (sve_access_check(s)) {
|
||||
unsigned vsz = vec_full_reg_size(s);
|
||||
TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
|
||||
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
|
||||
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,
|
||||
a->index * 4 + a->rot,
|
||||
fns[a->esz - 1]);
|
||||
|
@ -657,13 +657,11 @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
|
||||
void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm, void *va,
|
||||
void *vfpst, uint32_t desc)
|
||||
{
|
||||
uintptr_t opr_sz = simd_oprsz(desc);
|
||||
float16 *d = vd;
|
||||
float16 *n = vn;
|
||||
float16 *m = vm;
|
||||
float16 *d = vd, *n = vn, *m = vm, *a = va;
|
||||
float_status *fpst = vfpst;
|
||||
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
|
||||
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
|
||||
@ -680,19 +678,17 @@ void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
|
||||
float16 e4 = e2;
|
||||
float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
|
||||
|
||||
d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
|
||||
d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
|
||||
d[H2(i)] = float16_muladd(e2, e1, a[H2(i)], 0, fpst);
|
||||
d[H2(i + 1)] = float16_muladd(e4, e3, a[H2(i + 1)], 0, fpst);
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
|
||||
void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm, void *va,
|
||||
void *vfpst, uint32_t desc)
|
||||
{
|
||||
uintptr_t opr_sz = simd_oprsz(desc);
|
||||
float16 *d = vd;
|
||||
float16 *n = vn;
|
||||
float16 *m = vm;
|
||||
float16 *d = vd, *n = vn, *m = vm, *a = va;
|
||||
float_status *fpst = vfpst;
|
||||
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
|
||||
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
|
||||
@ -716,20 +712,18 @@ void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
|
||||
float16 e2 = n[H2(j + flip)];
|
||||
float16 e4 = e2;
|
||||
|
||||
d[H2(j)] = float16_muladd(e2, e1, d[H2(j)], 0, fpst);
|
||||
d[H2(j + 1)] = float16_muladd(e4, e3, d[H2(j + 1)], 0, fpst);
|
||||
d[H2(j)] = float16_muladd(e2, e1, a[H2(j)], 0, fpst);
|
||||
d[H2(j + 1)] = float16_muladd(e4, e3, a[H2(j + 1)], 0, fpst);
|
||||
}
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
|
||||
void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm, void *va,
|
||||
void *vfpst, uint32_t desc)
|
||||
{
|
||||
uintptr_t opr_sz = simd_oprsz(desc);
|
||||
float32 *d = vd;
|
||||
float32 *n = vn;
|
||||
float32 *m = vm;
|
||||
float32 *d = vd, *n = vn, *m = vm, *a = va;
|
||||
float_status *fpst = vfpst;
|
||||
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
|
||||
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
|
||||
@ -746,19 +740,17 @@ void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
|
||||
float32 e4 = e2;
|
||||
float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
|
||||
|
||||
d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
|
||||
d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
|
||||
d[H4(i)] = float32_muladd(e2, e1, a[H4(i)], 0, fpst);
|
||||
d[H4(i + 1)] = float32_muladd(e4, e3, a[H4(i + 1)], 0, fpst);
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
|
||||
void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm, void *va,
|
||||
void *vfpst, uint32_t desc)
|
||||
{
|
||||
uintptr_t opr_sz = simd_oprsz(desc);
|
||||
float32 *d = vd;
|
||||
float32 *n = vn;
|
||||
float32 *m = vm;
|
||||
float32 *d = vd, *n = vn, *m = vm, *a = va;
|
||||
float_status *fpst = vfpst;
|
||||
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
|
||||
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
|
||||
@ -782,20 +774,18 @@ void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
|
||||
float32 e2 = n[H4(j + flip)];
|
||||
float32 e4 = e2;
|
||||
|
||||
d[H4(j)] = float32_muladd(e2, e1, d[H4(j)], 0, fpst);
|
||||
d[H4(j + 1)] = float32_muladd(e4, e3, d[H4(j + 1)], 0, fpst);
|
||||
d[H4(j)] = float32_muladd(e2, e1, a[H4(j)], 0, fpst);
|
||||
d[H4(j + 1)] = float32_muladd(e4, e3, a[H4(j + 1)], 0, fpst);
|
||||
}
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
||||
void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
|
||||
void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm, void *va,
|
||||
void *vfpst, uint32_t desc)
|
||||
{
|
||||
uintptr_t opr_sz = simd_oprsz(desc);
|
||||
float64 *d = vd;
|
||||
float64 *n = vn;
|
||||
float64 *m = vm;
|
||||
float64 *d = vd, *n = vn, *m = vm, *a = va;
|
||||
float_status *fpst = vfpst;
|
||||
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
|
||||
uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
|
||||
@ -812,8 +802,8 @@ void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
|
||||
float64 e4 = e2;
|
||||
float64 e3 = m[i + 1 - flip] ^ neg_imag;
|
||||
|
||||
d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
|
||||
d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
|
||||
d[i] = float64_muladd(e2, e1, a[i], 0, fpst);
|
||||
d[i + 1] = float64_muladd(e4, e3, a[i + 1], 0, fpst);
|
||||
}
|
||||
clear_tail(d, opr_sz, simd_maxsz(desc));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user