This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[libgfortran] FPE support for ppc-darwin
- From: FX Coudert <fxcoudert at gmail dot com>
- To: gfortran <fortran at gcc dot gnu dot org>, patch <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 02 Apr 2006 00:09:02 +0200
- Subject: [libgfortran] FPE support for ppc-darwin
Attached patch should add support for
-ffpe-trap={zero,denormal,precision,underflow,overflow} on ppc-darwin.
Unfortunately, I don't have access to such computer any more, so I'm
looking for someone to test this patch. Once compiled, you can test it
with, eg:
$ cat a.f
real*8 x
x = -1
print *, sqrt(x)
end
$ gfortran a.f && ./a.out
NaN
$ gfortran a.f -ffpe-trap=invalid && ./a.out
Floating point exception
Thanks!
FX
Index: configure.host
===================================================================
--- configure.host (revision 112610)
+++ configure.host (working copy)
@@ -24,6 +24,8 @@
case "${host_cpu}" in
i?86 | x86_64)
fpu_host='fpu-387' ;;
+ powerpc*-*-darwin*)
+ fpu_host='fpu-ppc-darwin' ;;
esac
# CONFIGURATION-SPECIFIC OVERRIDES
Index: config/fpu-ppc-darwin.h
===================================================================
--- config/fpu-ppc-darwin.h (revision 0)
+++ config/fpu-ppc-darwin.h (revision 0)
@@ -0,0 +1,86 @@
+/* FPU-related code for Darwin on PowerPC
+ Copyright 2006 Free Software Foundation, Inc.
+ Contributed by Francois-Xavier Coudert <coudert@clipper.ens.fr>
+
+This file is part of the GNU Fortran 95 runtime library (libgfortran).
+
+Libgfortran 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 2 of the License, or (at your option) any later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+Libgfortran 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 libgfortran; see the file COPYING. If not,
+write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include <fenv.h>
+#include <signal.h>
+#include <ucontext.h>
+#include <mach/thread_status.h>
+#include <stdlib.h>
+
+#include "io/io.h"
+
+/* From http://developer.apple.com/documentation/Performance/Conceptual/Mac_OSX_Numerics/Mac_OSX_Numerics.pdf , page 7-15. */
+
+#define fegetenvd(x) asm volatile("mffs %0" : "=f" (x));
+#define fesetenvd(x) asm volatile("mtfsf 255,%0" : : "f" (x));
+
+enum {
+ FE_ENABLE_INEXACT = 0x00000008,
+ FE_ENABLE_DIVBYZERO = 0x00000010,
+ FE_ENABLE_UNDERFLOW = 0x00000020,
+ FE_ENABLE_OVERFLOW = 0x00000040,
+ FE_ENABLE_INVALID = 0x00000080,
+ FE_ENABLE_ALL_EXCEPT = 0x000000F8
+};
+
+typedef union {
+ struct {
+ unsigned long hi;
+ unsigned long lo;
+ } i;
+ double d;
+} hexdouble;
+
+static void sighandler (int signum)
+{
+ signal (signum, SIG_DFL);
+ runtime_error ("Floating Point Exception");
+}
+
+void set_fpu (void)
+{
+ hexdouble t;
+
+ fegetenvd(t.d);
+ if (options.fpe & GFC_FPE_DENORMAL)
+ st_printf ("Fortran runtime warning: IEEE 'denormal number' "
+ "exception not supported.\n");
+ if (options.fpe & GFC_FPE_PRECISION)
+ t.i.lo |= FE_ENABLE_INEXACT;
+ if (options.fpe & GFC_FPE_ZERO)
+ t.i.lo |= FE_ENABLE_DIVBYZERO;
+ if (options.fpe & GFC_FPE_UNDERFLOW)
+ t.i.lo |= FE_ENABLE_UNDERFLOW;
+ if (options.fpe & GFC_FPE_OVERFLOW)
+ t.i.lo |= FE_ENABLE_OVERFLOW;
+ if (options.fpe & GFC_FPE_INVALID)
+ t.i.lo |= FE_ENABLE_INVALID;
+ fesetenvd(t.d);
+}