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
56void
57sgl_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
94void
95dbl_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