⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 real.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,   and support for XFmode IEEE extended real floating point arithmetic.   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.   Contributed by Stephen L. Moshier (moshier@world.std.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include <stdio.h>#include <errno.h>#include "config.h"#include "tree.h"#ifndef errnoextern int errno;#endif/* To enable support of XFmode extended real floating point, defineLONG_DOUBLE_TYPE_SIZE 96 in the tm.h file (m68k.h or i386.h).To support cross compilation between IEEE, VAX and IBM floatingpoint formats, define REAL_ARITHMETIC in the tm.h file.In either case the machine files (tm.h) must not contain any codethat tries to use host floating point arithmetic to convertREAL_VALUE_TYPEs from `double' to `float', pass them to fprintf,etc.  In cross-compile situations a REAL_VALUE_TYPE may notbe intelligible to the host computer's native arithmetic.The emulator defaults to the host's floating point format so thatits decimal conversion functions can be used if desired (seereal.h).The first part of this file interfaces gcc to a floating pointarithmetic suite that was not written with gcc in mind.  Avoidchanging the low-level arithmetic routines unless you have suitabletest programs available.  A special version of the PARANOIA floatingpoint arithmetic tester, modified for this purpose, can be found onusc.edu: /pub/C-numanal/ieeetest.zoo.  Other tests, and libraries ofXFmode and TFmode transcendental functions, can be obtained by ftp fromnetlib.att.com: netlib/cephes.   *//* Type of computer arithmetic.   Only one of DEC, IBM, IEEE, or UNK should get defined.   `IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically   to big-endian IEEE floating-point data structure.  This definition   should work in SFmode `float' type and DFmode `double' type on   virtually all big-endian IEEE machines.  If LONG_DOUBLE_TYPE_SIZE   has been defined to be 96, then IEEE also invokes the particular   XFmode (`long double' type) data structure used by the Motorola   680x0 series processors.   `IEEE', when REAL_WORDS_BIG_ENDIAN is zero, refers generally to   little-endian IEEE machines. In this case, if LONG_DOUBLE_TYPE_SIZE   has been defined to be 96, then IEEE also invokes the particular   XFmode `long double' data structure used by the Intel 80x86 series   processors.   `DEC' refers specifically to the Digital Equipment Corp PDP-11   and VAX floating point data structure.  This model currently   supports no type wider than DFmode.   `IBM' refers specifically to the IBM System/370 and compatible   floating point data structure.  This model currently supports   no type wider than DFmode.  The IBM conversions were contributed by   frank@atom.ansto.gov.au (Frank Crawford).   If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it)   then `long double' and `double' are both implemented, but they   both mean DFmode.  In this case, the software floating-point   support available here is activated by writing      #define REAL_ARITHMETIC   in tm.h.    The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support   and may deactivate XFmode since `long double' is used to refer   to both modes.   The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,   contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,   separate the floating point unit's endian-ness from that of   the integer addressing.  This permits one to define a big-endian   FPU on a little-endian machine (e.g., ARM).  An extension to   BYTES_BIG_ENDIAN may be required for some machines in the future.   These optional macros may be defined in tm.h.  In real.h, they   default to WORDS_BIG_ENDIAN, etc., so there is no need to define   them for any normal host or target machine on which the floats   and the integers have the same endian-ness.   *//* The following converts gcc macros into the ones used by this file.  *//* REAL_ARITHMETIC defined means that macros in real.h are   defined to call emulator functions.  */#ifdef REAL_ARITHMETIC#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT/* PDP-11, Pro350, VAX: */#define DEC 1#else /* it's not VAX */#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT/* IBM System/370 style */#define IBM 1#else /* it's also not an IBM */#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT#define IEEE#else /* it's not IEEE either *//* UNKnown arithmetic.  We don't support this and can't go on. */unknown arithmetic type#define UNK 1#endif /* not IEEE */#endif /* not IBM */#endif /* not VAX */#define REAL_WORDS_BIG_ENDIAN FLOAT_WORDS_BIG_ENDIAN#else/* REAL_ARITHMETIC not defined means that the *host's* data   structure will be used.  It may differ by endian-ness from the   target machine's structure and will get its ends swapped   accordingly (but not here).  Probably only the decimal <-> binary   functions in this file will actually be used in this case.  */#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT#define DEC 1#else /* it's not VAX */#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT/* IBM System/370 style */#define IBM 1#else /* it's also not an IBM */#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT#define IEEE#else /* it's not IEEE either */unknown arithmetic type#define UNK 1#endif /* not IEEE */#endif /* not IBM */#endif /* not VAX */#define REAL_WORDS_BIG_ENDIAN HOST_FLOAT_WORDS_BIG_ENDIAN#endif /* REAL_ARITHMETIC not defined *//* Define INFINITY for support of infinity.   Define NANS for support of Not-a-Number's (NaN's).  */#if !defined(DEC) && !defined(IBM)#define INFINITY#define NANS#endif/* Support of NaNs requires support of infinity. */#ifdef NANS#ifndef INFINITY#define INFINITY#endif#endif/* Find a host integer type that is at least 16 bits wide,   and another type at least twice whatever that size is. */#if HOST_BITS_PER_CHAR >= 16#define EMUSHORT char#define EMUSHORT_SIZE HOST_BITS_PER_CHAR#define EMULONG_SIZE (2 * HOST_BITS_PER_CHAR)#else#if HOST_BITS_PER_SHORT >= 16#define EMUSHORT short#define EMUSHORT_SIZE HOST_BITS_PER_SHORT#define EMULONG_SIZE (2 * HOST_BITS_PER_SHORT)#else#if HOST_BITS_PER_INT >= 16#define EMUSHORT int#define EMUSHORT_SIZE HOST_BITS_PER_INT#define EMULONG_SIZE (2 * HOST_BITS_PER_INT)#else#if HOST_BITS_PER_LONG >= 16#define EMUSHORT long#define EMUSHORT_SIZE HOST_BITS_PER_LONG#define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)#else/*  You will have to modify this program to have a smaller unit size. */#define EMU_NON_COMPILE#endif#endif#endif#endif#if HOST_BITS_PER_SHORT >= EMULONG_SIZE#define EMULONG short#else#if HOST_BITS_PER_INT >= EMULONG_SIZE#define EMULONG int#else#if HOST_BITS_PER_LONG >= EMULONG_SIZE#define EMULONG long#else#if HOST_BITS_PER_LONG_LONG >= EMULONG_SIZE#define EMULONG long long int#else/*  You will have to modify this program to have a smaller unit size. */#define EMU_NON_COMPILE#endif#endif#endif#endif/* The host interface doesn't work if no 16-bit size exists. */#if EMUSHORT_SIZE != 16#define EMU_NON_COMPILE#endif/* OK to continue compilation. */#ifndef EMU_NON_COMPILE/* Construct macros to translate between REAL_VALUE_TYPE and e type.   In GET_REAL and PUT_REAL, r and e are pointers.   A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations   in memory, with no holes.  */#if LONG_DOUBLE_TYPE_SIZE == 96/* Number of 16 bit words in external e type format */#define NE 6#define MAXDECEXP 4932#define MINDECEXP -4956#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)#else /* no XFmode */#if LONG_DOUBLE_TYPE_SIZE == 128#define NE 10#define MAXDECEXP 4932#define MINDECEXP -4977#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)#else#define NE 6#define MAXDECEXP 4932#define MINDECEXP -4956#ifdef REAL_ARITHMETIC/* Emulator uses target format internally   but host stores it in host endian-ness. */#define GET_REAL(r,e)						\do {								\     if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN)	\       e53toe ((unsigned EMUSHORT*) (r), (e));			\     else							\       {							\	 unsigned EMUSHORT w[4];				\	 w[3] = ((EMUSHORT *) r)[0];				\	 w[2] = ((EMUSHORT *) r)[1];				\	 w[1] = ((EMUSHORT *) r)[2];				\	 w[0] = ((EMUSHORT *) r)[3];				\	 e53toe (w, (e));					\       }							\   } while (0)#define PUT_REAL(e,r)						\do {								\     if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN)	\       etoe53 ((e), (unsigned EMUSHORT *) (r));			\     else							\       {							\	 unsigned EMUSHORT w[4];				\	 etoe53 ((e), w);					\	 *((EMUSHORT *) r) = w[3];				\	 *((EMUSHORT *) r + 1) = w[2];				\	 *((EMUSHORT *) r + 2) = w[1];				\	 *((EMUSHORT *) r + 3) = w[0];				\       }							\   } while (0)#else /* not REAL_ARITHMETIC *//* emulator uses host format */#define GET_REAL(r,e) e53toe ((unsigned EMUSHORT *) (r), (e))#define PUT_REAL(e,r) etoe53 ((e), (unsigned EMUSHORT *) (r))#endif /* not REAL_ARITHMETIC */#endif /* not TFmode */#endif /* no XFmode *//* Number of 16 bit words in internal format */#define NI (NE+3)/* Array offset to exponent */#define E 1/* Array offset to high guard word */#define M 2/* Number of bits of precision */#define NBITS ((NI-4)*16)/* Maximum number of decimal digits in ASCII conversion * = NBITS*log10(2) */#define NDEC (NBITS*8/27)/* The exponent of 1.0 */#define EXONE (0x3fff)extern int extra_warnings;extern unsigned EMUSHORT ezero[], ehalf[], eone[], etwo[];extern unsigned EMUSHORT elog2[], esqrt2[];static void endian	PROTO((unsigned EMUSHORT *, long *,			       enum machine_mode));static void eclear	PROTO((unsigned EMUSHORT *));static void emov	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void eabs	PROTO((unsigned EMUSHORT *));static void eneg	PROTO((unsigned EMUSHORT *));static int eisneg	PROTO((unsigned EMUSHORT *));static int eisinf	PROTO((unsigned EMUSHORT *));static int eisnan	PROTO((unsigned EMUSHORT *));static void einfin	PROTO((unsigned EMUSHORT *));static void enan	PROTO((unsigned EMUSHORT *, int));static void emovi	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void emovo	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void ecleaz	PROTO((unsigned EMUSHORT *));static void ecleazs	PROTO((unsigned EMUSHORT *));static void emovz	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void einan	PROTO((unsigned EMUSHORT *));static int eiisnan	PROTO((unsigned EMUSHORT *));static int eiisneg	PROTO((unsigned EMUSHORT *));static void eiinfin	PROTO((unsigned EMUSHORT *));static int eiisinf	PROTO((unsigned EMUSHORT *));static int ecmpm	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void eshdn1	PROTO((unsigned EMUSHORT *));static void eshup1	PROTO((unsigned EMUSHORT *));static void eshdn8	PROTO((unsigned EMUSHORT *));static void eshup8	PROTO((unsigned EMUSHORT *));static void eshup6	PROTO((unsigned EMUSHORT *));static void eshdn6	PROTO((unsigned EMUSHORT *));static void eaddm	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void esubm	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void m16m	PROTO((unsigned int, unsigned short *,			       unsigned short *));static int edivm	PROTO((unsigned short *, unsigned short *));static int emulm	PROTO((unsigned short *, unsigned short *));static void emdnorm	PROTO((unsigned EMUSHORT *, int, int, EMULONG, int));static void esub	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       unsigned EMUSHORT *));static void eadd	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       unsigned EMUSHORT *));static void eadd1	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       unsigned EMUSHORT *));static void ediv	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       unsigned EMUSHORT *));static void emul	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       unsigned EMUSHORT *));static void e53toe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void e64toe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void e113toe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void e24toe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etoe113	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void toe113	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etoe64	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void toe64	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etoe53	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void toe53	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etoe24	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void toe24	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static int ecmp		PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void eround	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void ltoe	PROTO((HOST_WIDE_INT *, unsigned EMUSHORT *));static void ultoe	PROTO((unsigned HOST_WIDE_INT *, unsigned EMUSHORT *));static void eifrac	PROTO((unsigned EMUSHORT *, HOST_WIDE_INT *,			       unsigned EMUSHORT *));static void euifrac	PROTO((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,			       unsigned EMUSHORT *));static int eshift	PROTO((unsigned EMUSHORT *, int));static int enormlz	PROTO((unsigned EMUSHORT *));static void e24toasc	PROTO((unsigned EMUSHORT *, char *, int));static void e53toasc	PROTO((unsigned EMUSHORT *, char *, int));static void e64toasc	PROTO((unsigned EMUSHORT *, char *, int));static void e113toasc	PROTO((unsigned EMUSHORT *, char *, int));static void etoasc	PROTO((unsigned EMUSHORT *, char *, int));static void asctoe24	PROTO((char *, unsigned EMUSHORT *));static void asctoe53	PROTO((char *, unsigned EMUSHORT *));static void asctoe64	PROTO((char *, unsigned EMUSHORT *));static void asctoe113	PROTO((char *, unsigned EMUSHORT *));static void asctoe	PROTO((char *, unsigned EMUSHORT *));static void asctoeg	PROTO((char *, unsigned EMUSHORT *, int));static void efloor	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void efrexp	PROTO((unsigned EMUSHORT *, int *,			       unsigned EMUSHORT *));static void eldexp	PROTO((unsigned EMUSHORT *, int, unsigned EMUSHORT *));static void eremain	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       unsigned EMUSHORT *));static void eiremain	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void mtherr	PROTO((char *, int));static void dectoe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etodec	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void todec	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void ibmtoe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       enum machine_mode));static void etoibm	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       enum machine_mode));static void toibm	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,			       enum machine_mode));static void make_nan	PROTO((unsigned EMUSHORT *, int, enum machine_mode));static void uditoe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void ditoe	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etoudi	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void etodi	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));static void esqrt	PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));/* Copy 32-bit numbers obtained from array containing 16-bit numbers,   swapping ends if required, into output array of longs.  The   result is normally passed to fprintf by the ASM_OUTPUT_ macros.   */static void endian (e, x, mode)     unsigned EMUSHORT e[];     long x[];     enum machine_mode mode;{  unsigned long th, t;  if (REAL_WORDS_BIG_ENDIAN)    {      switch (mode)	{	case TFmode:	  /* Swap halfwords in the fourth long. */	  th = (unsigned long) e[6] & 0xffff;	  t = (unsigned long) e[7] & 0xffff;	  t |= th << 16;	  x[3] = (long) t;	case XFmode:	  /* Swap halfwords in the third long. */	  th = (unsigned long) e[4] & 0xffff;	  t = (unsigned long) e[5] & 0xffff;	  t |= th << 16;	  x[2] = (long) t;	  /* fall into the double case */	case DFmode:	  /* swap halfwords in the second word */	  th = (unsigned long) e[2] & 0xffff;	  t = (unsigned long) e[3] & 0xffff;	  t |= th << 16;	  x[1] = (long) t;	  /* fall into the float case */	case HFmode:	case SFmode:	  /* swap halfwords in the first word */	  th = (unsigned long) e[0] & 0xffff;	  t = (unsigned long) e[1] & 0xffff;	  t |= th << 16;	  x[0] = t;	  break;	default:	  abort ();	}    }  else    {      /* Pack the output array without swapping. */      switch (mode)	{	case TFmode:	  /* Pack the fourth long. */	  th = (unsigned long) e[7] & 0xffff;	  t = (unsigned long) e[6] & 0xffff;	  t |= th << 16;	  x[3] = (long) t;	case XFmode:	  /* Pack the third long.	     Each element of the input REAL_VALUE_TYPE array has 16 useful bits	     in it.  */	  th = (unsigned long) e[5] & 0xffff;	  t = (unsigned long) e[4] & 0xffff;	  t |= th << 16;	  x[2] = (long) t;	  /* fall into the double case */	case DFmode:	  /* pack the second long */	  th = (unsigned long) e[3] & 0xffff;	  t = (unsigned long) e[2] & 0xffff;	  t |= th << 16;	  x[1] = (long) t;	  /* fall into the float case */	case HFmode:	case SFmode:	  /* pack the first long */	  th = (unsigned long) e[1] & 0xffff;	  t = (unsigned long) e[0] & 0xffff;	  t |= th << 16;	  x[0] = t;	  break;	default:	  abort ();	}    }}/* This is the implementation of the REAL_ARITHMETIC macro.  */void earith (value, icode, r1, r2)     REAL_VALUE_TYPE *value;     int icode;     REAL_VALUE_TYPE *r1;     REAL_VALUE_TYPE *r2;{  unsigned EMUSHORT d1[NE], d2[NE], v[NE];  enum tree_code code;  GET_REAL (r1, d1);  GET_REAL (r2, d2);#ifdef NANS/*  Return NaN input back to the caller. */  if (eisnan (d1))    {      PUT_REAL (d1, value);      return;    }  if (eisnan (d2))    {      PUT_REAL (d2, value);      return;    }#endif  code = (enum tree_code) icode;  switch (code)    {    case PLUS_EXPR:      eadd (d2, d1, v);      break;    case MINUS_EXPR:      esub (d2, d1, v);		/* d1 - d2 */      break;    case MULT_EXPR:      emul (d2, d1, v);      break;    case RDIV_EXPR:#ifndef REAL_INFINITY      if (ecmp (d2, ezero) == 0)	{#ifdef NANS	enan (v, eisneg (d1) ^ eisneg (d2));	break;#else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -