@@ -658,6 +658,9 @@ DEF_HELPER_FLAGS_4(gvec_vcvt_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_vcvt_rz_hs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_vcvt_rz_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vcvt_sd, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_vcvt_ud, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_ss, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_us, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
@@ -9305,141 +9305,44 @@ TRANS_FEAT(FRINT64Z_v, aa64_frint, do_fp1_vector, a,
&f_scalar_frint64, FPROUNDING_ZERO)
TRANS_FEAT(FRINT64X_v, aa64_frint, do_fp1_vector, a, &f_scalar_frint64, -1)
-/* Common vector code for handling integer to FP conversion */
-static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
- int elements, int is_signed,
- int fracbits, int size)
+static bool do_gvec_op2_fpst(DisasContext *s, MemOp esz, bool is_q,
+ int rd, int rn, int data,
+ gen_helper_gvec_2_ptr * const fns[3])
{
- TCGv_ptr tcg_fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
- TCGv_i32 tcg_shift = NULL;
+ int check = fp_access_check_vector_hsd(s, is_q, esz);
+ TCGv_ptr fpst;
- MemOp mop = size | (is_signed ? MO_SIGN : 0);
- int pass;
-
- if (fracbits || size == MO_64) {
- tcg_shift = tcg_constant_i32(fracbits);
+ if (check <= 0) {
+ return check == 0;
}
- if (size == MO_64) {
- TCGv_i64 tcg_int64 = tcg_temp_new_i64();
- TCGv_i64 tcg_double = tcg_temp_new_i64();
-
- for (pass = 0; pass < elements; pass++) {
- read_vec_element(s, tcg_int64, rn, pass, mop);
-
- if (is_signed) {
- gen_helper_vfp_sqtod(tcg_double, tcg_int64,
- tcg_shift, tcg_fpst);
- } else {
- gen_helper_vfp_uqtod(tcg_double, tcg_int64,
- tcg_shift, tcg_fpst);
- }
- if (elements == 1) {
- write_fp_dreg(s, rd, tcg_double);
- } else {
- write_vec_element(s, tcg_double, rd, pass, MO_64);
- }
- }
- } else {
- TCGv_i32 tcg_int32 = tcg_temp_new_i32();
- TCGv_i32 tcg_float = tcg_temp_new_i32();
-
- for (pass = 0; pass < elements; pass++) {
- read_vec_element_i32(s, tcg_int32, rn, pass, mop);
-
- switch (size) {
- case MO_32:
- if (fracbits) {
- if (is_signed) {
- gen_helper_vfp_sltos(tcg_float, tcg_int32,
- tcg_shift, tcg_fpst);
- } else {
- gen_helper_vfp_ultos(tcg_float, tcg_int32,
- tcg_shift, tcg_fpst);
- }
- } else {
- if (is_signed) {
- gen_helper_vfp_sitos(tcg_float, tcg_int32, tcg_fpst);
- } else {
- gen_helper_vfp_uitos(tcg_float, tcg_int32, tcg_fpst);
- }
- }
- break;
- case MO_16:
- if (fracbits) {
- if (is_signed) {
- gen_helper_vfp_sltoh(tcg_float, tcg_int32,
- tcg_shift, tcg_fpst);
- } else {
- gen_helper_vfp_ultoh(tcg_float, tcg_int32,
- tcg_shift, tcg_fpst);
- }
- } else {
- if (is_signed) {
- gen_helper_vfp_sitoh(tcg_float, tcg_int32, tcg_fpst);
- } else {
- gen_helper_vfp_uitoh(tcg_float, tcg_int32, tcg_fpst);
- }
- }
- break;
- default:
- g_assert_not_reached();
- }
-
- if (elements == 1) {
- write_fp_sreg(s, rd, tcg_float);
- } else {
- write_vec_element_i32(s, tcg_float, rd, pass, size);
- }
- }
- }
-
- clear_vec_high(s, elements << size == 16, rd);
+ fpst = fpstatus_ptr(esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd),
+ vec_full_reg_offset(s, rn), fpst,
+ is_q ? 16 : 8, vec_full_reg_size(s),
+ data, fns[esz - 1]);
+ return true;
}
-/* UCVTF/SCVTF - Integer to FP conversion */
-static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
- bool is_q, bool is_u,
- int immh, int immb, int opcode,
- int rn, int rd)
-{
- int size, elements, fracbits;
- int immhb = immh << 3 | immb;
+static gen_helper_gvec_2_ptr * const f_scvtf_v[] = {
+ gen_helper_gvec_vcvt_sh,
+ gen_helper_gvec_vcvt_sf,
+ gen_helper_gvec_vcvt_sd,
+};
+TRANS(SCVTF_vi, do_gvec_op2_fpst,
+ a->esz, a->q, a->rd, a->rn, 0, f_scvtf_v)
+TRANS(SCVTF_vf, do_gvec_op2_fpst,
+ a->esz, a->q, a->rd, a->rn, a->shift, f_scvtf_v)
- if (immh & 8) {
- size = MO_64;
- if (!is_scalar && !is_q) {
- unallocated_encoding(s);
- return;
- }
- } else if (immh & 4) {
- size = MO_32;
- } else if (immh & 2) {
- size = MO_16;
- if (!dc_isar_feature(aa64_fp16, s)) {
- unallocated_encoding(s);
- return;
- }
- } else {
- /* immh == 0 would be a failure of the decode logic */
- g_assert(immh == 1);
- unallocated_encoding(s);
- return;
- }
-
- if (is_scalar) {
- elements = 1;
- } else {
- elements = (8 << is_q) >> size;
- }
- fracbits = (16 << size) - immhb;
-
- if (!fp_access_check(s)) {
- return;
- }
-
- handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
-}
+static gen_helper_gvec_2_ptr * const f_ucvtf_v[] = {
+ gen_helper_gvec_vcvt_uh,
+ gen_helper_gvec_vcvt_uf,
+ gen_helper_gvec_vcvt_ud,
+};
+TRANS(UCVTF_vi, do_gvec_op2_fpst,
+ a->esz, a->q, a->rd, a->rn, 0, f_ucvtf_v)
+TRANS(UCVTF_vf, do_gvec_op2_fpst,
+ a->esz, a->q, a->rd, a->rn, a->shift, f_ucvtf_v)
/* FCVTZS, FVCVTZU - FP to fixedpoint conversion */
static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
@@ -9890,10 +9793,6 @@ static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
}
switch (opcode) {
- case 0x1c: /* SCVTF / UCVTF */
- handle_simd_shift_intfp_conv(s, false, is_q, is_u, immh, immb,
- opcode, rn, rd);
- break;
case 0x1f: /* FCVTZS/ FCVTZU */
handle_simd_shift_fpint_conv(s, false, is_q, is_u, immh, immb, rn, rd);
return;
@@ -9911,6 +9810,7 @@ static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
case 0x12: /* SQSHRN / UQSHRN */
case 0x13: /* SQRSHRN / UQRSHRN */
case 0x14: /* SSHLL / USHLL */
+ case 0x1c: /* SCVTF / UCVTF */
unallocated_encoding(s);
return;
}
@@ -9990,21 +9890,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
size = is_double ? 3 : 2;
switch (opcode) {
- case 0x1d: /* SCVTF */
- case 0x5d: /* UCVTF */
- {
- bool is_signed = (opcode == 0x1d) ? true : false;
- int elements = is_double ? 2 : is_q ? 4 : 2;
- if (is_double && !is_q) {
- unallocated_encoding(s);
- return;
- }
- if (!fp_access_check(s)) {
- return;
- }
- handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
- return;
- }
case 0x2c: /* FCMGT (zero) */
case 0x2d: /* FCMEQ (zero) */
case 0x2e: /* FCMLT (zero) */
@@ -10087,6 +9972,8 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
case 0x1f: /* FRINT64Z */
case 0x5e: /* FRINT32X */
case 0x5f: /* FRINT64X */
+ case 0x1d: /* SCVTF */
+ case 0x5d: /* UCVTF */
unallocated_encoding(s);
return;
}
@@ -10252,24 +10139,6 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
fpop = deposit32(fpop, 6, 1, u);
switch (fpop) {
- case 0x1d: /* SCVTF */
- case 0x5d: /* UCVTF */
- {
- int elements;
-
- if (is_scalar) {
- elements = 1;
- } else {
- elements = (is_q ? 8 : 4);
- }
-
- if (!fp_access_check(s)) {
- return;
- }
- handle_simd_intfp_conv(s, rd, rn, elements, !u, 0, MO_16);
- return;
- }
- break;
case 0x2c: /* FCMGT (zero) */
case 0x2d: /* FCMEQ (zero) */
case 0x2e: /* FCMLT (zero) */
@@ -10323,6 +10192,8 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
case 0x58: /* FRINTA */
case 0x59: /* FRINTX */
case 0x79: /* FRINTI */
+ case 0x1d: /* SCVTF */
+ case 0x5d: /* UCVTF */
unallocated_encoding(s);
return;
}
@@ -2505,12 +2505,15 @@ DO_3OP_PAIR(gvec_uminp_s, MIN, uint32_t, H4)
clear_tail(d, oprsz, simd_maxsz(desc)); \
}
+DO_VCVT_FIXED(gvec_vcvt_sd, helper_vfp_sqtod, uint64_t)
+DO_VCVT_FIXED(gvec_vcvt_ud, helper_vfp_uqtod, uint64_t)
DO_VCVT_FIXED(gvec_vcvt_sf, helper_vfp_sltos, uint32_t)
DO_VCVT_FIXED(gvec_vcvt_uf, helper_vfp_ultos, uint32_t)
-DO_VCVT_FIXED(gvec_vcvt_rz_fs, helper_vfp_tosls_round_to_zero, uint32_t)
-DO_VCVT_FIXED(gvec_vcvt_rz_fu, helper_vfp_touls_round_to_zero, uint32_t)
DO_VCVT_FIXED(gvec_vcvt_sh, helper_vfp_shtoh, uint16_t)
DO_VCVT_FIXED(gvec_vcvt_uh, helper_vfp_uhtoh, uint16_t)
+
+DO_VCVT_FIXED(gvec_vcvt_rz_fs, helper_vfp_tosls_round_to_zero, uint32_t)
+DO_VCVT_FIXED(gvec_vcvt_rz_fu, helper_vfp_touls_round_to_zero, uint32_t)
DO_VCVT_FIXED(gvec_vcvt_rz_hs, helper_vfp_toshh_round_to_zero, uint16_t)
DO_VCVT_FIXED(gvec_vcvt_rz_hu, helper_vfp_touhh_round_to_zero, uint16_t)
@@ -1786,3 +1786,25 @@ FRINT32Z_v 0.00 1110 0.1 00001 11101 0 ..... ..... @qrr_sd
FRINT32X_v 0.10 1110 0.1 00001 11101 0 ..... ..... @qrr_sd
FRINT64Z_v 0.00 1110 0.1 00001 11111 0 ..... ..... @qrr_sd
FRINT64X_v 0.10 1110 0.1 00001 11111 0 ..... ..... @qrr_sd
+
+SCVTF_vi 0.00 1110 011 11001 11011 0 ..... ..... @qrr_h
+SCVTF_vi 0.00 1110 0.1 00001 11011 0 ..... ..... @qrr_sd
+
+UCVTF_vi 0.10 1110 011 11001 11011 0 ..... ..... @qrr_h
+UCVTF_vi 0.10 1110 0.1 00001 11011 0 ..... ..... @qrr_sd
+
+&fcvt_q rd rn esz q shift
+@fcvtq_h . q:1 . ...... 001 .... ...... rn:5 rd:5 \
+ &fcvt_q esz=1 shift=%fcvt_f_sh_h
+@fcvtq_s . q:1 . ...... 01 ..... ...... rn:5 rd:5 \
+ &fcvt_q esz=2 shift=%fcvt_f_sh_s
+@fcvtq_d . q:1 . ...... 1 ...... ...... rn:5 rd:5 \
+ &fcvt_q esz=3 shift=%fcvt_f_sh_d
+
+SCVTF_vf 0.00 11110 ....... 111001 ..... ..... @fcvtq_h
+SCVTF_vf 0.00 11110 ....... 111001 ..... ..... @fcvtq_s
+SCVTF_vf 0.00 11110 ....... 111001 ..... ..... @fcvtq_d
+
+UCVTF_vf 0.10 11110 ....... 111001 ..... ..... @fcvtq_h
+UCVTF_vf 0.10 11110 ....... 111001 ..... ..... @fcvtq_s
+UCVTF_vf 0.10 11110 ....... 111001 ..... ..... @fcvtq_d
Remove handle_simd_intfp_conv and handle_simd_shift_intfp_conv as these were the last insns decoded by those functions. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/arm/helper.h | 3 + target/arm/tcg/translate-a64.c | 201 ++++++--------------------------- target/arm/tcg/vec_helper.c | 7 +- target/arm/tcg/a64.decode | 22 ++++ 4 files changed, 66 insertions(+), 167 deletions(-)