8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbc / libc / gen / common / _Qfpack.c
blobf7462d9fc29b57de935b0373311304be8bc5c13b
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
22 #pragma ident "%Z%%M% %I% %E% SMI"
25 * Copyright (c) 1988 by Sun Microsystems, Inc.
28 /* Pack procedures for Sparc FPU simulator. */
30 #include "_Qquad.h"
31 #include "_Qglobals.h"
33 PRIVATE int
34 overflow_to_infinity(sign)
35 int sign;
37 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
40 int inf;
42 switch (fp_direction) {
43 case fp_nearest:
44 inf = 1;
45 break;
46 case fp_tozero:
47 inf = 0;
48 break;
49 case fp_positive:
50 inf = !sign;
51 break;
52 case fp_negative:
53 inf = sign;
54 break;
56 return (inf);
59 PRIVATE void
60 round(pu)
61 unpacked *pu;
63 /* Round according to current rounding mode. */
66 int increment; /* boolean to indicate round up */
67 int sr;
68 sr = pu->sticky|pu->rounded;
70 if (sr == 0)
71 return;
72 fpu_set_exception(fp_inexact);
73 switch (fp_direction) {
74 case fp_nearest:
75 increment = pu->rounded;
76 break;
77 case fp_tozero:
78 increment = 0;
79 break;
80 case fp_positive:
81 increment = (pu->sign == 0) & (sr != 0);
82 break;
83 case fp_negative:
84 increment = (pu->sign != 0) & (sr != 0);
85 break;
87 if (increment) {
88 pu->significand[3]++;
89 if (pu->significand[3] == 0) {
90 pu->significand[2]++;
91 if (pu->significand[2] == 0) {
92 pu->significand[1]++;
93 if (pu->significand[1] == 0) {
94 pu->significand[0]++; /* rounding carried out */
95 if( pu->significand[0] == 0x20000) {
96 pu->exponent++;
97 pu->significand[0] = 0x10000;
103 if ((fp_direction == fp_nearest) &&
104 (pu->sticky == 0) && increment!=0) { /* ambiguous case */
105 pu->significand[3] &= 0xfffffffe; /* force round to even */
109 PRIVATE void
110 packinteger(pu, px)
111 unpacked *pu; /* unpacked result */
112 int *px; /* packed integer */
114 switch (pu->fpclass) {
115 case fp_zero:
116 *px = 0;
117 break;
118 case fp_normal:
119 if (pu->exponent >= 32)
120 goto overflow;
121 fpu_rightshift(pu, 112 - pu->exponent);
122 round(pu);
123 if (pu->significand[3] >= 0x80000000)
124 if ((pu->sign == 0)||(pu->significand[3] > 0x80000000))
125 goto overflow;
126 *px = pu->significand[3];
127 if (pu->sign)
128 *px = -*px;
129 break;
130 case fp_infinity:
131 case fp_quiet:
132 case fp_signaling:
133 overflow:
134 if (pu->sign)
135 *px = 0x80000000;
136 else
137 *px = 0x7fffffff;
138 _fp_current_exceptions &= ~(1 << (int) fp_inexact);
139 fpu_set_exception(fp_invalid);
140 break;
144 PRIVATE void
145 packsingle(pu, px)
146 unpacked *pu; /* unpacked result */
147 single_type *px; /* packed single */
149 px->sign = pu->sign;
150 switch (pu->fpclass) {
151 case fp_zero:
152 px->exponent = 0;
153 px->significand = 0;
154 break;
155 case fp_infinity:
156 infinity:
157 px->exponent = 0xff;
158 px->significand = 0;
159 break;
160 case fp_quiet:
161 case fp_signaling:
162 fpu_rightshift(pu, 113-24);
163 px->exponent = 0xff;
164 px->significand = 0x400000|(0x3fffff&pu->significand[3]);
165 break;
166 case fp_normal:
167 fpu_rightshift(pu, 113-24);
168 pu->exponent += SINGLE_BIAS;
169 if (pu->exponent <= 0) {
170 px->exponent = 0;
171 fpu_rightshift(pu, 1 - pu->exponent);
172 round(pu);
173 if (pu->significand[3] == 0x800000) { /* rounded
174 * back up to
175 * normal */
176 px->exponent = 1;
177 px->significand = 0;
178 return;
180 if (_fp_current_exceptions & (1 << fp_inexact))
181 fpu_set_exception(fp_underflow);
182 px->significand = 0x7fffff & pu->significand[3];
183 return;
185 round(pu);
186 if (pu->significand[3] == 0x1000000) { /* rounding overflow */
187 pu->significand[3] = 0x800000;
188 pu->exponent += 1;
190 if (pu->exponent >= 0xff) {
191 fpu_set_exception(fp_overflow);
192 fpu_set_exception(fp_inexact);
193 if (overflow_to_infinity(pu->sign))
194 goto infinity;
195 px->exponent = 0xfe;
196 px->significand = 0x7fffff;
197 return;
199 px->exponent = pu->exponent;
200 px->significand = 0x7fffff & pu->significand[3];
204 PRIVATE void
205 packdouble(pu, px, py)
206 unpacked *pu; /* unpacked result */
207 double_type *px; /* packed double */
208 unsigned *py;
210 px->sign = pu->sign;
211 switch (pu->fpclass) {
212 case fp_zero:
213 px->exponent = 0;
214 px->significand = 0;
215 *py = 0;
216 break;
217 case fp_infinity:
218 infinity:
219 px->exponent = 0x7ff;
220 px->significand = 0;
221 *py = 0;
222 break;
223 case fp_quiet:
224 case fp_signaling:
225 fpu_rightshift(pu, 113-53);
226 px->exponent = 0x7ff;
227 px->significand = 0x80000 | (0x7ffff & pu->significand[2]);
228 *py = pu->significand[3];
229 break;
230 case fp_normal:
231 fpu_rightshift(pu, 113-53);
232 pu->exponent += DOUBLE_BIAS;
233 if (pu->exponent <= 0) { /* underflow */
234 px->exponent = 0;
235 fpu_rightshift(pu, 1 - pu->exponent);
236 round(pu);
237 if (pu->significand[2] == 0x100000) { /* rounded
238 * back up to
239 * normal */
240 px->exponent = 1;
241 px->significand = 0;
242 *py = 0;
243 return;
245 if (_fp_current_exceptions & (1 << fp_inexact))
246 fpu_set_exception(fp_underflow);
247 px->exponent = 0;
248 px->significand = 0xfffff & pu->significand[2];
249 *py = pu->significand[3];
250 return;
252 round(pu);
253 if (pu->significand[2] == 0x200000) { /* rounding overflow */
254 pu->significand[2] = 0x100000;
255 pu->exponent += 1;
257 if (pu->exponent >= 0x7ff) { /* overflow */
258 fpu_set_exception(fp_overflow);
259 fpu_set_exception(fp_inexact);
260 if (overflow_to_infinity(pu->sign))
261 goto infinity;
262 px->exponent = 0x7fe;
263 px->significand = 0xfffff;
264 *py = 0xffffffff;
265 return;
267 px->exponent = pu->exponent;
268 px->significand = 0xfffff & pu->significand[2];
269 *py = pu->significand[3];
270 break;
274 PRIVATE void
275 packextended(pu, px, py, pz, pw)
276 unpacked *pu; /* unpacked result */
277 extended_type *px; /* packed extended */
278 unsigned *py, *pz, *pw;
280 px->sign = pu->sign;
281 switch (pu->fpclass) {
282 case fp_zero:
283 px->exponent = 0;
284 px->significand = 0;
285 *pz = 0;
286 *py = 0;
287 *pw = 0;
288 break;
289 case fp_infinity:
290 infinity:
291 px->exponent = 0x7fff;
292 px->significand = 0;
293 *pz = 0;
294 *py = 0;
295 *pw = 0;
296 break;
297 case fp_quiet:
298 case fp_signaling:
299 px->exponent = 0x7fff;
300 px->significand = 0x8000 | pu->significand[0]; /* Insure quiet
301 * nan. */
302 *py = pu->significand[1];
303 *pz = pu->significand[2];
304 *pw = pu->significand[3];
305 break;
306 case fp_normal:
307 pu->exponent += EXTENDED_BIAS;
308 if (pu->exponent <= 0) { /* underflow */
309 fpu_rightshift(pu, 1-pu->exponent);
310 round(pu);
311 if (pu->significand[0] < 0x00010000) { /* not rounded
312 * back up
313 * to normal */
314 if (_fp_current_exceptions & (1 << fp_inexact))
315 fpu_set_exception(fp_underflow);
316 px->exponent = 0;
317 } else
318 px->exponent = 1;
319 px->significand = pu->significand[0];
320 *py = pu->significand[1];
321 *pz = pu->significand[2];
322 *pw = pu->significand[3];
323 return;
325 round(pu); /* rounding overflow handled in round() */
326 if (pu->exponent >= 0x7fff) { /* overflow */
327 fpu_set_exception(fp_overflow);
328 fpu_set_exception(fp_inexact);
329 if (overflow_to_infinity(pu->sign))
330 goto infinity;
331 px->exponent = 0x7ffe; /* overflow to max norm */
332 px->significand = 0xffff;
333 *py = 0xffffffff;
334 *pz = 0xffffffff;
335 *pw = 0xffffffff;
336 return;
338 px->exponent = pu->exponent;
339 px->significand = pu->significand[0];
340 *py = pu->significand[1];
341 *pz = pu->significand[2];
342 *pw = pu->significand[3];
343 break;
347 void
348 _fp_pack(pu, n, type)
349 unpacked *pu; /* unpacked operand */
350 int *n; /* output result's address */
351 enum fp_op_type type; /* type of datum */
354 switch (type) {
355 case fp_op_integer:
357 packinteger(pu, n);
358 break;
360 case fp_op_single:
362 single_type x;
363 packsingle(pu, &x);
364 n[0] = *(int*)&x;
365 break;
367 case fp_op_double:
369 double_type x;
370 double t=1.0;
371 int i0,i1;
372 if((*(int*)&t)!=0) {i0=0;i1=1;} else {i0=1;i1=0;}
373 packdouble(pu, &x,&n[i1]);
374 n[i0] = *(int*)&x;
375 break;
377 case fp_op_extended:
379 extended_type x;
380 unsigned y, z, w;
381 unpacked u;
382 int k;
383 switch (fp_precision) { /* Implement extended
384 * rounding precision mode. */
385 case fp_single:
387 single_type tx;
388 packsingle(pu, &tx);
389 pu = &u;
390 unpacksingle(pu, tx);
391 break;
393 case fp_double:
395 double_type tx;
396 unsigned ty;
397 packdouble(pu, &tx, &ty);
398 pu = &u;
399 unpackdouble(pu, tx, ty);
400 break;
402 case fp_precision_3: /* rounded to 64 bits */
404 k = pu->exponent+ EXTENDED_BIAS;
405 if(k>=0) k = 113-64;
406 else k = 113-64-k;
407 fpu_rightshift(pu,113-64);
408 round(pu);
409 pu->sticky=pu->rounded=0;
410 pu->exponent += k;
411 fpu_normalize(pu);
412 break;
416 int i0,i1,i2,i3;
417 double t = 1.0;
418 if((*(int*)&t)!=0) {i0=0;i1=1;i2=2;i3=3;}
419 else {i0=3;i1=2;i2=1;i3=0;}
420 packextended(pu, &x, &n[i1], &n[i2], &n[i3]);
421 n[i0] = *(int*)&x;
424 break;