Richard Henderson <richard.hender...@linaro.org> writes: > While we have some of the scalar paths for FCVT for fp16, > we failed to decode the fp16 version of these instructions. > > Signed-off-by: Richard Henderson <richard.hender...@linaro.org> > --- > target/arm/translate-a64.c | 65 > ++++++++++++++++++++++++++++++++-------------- > 1 file changed, 46 insertions(+), 19 deletions(-) > > diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c > index c92e052686..e2d11998bd 100644 > --- a/target/arm/translate-a64.c > +++ b/target/arm/translate-a64.c > @@ -7120,19 +7120,28 @@ static void handle_simd_shift_fpint_conv(DisasContext > *s, bool is_scalar, > bool is_q, bool is_u, > int immh, int immb, int rn, int rd) > { > - bool is_double = extract32(immh, 3, 1); > int immhb = immh << 3 | immb; > - int fracbits = (is_double ? 128 : 64) - immhb; > - int pass; > + int pass, size, fracbits; > TCGv_ptr tcg_fpstatus; > TCGv_i32 tcg_rmode, tcg_shift; > > - if (!extract32(immh, 2, 2)) { > - unallocated_encoding(s); > - return; > - } > - > - if (!is_scalar && !is_q && is_double) { > + if (immh & 0x8) { > + size = MO_64; > + if (!is_scalar && !is_q) { > + unallocated_encoding(s); > + return; > + } > + } else if (immh & 0x4) { > + size = MO_32; > + } else if (immh & 0x2) { > + size = MO_16; > + if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) { > + unallocated_encoding(s); > + return; > + } > + } else { > + /* Should have split out AdvSIMD modified immediate earlier. */ > + assert(immh == 1); > unallocated_encoding(s); > return; > } > @@ -7144,11 +7153,12 @@ static void handle_simd_shift_fpint_conv(DisasContext > *s, bool is_scalar, > assert(!(is_scalar && is_q)); > > tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO)); > - tcg_fpstatus = get_fpstatus_ptr(false); > + tcg_fpstatus = get_fpstatus_ptr(size == MO_16); > gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus); > + fracbits = (16 << size) - immhb; > tcg_shift = tcg_const_i32(fracbits); > > - if (is_double) { > + if (size == 3) { > int maxpass = is_scalar ? 1 : 2; > > for (pass = 0; pass < maxpass; pass++) { > @@ -7165,20 +7175,37 @@ static void handle_simd_shift_fpint_conv(DisasContext > *s, bool is_scalar, > } > clear_vec_high(s, is_q, rd); > } else { > - int maxpass = is_scalar ? 1 : is_q ? 4 : 2; > + void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr); > + int maxpass = is_scalar ? 1 : (8 << is_q >> size);
brackets > + > + switch (size) { > + case MO_16: > + if (is_u) { > + fn = gen_helper_vfp_toulh; > + } else { > + fn = gen_helper_vfp_toslh; > + } > + break; > + case MO_32: > + if (is_u) { > + fn = gen_helper_vfp_touls; > + } else { > + fn = gen_helper_vfp_tosls; > + } > + break; > + default: > + g_assert_not_reached(); > + } > + > for (pass = 0; pass < maxpass; pass++) { > TCGv_i32 tcg_op = tcg_temp_new_i32(); > > - read_vec_element_i32(s, tcg_op, rn, pass, MO_32); > - if (is_u) { > - gen_helper_vfp_touls(tcg_op, tcg_op, tcg_shift, > tcg_fpstatus); > - } else { > - gen_helper_vfp_tosls(tcg_op, tcg_op, tcg_shift, > tcg_fpstatus); > - } > + read_vec_element_i32(s, tcg_op, rn, pass, size); > + fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus); > if (is_scalar) { > write_fp_sreg(s, rd, tcg_op); > } else { > - write_vec_element_i32(s, tcg_op, rd, pass, MO_32); > + write_vec_element_i32(s, tcg_op, rd, pass, size); > } > tcg_temp_free_i32(tcg_op); > } -- Alex Bennée