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