xref: /openbmc/linux/arch/parisc/math-emu/denormal.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Floating-point emulation code
61da177e4SLinus Torvalds  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds  * BEGIN_DESC
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  File:
121da177e4SLinus Torvalds  *	@(#)	pa/fp/denormal.c		$ Revision: $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	<<please update with a synopsis of the functionality provided by this file>>
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  External Interfaces:
181da177e4SLinus Torvalds  *	<<the following list was autogenerated, please review>>
191da177e4SLinus Torvalds  *	dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
201da177e4SLinus Torvalds  *	sgl_denormalize(sgl_opnd,inexactflag,rmode)
211da177e4SLinus Torvalds  *
221da177e4SLinus Torvalds  *  Internal Interfaces:
231da177e4SLinus Torvalds  *	<<please update>>
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  *  Theory:
261da177e4SLinus Torvalds  *	<<please update with a overview of the operation of this file>>
271da177e4SLinus Torvalds  *
281da177e4SLinus Torvalds  * END_DESC
291da177e4SLinus Torvalds */
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds #include "float.h"
341da177e4SLinus Torvalds #include "sgl_float.h"
351da177e4SLinus Torvalds #include "dbl_float.h"
361da177e4SLinus Torvalds #include "hppa.h"
371da177e4SLinus Torvalds #include <linux/kernel.h>
381da177e4SLinus Torvalds /* #include <machine/sys/mdep_private.h> */
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds #undef Fpustatus_register
411da177e4SLinus Torvalds #define Fpustatus_register Fpu_register[0]
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds void
sgl_denormalize(unsigned int * sgl_opnd,boolean * inexactflag,int rmode)441da177e4SLinus Torvalds sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds 	unsigned int opnd;
471da177e4SLinus Torvalds 	int sign, exponent;
481da177e4SLinus Torvalds 	boolean guardbit = FALSE, stickybit, inexact;
491da177e4SLinus Torvalds 
501da177e4SLinus Torvalds 	opnd = *sgl_opnd;
511da177e4SLinus Torvalds 	stickybit = *inexactflag;
521da177e4SLinus Torvalds         exponent = Sgl_exponent(opnd) - SGL_WRAP;
531da177e4SLinus Torvalds         sign = Sgl_sign(opnd);
541da177e4SLinus Torvalds 	Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
551da177e4SLinus Torvalds 	if (inexact) {
561da177e4SLinus Torvalds 	    switch (rmode) {
571da177e4SLinus Torvalds 	      case ROUNDPLUS:
581da177e4SLinus Torvalds 		if (sign == 0) {
591da177e4SLinus Torvalds 			Sgl_increment(opnd);
601da177e4SLinus Torvalds 		}
611da177e4SLinus Torvalds 		break;
621da177e4SLinus Torvalds 	      case ROUNDMINUS:
631da177e4SLinus Torvalds 		if (sign != 0) {
641da177e4SLinus Torvalds 			Sgl_increment(opnd);
651da177e4SLinus Torvalds 		}
661da177e4SLinus Torvalds 		break;
671da177e4SLinus Torvalds 	      case ROUNDNEAREST:
681da177e4SLinus Torvalds 		if (guardbit && (stickybit ||
691da177e4SLinus Torvalds 		       Sgl_isone_lowmantissa(opnd))) {
701da177e4SLinus Torvalds 			   Sgl_increment(opnd);
711da177e4SLinus Torvalds 		}
721da177e4SLinus Torvalds 		break;
731da177e4SLinus Torvalds 	    }
741da177e4SLinus Torvalds 	}
751da177e4SLinus Torvalds 	Sgl_set_sign(opnd,sign);
761da177e4SLinus Torvalds 	*sgl_opnd = opnd;
771da177e4SLinus Torvalds 	*inexactflag = inexact;
781da177e4SLinus Torvalds 	return;
791da177e4SLinus Torvalds }
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds void
dbl_denormalize(unsigned int * dbl_opndp1,unsigned int * dbl_opndp2,boolean * inexactflag,int rmode)821da177e4SLinus Torvalds dbl_denormalize(unsigned int *dbl_opndp1,
831da177e4SLinus Torvalds 	unsigned int * dbl_opndp2,
841da177e4SLinus Torvalds 	boolean *inexactflag,
851da177e4SLinus Torvalds 	int rmode)
861da177e4SLinus Torvalds {
871da177e4SLinus Torvalds 	unsigned int opndp1, opndp2;
881da177e4SLinus Torvalds 	int sign, exponent;
891da177e4SLinus Torvalds 	boolean guardbit = FALSE, stickybit, inexact;
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds 	opndp1 = *dbl_opndp1;
921da177e4SLinus Torvalds 	opndp2 = *dbl_opndp2;
931da177e4SLinus Torvalds 	stickybit = *inexactflag;
941da177e4SLinus Torvalds 	exponent = Dbl_exponent(opndp1) - DBL_WRAP;
951da177e4SLinus Torvalds 	sign = Dbl_sign(opndp1);
961da177e4SLinus Torvalds 	Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
971da177e4SLinus Torvalds 	if (inexact) {
981da177e4SLinus Torvalds 	    switch (rmode) {
991da177e4SLinus Torvalds 	      case ROUNDPLUS:
1001da177e4SLinus Torvalds 		if (sign == 0) {
1011da177e4SLinus Torvalds 			Dbl_increment(opndp1,opndp2);
1021da177e4SLinus Torvalds 		}
1031da177e4SLinus Torvalds 		break;
1041da177e4SLinus Torvalds 	      case ROUNDMINUS:
1051da177e4SLinus Torvalds 		if (sign != 0) {
1061da177e4SLinus Torvalds 			Dbl_increment(opndp1,opndp2);
1071da177e4SLinus Torvalds 		}
1081da177e4SLinus Torvalds 		break;
1091da177e4SLinus Torvalds 	      case ROUNDNEAREST:
1101da177e4SLinus Torvalds 		if (guardbit && (stickybit ||
1111da177e4SLinus Torvalds 		       Dbl_isone_lowmantissap2(opndp2))) {
1121da177e4SLinus Torvalds 			   Dbl_increment(opndp1,opndp2);
1131da177e4SLinus Torvalds 		}
1141da177e4SLinus Torvalds 		break;
1151da177e4SLinus Torvalds 	    }
1161da177e4SLinus Torvalds 	}
1171da177e4SLinus Torvalds 	Dbl_set_sign(opndp1,sign);
1181da177e4SLinus Torvalds 	*dbl_opndp1 = opndp1;
1191da177e4SLinus Torvalds 	*dbl_opndp2 = opndp2;
1201da177e4SLinus Torvalds 	*inexactflag = inexact;
1211da177e4SLinus Torvalds 	return;
1221da177e4SLinus Torvalds }
123