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 /* conversion from hex chars to hex values */ 31 #define HEXVAL(c) (('0' <= c && c <= '9')? c - '0' : \ 32 10 + (('a' <= c && c <= 'f')? c - 'a' : c - 'A')) 33 34 /* 35 * Convert a hexadecimal record in *pd to unpacked form in *pu. 36 * 37 * Up to 30 hexadecimal digits from pd->ds are converted to a binary 38 * value in px->significand, which is then normalized so that the most 39 * significant bit is 1. If there are additional, unused digits in 40 * pd->ds, the least significant bit of px->significand will be set. 41 */ 42 static void 43 __hex_to_unpacked(decimal_record *pd, unpacked *pu) 44 { 45 int i, n; 46 47 pu->sign = pd->sign; 48 pu->fpclass = pd->fpclass; 49 50 /* 51 * Adjust the (base two) exponent to reflect the fact that the 52 * radix point in *pd lies to the right of the last (base sixteen) 53 * digit while the radix point in *pu lies to the right of the 54 * most significant bit. 55 */ 56 pu->exponent = pd->exponent + (pd->ndigits << 2) - 1; 57 58 /* fill in the significand */ 59 for (i = 0; i < 5; i++) 60 pu->significand[i] = 0; 61 62 n = pd->ndigits; 63 if (n > 30) 64 n = 30; 65 for (i = 0; i < n; i++) { 66 pu->significand[i >> 3] |= HEXVAL(pd->ds[i]) << 67 ((7 - (i & 7)) << 2); 68 } 69 70 /* sanity check */ 71 if (pu->significand[0] == 0) { 72 pu->fpclass = fp_zero; 73 return; 74 } 75 76 /* normalize so the most significant bit is set */ 77 while (pu->significand[0] < 0x80000000u) { 78 pu->significand[0] = (pu->significand[0] << 1) | 79 (pu->significand[1] >> 31); 80 pu->significand[1] = (pu->significand[1] << 1) | 81 (pu->significand[2] >> 31); 82 pu->significand[2] = (pu->significand[2] << 1) | 83 (pu->significand[3] >> 31); 84 pu->significand[3] <<= 1; 85 pu->exponent--; 86 } 87 88 /* if there are any unused digits, set a sticky bit */ 89 if (pd->ndigits > 30 || pd->more) 90 pu->significand[4] = 1; 91 } 92 93 /* 94 * The following routines convert the hexadecimal value encoded in the 95 * decimal record *pd to a floating point value *px observing the round- 96 * ing mode specified in rd and passing back any exceptions raised via 97 * *ps. 98 * 99 * These routines assume pd->fpclass is either fp_zero or fp_normal. 100 * If pd->fpclass is fp_zero, *px is set to zero with the sign indicated 101 * by pd->sign and no exceptions are raised. Otherwise, pd->ds must 102 * contain a string of hexadecimal digits of length pd->ndigits > 0, and 103 * the first digit must be nonzero. Let m be the integer represented by 104 * this string. Then *px is set to a correctly rounded approximation to 105 * 106 * (-1)^(pd->sign) * m * 2^(pd->exponent) 107 * 108 * with inexact, underflow, and/or overflow raised as appropriate. 109 */ 110 111 void 112 __hex_to_single(decimal_record *pd, enum fp_direction_type rd, single *px, 113 fp_exception_field_type *ps) 114 { 115 single_equivalence kluge; 116 unpacked u; 117 118 *ps = 0; 119 if (pd->fpclass == fp_zero) { 120 kluge.f.msw.sign = pd->sign? 1 : 0; 121 kluge.f.msw.exponent = 0; 122 kluge.f.msw.significand = 0; 123 *px = kluge.x; 124 } else { 125 __hex_to_unpacked(pd, &u); 126 __pack_single(&u, px, rd, ps); 127 if (*ps != 0) 128 __base_conversion_set_exception(*ps); 129 } 130 } 131 132 void 133 __hex_to_double(decimal_record *pd, enum fp_direction_type rd, double *px, 134 fp_exception_field_type *ps) 135 { 136 double_equivalence kluge; 137 unpacked u; 138 139 *ps = 0; 140 if (pd->fpclass == fp_zero) { 141 kluge.f.msw.sign = pd->sign? 1 : 0; 142 kluge.f.msw.exponent = 0; 143 kluge.f.msw.significand = 0; 144 kluge.f.significand2 = 0; 145 *px = kluge.x; 146 } else { 147 __hex_to_unpacked(pd, &u); 148 __pack_double(&u, px, rd, ps); 149 if (*ps != 0) 150 __base_conversion_set_exception(*ps); 151 } 152 } 153 154 #if defined(__sparc) 155 156 void 157 __hex_to_quadruple(decimal_record *pd, enum fp_direction_type rd, quadruple *px, 158 fp_exception_field_type *ps) 159 { 160 quadruple_equivalence kluge; 161 unpacked u; 162 163 *ps = 0; 164 if (pd->fpclass == fp_zero) { 165 kluge.f.msw.sign = pd->sign? 1 : 0; 166 kluge.f.msw.exponent = 0; 167 kluge.f.msw.significand = 0; 168 kluge.f.significand2 = 0; 169 kluge.f.significand3 = 0; 170 kluge.f.significand4 = 0; 171 *px = kluge.x; 172 } else { 173 __hex_to_unpacked(pd, &u); 174 __pack_quadruple(&u, px, rd, ps); 175 if (*ps != 0) 176 __base_conversion_set_exception(*ps); 177 } 178 } 179 180 #elif defined(__i386) || defined(__amd64) 181 182 void 183 __hex_to_extended(decimal_record *pd, enum fp_direction_type rd, extended *px, 184 fp_exception_field_type *ps) 185 { 186 extended_equivalence kluge; 187 unpacked u; 188 189 *ps = 0; 190 if (pd->fpclass == fp_zero) { 191 kluge.f.msw.sign = pd->sign? 1 : 0; 192 kluge.f.msw.exponent = 0; 193 kluge.f.significand = 0; 194 kluge.f.significand2 = 0; 195 (*px)[0] = kluge.x[0]; 196 (*px)[1] = kluge.x[1]; 197 (*px)[2] = kluge.x[2]; 198 } else { 199 __hex_to_unpacked(pd, &u); 200 __pack_extended(&u, px, rd, ps); 201 if (*ps != 0) 202 __base_conversion_set_exception(*ps); 203 } 204 } 205 206 #else 207 #error Unknown architecture 208 #endif 209