Revision e07be5d2 target-arm/helper.c

b/target-arm/helper.c
2755 2755
    return make_float32(val32);
2756 2756
}
2757 2757

  
2758
/* The algorithm that must be used to calculate the estimate
2759
 * is specified by the ARM ARM.
2760
 */
2761
static float64 recip_sqrt_estimate(float64 a, CPUState *env)
2762
{
2763
    float_status *s = &env->vfp.standard_fp_status;
2764
    float64 q;
2765
    int64_t q_int;
2766

  
2767
    if (float64_lt(a, float64_half, s)) {
2768
        /* range 0.25 <= a < 0.5 */
2769

  
2770
        /* a in units of 1/512 rounded down */
2771
        /* q0 = (int)(a * 512.0);  */
2772
        q = float64_mul(float64_512, a, s);
2773
        q_int = float64_to_int64_round_to_zero(q, s);
2774

  
2775
        /* reciprocal root r */
2776
        /* r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0);  */
2777
        q = int64_to_float64(q_int, s);
2778
        q = float64_add(q, float64_half, s);
2779
        q = float64_div(q, float64_512, s);
2780
        q = float64_sqrt(q, s);
2781
        q = float64_div(float64_one, q, s);
2782
    } else {
2783
        /* range 0.5 <= a < 1.0 */
2784

  
2785
        /* a in units of 1/256 rounded down */
2786
        /* q1 = (int)(a * 256.0); */
2787
        q = float64_mul(float64_256, a, s);
2788
        int64_t q_int = float64_to_int64_round_to_zero(q, s);
2789

  
2790
        /* reciprocal root r */
2791
        /* r = 1.0 /sqrt(((double)q1 + 0.5) / 256); */
2792
        q = int64_to_float64(q_int, s);
2793
        q = float64_add(q, float64_half, s);
2794
        q = float64_div(q, float64_256, s);
2795
        q = float64_sqrt(q, s);
2796
        q = float64_div(float64_one, q, s);
2797
    }
2798
    /* r in units of 1/256 rounded to nearest */
2799
    /* s = (int)(256.0 * r + 0.5); */
2800

  
2801
    q = float64_mul(q, float64_256,s );
2802
    q = float64_add(q, float64_half, s);
2803
    q_int = float64_to_int64_round_to_zero(q, s);
2804

  
2805
    /* return (double)s / 256.0;*/
2806
    return float64_div(int64_to_float64(q_int, s), float64_256, s);
2807
}
2808

  
2758 2809
float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
2759 2810
{
2760
    float_status *s = &env->vfp.fp_status;
2761
    float32 one = int32_to_float32(1, s);
2762
    return float32_div(one, float32_sqrt(a, s), s);
2811
    float_status *s = &env->vfp.standard_fp_status;
2812
    int result_exp;
2813
    float64 f64;
2814
    uint32_t val;
2815
    uint64_t val64;
2816

  
2817
    val = float32_val(a);
2818

  
2819
    if (float32_is_any_nan(a)) {
2820
        if (float32_is_signaling_nan(a)) {
2821
            float_raise(float_flag_invalid, s);
2822
        }
2823
        return float32_default_nan;
2824
    } else if (float32_is_zero_or_denormal(a)) {
2825
        float_raise(float_flag_divbyzero, s);
2826
        return float32_set_sign(float32_infinity, float32_is_neg(a));
2827
    } else if (float32_is_neg(a)) {
2828
        float_raise(float_flag_invalid, s);
2829
        return float32_default_nan;
2830
    } else if (float32_is_infinity(a)) {
2831
        return float32_zero;
2832
    }
2833

  
2834
    /* Normalize to a double-precision value between 0.25 and 1.0,
2835
     * preserving the parity of the exponent.  */
2836
    if ((val & 0x800000) == 0) {
2837
        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
2838
                           | (0x3feULL << 52)
2839
                           | ((uint64_t)(val & 0x7fffff) << 29));
2840
    } else {
2841
        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
2842
                           | (0x3fdULL << 52)
2843
                           | ((uint64_t)(val & 0x7fffff) << 29));
2844
    }
2845

  
2846
    result_exp = (380 - ((val & 0x7f800000) >> 23)) / 2;
2847

  
2848
    f64 = recip_sqrt_estimate(f64, env);
2849

  
2850
    val64 = float64_val(f64);
2851

  
2852
    val = ((val64 >> 63)  & 0x80000000)
2853
        | ((result_exp & 0xff) << 23)
2854
        | ((val64 >> 29)  & 0x7fffff);
2855
    return make_float32(val);
2763 2856
}
2764 2857

  
2765 2858
uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
......
2780 2873

  
2781 2874
uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
2782 2875
{
2783
    float_status *s = &env->vfp.fp_status;
2784
    float32 tmp;
2785
    tmp = int32_to_float32(a, s);
2786
    tmp = float32_scalbn(tmp, -32, s);
2787
    tmp = helper_rsqrte_f32(tmp, env);
2788
    tmp = float32_scalbn(tmp, 31, s);
2789
    return float32_to_int32(tmp, s);
2876
    float64 f64;
2877

  
2878
    if ((a & 0xc0000000) == 0) {
2879
        return 0xffffffff;
2880
    }
2881

  
2882
    if (a & 0x80000000) {
2883
        f64 = make_float64((0x3feULL << 52)
2884
                           | ((uint64_t)(a & 0x7fffffff) << 21));
2885
    } else { /* bits 31-30 == '01' */
2886
        f64 = make_float64((0x3fdULL << 52)
2887
                           | ((uint64_t)(a & 0x3fffffff) << 22));
2888
    }
2889

  
2890
    f64 = recip_sqrt_estimate(f64, env);
2891

  
2892
    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
2790 2893
}
2791 2894

  
2792 2895
void HELPER(set_teecr)(CPUState *env, uint32_t val)

Also available in: Unified diff