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 2004 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 "synonyms.h" 30 #include "base_conversion.h" 31 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')) 35 36 /* 37 * Convert a hexadecimal record in *pd to unpacked form in *pu. 38 * 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. 43 */ 44 static void 45 __hex_to_unpacked(decimal_record *pd, unpacked *pu) 46 { 47 int i, n; 48 49 pu->sign = pd->sign; 50 pu->fpclass = pd->fpclass; 51 52 /* 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. 57 */ 58 pu->exponent = pd->exponent + (pd->ndigits << 2) - 1; 59 60 /* fill in the significand */ 61 for (i = 0; i < 5; i++) 62 pu->significand[i] = 0; 63 64 n = pd->ndigits; 65 if (n > 30) 66 n = 30; 67 for (i = 0; i < n; i++) { 68 pu->significand[i >> 3] |= HEXVAL(pd->ds[i]) << 69 ((7 - (i & 7)) << 2); 70 } 71 72 /* sanity check */ 73 if (pu->significand[0] == 0) { 74 pu->fpclass = fp_zero; 75 return; 76 } 77 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; 87 pu->exponent--; 88 } 89 90 /* if there are any unused digits, set a sticky bit */ 91 if (pd->ndigits > 30 || pd->more) 92 pu->significand[4] = 1; 93 } 94 95 /* 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 99 * *ps. 100 * 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 107 * 108 * (-1)^(pd->sign) * m * 2^(pd->exponent) 109 * 110 * with inexact, underflow, and/or overflow raised as appropriate. 111 */ 112 113 void 114 __hex_to_single(decimal_record *pd, enum fp_direction_type rd, single *px, 115 fp_exception_field_type *ps) 116 { 117 single_equivalence kluge; 118 unpacked u; 119 120 *ps = 0; 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; 125 *px = kluge.x; 126 } else { 127 __hex_to_unpacked(pd, &u); 128 __pack_single(&u, px, rd, ps); 129 if (*ps != 0) 130 __base_conversion_set_exception(*ps); 131 } 132 } 133 134 void 135 __hex_to_double(decimal_record *pd, enum fp_direction_type rd, double *px, 136 fp_exception_field_type *ps) 137 { 138 double_equivalence kluge; 139 unpacked u; 140 141 *ps = 0; 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; 147 *px = kluge.x; 148 } else { 149 __hex_to_unpacked(pd, &u); 150 __pack_double(&u, px, rd, ps); 151 if (*ps != 0) 152 __base_conversion_set_exception(*ps); 153 } 154 } 155 156 #if defined(__sparc) 157 158 void 159 __hex_to_quadruple(decimal_record *pd, enum fp_direction_type rd, quadruple *px, 160 fp_exception_field_type *ps) 161 { 162 quadruple_equivalence kluge; 163 unpacked u; 164 165 *ps = 0; 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; 173 *px = kluge.x; 174 } else { 175 __hex_to_unpacked(pd, &u); 176 __pack_quadruple(&u, px, rd, ps); 177 if (*ps != 0) 178 __base_conversion_set_exception(*ps); 179 } 180 } 181 182 #elif defined(__i386) || defined(__amd64) 183 184 void 185 __hex_to_extended(decimal_record *pd, enum fp_direction_type rd, extended *px, 186 fp_exception_field_type *ps) 187 { 188 extended_equivalence kluge; 189 unpacked u; 190 191 *ps = 0; 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]; 200 } else { 201 __hex_to_unpacked(pd, &u); 202 __pack_extended(&u, px, rd, ps); 203 if (*ps != 0) 204 __base_conversion_set_exception(*ps); 205 } 206 } 207 208 #else 209 #error Unknown architecture 210 #endif 211