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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include "base_conversion.h"
32 /* conversion from hex chars to hex values */
33 #define HEXVAL(c) (('0' <= c && c <= '9')? c - '0' : \
34 10 + (('a' <= c && c <= 'f')? c - 'a' : c - 'A'))
37 * Convert a hexadecimal record in *pd to unpacked form in *pu.
39 * Up to 30 hexadecimal digits from pd->ds are converted to a binary
40 * value in px->significand, which is then normalized so that the most
41 * significant bit is 1. If there are additional, unused digits in
42 * pd->ds, the least significant bit of px->significand will be set.
45 __hex_to_unpacked(decimal_record
*pd
, unpacked
*pu
)
50 pu
->fpclass
= pd
->fpclass
;
53 * Adjust the (base two) exponent to reflect the fact that the
54 * radix point in *pd lies to the right of the last (base sixteen)
55 * digit while the radix point in *pu lies to the right of the
56 * most significant bit.
58 pu
->exponent
= pd
->exponent
+ (pd
->ndigits
<< 2) - 1;
60 /* fill in the significand */
61 for (i
= 0; i
< 5; i
++)
62 pu
->significand
[i
] = 0;
67 for (i
= 0; i
< n
; i
++) {
68 pu
->significand
[i
>> 3] |= HEXVAL(pd
->ds
[i
]) <<
73 if (pu
->significand
[0] == 0) {
74 pu
->fpclass
= fp_zero
;
78 /* normalize so the most significant bit is set */
79 while (pu
->significand
[0] < 0x80000000u
) {
80 pu
->significand
[0] = (pu
->significand
[0] << 1) |
81 (pu
->significand
[1] >> 31);
82 pu
->significand
[1] = (pu
->significand
[1] << 1) |
83 (pu
->significand
[2] >> 31);
84 pu
->significand
[2] = (pu
->significand
[2] << 1) |
85 (pu
->significand
[3] >> 31);
86 pu
->significand
[3] <<= 1;
90 /* if there are any unused digits, set a sticky bit */
91 if (pd
->ndigits
> 30 || pd
->more
)
92 pu
->significand
[4] = 1;
96 * The following routines convert the hexadecimal value encoded in the
97 * decimal record *pd to a floating point value *px observing the round-
98 * ing mode specified in rd and passing back any exceptions raised via
101 * These routines assume pd->fpclass is either fp_zero or fp_normal.
102 * If pd->fpclass is fp_zero, *px is set to zero with the sign indicated
103 * by pd->sign and no exceptions are raised. Otherwise, pd->ds must
104 * contain a string of hexadecimal digits of length pd->ndigits > 0, and
105 * the first digit must be nonzero. Let m be the integer represented by
106 * this string. Then *px is set to a correctly rounded approximation to
108 * (-1)^(pd->sign) * m * 2^(pd->exponent)
110 * with inexact, underflow, and/or overflow raised as appropriate.
114 __hex_to_single(decimal_record
*pd
, enum fp_direction_type rd
, single
*px
,
115 fp_exception_field_type
*ps
)
117 single_equivalence kluge
;
121 if (pd
->fpclass
== fp_zero
) {
122 kluge
.f
.msw
.sign
= pd
->sign
? 1 : 0;
123 kluge
.f
.msw
.exponent
= 0;
124 kluge
.f
.msw
.significand
= 0;
127 __hex_to_unpacked(pd
, &u
);
128 __pack_single(&u
, px
, rd
, ps
);
130 __base_conversion_set_exception(*ps
);
135 __hex_to_double(decimal_record
*pd
, enum fp_direction_type rd
, double *px
,
136 fp_exception_field_type
*ps
)
138 double_equivalence kluge
;
142 if (pd
->fpclass
== fp_zero
) {
143 kluge
.f
.msw
.sign
= pd
->sign
? 1 : 0;
144 kluge
.f
.msw
.exponent
= 0;
145 kluge
.f
.msw
.significand
= 0;
146 kluge
.f
.significand2
= 0;
149 __hex_to_unpacked(pd
, &u
);
150 __pack_double(&u
, px
, rd
, ps
);
152 __base_conversion_set_exception(*ps
);
159 __hex_to_quadruple(decimal_record
*pd
, enum fp_direction_type rd
, quadruple
*px
,
160 fp_exception_field_type
*ps
)
162 quadruple_equivalence kluge
;
166 if (pd
->fpclass
== fp_zero
) {
167 kluge
.f
.msw
.sign
= pd
->sign
? 1 : 0;
168 kluge
.f
.msw
.exponent
= 0;
169 kluge
.f
.msw
.significand
= 0;
170 kluge
.f
.significand2
= 0;
171 kluge
.f
.significand3
= 0;
172 kluge
.f
.significand4
= 0;
175 __hex_to_unpacked(pd
, &u
);
176 __pack_quadruple(&u
, px
, rd
, ps
);
178 __base_conversion_set_exception(*ps
);
182 #elif defined(__i386) || defined(__amd64)
185 __hex_to_extended(decimal_record
*pd
, enum fp_direction_type rd
, extended
*px
,
186 fp_exception_field_type
*ps
)
188 extended_equivalence kluge
;
192 if (pd
->fpclass
== fp_zero
) {
193 kluge
.f
.msw
.sign
= pd
->sign
? 1 : 0;
194 kluge
.f
.msw
.exponent
= 0;
195 kluge
.f
.significand
= 0;
196 kluge
.f
.significand2
= 0;
197 (*px
)[0] = kluge
.x
[0];
198 (*px
)[1] = kluge
.x
[1];
199 (*px
)[2] = kluge
.x
[2];
201 __hex_to_unpacked(pd
, &u
);
202 __pack_extended(&u
, px
, rd
, ps
);
204 __base_conversion_set_exception(*ps
);
209 #error Unknown architecture