(root)/
binutils-2.41/
gas/
config/
atof-vax.c
       1  /* atof_vax.c - turn a Flonum into a VAX floating point number
       2     Copyright (C) 1987-2023 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  
      33  int flonum_gen2vax (int, FLONUM_TYPE *, LITTLENUM_TYPE *);
      34  
      35  /* Number of chars in flonum type 'letter'.  */
      36  
      37  static unsigned int
      38  atof_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  
      72  static 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.  */
     111  static int bits_left_in_littlenum;
     112  static LITTLENUM_TYPE *littlenum_pointer;
     113  static LITTLENUM_TYPE *littlenum_end;
     114  
     115  static int
     116  next_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  
     140  static void
     141  make_invalid_floating_point_number (LITTLENUM_TYPE *words)
     142  {
     143    *words = 0x8000;		/* Floating Reserved Operand Code.  */
     144  }
     145  
     146  
     147  static int			/* 0 means letter is OK.  */
     148  what_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  
     189  static char *
     190  atof_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  
     240  int
     241  flonum_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  	  /* JF: Deal with new Nan, +Inf and -Inf codes.  */
     271  	  if (f->sign != '-' && f->sign != '+')
     272  	    {
     273  	      make_invalid_floating_point_number (words);
     274  	      return return_value;
     275  	    }
     276  
     277  	  /* All vaxen floating_point formats (so far) have:
     278  	     Bit 15 is sign bit.
     279  	     Bits 14:n are excess-whatever exponent.
     280  	     Bits n-1:0 (if any) are most significant bits of fraction.
     281  	     Bits 15:0 of the next word are the next most significant bits.
     282  	     And so on for each other word.
     283  
     284  	     All this to be compatible with a KF11?? (Which is still faster
     285  	     than lots of vaxen I can think of, but it also has higher
     286  	     maintenance costs ... sigh).
     287  
     288  	     So we need: number of bits of exponent, number of bits of
     289  	     mantissa.  */
     290  
     291  	  bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
     292  	  littlenum_pointer = f->leader;
     293  	  littlenum_end = f->low;
     294  	  /* Seek (and forget) 1st significant bit.  */
     295  	  for (exponent_skippage = 0;
     296  	       !next_bits (1);
     297  	       exponent_skippage++);
     298  
     299  	  exponent_1 = f->exponent + f->leader + 1 - f->low;
     300  	  /* Radix LITTLENUM_RADIX, point just higher than f->leader.  */
     301  	  exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
     302  	  /* Radix 2.  */
     303  	  exponent_3 = exponent_2 - exponent_skippage;
     304  	  /* Forget leading zeros, forget 1st bit.  */
     305  	  exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
     306  	  /* Offset exponent.  */
     307  
     308  	  if (exponent_4 & ~mask[exponent_bits])
     309  	    {
     310  	      /* Exponent overflow. Lose immediately.  */
     311  	      make_invalid_floating_point_number (words);
     312  
     313  	      /* We leave return_value alone: admit we read the
     314  	         number, but return a floating exception
     315  	         because we can't encode the number.  */
     316  	    }
     317  	  else
     318  	    {
     319  	      lp = words;
     320  
     321  	      /* Word 1. Sign, exponent and perhaps high bits.
     322  	         Assume 2's complement integers.  */
     323  	      word1 = (((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits))
     324  		       | ((f->sign == '+') ? 0 : 0x8000)
     325  		       | next_bits (15 - exponent_bits));
     326  	      *lp++ = word1;
     327  
     328  	      /* The rest of the words are just mantissa bits.  */
     329  	      for (; lp < words + precision; lp++)
     330  		*lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
     331  
     332  	      if (next_bits (1))
     333  		{
     334  		  /* Since the NEXT bit is a 1, round UP the mantissa.
     335  		     The cunning design of these hidden-1 floats permits
     336  		     us to let the mantissa overflow into the exponent, and
     337  		     it 'does the right thing'. However, we lose if the
     338  		     highest-order bit of the lowest-order word flips.
     339  		     Is that clear?  */
     340  		  unsigned long carry;
     341  
     342  		  /*
     343  		    #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
     344  		    Please allow at least 1 more bit in carry than is in a LITTLENUM.
     345  		    We need that extra bit to hold a carry during a LITTLENUM carry
     346  		    propagation. Another extra bit (kept 0) will assure us that we
     347  		    don't get a sticky sign bit after shifting right, and that
     348  		    permits us to propagate the carry without any masking of bits.
     349  		    #endif   */
     350  		  for (carry = 1, lp--;
     351  		       carry && (lp >= words);
     352  		       lp--)
     353  		    {
     354  		      carry = *lp + carry;
     355  		      *lp = carry;
     356  		      carry >>= LITTLENUM_NUMBER_OF_BITS;
     357  		    }
     358  
     359  		  if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)))
     360  		    {
     361  		      make_invalid_floating_point_number (words);
     362  		      /* We leave return_value alone: admit we read the
     363  		         number, but return a floating exception
     364  		         because we can't encode the number.  */
     365  		    }
     366  		}
     367  	    }
     368  	}
     369      }
     370    return return_value;
     371  }
     372  
     373  /* JF this used to be in vax.c but this looks like a better place for it.  */
     374  
     375  /* In:	input_line_pointer->the 1st character of a floating-point
     376    		number.
     377    	1 letter denoting the type of statement that wants a
     378    		binary floating point number returned.
     379    	Address of where to build floating point literal.
     380    		Assumed to be 'big enough'.
     381    	Address of where to return size of literal (in chars).
     382  
     383     Out:	Input_line_pointer->of next char after floating number.
     384    	Error message, or 0.
     385    	Floating point literal.
     386    	Number of chars we used for the literal.  */
     387  
     388  #define MAXIMUM_NUMBER_OF_LITTLENUMS  8 	/* For .hfloats.  */
     389  
     390  const char *
     391  vax_md_atof (int what_statement_type,
     392  	     char *literalP,
     393  	     int *sizeP)
     394  {
     395    LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS];
     396    char kind_of_float;
     397    unsigned int number_of_chars;
     398    LITTLENUM_TYPE *littlenumP;
     399  
     400    switch (what_statement_type)
     401      {
     402      case 'F':
     403      case 'f':
     404        kind_of_float = 'f';
     405        break;
     406  
     407      case 'D':
     408      case 'd':
     409        kind_of_float = 'd';
     410        break;
     411  
     412      case 'g':
     413        kind_of_float = 'g';
     414        break;
     415  
     416      case 'h':
     417        kind_of_float = 'h';
     418        break;
     419  
     420      default:
     421        kind_of_float = 0;
     422        break;
     423      };
     424  
     425    if (kind_of_float)
     426      {
     427        LITTLENUM_TYPE *limit;
     428  
     429        input_line_pointer = atof_vax (input_line_pointer,
     430  				     kind_of_float,
     431  				     words);
     432        /* The atof_vax() builds up 16-bit numbers.
     433           Since the assembler may not be running on
     434           a little-endian machine, be very careful about
     435           converting words to chars.  */
     436        number_of_chars = atof_vax_sizeof (kind_of_float);
     437        know (number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof (LITTLENUM_TYPE));
     438        limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE));
     439        for (littlenumP = words; littlenumP < limit; littlenumP++)
     440  	{
     441  	  md_number_to_chars (literalP, *littlenumP, sizeof (LITTLENUM_TYPE));
     442  	  literalP += sizeof (LITTLENUM_TYPE);
     443  	};
     444      }
     445    else
     446      number_of_chars = 0;
     447  
     448    *sizeP = number_of_chars;
     449    return kind_of_float ? NULL : _("Unrecognized or unsupported floating point constant");
     450  }