4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 #pragma ident "%Z%%M% %I% %E% SMI"
25 * Copyright (c) 1988 by Sun Microsystems, Inc.
28 /* Utility functions for Sparc FPU simulator. */
31 #include "_Qglobals.h"
38 /* Normalize a number. Does not affect zeros, infs, or NaNs. */
39 /* The number will be normalized to 113 bit extended:
40 * 0x0001####,0x########,0x########,0x########.
44 unsigned u
,u0
,u1
,u2
,u3
,m
,n
,k
;
45 u0
= pu
->significand
[0];
46 u1
= pu
->significand
[1];
47 u2
= pu
->significand
[2];
48 u3
= pu
->significand
[3];
49 if ((*pu
).fpclass
== fp_normal
) {
50 if ((u0
|u1
|u2
|u3
)==0) {
51 (*pu
).fpclass
= fp_zero
;
55 u0
= u1
; u1
=u2
; u2
=u3
; u3
=0;
56 (*pu
).exponent
= (*pu
).exponent
- 32;
58 if (u0
>=0x20000) { /* u3 should be zero */
60 while(u
>=0x20000) {u
>>= 1; n
+= 1;}
64 u3
= ((u2
&m
)<<k
)|(u3
>>n
);
65 u2
= ((u1
&m
)<<k
)|(u2
>>n
);
66 u1
= ((u0
&m
)<<k
)|(u1
>>n
);
68 } else if(u0
<0x10000) {
70 while(u
<0x10000) {u
<<= 1; n
+= 1;}
74 u0
= (u0
<<n
)|((u1
&m
)>>k
);
75 u1
= (u1
<<n
)|((u2
&m
)>>k
);
76 u2
= (u2
<<n
)|((u3
&m
)>>k
);
79 pu
->significand
[0] = u0
;
80 pu
->significand
[1] = u1
;
81 pu
->significand
[2] = u2
;
82 pu
->significand
[3] = u3
;
91 /* Right shift significand sticky by n bits. */
94 unsigned m
,k
,j
,u0
,u1
,u2
,u3
;
95 if (n
> 113) { /* drastic */
96 if (((*pu
).significand
[0] | (*pu
).significand
[1]
97 | (*pu
).significand
[2] | (*pu
).significand
[3]) == 0){
99 pu
->fpclass
= fp_zero
;
104 pu
->significand
[3] = 0;
105 pu
->significand
[2] = 0;
106 pu
->significand
[1] = 0;
107 pu
->significand
[0] = 0;
111 while (n
>= 32) { /* big shift */
112 pu
->sticky
|= pu
->rounded
| (pu
->significand
[3]&0x7fffffff);
113 pu
->rounded
= (*pu
).significand
[3]>>31;
114 (*pu
).significand
[3] = (*pu
).significand
[2];
115 (*pu
).significand
[2] = (*pu
).significand
[1];
116 (*pu
).significand
[1] = (*pu
).significand
[0];
117 (*pu
).significand
[0] = 0;
120 if (n
> 0) { /* small shift */
121 u0
= pu
->significand
[0];
122 u1
= pu
->significand
[1];
123 u2
= pu
->significand
[2];
124 u3
= pu
->significand
[3];
128 pu
->sticky
|= pu
->rounded
| (u3
&j
);
129 pu
->rounded
= (u3
&m
)>>(n
-1);
130 pu
->significand
[3] = ((u2
&m
)<<k
)|(u3
>>n
);
131 pu
->significand
[2] = ((u1
&m
)<<k
)|(u2
>>n
);
132 pu
->significand
[1] = ((u0
&m
)<<k
)|(u1
>>n
);
133 pu
->significand
[0] = u0
>>n
;
138 fpu_set_exception(ex
)
139 enum fp_exception_type ex
;
141 /* Set the exception bit in the current exception register. */
144 _fp_current_exceptions
|= 1 << (int) ex
;
151 { /* Set invalid exception and error nan in *pu */
153 fpu_set_exception(fp_invalid
);
154 pu
->significand
[0] = 0x7fffffff|((pu
->sign
)<<31);
155 pu
->significand
[1] = 0xffffffff;
156 pu
->significand
[2] = 0xffffffff;
157 pu
->significand
[3] = 0xffffffff;
160 /* the following fpu_add3wc should be inlined as
161 * .inline _fpu_add3wc,3
162 * ld [%o1],%o4 ! sum = x
163 * addcc -1,%o3,%g0 ! restore last carry in cc reg
164 * addxcc %o4,%o2,%o4 ! sum = sum + y + last carry
165 * st %o4,[%o0] ! *z = sum
166 * addx %g0,%g0,%o0 ! return new carry
171 fpu_add3wc(z
,x
,y
,carry
)
172 unsigned *z
,x
,y
,carry
;
173 { /* *z = x + y + carry, set carry; */
183 /* the following fpu_sub3wc should be inlined as
184 * .inline _fpu_sub3wc,3
185 * ld [%o1],%o4 ! sum = *x
186 * addcc -1,%o3,%g0 ! restore last carry in cc reg
187 * subxcc %o4,%o2,%o4 ! sum = sum - y - last carry
188 * st %o4,[%o0] ! *x = sum
189 * addx %g0,%g0,%o0 ! return new carry
194 fpu_sub3wc(z
,x
,y
,carry
)
195 unsigned *z
,x
,y
,carry
;
196 { /* *z = x - y - carry, set carry; */
206 /* the following fpu_neg2wc should be inlined as
207 * .inline _fpu_neg2wc,2
208 * ld [%o1],%o3 ! tmp = *x
209 * addcc -1,%o2,%g0 ! restore last carry in cc reg
210 * subxcc %g0,%o3,%o3 ! sum = 0 - tmp - last carry
211 * st %o3,[%o0] ! *x = sum
212 * addx %g0,%g0,%o0 ! return new carry
217 fpu_neg2wc(z
,x
,carry
)
219 { /* *x = 0 - *x - carry, set carry; */
231 unsigned x
[],y
[]; int n
;
232 { /* compare two unsigned array */
236 if(x
[i
]>y
[i
]) return 1;
237 else if(x
[i
]<y
[i
]) return -1;
248 /* Print out unpacked record. */
251 (void) printf(" unpacked ");
257 switch (pu
->fpclass
) {
262 (void) printf("normal");
265 (void) printf("Inf ");
269 (void) printf("nan ");
272 (void) printf(" %X %X %X %X (%X,%X) exponent %X \n",
273 pu
->significand
[0], pu
->significand
[1],pu
->significand
[2],
274 pu
->significand
[3], (pu
->rounded
!=0),
275 (pu
->sticky
!=0),pu
->exponent
);