|  | @@ -92,3 +92,165 @@ u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exce
 | 
	
		
			
				|  |  |  	exponent = vd->exponent;
 | 
	
		
			
				|  |  |  	significand = vd->significand;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	shift = 32 - fls(significand >> 32);
 | 
	
		
			
				|  |  | +	if (shift == 32)
 | 
	
		
			
				|  |  | +		shift = 64 - fls(significand);
 | 
	
		
			
				|  |  | +	if (shift) {
 | 
	
		
			
				|  |  | +		exponent -= shift;
 | 
	
		
			
				|  |  | +		significand <<= shift;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +	vd->exponent = exponent;
 | 
	
		
			
				|  |  | +	vd->significand = significand;
 | 
	
		
			
				|  |  | +	vfp_double_dump("pack: normalised", vd);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Tiny number?
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	underflow = exponent < 0;
 | 
	
		
			
				|  |  | +	if (underflow) {
 | 
	
		
			
				|  |  | +		significand = vfp_shiftright64jamming(significand, -exponent);
 | 
	
		
			
				|  |  | +		exponent = 0;
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +		vd->exponent = exponent;
 | 
	
		
			
				|  |  | +		vd->significand = significand;
 | 
	
		
			
				|  |  | +		vfp_double_dump("pack: tiny number", vd);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +		if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1)))
 | 
	
		
			
				|  |  | +			underflow = 0;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Select rounding increment.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	incr = 0;
 | 
	
		
			
				|  |  | +	rmode = fpscr & FPSCR_RMODE_MASK;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (rmode == FPSCR_ROUND_NEAREST) {
 | 
	
		
			
				|  |  | +		incr = 1ULL << VFP_DOUBLE_LOW_BITS;
 | 
	
		
			
				|  |  | +		if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0)
 | 
	
		
			
				|  |  | +			incr -= 1;
 | 
	
		
			
				|  |  | +	} else if (rmode == FPSCR_ROUND_TOZERO) {
 | 
	
		
			
				|  |  | +		incr = 0;
 | 
	
		
			
				|  |  | +	} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
 | 
	
		
			
				|  |  | +		incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pr_debug("VFP: rounding increment = 0x%08llx\n", incr);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Is our rounding going to overflow?
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if ((significand + incr) < significand) {
 | 
	
		
			
				|  |  | +		exponent += 1;
 | 
	
		
			
				|  |  | +		significand = (significand >> 1) | (significand & 1);
 | 
	
		
			
				|  |  | +		incr >>= 1;
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +		vd->exponent = exponent;
 | 
	
		
			
				|  |  | +		vd->significand = significand;
 | 
	
		
			
				|  |  | +		vfp_double_dump("pack: overflow", vd);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * If any of the low bits (which will be shifted out of the
 | 
	
		
			
				|  |  | +	 * number) are non-zero, the result is inexact.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1))
 | 
	
		
			
				|  |  | +		exceptions |= FPSCR_IXC;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Do our rounding.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	significand += incr;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Infinity?
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (exponent >= 2046) {
 | 
	
		
			
				|  |  | +		exceptions |= FPSCR_OFC | FPSCR_IXC;
 | 
	
		
			
				|  |  | +		if (incr == 0) {
 | 
	
		
			
				|  |  | +			vd->exponent = 2045;
 | 
	
		
			
				|  |  | +			vd->significand = 0x7fffffffffffffffULL;
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			vd->exponent = 2047;		/* infinity */
 | 
	
		
			
				|  |  | +			vd->significand = 0;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +		if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0)
 | 
	
		
			
				|  |  | +			exponent = 0;
 | 
	
		
			
				|  |  | +		if (exponent || significand > 0x8000000000000000ULL)
 | 
	
		
			
				|  |  | +			underflow = 0;
 | 
	
		
			
				|  |  | +		if (underflow)
 | 
	
		
			
				|  |  | +			exceptions |= FPSCR_UFC;
 | 
	
		
			
				|  |  | +		vd->exponent = exponent;
 | 
	
		
			
				|  |  | +		vd->significand = significand >> 1;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | + pack:
 | 
	
		
			
				|  |  | +	vfp_double_dump("pack: final", vd);
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		s64 d = vfp_double_pack(vd);
 | 
	
		
			
				|  |  | +		pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
 | 
	
		
			
				|  |  | +			 dd, d, exceptions);
 | 
	
		
			
				|  |  | +		vfp_put_double(d, dd);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return exceptions;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Propagate the NaN, setting exceptions if it is signalling.
 | 
	
		
			
				|  |  | + * 'n' is always a NaN.  'm' may be a number, NaN or infinity.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static u32
 | 
	
		
			
				|  |  | +vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
 | 
	
		
			
				|  |  | +		  struct vfp_double *vdm, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct vfp_double *nan;
 | 
	
		
			
				|  |  | +	int tn, tm = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	tn = vfp_double_type(vdn);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (vdm)
 | 
	
		
			
				|  |  | +		tm = vfp_double_type(vdm);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (fpscr & FPSCR_DEFAULT_NAN)
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * Default NaN mode - always returns a quiet NaN
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		nan = &vfp_double_default_qnan;
 | 
	
		
			
				|  |  | +	else {
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * Contemporary mode - select the first signalling
 | 
	
		
			
				|  |  | +		 * NAN, or if neither are signalling, the first
 | 
	
		
			
				|  |  | +		 * quiet NAN.
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN))
 | 
	
		
			
				|  |  | +			nan = vdn;
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +			nan = vdm;
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * Make the NaN quiet.
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	*vdd = *nan;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * If one was a signalling NAN, raise invalid operation.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Extended operations
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static u32 vfp_double_fabs(int dd, int unused, int dm, u32 fpscr)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	vfp_put_double(vfp_double_packed_abs(vfp_get_double(dm)), dd);
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static u32 vfp_double_fcpy(int dd, int unused, int dm, u32 fpscr)
 |