| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 | /* *  linux/arch/arm/vfp/vfpsingle.c * * This code is derived in part from John R. Housers softfloat library, which * carries the following notice: * * =========================================================================== * This C source file is part of the SoftFloat IEC/IEEE Floating-point * Arithmetic Package, Release 2. * * Written by John R. Hauser.  This work was made possible in part by the * International Computer Science Institute, located at Suite 600, 1947 Center * Street, Berkeley, California 94704.  Funding was partially provided by the * National Science Foundation under grant MIP-9311980.  The original version * of this code was written as part of a project to build a fixed-point vector * processor in collaboration with the University of California at Berkeley, * overseen by Profs. Nelson Morgan and John Wawrzynek.  More information * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ * arithmetic/softfloat.html'. * * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT * TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. * * Derivative works are acceptable, even for commercial purposes, so long as * (1) they include prominent notice that the work is derivative, and (2) they * include prominent notice akin to these three paragraphs for those parts of * this code that are retained. * =========================================================================== */#include <linux/kernel.h>#include <linux/bitops.h>#include <asm/div64.h>#include <asm/vfp.h>#include "vfpinstr.h"#include "vfp.h"static struct vfp_single vfp_single_default_qnan = {	.exponent	= 255,	.sign		= 0,	.significand	= VFP_SINGLE_SIGNIFICAND_QNAN,};static void vfp_single_dump(const char *str, struct vfp_single *s){	pr_debug("VFP: %s: sign=%d exponent=%d significand=%08x\n",		 str, s->sign != 0, s->exponent, s->significand);}static void vfp_single_normalise_denormal(struct vfp_single *vs){	int bits = 31 - fls(vs->significand);	vfp_single_dump("normalise_denormal: in", vs);	if (bits) {		vs->exponent -= bits - 1;		vs->significand <<= bits;	}	vfp_single_dump("normalise_denormal: out", vs);}#ifndef DEBUG#define vfp_single_normaliseround(sd,vsd,fpscr,except,func) __vfp_single_normaliseround(sd,vsd,fpscr,except)u32 __vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions)#elseu32 vfp_single_normaliseround(int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func)#endif{	u32 significand, incr, rmode;	int exponent, shift, underflow;	vfp_single_dump("pack: in", vs);	/*	 * Infinities and NaNs are a special case.	 */	if (vs->exponent == 255 && (vs->significand == 0 || exceptions))		goto pack;	/*	 * Special-case zero.	 */	if (vs->significand == 0) {		vs->exponent = 0;		goto pack;	}	exponent = vs->exponent;	significand = vs->significand;	/*	 * Normalise first.  Note that we shift the significand up to	 * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least	 * significant bit.	 */	shift = 32 - fls(significand);	if (shift < 32 && shift) {		exponent -= shift;		significand <<= shift;	}
 |