Commit | Line | Data |
---|---|---|
fecd2382 RP |
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 |