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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include "lint.h"
30 #include "base_conversion.h"
31
32 static void
__fp_rightshift(unpacked * pu,int n)33 __fp_rightshift(unpacked *pu, 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);
42 i++);
43 if (i >= UNPACKED_SIZE) {
44 pu->fpclass = fp_zero;
45 return;
46 } else {
47 for (i = 0; i < (UNPACKED_SIZE - 1); i++)
48 pu->significand[i] = 0;
49 pu->significand[UNPACKED_SIZE - 1] = 1;
50 return;
51 }
52 }
53 while (n >= 32) { /* big shift */
54 if (pu->significand[UNPACKED_SIZE - 1] != 0)
55 pu->significand[UNPACKED_SIZE - 2] |= 1;
56 for (i = UNPACKED_SIZE - 2; i >= 0; i--)
57 pu->significand[i + 1] = pu->significand[i];
58 pu->significand[0] = 0;
59 n -= 32;
60 }
61 if (n >= 1) { /* small shift */
62 unsigned int high, low, shiftout = 0;
63 for (i = 0; i < UNPACKED_SIZE; i++) {
64 high = pu->significand[i] >> n;
65 low = pu->significand[i] << (32 - n);
66 pu->significand[i] = shiftout | high;
67 shiftout = low;
68 }
69 if (shiftout != 0)
70 pu->significand[UNPACKED_SIZE - 1] |= 1;
71 }
72 }
73
74 static int
overflow_to_infinity(int sign,enum fp_direction_type rd)75 overflow_to_infinity(int sign, enum fp_direction_type rd)
76
77 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
78
79 {
80 int inf;
81
82 switch (rd) {
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 static void
round(unpacked * pu,int roundword,enum fp_direction_type rd,int * ex)100 round(unpacked *pu, int roundword, enum fp_direction_type rd, int *ex)
101 /*
102 * Round according to current rounding mode. pu must be shifted to so that
103 * the roundbit is pu->significand[roundword] & 0x80000000
104 */
105 {
106 int increment; /* boolean to indicate round up */
107 int is;
108 unsigned msw; /* msw before increment */
109
110 for (is = (roundword + 1); is < UNPACKED_SIZE; is++)
111 if (pu->significand[is] != 0) {
112 /* Condense extra bits into sticky bottom of roundword. */
113 pu->significand[roundword] |= 1;
114 break;
115 }
116 if (pu->significand[roundword] == 0)
117 return;
118 *ex |= (1 << fp_inexact);
119 switch (rd) {
120 case fp_nearest:
121 increment = pu->significand[roundword] >= 0x80000000;
122 break;
123 case fp_tozero:
124 increment = 0;
125 break;
126 case fp_positive:
127 increment = (pu->sign == 0) & (pu->significand[roundword] != 0);
128 break;
129 case fp_negative:
130 increment = (pu->sign != 0) & (pu->significand[roundword] != 0);
131 break;
132 }
133 if (increment) {
134 msw = pu->significand[0]; /* save msw before round */
135 is = roundword;
136 do {
137 is--;
138 pu->significand[is]++;
139 }
140 while ((pu->significand[is] == 0) && (is > 0));
141 if (pu->significand[0] < msw) { /* rounding carried out */
142 pu->exponent++;
143 pu->significand[0] = 0x80000000;
144 }
145 }
146 if ((rd == fp_nearest) &&
147 (pu->significand[roundword] == 0x80000000)) {
148 /* ambiguous case */
149 pu->significand[roundword - 1] &= ~1; /* force round to even */
150 }
151 }
152
153 void
__pack_single(unpacked * pu,single * px,enum fp_direction_type rd,fp_exception_field_type * ex)154 __pack_single(unpacked *pu, single *px, enum fp_direction_type rd,
155 fp_exception_field_type *ex)
156 {
157 single_equivalence kluge;
158 int e;
159
160 e = 0;
161 kluge.f.msw.sign = pu->sign;
162 switch (pu->fpclass) {
163 case fp_zero:
164 kluge.f.msw.exponent = 0;
165 kluge.f.msw.significand = 0;
166 break;
167 case fp_infinity:
168 infinity:
169 kluge.f.msw.exponent = 0xff;
170 kluge.f.msw.significand = 0;
171 break;
172 case fp_quiet:
173 kluge.f.msw.exponent = 0xff;
174 kluge.f.msw.significand = 0x400000 |
175 (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, rd, &e);
184 if (pu->significand[0] == 0x800000) {
185 /* rounded back up to normal */
186 kluge.f.msw.exponent = 1;
187 kluge.f.msw.significand = 0;
188 e |= (1 << fp_underflow);
189 goto ret;
190 }
191 if (e & (1 << fp_inexact))
192 e |= (1 << fp_underflow);
193 kluge.f.msw.significand = 0x7fffff & pu->significand[0];
194 goto ret;
195 }
196 round(pu, 1, rd, &e);
197 if (pu->significand[0] == 0x1000000) { /* rounding overflow */
198 pu->significand[0] = 0x800000;
199 pu->exponent += 1;
200 }
201 if (pu->exponent >= 0xff) {
202 e |= (1 << fp_overflow) | (1 << fp_inexact);
203 if (overflow_to_infinity(pu->sign, rd))
204 goto infinity;
205 kluge.f.msw.exponent = 0xfe;
206 kluge.f.msw.significand = 0x7fffff;
207 goto ret;
208 }
209 kluge.f.msw.exponent = pu->exponent;
210 kluge.f.msw.significand = 0x7fffff & pu->significand[0];
211 }
212 ret:
213 *px = kluge.x;
214 *ex = (fp_exception_field_type)e;
215 }
216
217 void
__pack_double(unpacked * pu,double * px,enum fp_direction_type rd,fp_exception_field_type * ex)218 __pack_double(unpacked *pu, double *px, enum fp_direction_type rd,
219 fp_exception_field_type *ex)
220 {
221 double_equivalence kluge;
222 int e;
223
224 e = 0;
225 kluge.f.msw.sign = pu->sign;
226 switch (pu->fpclass) {
227 case fp_zero:
228 kluge.f.msw.exponent = 0;
229 kluge.f.msw.significand = 0;
230 kluge.f.significand2 = 0;
231 break;
232 case fp_infinity:
233 infinity:
234 kluge.f.msw.exponent = 0x7ff;
235 kluge.f.msw.significand = 0;
236 kluge.f.significand2 = 0;
237 break;
238 case fp_quiet:
239 kluge.f.msw.exponent = 0x7ff;
240 __fp_rightshift(pu, 11);
241 kluge.f.msw.significand = 0x80000 |
242 (0x7ffff & pu->significand[0]);
243 kluge.f.significand2 = pu->significand[1];
244 break;
245 case fp_normal:
246 __fp_rightshift(pu, 11);
247 pu->exponent += DOUBLE_BIAS;
248 if (pu->exponent <= 0) { /* underflow */
249 __fp_rightshift(pu, 1 - pu->exponent);
250 round(pu, 2, rd, &e);
251 if (pu->significand[0] == 0x100000) {
252 /* rounded back up to normal */
253 kluge.f.msw.exponent = 1;
254 kluge.f.msw.significand = 0;
255 kluge.f.significand2 = 0;
256 e |= (1 << fp_underflow);
257 goto ret;
258 }
259 if (e & (1 << fp_inexact))
260 e |= (1 << fp_underflow);
261 kluge.f.msw.exponent = 0;
262 kluge.f.msw.significand = 0xfffff & pu->significand[0];
263 kluge.f.significand2 = pu->significand[1];
264 goto ret;
265 }
266 round(pu, 2, rd, &e);
267 if (pu->significand[0] == 0x200000) { /* rounding overflow */
268 pu->significand[0] = 0x100000;
269 pu->exponent += 1;
270 }
271 if (pu->exponent >= 0x7ff) { /* overflow */
272 e |= (1 << fp_overflow) | (1 << fp_inexact);
273 if (overflow_to_infinity(pu->sign, rd))
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 *ex = (fp_exception_field_type)e;
288 }
289
290 void
__pack_extended(unpacked * pu,extended * px,enum fp_direction_type rd,fp_exception_field_type * ex)291 __pack_extended(unpacked *pu, extended *px, enum fp_direction_type rd,
292 fp_exception_field_type *ex)
293 {
294 extended_equivalence kluge;
295 int e;
296
297 e = 0;
298 kluge.f.msw.sign = pu->sign;
299 switch (pu->fpclass) {
300 case fp_zero:
301 kluge.f.msw.exponent = 0;
302 kluge.f.significand = 0;
303 kluge.f.significand2 = 0;
304 break;
305 case fp_infinity:
306 infinity:
307 kluge.f.msw.exponent = 0x7fff;
308 kluge.f.significand = 0x80000000;
309 kluge.f.significand2 = 0;
310 break;
311 case fp_quiet:
312 kluge.f.msw.exponent = 0x7fff;
313 kluge.f.significand = 0x40000000 | pu->significand[0];
314 kluge.f.significand2 = pu->significand[1];
315 break;
316 case fp_normal:
317 pu->exponent += EXTENDED_BIAS;
318 if (pu->exponent <= 0) { /* underflow */
319 __fp_rightshift(pu, 1 - pu->exponent);
320 round(pu, 2, rd, &e);
321 if (pu->significand[0] == 0x80000000u) {
322 /* rounded back up to normal */
323 kluge.f.msw.exponent = 1;
324 kluge.f.significand = 0x80000000u;
325 kluge.f.significand2 = 0;
326 e |= (1 << fp_underflow);
327 goto ret;
328 }
329 if (e & (1 << fp_inexact))
330 e |= (1 << fp_underflow);
331 kluge.f.msw.exponent = 0;
332 kluge.f.significand = pu->significand[0];
333 kluge.f.significand2 = pu->significand[1];
334 goto ret;
335 }
336 round(pu, 2, rd, &e);
337 if (pu->exponent >= 0x7fff) { /* overflow */
338 e |= (1 << fp_overflow) | (1 << fp_inexact);
339 if (overflow_to_infinity(pu->sign, rd))
340 goto infinity;
341 kluge.f.msw.exponent = 0x7ffe;
342 kluge.f.significand = 0xffffffff;
343 kluge.f.significand2 = 0xffffffff;
344 goto ret;
345 }
346 kluge.f.msw.exponent = pu->exponent;
347 kluge.f.significand = pu->significand[0];
348 kluge.f.significand2 = pu->significand[1];
349 break;
350 }
351 ret:
352 (*px)[0] = kluge.x[0];
353 (*px)[1] = kluge.x[1];
354 (*px)[2] = kluge.x[2];
355 *ex = (fp_exception_field_type)e;
356 }
357
358 void
__pack_quadruple(unpacked * pu,quadruple * px,enum fp_direction_type rd,fp_exception_field_type * ex)359 __pack_quadruple(unpacked *pu, quadruple *px, enum fp_direction_type rd,
360 fp_exception_field_type *ex)
361 {
362 quadruple_equivalence kluge;
363 int e;
364
365 e = 0;
366 kluge.f.msw.sign = pu->sign;
367 switch (pu->fpclass) {
368 case fp_zero:
369 kluge.f.msw.exponent = 0;
370 kluge.f.msw.significand = 0;
371 kluge.f.significand2 = 0;
372 kluge.f.significand3 = 0;
373 kluge.f.significand4 = 0;
374 break;
375 case fp_infinity:
376 infinity:
377 kluge.f.msw.exponent = 0x7fff;
378 kluge.f.msw.significand = 0;
379 kluge.f.significand2 = 0;
380 kluge.f.significand3 = 0;
381 kluge.f.significand4 = 0;
382 break;
383 case fp_quiet:
384 kluge.f.msw.exponent = 0x7fff;
385 __fp_rightshift(pu, 15);
386 kluge.f.msw.significand = 0x8000 |
387 (0xffff & pu->significand[0]);
388 kluge.f.significand2 = pu->significand[1];
389 kluge.f.significand3 = pu->significand[2];
390 kluge.f.significand4 = pu->significand[3];
391 break;
392 case fp_normal:
393 __fp_rightshift(pu, 15);
394 pu->exponent += QUAD_BIAS;
395 if (pu->exponent <= 0) { /* underflow */
396 __fp_rightshift(pu, 1 - pu->exponent);
397 round(pu, 4, rd, &e);
398 if (pu->significand[0] == 0x10000) {
399 /* rounded back up to normal */
400 kluge.f.msw.exponent = 1;
401 kluge.f.msw.significand = 0;
402 kluge.f.significand2 = 0;
403 kluge.f.significand3 = 0;
404 kluge.f.significand4 = 0;
405 e |= (1 << fp_underflow);
406 goto ret;
407 }
408 if (e & (1 << fp_inexact))
409 e |= (1 << fp_underflow);
410 kluge.f.msw.exponent = 0;
411 kluge.f.msw.significand = 0xffff & pu->significand[0];
412 kluge.f.significand2 = pu->significand[1];
413 kluge.f.significand3 = pu->significand[2];
414 kluge.f.significand4 = pu->significand[3];
415 goto ret;
416 }
417 round(pu, 4, rd, &e);
418 if (pu->significand[0] == 0x20000) { /* rounding overflow */
419 pu->significand[0] = 0x10000;
420 pu->exponent += 1;
421 }
422 if (pu->exponent >= 0x7fff) { /* overflow */
423 e |= (1 << fp_overflow) | (1 << fp_inexact);
424 if (overflow_to_infinity(pu->sign, rd))
425 goto infinity;
426 kluge.f.msw.exponent = 0x7ffe;
427 kluge.f.msw.significand = 0xffff;
428 kluge.f.significand2 = 0xffffffff;
429 kluge.f.significand3 = 0xffffffff;
430 kluge.f.significand4 = 0xffffffff;
431 goto ret;
432 }
433 kluge.f.msw.exponent = pu->exponent;
434 kluge.f.msw.significand = pu->significand[0] & 0xffff;
435 kluge.f.significand2 = pu->significand[1];
436 kluge.f.significand3 = pu->significand[2];
437 kluge.f.significand4 = pu->significand[3];
438 break;
439 }
440 ret:
441 *px = kluge.x;
442 *ex = (fp_exception_field_type)e;
443 }
444