Commit e3d6f429 authored by Peter Maydell's avatar Peter Maydell
Browse files

target/arm: Convert VCVT fp/fixed-point conversion insns to decodetree



Convert the VCVT (between floating-point and fixed-point) instructions
to decodetree.

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent 92073e94
Loading
Loading
Loading
Loading
+124 −0
Original line number Diff line number Diff line
@@ -2454,3 +2454,127 @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
    tcg_temp_free_i32(vd);
    return true;
}

static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
{
    TCGv_i32 vd, shift;
    TCGv_ptr fpst;
    int frac_bits;

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

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

    frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);

    vd = tcg_temp_new_i32();
    neon_load_reg32(vd, a->vd);

    fpst = get_fpstatus_ptr(false);
    shift = tcg_const_i32(frac_bits);

    /* Switch on op:U:sx bits */
    switch (a->opc) {
    case 0:
        gen_helper_vfp_shtos(vd, vd, shift, fpst);
        break;
    case 1:
        gen_helper_vfp_sltos(vd, vd, shift, fpst);
        break;
    case 2:
        gen_helper_vfp_uhtos(vd, vd, shift, fpst);
        break;
    case 3:
        gen_helper_vfp_ultos(vd, vd, shift, fpst);
        break;
    case 4:
        gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
        break;
    case 5:
        gen_helper_vfp_tosls_round_to_zero(vd, vd, shift, fpst);
        break;
    case 6:
        gen_helper_vfp_touhs_round_to_zero(vd, vd, shift, fpst);
        break;
    case 7:
        gen_helper_vfp_touls_round_to_zero(vd, vd, shift, fpst);
        break;
    default:
        g_assert_not_reached();
    }

    neon_store_reg32(vd, a->vd);
    tcg_temp_free_i32(vd);
    tcg_temp_free_i32(shift);
    tcg_temp_free_ptr(fpst);
    return true;
}

static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
{
    TCGv_i64 vd;
    TCGv_i32 shift;
    TCGv_ptr fpst;
    int frac_bits;

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

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

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

    frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);

    vd = tcg_temp_new_i64();
    neon_load_reg64(vd, a->vd);

    fpst = get_fpstatus_ptr(false);
    shift = tcg_const_i32(frac_bits);

    /* Switch on op:U:sx bits */
    switch (a->opc) {
    case 0:
        gen_helper_vfp_shtod(vd, vd, shift, fpst);
        break;
    case 1:
        gen_helper_vfp_sltod(vd, vd, shift, fpst);
        break;
    case 2:
        gen_helper_vfp_uhtod(vd, vd, shift, fpst);
        break;
    case 3:
        gen_helper_vfp_ultod(vd, vd, shift, fpst);
        break;
    case 4:
        gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
        break;
    case 5:
        gen_helper_vfp_tosld_round_to_zero(vd, vd, shift, fpst);
        break;
    case 6:
        gen_helper_vfp_touhd_round_to_zero(vd, vd, shift, fpst);
        break;
    case 7:
        gen_helper_vfp_tould_round_to_zero(vd, vd, shift, fpst);
        break;
    default:
        g_assert_not_reached();
    }

    neon_store_reg64(vd, a->vd);
    tcg_temp_free_i64(vd);
    tcg_temp_free_i32(shift);
    tcg_temp_free_ptr(fpst);
    return true;
}
+2 −55
Original line number Diff line number Diff line
@@ -1439,13 +1439,9 @@ static inline void gen_vfp_##name(int dp, int shift, int neon) \
    tcg_temp_free_i32(tmp_shift); \
    tcg_temp_free_ptr(statusptr); \
}
VFP_GEN_FIX(tosh, _round_to_zero)
VFP_GEN_FIX(tosl, _round_to_zero)
VFP_GEN_FIX(touh, _round_to_zero)
VFP_GEN_FIX(toul, _round_to_zero)
VFP_GEN_FIX(shto, )
VFP_GEN_FIX(slto, )
VFP_GEN_FIX(uhto, )
VFP_GEN_FIX(ulto, )
#undef VFP_GEN_FIX

@@ -3050,7 +3046,8 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
                return 1;
            case 15:
                switch (rn) {
                case 0 ... 19:
                case 0 ... 23:
                case 28 ... 31:
                    /* Already handled by decodetree */
                    return 1;
                default:
@@ -3070,21 +3067,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
                    rd_is_dp = false;
                    break;

                case 0x14: /* vcvt fp <-> fixed */
                case 0x15:
                case 0x16:
                case 0x17:
                case 0x1c:
                case 0x1d:
                case 0x1e:
                case 0x1f:
                    if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
                        return 1;
                    }
                    /* Immediate frac_bits has same format as SREG_M.  */
                    rm_is_dp = false;
                    break;

                default:
                    return 1;
                }
@@ -3143,17 +3125,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
            /* Load the initial operands.  */
            if (op == 15) {
                switch (rn) {
                case 0x14: /* vcvt fp <-> fixed */
                case 0x15:
                case 0x16:
                case 0x17:
                case 0x1c:
                case 0x1d:
                case 0x1e:
                case 0x1f:
                    /* Source and destination the same.  */
                    gen_mov_F0_vreg(dp, rd);
                    break;
                default:
                    /* One source operand.  */
                    gen_mov_F0_vreg(rm_is_dp, rm);
@@ -3170,18 +3141,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
                switch (op) {
                case 15: /* extension space */
                    switch (rn) {
                    case 20: /* fshto */
                        gen_vfp_shto(dp, 16 - rm, 0);
                        break;
                    case 21: /* fslto */
                        gen_vfp_slto(dp, 32 - rm, 0);
                        break;
                    case 22: /* fuhto */
                        gen_vfp_uhto(dp, 16 - rm, 0);
                        break;
                    case 23: /* fulto */
                        gen_vfp_ulto(dp, 32 - rm, 0);
                        break;
                    case 24: /* ftoui */
                        gen_vfp_toui(dp, 0);
                        break;
@@ -3194,18 +3153,6 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
                    case 27: /* ftosiz */
                        gen_vfp_tosiz(dp, 0);
                        break;
                    case 28: /* ftosh */
                        gen_vfp_tosh(dp, 16 - rm, 0);
                        break;
                    case 29: /* ftosl */
                        gen_vfp_tosl(dp, 32 - rm, 0);
                        break;
                    case 30: /* ftouh */
                        gen_vfp_touh(dp, 16 - rm, 0);
                        break;
                    case 31: /* ftoul */
                        gen_vfp_toul(dp, 32 - rm, 0);
                        break;
                    default: /* undefined */
                        g_assert_not_reached();
                    }
+10 −0
Original line number Diff line number Diff line
@@ -224,3 +224,13 @@ VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
# VJCVT is always dp to sp
VJCVT        ---- 1110 1.11 1001 .... 1011 11.0 .... \
             vd=%vd_sp vm=%vm_dp

# VCVT between floating-point and fixed-point. The immediate value
# is in the same format as a Vm single-precision register number.
# We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field
# for the convenience of the trans_VCVT_fix functions.
%vcvt_fix_op 18:1 16:1 7:1
VCVT_fix_sp  ---- 1110 1.11 1.1. .... 1010 .1.0 .... \
             vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
VCVT_fix_dp  ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
             vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op