Commit 3da26f11 authored by Peter Maydell's avatar Peter Maydell
Browse files

target/arm: Convert VCVT fixed-point ops to decodetree



Convert the VCVT fixed-point conversion operations in the
Neon 2-regs-and-shift group to decodetree.

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-id: 20200522145520.6778-9-peter.maydell@linaro.org
parent 968bf842
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -251,6 +251,10 @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
@2reg_shll_b     .... ... . . . 001 shift:3  .... .... 0 . . . .... \
                 &2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0

# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
@2reg_vcvt       .... ... . . . 1 ..... .... .... . q:1 . . .... \
                 &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5

VSHR_S_2sh       1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
VSHR_S_2sh       1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
VSHR_S_2sh       1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
@@ -364,3 +368,10 @@ VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
VSHLL_U_2sh      1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
VSHLL_U_2sh      1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
VSHLL_U_2sh      1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b

# VCVT fixed<->float conversions
# TODO: FP16 fixed<->float conversions are opc==0b1100 and 0b1101
VCVT_SF_2sh      1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
VCVT_UF_2sh      1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
VCVT_FS_2sh      1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
VCVT_FU_2sh      1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
+49 −0
Original line number Diff line number Diff line
@@ -1659,3 +1659,52 @@ static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
    };
    return do_vshll_2sh(s, a, widenfn[a->size], true);
}

static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
                      NeonGenTwoSingleOPFn *fn)
{
    /* FP operations in 2-reg-and-shift group */
    TCGv_i32 tmp, shiftv;
    TCGv_ptr fpstatus;
    int pass;

    if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
        return false;
    }

    /* UNDEF accesses to D16-D31 if they don't exist. */
    if (!dc_isar_feature(aa32_simd_r32, s) &&
        ((a->vd | a->vm) & 0x10)) {
        return false;
    }

    if ((a->vm | a->vd) & a->q) {
        return false;
    }

    if (!vfp_access_check(s)) {
        return true;
    }

    fpstatus = get_fpstatus_ptr(1);
    shiftv = tcg_const_i32(a->shift);
    for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
        tmp = neon_load_reg(a->vm, pass);
        fn(tmp, tmp, shiftv, fpstatus);
        neon_store_reg(a->vd, pass, tmp);
    }
    tcg_temp_free_ptr(fpstatus);
    tcg_temp_free_i32(shiftv);
    return true;
}

#define DO_FP_2SH(INSN, FUNC)                                           \
    static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a)  \
    {                                                                   \
        return do_fp_2sh(s, a, FUNC);                                   \
    }

DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
+2 −73
Original line number Diff line number Diff line
@@ -5193,7 +5193,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
    int q;
    int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
    int size;
    int shift;
    int pass;
    int u;
    int vec_size;
@@ -5234,78 +5233,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
        return 1;
    } else if (insn & (1 << 4)) {
        if ((insn & 0x00380080) != 0) {
            /* Two registers and shift.  */
            op = (insn >> 8) & 0xf;

            switch (op) {
            case 0: /* VSHR */
            case 1: /* VSRA */
            case 2: /* VRSHR */
            case 3: /* VRSRA */
            case 4: /* VSRI */
            case 5: /* VSHL, VSLI */
            case 6: /* VQSHLU */
            case 7: /* VQSHL */
            case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
            case 9: /* VQSHRN, VQRSHRN */
            case 10: /* VSHLL, including VMOVL */
                return 1; /* handled by decodetree */
            default:
                break;
            }

            if (insn & (1 << 7)) {
                /* 64-bit shift. */
                if (op > 7) {
                    return 1;
                }
                size = 3;
            } else {
                size = 2;
                while ((insn & (1 << (size + 19))) == 0)
                    size--;
            }
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
            if (op >= 14) {
                /* VCVT fixed-point.  */
                TCGv_ptr fpst;
                TCGv_i32 shiftv;
                VFPGenFixPointFn *fn;

                if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
            /* Two registers and shift: handled by decodetree */
            return 1;
                }

                if (!(op & 1)) {
                    if (u) {
                        fn = gen_helper_vfp_ultos;
                    } else {
                        fn = gen_helper_vfp_sltos;
                    }
                } else {
                    if (u) {
                        fn = gen_helper_vfp_touls_round_to_zero;
                    } else {
                        fn = gen_helper_vfp_tosls_round_to_zero;
                    }
                }

                /* We have already masked out the must-be-1 top bit of imm6,
                 * hence this 32-shift where the ARM ARM has 64-imm6.
                 */
                shift = 32 - shift;
                fpst = get_fpstatus_ptr(1);
                shiftv = tcg_const_i32(shift);
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
                    TCGv_i32 tmpf = neon_load_reg(rm, pass);
                    fn(tmpf, tmpf, shiftv, fpst);
                    neon_store_reg(rd, pass, tmpf);
                }
                tcg_temp_free_ptr(fpst);
                tcg_temp_free_i32(shiftv);
            } else {
                return 1;
            }
        } else { /* (insn & 0x00380080) == 0 */
            int invert, reg_ofs, vec_size;