| 
					
				 | 
			
			
				@@ -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) 
			 |