diff options
author | ro <ro@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-05 14:53:09 +0000 |
---|---|---|
committer | ro <ro@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-05 14:53:09 +0000 |
commit | a23b9c51a0b27c4507a2fb82275b725b6d6fc8eb (patch) | |
tree | 24104c84aafe6bb8ace23e951f7e0950cbc3d4fa /libgcc | |
parent | e59be7e3775cce7a65bfac5c9aeb5f76d42f539b (diff) | |
download | gcc-a23b9c51a0b27c4507a2fb82275b725b6d6fc8eb.tar.gz |
gcc:
* Makefile.in (FPBIT_FUNCS, DPBIT_FUNCS, TPBIT_FUNCS): Remove.
(libgcc-support): Remove $(FPBIT), $(DPBIT), $(TPBIT)
dependencies.
(libgcc.mvars): Remove FPBIT, FPBIT_FUNCS, DPBIT, DPBIT_FUNCS,
TPBIT, TPBIT_FUNCS.
* config/fp-bit.c, config/fp-bit.h: Move to ../libgcc.
* config/arm/t-strongarm-elf (FPBIT, DPBIT, dp-bit.c, fp-bit.c):
Remove.
* config/arm/t-vxworks: Likewise.
* config/arm/t-wince-pe: Likewise.
* config/avr/t-avr (fp-bit.c, FPBIT): Remove.
* config/bfin/t-bfin (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/bfin/t-bfin-elf: Likewise.
* config/bfin/t-bfin-linux: Likewise.
* config/bfin/t-bfin-uclinux: Likewise.
* config/cris/t-cris (FPBIT, DPBIT, dp-bit.c, tmplibgcc_fp_bit.c):
Remove.
* config/fr30/t-fr30: Likewise.
* config/frv/t-frv: Likewise.
* config/h8300/t-h8300 (FPBIT, fp-bit.c): Remove.
* config/iq2000/t-iq2000 (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/m32c/t-m32c: Likewise.
* config/m32r/t-linux: (LIB2FUNCS_EXTRA, fp-bit.c, dp-bit.c): Remove.
* config/m32r/t-m32r (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/mcore/t-mcore: Likewise.
* config/mep/t-mep: Likewise.
* config/microblaze/t-microblaze: Likewise.
* config/mips/t-linux64 (TPBIT, tp-bit.c): Remove.
* config/mips/t-mips (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/mips/t-sdemtk (FPBIT, DPBIT): Remove.
* config/mips/t-sr71k (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/mn10300/t-linux: Remove.
* config/mn10300/t-mn10300 (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/pdp11/t-pdp11: Likewise.
* config/picochip/t-picochip (FPBIT, fp-bit.c): Remove.
* config/rs6000/ppc64-fp.c: Move to ../libgcc/config/rs6000.
* config/rs6000/t-aix43 (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
(LIB2FUNCS_EXTRA): Remove $(srcdir)/config/rs6000/ppc64-fp.c.
* config/rs6000/t-aix52: Likewise.
* config/rs6000/t-darwin (LIB2FUNCS_EXTRA): Remove
$(srcdir)/config/rs6000/ppc64-fp.c.
* config/rs6000/t-fprules-fpbit: Remove.
* config/rs6000/t-linux64 (LIB2FUNCS_EXTRA): Remove.
* config/rs6000/t-lynx (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/sh/t-netbsd (FPBIT, DPBIT): Remove.
* config/sh/t-sh (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/sparc/t-elf: Likewise.
* config/sparc/t-leon: Likewise.
* config/sparc/t-leon3: Likewise.
* config/spu/t-spu-elf: Likewise.
(DPBIT_FUNCS): Remove.
* config/stormy16/t-stormy16 (FPBIT, DPBIT, dp-bit.c, fp-bit.c): Remove.
* config/v850/t-v850: Likewise.
* config.gcc (avr-*-rtems*): Add avr/avr-lib.h to libgcc_tm_file.
(avr-*-*): Likewise.
(h8300-*-rtems*): Set libgcc_tm_file.
(h8300-*-elf*): Likewise.
(powerpc-*-eabisimaltivec*): Remove rs6000/t-fprules-fpbit from
tmake_file.
(powerpc-*-eabisim*): Likewise.
(powerpc-*-elf*): Likewise.
(powerpc-*-eabialtivec*): Likewise.
(powerpc-xilinx-eabi*): Likewise.
(powerpc-*-eabi*): Likewise.
(powerpc-*-rtems*): Likewise.
(powerpc-wrs-vxworks, powerpc-wrs-vxworksae): Likewise.
(powerpcle-*-elf*): Likewise.
(powerpcle-*-eabisim*): Likewise.
(powerpcle-*-eabi*): Likewise.
(rx-*-elf*): Add rx/rx-lib.h to libgcc_tm_file.
(am33_2.0-*-linux*): Remove mn10300/t-linux from tmake_file.
* doc/fragments.texi (Target Fragment, Floating Point Emulation):
Remove.
gcc/po:
* EXCLUDES (config/fp-bit.c, config/fp-bit.h): Remove.
libgcc:
* Makefile.in (double_type_size, long_double_type_size): Set.
Remove $(fpbit-in-libgcc) support.
(FPBIT_FUNCS, DPBIT_FUNCS, TPBIT_FUNCS): New variables.
(fpbit-src): New variable.
($(fpbit-o), $(fpbit-s-o)): Use $(fpbit-src) instead of $(FPBIT).
Compile with -DFLOAT $(FPBIT_CFLAGS).
Use $<.
($(dpbit-o), $(dpbit-s-o)): Use $(fpbit-src) instead of $(DPBIT).
Compile with $(FPBIT_CFLAGS).
Use $<.
($(tpbit-o), $(tpbit-s-o): Use $(fpbit-src) instead of $(TPBIT).
Compile with -DFLOAT $(TPBIT_CFLAGS).
Use $<.
* configure.ac (double_type_size, long_double_type_size):
Determine and substitute.
* configure: Regenerate.
* fp-bit.c, fp-bit.h: New files.
* config/avr/avr-lib.h, config/h8300/h8300-lib.h: New files.
* config/mips/t-irix6 (TPBIT, $(gcc_objdir)/tp-bit.c): Remove.
* config/mips/t-mips: New file.
* config/mips/t-sdemtk: New file.
* config/rs6000/ppc64-fp.c: New file.
* config/rs6000/t-darwin (LIB2ADD): Add
$(srcdir)/config/rs6000/ppc64-fp.c.
* config/rs6000/t-ppc64-fp: New file.
* config/rx/rx-lib.h: New file.
* config/rx/t-rx (FPBIT): Set to true.
($(gcc_objdir)/fp-bit.c): Remove.
(DPBIT): Set to true only with -m64bit-doubles.
($(gcc_objdir)/dp-bit.c): Remove.
* config/sparc/t-softfp: Remove.
* config/spu/t-elf: New file.
* config/t-fdpbit, config/t-fpbit: New files.
* config.host (m32c*-*-*): Add t-fdpbit to tmake_file.
(mips*-*-*): Likewise.
(arm-wrs-vxworks): Likewise.
(arm*-*-freebsd*): Likewise.
(avr-*-rtems*): Add t-fpbit to tmake_file.
(avr-*-*): Likewise.
(bfin*-elf*): Add t-fdpbit to tmake_file.
(bfin*-uclinux*): Likewise.
(bfin*-linux-uclibc*): Likewise.
(bfin*-rtems*): New case.
Add t-fdpbit to tmake_file.
(bfin*-*): Add t-fdpbit to tmake_file.
(crisv32-*-elf): Likewise.
(cris-*-linux*): Likewise.
(fr30-*-elf): Likewise.
(frv-*-elf, frv-*-*linux*): Likewise.
(h8300-*-rtems*, h8300-*-elf*): Add t-fpbit to tmake_file.
(iq2000*-*-elf*): Add t-fdpbit to tmake_file.
(m32r-*-elf*): Likewise.
(m32rle-*-elf*): Likewise.
(m32r-*-linux*): Likewise.
(m32rle-*-linux*): Likewise.
(mcore-*-elf): Add t-fdpbit to tmake_file.
(microblaze*-*-*): Likewise.
(mips-sgi-irix6.5*): Add t-tpbit to tmake_file.
(mips*-*-netbsd*): Add mips/t-mips to tmake_file.
(mips64*-*-linux*): Also handle mipsisa64*-*-linux*.
Fix typo.
Add mips/t-tpbit to tmake-file.
(mips*-*-linux*): Fix typo.
(mips*-sde-elf*): New case
Add mips/t-sdemtk unless using newlib.
(mipsisa64sr71k-*-elf*): Add t-fdpbit to tmake_file.
(mipsisa64sb1-*-elf*): Add mips/t-mips to tmake_file.
(mn10300-*-*): Likewise.
(pdp11-*-*): Likewise.
(picochip-*-*): Add t-fpbit to tmake_file.
(powerpc-*-eabisimaltivec*): Likewise.
(powerpc-*-eabisim*): Likewise.
(powerpc-*-elf*): Likewise.
(powerpc-*-eabialtivec*): Likewise.
(powerpc-xilinx-eabi*): New case.
Add t-fdpbit to tmake_file.
(powerpc-*-eabi*): Add t-fdpbit to tmake_file.
(powerpc-*-rtems*): Likewise.
(powerpc-*-linux*, powerpc64-*-linux*): Add rs6000/t-ppc64-fp to
tmake_file.
(powerpc-wrs-vxworks, powerpc-wrs-vxworksae): Add t-fdpbit to
tmake_file.
(powerpc-*-lynxos*): Likewise.
(powerpcle-*-elf*): Likewise.
(powerpcle-*-eabisim*): Likewise.
(powerpcle-*-eabi*): Likewise.
(rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Add
t-fdpbit, rs6000/t-ppc64-fp to tmake_file.
(rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise.
(rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise.
(rx-*-elf): Add t-fdpbit to tmake_file.
(sh-*-elf*, sh[12346l]*-*-elf*, sh-*-linux*)
(sh[2346lbe]*-*-linux*, sh-*-netbsdelf*, shl*-*-netbsdelf*)
(sh5-*-netbsd*, sh5l*-*-netbsd*, sh64-*-netbsd*)
(sh64l*-*-netbsd*): Add t-fdpbit to tmake_file except on
sh*-*-netbsd*.
(sh-*-rtems*): Add t-fdpbit to tmake_file.
(sh-wrs-vxworks): Likewise.
(sparc-*-elf*): Replace sparc/t-softfp by t-fdpbit in tmake_file.
(sparc-*-linux*): Add t-fdpbit to tmake_file for *-leon*.
(sparc-*-rtems*, sparc64-*-rtems*): Split off ...
(sparc64-*-rtems*): ... new case.
(sparc-*-rtems*): Add t-fdpbit to tmake_file.
(spu-*-elf*): Likewise.
Add spu/t-elf to tmake_file.
(v850*-*-*): Add t-fdpbit to tmake_file.
(xstormy16-*-elf): Likewise.
(am33_2.0-*-linux*): Add t-fdpbit to tmake_file.
(mep*-*-*): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177448 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc')
-rw-r--r-- | libgcc/ChangeLog | 112 | ||||
-rw-r--r-- | libgcc/Makefile.in | 54 | ||||
-rw-r--r-- | libgcc/config.host | 111 | ||||
-rw-r--r-- | libgcc/config/avr/avr-lib.h | 6 | ||||
-rw-r--r-- | libgcc/config/h8300/h8300-lib.h | 7 | ||||
-rw-r--r-- | libgcc/config/mips/t-irix6 | 12 | ||||
-rw-r--r-- | libgcc/config/mips/t-mips | 4 | ||||
-rw-r--r-- | libgcc/config/mips/t-sdemtk | 3 | ||||
-rw-r--r-- | libgcc/config/mips/t-tpbit | 4 | ||||
-rw-r--r-- | libgcc/config/rs6000/ppc64-fp.c | 239 | ||||
-rw-r--r-- | libgcc/config/rs6000/t-darwin | 2 | ||||
-rw-r--r-- | libgcc/config/rs6000/t-ppc64-fp | 2 | ||||
-rw-r--r-- | libgcc/config/rx/rx-lib.h | 6 | ||||
-rw-r--r-- | libgcc/config/rx/t-rx | 20 | ||||
-rw-r--r-- | libgcc/config/sparc/t-softfp | 29 | ||||
-rw-r--r-- | libgcc/config/spu/t-elf | 3 | ||||
-rw-r--r-- | libgcc/config/t-fdpbit | 2 | ||||
-rw-r--r-- | libgcc/config/t-fpbit | 2 | ||||
-rw-r--r-- | libgcc/configure | 626 | ||||
-rw-r--r-- | libgcc/configure.ac | 7 | ||||
-rw-r--r-- | libgcc/fp-bit.c | 1657 | ||||
-rw-r--r-- | libgcc/fp-bit.h | 507 |
22 files changed, 3319 insertions, 96 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 65d47a80278..00c4fa63b7b 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,5 +1,117 @@ 2011-08-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + * Makefile.in (double_type_size, long_double_type_size): Set. + Remove $(fpbit-in-libgcc) support. + (FPBIT_FUNCS, DPBIT_FUNCS, TPBIT_FUNCS): New variables. + (fpbit-src): New variable. + ($(fpbit-o), $(fpbit-s-o)): Use $(fpbit-src) instead of $(FPBIT). + Compile with -DFLOAT $(FPBIT_CFLAGS). + Use $<. + ($(dpbit-o), $(dpbit-s-o)): Use $(fpbit-src) instead of $(DPBIT). + Compile with $(FPBIT_CFLAGS). + Use $<. + ($(tpbit-o), $(tpbit-s-o): Use $(fpbit-src) instead of $(TPBIT). + Compile with -DFLOAT $(TPBIT_CFLAGS). + Use $<. + * configure.ac (double_type_size, long_double_type_size): + Determine and substitute. + * configure: Regenerate. + * fp-bit.c, fp-bit.h: New files. + * config/avr/avr-lib.h, config/h8300/h8300-lib.h: New files. + * config/mips/t-irix6 (TPBIT, $(gcc_objdir)/tp-bit.c): Remove. + * config/mips/t-mips: New file. + * config/mips/t-sdemtk: New file. + * config/rs6000/ppc64-fp.c: New file. + * config/rs6000/t-darwin (LIB2ADD): Add + $(srcdir)/config/rs6000/ppc64-fp.c. + * config/rs6000/t-ppc64-fp: New file. + * config/rx/rx-lib.h: New file. + * config/rx/t-rx (FPBIT): Set to true. + ($(gcc_objdir)/fp-bit.c): Remove. + (DPBIT): Set to true only with -m64bit-doubles. + ($(gcc_objdir)/dp-bit.c): Remove. + * config/sparc/t-softfp: Remove. + * config/spu/t-elf: New file. + * config/t-fdpbit, config/t-fpbit: New files. + * config.host (m32c*-*-*): Add t-fdpbit to tmake_file. + (mips*-*-*): Likewise. + (arm-wrs-vxworks): Likewise. + (arm*-*-freebsd*): Likewise. + (avr-*-rtems*): Add t-fpbit to tmake_file. + (avr-*-*): Likewise. + (bfin*-elf*): Add t-fdpbit to tmake_file. + (bfin*-uclinux*): Likewise. + (bfin*-linux-uclibc*): Likewise. + (bfin*-rtems*): New case. + Add t-fdpbit to tmake_file. + (bfin*-*): Add t-fdpbit to tmake_file. + (crisv32-*-elf): Likewise. + (cris-*-linux*): Likewise. + (fr30-*-elf): Likewise. + (frv-*-elf, frv-*-*linux*): Likewise. + (h8300-*-rtems*, h8300-*-elf*): Add t-fpbit to tmake_file. + (iq2000*-*-elf*): Add t-fdpbit to tmake_file. + (m32r-*-elf*): Likewise. + (m32rle-*-elf*): Likewise. + (m32r-*-linux*): Likewise. + (m32rle-*-linux*): Likewise. + (mcore-*-elf): Add t-fdpbit to tmake_file. + (microblaze*-*-*): Likewise. + (mips-sgi-irix6.5*): Add t-tpbit to tmake_file. + (mips*-*-netbsd*): Add mips/t-mips to tmake_file. + (mips64*-*-linux*): Also handle mipsisa64*-*-linux*. + Fix typo. + Add mips/t-tpbit to tmake-file. + (mips*-*-linux*): Fix typo. + (mips*-sde-elf*): New case + Add mips/t-sdemtk unless using newlib. + (mipsisa64sr71k-*-elf*): Add t-fdpbit to tmake_file. + (mipsisa64sb1-*-elf*): Add mips/t-mips to tmake_file. + (mn10300-*-*): Likewise. + (pdp11-*-*): Likewise. + (picochip-*-*): Add t-fpbit to tmake_file. + (powerpc-*-eabisimaltivec*): Likewise. + (powerpc-*-eabisim*): Likewise. + (powerpc-*-elf*): Likewise. + (powerpc-*-eabialtivec*): Likewise. + (powerpc-xilinx-eabi*): New case. + Add t-fdpbit to tmake_file. + (powerpc-*-eabi*): Add t-fdpbit to tmake_file. + (powerpc-*-rtems*): Likewise. + (powerpc-*-linux*, powerpc64-*-linux*): Add rs6000/t-ppc64-fp to + tmake_file. + (powerpc-wrs-vxworks, powerpc-wrs-vxworksae): Add t-fdpbit to + tmake_file. + (powerpc-*-lynxos*): Likewise. + (powerpcle-*-elf*): Likewise. + (powerpcle-*-eabisim*): Likewise. + (powerpcle-*-eabi*): Likewise. + (rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Add + t-fdpbit, rs6000/t-ppc64-fp to tmake_file. + (rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise. + (rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise. + (rx-*-elf): Add t-fdpbit to tmake_file. + (sh-*-elf*, sh[12346l]*-*-elf*, sh-*-linux*) + (sh[2346lbe]*-*-linux*, sh-*-netbsdelf*, shl*-*-netbsdelf*) + (sh5-*-netbsd*, sh5l*-*-netbsd*, sh64-*-netbsd*) + (sh64l*-*-netbsd*): Add t-fdpbit to tmake_file except on + sh*-*-netbsd*. + (sh-*-rtems*): Add t-fdpbit to tmake_file. + (sh-wrs-vxworks): Likewise. + (sparc-*-elf*): Replace sparc/t-softfp by t-fdpbit in tmake_file. + (sparc-*-linux*): Add t-fdpbit to tmake_file for *-leon*. + (sparc-*-rtems*, sparc64-*-rtems*): Split off ... + (sparc64-*-rtems*): ... new case. + (sparc-*-rtems*): Add t-fdpbit to tmake_file. + (spu-*-elf*): Likewise. + Add spu/t-elf to tmake_file. + (v850*-*-*): Add t-fdpbit to tmake_file. + (xstormy16-*-elf): Likewise. + (am33_2.0-*-linux*): Add t-fdpbit to tmake_file. + (mep*-*-*): Likewise. + +2011-08-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + * Makefile.in (LIB2ADDEH, LIB2ADDEHSTATIC, LIB2ADDEHSHARED): New variables. (LIBUNWIND, SHLIBUNWIND_LINK, SHLIBUNWIND_INSTALL): New variables. diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index c252d9a2217..4a75a37048e 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -37,6 +37,8 @@ SHELL = @SHELL@ cpu_type = @cpu_type@ enable_shared = @enable_shared@ +double_type_size = @double_type_size@ +long_double_type_size = @long_double_type_size@ decimal_float = @decimal_float@ enable_decimal_float = @enable_decimal_float@ fixed_point = @fixed_point@ @@ -256,6 +258,21 @@ LIBGCC_VER_GNU_PREFIX = __ LIBGCC_VER_FIXEDPOINT_GNU_PREFIX = __ LIBGCC_VER_SYMBOLS_PREFIX = +FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \ + _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \ + _lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \ + _sf_to_df _sf_to_tf _thenan_sf _sf_to_usi _usi_to_sf + +DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \ + _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \ + _lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \ + _df_to_sf _df_to_tf _thenan_df _df_to_usi _usi_to_df + +TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \ + _fpcmp_parts_tf _compare_tf _eq_tf _ne_tf _gt_tf _ge_tf \ + _lt_tf _le_tf _unord_tf _si_to_tf _tf_to_si _negate_tf _make_tf \ + _tf_to_df _tf_to_sf _thenan_tf _tf_to_usi _usi_to_tf + # Additional sources to handle exceptions; overridden by targets as needed. LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \ $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c @@ -445,34 +462,25 @@ $(lib2-divmod-s-o): %_s$(objext): $(gcc_srcdir)/libgcc2.c libgcc-s-objects += $(lib2-divmod-s-o) endif -# $(FPBIT) et al. are pathnames relative to the GCC build -# directory; the supporting files are made by the GCC -# Makefile. -# FIXME: Soon we will be able to move this logic into this directory. - -ifneq ($(fpbit-in-libgcc),yes) -FPBIT:=$(if $(FPBIT),$(gcc_objdir)/$(FPBIT),) -DPBIT:=$(if $(DPBIT),$(gcc_objdir)/$(DPBIT),) -TPBIT:=$(if $(TPBIT),$(gcc_objdir)/$(TPBIT),) -endif - ifeq ($(TPBIT),) # _sf_to_tf and _df_to_tf require tp-bit.c being compiled in. FPBIT_FUNCS := $(filter-out _sf_to_tf,$(FPBIT_FUNCS)) DPBIT_FUNCS := $(filter-out _df_to_tf,$(DPBIT_FUNCS)) endif +fpbit-src := $(srcdir)/fp-bit.c + # Build FPBIT. ifneq ($(FPBIT),) fpbit-o = $(patsubst %,%$(objext),$(FPBIT_FUNCS)) -$(fpbit-o): %$(objext): $(FPBIT) - $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(FPBIT) $(vis_hide) +$(fpbit-o): %$(objext): $(fpbit-src) + $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -DFLOAT $(FPBIT_CFLAGS) -c $< $(vis_hide) libgcc-objects += $(fpbit-o) ifeq ($(enable_shared),yes) fpbit-s-o = $(patsubst %,%_s$(objext),$(FPBIT_FUNCS)) -$(fpbit-s-o): %_s$(objext): $(FPBIT) - $(gcc_s_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(FPBIT) +$(fpbit-s-o): %_s$(objext): $(fpbit-src) + $(gcc_s_compile) -DFINE_GRAINED_LIBRARIES -DL$* -DFLOAT $(FPBIT_CFLAGS) -c $< libgcc-s-objects += $(fpbit-s-o) endif endif @@ -480,14 +488,14 @@ endif # Build DPBIT. ifneq ($(DPBIT),) dpbit-o = $(patsubst %,%$(objext),$(DPBIT_FUNCS)) -$(dpbit-o): %$(objext): $(DPBIT) - $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(DPBIT) $(vis_hide) +$(dpbit-o): %$(objext): $(fpbit-src) + $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* $(DPBIT_CFLAGS) -c $< $(vis_hide) libgcc-objects += $(dpbit-o) ifeq ($(enable_shared),yes) dpbit-s-o = $(patsubst %,%_s$(objext),$(DPBIT_FUNCS)) -$(dpbit-s-o): %_s$(objext): $(DPBIT) - $(gcc_s_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(DPBIT) +$(dpbit-s-o): %_s$(objext): $(fpbit-src) + $(gcc_s_compile) -DFINE_GRAINED_LIBRARIES -DL$* $(DPBIT_CFLAGS) -c $< libgcc-s-objects += $(dpbit-s-o) endif endif @@ -495,14 +503,14 @@ endif # Build TPBIT. ifneq ($(TPBIT),) tpbit-o = $(patsubst %,%$(objext),$(TPBIT_FUNCS)) -$(tpbit-o): %$(objext): $(TPBIT) - $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(TPBIT) $(vis_hide) +$(tpbit-o): %$(objext): $(fpbit-src) + $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -DTFLOAT $(TPBIT_CFLAGS) -c $< $(vis_hide) libgcc-objects += $(tpbit-o) ifeq ($(enable_shared),yes) tpbit-s-o = $(patsubst %,%_s$(objext),$(TPBIT_FUNCS)) -$(tpbit-s-o): %_s$(objext): $(TPBIT) - $(gcc_s_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(TPBIT) +$(tpbit-s-o): %_s$(objext): $(fpbit-src) + $(gcc_s_compile) -DFINE_GRAINED_LIBRARIES -DL$* -DTFLOAT $(TPBIT_CFLAGS) -c $< libgcc-s-objects += $(tpbit-s-o) endif endif diff --git a/libgcc/config.host b/libgcc/config.host index db00c4c2d8c..cd4f054336b 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -72,6 +72,7 @@ cpu_type=`echo ${host} | sed 's/-.*$//'` case ${host} in m32c*-*-*) cpu_type=m32c + tmake_file=t-fdpbit ;; alpha*-*-*) cpu_type=alpha @@ -121,6 +122,7 @@ microblaze*-*-*) ;; mips*-*-*) cpu_type=mips + tmake_file=mips/t-mips ;; powerpc*-*-*) cpu_type=rs6000 @@ -265,8 +267,10 @@ alpha*-dec-*vms*) md_unwind_header=alpha/vms-unwind.h ;; arm-wrs-vxworks) + tmake_file=t-fdpbit ;; arm*-*-freebsd*) + tmake_file=t-fdpbit ;; arm*-*-netbsdelf*) ;; @@ -309,40 +313,56 @@ arm*-*-elf) arm*-wince-pe*) ;; avr-*-rtems*) + tmake_file=t-fpbit ;; avr-*-*) - # Make HImode functions for AVR - tmake_file=${cpu_type}/t-avr + # Make HImode functions for AVR + tmake_file="${cpu_type}/t-avr t-fpbit" + ;; bfin*-elf*) + tmke_file=t-fdpbit ;; bfin*-uclinux*) + tmake_file=t-fdpbit md_unwind_header=bfin/linux-unwind.h ;; bfin*-linux-uclibc*) + tmake_file=t-fdpbit # No need to build crtbeginT.o on uClibc systems. Should probably # be moved to the OS specific section above. extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" md_unwind_header=bfin/linux-unwind.h ;; +bfin*-rtems*) + tmake_file=t-fdpbit + ;; bfin*-*) + tmake_file=t-fdpbit ;; crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none) + tmake_file=t-fdpbit extra_parts="crtbegin.o crtend.o" ;; cris-*-linux* | crisv32-*-linux*) + tmake_file=t-fdpbit ;; fido-*-elf) ;; fr30-*-elf) + tmake_file=t-fdpbit ;; frv-*-elf) + tmake_file=t-fdpbit ;; frv-*-*linux*) + tmake_file=t-fdpbit ;; h8300-*-rtems*) + tmake_file=t-fpbit ;; h8300-*-elf*) + tmake_file=t-fpbit ;; hppa*64*-*-linux*) ;; @@ -458,6 +478,7 @@ ia64-hp-*vms*) md_unwind_header=ia64/vms-unwind.h ;; iq2000*-*-elf*) + tmake_file=t-fdpbit ;; lm32-*-elf*|lm32-*-rtems*) extra_parts="crtbegin.o crtend.o crti.o crtn.o" @@ -468,12 +489,16 @@ lm32-*-uclinux*) tmake_file="lm32/t-lm32 lm32/t-uclinux t-softfp" ;; m32r-*-elf*|m32r-*-rtems*) + tmake_file=t-fdpbit ;; m32rle-*-elf*) + tmake_file=t-fdpbit ;; m32r-*-linux*) + tmake_file=t-fdpbit ;; m32rle-*-linux*) + tmake_file=t-fdpbit ;; m68k-*-elf*) ;; @@ -492,29 +517,41 @@ m68k-*-linux*) # Motorola m68k's running GNU/Linux m68k-*-rtems*) ;; mcore-*-elf) + tmake_file=t-fdpbit ;; microblaze*-*-*) - tmake_file="microblaze/t-microblaze" + tmake_file="microblaze/t-microblaze t-fdpbit" ;; mips-sgi-irix6.5*) - tmake_file="mips/t-irix6 t-crtfm t-slibgcc mips/t-slibgcc-irix" + tmake_file="$tmake_file mips/t-irix6 t-crtfm mips/t-tpbit t-slibgcc mips/t-slibgcc-irix" extra_parts="crtbegin.o crtend.o crtfastmath.o irix-crti.o irix-crtn.o" md_unwind_header=mips/irix6-unwind.h ;; mips*-*-netbsd*) # NetBSD/mips, either endian. ;; -mips64*-*-linux*) +mips64*-*-linux* | mipsisa64*-*-linux*) extra_parts="$extra_parts crtfastmath.o" - tmake_file="{$tmake_file} t-crtfm" + tmake_file="${tmake_file} t-crtfm mips/t-tpbit" md_unwind_header=mips/linux-unwind.h ;; mips*-*-linux*) # Linux MIPS, either endian. extra_parts="$extra_parts crtfastmath.o" - tmake_file="{$tmake_file} t-crtfm" + tmake_file="${tmake_file} t-crtfm" md_unwind_header=mips/linux-unwind.h ;; mips*-*-openbsd*) ;; +mips*-sde-elf*) + case "${with_newlib}" in + yes) + # newlib / libgloss. + ;; + *) + # MIPS toolkit libraries. + tmake_file=mips/t-sdemtk + ;; + esac + ;; mipsisa32-*-elf* | mipsisa32el-*-elf*) ;; mipsisa32r2-*-elf* | mipsisa32r2el-*-elf*) @@ -524,6 +561,7 @@ mipsisa64-*-elf* | mipsisa64el-*-elf*) mipsisa64r2-*-elf* | mipsisa64r2el-*-elf*) ;; mipsisa64sr71k-*-elf*) + tmake_file=t-fdpbit ;; mipsisa64sb1-*-elf* | mipsisa64sb1el-*-elf*) ;; @@ -546,15 +584,17 @@ mmix-knuth-mmixware) tmake_file="${tmake_file} ${cpu_type}/t-${cpu_type}" ;; mn10300-*-*) + tmake_file=t-fdpbit ;; moxie-*-*) tmake_file="moxie/t-moxie moxie/t-moxie-softfp" extra_parts="crtbegin.o crtend.o crti.o crtn.o" ;; pdp11-*-*) + tmake_file=t-fdpbit ;; picochip-*-*) - tmake_file=picochip/t-picochip + tmake_file="picochip/t-picochip t-fpbit" ;; powerpc-*-darwin*) case ${host} in @@ -580,44 +620,60 @@ powerpc-*-eabispe*) tmake_file="${tmake_file} rs6000/t-ppccomm" ;; powerpc-*-eabisimaltivec*) + tmake_file=t-fdpbit ;; powerpc-*-eabisim*) + tmake_file=t-fdpbit ;; powerpc-*-elf*) + tmake_file=t-fdpbit ;; powerpc-*-eabialtivec*) + tmake_file=t-fdpbit + ;; +powerpc-xilinx-eabi*) + tmake_file=t-fdpbit ;; powerpc-*-eabi*) - tmake_file="${tmake_file} rs6000/t-ppccomm" + tmake_file="${tmake_file} rs6000/t-ppccomm t-fdpbit" ;; powerpc-*-rtems*) + tmake_file=t-fdpbit ;; powerpc-*-linux* | powerpc64-*-linux*) - tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ldbl128 t-softfp t-dfprules" + tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ldbl128 t-softfp t-dfprules rs6000/t-ppc64-fp" md_unwind_header=rs6000/linux-unwind.h ;; powerpc-wrs-vxworks|powerpc-wrs-vxworksae) + tmake_file=t-fdpbit ;; powerpc-*-lynxos*) + tmake_file=t-fdpbit ;; powerpcle-*-elf*) + tmake_file=t-fdpbit ;; powerpcle-*-eabisim*) + tmake_file=t-fdpbit ;; powerpcle-*-eabi*) + tmake_file=t-fdpbit ;; rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*) md_unwind_header=rs6000/aix-unwind.h + tmake_file="t-fdpbit rs6000/t-ppc64-fp" ;; rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*) md_unwind_header=rs6000/aix-unwind.h + tmake_file="t-fdpbit rs6000/t-ppc64-fp" ;; rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*) md_unwind_header=rs6000/aix-unwind.h + tmake_file="t-fdpbit rs6000/t-ppc64-fp" ;; rx-*-elf) extra_parts="crtbegin.o crtend.o" - tmake_file="rx/t-rx" + tmake_file="rx/t-rx t-fdpbit" ;; s390-*-linux*) tmake_file="${tmake_file} s390/t-crtstuff s390/t-linux s390/32/t-floattodi" @@ -639,14 +695,25 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ sh64-*-netbsd* | sh64l*-*-netbsd*) case ${host} in sh*-*-linux*) - tmake_file="${tmake_file} sh/t-linux" + tmake_file="${tmake_file} sh/t-linux t-fdpbit" md_unwind_header=sh/linux-unwind.h ;; + sh*-*-netbsd*) + # NetBSD's C library includes a fast software FP library that + # has support for setting/setting the rounding mode, exception + # mask, etc. Therefore, we don't want to include software FP + # in libgcc. + ;; + sh*-*-*) + tmake_file=t-fdpbit + ;; esac ;; sh-*-rtems*) + tmake_file=t-fdpbit ;; sh-wrs-vxworks) + tmake_file=t-fdpbit ;; sparc-*-netbsdelf*) ;; @@ -660,16 +727,21 @@ sparc-*-elf*) tmake_file="sparc/t-softmul" ;; esac - tmake_file="${tmake_file} sparc/t-softfp t-crtin t-crtfm" + tmake_file="${tmake_file} t-fdpbit t-crtin t-crtfm" extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o" ;; sparc-*-linux*) # SPARC's running GNU/Linux, libc6 + case ${host} in + *-leon*) + tmake_file=t-fdpbit + ;; + esac extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} t-crtfm" md_unwind_header=sparc/linux-unwind.h ;; -sparc-*-rtems* | sparc64-*-rtems* ) - tmake_file="sparc/t-elf t-crtin t-crtfm t-rtems" +sparc-*-rtems*) + tmake_file="sparc/t-elf t-crtin t-crtfm t-rtems t-fdpbit" extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o" ;; sparc*-*-solaris2*) @@ -681,6 +753,10 @@ sparc64-*-elf*) tmake_file="${tmake_file} t-crtin t-crtfm" extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o" ;; +sparc64-*-rtems*) + tmake_file="sparc/t-elf t-crtin t-crtfm t-rtems" + extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o" + ;; sparc-wrs-vxworks) ;; sparc64-*-freebsd*|ultrasparc-*-freebsd*) @@ -695,11 +771,13 @@ sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux sparc64-*-netbsd*) ;; spu-*-elf*) + tmake_file="t-fdpbit spu/t-elf" ;; tic6x-*-*) tmake_file="${tmake_file} t-gnu-prefix" ;; v850*-*-*) + tmake_file=t-fdpbit ;; vax-*-linux*) ;; @@ -708,6 +786,7 @@ vax-*-netbsdelf*) vax-*-openbsd*) ;; xstormy16-*-elf) + tmake_file=t-fdpbit ;; xtensa*-*-elf*) tmake_file=xtensa/t-xtensa @@ -718,10 +797,12 @@ xtensa*-*-linux*) ;; am33_2.0-*-linux*) extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o" + tmake_file=t-fdpbit ;; m32c-*-elf*|m32c-*-rtems*) ;; mep*-*-*) + tmake_file=t-fdpbit ;; *) echo "*** Configuration ${host} not supported" 1>&2 diff --git a/libgcc/config/avr/avr-lib.h b/libgcc/config/avr/avr-lib.h new file mode 100644 index 00000000000..daca4d81f9a --- /dev/null +++ b/libgcc/config/avr/avr-lib.h @@ -0,0 +1,6 @@ +#ifdef FLOAT +#define CMPtype QItype +#define DF SF +#define DI SI +typedef int QItype __attribute__ ((mode (QI))); +#endif diff --git a/libgcc/config/h8300/h8300-lib.h b/libgcc/config/h8300/h8300-lib.h new file mode 100644 index 00000000000..cff664a54ce --- /dev/null +++ b/libgcc/config/h8300/h8300-lib.h @@ -0,0 +1,7 @@ +#ifdef FLOAT +#ifdef __H8300__ +#define CMPtype HItype +#else +#define CMPtype SItype +#endif +#endif diff --git a/libgcc/config/mips/t-irix6 b/libgcc/config/mips/t-irix6 index 77dd41da276..c9bd3cdcb0a 100644 --- a/libgcc/config/mips/t-irix6 +++ b/libgcc/config/mips/t-irix6 @@ -22,15 +22,3 @@ irix-crti.o: $(srcdir)/config/mips/irix-crti.S irix-crtn.o: $(srcdir)/config/mips/irix-crtn.S $(crt_compile) -c $< - -TPBIT = tp-bit.c - -$(gcc_objdir)/tp-bit.c: $(gcc_srcdir)/config/fp-bit.c - echo '#ifdef __MIPSEL__' > $@ - echo '# define FLOAT_BIT_ORDER_MISMATCH' >> $@ - echo '#endif' >> $@ - echo '#define QUIET_NAN_NEGATED' >> $@ - echo '#if __LDBL_MANT_DIG__ == 106' >> $@ - echo '# define TFLOAT' >> $@ - cat $< >> $@ - echo '#endif' >> $@ diff --git a/libgcc/config/mips/t-mips b/libgcc/config/mips/t-mips new file mode 100644 index 00000000000..b7d13b3ddb3 --- /dev/null +++ b/libgcc/config/mips/t-mips @@ -0,0 +1,4 @@ +FPBIT = true +FPBIT_CFLAGS = -DQUIET_NAN_NEGATED +DPBIT = true +DPBIT_CFLAGS = -DQUIET_NAN_NEGATED diff --git a/libgcc/config/mips/t-sdemtk b/libgcc/config/mips/t-sdemtk new file mode 100644 index 00000000000..a06e828b545 --- /dev/null +++ b/libgcc/config/mips/t-sdemtk @@ -0,0 +1,3 @@ +# Don't build FPBIT and DPBIT; we'll be using the SDE soft-float library. +FPBIT = +DPBIT = diff --git a/libgcc/config/mips/t-tpbit b/libgcc/config/mips/t-tpbit new file mode 100644 index 00000000000..1670ef3ffd6 --- /dev/null +++ b/libgcc/config/mips/t-tpbit @@ -0,0 +1,4 @@ +ifeq ($(long_double_type_size),128) +TPBIT = true +TPBIT_CFLAGS = -DQUIET_NAN_NEGATED +endif diff --git a/libgcc/config/rs6000/ppc64-fp.c b/libgcc/config/rs6000/ppc64-fp.c new file mode 100644 index 00000000000..ab18d2d94b5 --- /dev/null +++ b/libgcc/config/rs6000/ppc64-fp.c @@ -0,0 +1,239 @@ +/* Functions needed for soft-float on powerpc64-linux, copied from + libgcc2.c with macros expanded to force the use of specific types. + + Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2006, 2009, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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. + +GCC 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/>. */ + +#if defined(__powerpc64__) || defined (__64BIT__) || defined(__ppc64__) +#define TMODES +#include "fp-bit.h" + +extern DItype __fixtfdi (TFtype); +extern DItype __fixdfdi (DFtype); +extern DItype __fixsfdi (SFtype); +extern USItype __fixunsdfsi (DFtype); +extern USItype __fixunssfsi (SFtype); +extern TFtype __floatditf (DItype); +extern TFtype __floatunditf (UDItype); +extern DFtype __floatdidf (DItype); +extern DFtype __floatundidf (UDItype); +extern SFtype __floatdisf (DItype); +extern SFtype __floatundisf (UDItype); +extern DItype __fixunstfdi (TFtype); + +static DItype local_fixunssfdi (SFtype); +static DItype local_fixunsdfdi (DFtype); + +DItype +__fixtfdi (TFtype a) +{ + if (a < 0) + return - __fixunstfdi (-a); + return __fixunstfdi (a); +} + +DItype +__fixdfdi (DFtype a) +{ + if (a < 0) + return - local_fixunsdfdi (-a); + return local_fixunsdfdi (a); +} + +DItype +__fixsfdi (SFtype a) +{ + if (a < 0) + return - local_fixunssfdi (-a); + return local_fixunssfdi (a); +} + +USItype +__fixunsdfsi (DFtype a) +{ + if (a >= - (DFtype) (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1)) + return (SItype) (a + (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1)) + - (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1); + return (SItype) a; +} + +USItype +__fixunssfsi (SFtype a) +{ + if (a >= - (SFtype) (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1)) + return (SItype) (a + (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1)) + - (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1); + return (SItype) a; +} + +TFtype +__floatditf (DItype u) +{ + DFtype dh, dl; + + dh = (SItype) (u >> (sizeof (SItype) * 8)); + dh *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1)); + dl = (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1)); + + return (TFtype) dh + (TFtype) dl; +} + +TFtype +__floatunditf (UDItype u) +{ + DFtype dh, dl; + + dh = (USItype) (u >> (sizeof (SItype) * 8)); + dh *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1)); + dl = (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1)); + + return (TFtype) dh + (TFtype) dl; +} + +DFtype +__floatdidf (DItype u) +{ + DFtype d; + + d = (SItype) (u >> (sizeof (SItype) * 8)); + d *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1)); + d += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1)); + + return d; +} + +DFtype +__floatundidf (UDItype u) +{ + DFtype d; + + d = (USItype) (u >> (sizeof (SItype) * 8)); + d *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1)); + d += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1)); + + return d; +} + +SFtype +__floatdisf (DItype u) +{ + DFtype f; + + if (53 < (sizeof (DItype) * 8) + && 53 > ((sizeof (DItype) * 8) - 53 + 24)) + { + if (! (- ((DItype) 1 << 53) < u + && u < ((DItype) 1 << 53))) + { + if ((UDItype) u & (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1)) + { + u &= ~ (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1); + u |= ((UDItype) 1 << ((sizeof (DItype) * 8) - 53)); + } + } + } + f = (SItype) (u >> (sizeof (SItype) * 8)); + f *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1)); + f += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1)); + + return (SFtype) f; +} + +SFtype +__floatundisf (UDItype u) +{ + DFtype f; + + if (53 < (sizeof (DItype) * 8) + && 53 > ((sizeof (DItype) * 8) - 53 + 24)) + { + if (u >= ((UDItype) 1 << 53)) + { + if ((UDItype) u & (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1)) + { + u &= ~ (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1); + u |= ((UDItype) 1 << ((sizeof (DItype) * 8) - 53)); + } + } + } + f = (USItype) (u >> (sizeof (SItype) * 8)); + f *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1)); + f += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1)); + + return (SFtype) f; +} + +DItype +__fixunstfdi (TFtype a) +{ + if (a < 0) + return 0; + + /* Compute high word of result, as a flonum. */ + const TFtype b = (a / (((UDItype) 1) << (sizeof (SItype) * 8))); + /* Convert that to fixed (but not to DItype!), + and shift it into the high word. */ + UDItype v = (USItype) b; + v <<= (sizeof (SItype) * 8); + /* Remove high part from the TFtype, leaving the low part as flonum. */ + a -= (TFtype) v; + /* Convert that to fixed (but not to DItype!) and add it in. + Sometimes A comes out negative. This is significant, since + A has more bits than a long int does. */ + if (a < 0) + v -= (USItype) (-a); + else + v += (USItype) a; + return v; +} + +/* This version is needed to prevent recursion; fixunsdfdi in libgcc + calls fixdfdi, which in turn calls calls fixunsdfdi. */ + +static DItype +local_fixunsdfdi (DFtype a) +{ + USItype hi, lo; + + hi = a / (((UDItype) 1) << (sizeof (SItype) * 8)); + lo = (a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (SItype) * 8))); + return ((UDItype) hi << (sizeof (SItype) * 8)) | lo; +} + +/* This version is needed to prevent recursion; fixunssfdi in libgcc + calls fixsfdi, which in turn calls calls fixunssfdi. */ + +static DItype +local_fixunssfdi (SFtype original_a) +{ + DFtype a = original_a; + USItype hi, lo; + + hi = a / (((UDItype) 1) << (sizeof (SItype) * 8)); + lo = (a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (SItype) * 8))); + return ((UDItype) hi << (sizeof (SItype) * 8)) | lo; +} + +#endif /* __powerpc64__ */ diff --git a/libgcc/config/rs6000/t-darwin b/libgcc/config/rs6000/t-darwin index 404df85870f..4464fd7d6e6 100644 --- a/libgcc/config/rs6000/t-darwin +++ b/libgcc/config/rs6000/t-darwin @@ -3,6 +3,8 @@ DARWIN_EXTRA_CRT_BUILD_CFLAGS = -mlongcall -mmacosx-version-min=10.4 crt2.o: $(srcdir)/config/rs6000/darwin-crt2.c $(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $< +LIB2ADD += $(srcdir)/config/rs6000/ppc64-fp.c + LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c SHLIB_VERPFX = $(gcc_srcdir)/config/rs6000/darwin-libgcc diff --git a/libgcc/config/rs6000/t-ppc64-fp b/libgcc/config/rs6000/t-ppc64-fp new file mode 100644 index 00000000000..26d1730bcdb --- /dev/null +++ b/libgcc/config/rs6000/t-ppc64-fp @@ -0,0 +1,2 @@ +# Can be used unconditionally, wrapped in __powerpc64__ || __64BIT__ __ppc64__. +LIB2ADD += $(srcdir)/config/rs6000/ppc64-fp.c diff --git a/libgcc/config/rx/rx-lib.h b/libgcc/config/rx/rx-lib.h new file mode 100644 index 00000000000..fb1d14632a6 --- /dev/null +++ b/libgcc/config/rx/rx-lib.h @@ -0,0 +1,6 @@ +#ifdef FLOAT +#ifndef __RX_64BIT_DOUBLES__ +#define DF SF +#define FLOAT_ONLY +#endif +#endif diff --git a/libgcc/config/rx/t-rx b/libgcc/config/rx/t-rx index 1e66af0c8d3..3ca7dc069fa 100644 --- a/libgcc/config/rx/t-rx +++ b/libgcc/config/rx/t-rx @@ -1,5 +1,5 @@ # Makefile fragment for building LIBGCC for the Renesas RX target. -# Copyright (C) 2008, 2009 Free Software Foundation, Inc. +# Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. # Contributed by Red Hat. # # This file is part of GCC. @@ -28,17 +28,7 @@ LIB2ADD = $(srcdir)/config/rx/rx-abi-functions.c # We need special handling of the floating point conversion # routines, to allow for the varying size of a double: -FPBIT = fp-bit.c -$(gcc_objdir)/fp-bit.c: $(gcc_srcdir)/config/fp-bit.c - echo '#define FLOAT' > $@ - echo '#ifndef __RX_64BIT_DOUBLES__' >> $@ - echo '#define DF SF' >> $@ - echo '#define FLOAT_ONLY' >> $@ - echo '#endif' >> $@ - cat $(gcc_srcdir)/config/fp-bit.c >> $@ - -DPBIT = dp-bit.c -$(gcc_objdir)/dp-bit.c: $(gcc_srcdir)/config/fp-bit.c - echo '#ifdef __RX_64BIT_DOUBLES__' > $@ - cat $(gcc_srcdir)/config/fp-bit.c >> $@ - echo '#endif' >> $@ +FPBIT = true +ifeq ($(double_type_size),64) +DPBIT = true +endif diff --git a/libgcc/config/sparc/t-softfp b/libgcc/config/sparc/t-softfp deleted file mode 100644 index 94dfcfae0a1..00000000000 --- a/libgcc/config/sparc/t-softfp +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC 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. -# -# GCC 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. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -# We want fine grained libraries, so use the new code to build the -# floating point emulation libraries. -FPBIT = fp-bit.c -DPBIT = dp-bit.c - -$(gcc_objdir)/dp-bit.c: $(gcc_srcdir)/config/fp-bit.c - cat $< > $@ - -$(gcc_objdir)/fp-bit.c: $(gcc_srcdir)/config/fp-bit.c - echo '#define FLOAT' > $@ - cat $< >> $@ diff --git a/libgcc/config/spu/t-elf b/libgcc/config/spu/t-elf new file mode 100644 index 00000000000..7094da526bb --- /dev/null +++ b/libgcc/config/spu/t-elf @@ -0,0 +1,3 @@ +# We provide our own version of __divdf3 that performs better and has +# better support for non-default rounding modes. +DPBIT_FUNCS := $(filter-out _div_df, $(DPBIT_FUNCS)) diff --git a/libgcc/config/t-fdpbit b/libgcc/config/t-fdpbit new file mode 100644 index 00000000000..0e7119adeaf --- /dev/null +++ b/libgcc/config/t-fdpbit @@ -0,0 +1,2 @@ +FPBIT = true +DPBIT = true diff --git a/libgcc/config/t-fpbit b/libgcc/config/t-fpbit new file mode 100644 index 00000000000..e56e34d91c8 --- /dev/null +++ b/libgcc/config/t-fpbit @@ -0,0 +1,2 @@ +FPBIT = true +FPBIT_CFLAGS = -DFLOAT_ONLY -DSMALL_MACHINE diff --git a/libgcc/configure b/libgcc/configure index 60363387312..0ead080691d 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -168,7 +168,8 @@ test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else @@ -551,6 +552,42 @@ PACKAGE_BUGREPORT='' PACKAGE_URL='http://www.gnu.org/software/libgcc/' ac_unique_file="static-object.mk" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + ac_subst_vars='LTLIBOBJS LIBOBJS asm_hidden_op @@ -563,6 +600,10 @@ vis_hide fixed_point enable_decimal_float decimal_float +long_double_type_size +double_type_size +EGREP +GREP CPP OBJEXT EXEEXT @@ -1464,6 +1505,255 @@ fi return $ac_retval } # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 <conftest.val; ac_retval=0 +else + ac_retval=1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f conftest.val + + fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_compute_int + +# ac_fn_c_check_header_preproc LINENO HEADER VAR +# ---------------------------------------------- +# Tests whether HEADER is present, setting the cache variable VAR accordingly. +ac_fn_c_check_header_preproc () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f conftest.err conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_preproc cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -3649,8 +3939,340 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_c_preproc_warn_flag=yes -# Check for decimal float support. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of double" >&5 +$as_echo_n "checking size of double... " >&6; } +if test "${ac_cv_sizeof_double+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_double" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (double) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_double=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_double" >&5 +$as_echo "$ac_cv_sizeof_double" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_DOUBLE $ac_cv_sizeof_double +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long double" >&5 +$as_echo_n "checking size of long double... " >&6; } +if test "${ac_cv_sizeof_long_double+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long double))" "ac_cv_sizeof_long_double" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long_double" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (long double) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_long_double=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_double" >&5 +$as_echo "$ac_cv_sizeof_long_double" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_DOUBLE $ac_cv_sizeof_long_double +_ACEOF + + +as_fn_arith $ac_cv_sizeof_double \* 8 && double_type_size=$as_val +as_fn_arith $ac_cv_sizeof_long_double \* 8 && long_double_type_size=$as_val + + + +# Check for decimal float support. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether decimal floating point is supported" >&5 $as_echo_n "checking whether decimal floating point is supported... " >&6; } if test "${libgcc_cv_dfp+set}" = set; then : diff --git a/libgcc/configure.ac b/libgcc/configure.ac index d96bcb4224a..8e2d1accd9d 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -152,6 +152,13 @@ GCC_NO_EXECUTABLES AC_PROG_CC AC_PROG_CPP_WERROR +AC_CHECK_SIZEOF([double]) +AC_CHECK_SIZEOF([long double]) +AS_VAR_ARITH([double_type_size], [$ac_cv_sizeof_double \* 8]) +AS_VAR_ARITH([long_double_type_size], [$ac_cv_sizeof_long_double \* 8]) +AC_SUBST(double_type_size) +AC_SUBST(long_double_type_size) + # Check for decimal float support. AC_CACHE_CHECK([whether decimal floating point is supported], [libgcc_cv_dfp], [AC_COMPILE_IFELSE([_Decimal32 x;], [libgcc_cv_dfp=yes], diff --git a/libgcc/fp-bit.c b/libgcc/fp-bit.c new file mode 100644 index 00000000000..de9b3ada5ec --- /dev/null +++ b/libgcc/fp-bit.c @@ -0,0 +1,1657 @@ +/* This is a software floating point library which can be used + for targets without hardware floating point. + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, + 2004, 2005, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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. + +GCC 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/>. */ + +/* This implements IEEE 754 format arithmetic, but does not provide a + mechanism for setting the rounding mode, or for generating or handling + exceptions. + + The original code by Steve Chamberlain, hacked by Mark Eichin and Jim + Wilson, all of Cygnus Support. */ + +/* The intended way to use this file is to make two copies, add `#define FLOAT' + to one copy, then compile both copies and add them to libgcc.a. */ + +#include "tconfig.h" +#include "coretypes.h" +#include "tm.h" +#include "fp-bit.h" + +/* The following macros can be defined to change the behavior of this file: + FLOAT: Implement a `float', aka SFmode, fp library. If this is not + defined, then this file implements a `double', aka DFmode, fp library. + FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e. + don't include float->double conversion which requires the double library. + This is useful only for machines which can't support doubles, e.g. some + 8-bit processors. + CMPtype: Specify the type that floating point compares should return. + This defaults to SItype, aka int. + _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding + two integers to the FLO_union_type. + NO_DENORMALS: Disable handling of denormals. + NO_NANS: Disable nan and infinity handling + SMALL_MACHINE: Useful when operations on QIs and HIs are faster + than on an SI */ + +/* We don't currently support extended floats (long doubles) on machines + without hardware to deal with them. + + These stubs are just to keep the linker from complaining about unresolved + references which can be pulled in from libio & libstdc++, even if the + user isn't using long doubles. However, they may generate an unresolved + external to abort if abort is not used by the function, and the stubs + are referenced from within libc, since libgcc goes before and after the + system library. */ + +#ifdef DECLARE_LIBRARY_RENAMES + DECLARE_LIBRARY_RENAMES +#endif + +#ifdef EXTENDED_FLOAT_STUBS +extern void abort (void); +void __extendsfxf2 (void) { abort(); } +void __extenddfxf2 (void) { abort(); } +void __truncxfdf2 (void) { abort(); } +void __truncxfsf2 (void) { abort(); } +void __fixxfsi (void) { abort(); } +void __floatsixf (void) { abort(); } +void __addxf3 (void) { abort(); } +void __subxf3 (void) { abort(); } +void __mulxf3 (void) { abort(); } +void __divxf3 (void) { abort(); } +void __negxf2 (void) { abort(); } +void __eqxf2 (void) { abort(); } +void __nexf2 (void) { abort(); } +void __gtxf2 (void) { abort(); } +void __gexf2 (void) { abort(); } +void __lexf2 (void) { abort(); } +void __ltxf2 (void) { abort(); } + +void __extendsftf2 (void) { abort(); } +void __extenddftf2 (void) { abort(); } +void __trunctfdf2 (void) { abort(); } +void __trunctfsf2 (void) { abort(); } +void __fixtfsi (void) { abort(); } +void __floatsitf (void) { abort(); } +void __addtf3 (void) { abort(); } +void __subtf3 (void) { abort(); } +void __multf3 (void) { abort(); } +void __divtf3 (void) { abort(); } +void __negtf2 (void) { abort(); } +void __eqtf2 (void) { abort(); } +void __netf2 (void) { abort(); } +void __gttf2 (void) { abort(); } +void __getf2 (void) { abort(); } +void __letf2 (void) { abort(); } +void __lttf2 (void) { abort(); } +#else /* !EXTENDED_FLOAT_STUBS, rest of file */ + +/* IEEE "special" number predicates */ + +#ifdef NO_NANS + +#define nan() 0 +#define isnan(x) 0 +#define isinf(x) 0 +#else + +#if defined L_thenan_sf +const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; +#elif defined L_thenan_df +const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} }; +#elif defined L_thenan_tf +const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; +#elif defined TFLOAT +extern const fp_number_type __thenan_tf; +#elif defined FLOAT +extern const fp_number_type __thenan_sf; +#else +extern const fp_number_type __thenan_df; +#endif + +INLINE +static const fp_number_type * +makenan (void) +{ +#ifdef TFLOAT + return & __thenan_tf; +#elif defined FLOAT + return & __thenan_sf; +#else + return & __thenan_df; +#endif +} + +INLINE +static int +isnan (const fp_number_type *x) +{ + return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN, + 0); +} + +INLINE +static int +isinf (const fp_number_type * x) +{ + return __builtin_expect (x->class == CLASS_INFINITY, 0); +} + +#endif /* NO_NANS */ + +INLINE +static int +iszero (const fp_number_type * x) +{ + return x->class == CLASS_ZERO; +} + +INLINE +static void +flip_sign ( fp_number_type * x) +{ + x->sign = !x->sign; +} + +/* Count leading zeroes in N. */ +INLINE +static int +clzusi (USItype n) +{ + extern int __clzsi2 (USItype); + if (sizeof (USItype) == sizeof (unsigned int)) + return __builtin_clz (n); + else if (sizeof (USItype) == sizeof (unsigned long)) + return __builtin_clzl (n); + else if (sizeof (USItype) == sizeof (unsigned long long)) + return __builtin_clzll (n); + else + return __clzsi2 (n); +} + +extern FLO_type pack_d (const fp_number_type * ); + +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf) +FLO_type +pack_d (const fp_number_type *src) +{ + FLO_union_type dst; + fractype fraction = src->fraction.ll; /* wasn't unsigned before? */ + int sign = src->sign; + int exp = 0; + + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src))) + { + /* We can't represent these values accurately. By using the + largest possible magnitude, we guarantee that the conversion + of infinity is at least as big as any finite number. */ + exp = EXPMAX; + fraction = ((fractype) 1 << FRACBITS) - 1; + } + else if (isnan (src)) + { + exp = EXPMAX; + if (src->class == CLASS_QNAN || 1) + { +#ifdef QUIET_NAN_NEGATED + fraction |= QUIET_NAN - 1; +#else + fraction |= QUIET_NAN; +#endif + } + } + else if (isinf (src)) + { + exp = EXPMAX; + fraction = 0; + } + else if (iszero (src)) + { + exp = 0; + fraction = 0; + } + else if (fraction == 0) + { + exp = 0; + } + else + { + if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0)) + { +#ifdef NO_DENORMALS + /* Go straight to a zero representation if denormals are not + supported. The denormal handling would be harmless but + isn't unnecessary. */ + exp = 0; + fraction = 0; +#else /* NO_DENORMALS */ + /* This number's exponent is too low to fit into the bits + available in the number, so we'll store 0 in the exponent and + shift the fraction to the right to make up for it. */ + + int shift = NORMAL_EXPMIN - src->normal_exp; + + exp = 0; + + if (shift > FRAC_NBITS - NGARDS) + { + /* No point shifting, since it's more that 64 out. */ + fraction = 0; + } + else + { + int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0; + fraction = (fraction >> shift) | lowbit; + } + if ((fraction & GARDMASK) == GARDMSB) + { + if ((fraction & (1 << NGARDS))) + fraction += GARDROUND + 1; + } + else + { + /* Add to the guards to round up. */ + fraction += GARDROUND; + } + /* Perhaps the rounding means we now need to change the + exponent, because the fraction is no longer denormal. */ + if (fraction >= IMPLICIT_1) + { + exp += 1; + } + fraction >>= NGARDS; +#endif /* NO_DENORMALS */ + } + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) + && __builtin_expect (src->normal_exp > EXPBIAS, 0)) + { + exp = EXPMAX; + fraction = 0; + } + else + { + exp = src->normal_exp + EXPBIAS; + if (!ROUND_TOWARDS_ZERO) + { + /* IF the gard bits are the all zero, but the first, then we're + half way between two numbers, choose the one which makes the + lsb of the answer 0. */ + if ((fraction & GARDMASK) == GARDMSB) + { + if (fraction & (1 << NGARDS)) + fraction += GARDROUND + 1; + } + else + { + /* Add a one to the guards to round up */ + fraction += GARDROUND; + } + if (fraction >= IMPLICIT_2) + { + fraction >>= 1; + exp += 1; + } + } + fraction >>= NGARDS; + + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX) + { + /* Saturate on overflow. */ + exp = EXPMAX; + fraction = ((fractype) 1 << FRACBITS) - 1; + } + } + } + + /* We previously used bitfields to store the number, but this doesn't + handle little/big endian systems conveniently, so use shifts and + masks */ +#ifdef FLOAT_BIT_ORDER_MISMATCH + dst.bits.fraction = fraction; + dst.bits.exp = exp; + dst.bits.sign = sign; +#else +# if defined TFLOAT && defined HALFFRACBITS + { + halffractype high, low, unity; + int lowsign, lowexp; + + unity = (halffractype) 1 << HALFFRACBITS; + + /* Set HIGH to the high double's significand, masking out the implicit 1. + Set LOW to the low double's full significand. */ + high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1); + low = fraction & (unity * 2 - 1); + + /* Get the initial sign and exponent of the low double. */ + lowexp = exp - HALFFRACBITS - 1; + lowsign = sign; + + /* HIGH should be rounded like a normal double, making |LOW| <= + 0.5 ULP of HIGH. Assume round-to-nearest. */ + if (exp < EXPMAX) + if (low > unity || (low == unity && (high & 1) == 1)) + { + /* Round HIGH up and adjust LOW to match. */ + high++; + if (high == unity) + { + /* May make it infinite, but that's OK. */ + high = 0; + exp++; + } + low = unity * 2 - low; + lowsign ^= 1; + } + + high |= (halffractype) exp << HALFFRACBITS; + high |= (halffractype) sign << (HALFFRACBITS + EXPBITS); + + if (exp == EXPMAX || exp == 0 || low == 0) + low = 0; + else + { + while (lowexp > 0 && low < unity) + { + low <<= 1; + lowexp--; + } + + if (lowexp <= 0) + { + halffractype roundmsb, round; + int shift; + + shift = 1 - lowexp; + roundmsb = (1 << (shift - 1)); + round = low & ((roundmsb << 1) - 1); + + low >>= shift; + lowexp = 0; + + if (round > roundmsb || (round == roundmsb && (low & 1) == 1)) + { + low++; + if (low == unity) + /* LOW rounds up to the smallest normal number. */ + lowexp++; + } + } + + low &= unity - 1; + low |= (halffractype) lowexp << HALFFRACBITS; + low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS); + } + dst.value_raw = ((fractype) high << HALFSHIFT) | low; + } +# else + dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1); + dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS; + dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS); +# endif +#endif + +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) +#ifdef TFLOAT + { + qrtrfractype tmp1 = dst.words[0]; + qrtrfractype tmp2 = dst.words[1]; + dst.words[0] = dst.words[3]; + dst.words[1] = dst.words[2]; + dst.words[2] = tmp2; + dst.words[3] = tmp1; + } +#else + { + halffractype tmp = dst.words[0]; + dst.words[0] = dst.words[1]; + dst.words[1] = tmp; + } +#endif +#endif + + return dst.value; +} +#endif + +#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf) +void +unpack_d (FLO_union_type * src, fp_number_type * dst) +{ + /* We previously used bitfields to store the number, but this doesn't + handle little/big endian systems conveniently, so use shifts and + masks */ + fractype fraction; + int exp; + int sign; + +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) + FLO_union_type swapped; + +#ifdef TFLOAT + swapped.words[0] = src->words[3]; + swapped.words[1] = src->words[2]; + swapped.words[2] = src->words[1]; + swapped.words[3] = src->words[0]; +#else + swapped.words[0] = src->words[1]; + swapped.words[1] = src->words[0]; +#endif + src = &swapped; +#endif + +#ifdef FLOAT_BIT_ORDER_MISMATCH + fraction = src->bits.fraction; + exp = src->bits.exp; + sign = src->bits.sign; +#else +# if defined TFLOAT && defined HALFFRACBITS + { + halffractype high, low; + + high = src->value_raw >> HALFSHIFT; + low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1); + + fraction = high & ((((fractype)1) << HALFFRACBITS) - 1); + fraction <<= FRACBITS - HALFFRACBITS; + exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); + sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1; + + if (exp != EXPMAX && exp != 0 && low != 0) + { + int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); + int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1; + int shift; + fractype xlow; + + xlow = low & ((((fractype)1) << HALFFRACBITS) - 1); + if (lowexp) + xlow |= (((halffractype)1) << HALFFRACBITS); + else + lowexp = 1; + shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp); + if (shift > 0) + xlow <<= shift; + else if (shift < 0) + xlow >>= -shift; + if (sign == lowsign) + fraction += xlow; + else if (fraction >= xlow) + fraction -= xlow; + else + { + /* The high part is a power of two but the full number is lower. + This code will leave the implicit 1 in FRACTION, but we'd + have added that below anyway. */ + fraction = (((fractype) 1 << FRACBITS) - xlow) << 1; + exp--; + } + } + } +# else + fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1); + exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1); + sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1; +# endif +#endif + + dst->sign = sign; + if (exp == 0) + { + /* Hmm. Looks like 0 */ + if (fraction == 0 +#ifdef NO_DENORMALS + || 1 +#endif + ) + { + /* tastes like zero */ + dst->class = CLASS_ZERO; + } + else + { + /* Zero exponent with nonzero fraction - it's denormalized, + so there isn't a leading implicit one - we'll shift it so + it gets one. */ + dst->normal_exp = exp - EXPBIAS + 1; + fraction <<= NGARDS; + + dst->class = CLASS_NUMBER; +#if 1 + while (fraction < IMPLICIT_1) + { + fraction <<= 1; + dst->normal_exp--; + } +#endif + dst->fraction.ll = fraction; + } + } + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) + && __builtin_expect (exp == EXPMAX, 0)) + { + /* Huge exponent*/ + if (fraction == 0) + { + /* Attached to a zero fraction - means infinity */ + dst->class = CLASS_INFINITY; + } + else + { + /* Nonzero fraction, means nan */ +#ifdef QUIET_NAN_NEGATED + if ((fraction & QUIET_NAN) == 0) +#else + if (fraction & QUIET_NAN) +#endif + { + dst->class = CLASS_QNAN; + } + else + { + dst->class = CLASS_SNAN; + } + /* Keep the fraction part as the nan number */ + dst->fraction.ll = fraction; + } + } + else + { + /* Nothing strange about this number */ + dst->normal_exp = exp - EXPBIAS; + dst->class = CLASS_NUMBER; + dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1; + } +} +#endif /* L_unpack_df || L_unpack_sf */ + +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf) +static const fp_number_type * +_fpadd_parts (fp_number_type * a, + fp_number_type * b, + fp_number_type * tmp) +{ + intfrac tfraction; + + /* Put commonly used fields in local variables. */ + int a_normal_exp; + int b_normal_exp; + fractype a_fraction; + fractype b_fraction; + + if (isnan (a)) + { + return a; + } + if (isnan (b)) + { + return b; + } + if (isinf (a)) + { + /* Adding infinities with opposite signs yields a NaN. */ + if (isinf (b) && a->sign != b->sign) + return makenan (); + return a; + } + if (isinf (b)) + { + return b; + } + if (iszero (b)) + { + if (iszero (a)) + { + *tmp = *a; + tmp->sign = a->sign & b->sign; + return tmp; + } + return a; + } + if (iszero (a)) + { + return b; + } + + /* Got two numbers. shift the smaller and increment the exponent till + they're the same */ + { + int diff; + int sdiff; + + a_normal_exp = a->normal_exp; + b_normal_exp = b->normal_exp; + a_fraction = a->fraction.ll; + b_fraction = b->fraction.ll; + + diff = a_normal_exp - b_normal_exp; + sdiff = diff; + + if (diff < 0) + diff = -diff; + if (diff < FRAC_NBITS) + { + if (sdiff > 0) + { + b_normal_exp += diff; + LSHIFT (b_fraction, diff); + } + else if (sdiff < 0) + { + a_normal_exp += diff; + LSHIFT (a_fraction, diff); + } + } + else + { + /* Somethings's up.. choose the biggest */ + if (a_normal_exp > b_normal_exp) + { + b_normal_exp = a_normal_exp; + b_fraction = 0; + } + else + { + a_normal_exp = b_normal_exp; + a_fraction = 0; + } + } + } + + if (a->sign != b->sign) + { + if (a->sign) + { + tfraction = -a_fraction + b_fraction; + } + else + { + tfraction = a_fraction - b_fraction; + } + if (tfraction >= 0) + { + tmp->sign = 0; + tmp->normal_exp = a_normal_exp; + tmp->fraction.ll = tfraction; + } + else + { + tmp->sign = 1; + tmp->normal_exp = a_normal_exp; + tmp->fraction.ll = -tfraction; + } + /* and renormalize it */ + + while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll) + { + tmp->fraction.ll <<= 1; + tmp->normal_exp--; + } + } + else + { + tmp->sign = a->sign; + tmp->normal_exp = a_normal_exp; + tmp->fraction.ll = a_fraction + b_fraction; + } + tmp->class = CLASS_NUMBER; + /* Now the fraction is added, we have to shift down to renormalize the + number */ + + if (tmp->fraction.ll >= IMPLICIT_2) + { + LSHIFT (tmp->fraction.ll, 1); + tmp->normal_exp++; + } + return tmp; +} + +FLO_type +add (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + fp_number_type tmp; + const fp_number_type *res; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + res = _fpadd_parts (&a, &b, &tmp); + + return pack_d (res); +} + +FLO_type +sub (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + fp_number_type tmp; + const fp_number_type *res; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + b.sign ^= 1; + + res = _fpadd_parts (&a, &b, &tmp); + + return pack_d (res); +} +#endif /* L_addsub_sf || L_addsub_df */ + +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf) +static inline __attribute__ ((__always_inline__)) const fp_number_type * +_fpmul_parts ( fp_number_type * a, + fp_number_type * b, + fp_number_type * tmp) +{ + fractype low = 0; + fractype high = 0; + + if (isnan (a)) + { + a->sign = a->sign != b->sign; + return a; + } + if (isnan (b)) + { + b->sign = a->sign != b->sign; + return b; + } + if (isinf (a)) + { + if (iszero (b)) + return makenan (); + a->sign = a->sign != b->sign; + return a; + } + if (isinf (b)) + { + if (iszero (a)) + { + return makenan (); + } + b->sign = a->sign != b->sign; + return b; + } + if (iszero (a)) + { + a->sign = a->sign != b->sign; + return a; + } + if (iszero (b)) + { + b->sign = a->sign != b->sign; + return b; + } + + /* Calculate the mantissa by multiplying both numbers to get a + twice-as-wide number. */ + { +#if defined(NO_DI_MODE) || defined(TFLOAT) + { + fractype x = a->fraction.ll; + fractype ylow = b->fraction.ll; + fractype yhigh = 0; + int bit; + + /* ??? This does multiplies one bit at a time. Optimize. */ + for (bit = 0; bit < FRAC_NBITS; bit++) + { + int carry; + + if (x & 1) + { + carry = (low += ylow) < ylow; + high += yhigh + carry; + } + yhigh <<= 1; + if (ylow & FRACHIGH) + { + yhigh |= 1; + } + ylow <<= 1; + x >>= 1; + } + } +#elif defined(FLOAT) + /* Multiplying two USIs to get a UDI, we're safe. */ + { + UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll; + + high = answer >> BITS_PER_SI; + low = answer; + } +#else + /* fractype is DImode, but we need the result to be twice as wide. + Assuming a widening multiply from DImode to TImode is not + available, build one by hand. */ + { + USItype nl = a->fraction.ll; + USItype nh = a->fraction.ll >> BITS_PER_SI; + USItype ml = b->fraction.ll; + USItype mh = b->fraction.ll >> BITS_PER_SI; + UDItype pp_ll = (UDItype) ml * nl; + UDItype pp_hl = (UDItype) mh * nl; + UDItype pp_lh = (UDItype) ml * nh; + UDItype pp_hh = (UDItype) mh * nh; + UDItype res2 = 0; + UDItype res0 = 0; + UDItype ps_hh__ = pp_hl + pp_lh; + if (ps_hh__ < pp_hl) + res2 += (UDItype)1 << BITS_PER_SI; + pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI; + res0 = pp_ll + pp_hl; + if (res0 < pp_ll) + res2++; + res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh; + high = res2; + low = res0; + } +#endif + } + + tmp->normal_exp = a->normal_exp + b->normal_exp + + FRAC_NBITS - (FRACBITS + NGARDS); + tmp->sign = a->sign != b->sign; + while (high >= IMPLICIT_2) + { + tmp->normal_exp++; + if (high & 1) + { + low >>= 1; + low |= FRACHIGH; + } + high >>= 1; + } + while (high < IMPLICIT_1) + { + tmp->normal_exp--; + + high <<= 1; + if (low & FRACHIGH) + high |= 1; + low <<= 1; + } + + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB) + { + if (high & (1 << NGARDS)) + { + /* Because we're half way, we would round to even by adding + GARDROUND + 1, except that's also done in the packing + function, and rounding twice will lose precision and cause + the result to be too far off. Example: 32-bit floats with + bit patterns 0xfff * 0x3f800400 ~= 0xfff (less than 0.5ulp + off), not 0x1000 (more than 0.5ulp off). */ + } + else if (low) + { + /* We're a further than half way by a small amount corresponding + to the bits set in "low". Knowing that, we round here and + not in pack_d, because there we don't have "low" available + anymore. */ + high += GARDROUND + 1; + + /* Avoid further rounding in pack_d. */ + high &= ~(fractype) GARDMASK; + } + } + tmp->fraction.ll = high; + tmp->class = CLASS_NUMBER; + return tmp; +} + +FLO_type +multiply (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + fp_number_type tmp; + const fp_number_type *res; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + res = _fpmul_parts (&a, &b, &tmp); + + return pack_d (res); +} +#endif /* L_mul_sf || L_mul_df || L_mul_tf */ + +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf) +static inline __attribute__ ((__always_inline__)) const fp_number_type * +_fpdiv_parts (fp_number_type * a, + fp_number_type * b) +{ + fractype bit; + fractype numerator; + fractype denominator; + fractype quotient; + + if (isnan (a)) + { + return a; + } + if (isnan (b)) + { + return b; + } + + a->sign = a->sign ^ b->sign; + + if (isinf (a) || iszero (a)) + { + if (a->class == b->class) + return makenan (); + return a; + } + + if (isinf (b)) + { + a->fraction.ll = 0; + a->normal_exp = 0; + return a; + } + if (iszero (b)) + { + a->class = CLASS_INFINITY; + return a; + } + + /* Calculate the mantissa by multiplying both 64bit numbers to get a + 128 bit number */ + { + /* quotient = + ( numerator / denominator) * 2^(numerator exponent - denominator exponent) + */ + + a->normal_exp = a->normal_exp - b->normal_exp; + numerator = a->fraction.ll; + denominator = b->fraction.ll; + + if (numerator < denominator) + { + /* Fraction will be less than 1.0 */ + numerator *= 2; + a->normal_exp--; + } + bit = IMPLICIT_1; + quotient = 0; + /* ??? Does divide one bit at a time. Optimize. */ + while (bit) + { + if (numerator >= denominator) + { + quotient |= bit; + numerator -= denominator; + } + bit >>= 1; + numerator *= 2; + } + + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB) + { + if (quotient & (1 << NGARDS)) + { + /* Because we're half way, we would round to even by adding + GARDROUND + 1, except that's also done in the packing + function, and rounding twice will lose precision and cause + the result to be too far off. */ + } + else if (numerator) + { + /* We're a further than half way by the small amount + corresponding to the bits set in "numerator". Knowing + that, we round here and not in pack_d, because there we + don't have "numerator" available anymore. */ + quotient += GARDROUND + 1; + + /* Avoid further rounding in pack_d. */ + quotient &= ~(fractype) GARDMASK; + } + } + + a->fraction.ll = quotient; + return (a); + } +} + +FLO_type +divide (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + const fp_number_type *res; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + res = _fpdiv_parts (&a, &b); + + return pack_d (res); +} +#endif /* L_div_sf || L_div_df */ + +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \ + || defined(L_fpcmp_parts_tf) +/* according to the demo, fpcmp returns a comparison with 0... thus + a<b -> -1 + a==b -> 0 + a>b -> +1 + */ + +int +__fpcmp_parts (fp_number_type * a, fp_number_type * b) +{ +#if 0 + /* either nan -> unordered. Must be checked outside of this routine. */ + if (isnan (a) && isnan (b)) + { + return 1; /* still unordered! */ + } +#endif + + if (isnan (a) || isnan (b)) + { + return 1; /* how to indicate unordered compare? */ + } + if (isinf (a) && isinf (b)) + { + /* +inf > -inf, but +inf != +inf */ + /* b \a| +inf(0)| -inf(1) + ______\+--------+-------- + +inf(0)| a==b(0)| a<b(-1) + -------+--------+-------- + -inf(1)| a>b(1) | a==b(0) + -------+--------+-------- + So since unordered must be nonzero, just line up the columns... + */ + return b->sign - a->sign; + } + /* but not both... */ + if (isinf (a)) + { + return a->sign ? -1 : 1; + } + if (isinf (b)) + { + return b->sign ? 1 : -1; + } + if (iszero (a) && iszero (b)) + { + return 0; + } + if (iszero (a)) + { + return b->sign ? 1 : -1; + } + if (iszero (b)) + { + return a->sign ? -1 : 1; + } + /* now both are "normal". */ + if (a->sign != b->sign) + { + /* opposite signs */ + return a->sign ? -1 : 1; + } + /* same sign; exponents? */ + if (a->normal_exp > b->normal_exp) + { + return a->sign ? -1 : 1; + } + if (a->normal_exp < b->normal_exp) + { + return a->sign ? 1 : -1; + } + /* same exponents; check size. */ + if (a->fraction.ll > b->fraction.ll) + { + return a->sign ? -1 : 1; + } + if (a->fraction.ll < b->fraction.ll) + { + return a->sign ? 1 : -1; + } + /* after all that, they're equal. */ + return 0; +} +#endif + +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf) +CMPtype +compare (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + return __fpcmp_parts (&a, &b); +} +#endif /* L_compare_sf || L_compare_df */ + +/* These should be optimized for their specific tasks someday. */ + +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf) +CMPtype +_eq_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + if (isnan (&a) || isnan (&b)) + return 1; /* false, truth == 0 */ + + return __fpcmp_parts (&a, &b) ; +} +#endif /* L_eq_sf || L_eq_df */ + +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf) +CMPtype +_ne_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + if (isnan (&a) || isnan (&b)) + return 1; /* true, truth != 0 */ + + return __fpcmp_parts (&a, &b) ; +} +#endif /* L_ne_sf || L_ne_df */ + +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf) +CMPtype +_gt_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + if (isnan (&a) || isnan (&b)) + return -1; /* false, truth > 0 */ + + return __fpcmp_parts (&a, &b); +} +#endif /* L_gt_sf || L_gt_df */ + +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf) +CMPtype +_ge_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + if (isnan (&a) || isnan (&b)) + return -1; /* false, truth >= 0 */ + return __fpcmp_parts (&a, &b) ; +} +#endif /* L_ge_sf || L_ge_df */ + +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf) +CMPtype +_lt_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + if (isnan (&a) || isnan (&b)) + return 1; /* false, truth < 0 */ + + return __fpcmp_parts (&a, &b); +} +#endif /* L_lt_sf || L_lt_df */ + +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf) +CMPtype +_le_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + if (isnan (&a) || isnan (&b)) + return 1; /* false, truth <= 0 */ + + return __fpcmp_parts (&a, &b) ; +} +#endif /* L_le_sf || L_le_df */ + +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf) +CMPtype +_unord_f2 (FLO_type arg_a, FLO_type arg_b) +{ + fp_number_type a; + fp_number_type b; + FLO_union_type au, bu; + + au.value = arg_a; + bu.value = arg_b; + + unpack_d (&au, &a); + unpack_d (&bu, &b); + + return (isnan (&a) || isnan (&b)); +} +#endif /* L_unord_sf || L_unord_df */ + +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf) +FLO_type +si_to_float (SItype arg_a) +{ + fp_number_type in; + + in.class = CLASS_NUMBER; + in.sign = arg_a < 0; + if (!arg_a) + { + in.class = CLASS_ZERO; + } + else + { + USItype uarg; + int shift; + in.normal_exp = FRACBITS + NGARDS; + if (in.sign) + { + /* Special case for minint, since there is no +ve integer + representation for it */ + if (arg_a == (- MAX_SI_INT - 1)) + { + return (FLO_type)(- MAX_SI_INT - 1); + } + uarg = (-arg_a); + } + else + uarg = arg_a; + + in.fraction.ll = uarg; + shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS); + if (shift > 0) + { + in.fraction.ll <<= shift; + in.normal_exp -= shift; + } + } + return pack_d (&in); +} +#endif /* L_si_to_sf || L_si_to_df */ + +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf) +FLO_type +usi_to_float (USItype arg_a) +{ + fp_number_type in; + + in.sign = 0; + if (!arg_a) + { + in.class = CLASS_ZERO; + } + else + { + int shift; + in.class = CLASS_NUMBER; + in.normal_exp = FRACBITS + NGARDS; + in.fraction.ll = arg_a; + + shift = clzusi (arg_a) - (BITS_PER_SI - 1 - FRACBITS - NGARDS); + if (shift < 0) + { + fractype guard = in.fraction.ll & (((fractype)1 << -shift) - 1); + in.fraction.ll >>= -shift; + in.fraction.ll |= (guard != 0); + in.normal_exp -= shift; + } + else if (shift > 0) + { + in.fraction.ll <<= shift; + in.normal_exp -= shift; + } + } + return pack_d (&in); +} +#endif + +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si) +SItype +float_to_si (FLO_type arg_a) +{ + fp_number_type a; + SItype tmp; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &a); + + if (iszero (&a)) + return 0; + if (isnan (&a)) + return 0; + /* get reasonable MAX_SI_INT... */ + if (isinf (&a)) + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; + /* it is a number, but a small one */ + if (a.normal_exp < 0) + return 0; + if (a.normal_exp > BITS_PER_SI - 2) + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; + tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); + return a.sign ? (-tmp) : (tmp); +} +#endif /* L_sf_to_si || L_df_to_si */ + +#if defined(L_tf_to_usi) +USItype +float_to_usi (FLO_type arg_a) +{ + fp_number_type a; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &a); + + if (iszero (&a)) + return 0; + if (isnan (&a)) + return 0; + /* it is a negative number */ + if (a.sign) + return 0; + /* get reasonable MAX_USI_INT... */ + if (isinf (&a)) + return MAX_USI_INT; + /* it is a number, but a small one */ + if (a.normal_exp < 0) + return 0; + if (a.normal_exp > BITS_PER_SI - 1) + return MAX_USI_INT; + else if (a.normal_exp > (FRACBITS + NGARDS)) + return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS)); + else + return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); +} +#endif /* L_tf_to_usi */ + +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf) +FLO_type +negate (FLO_type arg_a) +{ + fp_number_type a; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &a); + + flip_sign (&a); + return pack_d (&a); +} +#endif /* L_negate_sf || L_negate_df */ + +#ifdef FLOAT + +#if defined(L_make_sf) +SFtype +__make_fp(fp_class_type class, + unsigned int sign, + int exp, + USItype frac) +{ + fp_number_type in; + + in.class = class; + in.sign = sign; + in.normal_exp = exp; + in.fraction.ll = frac; + return pack_d (&in); +} +#endif /* L_make_sf */ + +#ifndef FLOAT_ONLY + +/* This enables one to build an fp library that supports float but not double. + Otherwise, we would get an undefined reference to __make_dp. + This is needed for some 8-bit ports that can't handle well values that + are 8-bytes in size, so we just don't support double for them at all. */ + +#if defined(L_sf_to_df) +DFtype +sf_to_df (SFtype arg_a) +{ + fp_number_type in; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + return __make_dp (in.class, in.sign, in.normal_exp, + ((UDItype) in.fraction.ll) << F_D_BITOFF); +} +#endif /* L_sf_to_df */ + +#if defined(L_sf_to_tf) && defined(TMODES) +TFtype +sf_to_tf (SFtype arg_a) +{ + fp_number_type in; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + return __make_tp (in.class, in.sign, in.normal_exp, + ((UTItype) in.fraction.ll) << F_T_BITOFF); +} +#endif /* L_sf_to_df */ + +#endif /* ! FLOAT_ONLY */ +#endif /* FLOAT */ + +#ifndef FLOAT + +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); + +#if defined(L_make_df) +DFtype +__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac) +{ + fp_number_type in; + + in.class = class; + in.sign = sign; + in.normal_exp = exp; + in.fraction.ll = frac; + return pack_d (&in); +} +#endif /* L_make_df */ + +#if defined(L_df_to_sf) +SFtype +df_to_sf (DFtype arg_a) +{ + fp_number_type in; + USItype sffrac; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + sffrac = in.fraction.ll >> F_D_BITOFF; + + /* We set the lowest guard bit in SFFRAC if we discarded any non + zero bits. */ + if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0) + sffrac |= 1; + + return __make_fp (in.class, in.sign, in.normal_exp, sffrac); +} +#endif /* L_df_to_sf */ + +#if defined(L_df_to_tf) && defined(TMODES) \ + && !defined(FLOAT) && !defined(TFLOAT) +TFtype +df_to_tf (DFtype arg_a) +{ + fp_number_type in; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + return __make_tp (in.class, in.sign, in.normal_exp, + ((UTItype) in.fraction.ll) << D_T_BITOFF); +} +#endif /* L_sf_to_df */ + +#ifdef TFLOAT +#if defined(L_make_tf) +TFtype +__make_tp(fp_class_type class, + unsigned int sign, + int exp, + UTItype frac) +{ + fp_number_type in; + + in.class = class; + in.sign = sign; + in.normal_exp = exp; + in.fraction.ll = frac; + return pack_d (&in); +} +#endif /* L_make_tf */ + +#if defined(L_tf_to_df) +DFtype +tf_to_df (TFtype arg_a) +{ + fp_number_type in; + UDItype sffrac; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + sffrac = in.fraction.ll >> D_T_BITOFF; + + /* We set the lowest guard bit in SFFRAC if we discarded any non + zero bits. */ + if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0) + sffrac |= 1; + + return __make_dp (in.class, in.sign, in.normal_exp, sffrac); +} +#endif /* L_tf_to_df */ + +#if defined(L_tf_to_sf) +SFtype +tf_to_sf (TFtype arg_a) +{ + fp_number_type in; + USItype sffrac; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + sffrac = in.fraction.ll >> F_T_BITOFF; + + /* We set the lowest guard bit in SFFRAC if we discarded any non + zero bits. */ + if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0) + sffrac |= 1; + + return __make_fp (in.class, in.sign, in.normal_exp, sffrac); +} +#endif /* L_tf_to_sf */ +#endif /* TFLOAT */ + +#endif /* ! FLOAT */ +#endif /* !EXTENDED_FLOAT_STUBS */ diff --git a/libgcc/fp-bit.h b/libgcc/fp-bit.h new file mode 100644 index 00000000000..1ae0741d6af --- /dev/null +++ b/libgcc/fp-bit.h @@ -0,0 +1,507 @@ +/* Header file for fp-bit.c. */ +/* Copyright (C) 2000, 2002, 2003, 2006, 2009, 2010, 2011 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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. + +GCC 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/>. */ + +#ifndef GCC_FP_BIT_H +#define GCC_FP_BIT_H + +/* Defining FINE_GRAINED_LIBRARIES allows one to select which routines + from this file are compiled via additional -D options. + + This avoids the need to pull in the entire fp emulation library + when only a small number of functions are needed. + + If FINE_GRAINED_LIBRARIES is not defined, then compile every + suitable routine. */ +#ifndef FINE_GRAINED_LIBRARIES +#define L_pack_df +#define L_unpack_df +#define L_pack_sf +#define L_unpack_sf +#define L_addsub_sf +#define L_addsub_df +#define L_mul_sf +#define L_mul_df +#define L_div_sf +#define L_div_df +#define L_fpcmp_parts_sf +#define L_fpcmp_parts_df +#define L_compare_sf +#define L_compare_df +#define L_eq_sf +#define L_eq_df +#define L_ne_sf +#define L_ne_df +#define L_gt_sf +#define L_gt_df +#define L_ge_sf +#define L_ge_df +#define L_lt_sf +#define L_lt_df +#define L_le_sf +#define L_le_df +#define L_unord_sf +#define L_unord_df +#define L_usi_to_sf +#define L_usi_to_df +#define L_si_to_sf +#define L_si_to_df +#define L_sf_to_si +#define L_df_to_si +#define L_f_to_usi +#define L_df_to_usi +#define L_negate_sf +#define L_negate_df +#define L_make_sf +#define L_make_df +#define L_sf_to_df +#define L_df_to_sf +#ifdef FLOAT +#define L_thenan_sf +#else +#define L_thenan_df +#endif +#endif /* ! FINE_GRAINED_LIBRARIES */ + +#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106 +# if defined(TFLOAT) || defined(L_sf_to_tf) || defined(L_df_to_tf) +# define TMODES +# endif +#endif + +typedef float SFtype __attribute__ ((mode (SF))); +typedef float DFtype __attribute__ ((mode (DF))); +#ifdef TMODES +typedef float TFtype __attribute__ ((mode (TF))); +#endif + +typedef int HItype __attribute__ ((mode (HI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +#ifdef TMODES +typedef int TItype __attribute__ ((mode (TI))); +#endif + +/* The type of the result of a floating point comparison. This must + match `__libgcc_cmp_return__' in GCC for the target. */ +#ifndef CMPtype +typedef int CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); +#endif + +typedef unsigned int UHItype __attribute__ ((mode (HI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#ifdef TMODES +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#endif + +#define MAX_USI_INT (~(USItype)0) +#define MAX_SI_INT ((SItype) (MAX_USI_INT >> 1)) +#define BITS_PER_SI (4 * BITS_PER_UNIT) +#ifdef TMODES +#define MAX_UDI_INT (~(UDItype)0) +#define MAX_DI_INT ((DItype) (MAX_UDI_INT >> 1)) +#define BITS_PER_DI (8 * BITS_PER_UNIT) +#endif + +#ifdef FLOAT_ONLY +#define NO_DI_MODE +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define FLOAT_BIT_ORDER_MISMATCH +#endif + +#if __BYTE_ORDER__ != __FLOAT_WORD_ORDER__ +#define FLOAT_WORD_ORDER_MISMATCH +#endif + +#ifdef TFLOAT +# ifndef TMODES +# error "TFLOAT requires long double to have 113 bits of mantissa" +# endif + +# define PREFIXFPDP tp +# define PREFIXSFDF tf +# define NGARDS 10L /* Is this right? */ +# define GARDROUND 0x1ff +# define GARDMASK 0x3ff +# define GARDMSB 0x200 +# define FRAC_NBITS 128 + +# if __LDBL_MANT_DIG__ == 113 /* IEEE quad */ +# define EXPBITS 15 +# define EXPBIAS 16383 +# define EXPMAX (0x7fff) +# define QUIET_NAN ((TItype)0x8 << 108) +# define FRACHIGH ((TItype)0x8 << 124) +# define FRACHIGH2 ((TItype)0xc << 124) +# define FRACBITS 112 +# endif + +# if __LDBL_MANT_DIG__ == 106 /* IBM extended (double+double) */ +# define EXPBITS 11 +# define EXPBIAS 1023 +# define EXPMAX (0x7ff) +# define QUIET_NAN ((TItype)0x8 << (48 + 64)) +# define FRACHIGH ((TItype)0x8 << 124) +# define FRACHIGH2 ((TItype)0xc << 124) +# define FRACBITS 105 +# define HALFFRACBITS 52 +# define HALFSHIFT 64 +# endif + +# define pack_d __pack_t +# define unpack_d __unpack_t +# define __fpcmp_parts __fpcmp_parts_t + typedef UTItype fractype; + typedef UDItype halffractype; + typedef USItype qrtrfractype; +#define qrtrfractype qrtrfractype + typedef TFtype FLO_type; + typedef TItype intfrac; +#elif defined FLOAT +# define NGARDS 7L +# define GARDROUND 0x3f +# define GARDMASK 0x7f +# define GARDMSB 0x40 +# define EXPBITS 8 +# define EXPBIAS 127 +# define FRACBITS 23 +# define EXPMAX (0xff) +# define QUIET_NAN 0x100000L +# define FRAC_NBITS 32 +# define FRACHIGH 0x80000000L +# define FRACHIGH2 0xc0000000L +# define pack_d __pack_f +# define unpack_d __unpack_f +# define __fpcmp_parts __fpcmp_parts_f + typedef USItype fractype; + typedef UHItype halffractype; + typedef SFtype FLO_type; + typedef SItype intfrac; + +#else +# define PREFIXFPDP dp +# define PREFIXSFDF df +# define NGARDS 8L +# define GARDROUND 0x7f +# define GARDMASK 0xff +# define GARDMSB 0x80 +# define EXPBITS 11 +# define EXPBIAS 1023 +# define FRACBITS 52 +# define EXPMAX (0x7ff) +# define QUIET_NAN 0x8000000000000LL +# define FRAC_NBITS 64 +# define FRACHIGH 0x8000000000000000LL +# define FRACHIGH2 0xc000000000000000LL +# define pack_d __pack_d +# define unpack_d __unpack_d +# define __fpcmp_parts __fpcmp_parts_d + typedef UDItype fractype; + typedef USItype halffractype; + typedef DFtype FLO_type; + typedef DItype intfrac; +#endif /* FLOAT */ + +#ifdef TFLOAT +# define add __addtf3 +# define sub __subtf3 +# define multiply __multf3 +# define divide __divtf3 +# define compare __cmptf2 +# define _eq_f2 __eqtf2 +# define _ne_f2 __netf2 +# define _gt_f2 __gttf2 +# define _ge_f2 __getf2 +# define _lt_f2 __lttf2 +# define _le_f2 __letf2 +# define _unord_f2 __unordtf2 +# define usi_to_float __floatunsitf +# define si_to_float __floatsitf +# define float_to_si __fixtfsi +# define float_to_usi __fixunstfsi +# define negate __negtf2 +# define tf_to_sf __trunctfsf2 +# define tf_to_df __trunctfdf2 +#elif defined FLOAT +# define add __addsf3 +# define sub __subsf3 +# define multiply __mulsf3 +# define divide __divsf3 +# define compare __cmpsf2 +# define _eq_f2 __eqsf2 +# define _ne_f2 __nesf2 +# define _gt_f2 __gtsf2 +# define _ge_f2 __gesf2 +# define _lt_f2 __ltsf2 +# define _le_f2 __lesf2 +# define _unord_f2 __unordsf2 +# define usi_to_float __floatunsisf +# define si_to_float __floatsisf +# define float_to_si __fixsfsi +# define float_to_usi __fixunssfsi +# define negate __negsf2 +# define sf_to_df __extendsfdf2 +# define sf_to_tf __extendsftf2 +#else +# define add __adddf3 +# define sub __subdf3 +# define multiply __muldf3 +# define divide __divdf3 +# define compare __cmpdf2 +# define _eq_f2 __eqdf2 +# define _ne_f2 __nedf2 +# define _gt_f2 __gtdf2 +# define _ge_f2 __gedf2 +# define _lt_f2 __ltdf2 +# define _le_f2 __ledf2 +# define _unord_f2 __unorddf2 +# define usi_to_float __floatunsidf +# define si_to_float __floatsidf +# define float_to_si __fixdfsi +# define float_to_usi __fixunsdfsi +# define negate __negdf2 +# define df_to_sf __truncdfsf2 +# define df_to_tf __extenddftf2 +#endif /* FLOAT */ + +#ifndef INLINE +#define INLINE __inline__ +#endif + +/* Preserve the sticky-bit when shifting fractions to the right. */ +#define LSHIFT(a, s) { a = (a >> s) | !!(a & (((fractype) 1 << s) - 1)); } + +/* numeric parameters */ +/* F_D_BITOFF is the number of bits offset between the MSB of the mantissa + of a float and of a double. Assumes there are only two float types. + (double::FRAC_BITS+double::NGARDS-(float::FRAC_BITS-float::NGARDS)) + */ +#define F_D_BITOFF (52+8-(23+7)) + +#ifdef TMODES +# define F_T_BITOFF (__LDBL_MANT_DIG__-1+10-(23+7)) +# define D_T_BITOFF (__LDBL_MANT_DIG__-1+10-(52+8)) +#endif + + +#define NORMAL_EXPMIN (-(EXPBIAS)+1) +#define IMPLICIT_1 ((fractype)1<<(FRACBITS+NGARDS)) +#define IMPLICIT_2 ((fractype)1<<(FRACBITS+1+NGARDS)) + +/* common types */ + +typedef enum +{ + CLASS_SNAN, + CLASS_QNAN, + CLASS_ZERO, + CLASS_NUMBER, + CLASS_INFINITY +} fp_class_type; + +typedef struct +{ +#ifdef SMALL_MACHINE + char class; + unsigned char sign; + short normal_exp; +#else + fp_class_type class; + unsigned int sign; + int normal_exp; +#endif + + union + { + fractype ll; + halffractype l[2]; + } fraction; +} fp_number_type; + +typedef union +{ + FLO_type value; + fractype value_raw; + +#ifndef FLOAT +# ifdef qrtrfractype + qrtrfractype qwords[4]; +# else + halffractype words[2]; +# endif +#endif + +#ifdef FLOAT_BIT_ORDER_MISMATCH + struct + { + fractype fraction:FRACBITS __attribute__ ((packed)); + unsigned int exp:EXPBITS __attribute__ ((packed)); + unsigned int sign:1 __attribute__ ((packed)); + } + bits; +#endif + +#ifdef _DEBUG_BITFLOAT + struct + { + unsigned int sign:1 __attribute__ ((packed)); + unsigned int exp:EXPBITS __attribute__ ((packed)); + fractype fraction:FRACBITS __attribute__ ((packed)); + } + bits_big_endian; + + struct + { + fractype fraction:FRACBITS __attribute__ ((packed)); + unsigned int exp:EXPBITS __attribute__ ((packed)); + unsigned int sign:1 __attribute__ ((packed)); + } + bits_little_endian; +#endif +} +FLO_union_type; + +/* Prototypes. */ + +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf) +extern FLO_type pack_d (const fp_number_type *); +#endif + +extern void unpack_d (FLO_union_type *, fp_number_type *); + +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf) +extern FLO_type add (FLO_type, FLO_type); +extern FLO_type sub (FLO_type, FLO_type); +#endif + +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf) +extern FLO_type multiply (FLO_type, FLO_type); +#endif + +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf) +extern FLO_type divide (FLO_type, FLO_type); +#endif + +extern int __fpcmp_parts (fp_number_type *, fp_number_type *); + +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compare_tf) +extern CMPtype compare (FLO_type, FLO_type); +#endif + +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf) +extern CMPtype _eq_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf) +extern CMPtype _ne_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf) +extern CMPtype _gt_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf) +extern CMPtype _ge_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf) +extern CMPtype _lt_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf) +extern CMPtype _le_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf) +extern CMPtype _unord_f2 (FLO_type, FLO_type); +#endif + +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf) +extern FLO_type si_to_float (SItype); +#endif + +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si) +extern SItype float_to_si (FLO_type); +#endif + +#if defined(L_tf_to_usi) +extern USItype float_to_usi (FLO_type); +#endif + +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf) +extern FLO_type usi_to_float (USItype); +#endif + +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf) +extern FLO_type negate (FLO_type); +#endif + +#ifdef FLOAT +#if defined(L_make_sf) +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); +#endif +#ifndef FLOAT_ONLY +extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype); +#if defined(L_sf_to_df) +extern DFtype sf_to_df (SFtype); +#endif +#if defined(L_sf_to_tf) && defined(TMODES) +extern TFtype sf_to_tf (SFtype); +#endif +#endif /* ! FLOAT_ONLY */ +#endif /* FLOAT */ + +#ifndef FLOAT +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype); +#if defined(L_make_df) +extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype); +#endif +#if defined(L_df_to_sf) +extern SFtype df_to_sf (DFtype); +#endif +#if defined(L_df_to_tf) && defined(TMODES) +extern TFtype df_to_tf (DFtype); +#endif +#endif /* ! FLOAT */ + +#ifdef TMODES +extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype); +extern TFtype __make_tp (fp_class_type, unsigned int, int, UTItype); +#ifdef TFLOAT +#if defined(L_tf_to_sf) +extern SFtype tf_to_sf (TFtype); +#endif +#if defined(L_tf_to_df) +extern DFtype tf_to_df (TFtype); +#endif +#if defined(L_di_to_tf) +extern TFtype di_to_df (DItype); +#endif +#endif /* TFLOAT */ +#endif /* TMODES */ + +#endif /* ! GCC_FP_BIT_H */ |