OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [arm/] [fp16.c] - Rev 758

Go to most recent revision | Compare with Previous | Blame | View Log

/* Half-float conversion routines.
 
   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
   Contributed by CodeSourcery.
 
   This file is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3, or (at your option) any
   later version.
 
   This file is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.
 
   Under Section 7 of GPL version 3, you are granted additional
   permissions described in the GCC Runtime Library Exception, version
   3.1, as published by the Free Software Foundation.
 
   You should have received a copy of the GNU General Public License and
   a copy of the GCC Runtime Library Exception along with this program;
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   <http://www.gnu.org/licenses/>.  */
 
static inline unsigned short
__gnu_f2h_internal(unsigned int a, int ieee)
{
  unsigned short sign = (a >> 16) & 0x8000;
  int aexp = (a >> 23) & 0xff;
  unsigned int mantissa = a & 0x007fffff;
  unsigned int mask;
  unsigned int increment;
 
  if (aexp == 0xff)
    {
      if (!ieee)
	return sign;
      return sign | 0x7e00 | (mantissa >> 13);
    }
 
  if (aexp == 0 && mantissa == 0)
    return sign;
 
  aexp -= 127;
 
  /* Decimal point between bits 22 and 23.  */
  mantissa |= 0x00800000;
  if (aexp < -14)
    {
      mask = 0x007fffff;
      if (aexp < -25)
	aexp = -26;
      else if (aexp != -25)
	mask >>= 24 + aexp;
    }
  else
    mask = 0x00001fff;
 
  /* Round.  */
  if (mantissa & mask)
    {
      increment = (mask + 1) >> 1;
      if ((mantissa & mask) == increment)
	increment = mantissa & (increment << 1);
      mantissa += increment;
      if (mantissa >= 0x01000000)
       	{
	  mantissa >>= 1;
	  aexp++;
	}
    }
 
  if (ieee)
    {
      if (aexp > 15)
	return sign | 0x7c00;
    }
  else
    {
      if (aexp > 16)
	return sign | 0x7fff;
    }
 
  if (aexp < -24)
    return sign;
 
  if (aexp < -14)
    {
      mantissa >>= -14 - aexp;
      aexp = -14;
    }
 
  /* We leave the leading 1 in the mantissa, and subtract one
     from the exponent bias to compensate.  */
  return sign | (((aexp + 14) << 10) + (mantissa >> 13));
}
 
unsigned int
__gnu_h2f_internal(unsigned short a, int ieee)
{
  unsigned int sign = (unsigned int)(a & 0x8000) << 16;
  int aexp = (a >> 10) & 0x1f;
  unsigned int mantissa = a & 0x3ff;
 
  if (aexp == 0x1f && ieee)
    return sign | 0x7f800000 | (mantissa << 13);
 
  if (aexp == 0)
    {
      int shift;
 
      if (mantissa == 0)
	return sign;
 
      shift = __builtin_clz(mantissa) - 21;
      mantissa <<= shift;
      aexp = -shift;
    }
 
  return sign | (((aexp + 0x70) << 23) + (mantissa << 13));
}
 
unsigned short
__gnu_f2h_ieee(unsigned int a)
{
  return __gnu_f2h_internal(a, 1);
}
 
unsigned int
__gnu_h2f_ieee(unsigned short a)
{
  return __gnu_h2f_internal(a, 1);
}
 
unsigned short
__gnu_f2h_alternative(unsigned int x)
{
  return __gnu_f2h_internal(x, 0);
}
 
unsigned int
__gnu_h2f_alternative(unsigned short a)
{
  return __gnu_h2f_internal(a, 0);
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.