From patchwork Tue May 22 01:45:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: rbmj X-Patchwork-Id: 160522 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 56F7CB6F9D for ; Tue, 22 May 2012 11:45:56 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1338255957; h=Comment: DomainKey-Signature:Received:Received:Received:Received: Message-id:Date:From:User-Agent:MIME-version:To:Subject: Content-type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=DihrC/1 Q5e0sbsf6L6J/g7PcJXI=; b=mCFOEnHPONhidld+uXcb+3ljuNrhcRYmGleY2Ph cIqGm6S+mRArpHJSrHiRGVHddLSBrX4SeotU6jrx+z1IGswEHxpBswTjx4nEU/UV YZ5tUMmx5J4kd97O8IhVZUGGEf1vXDp5mleRxwryOWC5nuyHVOAVz3Kd8YbTl8Xp AuCc= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Message-id:Date:From:User-Agent:MIME-version:To:Subject:Content-type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=qX48ZLg7E+L4U9pq4ibYZk6eZFDqtYze0JtEar7Lkjd8sS3hY/PXdGQRv4izFB r42n23TStVpNIQchYS0ctkDa27CAKrrEeyPv1WPxSHbjY/JHL874t66HgQKsYzkH zzwggDf49VUPMP+JmUt7O+n7kmA+qh5QLtpg0/6kyDBxE=; Received: (qmail 19590 invoked by alias); 22 May 2012 01:45:50 -0000 Received: (qmail 19580 invoked by uid 22791); 22 May 2012 01:45:45 -0000 X-SWARE-Spam-Status: No, hits=3.0 required=5.0 tests=BAYES_00, BOTNET, RCVD_IN_DNSWL_NONE, RCVD_IN_HOSTKARMA_NO, RCVD_IN_HOSTKARMA_YE, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from vms173015pub.verizon.net (HELO vms173015pub.verizon.net) (206.46.173.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 22 May 2012 01:45:20 +0000 Received: from [192.168.1.9] ([unknown] [96.241.225.152]) by vms173015.mailsrvcs.net (Sun Java(tm) System Messaging Server 7u2-7.02 32bit (built Apr 16 2009)) with ESMTPA id <0M4E00LHCI73MXD0@vms173015.mailsrvcs.net> for gcc-patches@gcc.gnu.org; Mon, 21 May 2012 20:45:04 -0500 (CDT) Message-id: <4FBAEF9F.9000402@verizon.net> Date: Mon, 21 May 2012 21:45:03 -0400 From: rbmj User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120329 Thunderbird/11.0.1 MIME-version: 1.0 To: gcc-patches@gcc.gnu.org Subject: [Patch, libgfortran] Add FPU Support for powerpc Content-type: multipart/mixed; boundary=------------030503020108060203000301 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi everyone, This patch adds FPU support for powerpc on platforms that do not have glibc. It is basically the same code as glibc has. The motivation for this was that right now there is no fpu-target.h that works for powerpc-*-vxworks. Again, 90% of this code comes directly from glibc. But on vxworks targets there is no glibc. I also patched the configure.host script in order to add this in. Any opinions? Robert Mason From f9449738730fa0d460a30affa826a157bf97cf62 Mon Sep 17 00:00:00 2001 From: rbmj Date: Mon, 21 May 2012 15:56:06 -0400 Subject: [PATCH 3/6] Add FPU Support for PPC on VxWorks libgfortran/config/fpu-ppc.h: Started work on a fpu-target.h that will work for VxWorks on PPC. 90% of it is stolen from glibc. I just took the necessary pieces and added the right VxWorks glue. I made as few changes to the glibc code as possible in order to avoid introducing a bug. The VxWorks part seems to be correct, but I don't have a whole lot of experience in this area and documentation is incomplete. libgfortran/configure.host: This just adds fpu-ppc.h to the list of targets. For some reason, my powerpc-wrs-vxworks is getting mis-identified as AIX, even though it does not have the functions, so I'll also have to work on a patch for configure.ac. I'll check on that. Also, I put it before glibc so that glibc targets will get to use glibc and not rely on my cruft. --- libgfortran/config/fpu-ppc.h | 407 ++++++++++++++++++++++++++++++++++++++++++ libgfortran/configure.host | 11 ++ 2 files changed, 418 insertions(+), 0 deletions(-) create mode 100644 libgfortran/config/fpu-ppc.h diff --git a/libgfortran/config/fpu-ppc.h b/libgfortran/config/fpu-ppc.h new file mode 100644 index 0000000..f27df7f --- /dev/null +++ b/libgfortran/config/fpu-ppc.h @@ -0,0 +1,407 @@ +/* FPU-related code for systems without glibc on powerpc. + Copyright (C) 1997, 1998, 1999, 2008 Free Software Foundation, Inc. + +This file is part of the GNU Fortran runtime library (libgfortran). +This file incorporates code from the GNU C Library (glibc) under the GNU LGPL. + +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 3 of the License, or (at your option) any later version. + +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. + +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 +. */ + +/* FPU Types/Constants: */ + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. We leave it as 'double' + for efficiency reasons (rather than writing it to a 32-bit integer). */ +typedef double fenv_t; + +/* We want to specify the bit pattern of the __fe_*_env constants, so + pretend they're really `long long' instead of `double'. */ + +/* If the default argument is used we use this value. */ +const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = +0xfff8000000000000ULL; +#define FE_DFL_ENV ((double*)(&__fe_dfl_env)) + +/* Floating-point environment where all exceptions are enabled. Note that + this is not sufficient to give you SIGFPE. */ +const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = +0xfff80000000000f8ULL; +# define FE_ENABLED_ENV ((double*)(&__fe_enabled_env)) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. */ +const unsigned long long __fe_nonieee_env __attribute__ ((aligned (8))) = +0xfff8000000000004ULL; +# define FE_NONIEEE_ENV ((double*)(&__fe_nonieee_env)) + +/* Provide __fe_mask_env and __fe_nomask_env */ +#ifdef __VXWORKS__ + +/* These are based loosly off of glibc + + see also glibc/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe{,no}mask.c + */ + +#include +#include + +#if !defined (_PPC_MSR_FE0) || !defined (_PPC_MSR_FE1) +#error FPU Support does not appear to exist on target platform +#else + +const fenv_t * +__fe_nomask_env(void) +{ + UINT32 msr = vxMsrGet(); + msr |= _PPC_MSR_FE0 | _PPC_MSR_FE1; + vxMsrSet(msr); + return FE_ENABLED_ENV; +} + +const fenv_t * +__fe_nomask_env(void) +{ + UINT32 msr = vxMsrGet(); + msr &= ~(_PPC_MSR_FE0 | _PPC_MSR_FE1); + vxMsrSet(msr); + return FE_DFL_ENV; +} + +#endif + +#else + +/* VxWorks is the only OS that this header supports so far. It would be trivial + to also support Linux on PowerPC, but this should be unnecessary as Linux + uses glibc so fpu-glibc.h should be used instead anyway. */ + +/* These stubs won't work... error unless there's reason not to do so: */ +#error Unsupported target, use fpu-glibc.h or similar instead. + +#include + +/* This is a generic stub. An OS specific override is required to set + the FE0/FE1 bits in the MSR. MSR update is privileged, so this will + normally involve a syscall. */ + +const fenv_t * +__fe_nomask_env(void) +{ + __set_errno (ENOSYS); + return FE_ENABLED_ENV; +} + +/* This is a generic stub. An OS specific override is required to clear + the FE0/FE1 bits in the MSR. MSR update is privileged, so this will + normally involve a syscall. */ + +const fenv_t * +__fe_mask_env(void) +{ + __set_errno (ENOSYS); + return FE_DFL_ENV; +} +#endif + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSCR... */ +enum + { + FE_INEXACT = 1 << (31 - 6), +#define FE_INEXACT FE_INEXACT + FE_DIVBYZERO = 1 << (31 - 5), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << (31 - 4), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << (31 - 3), +#define FE_OVERFLOW FE_OVERFLOW + + /* ... except for FE_INVALID, for which we use bit 31. FE_INVALID + actually corresponds to bits 7 through 12 and 21 through 23 + in the FPSCR, but we can't use that because the current draft + says that it must be a power of 2. Instead we use bit 2 which + is the summary bit for all the FE_INVALID exceptions, which + kind of makes sense. */ + FE_INVALID = 1 << (31 - 2), +#define FE_INVALID FE_INVALID + + /* Breakdown of the FE_INVALID bits. Setting FE_INVALID on an + input to a routine is equivalent to setting all of these bits; + FE_INVALID will be set on output from a routine iff one of + these bits is set. Note, though, that you can't disable or + enable these exceptions individually. */ + + /* Operation with SNaN. */ + FE_INVALID_SNAN = 1 << (31 - 7), +# define FE_INVALID_SNAN FE_INVALID_SNAN + + /* Inf - Inf */ + FE_INVALID_ISI = 1 << (31 - 8), +# define FE_INVALID_ISI FE_INVALID_ISI + + /* Inf / Inf */ + FE_INVALID_IDI = 1 << (31 - 9), +# define FE_INVALID_IDI FE_INVALID_IDI + + /* 0 / 0 */ + FE_INVALID_ZDZ = 1 << (31 - 10), +# define FE_INVALID_ZDZ FE_INVALID_ZDZ + + /* Inf * 0 */ + FE_INVALID_IMZ = 1 << (31 - 11), +# define FE_INVALID_IMZ FE_INVALID_IMZ + + /* Comparison with NaN or SNaN. */ + FE_INVALID_COMPARE = 1 << (31 - 12), +# define FE_INVALID_COMPARE FE_INVALID_COMPARE + + /* Invalid operation flag for software (not set by hardware). */ + /* Note that some chips don't have this implemented, presumably + because no-one expected anyone to write software for them %-). */ + FE_INVALID_SOFTWARE = 1 << (31 - 21), +# define FE_INVALID_SOFTWARE FE_INVALID_SOFTWARE + + /* Square root of negative number (including -Inf). */ + /* Note that some chips don't have this implemented. */ + FE_INVALID_SQRT = 1 << (31 - 22), +# define FE_INVALID_SQRT FE_INVALID_SQRT + + /* Conversion-to-integer of a NaN or a number too large or too small. */ + FE_INVALID_INTEGER_CONVERSION = 1 << (31 - 23) +# define FE_INVALID_INTEGER_CONVERSION FE_INVALID_INTEGER_CONVERSION + +# define FE_ALL_INVALID \ + (FE_INVALID_SNAN | FE_INVALID_ISI | FE_INVALID_IDI | FE_INVALID_ZDZ \ + | FE_INVALID_IMZ | FE_INVALID_COMPARE | FE_INVALID_SOFTWARE \ + | FE_INVALID_SQRT | FE_INVALID_INTEGER_CONVERSION) + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* PowerPC chips support all of the four defined rounding modes. We + use the bit pattern in the FPSCR as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 3 +#define FE_DOWNWARD FE_DOWNWARD + }; + +/* Floating-point environment with all exceptions enabled. Note that + just evaluating this value does not change the processor exception mode. + Passing this mask to fesetenv will result in a prctl syscall to change + the MSR FE0/FE1 bits to "Precise Mode". On some processors this will + result in slower floating point execution. This will last until an + fenv or exception mask is installed that disables all FP exceptions. */ +# define FE_NOMASK_ENV FE_ENABLED_ENV + +/* Floating-point environment with all exceptions disabled. Note that + just evaluating this value does not change the processor exception mode. + Passing this mask to fesetenv will result in a prctl syscall to change + the MSR FE0/FE1 bits to "Ignore Exceptions Mode". On most processors + this allows the fastest possible floating point execution.*/ +# define FE_MASK_ENV FE_DFL_ENV + +/* Type to represent floating point environment */ + +typedef union +{ + fenv_t fenv; + unsigned int l[2]; +} fenv_union_t; + +/* Set/Get FPSCR Register */ + +#define fegetenv_register() \ + ({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; }) + +#define fesetenv_register(env) \ + do { \ + double d = (env); \ + if(GLRO(dl_hwcap) & PPC_FEATURE_HAS_DFP) \ + asm volatile (".machine push; " \ + ".machine \"power6\"; " \ + "mtfsf 0xff,%0,1,0; " \ + ".machine pop" : : "f" (d)); \ + else \ + asm volatile ("mtfsf 0xff,%0" : : "f" (d)); \ + } while(0) + +#ifdef __cplusplus +extern "C" { +#endif + +int +__fegetexcept (void) +{ + fenv_union_t fe; + int result = 0; + + fe.fenv = fegetenv_register (); + + if (fe.l[1] & (1 << (31 - FPSCR_XE))) + result |= FE_INEXACT; + if (fe.l[1] & (1 << (31 - FPSCR_ZE))) + result |= FE_DIVBYZERO; + if (fe.l[1] & (1 << (31 - FPSCR_UE))) + result |= FE_UNDERFLOW; + if (fe.l[1] & (1 << (31 - FPSCR_OE))) + result |= FE_OVERFLOW; + if (fe.l[1] & (1 << (31 - FPSCR_VE))) + result |= FE_INVALID; + + return result; +} + +int +feenableexcept (int excepts) +{ + fenv_union_t fe; + int result, new; + + result = __fegetexcept (); + + if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) + excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; + + fe.fenv = fegetenv_register (); + if (excepts & FE_INEXACT) + fe.l[1] |= (1 << (31 - FPSCR_XE)); + if (excepts & FE_DIVBYZERO) + fe.l[1] |= (1 << (31 - FPSCR_ZE)); + if (excepts & FE_UNDERFLOW) + fe.l[1] |= (1 << (31 - FPSCR_UE)); + if (excepts & FE_OVERFLOW) + fe.l[1] |= (1 << (31 - FPSCR_OE)); + if (excepts & FE_INVALID) + fe.l[1] |= (1 << (31 - FPSCR_VE)); + fesetenv_register (fe.fenv); + + new = __fegetexcept (); + if (new != 0 && result == 0) + (void)__fe_nomask_env (); + + if ((new & excepts) != excepts) + result = -1; + + return result; +} + +int +fedisableexcept (int excepts) +{ + fenv_union_t fe; + int result, new; + + result = __fegetexcept (); + + if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) + excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; + + fe.fenv = fegetenv_register (); + if (excepts & FE_INEXACT) + fe.l[1] &= ~(1 << (31 - FPSCR_XE)); + if (excepts & FE_DIVBYZERO) + fe.l[1] &= ~(1 << (31 - FPSCR_ZE)); + if (excepts & FE_UNDERFLOW) + fe.l[1] &= ~(1 << (31 - FPSCR_UE)); + if (excepts & FE_OVERFLOW) + fe.l[1] &= ~(1 << (31 - FPSCR_OE)); + if (excepts & FE_INVALID) + fe.l[1] &= ~(1 << (31 - FPSCR_VE)); + fesetenv_register (fe.fenv); + + new = __fegetexcept (); + if (new == 0 && result != 0) + (void)__fe_mask_env (); + + if ((new & excepts) != 0) + result = -1; + return result; +} + +/* This is from fpu-glibc.h: This is what *all of the above* is for */ + +void set_fpu (void) +{ + if (FE_ALL_EXCEPT != 0) + fedisableexcept (FE_ALL_EXCEPT); + + if (options.fpe & GFC_FPE_INVALID) +#ifdef FE_INVALID + feenableexcept (FE_INVALID); +#else + estr_write ("Fortran runtime warning: IEEE 'invalid operation' " + "exception not supported.\n"); +#endif + +/* glibc does never have a FE_DENORMAL. */ + if (options.fpe & GFC_FPE_DENORMAL) +#ifdef FE_DENORMAL + feenableexcept (FE_DENORMAL); +#else + estr_write ("Fortran runtime warning: Floating point 'denormal operand' " + "exception not supported.\n"); +#endif + + if (options.fpe & GFC_FPE_ZERO) +#ifdef FE_DIVBYZERO + feenableexcept (FE_DIVBYZERO); +#else + estr_write ("Fortran runtime warning: IEEE 'division by zero' " + "exception not supported.\n"); +#endif + + if (options.fpe & GFC_FPE_OVERFLOW) +#ifdef FE_OVERFLOW + feenableexcept (FE_OVERFLOW); +#else + estr_write ("Fortran runtime warning: IEEE 'overflow' " + "exception not supported.\n"); +#endif + + if (options.fpe & GFC_FPE_UNDERFLOW) +#ifdef FE_UNDERFLOW + feenableexcept (FE_UNDERFLOW); +#else + estr_write ("Fortran runtime warning: IEEE 'underflow' " + "exception not supported.\n"); +#endif + + if (options.fpe & GFC_FPE_INEXACT) +#ifdef FE_INEXACT + feenableexcept (FE_INEXACT); +#else + estr_write ("Fortran runtime warning: IEEE 'inexact' " + "exception not supported.\n"); +#endif +} + +#ifdef __cplusplus +} +#endif diff --git a/libgfortran/configure.host b/libgfortran/configure.host index 92b6433..5e4af03 100644 --- a/libgfortran/configure.host +++ b/libgfortran/configure.host @@ -20,6 +20,17 @@ # DEFAULTS fpu_host='fpu-generic' +# powerpc asm fpu_host based off of glibc for systems without glibc +# this is before the glibc test so that fpu-glibc will override it, as +# it requires a *small* amount of OS support (which is only implemented +# right now with VxWorks), and since it is based off of glibc in theory +# glibc will always be better/more current/more optimized. + +case "${host_cpu}" in + powerpc) + fpu_host='fpu-ppc' ;; +esac + if test "x${have_feenableexcept}" = "xyes"; then fpu_host='fpu-glibc' fi -- 1.7.5.4