target/arm: Split VFM decode

Passing the raw o1 and o2 fields from the manual is less
instructive than it might be.  Do the full decode and let
the trans_* functions pass in booleans to a helper.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200224222232.13807-17-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2020-02-24 14:22:31 -08:00 committed by Peter Maydell
parent 906b60facc
commit d486f8308a
2 changed files with 55 additions and 14 deletions

View file

@ -1784,7 +1784,7 @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
}
static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
{
/*
* VFNMA : fd = muladd(-fd, fn, fm)
@ -1828,12 +1828,12 @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
neon_load_reg32(vn, a->vn);
neon_load_reg32(vm, a->vm);
if (a->o2) {
if (neg_n) {
/* VFNMS, VFMS */
gen_helper_vfp_negs(vn, vn);
}
neon_load_reg32(vd, a->vd);
if (a->o1 & 1) {
if (neg_d) {
/* VFNMA, VFNMS */
gen_helper_vfp_negs(vd, vd);
}
@ -1849,7 +1849,27 @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
return true;
}
static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
static bool trans_VFMA_sp(DisasContext *s, arg_VFMA_sp *a)
{
return do_vfm_sp(s, a, false, false);
}
static bool trans_VFMS_sp(DisasContext *s, arg_VFMS_sp *a)
{
return do_vfm_sp(s, a, true, false);
}
static bool trans_VFNMA_sp(DisasContext *s, arg_VFNMA_sp *a)
{
return do_vfm_sp(s, a, false, true);
}
static bool trans_VFNMS_sp(DisasContext *s, arg_VFNMS_sp *a)
{
return do_vfm_sp(s, a, true, true);
}
static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
{
/*
* VFNMA : fd = muladd(-fd, fn, fm)
@ -1905,12 +1925,12 @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
neon_load_reg64(vn, a->vn);
neon_load_reg64(vm, a->vm);
if (a->o2) {
if (neg_n) {
/* VFNMS, VFMS */
gen_helper_vfp_negd(vn, vn);
}
neon_load_reg64(vd, a->vd);
if (a->o1 & 1) {
if (neg_d) {
/* VFNMA, VFNMS */
gen_helper_vfp_negd(vd, vd);
}
@ -1926,6 +1946,26 @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
return true;
}
static bool trans_VFMA_dp(DisasContext *s, arg_VFMA_dp *a)
{
return do_vfm_dp(s, a, false, false);
}
static bool trans_VFMS_dp(DisasContext *s, arg_VFMS_dp *a)
{
return do_vfm_dp(s, a, true, false);
}
static bool trans_VFNMA_dp(DisasContext *s, arg_VFNMA_dp *a)
{
return do_vfm_dp(s, a, false, true);
}
static bool trans_VFNMS_dp(DisasContext *s, arg_VFNMS_dp *a)
{
return do_vfm_dp(s, a, true, true);
}
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
{
uint32_t delta_d = 0;

View file

@ -130,14 +130,15 @@ VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
VFM_sp ---- 1110 1.01 .... .... 1010 . o2:1 . 0 .... \
vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=1
VFM_dp ---- 1110 1.01 .... .... 1011 . o2:1 . 0 .... \
vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=1
VFM_sp ---- 1110 1.10 .... .... 1010 . o2:1 . 0 .... \
vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=2
VFM_dp ---- 1110 1.10 .... .... 1011 . o2:1 . 0 .... \
vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=2
VFMA_sp ---- 1110 1.10 .... .... 1010 .0. 0 .... @vfp_dnm_s
VFMS_sp ---- 1110 1.10 .... .... 1010 .1. 0 .... @vfp_dnm_s
VFNMA_sp ---- 1110 1.01 .... .... 1010 .0. 0 .... @vfp_dnm_s
VFNMS_sp ---- 1110 1.01 .... .... 1010 .1. 0 .... @vfp_dnm_s
VFMA_dp ---- 1110 1.10 .... .... 1011 .0.0 .... @vfp_dnm_d
VFMS_dp ---- 1110 1.10 .... .... 1011 .1.0 .... @vfp_dnm_d
VFNMA_dp ---- 1110 1.01 .... .... 1011 .0.0 .... @vfp_dnm_d
VFNMS_dp ---- 1110 1.01 .... .... 1011 .1.0 .... @vfp_dnm_d
VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
vd=%vd_sp imm=%vmov_imm