target/arm: Implement VFP vp16 VCVT-with-specified-rounding-mode
Implement the fp16 versions of the VFP VCVT instruction forms which convert between floating point and integer with a specified rounding mode. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20200828183354.27913-17-peter.maydell@linaro.org
This commit is contained in:
parent
a149e2de0b
commit
c505bc6a9d
@ -396,7 +396,7 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
|
||||
static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
|
||||
{
|
||||
uint32_t rd, rm;
|
||||
bool dp = a->dp;
|
||||
int sz = a->sz;
|
||||
TCGv_ptr fpst;
|
||||
TCGv_i32 tcg_rmode, tcg_shift;
|
||||
int rounding = fp_decode_rm[a->rm];
|
||||
@ -406,12 +406,16 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
|
||||
if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* UNDEF accesses to D16-D31 if they don't exist */
|
||||
if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
|
||||
if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -422,14 +426,18 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sz == 1) {
|
||||
fpst = fpstatus_ptr(FPST_FPCR_F16);
|
||||
} else {
|
||||
fpst = fpstatus_ptr(FPST_FPCR);
|
||||
}
|
||||
|
||||
tcg_shift = tcg_const_i32(0);
|
||||
|
||||
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
|
||||
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
|
||||
|
||||
if (dp) {
|
||||
if (sz == 3) {
|
||||
TCGv_i64 tcg_double, tcg_res;
|
||||
TCGv_i32 tcg_tmp;
|
||||
tcg_double = tcg_temp_new_i64();
|
||||
@ -451,11 +459,19 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
|
||||
tcg_single = tcg_temp_new_i32();
|
||||
tcg_res = tcg_temp_new_i32();
|
||||
neon_load_reg32(tcg_single, rm);
|
||||
if (sz == 1) {
|
||||
if (is_signed) {
|
||||
gen_helper_vfp_toslh(tcg_res, tcg_single, tcg_shift, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_toulh(tcg_res, tcg_single, tcg_shift, fpst);
|
||||
}
|
||||
} else {
|
||||
if (is_signed) {
|
||||
gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
|
||||
}
|
||||
}
|
||||
neon_store_reg32(tcg_res, rd);
|
||||
tcg_temp_free_i32(tcg_res);
|
||||
tcg_temp_free_i32(tcg_single);
|
||||
|
@ -64,7 +64,9 @@ VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
|
||||
vm=%vm_dp vd=%vd_dp dp=1
|
||||
|
||||
# VCVT float to int with specified rounding mode; Vd is always single-precision
|
||||
VCVT 1111 1110 1.11 11 rm:2 .... 1001 op:1 1.0 .... \
|
||||
vm=%vm_sp vd=%vd_sp sz=1
|
||||
VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
|
||||
vm=%vm_sp vd=%vd_sp dp=0
|
||||
vm=%vm_sp vd=%vd_sp sz=2
|
||||
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
|
||||
vm=%vm_dp vd=%vd_sp dp=1
|
||||
vm=%vm_dp vd=%vd_sp sz=3
|
||||
|
Loading…
Reference in New Issue
Block a user