Merge tag 'perf-tools-fixes-for-v6.6-2-2023-10-20' of git://git.kernel.org/pub/scm...
[platform/kernel/linux-starfive.git] / arch / parisc / math-emu / denormal.c
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
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
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 }