1 /* $NetBSD: fpu_subr.c,v 1.1.24.3 2004/09/21 13:20:34 skrll Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * @(#)fpu_subr.c 8.1 (Berkeley) 6/11/93
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: fpu_subr.c,v 1.1.24.3 2004/09/21 13:20:34 skrll Exp $");
50 #include <sys/types.h>
51 #if defined(DIAGNOSTIC)||defined(DEBUG)
52 #include <sys/systm.h>
55 #include <machine/reg.h>
56 #include <powerpc/instr.h>
57 #include <machine/fpu.h>
59 #include <powerpc/fpu/fpu_arith.h>
60 #include <powerpc/fpu/fpu_emu.h>
61 #include <powerpc/fpu/fpu_extern.h>
64 * Shift the given number right rsh bits. Any bits that `fall off' will get
65 * shoved into the sticky field; we return the resulting sticky. Note that
66 * shifting NaNs is legal (this will never shift all bits out); a NaN's
67 * sticky field is ignored anyway.
70 fpu_shr(struct fpn
*fp
, int rsh
)
72 u_int m0
, m1
, m2
, m3
, s
;
76 if (rsh
<= 0 || (fp
->fp_class
!= FPC_NUM
&& !ISNAN(fp
)))
77 panic("fpu_rightshift 1");
85 /* If shifting all the bits out, take a shortcut. */
86 if (rsh
>= FP_NMANT
) {
88 if ((m0
| m1
| m2
| m3
) == 0)
89 panic("fpu_rightshift 2");
96 if ((m0
| m1
| m2
| m3
) == 0)
97 fp
->fp_class
= FPC_ZERO
;
104 /* Squish out full words. */
108 m3
= m0
, m2
= 0, m1
= 0, m0
= 0;
109 } else if (rsh
>= 32 * 2) {
111 m3
= m1
, m2
= m0
, m1
= 0, m0
= 0;
112 } else if (rsh
>= 32) {
114 m3
= m2
, m2
= m1
, m1
= m0
, m0
= 0;
117 /* Handle any remaining partial word. */
118 if ((rsh
&= 31) != 0) {
121 m3
= (m3
>> rsh
) | (m2
<< lsh
);
122 m2
= (m2
>> rsh
) | (m1
<< lsh
);
123 m1
= (m1
>> rsh
) | (m0
<< lsh
);
135 * Force a number to be normal, i.e., make its fraction have all zero
136 * bits before FP_1, then FP_1, then all 1 bits. This is used for denorms
137 * and (sometimes) for intermediate results.
139 * Internally, this may use a `supernormal' -- a number whose fp_mant
140 * is greater than or equal to 2.0 -- so as a side effect you can hand it
141 * a supernormal and it will fix it (provided fp->fp_mant[3] == 0).
144 fpu_norm(struct fpn
*fp
)
146 u_int m0
, m1
, m2
, m3
, top
, sup
, nrm
;
155 /* Handle severe subnormals with 32-bit moves. */
158 m0
= m1
, m1
= m2
, m2
= m3
, m3
= 0, exp
-= 32;
160 m0
= m2
, m1
= m3
, m2
= 0, m3
= 0, exp
-= 2 * 32;
162 m0
= m3
, m1
= 0, m2
= 0, m3
= 0, exp
-= 3 * 32;
164 fp
->fp_class
= FPC_ZERO
;
169 /* Now fix any supernormal or remaining subnormal. */
174 * We have a supernormal number. We need to shift it right.
175 * We may assume m3==0.
177 for (rsh
= 1, top
= m0
>> 1; top
>= sup
; rsh
++) /* XXX slow */
182 m2
= (m2
>> rsh
) | (m1
<< lsh
);
183 m1
= (m1
>> rsh
) | (m0
<< lsh
);
185 } else if (m0
< nrm
) {
187 * We have a regular denorm (a subnormal number), and need
190 for (lsh
= 1, top
= m0
<< 1; top
< nrm
; lsh
++) /* XXX slow */
194 m0
= top
| (m1
>> rsh
);
195 m1
= (m1
<< lsh
) | (m2
>> rsh
);
196 m2
= (m2
<< lsh
) | (m3
>> rsh
);
208 * Concoct a `fresh' Quiet NaN per Appendix N.
209 * As a side effect, we set NV (invalid) for the current exceptions.
212 fpu_newnan(struct fpemu
*fe
)
216 fe
->fe_cx
|= FPSCR_VXSNAN
;
218 fp
->fp_class
= FPC_QNAN
;
220 fp
->fp_mant
[0] = FP_1
- 1;
221 fp
->fp_mant
[1] = fp
->fp_mant
[2] = fp
->fp_mant
[3] = ~0;
222 DUMPFPN(FPE_REG
, fp
);