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