gcc/libgcc/fp-bit.c

1667 lines
37 KiB
C
Raw Normal View History

i * libgcc1-test.c, libgcc1.c, config/i386/perform.h: Delete file. * testsuite/gcc.dg/complete-port.c: New (revised version of libgcc1-test.c) * po/POTFILES.in: Remove libgcc1-test.c and libgcc1.c. * Makefile.in: Delete variables: OLDCC, CCLIBFLAGS, OLDAR, OLDAR_FLAGS, LIBGCC1, LIBGCC1_TEST, CROSS_LIBGCC1, LIB1FUNCS, and LIB1FUNCS_EXTRA. Delete rules: libgcc1-test, libgcc1-test.o. Clarify commentary now that libgcc1 no longer exists. * cross-make: Don't set LIBGCC1. * mklibgcc.in: Delete all code for building from libgcc1.c. Always honor LIB1ASMFUNCS if set. * crtstuff.c, floatlib.c, longlong.h, config/fp-bit.c, config/arc/lib1funcs.asm, config/arm/lib1funcs.asm, config/d30v/libgcc1.asm, config/fr30/lib1funcs.asm, config/h8300/lib1funcs.asm, config/i386/cygwin.asm, config/i386/uwin.asm, config/m68hc11/larith.asm, config/m68k/lb1sf68.asm, config/mcore/lib1.asm, config/mn10200/lib1funcs.asm, config/sh/lib1funcs.asm, config/sparc/lb1spc.asm, config/sparc/lb1spl.asm, config/v850/lib1funcs.asm, config/c4x/libgcc.S: Delete or update references to libgcc1 in commentary. * config/t-libc-ok, config/t-linux, config/t-linux-aout, config/t-netbsd, config/a29k/t-a29kbare, config/a29k/t-vx29k, config/alpha/t-interix, config/alpha/t-osf, config/alpha/t-vms, config/arc/t-arc, config/arm/t-arm-aout, config/arm/t-arm-coff, config/arm/t-arm-elf, config/arm/t-linux, config/arm/t-pe, config/arm/t-semi, config/arm/t-strongarm-coff, config/arm/t-strongarm-elf, config/arm/t-strongarm-pe, config/arm/t-xscale-coff, config/arm/t-xscale-elf, config/avr/t-avr, config/c4x/t-c4x, config/d30v/t-d30v, config/fr30/t-fr30, config/h8300/t-h8300, config/i386/t-beos, config/i386/t-cygwin, config/i386/t-i386elf, config/i386/t-interix, config/i386/t-netware, config/i386/t-next, config/i386/t-rtems-i386, config/i386/t-sol2, config/i960/t-960bare, config/i960/t-vxworks960, config/ia64/t-ia64, config/m32r/t-m32r, config/m68hc11/t-m68hc11-gas, config/m68k/t-lynx, config/m68k/t-m68kbare, config/m68k/t-m68kelf, config/m68k/t-mot3300-gald, config/m68k/t-mot3300-gas, config/m68k/t-next, config/m68k/t-vxworks68, config/m88k/t-bug, config/m88k/t-dgux, config/m88k/t-dgux-gas, config/m88k/t-dguxbcs, config/m88k/t-luna, config/m88k/t-luna-gas, config/m88k/t-m88k, config/m88k/t-m88k-gas, config/m88k/t-sysv4, config/mcore/t-mcore, config/mcore/t-mcore-pe, config/mips/t-bsd, config/mips/t-bsd-gas, config/mips/t-cross64, config/mips/t-ecoff, config/mips/t-elf, config/mips/t-iris6, config/mips/t-r3900, config/mips/t-svr3, config/mips/t-svr3-gas, config/mips/t-svr4, config/mips/t-svr4-gas, config/mips/t-ultrix, config/mn10200/t-mn10200, config/mn10300/t-mn10300, config/pa/t-linux, config/pa/t-linux64, config/pa/t-pa, config/pa/t-pa64, config/pa/t-pro, config/pdp11/t-pdp11, config/pj/t-pj, config/rs6000/t-aix43, config/rs6000/t-beos, config/rs6000/t-darwin, config/rs6000/t-newas, config/rs6000/t-ppccomm, config/rs6000/t-rs6000, config/sh/t-linux, config/sh/t-sh, config/sparc/t-chorus-elf, config/sparc/t-elf, config/sparc/t-sol2, config/sparc/t-sp86x, config/sparc/t-sparcbare, config/sparc/t-sparclite, config/sparc/t-splet, config/sparc/t-sunos41, config/sparc/t-vxsparc, config/sparc/t-vxsparc64, config/v850/t-v850: Don't set any of LIBGCC1, CROSS_LIBGCC1, or LIBGCC1_TEST. * config/alpha/alpha.h, config/i386/i386.h, config/i860/i860.h: Don't set FLOAT_VALUE_TYPE, FLOAT_ARG_TYPE, INTIFY, or FLOATIFY. * config/d30v/d30v.h: Don't mention LIBGCC_NEEDS_DOUBLE, FLOAT_VALUE_TYPE, FLOAT_ARG_TYPE, FLOATIFY, INTIFY, nongcc_SI_type, nongcc_word_type, or perform_* * config/i860/fx2800: Don't define perform_umodsi3 or perform_modsi3. * config/i386/386bsd.h, config/i386/beos-elf.h, config/i386/linux-aout.h, config/i386/linux-oldld.h, config/i386/linux.h, config/i386/mach.h, config/i386/netbsd.h, config/i386/openbsd.h, config/i386/osfrose.h, config/i386/rtemself.h: Don't include i386/perform.h. * config/a29k/t-a29k, config/arm/t-semiaof, config/i370/t-i370, config/i370/t-linux, config/i370/t-mvs, config/i370/t-oe, config/i386/t-djgpp, config/i386/t-i386bare, config/i386/t-vsta, config/ia64/t-hpux, config/mips/t-mips, config/mips/t-mips-gas, config/mips/t-osfrose, config/sparc/t-sp64, config/sparc/t-sunos40, config/vax/t-openbsd, config/vax/t-vax: Delete. * config.gcc: Remove references to deleted files. (arm-semi-aof): Use arm/t-semi for tmake_file. * gcc.texi, install.texi, invoke.texi, tm.texi: Delete or rewrite text which is no longer relevant now that libgcc1 no longer exists. * config/t-openbsd, config/alpha/t-interix, config/i386/t-interix: No need to set INSTALL_ASSERT_H. (Missed in previous sweep.) From-SVN: r42188
2001-05-17 05:16:18 +02:00
/* This is a software floating point library which can be used
for targets without hardware floating point.
Copyright (C) 1994-2013 Free Software Foundation, Inc.
1994-07-16 22:45:33 +02:00
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.
1994-07-16 22:45:33 +02:00
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.
1994-07-16 22:45:33 +02:00
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/>. */
1994-07-16 22:45:33 +02:00
/* This implements IEEE 754 format arithmetic, but does not provide a
1994-07-12 00:32:24 +02:00
mechanism for setting the rounding mode, or for generating or handling
exceptions.
The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
1994-07-16 22:45:33 +02:00
Wilson, all of Cygnus Support. */
1994-07-12 00:32:24 +02:00
/* 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. */
configure.in: Kill tm.h. * configure.in: Kill tm.h. Include the files in the $tm_file list in all three of config.h, hconfig.h, tconfig.h, after the relevant set of xm_files. Put TARGET_CPU_DEFAULT in all three, include insn-codes.h in all three (#ifndef GENERATOR_FILE). * configure: Regenerate. * Makefile.in (clean): Don't delete tm.h. * system.h: If SUCCESS_EXIT_CODE and FATAL_EXIT_CODE are not defined, set them from EXIT_SUCCESS and EXIT_FAILURE. If those are not defined, set SEC and FEC to 0 and 1. * gcc.texi: Update to match. * crtstuff.c: Include tconfig.h, not auto-host.h and tm.h. * config/fp-bit.c, config/m68k/aux-crt2.asm, config/m68k/aux-crtn.asm, config/m68k/aux-mcount.c: Include tconfig.h, not tm.h. * config/xm-lynx.h, config/xm-std32.h, config/a29k/xm-a29k.h, config/a29k/xm-unix.h, config/alpha/xm-alpha.h, config/arc/xm-arc.h, config/avr/xm-avr.h, config/c4x/xm-c4x.h, config/clipper/xm-clix.h, config/convex/xm-convex.h, config/d30v/xm-d30v.h, config/dsp16xx/xm-dsp16xx.h, config/elxsi/xm-elxsi.h, config/fr30/xm-fr30.h, config/h8300/xm-h8300.h, config/i370/xm-linux.h, config/i386/xm-i386.h, config/i860/xm-i860.h, config/i960/xm-i960.h, config/ia64/xm-ia64.h, config/m32r/xm-m32r.h, config/m68hc11/xm-m68hc11.h, config/m88k/xm-m88k.h, config/mcore/xm-mcore.h, config/mips/xm-mips.h, config/mn10200/xm-mn10200.h, config/mn10300/xm-mn10300.h, config/ns32k/xm-ns32k.h, config/pa/xm-linux.h, config/pa/xm-pa.h, config/pa/xm-pa64hpux.h, config/pa/xm-pahpux.h, config/pa/xm-papro.h, config/pdp11/xm-pdp11.h, config/pj/xm-pj.h, config/romp/xm-romp.h, config/rs6000/xm-beos.h, config/rs6000/xm-rs6000.h, config/rs6000/xm-sysv4.h, config/sh/xm-sh.h, config/sparc/xm-sparc.h, config/sparc/xm-sysv4.h, config/v850/xm-v850.h, config/vax/xm-vax.h, config/we32k/xm-we32k.h: Don't include tm.h. Don't define SUCCESS_EXIT_CODE or FATAL_EXIT_CODE. * config/i370/xm-i370.h, config/i370/xm-mvs.h, config/i370/xm-oe.h: Don't include tm.h. Don't define SUCCESS_EXIT_CODE. * config/vax/xm-vms.h: Don't include tm.h. * config/xm-lynx.h, config/avr/xm-avr.h, config/fr30/xm-fr30.h, config/pdp11/xm-pdp11.h, Delete; made empty by above changes. * config/i386/xm-lynx.h, config/m68k/xm-lynx.h, config/rs6000/xm-lynx.h, config/sparc/xm-lynx.h: Don't include config/xm-lynx.h or tm.h. * config/xm-gnu.h: Don't include fcntl.h. * config/sparc/xm-lynx.h: Don't include sys/types.h and sys/wait.h. * config/clipper/xm-clix.h, config/vax/xm-vax.h: Don't define isinf. From-SVN: r40199
2001-03-03 04:32:55 +01:00
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
Move libgcc_tm_file to toplevel libgcc gcc: * configure.ac (libgcc_tm_file_list, libgcc_tm_include_list): Remove. * configure: Regenerate. * Makefile.in (libgcc_tm_file_list, libgcc_tm_include_list): Remove. (TM_H): Remove libgcc_tm.h, $(libgcc_tm_file_list). (libgcc_tm.h, cs-libgcc_tm.h): Remove. (clean): Remove libgcc_tm.h * mkconfig.sh: Don't include libgcc_tm.h in tm.h. * config.gcc (libgcc_tm_file): Remove. (arm*-*-linux*): Remove libgcc_tm_file for arm*-*-linux-*eabi. (arm*-*-uclinux*): Remove libgcc_tm_file for arm*-*-uclinux*eabi. (arm*-*-eabi*, arm*-*-symbianelf*): Remove libgcc_tm_file. (avr-*-rtems*): Likewise. (avr-*-*): Likewise. (frv-*-elf): Likewise. (frv-*-*linux*): Likewise. (h8300-*-rtems*): Likewise. (h8300-*-elf*): Likewise. (i[34567]86-*-darwin*): Likewise. (x86_64-*-darwin*): Likewise. (rx-*-elf*): Likewise. (tic6x-*-elf): Likewise. (tic6x-*-uclinux): Likewise. (i[34567]86-*-linux*, x86_64-*-linux*): Likewise. libgcc: * configure.ac (tm_file_): New variable. Determine from tm_file. (tm_file, tm_defines): Substitute. * configure: Regenerate. * mkheader.sh: New file. * Makefile.in (clean): Remove libgcc_tm.h. ($(objects)): Depend on libgcc_tm.h. (libgcc_tm_defines, libgcc_tm_file): New variables. (libgcc_tm.h, libgcc_tm.stamp): New targets. ($(libgcc-objects), $(libgcc-s-objects), $(libgcc-eh-objects)) ($(libgcov-objects), $(libunwind-objects), $(libunwind-s-objects)) ($(extra-parts)): Depend on libgcc_tm.h. * config.host (tm_defines, tm_file): New variable. (arm*-*-linux*): Set tm_file for arm*-*-linux-*eabi. (arm*-*-uclinux*): Set tm_file for arm*-*-uclinux*eabi. (arm*-*-eabi*, arm*-*-symbianelf*): Set tm_file. (avr-*-rtems*): Likewise. (avr-*-*): Likewise. (frv-*-elf): Likewise. (frv-*-*linux*): Likewise. (h8300-*-rtems*): Likewise. (h8300-*-elf*): Likewise. (i[34567]86-*-darwin*): Likewise. (x86_64-*-darwin*): Likewise. (rx-*-elf): Likewise. (tic6x-*-uclinux): Likewise. (tic6x-*-elf): Likewise. (i[34567]86-*-linux*, x86_64-*-linux*): Likewise. * config/alpha/gthr-posix.c: Include libgcc_tm.h. * config/i386/cygming-crtbegin.c: Likewise. * config/i386/cygming-crtend.c: Likewise. * config/ia64/fde-vms.c: Likewise. * config/ia64/unwind-ia64.c: Likewise. * config/libbid/bid_gcc_intrinsics.h: Likewise. * config/rs6000/darwin-fallback.c: Likewise. * config/stormy16/lib2funcs.c: Likewise. * config/xtensa/unwind-dw2-xtensa.c: Likewise. * crtstuff.c: Likewise. * dfp-bit.h: Likewise. * emutls.c: Likewise. * fixed-bit.c: Likewise. * fp-bit.c: Likewise. * generic-morestack-thread.c: Likewise. * generic-morestack.c: Likewise. * libgcc2.c: Likewise. * libgcov.c: Likewise. * unwind-dw2-fde-dip.c: Likewise. * unwind-dw2-fde.c: Likewise. * unwind-dw2.c: Likewise. * unwind-sjlj.c: Likewise. Co-Authored-By: Paolo Bonzini <bonzini@gnu.org> From-SVN: r180775
2011-11-02 16:26:35 +01:00
#include "libgcc_tm.h"
Makefile.in (FPBIT_FUNCS, [...]): Remove. 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. From-SVN: r177448
2011-08-05 16:53:09 +02:00
#include "fp-bit.h"
/* The following macros can be defined to change the behavior of this file:
1994-07-12 00:32:24 +02:00
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.
1994-07-12 00:32:24 +02:00
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 */
1994-07-12 00:32:24 +02:00
/* 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
1994-07-12 00:32:24 +02:00
INLINE
static const fp_number_type *
makenan (void)
1994-07-12 00:32:24 +02:00
{
#ifdef TFLOAT
return & __thenan_tf;
#elif defined FLOAT
return & __thenan_sf;
#else
return & __thenan_df;
#endif
1994-07-12 00:32:24 +02:00
}
INLINE
static int
isnan (const fp_number_type *x)
1994-07-12 00:32:24 +02:00
{
return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN,
0);
1994-07-12 00:32:24 +02:00
}
INLINE
static int
isinf (const fp_number_type * x)
1994-07-12 00:32:24 +02:00
{
return __builtin_expect (x->class == CLASS_INFINITY, 0);
1994-07-12 00:32:24 +02:00
}
#endif /* NO_NANS */
1994-07-12 00:32:24 +02:00
INLINE
static int
iszero (const fp_number_type * x)
1994-07-12 00:32:24 +02:00
{
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)
1994-07-12 00:32:24 +02:00
{
FLO_union_type dst;
fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
int sign = src->sign;
int exp = 0;
1994-07-12 00:32:24 +02:00
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))
1994-07-12 00:32:24 +02:00
{
exp = EXPMAX;
/* Restore the NaN's payload. */
fraction >>= NGARDS;
fraction &= QUIET_NAN - 1;
1994-07-12 00:32:24 +02:00
if (src->class == CLASS_QNAN || 1)
{
#ifdef QUIET_NAN_NEGATED
/* The quiet/signaling bit remains unset. */
/* Make sure the fraction has a non-zero value. */
if (fraction == 0)
fraction |= QUIET_NAN - 1;
#else
/* Set the quiet/signaling bit. */
fraction |= QUIET_NAN;
#endif
1994-07-12 00:32:24 +02:00
}
}
else if (isinf (src))
{
exp = EXPMAX;
fraction = 0;
1994-07-12 00:32:24 +02:00
}
else if (iszero (src))
{
exp = 0;
fraction = 0;
1994-07-12 00:32:24 +02:00
}
else if (fraction == 0)
{
exp = 0;
1994-07-12 00:32:24 +02:00
}
else
{
if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0))
1994-07-12 00:32:24 +02:00
{
#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 */
1994-07-12 00:32:24 +02:00
/* 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;
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
}
fraction >>= NGARDS;
#endif /* NO_DENORMALS */
1994-07-12 00:32:24 +02:00
}
else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
&& __builtin_expect (src->normal_exp > EXPBIAS, 0))
1994-07-12 00:32:24 +02:00
{
exp = EXPMAX;
fraction = 0;
1994-07-12 00:32:24 +02:00
}
else
{
exp = src->normal_exp + EXPBIAS;
if (!ROUND_TOWARDS_ZERO)
1994-07-12 00:32:24 +02:00
{
/* 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;
}
1994-07-12 00:32:24 +02:00
}
fraction >>= NGARDS;
if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
1994-07-12 00:32:24 +02:00
{
/* Saturate on overflow. */
exp = EXPMAX;
fraction = ((fractype) 1 << FRACBITS) - 1;
1994-07-12 00:32:24 +02:00
}
}
}
/* 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
1994-07-12 00:32:24 +02:00
return dst.value;
}
#endif
1994-07-12 00:32:24 +02:00
#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
void
1994-07-12 00:32:24 +02:00
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)
1994-07-12 00:32:24 +02:00
{
/* Hmm. Looks like 0 */
if (fraction == 0
#ifdef NO_DENORMALS
|| 1
#endif
)
1994-07-12 00:32:24 +02:00
{
/* tastes like zero */
dst->class = CLASS_ZERO;
}
else
{
/* Zero exponent with nonzero fraction - it's denormalized,
1994-07-12 00:32:24 +02:00
so there isn't a leading implicit one - we'll shift it so
it gets one. */
dst->normal_exp = exp - EXPBIAS + 1;
1994-07-12 00:32:24 +02:00
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))
1994-07-12 00:32:24 +02:00
{
/* Huge exponent*/
if (fraction == 0)
{
1995-05-16 14:14:26 +02:00
/* Attached to a zero fraction - means infinity */
1994-07-12 00:32:24 +02:00
dst->class = CLASS_INFINITY;
}
else
{
/* Nonzero fraction, means nan */
#ifdef QUIET_NAN_NEGATED
if ((fraction & QUIET_NAN) == 0)
#else
if (fraction & QUIET_NAN)
#endif
1994-07-12 00:32:24 +02:00
{
dst->class = CLASS_QNAN;
1994-07-12 00:32:24 +02:00
}
else
{
dst->class = CLASS_SNAN;
1994-07-12 00:32:24 +02:00
}
/* Now that we know which kind of NaN we got, discard the
quiet/signaling bit, but do preserve the NaN payload. */
fraction &= ~QUIET_NAN;
dst->fraction.ll = fraction << NGARDS;
1994-07-12 00:32:24 +02:00
}
}
else
{
/* Nothing strange about this number */
dst->normal_exp = exp - EXPBIAS;
1994-07-12 00:32:24 +02:00
dst->class = CLASS_NUMBER;
dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
}
}
#endif /* L_unpack_df || L_unpack_sf */
1994-07-12 00:32:24 +02:00
#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
static const fp_number_type *
1994-07-12 00:32:24 +02:00
_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 ();
1994-07-12 00:32:24 +02:00
return a;
}
if (isinf (b))
{
return b;
}
if (iszero (b))
{
if (iszero (a))
{
*tmp = *a;
tmp->sign = a->sign & b->sign;
return tmp;
}
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
if (diff < 0)
diff = -diff;
if (diff < FRAC_NBITS)
{
if (sdiff > 0)
1994-07-12 00:32:24 +02:00
{
b_normal_exp += diff;
LSHIFT (b_fraction, diff);
1994-07-12 00:32:24 +02:00
}
else if (sdiff < 0)
1994-07-12 00:32:24 +02:00
{
a_normal_exp += diff;
LSHIFT (a_fraction, diff);
1994-07-12 00:32:24 +02:00
}
}
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)
1994-07-12 00:32:24 +02:00
{
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;
}
1995-05-16 14:14:26 +02:00
/* and renormalize it */
1994-07-12 00:32:24 +02:00
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);
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
au.value = arg_a;
bu.value = arg_b;
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
b.sign ^= 1;
res = _fpadd_parts (&a, &b, &tmp);
return pack_d (res);
}
#endif /* L_addsub_sf || L_addsub_df */
1994-07-12 00:32:24 +02:00
#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
static inline __attribute__ ((__always_inline__)) const fp_number_type *
1994-07-12 00:32:24 +02:00
_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 ();
1994-07-12 00:32:24 +02:00
a->sign = a->sign != b->sign;
return a;
}
if (isinf (b))
{
if (iszero (a))
{
return makenan ();
1994-07-12 00:32:24 +02:00
}
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. */
1994-07-12 00:32:24 +02:00
{
#if defined(NO_DI_MODE) || defined(TFLOAT)
1994-07-12 00:32:24 +02:00
{
Warning fixes: * Makefile.in (xcoffout.o): Depend on toplev.h, output.h and dbxout.h. * config/fp-bit.c (_fpmul_parts): Move variables `x', `ylow', `yhigh' and `bit' into the scope in which they are used. (_fpdiv_parts): Remove unused variables `low', `high', `r0', `r1', `y0', `y1', `q', `remainder', `carry', `d0' and `d1'. * rs6000.c: Move include of output.h below tree.h. Include toplev.h. (any_operand): Mark unused parameters `op' and `mode' with ATTRIBUTE_UNUSED. (count_register_operand): Likewise for parameter `mode'. (fpmem_operand): Likewise. (short_cint_operand): Likewise. (u_short_cint_operand): Likewise. (non_short_cint_operand): Likewise. (got_operand): Likewise. (got_no_const_operand): Likewise. (non_add_cint_operand): Likewise. (non_logical_cint_operand): Likewise. (mask_operand): Likewise. (current_file_function_operand): Likewise. (small_data_operand): Likewise for parameters `op' and `mode' but only when !TARGET_ELF. (init_cumulative_args): Mark parameters `libname' with ATTRIBUTE_UNUSED. (function_arg_pass_by_reference): Likewise for parameters `cum', `mode' and `named'. (expand_builtin_saveregs): Likewise for parameter `args'. (load_multiple_operation): Likewise for parameter `mode'. (store_multiple_operation): Likewise. (branch_comparison_operator): Likewise. (secondary_reload_class): Likewise. (print_operand): Add parentheses around & operation. (output_prolog): Mark parameter `size' with ATTRIBUTE_UNUSED. (output_epilog): Likewise. Cast argument to fprintf to int. (rs6000_adjust_cost): Mark parameter `dep_insn' with ATTRIBUTE_UNUSED. (rs6000_valid_decl_attribute_p): Likewise for parameters `decl', `attributes', `identifier' and `args'. (rs6000_valid_type_attribute_p): Likewise for parameter `attributes'. (rs6000_comp_type_attributes): Likewise for parameters `type1' and `type2'. (rs6000_set_default_type_attributes): Likewise for parameter `type'. * rs6000.h (RTX_COSTS): Add parentheses around & operation. (toc_section, private_data_section, trap_comparison_operator): Add prototypes. * dbxout.h (dbxout_parms, dbxout_reg_parms, dbxout_syms): Add prototypes. * xcoffout.c: Include toplev.h, outout.h and dbxout.h. * xcoffout.h (stab_to_sclass, xcoffout_begin_function, xcoffout_begin_block, xcoffout_end_epilogue, xcoffout_end_function, xcoffout_end_block, xcoff_output_standard_types, xcoffout_declare_function, xcoffout_source_line): Add prototypes. From-SVN: r20717
1998-06-25 15:05:20 +02:00
fractype x = a->fraction.ll;
fractype ylow = b->fraction.ll;
fractype yhigh = 0;
int bit;
1994-07-12 00:32:24 +02:00
/* ??? 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. */
1994-07-12 00:32:24 +02:00
{
UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
1994-07-12 00:32:24 +02:00
high = answer >> BITS_PER_SI;
1994-07-12 00:32:24 +02:00
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. */
1994-07-12 00:32:24 +02:00
{
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;
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
res0 = pp_ll + pp_hl;
if (res0 < pp_ll)
res2++;
res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
1994-07-12 00:32:24 +02:00
high = res2;
low = res0;
}
#endif
}
tmp->normal_exp = a->normal_exp + b->normal_exp
+ FRAC_NBITS - (FRACBITS + NGARDS);
1994-07-12 00:32:24 +02:00
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)
1994-07-12 00:32:24 +02:00
{
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). */
1994-07-12 00:32:24 +02:00
}
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. */
1994-07-12 00:32:24 +02:00
high += GARDROUND + 1;
/* Avoid further rounding in pack_d. */
high &= ~(fractype) GARDMASK;
1994-07-12 00:32:24 +02:00
}
}
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;
1994-07-12 00:32:24 +02:00
au.value = arg_a;
bu.value = arg_b;
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
res = _fpmul_parts (&a, &b, &tmp);
return pack_d (res);
}
#endif /* L_mul_sf || L_mul_df || L_mul_tf */
1994-07-12 00:32:24 +02:00
#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
static inline __attribute__ ((__always_inline__)) const fp_number_type *
1994-07-12 00:32:24 +02:00
_fpdiv_parts (fp_number_type * a,
fp_number_type * b)
1994-07-12 00:32:24 +02:00
{
Warning fixes: * Makefile.in (xcoffout.o): Depend on toplev.h, output.h and dbxout.h. * config/fp-bit.c (_fpmul_parts): Move variables `x', `ylow', `yhigh' and `bit' into the scope in which they are used. (_fpdiv_parts): Remove unused variables `low', `high', `r0', `r1', `y0', `y1', `q', `remainder', `carry', `d0' and `d1'. * rs6000.c: Move include of output.h below tree.h. Include toplev.h. (any_operand): Mark unused parameters `op' and `mode' with ATTRIBUTE_UNUSED. (count_register_operand): Likewise for parameter `mode'. (fpmem_operand): Likewise. (short_cint_operand): Likewise. (u_short_cint_operand): Likewise. (non_short_cint_operand): Likewise. (got_operand): Likewise. (got_no_const_operand): Likewise. (non_add_cint_operand): Likewise. (non_logical_cint_operand): Likewise. (mask_operand): Likewise. (current_file_function_operand): Likewise. (small_data_operand): Likewise for parameters `op' and `mode' but only when !TARGET_ELF. (init_cumulative_args): Mark parameters `libname' with ATTRIBUTE_UNUSED. (function_arg_pass_by_reference): Likewise for parameters `cum', `mode' and `named'. (expand_builtin_saveregs): Likewise for parameter `args'. (load_multiple_operation): Likewise for parameter `mode'. (store_multiple_operation): Likewise. (branch_comparison_operator): Likewise. (secondary_reload_class): Likewise. (print_operand): Add parentheses around & operation. (output_prolog): Mark parameter `size' with ATTRIBUTE_UNUSED. (output_epilog): Likewise. Cast argument to fprintf to int. (rs6000_adjust_cost): Mark parameter `dep_insn' with ATTRIBUTE_UNUSED. (rs6000_valid_decl_attribute_p): Likewise for parameters `decl', `attributes', `identifier' and `args'. (rs6000_valid_type_attribute_p): Likewise for parameter `attributes'. (rs6000_comp_type_attributes): Likewise for parameters `type1' and `type2'. (rs6000_set_default_type_attributes): Likewise for parameter `type'. * rs6000.h (RTX_COSTS): Add parentheses around & operation. (toc_section, private_data_section, trap_comparison_operator): Add prototypes. * dbxout.h (dbxout_parms, dbxout_reg_parms, dbxout_syms): Add prototypes. * xcoffout.c: Include toplev.h, outout.h and dbxout.h. * xcoffout.h (stab_to_sclass, xcoffout_begin_function, xcoffout_begin_block, xcoffout_end_epilogue, xcoffout_end_function, xcoffout_end_block, xcoff_output_standard_types, xcoffout_declare_function, xcoffout_source_line): Add prototypes. From-SVN: r20717
1998-06-25 15:05:20 +02:00
fractype bit;
1994-07-12 00:32:24 +02:00
fractype numerator;
fractype denominator;
fractype quotient;
if (isnan (a))
{
return a;
}
if (isnan (b))
{
return b;
}
a->sign = a->sign ^ b->sign;
1994-07-12 00:32:24 +02:00
if (isinf (a) || iszero (a))
{
if (a->class == b->class)
return makenan ();
1994-07-12 00:32:24 +02:00
return a;
}
if (isinf (b))
{
a->fraction.ll = 0;
a->normal_exp = 0;
return a;
}
if (iszero (b))
{
a->class = CLASS_INFINITY;
return a;
1994-07-12 00:32:24 +02:00
}
/* 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)
1994-07-12 00:32:24 +02:00
{
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. */
1994-07-12 00:32:24 +02:00
}
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. */
1994-07-12 00:32:24 +02:00
quotient += GARDROUND + 1;
/* Avoid further rounding in pack_d. */
quotient &= ~(fractype) GARDMASK;
1994-07-12 00:32:24 +02:00
}
}
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;
1994-07-12 00:32:24 +02:00
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
res = _fpdiv_parts (&a, &b);
1994-07-12 00:32:24 +02:00
return pack_d (res);
}
#endif /* L_div_sf || L_div_df */
1994-07-12 00:32:24 +02:00
#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
|| defined(L_fpcmp_parts_tf)
1994-07-12 00:32:24 +02:00
/* 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)
1994-07-12 00:32:24 +02:00
{
#if 0
/* either nan -> unordered. Must be checked outside of this routine. */
1994-07-12 00:32:24 +02:00
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...
1994-07-12 00:32:24 +02:00
*/
return b->sign - a->sign;
}
/* but not both... */
1994-07-12 00:32:24 +02:00
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". */
1994-07-12 00:32:24 +02:00
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. */
1994-07-12 00:32:24 +02:00
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. */
1994-07-12 00:32:24 +02:00
return 0;
}
#endif
1994-07-12 00:32:24 +02:00
#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
1994-07-12 00:32:24 +02:00
CMPtype
compare (FLO_type arg_a, FLO_type arg_b)
{
fp_number_type a;
fp_number_type b;
FLO_union_type au, bu;
1994-07-12 00:32:24 +02:00
au.value = arg_a;
bu.value = arg_b;
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
return __fpcmp_parts (&a, &b);
1994-07-12 00:32:24 +02:00
}
#endif /* L_compare_sf || L_compare_df */
1994-07-12 00:32:24 +02:00
/* These should be optimized for their specific tasks someday. */
#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
if (isnan (&a) || isnan (&b))
return 1; /* false, truth == 0 */
return __fpcmp_parts (&a, &b) ;
1994-07-12 00:32:24 +02:00
}
#endif /* L_eq_sf || L_eq_df */
1994-07-12 00:32:24 +02:00
#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
1994-07-12 00:32:24 +02:00
CMPtype
_ne_f2 (FLO_type arg_a, FLO_type arg_b)
{
fp_number_type a;
fp_number_type b;
FLO_union_type au, bu;
1994-07-12 00:32:24 +02:00
au.value = arg_a;
bu.value = arg_b;
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
if (isnan (&a) || isnan (&b))
return 1; /* true, truth != 0 */
return __fpcmp_parts (&a, &b) ;
1994-07-12 00:32:24 +02:00
}
#endif /* L_ne_sf || L_ne_df */
1994-07-12 00:32:24 +02:00
#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
if (isnan (&a) || isnan (&b))
return -1; /* false, truth > 0 */
return __fpcmp_parts (&a, &b);
1994-07-12 00:32:24 +02:00
}
#endif /* L_gt_sf || L_gt_df */
1994-07-12 00:32:24 +02:00
#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
1994-07-12 00:32:24 +02:00
CMPtype
_ge_f2 (FLO_type arg_a, FLO_type arg_b)
{
fp_number_type a;
fp_number_type b;
FLO_union_type au, bu;
1994-07-12 00:32:24 +02:00
au.value = arg_a;
bu.value = arg_b;
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
if (isnan (&a) || isnan (&b))
return -1; /* false, truth >= 0 */
return __fpcmp_parts (&a, &b) ;
1994-07-12 00:32:24 +02:00
}
#endif /* L_ge_sf || L_ge_df */
1994-07-12 00:32:24 +02:00
#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
if (isnan (&a) || isnan (&b))
return 1; /* false, truth < 0 */
return __fpcmp_parts (&a, &b);
1994-07-12 00:32:24 +02:00
}
#endif /* L_lt_sf || L_lt_df */
1994-07-12 00:32:24 +02:00
#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
1994-07-12 00:32:24 +02:00
CMPtype
_le_f2 (FLO_type arg_a, FLO_type arg_b)
{
fp_number_type a;
fp_number_type b;
FLO_union_type au, bu;
1994-07-12 00:32:24 +02:00
au.value = arg_a;
bu.value = arg_b;
unpack_d (&au, &a);
unpack_d (&bu, &b);
1994-07-12 00:32:24 +02:00
if (isnan (&a) || isnan (&b))
return 1; /* false, truth <= 0 */
return __fpcmp_parts (&a, &b) ;
1994-07-12 00:32:24 +02:00
}
#endif /* L_le_sf || L_le_df */
1994-07-12 00:32:24 +02:00
#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
rtl.def: Add unordered fp comparisions. * rtl.def: Add unordered fp comparisions. * tree.def: Likewise. * tree.h: Add ISO C 9x unordered fp comparision builtins. * builtins.c (expand_tree_builtin): New function. * c-typeck.c (build_function_call): Use it. (build_binary_op): Support unordered compares. * c-common.c (c_common_nodes_and_builtins): Add unordered compares. * combine.c (known_cond): Handle reverse_condition returning UNKNOWN. (reversible_comparison_p): Allow UNORDERED/ORDERED to be reversed. * cse.c (fold_rtx): Check FLOAT_MODE_P before reversing. (record_jump_equiv): Handle reverse_condition returning UNKNOWN. * jump.c (reverse_condition): Don't abort for UNLE etc, but return UNKNOWN. (swap_condition): Handle unordered compares. (thread_jumps): Check can_reverse before reversing. * loop.c (get_condition): Likewise. Allow UNORERED/ORDERED to be reversed for FP. * optabs.c (can_compare_p): New argument CODE. Verify branch or setcc is present before acking for cmp_optab. Update all callers. (prepare_float_lib_cmp, init_optabs): Handle UNORDERED. * expmed.c (do_cmp_and_jump): Update for can_compare_p. * expr.c (expand_expr): Likewise. Support unordered compares. (do_jump, do_store_flag): Likewise. * expr.h (enum libfunc_index): Add unordered compares. * Makefile.in (FPBIT_FUNCS): Add _unord_sf. (DPBIT_FUNCS): Add _unord_df. * config/fp-bit.c (_unord_f2): New. * fp-test.c (main): Try unordered compare builtins. * alpha-protos.h (alpha_fp_comparison_operator): Declare. * alpha.c (alpha_comparison_operator): Check mode properly. (alpha_swapped_comparison_operator): Likewise. (signed_comparison_operator): Likewise. (alpha_fp_comparison_operator): New. (alpha_emit_conditional_branch): Handle unordered compares. * alpha.h (PREDICATE_CODES): Update. * alpha.md (fp compares): Use alpha_fp_comparison_operator. (bunordered, bordered): New. * cp/call.c (build_over_call): Use expand_tree_builtin. * cp/typeck.c (build_function_call_real): Likewise. (build_binary_op_nodefault): Handle unordered compares. * gcc.c-torture/execute/ieee/fp-cmp-4.c: New. From-SVN: r31591
2000-01-24 21:10:04 +01:00
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));
rtl.def: Add unordered fp comparisions. * rtl.def: Add unordered fp comparisions. * tree.def: Likewise. * tree.h: Add ISO C 9x unordered fp comparision builtins. * builtins.c (expand_tree_builtin): New function. * c-typeck.c (build_function_call): Use it. (build_binary_op): Support unordered compares. * c-common.c (c_common_nodes_and_builtins): Add unordered compares. * combine.c (known_cond): Handle reverse_condition returning UNKNOWN. (reversible_comparison_p): Allow UNORDERED/ORDERED to be reversed. * cse.c (fold_rtx): Check FLOAT_MODE_P before reversing. (record_jump_equiv): Handle reverse_condition returning UNKNOWN. * jump.c (reverse_condition): Don't abort for UNLE etc, but return UNKNOWN. (swap_condition): Handle unordered compares. (thread_jumps): Check can_reverse before reversing. * loop.c (get_condition): Likewise. Allow UNORERED/ORDERED to be reversed for FP. * optabs.c (can_compare_p): New argument CODE. Verify branch or setcc is present before acking for cmp_optab. Update all callers. (prepare_float_lib_cmp, init_optabs): Handle UNORDERED. * expmed.c (do_cmp_and_jump): Update for can_compare_p. * expr.c (expand_expr): Likewise. Support unordered compares. (do_jump, do_store_flag): Likewise. * expr.h (enum libfunc_index): Add unordered compares. * Makefile.in (FPBIT_FUNCS): Add _unord_sf. (DPBIT_FUNCS): Add _unord_df. * config/fp-bit.c (_unord_f2): New. * fp-test.c (main): Try unordered compare builtins. * alpha-protos.h (alpha_fp_comparison_operator): Declare. * alpha.c (alpha_comparison_operator): Check mode properly. (alpha_swapped_comparison_operator): Likewise. (signed_comparison_operator): Likewise. (alpha_fp_comparison_operator): New. (alpha_emit_conditional_branch): Handle unordered compares. * alpha.h (PREDICATE_CODES): Update. * alpha.md (fp compares): Use alpha_fp_comparison_operator. (bunordered, bordered): New. * cp/call.c (build_over_call): Use expand_tree_builtin. * cp/typeck.c (build_function_call_real): Likewise. (build_binary_op_nodefault): Handle unordered compares. * gcc.c-torture/execute/ieee/fp-cmp-4.c: New. From-SVN: r31591
2000-01-24 21:10:04 +01:00
}
#endif /* L_unord_sf || L_unord_df */
rtl.def: Add unordered fp comparisions. * rtl.def: Add unordered fp comparisions. * tree.def: Likewise. * tree.h: Add ISO C 9x unordered fp comparision builtins. * builtins.c (expand_tree_builtin): New function. * c-typeck.c (build_function_call): Use it. (build_binary_op): Support unordered compares. * c-common.c (c_common_nodes_and_builtins): Add unordered compares. * combine.c (known_cond): Handle reverse_condition returning UNKNOWN. (reversible_comparison_p): Allow UNORDERED/ORDERED to be reversed. * cse.c (fold_rtx): Check FLOAT_MODE_P before reversing. (record_jump_equiv): Handle reverse_condition returning UNKNOWN. * jump.c (reverse_condition): Don't abort for UNLE etc, but return UNKNOWN. (swap_condition): Handle unordered compares. (thread_jumps): Check can_reverse before reversing. * loop.c (get_condition): Likewise. Allow UNORERED/ORDERED to be reversed for FP. * optabs.c (can_compare_p): New argument CODE. Verify branch or setcc is present before acking for cmp_optab. Update all callers. (prepare_float_lib_cmp, init_optabs): Handle UNORDERED. * expmed.c (do_cmp_and_jump): Update for can_compare_p. * expr.c (expand_expr): Likewise. Support unordered compares. (do_jump, do_store_flag): Likewise. * expr.h (enum libfunc_index): Add unordered compares. * Makefile.in (FPBIT_FUNCS): Add _unord_sf. (DPBIT_FUNCS): Add _unord_df. * config/fp-bit.c (_unord_f2): New. * fp-test.c (main): Try unordered compare builtins. * alpha-protos.h (alpha_fp_comparison_operator): Declare. * alpha.c (alpha_comparison_operator): Check mode properly. (alpha_swapped_comparison_operator): Likewise. (signed_comparison_operator): Likewise. (alpha_fp_comparison_operator): New. (alpha_emit_conditional_branch): Handle unordered compares. * alpha.h (PREDICATE_CODES): Update. * alpha.md (fp compares): Use alpha_fp_comparison_operator. (bunordered, bordered): New. * cp/call.c (build_over_call): Use expand_tree_builtin. * cp/typeck.c (build_function_call_real): Likewise. (build_binary_op_nodefault): Handle unordered compares. * gcc.c-torture/execute/ieee/fp-cmp-4.c: New. From-SVN: r31591
2000-01-24 21:10:04 +01:00
#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
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))
1994-07-12 00:32:24 +02:00
{
return (FLO_type)(- MAX_SI_INT - 1);
1994-07-12 00:32:24 +02:00
}
uarg = (-arg_a);
1994-07-12 00:32:24 +02:00
}
else
uarg = arg_a;
1994-07-12 00:32:24 +02:00
in.fraction.ll = uarg;
shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
if (shift > 0)
1994-07-12 00:32:24 +02:00
{
in.fraction.ll <<= shift;
in.normal_exp -= shift;
1994-07-12 00:32:24 +02:00
}
}
return pack_d (&in);
}
#endif /* L_si_to_sf || L_si_to_df */
1994-07-12 00:32:24 +02:00
#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)
1994-07-12 00:32:24 +02:00
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);
1994-07-12 00:32:24 +02:00
if (iszero (&a))
return 0;
if (isnan (&a))
return 0;
/* get reasonable MAX_SI_INT... */
1994-07-12 00:32:24 +02:00
if (isinf (&a))
return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
1994-07-12 00:32:24 +02:00
/* it is a number, but a small one */
if (a.normal_exp < 0)
return 0;
if (a.normal_exp > BITS_PER_SI - 2)
1994-07-12 00:32:24 +02:00
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 */
1994-07-12 00:32:24 +02:00
#if defined(L_tf_to_usi)
1994-07-12 00:32:24 +02:00
USItype
float_to_usi (FLO_type arg_a)
{
fp_number_type a;
FLO_union_type au;
au.value = arg_a;
unpack_d (&au, &a);
1994-07-12 00:32:24 +02:00
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;
1994-07-12 00:32:24 +02:00
/* it is a number, but a small one */
if (a.normal_exp < 0)
return 0;
if (a.normal_exp > BITS_PER_SI - 1)
1994-07-12 00:32:24 +02:00
return MAX_USI_INT;
else if (a.normal_exp > (FRACBITS + NGARDS))
return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
1994-07-12 00:32:24 +02:00
else
return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
}
#endif /* L_tf_to_usi */
1994-07-12 00:32:24 +02:00
#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
1994-07-12 00:32:24 +02:00
FLO_type
negate (FLO_type arg_a)
{
fp_number_type a;
FLO_union_type au;
au.value = arg_a;
unpack_d (&au, &a);
1994-07-12 00:32:24 +02:00
flip_sign (&a);
return pack_d (&a);
}
#endif /* L_negate_sf || L_negate_df */
1994-07-12 00:32:24 +02:00
#ifdef FLOAT
#if defined(L_make_sf)
1994-07-12 00:32:24 +02:00
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 */
1994-07-12 00:32:24 +02:00
#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)
1994-07-12 00:32:24 +02:00
DFtype
sf_to_df (SFtype arg_a)
{
fp_number_type in;
FLO_union_type au;
au.value = arg_a;
unpack_d (&au, &in);
1994-07-12 00:32:24 +02:00
return __make_dp (in.class, in.sign, in.normal_exp,
((UDItype) in.fraction.ll) << F_D_BITOFF);
}
#endif /* L_sf_to_df */
1994-07-12 00:32:24 +02:00
#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 */
1994-07-12 00:32:24 +02:00
#ifndef FLOAT
extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
#if defined(L_make_df)
1994-07-12 00:32:24 +02:00
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 */
1994-07-12 00:32:24 +02:00
#if defined(L_df_to_sf)
1994-07-12 00:32:24 +02:00
SFtype
df_to_sf (DFtype arg_a)
{
fp_number_type in;
USItype sffrac;
FLO_union_type au;
1994-07-12 00:32:24 +02:00
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);
1994-07-12 00:32:24 +02:00
}
#endif /* L_df_to_sf */
1994-07-12 00:32:24 +02:00
#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 */