Commit 74343409 authored by Richard Henderson's avatar Richard Henderson Committed by Blue Swirl
Browse files

target-alpha: Make use of fp_status.flush_inputs_to_zero.



This softfp feature post-dates the last major update to the Alpha
fpu translation.  We can make use of this to eliminate at least
one helper function that was performing this operation by hand.

Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarBlue Swirl <blauwirbel@gmail.com>
parent c3082755
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -234,7 +234,6 @@ struct CPUAlphaState {
    uint8_t fpcr_exc_mask;
    uint8_t fpcr_dyn_round;
    uint8_t fpcr_flush_to_zero;
    uint8_t fpcr_dnz;
    uint8_t fpcr_dnod;
    uint8_t fpcr_undz;

+10 −34
Original line number Diff line number Diff line
@@ -88,22 +88,18 @@ void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
    }
}

/* Input remapping without software completion.  Handle denormal-map-to-zero
   and trap for all other non-finite numbers.  */
uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
/* Input handing without software completion.  Trap for all
   non-finite numbers.  */
void helper_ieee_input(CPUAlphaState *env, uint64_t val)
{
    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
    uint64_t frac = val & 0xfffffffffffffull;

    if (exp == 0) {
        if (frac != 0) {
            /* If DNZ is set flush denormals to zero on input.  */
            if (env->fpcr_dnz) {
                val &= 1ull << 63;
            } else {
        /* Denormals without DNZ set raise an exception.  */
        if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
            arith_excp(env, GETPC(), EXC_M_UNF, 0);
        }
        }
    } else if (exp == 0x7ff) {
        /* Infinity or NaN.  */
        /* ??? I'm not sure these exception bit flags are correct.  I do
@@ -111,43 +107,23 @@ uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
           just emulates the insn to figure out what exception to use.  */
        arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
    }
    return val;
}

/* Similar, but does not trap for infinities.  Used for comparisons.  */
uint64_t helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
{
    uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
    uint64_t frac = val & 0xfffffffffffffull;

    if (exp == 0) {
        if (frac != 0) {
            /* If DNZ is set flush denormals to zero on input.  */
            if (env->fpcr_dnz) {
                val &= 1ull << 63;
            } else {
        /* Denormals without DNZ set raise an exception.  */
        if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
            arith_excp(env, GETPC(), EXC_M_UNF, 0);
        }
        }
    } else if (exp == 0x7ff && frac) {
        /* NaN.  */
        arith_excp(env, GETPC(), EXC_M_INV, 0);
    }
    return val;
}

/* Input remapping with software completion enabled.  All we have to do
   is handle denormal-map-to-zero; all other inputs get exceptions as
   needed from the actual operation.  */
uint64_t helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
{
    if (env->fpcr_dnz) {
        uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
        if (exp == 0) {
            val &= 1ull << 63;
        }
    }
    return val;
}

/* F floating (VAX) */
+3 −5
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
        break;
    }

    if (env->fpcr_dnz) {
    if (env->fp_status.flush_inputs_to_zero) {
        r |= FPCR_DNZ;
    }
    if (env->fpcr_dnod) {
@@ -151,12 +151,10 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
    }
    env->fpcr_dyn_round = t;

    env->fpcr_flush_to_zero
      = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);

    env->fpcr_dnz = (val & FPCR_DNZ) != 0;
    env->fpcr_dnod = (val & FPCR_DNOD) != 0;
    env->fpcr_undz = (val & FPCR_UNDZ) != 0;
    env->fpcr_flush_to_zero = env->fpcr_dnod & env->fpcr_undz;
    env->fp_status.flush_inputs_to_zero = (val & FPCR_DNZ) != 0;
}

uint64_t helper_load_fpcr(CPUAlphaState *env)
+2 −3
Original line number Diff line number Diff line
@@ -95,9 +95,8 @@ DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env)
DEF_HELPER_3(fp_exc_raise, void, env, i32, i32)
DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32)

DEF_HELPER_2(ieee_input, i64, env, i64)
DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
DEF_HELPER_2(ieee_input_s, i64, env, i64)
DEF_HELPER_2(ieee_input, void, env, i64)
DEF_HELPER_2(ieee_input_cmp, void, env, i64)

#if !defined (CONFIG_USER_ONLY)
DEF_HELPER_2(hw_ret, void, env, i64)
+11 −7
Original line number Diff line number Diff line
@@ -661,15 +661,19 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)

static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
{
    TCGv val = tcg_temp_new();
    TCGv val;
    if (reg == 31) {
        tcg_gen_movi_i64(val, 0);
    } else if (fn11 & QUAL_S) {
        gen_helper_ieee_input_s(val, cpu_env, cpu_fir[reg]);
    } else if (is_cmp) {
        gen_helper_ieee_input_cmp(val, cpu_env, cpu_fir[reg]);
        val = tcg_const_i64(0);
    } else {
        if ((fn11 & QUAL_S) == 0) {
            if (is_cmp) {
                gen_helper_ieee_input_cmp(cpu_env, cpu_fir[reg]);
            } else {
        gen_helper_ieee_input(val, cpu_env, cpu_fir[reg]);
                gen_helper_ieee_input(cpu_env, cpu_fir[reg]);
            }
        }
        val = tcg_temp_new();
        tcg_gen_mov_i64(val, cpu_fir[reg]);
    }
    return val;
}