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