134351Sjb/* atof_vax.c - turn a Flonum into a VAX floating point number
2218822Sdim   Copyright 1987, 1992, 1993, 1995, 1997, 1999, 2000, 2005, 2007
369180Sobrien   Free Software Foundation, Inc.
434351Sjb
534351Sjb   This file is part of GAS, the GNU Assembler.
634351Sjb
734351Sjb   GAS is free software; you can redistribute it and/or modify
834351Sjb   it under the terms of the GNU General Public License as published by
934351Sjb   the Free Software Foundation; either version 2, or (at your option)
1034351Sjb   any later version.
1134351Sjb
1234351Sjb   GAS is distributed in the hope that it will be useful,
1334351Sjb   but WITHOUT ANY WARRANTY; without even the implied warranty of
1434351Sjb   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1534351Sjb   GNU General Public License for more details.
1634351Sjb
1734351Sjb   You should have received a copy of the GNU General Public License
1834351Sjb   along with GAS; see the file COPYING.  If not, write to the Free
19218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2134351Sjb
2234351Sjb#include "as.h"
2334351Sjb
2494536Sobrien/* Precision in LittleNums.  */
25218822Sdim#define MAX_PRECISION	8
26218822Sdim#define H_PRECISION	8
27218822Sdim#define G_PRECISION	4
28218822Sdim#define D_PRECISION	4
29218822Sdim#define F_PRECISION	2
3034351Sjb
3194536Sobrien/* Length in LittleNums of guard bits.  */
32218822Sdim#define GUARD		2
3334351Sjb
34218822Sdimint flonum_gen2vax (int, FLONUM_TYPE *, LITTLENUM_TYPE *);
3534351Sjb
3694536Sobrien/* Number of chars in flonum type 'letter'.  */
37218822Sdim
38218822Sdimstatic unsigned int
39218822Sdimatof_vax_sizeof (int letter)
4034351Sjb{
4134351Sjb  int return_value;
4234351Sjb
43218822Sdim  /* Permitting uppercase letters is probably a bad idea.
44218822Sdim     Please use only lower-cased letters in case the upper-cased
45218822Sdim     ones become unsupported!  */
4634351Sjb  switch (letter)
4734351Sjb    {
4834351Sjb    case 'f':
4934351Sjb    case 'F':
5034351Sjb      return_value = 4;
5134351Sjb      break;
5234351Sjb
5334351Sjb    case 'd':
5434351Sjb    case 'D':
5534351Sjb    case 'g':
5634351Sjb    case 'G':
5734351Sjb      return_value = 8;
5834351Sjb      break;
5934351Sjb
6034351Sjb    case 'h':
6134351Sjb    case 'H':
6234351Sjb      return_value = 16;
6334351Sjb      break;
6434351Sjb
6534351Sjb    default:
6634351Sjb      return_value = 0;
6734351Sjb      break;
6834351Sjb    }
6934351Sjb
70218822Sdim  return return_value;
71218822Sdim}
72218822Sdim
7334351Sjbstatic const long mask[] =
7434351Sjb{
7534351Sjb  0x00000000,
7634351Sjb  0x00000001,
7734351Sjb  0x00000003,
7834351Sjb  0x00000007,
7934351Sjb  0x0000000f,
8034351Sjb  0x0000001f,
8134351Sjb  0x0000003f,
8234351Sjb  0x0000007f,
8334351Sjb  0x000000ff,
8434351Sjb  0x000001ff,
8534351Sjb  0x000003ff,
8634351Sjb  0x000007ff,
8734351Sjb  0x00000fff,
8834351Sjb  0x00001fff,
8934351Sjb  0x00003fff,
9034351Sjb  0x00007fff,
9134351Sjb  0x0000ffff,
9234351Sjb  0x0001ffff,
9334351Sjb  0x0003ffff,
9434351Sjb  0x0007ffff,
9534351Sjb  0x000fffff,
9634351Sjb  0x001fffff,
9734351Sjb  0x003fffff,
9834351Sjb  0x007fffff,
9934351Sjb  0x00ffffff,
10034351Sjb  0x01ffffff,
10134351Sjb  0x03ffffff,
10234351Sjb  0x07ffffff,
10334351Sjb  0x0fffffff,
10434351Sjb  0x1fffffff,
10534351Sjb  0x3fffffff,
10634351Sjb  0x7fffffff,
10734351Sjb  0xffffffff
10834351Sjb};
10934351Sjb
11034351Sjb
111218822Sdim/* Shared between flonum_gen2vax and next_bits.  */
11234351Sjbstatic int bits_left_in_littlenum;
11334351Sjbstatic LITTLENUM_TYPE *littlenum_pointer;
11434351Sjbstatic LITTLENUM_TYPE *littlenum_end;
11534351Sjb
11634351Sjbstatic int
117218822Sdimnext_bits (int number_of_bits)
11834351Sjb{
11934351Sjb  int return_value;
12034351Sjb
12134351Sjb  if (littlenum_pointer < littlenum_end)
12234351Sjb    return 0;
12334351Sjb  if (number_of_bits >= bits_left_in_littlenum)
12434351Sjb    {
12534351Sjb      return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
12634351Sjb      number_of_bits -= bits_left_in_littlenum;
12734351Sjb      return_value <<= number_of_bits;
12834351Sjb      bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
12934351Sjb      littlenum_pointer--;
13034351Sjb      if (littlenum_pointer >= littlenum_end)
13134351Sjb	return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & mask[number_of_bits];
13234351Sjb    }
13334351Sjb  else
13434351Sjb    {
13534351Sjb      bits_left_in_littlenum -= number_of_bits;
13634351Sjb      return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum);
13734351Sjb    }
138218822Sdim  return return_value;
13934351Sjb}
14034351Sjb
14134351Sjbstatic void
142218822Sdimmake_invalid_floating_point_number (LITTLENUM_TYPE *words)
14334351Sjb{
144218822Sdim  *words = 0x8000;		/* Floating Reserved Operand Code.  */
14534351Sjb}
146218822Sdim
14734351Sjb
14894536Sobrienstatic int			/* 0 means letter is OK.  */
149218822Sdimwhat_kind_of_float (int letter,			/* In: lowercase please. What kind of float?  */
150218822Sdim		    int *precisionP,		/* Number of 16-bit words in the float.  */
151218822Sdim		    long *exponent_bitsP)	/* Number of exponent bits.  */
15234351Sjb{
153218822Sdim  int retval;
15434351Sjb
15534351Sjb  retval = 0;
15634351Sjb  switch (letter)
15734351Sjb    {
15834351Sjb    case 'f':
15934351Sjb      *precisionP = F_PRECISION;
16034351Sjb      *exponent_bitsP = 8;
16134351Sjb      break;
16234351Sjb
16334351Sjb    case 'd':
16434351Sjb      *precisionP = D_PRECISION;
16534351Sjb      *exponent_bitsP = 8;
16634351Sjb      break;
16734351Sjb
16834351Sjb    case 'g':
16934351Sjb      *precisionP = G_PRECISION;
17034351Sjb      *exponent_bitsP = 11;
17134351Sjb      break;
17234351Sjb
17334351Sjb    case 'h':
17434351Sjb      *precisionP = H_PRECISION;
17534351Sjb      *exponent_bitsP = 15;
17634351Sjb      break;
17734351Sjb
17834351Sjb    default:
17934351Sjb      retval = 69;
18034351Sjb      break;
18134351Sjb    }
182218822Sdim  return retval;
18334351Sjb}
18434351Sjb
185218822Sdim/* Warning: this returns 16-bit LITTLENUMs, because that is
186218822Sdim   what the VAX thinks in. It is up to the caller to figure
187218822Sdim   out any alignment problems and to conspire for the bytes/word
188218822Sdim   to be emitted in the right order. Bigendians beware!  */
18934351Sjb
190218822Sdimstatic char *
191218822Sdimatof_vax (char *str,			/* Text to convert to binary.  */
192218822Sdim	  int what_kind,		/* 'd', 'f', 'g', 'h'  */
193218822Sdim	  LITTLENUM_TYPE *words)	/* Build the binary here.  */
19434351Sjb{
19534351Sjb  FLONUM_TYPE f;
19634351Sjb  LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
197218822Sdim  /* Extra bits for zeroed low-order bits.
198218822Sdim     The 1st MAX_PRECISION are zeroed,
199218822Sdim     the last contain flonum bits.  */
20034351Sjb  char *return_value;
20194536Sobrien  int precision;		/* Number of 16-bit words in the format.  */
20234351Sjb  long exponent_bits;
20334351Sjb
20434351Sjb  return_value = str;
20534351Sjb  f.low = bits + MAX_PRECISION;
20634351Sjb  f.high = NULL;
20734351Sjb  f.leader = NULL;
20834351Sjb  f.exponent = 0;
20934351Sjb  f.sign = '\0';
21034351Sjb
21134351Sjb  if (what_kind_of_float (what_kind, &precision, &exponent_bits))
21234351Sjb    {
213218822Sdim      return_value = NULL;
21434351Sjb      make_invalid_floating_point_number (words);
21534351Sjb    }
21634351Sjb
21734351Sjb  if (return_value)
21834351Sjb    {
21934351Sjb      memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
22034351Sjb
221218822Sdim      /* Use more LittleNums than seems
222218822Sdim         necessary: the highest flonum may have
223218822Sdim         15 leading 0 bits, so could be useless.  */
22434351Sjb      f.high = f.low + precision - 1 + GUARD;
22534351Sjb
22634351Sjb      if (atof_generic (&return_value, ".", "eE", &f))
22734351Sjb	{
22834351Sjb	  make_invalid_floating_point_number (words);
229218822Sdim	  return_value = NULL;
23034351Sjb	}
231218822Sdim      else if (flonum_gen2vax (what_kind, &f, words))
232218822Sdim	return_value = NULL;
23334351Sjb    }
234218822Sdim
235218822Sdim  return return_value;
236218822Sdim}
23734351Sjb
238218822Sdim/* In: a flonum, a vax floating point format.
239218822Sdim   Out: a vax floating-point bit pattern.  */
24034351Sjb
241218822Sdimint
242218822Sdimflonum_gen2vax (int format_letter,	/* One of 'd' 'f' 'g' 'h'.  */
243218822Sdim		FLONUM_TYPE *f,
244218822Sdim		LITTLENUM_TYPE *words)	/* Deliver answer here.  */
24534351Sjb{
24634351Sjb  LITTLENUM_TYPE *lp;
24734351Sjb  int precision;
24834351Sjb  long exponent_bits;
24994536Sobrien  int return_value;		/* 0 == OK.  */
25034351Sjb
25134351Sjb  return_value = what_kind_of_float (format_letter, &precision, &exponent_bits);
25234351Sjb
25334351Sjb  if (return_value != 0)
254218822Sdim    make_invalid_floating_point_number (words);
255218822Sdim
25634351Sjb  else
25734351Sjb    {
25834351Sjb      if (f->low > f->leader)
259218822Sdim	/* 0.0e0 seen.  */
260218822Sdim	memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision);
261218822Sdim
26234351Sjb      else
26334351Sjb	{
26434351Sjb	  long exponent_1;
26534351Sjb	  long exponent_2;
26634351Sjb	  long exponent_3;
26734351Sjb	  long exponent_4;
26834351Sjb	  int exponent_skippage;
26934351Sjb	  LITTLENUM_TYPE word1;
27034351Sjb
271218822Sdim	  /* JF: Deal with new Nan, +Inf and -Inf codes.  */
27234351Sjb	  if (f->sign != '-' && f->sign != '+')
27334351Sjb	    {
27434351Sjb	      make_invalid_floating_point_number (words);
27534351Sjb	      return return_value;
27634351Sjb	    }
27734351Sjb
278218822Sdim	  /* All vaxen floating_point formats (so far) have:
279218822Sdim	     Bit 15 is sign bit.
280218822Sdim	     Bits 14:n are excess-whatever exponent.
281218822Sdim	     Bits n-1:0 (if any) are most significant bits of fraction.
282218822Sdim	     Bits 15:0 of the next word are the next most significant bits.
283218822Sdim	     And so on for each other word.
28434351Sjb
285218822Sdim	     All this to be compatible with a KF11?? (Which is still faster
286218822Sdim	     than lots of vaxen I can think of, but it also has higher
287218822Sdim	     maintenance costs ... sigh).
288218822Sdim
289218822Sdim	     So we need: number of bits of exponent, number of bits of
290218822Sdim	     mantissa.  */
291218822Sdim
29234351Sjb	  bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
29334351Sjb	  littlenum_pointer = f->leader;
29434351Sjb	  littlenum_end = f->low;
295218822Sdim	  /* Seek (and forget) 1st significant bit.  */
29634351Sjb	  for (exponent_skippage = 0;
29734351Sjb	       !next_bits (1);
29834351Sjb	       exponent_skippage++);;
29934351Sjb
30034351Sjb	  exponent_1 = f->exponent + f->leader + 1 - f->low;
30194536Sobrien	  /* Radix LITTLENUM_RADIX, point just higher than f->leader.  */
30234351Sjb	  exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
30394536Sobrien	  /* Radix 2.  */
30434351Sjb	  exponent_3 = exponent_2 - exponent_skippage;
30594536Sobrien	  /* Forget leading zeros, forget 1st bit.  */
30634351Sjb	  exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
30794536Sobrien	  /* Offset exponent.  */
30834351Sjb
30934351Sjb	  if (exponent_4 & ~mask[exponent_bits])
31034351Sjb	    {
311218822Sdim	      /* Exponent overflow. Lose immediately.  */
31234351Sjb	      make_invalid_floating_point_number (words);
31334351Sjb
314218822Sdim	      /* We leave return_value alone: admit we read the
315218822Sdim	         number, but return a floating exception
316218822Sdim	         because we can't encode the number.  */
31734351Sjb	    }
31834351Sjb	  else
31934351Sjb	    {
32034351Sjb	      lp = words;
32134351Sjb
322218822Sdim	      /* Word 1. Sign, exponent and perhaps high bits.
323218822Sdim	         Assume 2's complement integers.  */
32434351Sjb	      word1 = (((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits))
32534351Sjb		       | ((f->sign == '+') ? 0 : 0x8000)
32634351Sjb		       | next_bits (15 - exponent_bits));
32734351Sjb	      *lp++ = word1;
32834351Sjb
32994536Sobrien	      /* The rest of the words are just mantissa bits.  */
33034351Sjb	      for (; lp < words + precision; lp++)
331218822Sdim		*lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
33234351Sjb
33334351Sjb	      if (next_bits (1))
33434351Sjb		{
335218822Sdim		  /* Since the NEXT bit is a 1, round UP the mantissa.
336218822Sdim		     The cunning design of these hidden-1 floats permits
337218822Sdim		     us to let the mantissa overflow into the exponent, and
338218822Sdim		     it 'does the right thing'. However, we lose if the
339218822Sdim		     highest-order bit of the lowest-order word flips.
340218822Sdim		     Is that clear?  */
34134351Sjb		  unsigned long carry;
34234351Sjb
34334351Sjb		  /*
344218822Sdim		    #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
345218822Sdim		    Please allow at least 1 more bit in carry than is in a LITTLENUM.
346218822Sdim		    We need that extra bit to hold a carry during a LITTLENUM carry
347218822Sdim		    propagation. Another extra bit (kept 0) will assure us that we
348218822Sdim		    don't get a sticky sign bit after shifting right, and that
349218822Sdim		    permits us to propagate the carry without any masking of bits.
350218822Sdim		    #endif   */
35134351Sjb		  for (carry = 1, lp--;
35234351Sjb		       carry && (lp >= words);
35334351Sjb		       lp--)
35434351Sjb		    {
35534351Sjb		      carry = *lp + carry;
35634351Sjb		      *lp = carry;
35734351Sjb		      carry >>= LITTLENUM_NUMBER_OF_BITS;
35834351Sjb		    }
35934351Sjb
36034351Sjb		  if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)))
36134351Sjb		    {
36234351Sjb		      make_invalid_floating_point_number (words);
363218822Sdim		      /* We leave return_value alone: admit we read the
364218822Sdim		         number, but return a floating exception
365218822Sdim		         because we can't encode the number.  */
36634351Sjb		    }
367218822Sdim		}
368218822Sdim	    }
369218822Sdim	}
370218822Sdim    }
371218822Sdim  return return_value;
372218822Sdim}
37334351Sjb
374218822Sdim/* JF this used to be in vax.c but this looks like a better place for it.  */
37534351Sjb
376218822Sdim/* In:	input_line_pointer->the 1st character of a floating-point
377218822Sdim  		number.
378218822Sdim  	1 letter denoting the type of statement that wants a
379218822Sdim  		binary floating point number returned.
380218822Sdim  	Address of where to build floating point literal.
381218822Sdim  		Assumed to be 'big enough'.
382218822Sdim  	Address of where to return size of literal (in chars).
383218822Sdim
384218822Sdim   Out:	Input_line_pointer->of next char after floating number.
385218822Sdim  	Error message, or 0.
386218822Sdim  	Floating point literal.
387218822Sdim  	Number of chars we used for the literal.  */
38834351Sjb
389218822Sdim#define MAXIMUM_NUMBER_OF_LITTLENUMS  8 	/* For .hfloats.  */
39034351Sjb
39134351Sjbchar *
392218822Sdimmd_atof (int what_statement_type,
393218822Sdim	 char *literalP,
394218822Sdim	 int *sizeP)
39534351Sjb{
39634351Sjb  LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS];
397218822Sdim  char kind_of_float;
398218822Sdim  unsigned int number_of_chars;
399218822Sdim  LITTLENUM_TYPE *littlenumP;
40034351Sjb
40134351Sjb  switch (what_statement_type)
40234351Sjb    {
403218822Sdim    case 'F':
404218822Sdim    case 'f':
40534351Sjb      kind_of_float = 'f';
40634351Sjb      break;
40734351Sjb
408218822Sdim    case 'D':
409218822Sdim    case 'd':
41034351Sjb      kind_of_float = 'd';
41134351Sjb      break;
41234351Sjb
413218822Sdim    case 'g':
41434351Sjb      kind_of_float = 'g';
41534351Sjb      break;
41634351Sjb
417218822Sdim    case 'h':
41834351Sjb      kind_of_float = 'h';
41934351Sjb      break;
42034351Sjb
42134351Sjb    default:
42234351Sjb      kind_of_float = 0;
42334351Sjb      break;
42434351Sjb    };
42534351Sjb
42634351Sjb  if (kind_of_float)
42734351Sjb    {
428218822Sdim      LITTLENUM_TYPE *limit;
42934351Sjb
43034351Sjb      input_line_pointer = atof_vax (input_line_pointer,
43134351Sjb				     kind_of_float,
43234351Sjb				     words);
433218822Sdim      /* The atof_vax() builds up 16-bit numbers.
434218822Sdim         Since the assembler may not be running on
435218822Sdim         a little-endian machine, be very careful about
436218822Sdim         converting words to chars.  */
43734351Sjb      number_of_chars = atof_vax_sizeof (kind_of_float);
43834351Sjb      know (number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof (LITTLENUM_TYPE));
43934351Sjb      limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE));
44034351Sjb      for (littlenumP = words; littlenumP < limit; littlenumP++)
44134351Sjb	{
44234351Sjb	  md_number_to_chars (literalP, *littlenumP, sizeof (LITTLENUM_TYPE));
44334351Sjb	  literalP += sizeof (LITTLENUM_TYPE);
44434351Sjb	};
44534351Sjb    }
44634351Sjb  else
447218822Sdim    number_of_chars = 0;
44834351Sjb
44934351Sjb  *sizeP = number_of_chars;
45069180Sobrien  return kind_of_float ? NULL : _("Bad call to md_atof()");
45134351Sjb}
452