xref: /openbmc/linux/arch/parisc/math-emu/denormal.c (revision 68198dca)
1 /*
2  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3  *
4  * Floating-point emulation code
5  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2, or (at your option)
10  *    any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 /*
22  * BEGIN_DESC
23  *
24  *  File:
25  *	@(#)	pa/fp/denormal.c		$ Revision: $
26  *
27  *  Purpose:
28  *	<<please update with a synopsis of the functionality provided by this file>>
29  *
30  *  External Interfaces:
31  *	<<the following list was autogenerated, please review>>
32  *	dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
33  *	sgl_denormalize(sgl_opnd,inexactflag,rmode)
34  *
35  *  Internal Interfaces:
36  *	<<please update>>
37  *
38  *  Theory:
39  *	<<please update with a overview of the operation of this file>>
40  *
41  * END_DESC
42 */
43 
44 
45 
46 #include "float.h"
47 #include "sgl_float.h"
48 #include "dbl_float.h"
49 #include "hppa.h"
50 #include <linux/kernel.h>
51 /* #include <machine/sys/mdep_private.h> */
52 
53 #undef Fpustatus_register
54 #define Fpustatus_register Fpu_register[0]
55 
56 void
57 sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
58 {
59 	unsigned int opnd;
60 	int sign, exponent;
61 	boolean guardbit = FALSE, stickybit, inexact;
62 
63 	opnd = *sgl_opnd;
64 	stickybit = *inexactflag;
65         exponent = Sgl_exponent(opnd) - SGL_WRAP;
66         sign = Sgl_sign(opnd);
67 	Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
68 	if (inexact) {
69 	    switch (rmode) {
70 	      case ROUNDPLUS:
71 		if (sign == 0) {
72 			Sgl_increment(opnd);
73 		}
74 		break;
75 	      case ROUNDMINUS:
76 		if (sign != 0) {
77 			Sgl_increment(opnd);
78 		}
79 		break;
80 	      case ROUNDNEAREST:
81 		if (guardbit && (stickybit ||
82 		       Sgl_isone_lowmantissa(opnd))) {
83 			   Sgl_increment(opnd);
84 		}
85 		break;
86 	    }
87 	}
88 	Sgl_set_sign(opnd,sign);
89 	*sgl_opnd = opnd;
90 	*inexactflag = inexact;
91 	return;
92 }
93 
94 void
95 dbl_denormalize(unsigned int *dbl_opndp1,
96 	unsigned int * dbl_opndp2,
97 	boolean *inexactflag,
98 	int rmode)
99 {
100 	unsigned int opndp1, opndp2;
101 	int sign, exponent;
102 	boolean guardbit = FALSE, stickybit, inexact;
103 
104 	opndp1 = *dbl_opndp1;
105 	opndp2 = *dbl_opndp2;
106 	stickybit = *inexactflag;
107 	exponent = Dbl_exponent(opndp1) - DBL_WRAP;
108 	sign = Dbl_sign(opndp1);
109 	Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
110 	if (inexact) {
111 	    switch (rmode) {
112 	      case ROUNDPLUS:
113 		if (sign == 0) {
114 			Dbl_increment(opndp1,opndp2);
115 		}
116 		break;
117 	      case ROUNDMINUS:
118 		if (sign != 0) {
119 			Dbl_increment(opndp1,opndp2);
120 		}
121 		break;
122 	      case ROUNDNEAREST:
123 		if (guardbit && (stickybit ||
124 		       Dbl_isone_lowmantissap2(opndp2))) {
125 			   Dbl_increment(opndp1,opndp2);
126 		}
127 		break;
128 	    }
129 	}
130 	Dbl_set_sign(opndp1,sign);
131 	*dbl_opndp1 = opndp1;
132 	*dbl_opndp2 = opndp2;
133 	*inexactflag = inexact;
134 	return;
135 }
136