target/arm: Introduce fp_access_check_scalar_hsd

Provide a simple way to check for float64, float32,
and float16 support, as well as the fpu enabled.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20241211163036.2297116-21-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2024-12-11 10:29:47 -06:00 committed by Peter Maydell
parent 32f0661573
commit 648e654efa

View File

@ -1239,6 +1239,27 @@ static bool fp_access_check(DisasContext *s)
return true; return true;
} }
/*
* Return <0 for non-supported element sizes, with MO_16 controlled by
* FEAT_FP16; return 0 for fp disabled; otherwise return >0 for success.
*/
static int fp_access_check_scalar_hsd(DisasContext *s, MemOp esz)
{
switch (esz) {
case MO_64:
case MO_32:
break;
case MO_16:
if (!dc_isar_feature(aa64_fp16, s)) {
return -1;
}
break;
default:
return -1;
}
return fp_access_check(s);
}
/* /*
* Check that SVE access is enabled. If it is, return true. * Check that SVE access is enabled. If it is, return true.
* If not, emit code to generate an appropriate exception and return false. * If not, emit code to generate an appropriate exception and return false.
@ -6628,22 +6649,10 @@ static bool trans_FCSEL(DisasContext *s, arg_FCSEL *a)
{ {
TCGv_i64 t_true, t_false; TCGv_i64 t_true, t_false;
DisasCompare64 c; DisasCompare64 c;
int check = fp_access_check_scalar_hsd(s, a->esz);
switch (a->esz) { if (check <= 0) {
case MO_32: return check == 0;
case MO_64:
break;
case MO_16:
if (!dc_isar_feature(aa64_fp16, s)) {
return false;
}
break;
default:
return false;
}
if (!fp_access_check(s)) {
return true;
} }
/* Zero extend sreg & hreg inputs to 64 bits now. */ /* Zero extend sreg & hreg inputs to 64 bits now. */
@ -6894,22 +6903,15 @@ TRANS(FMINV_s, do_fp_reduction, a, gen_helper_vfp_mins)
static bool trans_FMOVI_s(DisasContext *s, arg_FMOVI_s *a) static bool trans_FMOVI_s(DisasContext *s, arg_FMOVI_s *a)
{ {
switch (a->esz) { int check = fp_access_check_scalar_hsd(s, a->esz);
case MO_32: uint64_t imm;
case MO_64:
break; if (check <= 0) {
case MO_16: return check == 0;
if (!dc_isar_feature(aa64_fp16, s)) {
return false;
}
break;
default:
return false;
}
if (fp_access_check(s)) {
uint64_t imm = vfp_expand_imm(a->esz, a->imm);
write_fp_dreg(s, a->rd, tcg_constant_i64(imm));
} }
imm = vfp_expand_imm(a->esz, a->imm);
write_fp_dreg(s, a->rd, tcg_constant_i64(imm));
return true; return true;
} }