Commit | Line | Data |
---|---|---|
88db8f81 KR |
1 | |
2 | /* atof_tahoe.c - turn a string into a Tahoe floating point number | |
48401fcf | 3 | Copyright (C) 1987, 1998 Free Software Foundation, Inc. |
88db8f81 KR |
4 | */ |
5 | ||
6 | /* This is really a simplified version of atof_vax.c. I glommed it wholesale | |
7 | and then shaved it down. I don't even know how it works. (Don't you find | |
8 | my honesty refreshing? bowen@cs.Buffalo.EDU (Devon E Bowen) | |
9 | ||
10 | I don't allow uppercase letters in the precision descrpitors. Ie 'f' and | |
11 | 'd' are allowed but 'F' and 'D' aren't */ | |
12 | ||
13 | #include "as.h" | |
14 | ||
15 | /* Precision in LittleNums. */ | |
16 | #define MAX_PRECISION (4) | |
17 | #define D_PRECISION (4) | |
18 | #define F_PRECISION (2) | |
19 | ||
20 | /* Precision in chars. */ | |
21 | #define D_PRECISION_CHARS (8) | |
22 | #define F_PRECISION_CHARS (4) | |
23 | ||
24 | /* Length in LittleNums of guard bits. */ | |
25 | #define GUARD (2) | |
26 | ||
27 | static const long int mask[] = | |
28 | { | |
29 | 0x00000000, | |
30 | 0x00000001, | |
31 | 0x00000003, | |
32 | 0x00000007, | |
33 | 0x0000000f, | |
34 | 0x0000001f, | |
35 | 0x0000003f, | |
36 | 0x0000007f, | |
37 | 0x000000ff, | |
38 | 0x000001ff, | |
39 | 0x000003ff, | |
40 | 0x000007ff, | |
41 | 0x00000fff, | |
42 | 0x00001fff, | |
43 | 0x00003fff, | |
44 | 0x00007fff, | |
45 | 0x0000ffff, | |
46 | 0x0001ffff, | |
47 | 0x0003ffff, | |
48 | 0x0007ffff, | |
49 | 0x000fffff, | |
50 | 0x001fffff, | |
51 | 0x003fffff, | |
52 | 0x007fffff, | |
53 | 0x00ffffff, | |
54 | 0x01ffffff, | |
55 | 0x03ffffff, | |
56 | 0x07ffffff, | |
57 | 0x0fffffff, | |
58 | 0x1fffffff, | |
59 | 0x3fffffff, | |
60 | 0x7fffffff, | |
61 | 0xffffffff | |
62 | }; | |
63 | \f | |
64 | ||
65 | /* Shared between flonum_gen2tahoe and next_bits */ | |
66 | static int bits_left_in_littlenum; | |
67 | static LITTLENUM_TYPE *littlenum_pointer; | |
68 | static LITTLENUM_TYPE *littlenum_end; | |
69 | ||
70 | #if __STDC__ == 1 | |
71 | ||
72 | int flonum_gen2tahoe (int format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words); | |
73 | ||
74 | #else /* not __STDC__ */ | |
75 | ||
76 | int flonum_gen2tahoe (); | |
77 | ||
78 | #endif /* not __STDC__ */ | |
79 | ||
80 | ||
81 | static int | |
82 | next_bits (number_of_bits) | |
83 | int number_of_bits; | |
84 | { | |
85 | int return_value; | |
86 | ||
87 | if (littlenum_pointer < littlenum_end) | |
88 | return 0; | |
89 | if (number_of_bits >= bits_left_in_littlenum) | |
90 | { | |
91 | return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; | |
92 | number_of_bits -= bits_left_in_littlenum; | |
93 | return_value <<= number_of_bits; | |
94 | bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; | |
95 | littlenum_pointer--; | |
96 | if (littlenum_pointer >= littlenum_end) | |
97 | return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & | |
98 | mask[number_of_bits]; | |
99 | } | |
100 | else | |
101 | { | |
102 | bits_left_in_littlenum -= number_of_bits; | |
103 | return_value = mask[number_of_bits] & | |
104 | ((*littlenum_pointer) >> bits_left_in_littlenum); | |
105 | } | |
106 | return (return_value); | |
107 | } | |
108 | ||
109 | static void | |
110 | make_invalid_floating_point_number (words) | |
111 | LITTLENUM_TYPE *words; | |
112 | { | |
113 | *words = 0x8000; /* Floating Reserved Operand Code */ | |
114 | } | |
115 | \f | |
116 | static int /* 0 means letter is OK. */ | |
117 | what_kind_of_float (letter, precisionP, exponent_bitsP) | |
118 | char letter; /* In: lowercase please. What kind of float? */ | |
119 | int *precisionP; /* Number of 16-bit words in the float. */ | |
120 | long int *exponent_bitsP; /* Number of exponent bits. */ | |
121 | { | |
122 | int retval; /* 0: OK. */ | |
123 | ||
124 | retval = 0; | |
125 | switch (letter) | |
126 | { | |
127 | case 'f': | |
128 | *precisionP = F_PRECISION; | |
129 | *exponent_bitsP = 8; | |
130 | break; | |
131 | ||
132 | case 'd': | |
133 | *precisionP = D_PRECISION; | |
134 | *exponent_bitsP = 8; | |
135 | break; | |
136 | ||
137 | default: | |
138 | retval = 69; | |
139 | break; | |
140 | } | |
141 | return (retval); | |
142 | } | |
143 | \f | |
144 | /***********************************************************************\ | |
145 | * * | |
146 | * Warning: this returns 16-bit LITTLENUMs, because that is * | |
147 | * what the VAX thinks in. It is up to the caller to figure * | |
148 | * out any alignment problems and to conspire for the bytes/word * | |
149 | * to be emitted in the right order. Bigendians beware! * | |
150 | * * | |
151 | \***********************************************************************/ | |
152 | ||
153 | char * /* Return pointer past text consumed. */ | |
154 | atof_tahoe (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 | FLONUM_TYPE f; | |
160 | LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; | |
161 | /* Extra bits for zeroed low-order bits. */ | |
162 | /* The 1st MAX_PRECISION are zeroed, */ | |
163 | /* the last contain flonum bits. */ | |
164 | char *return_value; | |
165 | int precision; /* Number of 16-bit words in the format. */ | |
166 | long int exponent_bits; | |
167 | ||
168 | return_value = str; | |
169 | f.low = bits + MAX_PRECISION; | |
170 | f.high = NULL; | |
171 | f.leader = NULL; | |
172 | f.exponent = NULL; | |
173 | f.sign = '\0'; | |
174 | ||
175 | if (what_kind_of_float (what_kind, &precision, &exponent_bits)) | |
176 | { | |
177 | return_value = NULL; /* We lost. */ | |
178 | make_invalid_floating_point_number (words); | |
179 | } | |
180 | if (return_value) | |
181 | { | |
182 | memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); | |
183 | ||
184 | /* Use more LittleNums than seems */ | |
185 | /* necessary: the highest flonum may have */ | |
186 | /* 15 leading 0 bits, so could be useless. */ | |
187 | f.high = f.low + precision - 1 + GUARD; | |
188 | ||
189 | if (atof_generic (&return_value, ".", "eE", &f)) | |
190 | { | |
191 | make_invalid_floating_point_number (words); | |
192 | return_value = NULL; /* we lost */ | |
193 | } | |
194 | else | |
195 | { | |
196 | if (flonum_gen2tahoe (what_kind, &f, words)) | |
197 | { | |
198 | return_value = NULL; | |
199 | } | |
200 | } | |
201 | } | |
202 | return (return_value); | |
203 | } | |
204 | \f | |
205 | /* | |
206 | * In: a flonum, a Tahoe floating point format. | |
207 | * Out: a Tahoe floating-point bit pattern. | |
208 | */ | |
209 | ||
210 | int /* 0: OK. */ | |
211 | flonum_gen2tahoe (format_letter, f, words) | |
212 | char format_letter; /* One of 'd' 'f'. */ | |
213 | FLONUM_TYPE *f; | |
214 | LITTLENUM_TYPE *words; /* Deliver answer here. */ | |
215 | { | |
216 | LITTLENUM_TYPE *lp; | |
217 | int precision; | |
218 | long int exponent_bits; | |
219 | int return_value; /* 0 == OK. */ | |
220 | ||
221 | return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); | |
222 | if (return_value != 0) | |
223 | { | |
224 | make_invalid_floating_point_number (words); | |
225 | } | |
226 | else | |
227 | { | |
228 | if (f->low > f->leader) | |
229 | { | |
230 | /* 0.0e0 seen. */ | |
231 | memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); | |
232 | } | |
233 | else | |
234 | { | |
235 | long int exponent_1; | |
236 | long int exponent_2; | |
237 | long int exponent_3; | |
238 | long int exponent_4; | |
239 | int exponent_skippage; | |
240 | LITTLENUM_TYPE word1; | |
241 | ||
242 | /* JF: Deal with new Nan, +Inf and -Inf codes */ | |
243 | if (f->sign != '-' && f->sign != '+') | |
244 | { | |
245 | make_invalid_floating_point_number (words); | |
246 | return return_value; | |
247 | } | |
248 | /* | |
249 | * All tahoe floating_point formats have: | |
250 | * Bit 15 is sign bit. | |
251 | * Bits 14:n are excess-whatever exponent. | |
252 | * Bits n-1:0 (if any) are most significant bits of fraction. | |
253 | * Bits 15:0 of the next word are the next most significant bits. | |
254 | * And so on for each other word. | |
255 | * | |
256 | * So we need: number of bits of exponent, number of bits of | |
257 | * mantissa. | |
258 | */ | |
259 | ||
260 | bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; | |
261 | littlenum_pointer = f->leader; | |
262 | littlenum_end = f->low; | |
263 | /* Seek (and forget) 1st significant bit */ | |
264 | for (exponent_skippage = 0; | |
265 | !next_bits (1); | |
266 | exponent_skippage++) | |
267 | { | |
268 | } | |
269 | exponent_1 = f->exponent + f->leader + 1 - f->low; | |
270 | /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */ | |
271 | exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; | |
272 | /* Radix 2. */ | |
273 | exponent_3 = exponent_2 - exponent_skippage; | |
274 | /* Forget leading zeros, forget 1st bit. */ | |
275 | exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); | |
276 | /* Offset exponent. */ | |
277 | ||
278 | if (exponent_4 & ~mask[exponent_bits]) | |
279 | { | |
280 | /* | |
281 | * Exponent overflow. Lose immediately. | |
282 | */ | |
283 | ||
284 | make_invalid_floating_point_number (words); | |
285 | ||
286 | /* | |
287 | * We leave return_value alone: admit we read the | |
288 | * number, but return a floating exception | |
289 | * because we can't encode the number. | |
290 | */ | |
291 | } | |
292 | else | |
293 | { | |
294 | lp = words; | |
295 | ||
296 | /* Word 1. Sign, exponent and perhaps high bits. */ | |
297 | /* Assume 2's complement integers. */ | |
298 | word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) | |
299 | | ((f->sign == '+') ? 0 : 0x8000) | |
300 | | next_bits (15 - exponent_bits); | |
301 | *lp++ = word1; | |
302 | ||
303 | /* The rest of the words are just mantissa bits. */ | |
304 | for (; lp < words + precision; lp++) | |
305 | { | |
306 | *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); | |
307 | } | |
308 | ||
309 | if (next_bits (1)) | |
310 | { | |
311 | /* | |
312 | * Since the NEXT bit is a 1, round UP the mantissa. | |
313 | * The cunning design of these hidden-1 floats permits | |
314 | * us to let the mantissa overflow into the exponent, and | |
315 | * it 'does the right thing'. However, we lose if the | |
316 | * highest-order bit of the lowest-order word flips. | |
317 | * Is that clear? | |
318 | */ | |
319 | ||
320 | unsigned long int carry; | |
321 | ||
322 | /* | |
323 | #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) | |
324 | Please allow at least 1 more bit in carry than is in a LITTLENUM. | |
325 | We need that extra bit to hold a carry during a LITTLENUM carry | |
326 | propagation. Another extra bit (kept 0) will assure us that we | |
327 | don't get a sticky sign bit after shifting right, and that | |
328 | permits us to propagate the carry without any masking of bits. | |
329 | #endif | |
330 | */ | |
331 | for (carry = 1, lp--; | |
332 | carry && (lp >= words); | |
333 | lp--) | |
334 | { | |
335 | carry = *lp + carry; | |
336 | *lp = carry; | |
337 | carry >>= LITTLENUM_NUMBER_OF_BITS; | |
338 | } | |
339 | ||
340 | if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) | |
341 | { | |
342 | make_invalid_floating_point_number (words); | |
343 | /* | |
344 | * We leave return_value alone: admit we read the | |
345 | * number, but return a floating exception | |
346 | * because we can't encode the number. | |
347 | */ | |
348 | } | |
349 | } /* if (we needed to round up) */ | |
350 | } /* if (exponent overflow) */ | |
351 | } /* if (0.0e0) */ | |
352 | } /* if (float_type was OK) */ | |
353 | return (return_value); | |
354 | } | |
355 | \f | |
356 | /* | |
357 | * md_atof() | |
358 | * | |
359 | * In: input_line_pointer -> the 1st character of a floating-point | |
360 | * number. | |
361 | * 1 letter denoting the type of statement that wants a | |
362 | * binary floating point number returned. | |
363 | * Address of where to build floating point literal. | |
364 | * Assumed to be 'big enough'. | |
365 | * Address of where to return size of literal (in chars). | |
366 | * | |
367 | * Out: Input_line_pointer -> of next char after floating number. | |
43029a8f | 368 | * Error message, or 0. |
88db8f81 KR |
369 | * Floating point literal. |
370 | * Number of chars we used for the literal. | |
371 | */ | |
372 | ||
373 | char * | |
374 | md_atof (what_statement_type, literalP, sizeP) | |
375 | char what_statement_type; | |
376 | char *literalP; | |
377 | int *sizeP; | |
378 | { | |
379 | LITTLENUM_TYPE words[MAX_PRECISION]; | |
380 | register char kind_of_float; | |
381 | register int number_of_chars; | |
382 | register LITTLENUM_TYPE *littlenum_pointer; | |
383 | ||
384 | switch (what_statement_type) | |
385 | { | |
386 | case 'f': /* .ffloat */ | |
387 | case 'd': /* .dfloat */ | |
388 | kind_of_float = what_statement_type; | |
389 | break; | |
390 | ||
391 | default: | |
392 | kind_of_float = 0; | |
393 | break; | |
394 | }; | |
395 | ||
396 | if (kind_of_float) | |
397 | { | |
398 | register LITTLENUM_TYPE *limit; | |
399 | ||
400 | input_line_pointer = atof_tahoe (input_line_pointer, | |
401 | kind_of_float, | |
402 | words); | |
403 | /* | |
404 | * The atof_tahoe() builds up 16-bit numbers. | |
405 | * Since the assembler may not be running on | |
406 | * a different-endian machine, be very careful about | |
407 | * converting words to chars. | |
408 | */ | |
409 | number_of_chars = (kind_of_float == 'f' ? F_PRECISION_CHARS : | |
410 | (kind_of_float == 'd' ? D_PRECISION_CHARS : 0)); | |
411 | know (number_of_chars <= MAX_PRECISION * sizeof (LITTLENUM_TYPE)); | |
412 | limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE)); | |
413 | for (littlenum_pointer = words; | |
414 | littlenum_pointer < limit; | |
415 | littlenum_pointer++) | |
416 | { | |
417 | md_number_to_chars (literalP, *littlenum_pointer, | |
418 | sizeof (LITTLENUM_TYPE)); | |
419 | literalP += sizeof (LITTLENUM_TYPE); | |
420 | }; | |
421 | } | |
422 | else | |
423 | { | |
424 | number_of_chars = 0; | |
425 | }; | |
426 | ||
427 | *sizeP = number_of_chars; | |
48401fcf | 428 | return kind_of_float ? 0 : _("Bad call to md_atof()"); |
43029a8f | 429 | } |
88db8f81 KR |
430 | |
431 | /* atof_tahoe.c */ |