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