xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/ieee/ieee_exceptions.F90 (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg!    Implementation of the IEEE_EXCEPTIONS standard intrinsic module
2*4c3eb207Smrg!    Copyright (C) 2013-2020 Free Software Foundation, Inc.
3627f7eb2Smrg!    Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
4627f7eb2Smrg!
5627f7eb2Smrg! This file is part of the GNU Fortran runtime library (libgfortran).
6627f7eb2Smrg!
7627f7eb2Smrg! Libgfortran is free software; you can redistribute it and/or
8627f7eb2Smrg! modify it under the terms of the GNU General Public
9627f7eb2Smrg! License as published by the Free Software Foundation; either
10627f7eb2Smrg! version 3 of the License, or (at your option) any later version.
11627f7eb2Smrg!
12627f7eb2Smrg! Libgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrg! but WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2Smrg! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15627f7eb2Smrg! GNU General Public License for more details.
16627f7eb2Smrg!
17627f7eb2Smrg! Under Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrg! permissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg! 3.1, as published by the Free Software Foundation.
20627f7eb2Smrg!
21627f7eb2Smrg! You should have received a copy of the GNU General Public License and
22627f7eb2Smrg! a copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrg! see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24627f7eb2Smrg! <http://www.gnu.org/licenses/>.  */
25627f7eb2Smrg
26627f7eb2Smrg#include "config.h"
27627f7eb2Smrg#include "kinds.inc"
28627f7eb2Smrg#include "c99_protos.inc"
29627f7eb2Smrg#include "fpu-target.inc"
30627f7eb2Smrg
31627f7eb2Smrgmodule IEEE_EXCEPTIONS
32627f7eb2Smrg
33627f7eb2Smrg  implicit none
34627f7eb2Smrg  private
35627f7eb2Smrg
36627f7eb2Smrg! Derived types and named constants
37627f7eb2Smrg
38627f7eb2Smrg  type, public :: IEEE_FLAG_TYPE
39627f7eb2Smrg    private
40627f7eb2Smrg    integer :: hidden
41627f7eb2Smrg  end type
42627f7eb2Smrg
43627f7eb2Smrg  type(IEEE_FLAG_TYPE), parameter, public :: &
44627f7eb2Smrg    IEEE_INVALID        = IEEE_FLAG_TYPE(GFC_FPE_INVALID), &
45627f7eb2Smrg    IEEE_OVERFLOW       = IEEE_FLAG_TYPE(GFC_FPE_OVERFLOW), &
46627f7eb2Smrg    IEEE_DIVIDE_BY_ZERO = IEEE_FLAG_TYPE(GFC_FPE_ZERO), &
47627f7eb2Smrg    IEEE_UNDERFLOW      = IEEE_FLAG_TYPE(GFC_FPE_UNDERFLOW), &
48627f7eb2Smrg    IEEE_INEXACT        = IEEE_FLAG_TYPE(GFC_FPE_INEXACT)
49627f7eb2Smrg
50627f7eb2Smrg  type(IEEE_FLAG_TYPE), parameter, public :: &
51627f7eb2Smrg    IEEE_USUAL(3) = [ IEEE_OVERFLOW, IEEE_DIVIDE_BY_ZERO, IEEE_INVALID ], &
52627f7eb2Smrg    IEEE_ALL(5)   = [ IEEE_USUAL, IEEE_UNDERFLOW, IEEE_INEXACT ]
53627f7eb2Smrg
54627f7eb2Smrg  type, public :: IEEE_STATUS_TYPE
55627f7eb2Smrg    private
56627f7eb2Smrg    character(len=GFC_FPE_STATE_BUFFER_SIZE) :: hidden
57627f7eb2Smrg  end type
58627f7eb2Smrg
59627f7eb2Smrg  interface IEEE_SUPPORT_FLAG
60627f7eb2Smrg    module procedure IEEE_SUPPORT_FLAG_4, &
61627f7eb2Smrg                     IEEE_SUPPORT_FLAG_8, &
62627f7eb2Smrg#ifdef HAVE_GFC_REAL_10
63627f7eb2Smrg                     IEEE_SUPPORT_FLAG_10, &
64627f7eb2Smrg#endif
65627f7eb2Smrg#ifdef HAVE_GFC_REAL_16
66627f7eb2Smrg                     IEEE_SUPPORT_FLAG_16, &
67627f7eb2Smrg#endif
68627f7eb2Smrg                     IEEE_SUPPORT_FLAG_NOARG
69627f7eb2Smrg  end interface IEEE_SUPPORT_FLAG
70627f7eb2Smrg
71627f7eb2Smrg  public :: IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
72627f7eb2Smrg  public :: IEEE_SET_HALTING_MODE, IEEE_GET_HALTING_MODE
73627f7eb2Smrg  public :: IEEE_SET_FLAG, IEEE_GET_FLAG
74627f7eb2Smrg  public :: IEEE_SET_STATUS, IEEE_GET_STATUS
75627f7eb2Smrg
76627f7eb2Smrgcontains
77627f7eb2Smrg
78627f7eb2Smrg! Saving and restoring floating-point status
79627f7eb2Smrg
80627f7eb2Smrg  subroutine IEEE_GET_STATUS (STATUS_VALUE)
81627f7eb2Smrg    implicit none
82627f7eb2Smrg    type(IEEE_STATUS_TYPE), intent(out) :: STATUS_VALUE
83627f7eb2Smrg
84627f7eb2Smrg    interface
85627f7eb2Smrg      subroutine helper(ptr) &
86627f7eb2Smrg          bind(c, name="_gfortrani_get_fpu_state")
87627f7eb2Smrg        use, intrinsic :: iso_c_binding, only : c_char
88627f7eb2Smrg        character(kind=c_char) :: ptr(*)
89627f7eb2Smrg      end subroutine
90627f7eb2Smrg    end interface
91627f7eb2Smrg
92627f7eb2Smrg    call helper(STATUS_VALUE%hidden)
93627f7eb2Smrg  end subroutine
94627f7eb2Smrg
95627f7eb2Smrg  subroutine IEEE_SET_STATUS (STATUS_VALUE)
96627f7eb2Smrg    implicit none
97627f7eb2Smrg    type(IEEE_STATUS_TYPE), intent(in) :: STATUS_VALUE
98627f7eb2Smrg
99627f7eb2Smrg    interface
100627f7eb2Smrg      subroutine helper(ptr) &
101627f7eb2Smrg          bind(c, name="_gfortrani_set_fpu_state")
102627f7eb2Smrg        use, intrinsic :: iso_c_binding, only : c_char
103627f7eb2Smrg        character(kind=c_char) :: ptr(*)
104627f7eb2Smrg      end subroutine
105627f7eb2Smrg    end interface
106627f7eb2Smrg
107627f7eb2Smrg    call helper(STATUS_VALUE%hidden)
108627f7eb2Smrg  end subroutine
109627f7eb2Smrg
110627f7eb2Smrg! Getting and setting flags
111627f7eb2Smrg
112627f7eb2Smrg  elemental subroutine IEEE_GET_FLAG (FLAG, FLAG_VALUE)
113627f7eb2Smrg    implicit none
114627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
115627f7eb2Smrg    logical, intent(out) :: FLAG_VALUE
116627f7eb2Smrg
117627f7eb2Smrg    interface
118627f7eb2Smrg      pure integer function helper() &
119627f7eb2Smrg        bind(c, name="_gfortrani_get_fpu_except_flags")
120627f7eb2Smrg      end function
121627f7eb2Smrg    end interface
122627f7eb2Smrg
123627f7eb2Smrg    FLAG_VALUE = (IAND(helper(), FLAG%hidden) /= 0)
124627f7eb2Smrg  end subroutine
125627f7eb2Smrg
126627f7eb2Smrg  elemental subroutine IEEE_SET_FLAG (FLAG, FLAG_VALUE)
127627f7eb2Smrg    implicit none
128627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
129627f7eb2Smrg    logical, intent(in) :: FLAG_VALUE
130627f7eb2Smrg
131627f7eb2Smrg    interface
132627f7eb2Smrg      pure subroutine helper(set, clear) &
133627f7eb2Smrg          bind(c, name="_gfortrani_set_fpu_except_flags")
134627f7eb2Smrg        integer, intent(in), value :: set, clear
135627f7eb2Smrg      end subroutine
136627f7eb2Smrg    end interface
137627f7eb2Smrg
138627f7eb2Smrg    if (FLAG_VALUE) then
139627f7eb2Smrg      call helper(FLAG%hidden, 0)
140627f7eb2Smrg    else
141627f7eb2Smrg      call helper(0, FLAG%hidden)
142627f7eb2Smrg    end if
143627f7eb2Smrg  end subroutine
144627f7eb2Smrg
145627f7eb2Smrg! Querying and changing the halting mode
146627f7eb2Smrg
147627f7eb2Smrg  elemental subroutine IEEE_GET_HALTING_MODE (FLAG, HALTING)
148627f7eb2Smrg    implicit none
149627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
150627f7eb2Smrg    logical, intent(out) :: HALTING
151627f7eb2Smrg
152627f7eb2Smrg    interface
153627f7eb2Smrg      pure integer function helper() &
154627f7eb2Smrg          bind(c, name="_gfortrani_get_fpu_trap_exceptions")
155627f7eb2Smrg      end function
156627f7eb2Smrg    end interface
157627f7eb2Smrg
158627f7eb2Smrg    HALTING = (IAND(helper(), FLAG%hidden) /= 0)
159627f7eb2Smrg  end subroutine
160627f7eb2Smrg
161627f7eb2Smrg  elemental subroutine IEEE_SET_HALTING_MODE (FLAG, HALTING)
162627f7eb2Smrg    implicit none
163627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
164627f7eb2Smrg    logical, intent(in) :: HALTING
165627f7eb2Smrg
166627f7eb2Smrg    interface
167627f7eb2Smrg      pure subroutine helper(trap, notrap) &
168627f7eb2Smrg          bind(c, name="_gfortrani_set_fpu_trap_exceptions")
169627f7eb2Smrg        integer, intent(in), value :: trap, notrap
170627f7eb2Smrg      end subroutine
171627f7eb2Smrg    end interface
172627f7eb2Smrg
173627f7eb2Smrg    if (HALTING) then
174627f7eb2Smrg      call helper(FLAG%hidden, 0)
175627f7eb2Smrg    else
176627f7eb2Smrg      call helper(0, FLAG%hidden)
177627f7eb2Smrg    end if
178627f7eb2Smrg  end subroutine
179627f7eb2Smrg
180627f7eb2Smrg! Querying support
181627f7eb2Smrg
182627f7eb2Smrg  pure logical function IEEE_SUPPORT_HALTING (FLAG)
183627f7eb2Smrg    implicit none
184627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
185627f7eb2Smrg
186627f7eb2Smrg    interface
187627f7eb2Smrg      pure integer function helper(flag) &
188627f7eb2Smrg          bind(c, name="_gfortrani_support_fpu_trap")
189627f7eb2Smrg        integer, intent(in), value :: flag
190627f7eb2Smrg      end function
191627f7eb2Smrg    end interface
192627f7eb2Smrg
193627f7eb2Smrg    IEEE_SUPPORT_HALTING = (helper(FLAG%hidden) /= 0)
194627f7eb2Smrg  end function
195627f7eb2Smrg
196627f7eb2Smrg  pure logical function IEEE_SUPPORT_FLAG_NOARG (FLAG)
197627f7eb2Smrg    implicit none
198627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
199627f7eb2Smrg
200627f7eb2Smrg    interface
201627f7eb2Smrg      pure integer function helper(flag) &
202627f7eb2Smrg          bind(c, name="_gfortrani_support_fpu_flag")
203627f7eb2Smrg        integer, intent(in), value :: flag
204627f7eb2Smrg      end function
205627f7eb2Smrg    end interface
206627f7eb2Smrg
207627f7eb2Smrg    IEEE_SUPPORT_FLAG_NOARG = (helper(FLAG%hidden) /= 0)
208627f7eb2Smrg  end function
209627f7eb2Smrg
210627f7eb2Smrg  pure logical function IEEE_SUPPORT_FLAG_4 (FLAG, X) result(res)
211627f7eb2Smrg    implicit none
212627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
213627f7eb2Smrg    real(kind=4), intent(in) :: X
214627f7eb2Smrg    res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
215627f7eb2Smrg  end function
216627f7eb2Smrg
217627f7eb2Smrg  pure logical function IEEE_SUPPORT_FLAG_8 (FLAG, X) result(res)
218627f7eb2Smrg    implicit none
219627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
220627f7eb2Smrg    real(kind=8), intent(in) :: X
221627f7eb2Smrg    res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
222627f7eb2Smrg  end function
223627f7eb2Smrg
224627f7eb2Smrg#ifdef HAVE_GFC_REAL_10
225627f7eb2Smrg  pure logical function IEEE_SUPPORT_FLAG_10 (FLAG, X) result(res)
226627f7eb2Smrg    implicit none
227627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
228627f7eb2Smrg    real(kind=10), intent(in) :: X
229627f7eb2Smrg    res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
230627f7eb2Smrg  end function
231627f7eb2Smrg#endif
232627f7eb2Smrg
233627f7eb2Smrg#ifdef HAVE_GFC_REAL_16
234627f7eb2Smrg  pure logical function IEEE_SUPPORT_FLAG_16 (FLAG, X) result(res)
235627f7eb2Smrg    implicit none
236627f7eb2Smrg    type(IEEE_FLAG_TYPE), intent(in) :: FLAG
237627f7eb2Smrg    real(kind=16), intent(in) :: X
238627f7eb2Smrg    res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
239627f7eb2Smrg  end function
240627f7eb2Smrg#endif
241627f7eb2Smrg
242627f7eb2Smrgend module IEEE_EXCEPTIONS
243