|  | @@ -331,3 +331,193 @@ static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  |  			ret = 0;
 | 
	
		
			
				|  |  |  		} else {
 | 
	
		
			
				|  |  |   sqrt_invalid:
 | 
	
		
			
				|  |  | +			vsp = &vfp_single_default_qnan;
 | 
	
		
			
				|  |  | +			ret = FPSCR_IOC;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		vfp_put_float(vfp_single_pack(vsp), sd);
 | 
	
		
			
				|  |  | +		return ret;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * sqrt(+/- 0) == +/- 0
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (tm & VFP_ZERO)
 | 
	
		
			
				|  |  | +		goto sqrt_copy;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Normalise a denormalised number
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (tm & VFP_DENORMAL)
 | 
	
		
			
				|  |  | +		vfp_single_normalise_denormal(&vsm);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * sqrt(<0) = invalid
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (vsm.sign)
 | 
	
		
			
				|  |  | +		goto sqrt_invalid;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	vfp_single_dump("sqrt", &vsm);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Estimate the square root.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	vsd.sign = 0;
 | 
	
		
			
				|  |  | +	vsd.exponent = ((vsm.exponent - 127) >> 1) + 127;
 | 
	
		
			
				|  |  | +	vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	vfp_single_dump("sqrt estimate", &vsd);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * And now adjust.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) {
 | 
	
		
			
				|  |  | +		if (vsd.significand < 2) {
 | 
	
		
			
				|  |  | +			vsd.significand = 0xffffffff;
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			u64 term;
 | 
	
		
			
				|  |  | +			s64 rem;
 | 
	
		
			
				|  |  | +			vsm.significand <<= !(vsm.exponent & 1);
 | 
	
		
			
				|  |  | +			term = (u64)vsd.significand * vsd.significand;
 | 
	
		
			
				|  |  | +			rem = ((u64)vsm.significand << 32) - term;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			pr_debug("VFP: term=%016llx rem=%016llx\n", term, rem);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			while (rem < 0) {
 | 
	
		
			
				|  |  | +				vsd.significand -= 1;
 | 
	
		
			
				|  |  | +				rem += ((u64)vsd.significand << 1) | 1;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			vsd.significand |= rem != 0;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	vsd.significand = vfp_shiftright32jamming(vsd.significand, 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return vfp_single_normaliseround(sd, &vsd, fpscr, 0, "fsqrt");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Equal	:= ZC
 | 
	
		
			
				|  |  | + * Less than	:= N
 | 
	
		
			
				|  |  | + * Greater than	:= C
 | 
	
		
			
				|  |  | + * Unordered	:= CV
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static u32 vfp_compare(int sd, int signal_on_qnan, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	s32 d;
 | 
	
		
			
				|  |  | +	u32 ret = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	d = vfp_get_float(sd);
 | 
	
		
			
				|  |  | +	if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
 | 
	
		
			
				|  |  | +		ret |= FPSCR_C | FPSCR_V;
 | 
	
		
			
				|  |  | +		if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * Signalling NaN, or signalling on quiet NaN
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			ret |= FPSCR_IOC;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
 | 
	
		
			
				|  |  | +		ret |= FPSCR_C | FPSCR_V;
 | 
	
		
			
				|  |  | +		if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * Signalling NaN, or signalling on quiet NaN
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			ret |= FPSCR_IOC;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (ret == 0) {
 | 
	
		
			
				|  |  | +		if (d == m || vfp_single_packed_abs(d | m) == 0) {
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * equal
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			ret |= FPSCR_Z | FPSCR_C;
 | 
	
		
			
				|  |  | +		} else if (vfp_single_packed_sign(d ^ m)) {
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * different signs
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			if (vfp_single_packed_sign(d))
 | 
	
		
			
				|  |  | +				/*
 | 
	
		
			
				|  |  | +				 * d is negative, so d < m
 | 
	
		
			
				|  |  | +				 */
 | 
	
		
			
				|  |  | +				ret |= FPSCR_N;
 | 
	
		
			
				|  |  | +			else
 | 
	
		
			
				|  |  | +				/*
 | 
	
		
			
				|  |  | +				 * d is positive, so d > m
 | 
	
		
			
				|  |  | +				 */
 | 
	
		
			
				|  |  | +				ret |= FPSCR_C;
 | 
	
		
			
				|  |  | +		} else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) {
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * d < m
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			ret |= FPSCR_N;
 | 
	
		
			
				|  |  | +		} else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) {
 | 
	
		
			
				|  |  | +			/*
 | 
	
		
			
				|  |  | +			 * d > m
 | 
	
		
			
				|  |  | +			 */
 | 
	
		
			
				|  |  | +			ret |= FPSCR_C;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return ret;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static u32 vfp_single_fcmp(int sd, int unused, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return vfp_compare(sd, 0, m, fpscr);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static u32 vfp_single_fcmpe(int sd, int unused, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return vfp_compare(sd, 1, m, fpscr);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static u32 vfp_single_fcmpz(int sd, int unused, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return vfp_compare(sd, 0, 0, fpscr);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static u32 vfp_single_fcmpez(int sd, int unused, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return vfp_compare(sd, 1, 0, fpscr);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static u32 vfp_single_fcvtd(int dd, int unused, s32 m, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct vfp_single vsm;
 | 
	
		
			
				|  |  | +	struct vfp_double vdd;
 | 
	
		
			
				|  |  | +	int tm;
 | 
	
		
			
				|  |  | +	u32 exceptions = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	vfp_single_unpack(&vsm, m);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	tm = vfp_single_type(&vsm);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * If we have a signalling NaN, signal invalid operation.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (tm == VFP_SNAN)
 | 
	
		
			
				|  |  | +		exceptions = FPSCR_IOC;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (tm & VFP_DENORMAL)
 | 
	
		
			
				|  |  | +		vfp_single_normalise_denormal(&vsm);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	vdd.sign = vsm.sign;
 | 
	
		
			
				|  |  | +	vdd.significand = (u64)vsm.significand << 32;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * If we have an infinity or NaN, the exponent must be 2047.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (tm & (VFP_INFINITY|VFP_NAN)) {
 | 
	
		
			
				|  |  | +		vdd.exponent = 2047;
 | 
	
		
			
				|  |  | +		if (tm == VFP_QNAN)
 | 
	
		
			
				|  |  | +			vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
 | 
	
		
			
				|  |  | +		goto pack_nan;
 | 
	
		
			
				|  |  | +	} else if (tm & VFP_ZERO)
 | 
	
		
			
				|  |  | +		vdd.exponent = 0;
 | 
	
		
			
				|  |  | +	else
 | 
	
		
			
				|  |  | +		vdd.exponent = vsm.exponent + (1023 - 127);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | + pack_nan:
 | 
	
		
			
				|  |  | +	vfp_put_double(vfp_double_pack(&vdd), dd);
 | 
	
		
			
				|  |  | +	return exceptions;
 | 
	
		
			
				|  |  | +}
 |