3a69b3ac |
1 | /* atof_ieee.c - turn a Flonum into an IEEE floating point number |
2 | Copyright (C) 1987 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GAS, the GNU Assembler. |
5 | |
6 | GAS is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 1, or (at your option) |
9 | any later version. |
10 | |
11 | GAS is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GAS; see the file COPYING. If not, write to |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
19 | |
20 | #include "as.h" |
21 | |
22 | #ifdef USG |
23 | #define bzero(s,n) memset(s,0,n) |
24 | #define bcopy(from,to,n) memcpy((to),(from),(n)) |
25 | #endif |
26 | |
27 | extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */ |
28 | |
29 | #ifndef NULL |
30 | #define NULL (0) |
31 | #endif |
32 | |
33 | extern char EXP_CHARS[]; |
34 | /* Precision in LittleNums. */ |
35 | #define MAX_PRECISION (6) |
36 | #define F_PRECISION (2) |
37 | #define D_PRECISION (4) |
38 | #define X_PRECISION (6) |
39 | #define P_PRECISION (6) |
40 | |
41 | /* Length in LittleNums of guard bits. */ |
42 | #define GUARD (2) |
43 | |
44 | static unsigned long mask [] = { |
45 | 0x00000000, |
46 | 0x00000001, |
47 | 0x00000003, |
48 | 0x00000007, |
49 | 0x0000000f, |
50 | 0x0000001f, |
51 | 0x0000003f, |
52 | 0x0000007f, |
53 | 0x000000ff, |
54 | 0x000001ff, |
55 | 0x000003ff, |
56 | 0x000007ff, |
57 | 0x00000fff, |
58 | 0x00001fff, |
59 | 0x00003fff, |
60 | 0x00007fff, |
61 | 0x0000ffff, |
62 | 0x0001ffff, |
63 | 0x0003ffff, |
64 | 0x0007ffff, |
65 | 0x000fffff, |
66 | 0x001fffff, |
67 | 0x003fffff, |
68 | 0x007fffff, |
69 | 0x00ffffff, |
70 | 0x01ffffff, |
71 | 0x03ffffff, |
72 | 0x07ffffff, |
73 | 0x0fffffff, |
74 | 0x1fffffff, |
75 | 0x3fffffff, |
76 | 0x7fffffff, |
77 | 0xffffffff |
78 | }; |
79 | \f |
80 | |
81 | static int bits_left_in_littlenum; |
82 | static int littlenums_left; |
83 | static LITTLENUM_TYPE *littlenum_pointer; |
84 | |
85 | static int |
86 | next_bits (number_of_bits) |
87 | int number_of_bits; |
88 | { |
89 | int return_value; |
90 | |
91 | if(!littlenums_left) |
92 | return 0; |
93 | if (number_of_bits >= bits_left_in_littlenum) |
94 | { |
95 | return_value = mask [bits_left_in_littlenum] & *littlenum_pointer; |
96 | number_of_bits -= bits_left_in_littlenum; |
97 | return_value <<= number_of_bits; |
98 | if(--littlenums_left) { |
99 | bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; |
100 | littlenum_pointer --; |
101 | return_value |= (*littlenum_pointer>>bits_left_in_littlenum) & mask[number_of_bits]; |
102 | } |
103 | } |
104 | else |
105 | { |
106 | bits_left_in_littlenum -= number_of_bits; |
107 | return_value = mask [number_of_bits] & (*littlenum_pointer>>bits_left_in_littlenum); |
108 | } |
109 | return (return_value); |
110 | } |
111 | |
112 | /* Num had better be less than LITTLENUM_NUMBER_OF_BITS */ |
113 | static void |
114 | unget_bits(num) |
115 | int num; |
116 | { |
117 | if(!littlenums_left) { |
118 | ++littlenum_pointer; |
119 | ++littlenums_left; |
120 | bits_left_in_littlenum=num; |
121 | } else if(bits_left_in_littlenum+num>LITTLENUM_NUMBER_OF_BITS) { |
122 | bits_left_in_littlenum= num-(LITTLENUM_NUMBER_OF_BITS-bits_left_in_littlenum); |
123 | ++littlenum_pointer; |
124 | ++littlenums_left; |
125 | } else |
126 | bits_left_in_littlenum+=num; |
127 | } |
128 | |
129 | static void |
130 | make_invalid_floating_point_number (words) |
131 | LITTLENUM_TYPE * words; |
132 | { |
133 | as_bad("cannot create floating-point number"); |
134 | words[0]= ((unsigned)-1)>>1; /* Zero the leftmost bit */ |
135 | words[1]= -1; |
136 | words[2]= -1; |
137 | words[3]= -1; |
138 | words[4]= -1; |
139 | words[5]= -1; |
140 | } |
141 | \f |
142 | /***********************************************************************\ |
143 | * Warning: this returns 16-bit LITTLENUMs. It is up to the caller * |
144 | * to figure out any alignment problems and to conspire for the * |
145 | * bytes/word to be emitted in the right order. Bigendians beware! * |
146 | * * |
147 | \***********************************************************************/ |
148 | |
149 | /* Note that atof-ieee always has X and P precisions enabled. it is up |
150 | to md_atof to filter them out if the target machine does not support |
151 | them. */ |
152 | |
153 | char * /* Return pointer past text consumed. */ |
154 | atof_ieee (str, what_kind, words) |
155 | char * str; /* Text to convert to binary. */ |
156 | char what_kind; /* 'd', 'f', 'g', 'h' */ |
157 | LITTLENUM_TYPE * words; /* Build the binary here. */ |
158 | { |
159 | static LITTLENUM_TYPE bits [MAX_PRECISION + MAX_PRECISION + GUARD]; |
160 | /* Extra bits for zeroed low-order bits. */ |
161 | /* The 1st MAX_PRECISION are zeroed, */ |
162 | /* the last contain flonum bits. */ |
163 | char * return_value; |
164 | int precision; /* Number of 16-bit words in the format. */ |
165 | long exponent_bits; |
166 | |
167 | return_value = str; |
168 | generic_floating_point_number.low = bits + MAX_PRECISION; |
169 | generic_floating_point_number.high = NULL; |
170 | generic_floating_point_number.leader = NULL; |
171 | generic_floating_point_number.exponent = NULL; |
172 | generic_floating_point_number.sign = '\0'; |
173 | |
174 | /* Use more LittleNums than seems */ |
175 | /* necessary: the highest flonum may have */ |
176 | /* 15 leading 0 bits, so could be useless. */ |
177 | |
178 | bzero (bits, sizeof(LITTLENUM_TYPE) * MAX_PRECISION); |
179 | |
180 | switch(what_kind) { |
181 | case 'f': |
182 | case 'F': |
183 | case 's': |
184 | case 'S': |
185 | precision = F_PRECISION; |
186 | exponent_bits = 8; |
187 | break; |
188 | |
189 | case 'd': |
190 | case 'D': |
191 | case 'r': |
192 | case 'R': |
193 | precision = D_PRECISION; |
194 | exponent_bits = 11; |
195 | break; |
196 | |
197 | case 'x': |
198 | case 'X': |
199 | case 'e': |
200 | case 'E': |
201 | precision = X_PRECISION; |
202 | exponent_bits = 15; |
203 | break; |
204 | |
205 | case 'p': |
206 | case 'P': |
207 | |
208 | precision = P_PRECISION; |
209 | exponent_bits= -1; |
210 | break; |
211 | |
212 | default: |
213 | make_invalid_floating_point_number (words); |
214 | return NULL; |
215 | } |
216 | |
217 | generic_floating_point_number.high = generic_floating_point_number.low + precision - 1 + GUARD; |
218 | |
219 | if (atof_generic (& return_value, ".", EXP_CHARS, & generic_floating_point_number)) { |
220 | /* as_bad("Error converting floating point number (Exponent overflow?)"); */ |
221 | make_invalid_floating_point_number (words); |
222 | return NULL; |
223 | } |
224 | gen_to_words(words, precision, exponent_bits); |
225 | return return_value; |
226 | } |
227 | |
228 | /* Turn generic_floating_point_number into a real float/double/extended */ |
229 | int gen_to_words(words, precision, exponent_bits) |
230 | LITTLENUM_TYPE *words; |
231 | int precision; |
232 | long exponent_bits; |
233 | { |
234 | int return_value=0; |
235 | |
236 | long exponent_1; |
237 | long exponent_2; |
238 | long exponent_3; |
239 | long exponent_4; |
240 | int exponent_skippage; |
241 | LITTLENUM_TYPE word1; |
242 | LITTLENUM_TYPE * lp; |
243 | |
244 | if (generic_floating_point_number.low > generic_floating_point_number.leader) { |
245 | /* 0.0e0 seen. */ |
246 | if(generic_floating_point_number.sign=='+') |
247 | words[0]=0x0000; |
248 | else |
249 | words[0]=0x8000; |
250 | bzero (&words[1], sizeof(LITTLENUM_TYPE) * (precision-1)); |
251 | return return_value; |
252 | } |
253 | |
254 | /* NaN: Do the right thing */ |
255 | if(generic_floating_point_number.sign==0) { |
256 | if(precision==F_PRECISION) { |
257 | words[0]=0x7fff; |
258 | words[1]=0xffff; |
259 | } else { |
260 | words[0]=0x7fff; |
261 | words[1]=0xffff; |
262 | words[2]=0xffff; |
263 | words[3]=0xffff; |
264 | } |
265 | return return_value; |
266 | } else if(generic_floating_point_number.sign=='P') { |
267 | /* +INF: Do the right thing */ |
268 | if(precision==F_PRECISION) { |
269 | words[0]=0x7f80; |
270 | words[1]=0; |
271 | } else { |
272 | words[0]=0x7ff0; |
273 | words[1]=0; |
274 | words[2]=0; |
275 | words[3]=0; |
276 | } |
277 | return return_value; |
278 | } else if(generic_floating_point_number.sign=='N') { |
279 | /* Negative INF */ |
280 | if(precision==F_PRECISION) { |
281 | words[0]=0xff80; |
282 | words[1]=0x0; |
283 | } else { |
284 | words[0]=0xfff0; |
285 | words[1]=0x0; |
286 | words[2]=0x0; |
287 | words[3]=0x0; |
288 | } |
289 | return return_value; |
290 | } |
291 | /* |
292 | * The floating point formats we support have: |
293 | * Bit 15 is sign bit. |
294 | * Bits 14:n are excess-whatever exponent. |
295 | * Bits n-1:0 (if any) are most significant bits of fraction. |
296 | * Bits 15:0 of the next word(s) are the next most significant bits. |
297 | * |
298 | * So we need: number of bits of exponent, number of bits of |
299 | * mantissa. |
300 | */ |
301 | bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; |
302 | littlenum_pointer = generic_floating_point_number.leader; |
303 | littlenums_left = 1+generic_floating_point_number.leader - generic_floating_point_number.low; |
304 | /* Seek (and forget) 1st significant bit */ |
305 | for (exponent_skippage = 0;! next_bits(1); exponent_skippage ++) |
306 | ; |
307 | exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader + 1 - |
308 | generic_floating_point_number.low; |
309 | /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */ |
310 | exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; |
311 | /* Radix 2. */ |
312 | exponent_3 = exponent_2 - exponent_skippage; |
313 | /* Forget leading zeros, forget 1st bit. */ |
314 | exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); |
315 | /* Offset exponent. */ |
316 | |
317 | lp = words; |
318 | |
319 | /* Word 1. Sign, exponent and perhaps high bits. */ |
320 | word1 = (generic_floating_point_number.sign == '+') ? 0 : (1<<(LITTLENUM_NUMBER_OF_BITS-1)); |
321 | |
322 | /* Assume 2's complement integers. */ |
323 | if(exponent_4<1 && exponent_4>=-62) { |
324 | int prec_bits; |
325 | int num_bits; |
326 | |
327 | unget_bits(1); |
328 | num_bits= -exponent_4; |
329 | prec_bits=LITTLENUM_NUMBER_OF_BITS*precision-(exponent_bits+1+num_bits); |
330 | if(precision==X_PRECISION && exponent_bits==15) |
331 | prec_bits-=LITTLENUM_NUMBER_OF_BITS+1; |
332 | |
333 | if(num_bits>=LITTLENUM_NUMBER_OF_BITS-exponent_bits) { |
334 | /* Bigger than one littlenum */ |
335 | num_bits-=(LITTLENUM_NUMBER_OF_BITS-1)-exponent_bits; |
336 | *lp++=word1; |
337 | if(num_bits+exponent_bits+1>=precision*LITTLENUM_NUMBER_OF_BITS) { |
338 | /* Exponent overflow */ |
339 | make_invalid_floating_point_number(words); |
340 | return return_value; |
341 | } |
342 | if(precision==X_PRECISION && exponent_bits==15) { |
343 | *lp++=0; |
344 | *lp++=0; |
345 | num_bits-=LITTLENUM_NUMBER_OF_BITS-1; |
346 | } |
347 | while(num_bits>=LITTLENUM_NUMBER_OF_BITS) { |
348 | num_bits-=LITTLENUM_NUMBER_OF_BITS; |
349 | *lp++=0; |
350 | } |
351 | if(num_bits) |
352 | *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-(num_bits)); |
353 | } else { |
354 | if(precision==X_PRECISION && exponent_bits==15) { |
355 | *lp++=word1; |
356 | *lp++=0; |
357 | if(num_bits==LITTLENUM_NUMBER_OF_BITS) { |
358 | *lp++=0; |
359 | *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-1); |
360 | } else if(num_bits==LITTLENUM_NUMBER_OF_BITS-1) |
361 | *lp++=0; |
362 | else |
363 | *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-1-num_bits); |
364 | num_bits=0; |
365 | } else { |
366 | word1|= next_bits ((LITTLENUM_NUMBER_OF_BITS-1) - (exponent_bits+num_bits)); |
367 | *lp++=word1; |
368 | } |
369 | } |
370 | while(lp<words+precision) |
371 | *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS); |
372 | |
373 | /* Round the mantissa up, but don't change the number */ |
374 | if(next_bits(1)) { |
375 | --lp; |
376 | if(prec_bits>LITTLENUM_NUMBER_OF_BITS) { |
377 | int n = 0; |
378 | int tmp_bits; |
379 | |
380 | n=0; |
381 | tmp_bits=prec_bits; |
382 | while(tmp_bits>LITTLENUM_NUMBER_OF_BITS) { |
383 | if(lp[n]!=(LITTLENUM_TYPE)-1) |
384 | break; |
385 | --n; |
386 | tmp_bits-=LITTLENUM_NUMBER_OF_BITS; |
387 | } |
388 | if(tmp_bits>LITTLENUM_NUMBER_OF_BITS || (lp[n]&mask[tmp_bits])!=mask[tmp_bits]) { |
389 | unsigned long carry; |
390 | |
391 | for (carry = 1; carry && (lp >= words); lp --) { |
392 | carry = * lp + carry; |
393 | * lp = carry; |
394 | carry >>= LITTLENUM_NUMBER_OF_BITS; |
395 | } |
396 | } |
397 | } else if((*lp&mask[prec_bits])!=mask[prec_bits]) |
398 | lp++; |
399 | } |
400 | |
401 | return return_value; |
402 | } else if (exponent_4 & ~ mask [exponent_bits]) { |
403 | /* |
404 | * Exponent overflow. Lose immediately. |
405 | */ |
406 | |
407 | /* |
408 | * We leave return_value alone: admit we read the |
409 | * number, but return a floating exception |
410 | * because we can't encode the number. |
411 | */ |
412 | make_invalid_floating_point_number (words); |
413 | return return_value; |
414 | } else { |
415 | word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS-1) - exponent_bits)) |
416 | | next_bits ((LITTLENUM_NUMBER_OF_BITS-1) - exponent_bits); |
417 | } |
418 | |
419 | * lp ++ = word1; |
420 | |
421 | /* X_PRECISION is special: it has 16 bits of zero in the middle, |
422 | followed by a 1 bit. */ |
423 | if(exponent_bits==15 && precision==X_PRECISION) { |
424 | *lp++=0; |
425 | *lp++= 1<<(LITTLENUM_NUMBER_OF_BITS)|next_bits(LITTLENUM_NUMBER_OF_BITS-1); |
426 | } |
427 | |
428 | /* The rest of the words are just mantissa bits. */ |
429 | while(lp < words + precision) |
430 | *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); |
431 | |
432 | if (next_bits (1)) { |
433 | unsigned long carry; |
434 | /* |
435 | * Since the NEXT bit is a 1, round UP the mantissa. |
436 | * The cunning design of these hidden-1 floats permits |
437 | * us to let the mantissa overflow into the exponent, and |
438 | * it 'does the right thing'. However, we lose if the |
439 | * highest-order bit of the lowest-order word flips. |
440 | * Is that clear? |
441 | */ |
442 | |
443 | |
444 | /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) |
445 | Please allow at least 1 more bit in carry than is in a LITTLENUM. |
446 | We need that extra bit to hold a carry during a LITTLENUM carry |
447 | propagation. Another extra bit (kept 0) will assure us that we |
448 | don't get a sticky sign bit after shifting right, and that |
449 | permits us to propagate the carry without any masking of bits. |
450 | #endif */ |
451 | for (carry = 1, lp --; carry && (lp >= words); lp --) { |
452 | carry = * lp + carry; |
453 | * lp = carry; |
454 | carry >>= LITTLENUM_NUMBER_OF_BITS; |
455 | } |
456 | if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) ) { |
457 | /* We leave return_value alone: admit we read the |
458 | * number, but return a floating exception |
459 | * because we can't encode the number. |
460 | */ |
461 | *words&= ~ (1 << (LITTLENUM_NUMBER_OF_BITS - 1)); |
462 | /* make_invalid_floating_point_number (words); */ |
463 | /* return return_value; */ |
464 | } |
465 | } |
466 | return (return_value); |
467 | } |
468 | |
469 | /* This routine is a real kludge. Someone really should do it better, but |
470 | I'm too lazy, and I don't understand this stuff all too well anyway |
471 | (JF) |
472 | */ |
473 | void |
474 | int_to_gen(x) |
475 | long x; |
476 | { |
477 | char buf[20]; |
478 | char *bufp; |
479 | |
480 | sprintf(buf,"%ld",x); |
481 | bufp= &buf[0]; |
482 | if(atof_generic(&bufp,".", EXP_CHARS, &generic_floating_point_number)) |
483 | as_bad("Error converting number to floating point (Exponent overflow?)"); |
484 | } |
485 | |
486 | #ifdef TEST |
487 | char * |
488 | print_gen(gen) |
489 | FLONUM_TYPE *gen; |
490 | { |
491 | FLONUM_TYPE f; |
492 | LITTLENUM_TYPE arr[10]; |
493 | double dv; |
494 | float fv; |
495 | static char sbuf[40]; |
496 | |
497 | if(gen) { |
498 | f=generic_floating_point_number; |
499 | generic_floating_point_number= *gen; |
500 | } |
501 | gen_to_words(&arr[0],4,11); |
502 | bcopy(&arr[0],&dv,sizeof(double)); |
503 | sprintf(sbuf,"%x %x %x %x %.14G ",arr[0],arr[1],arr[2],arr[3],dv); |
504 | gen_to_words(&arr[0],2,8); |
505 | bcopy(&arr[0],&fv,sizeof(float)); |
506 | sprintf(sbuf+strlen(sbuf),"%x %x %.12g\n",arr[0],arr[1],fv); |
507 | if(gen) |
508 | generic_floating_point_number=f; |
509 | return sbuf; |
510 | } |
511 | #endif |