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