1 /*
2 * CDDL HEADER START
3 *
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.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1988-1995, by Sun Microsystems, Inc.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include "base_conversion.h"
29
30 void
_fp_rightshift(pu,n)31 _fp_rightshift(pu, n)
32 unpacked *pu;
33 int n;
34
35 /* Right shift significand sticky by n bits. */
36
37 {
38 int i;
39
40 if (n >= (32 * UNPACKED_SIZE)) { /* drastic */
41 for (i = 0; (pu->significand[i] == 0) && (i < UNPACKED_SIZE); i++);
42 if (i >= UNPACKED_SIZE) {
43 pu->fpclass = fp_zero;
44 return;
45 } else {
46 for (i = 0; i < (UNPACKED_SIZE - 1); i++)
47 pu->significand[i] = 0;
48 pu->significand[UNPACKED_SIZE - 1] = 1;
49 return;
50 }
51 }
52 while (n >= 32) { /* big shift */
53 if (pu->significand[UNPACKED_SIZE - 1] != 0)
54 pu->significand[UNPACKED_SIZE - 2] |= 1;
55 for (i = UNPACKED_SIZE - 2; i >= 0; i--)
56 pu->significand[i + 1] = pu->significand[i];
57 pu->significand[0] = 0;
58 n -= 32;
59 }
60 if (n >= 1) { /* small shift */
61 unsigned long high, low, shiftout = 0;
62 for (i = 0; i < UNPACKED_SIZE; i++) {
63 high = pu->significand[i] >> n;
64 low = pu->significand[i] << (32 - n);
65 pu->significand[i] = shiftout | high;
66 shiftout = low;
67 }
68 if (shiftout != 0)
69 pu->significand[UNPACKED_SIZE - 1] |= 1;
70 }
71 }
72
73 PRIVATE int
overflow_to_infinity(sign)74 overflow_to_infinity(sign)
75 int sign;
76
77 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
78
79 {
80 int inf;
81
82 switch (_fp_current_direction) {
83 case fp_nearest:
84 inf = 1;
85 break;
86 case fp_tozero:
87 inf = 0;
88 break;
89 case fp_positive:
90 inf = !sign;
91 break;
92 case fp_negative:
93 inf = sign;
94 break;
95 }
96 return (inf);
97 }
98
99 PRIVATE void
round(pu,roundword)100 round(pu, roundword)
101 unpacked *pu;
102
103 /*
104 * Round according to current rounding mode. pu must be shifted to so that
105 * the roundbit is pu->significand[roundword] & 0x80000000
106 */
107
108 {
109 int increment; /* boolean to indicate round up */
110 int is;
111 unsigned msw; /* msw before increment */
112
113 for (is = (roundword + 1); is < UNPACKED_SIZE; is++)
114 if (pu->significand[is] != 0) { /* Condense extra bits into
115 * sticky bottom of
116 * roundword. */
117 pu->significand[roundword] |= 1;
118 break;
119 }
120 if (pu->significand[roundword] == 0)
121 return;
122 _fp_set_exception(fp_inexact);
123 switch (_fp_current_direction) {
124 case fp_nearest:
125 increment = pu->significand[roundword] >= 0x80000000;
126 break;
127 case fp_tozero:
128 increment = 0;
129 break;
130 case fp_positive:
131 increment = (pu->sign == 0) & (pu->significand[roundword] != 0);
132 break;
133 case fp_negative:
134 increment = (pu->sign != 0) & (pu->significand[roundword] != 0);
135 break;
136 }
137 if (increment) {
138 msw=pu->significand[0]; /* save msw before round */
139 is = roundword;
140 do {
141 is--;
142 pu->significand[is]++;
143 }
144 while ((pu->significand[is] == 0) && (is > 0));
145 if (pu->significand[0] < msw) { /* rounding carried out */
146 pu->exponent++;
147 pu->significand[0] = 0x80000000;
148 }
149 }
150 if ((_fp_current_direction == fp_nearest) && (pu->significand[roundword] == 0x80000000)) { /* ambiguous case */
151 pu->significand[roundword - 1] &= ~1; /* force round to even */
152 }
153 }
154
155 void
_pack_single(pu,px)156 _pack_single(pu, px)
157 unpacked *pu; /* unpacked result */
158 single *px; /* packed single */
159 {
160 single_equivalence kluge;
161
162 kluge.f.msw.sign = pu->sign;
163 switch (pu->fpclass) {
164 case fp_zero:
165 kluge.f.msw.exponent = 0;
166 kluge.f.msw.significand = 0;
167 break;
168 case fp_infinity:
169 infinity:
170 kluge.f.msw.exponent = 0xff;
171 kluge.f.msw.significand = 0;
172 break;
173 case fp_quiet:
174 kluge.f.msw.exponent = 0xff;
175 kluge.f.msw.significand = 0x400000 | (0x3fffff & (pu->significand[0] >> 8));
176 break;
177 case fp_normal:
178 _fp_rightshift(pu, 8);
179 pu->exponent += SINGLE_BIAS;
180 if (pu->exponent <= 0) {
181 kluge.f.msw.exponent = 0;
182 _fp_rightshift(pu, 1 - pu->exponent);
183 round(pu, 1);
184 if (pu->significand[0] == 0x800000) { /* rounded back up to
185 * normal */
186 kluge.f.msw.exponent = 1;
187 kluge.f.msw.significand = 0;
188 _fp_set_exception(fp_underflow);
189 goto ret;
190 }
191 if (_fp_current_exceptions & (1 << fp_inexact))
192 _fp_set_exception(fp_underflow);
193 kluge.f.msw.significand = 0x7fffff & pu->significand[0];
194 goto ret;
195 }
196 round(pu, 1);
197 if (pu->significand[0] == 0x1000000) { /* rounding overflow */
198 pu->significand[0] = 0x800000;
199 pu->exponent += 1;
200 }
201 if (pu->exponent >= 0xff) {
202 _fp_set_exception(fp_overflow);
203 _fp_set_exception(fp_inexact);
204 if (overflow_to_infinity(pu->sign))
205 goto infinity;
206 kluge.f.msw.exponent = 0xfe;
207 kluge.f.msw.significand = 0x7fffff;
208 goto ret;
209 }
210 kluge.f.msw.exponent = pu->exponent;
211 kluge.f.msw.significand = 0x7fffff & pu->significand[0];
212 }
213 ret:
214 *px = kluge.x;
215 }
216
217 void
_pack_double(pu,px)218 _pack_double(pu, px)
219 unpacked *pu; /* unpacked result */
220 double *px; /* packed double */
221 {
222 double_equivalence kluge;
223
224 kluge.f.msw.sign = pu->sign;
225 switch (pu->fpclass) {
226 case fp_zero:
227 kluge.f.msw.exponent = 0;
228 kluge.f.msw.significand = 0;
229 kluge.f.significand2 = 0;
230 break;
231 case fp_infinity:
232 infinity:
233 kluge.f.msw.exponent = 0x7ff;
234 kluge.f.msw.significand = 0;
235 kluge.f.significand2 = 0;
236 break;
237 case fp_quiet:
238 kluge.f.msw.exponent = 0x7ff;
239 _fp_rightshift(pu, 11);
240 kluge.f.msw.significand = 0x80000 | (0x7ffff & pu->significand[0]);
241 kluge.f.significand2 = pu->significand[1];
242 break;
243 case fp_normal:
244 _fp_rightshift(pu, 11);
245 pu->exponent += DOUBLE_BIAS;
246 if (pu->exponent <= 0) { /* underflow */
247 kluge.f.msw.exponent = 0;
248 _fp_rightshift(pu, 1 - pu->exponent);
249 round(pu, 2);
250 if (pu->significand[0] == 0x100000) { /* rounded back up to
251 * normal */
252 kluge.f.msw.exponent = 1;
253 kluge.f.msw.significand = 0;
254 kluge.f.significand2 = 0;
255 _fp_set_exception(fp_underflow);
256 goto ret;
257 }
258 if (_fp_current_exceptions & (1 << fp_inexact))
259 _fp_set_exception(fp_underflow);
260 kluge.f.msw.exponent = 0;
261 kluge.f.msw.significand = 0xfffff & pu->significand[0];
262 kluge.f.significand2 = pu->significand[1];
263 goto ret;
264 }
265 round(pu, 2);
266 if (pu->significand[0] == 0x200000) { /* rounding overflow */
267 pu->significand[0] = 0x100000;
268 pu->exponent += 1;
269 }
270 if (pu->exponent >= 0x7ff) { /* overflow */
271 _fp_set_exception(fp_overflow);
272 _fp_set_exception(fp_inexact);
273 if (overflow_to_infinity(pu->sign))
274 goto infinity;
275 kluge.f.msw.exponent = 0x7fe;
276 kluge.f.msw.significand = 0xfffff;
277 kluge.f.significand2 = 0xffffffff;
278 goto ret;
279 }
280 kluge.f.msw.exponent = pu->exponent;
281 kluge.f.msw.significand = 0xfffff & pu->significand[0];
282 kluge.f.significand2 = pu->significand[1];
283 break;
284 }
285 ret:
286 *px = kluge.x;
287 }
288
289 void
_pack_extended(pu,px)290 _pack_extended(pu, px)
291 unpacked *pu; /* unpacked result */
292 extended *px; /* packed extended */
293 {
294 extended_equivalence kluge;
295
296 kluge.f.msw.sign = pu->sign;
297 switch (pu->fpclass) {
298 case fp_zero:
299 kluge.f.msw.exponent = 0;
300 kluge.f.significand = 0;
301 kluge.f.significand2 = 0;
302 break;
303 case fp_infinity:
304 infinity:
305 kluge.f.msw.exponent = 0x7fff;
306 kluge.f.significand = 0;
307 kluge.f.significand2 = 0;
308 break;
309 case fp_quiet:
310 kluge.f.msw.exponent = 0x7fff;
311 kluge.f.significand = 0x40000000 | (0x7fffffff & pu->significand[0]);
312 kluge.f.significand2 = pu->significand[1];
313 break;
314 case fp_normal:
315 switch (_fp_current_precision) {
316 case fp_single:
317 {
318 single s;
319 _pack_single(pu, &s);
320 _unpack_single(pu, &s);
321 break;
322 }
323 case fp_double:
324 {
325 double s;
326 _pack_double(pu, &s);
327 _unpack_double(pu, &s);
328 break;
329 }
330 }
331 pu->exponent += EXTENDED_BIAS;
332 if (pu->exponent <= 0) { /* underflow */
333 kluge.f.msw.exponent = 0;
334 _fp_rightshift(pu, -pu->exponent);
335 round(pu, 2);
336 if (_fp_current_exceptions & (1 << fp_inexact))
337 _fp_set_exception(fp_underflow);
338 kluge.f.msw.exponent = 0;
339 kluge.f.significand = pu->significand[0];
340 kluge.f.significand2 = pu->significand[1];
341 goto ret;
342 }
343 round(pu, 2);
344 if (pu->exponent >= 0x7fff) { /* overflow */
345 _fp_set_exception(fp_overflow);
346 _fp_set_exception(fp_inexact);
347 if (overflow_to_infinity(pu->sign))
348 goto infinity;
349 kluge.f.msw.exponent = 0x7ffe;
350 kluge.f.significand = 0xffffffff;
351 kluge.f.significand2 = 0xffffffff;
352 goto ret;
353 }
354 kluge.f.msw.exponent = pu->exponent;
355 kluge.f.significand = pu->significand[0];
356 kluge.f.significand2 = pu->significand[1];
357 break;
358 }
359 ret:
360 (*px)[0] = kluge.x[0];
361 (*px)[1] = kluge.x[1];
362 (*px)[2] = kluge.x[2];
363 }
364
365 void
_pack_quadruple(pu,px)366 _pack_quadruple(pu, px)
367 unpacked *pu; /* unpacked result */
368 quadruple *px; /* packed quadruple */
369 {
370 quadruple_equivalence kluge;
371 int i;
372
373 kluge.f.msw.sign = pu->sign;
374 switch (pu->fpclass) {
375 case fp_zero:
376 kluge.f.msw.exponent = 0;
377 kluge.f.msw.significand = 0;
378 kluge.f.significand2 = 0;
379 kluge.f.significand3 = 0;
380 kluge.f.significand4 = 0;
381 break;
382 case fp_infinity:
383 infinity:
384 kluge.f.msw.exponent = 0x7fff;
385 kluge.f.msw.significand = 0;
386 kluge.f.significand2 = 0;
387 kluge.f.significand3 = 0;
388 kluge.f.significand4 = 0;
389 break;
390 case fp_quiet:
391 kluge.f.msw.exponent = 0x7fff;
392 _fp_rightshift(pu, 15);
393 kluge.f.msw.significand = 0x8000 | (0xffff & pu->significand[0]);
394 kluge.f.significand2 = pu->significand[1];
395 kluge.f.significand3 = pu->significand[2];
396 kluge.f.significand4 = pu->significand[3];
397 break;
398 case fp_normal:
399 _fp_rightshift(pu, 15);
400 pu->exponent += QUAD_BIAS;
401 if (pu->exponent <= 0) { /* underflow */
402 kluge.f.msw.exponent = 0;
403 _fp_rightshift(pu, 1 - pu->exponent);
404 round(pu, 4);
405 if (pu->significand[0] == 0x10000) { /* rounded back up to
406 * normal */
407 kluge.f.msw.exponent = 1;
408 kluge.f.msw.significand = 0;
409 kluge.f.significand2 = 0;
410 kluge.f.significand3 = 0;
411 kluge.f.significand4 = 0;
412 _fp_set_exception(fp_underflow);
413 goto ret;
414 }
415 if (_fp_current_exceptions & (1 << fp_inexact))
416 _fp_set_exception(fp_underflow);
417 kluge.f.msw.exponent = 0;
418 kluge.f.msw.significand = 0xffff & pu->significand[0];
419 kluge.f.significand2 = pu->significand[1];
420 kluge.f.significand3 = pu->significand[2];
421 kluge.f.significand4 = pu->significand[3];
422 goto ret;
423 }
424 round(pu, 4);
425 if (pu->significand[0] == 0x20000) { /* rounding overflow */
426 pu->significand[0] = 0x10000;
427 pu->exponent += 1;
428 }
429 if (pu->exponent >= 0x7fff) { /* overflow */
430 _fp_set_exception(fp_overflow);
431 _fp_set_exception(fp_inexact);
432 if (overflow_to_infinity(pu->sign))
433 goto infinity;
434 kluge.f.msw.exponent = 0x7ffe;
435 kluge.f.msw.significand = 0xffff;
436 kluge.f.significand2 = 0xffffffff;
437 kluge.f.significand3 = 0xffffffff;
438 kluge.f.significand4 = 0xffffffff;
439 goto ret;
440 }
441 kluge.f.msw.exponent = pu->exponent;
442 kluge.f.msw.significand = pu->significand[0] & 0xffff;
443 kluge.f.significand2 = pu->significand[1];
444 kluge.f.significand3 = pu->significand[2];
445 kluge.f.significand4 = pu->significand[3];
446 break;
447 }
448 ret:
449 #ifdef __STDC__
450 *px = kluge.x;
451 #else
452 for (i = 0; i < 4; i++)
453 px->u[i] = kluge.x.u[i];
454 #endif
455 }
456