xref: /openbmc/linux/arch/parisc/math-emu/denormal.c (revision 660662f8)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4  *
5  * Floating-point emulation code
6  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7  */
8 /*
9  * BEGIN_DESC
10  *
11  *  File:
12  *	@(#)	pa/fp/denormal.c		$ Revision: $
13  *
14  *  Purpose:
15  *	<<please update with a synopsis of the functionality provided by this file>>
16  *
17  *  External Interfaces:
18  *	<<the following list was autogenerated, please review>>
19  *	dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
20  *	sgl_denormalize(sgl_opnd,inexactflag,rmode)
21  *
22  *  Internal Interfaces:
23  *	<<please update>>
24  *
25  *  Theory:
26  *	<<please update with a overview of the operation of this file>>
27  *
28  * END_DESC
29 */
30 
31 
32 
33 #include "float.h"
34 #include "sgl_float.h"
35 #include "dbl_float.h"
36 #include "hppa.h"
37 #include <linux/kernel.h>
38 /* #include <machine/sys/mdep_private.h> */
39 
40 #undef Fpustatus_register
41 #define Fpustatus_register Fpu_register[0]
42 
43 void
sgl_denormalize(unsigned int * sgl_opnd,boolean * inexactflag,int rmode)44 sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
45 {
46 	unsigned int opnd;
47 	int sign, exponent;
48 	boolean guardbit = FALSE, stickybit, inexact;
49 
50 	opnd = *sgl_opnd;
51 	stickybit = *inexactflag;
52         exponent = Sgl_exponent(opnd) - SGL_WRAP;
53         sign = Sgl_sign(opnd);
54 	Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
55 	if (inexact) {
56 	    switch (rmode) {
57 	      case ROUNDPLUS:
58 		if (sign == 0) {
59 			Sgl_increment(opnd);
60 		}
61 		break;
62 	      case ROUNDMINUS:
63 		if (sign != 0) {
64 			Sgl_increment(opnd);
65 		}
66 		break;
67 	      case ROUNDNEAREST:
68 		if (guardbit && (stickybit ||
69 		       Sgl_isone_lowmantissa(opnd))) {
70 			   Sgl_increment(opnd);
71 		}
72 		break;
73 	    }
74 	}
75 	Sgl_set_sign(opnd,sign);
76 	*sgl_opnd = opnd;
77 	*inexactflag = inexact;
78 	return;
79 }
80 
81 void
dbl_denormalize(unsigned int * dbl_opndp1,unsigned int * dbl_opndp2,boolean * inexactflag,int rmode)82 dbl_denormalize(unsigned int *dbl_opndp1,
83 	unsigned int * dbl_opndp2,
84 	boolean *inexactflag,
85 	int rmode)
86 {
87 	unsigned int opndp1, opndp2;
88 	int sign, exponent;
89 	boolean guardbit = FALSE, stickybit, inexact;
90 
91 	opndp1 = *dbl_opndp1;
92 	opndp2 = *dbl_opndp2;
93 	stickybit = *inexactflag;
94 	exponent = Dbl_exponent(opndp1) - DBL_WRAP;
95 	sign = Dbl_sign(opndp1);
96 	Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
97 	if (inexact) {
98 	    switch (rmode) {
99 	      case ROUNDPLUS:
100 		if (sign == 0) {
101 			Dbl_increment(opndp1,opndp2);
102 		}
103 		break;
104 	      case ROUNDMINUS:
105 		if (sign != 0) {
106 			Dbl_increment(opndp1,opndp2);
107 		}
108 		break;
109 	      case ROUNDNEAREST:
110 		if (guardbit && (stickybit ||
111 		       Dbl_isone_lowmantissap2(opndp2))) {
112 			   Dbl_increment(opndp1,opndp2);
113 		}
114 		break;
115 	    }
116 	}
117 	Dbl_set_sign(opndp1,sign);
118 	*dbl_opndp1 = opndp1;
119 	*dbl_opndp2 = opndp2;
120 	*inexactflag = inexact;
121 	return;
122 }
123