1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
|
From: "Barak A. Pearlmutter" <barak+git@pearlmutter.net>
Date: Mon, 11 Jan 2016 20:45:51 +0000
Subject: C tweaks
---
unix/f2c/libf2c/uninit.c | 202 +++++++++++++++++++++++++++++++++--------------
1 file changed, 144 insertions(+), 58 deletions(-)
diff --git a/unix/f2c/libf2c/uninit.c b/unix/f2c/libf2c/uninit.c
index f15fe39..93c8be5 100644
--- a/unix/f2c/libf2c/uninit.c
+++ b/unix/f2c/libf2c/uninit.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "arith.h"
#define TYSHORT 2
@@ -15,24 +16,24 @@
#endif
#ifdef __mips
-#define RNAN 0xffc00000
-#define DNAN0 0xfff80000
+#define RNAN 0xffc00000 /* Quiet NaN */
+#define DNAN0 0xfff80000 /* Signalling NaN double Big endian */
#define DNAN1 0
#endif
#ifdef _PA_RISC1_1
-#define RNAN 0xffc00000
+#define RNAN 0xffc00000 /* Quiet Nan -- big endian */
#define DNAN0 0xfff80000
#define DNAN1 0
#endif
#ifndef RNAN
#define RNAN 0xff800001
-#ifdef IEEE_MC68k
-#define DNAN0 0xfff00000
+#ifdef IEEE_MC68k /* set on PPC*/
+#define DNAN0 0xfff00000 /* Quiet NaN big endian */
#define DNAN1 1
#else
-#define DNAN0 1
+#define DNAN0 1 /* LSB, MSB for little endian machines */
#define DNAN1 0xfff00000
#endif
#endif /*RNAN*/
@@ -57,6 +58,15 @@ static unsigned Long rnan = RNAN,
double _0 = 0.;
+void unsupported_error()
+{
+ fprintf(stderr,"Runtime Error: Your Architecture is not supported by the"
+ " -trapuv option of f2c\n");
+ exit(-1);
+}
+
+
+
void
#ifdef KR_headers
_uninit_f2c(x, type, len) void *x; int type; long len;
@@ -178,7 +188,8 @@ ieee0(Void)
}
#endif /* MSpc */
-#ifdef __mips /* must link with -lfpe */
+/* What follows is for SGI IRIX only */
+#if defined(__mips) && defined(__sgi) /* must link with -lfpe */
#define IEEE0_done
/* code from Eric Grosse */
#include <stdlib.h>
@@ -229,11 +240,65 @@ ieee0(Void)
_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,
ieeeuserhand,_ABORT_ON_ERROR,ieeeuserhand2);
}
-#endif /* mips */
+#endif /* IRIX mips */
+
+/*
+ * The following is the preferred method but depends upon a GLIBC extension only
+ * to be found in GLIBC 2.2 or later. It is a GNU extension, not included in the
+ * C99 extensions which allow the FP status register to be examined in a platform
+ * independent way. It should be used if at all possible -- AFRB
+ */
+
+
+#if (defined(__GLIBC__)&& ( __GLIBC__>=2) && (__GLIBC_MINOR__>=2) )
+#define _GNU_SOURCE 1
+#define IEEE0_done
+#include <fenv.h>
+ static void
+ ieee0(Void)
+
+{
+ /* Clear all exception flags */
+ if (fedisableexcept(FE_ALL_EXCEPT)==-1)
+ unsupported_error();
+ if (feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW)==-1)
+ unsupported_error();
+}
+
+#endif /* Glibc control */
+
+/* Many linux cases will be treated through GLIBC. Note that modern
+ * linux runs on many non-i86 plaforms and as a result the following code
+ * must be processor dependent rather than simply OS specific */
-#ifdef __linux__
+#if (defined(__linux__)&&(!defined(IEEE0_done)))
#define IEEE0_done
-#include "fpu_control.h"
+#include <fpu_control.h>
+
+
+#ifdef __alpha__
+#ifndef USE_setfpucw
+#define __setfpucw(x) __fpu_control = (x)
+#endif
+#endif
+
+/* Not all versions of libc define _FPU_SETCW;
+ * * some only provide the __setfpucw() function.
+ * */
+#ifndef _FPU_SETCW
+#define _FPU_SETCW(cw) __setfpucw(cw)
+#endif
+
+/* The exact set of flags we want to set in the FPU control word
+ * depends on the architecture.
+ * Note also that whether an exception is enabled or disabled when
+ * the _FPU_MASK_nn bit is set is architecture dependent!
+ * Enabled-when-set: M68k, ARM, MIPS, PowerPC
+ * Disabled-when-set: x86, Alpha
+ * The state we are after is:
+ * exceptions on division by zero, overflow and invalid operation.
+ */
+
#ifdef __alpha__
#ifndef USE_setfpucw
@@ -241,67 +306,88 @@ ieee0(Void)
#endif
#endif
+
#ifndef _FPU_SETCW
#undef Can_use__setfpucw
#define Can_use__setfpucw
#endif
- static void
-ieee0(Void)
-{
+#undef RQD_FPU_MASK
+#undef RQD_FPU_CLEAR_MASK
+
#if (defined(__mc68000__) || defined(__mc68020__) || defined(mc68020) || defined (__mc68k__))
/* Reported 20010705 by Alan Bain <alanb@chiark.greenend.org.uk> */
/* Note that IEEE 754 IOP (illegal operation) */
/* = Signaling NAN (SNAN) + operation error (OPERR). */
-#ifdef Can_use__setfpucw
- __setfpucw(_FPU_IEEE + _FPU_DOUBLE + _FPU_MASK_OPERR + _FPU_MASK_DZ + _FPU_MASK_SNAN+_FPU_MASK_OVFL);
-#else
- __fpu_control = _FPU_IEEE + _FPU_DOUBLE + _FPU_MASK_OPERR + _FPU_MASK_DZ + _FPU_MASK_SNAN+_FPU_MASK_OVFL;
- _FPU_SETCW(__fpu_control);
-#endif
+#define RQD_FPU_STATE (_FPU_IEEE + _FPU_DOUBLE + _FPU_MASK_OPERR + \
+ _FPU_MASK_DZ + _FPU_MASK_SNAN+_FPU_MASK_OVFL)
+#define RQD_FPU_MASK (_FPU_MASK_OPERR+_FPU_MASK_DZ+_FPU_MASK_SNAN+_FPU_MASK_OVFL)
#elif (defined(__powerpc__)||defined(_ARCH_PPC)||defined(_ARCH_PWR)) /* !__mc68k__ */
-/* Reported 20011109 by Alan Bain <alanb@chiark.greenend.org.uk> */
-
-#ifdef Can_use__setfpucw
-
-/* The following is NOT a mistake -- the author of the fpu_control.h
-for the PPC has erroneously defined IEEE mode to turn on exceptions
-other than Inexact! Start from default then and turn on only the ones
-which we want*/
-
- __setfpucw(_FPU_DEFAULT + _FPU_MASK_IM+_FPU_MASK_OM+_FPU_MASK_UM);
-
-#else /* PPC && !Can_use__setfpucw */
-
- __fpu_control = _FPU_DEFAULT +_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_UM;
- _FPU_SETCW(__fpu_control);
-
-#endif /*Can_use__setfpucw*/
-
-#else /* !(mc68000||powerpc) */
-
-#ifdef _FPU_IEEE
-#ifndef _FPU_EXTENDED /* e.g., ARM processor under Linux */
-#define _FPU_EXTENDED 0
-#endif
-#ifndef _FPU_DOUBLE
-#define _FPU_DOUBLE 0
+ /* The following is NOT a mistake -- the author of the fpu_control.h
+ * for the PPC has erroneously defined IEEE mode to turn on exceptions
+ * other than Inexact! Start from default then and turn on only the ones
+ * which we want*/
+
+ /* I have changed _FPU_MASK_UM here to _FPU_MASK_ZM, because that is
+ * in line with all the other architectures specified here. -- AFRB
+ */
+#define RQD_FPU_STATE (_FPU_DEFAULT +_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_ZM)
+#define RQD_FPU_MASK (_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_ZM)
+
+#elif (defined(__arm__))
+ /* On ARM too, IEEE implies all exceptions enabled.
+ * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ * Unfortunately some version of ARMlinux don't include any
+ * flags in the fpu_control.h file
+ */
+#define RQD_FPU_STATE (_FPU_DEFAULT +_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_ZM)
+#define RQD_FPU_MASK (_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_ZM)
+
+#elif (defined(__mips__))
+ /* And same again for MIPS; _FPU_IEEE => exceptions seems a common meme.
+ * * MIPS uses different MASK constant names, no idea why -- PMM
+ * */
+#define RQD_FPU_STATE (_FPU_DEFAULT +_FPU_MASK_O+_FPU_MASK_V+_FPU_MASK_Z)
+#define RQD_FPU_MASK (_FPU_MASK_O+_FPU_MASK_V+_FPU_MASK_Z)
+
+#elif (defined(__sparc__))
+#define RQD_FPU_STATE (_FPU_DEFAULT +_FPU_DOUBLE+_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_ZM)
+#define RQD_FPU_MASK (_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_ZM)
+
+#elif (defined(__i386__) || defined(__alpha__))
+ /* This case is for Intel, and also Alpha, because the Alpha header
+ * purposely emulates x86 flags and meanings for compatibility with
+ * stupid programs.
+ * We used to try this case for anything defining _FPU_IEEE, but I think
+ * that that's a bad idea because it isn't really likely to work.
+ * Instead for unknown architectures we just won't allow -trapuv to work.
+ * Trying this case was just getting us
+ * (a) compile errors on archs which didn't know all these constants
+ * (b) silent wrong behaviour on archs (like SPARC) which do know all
+ * constants but have different semantics for them
+ */
+#define RQD_FPU_STATE (_FPU_IEEE - _FPU_EXTENDED + _FPU_DOUBLE - _FPU_MASK_IM - _FPU_MASK_ZM - _FPU_MASK_OM)
+#define RQD_FPU_CLEAR_MASK (_FPU_MASK_IM + _FPU_MASK_ZM + _FPU_MASK_OM)
#endif
-#ifdef Can_use__setfpucw /* pre-1997 (?) Linux */
- __setfpucw(_FPU_IEEE - _FPU_MASK_IM - _FPU_MASK_ZM - _FPU_MASK_OM);
-#else
-#ifdef UNINIT_F2C_PRECISION_53 /* 20051004 */
- /* unmask invalid, etc., and change rounding precision to double */
- __fpu_control = _FPU_IEEE - _FPU_EXTENDED + _FPU_DOUBLE - _FPU_MASK_IM - _FPU_MASK_ZM - _FPU_MASK_OM;
- _FPU_SETCW(__fpu_control);
-#else
+
+static void ieee0(Void)
+{
+#ifdef RQD_FPU_STATE
+
+#ifndef UNINIT_F2C_PRECISION_53 /* 20051004 */
+ __fpu_control = RQD_FPU_STATE;
+ _FPU_SETCW(__fpu_control);
+#else
/* unmask invalid, etc., and keep current rounding precision */
fpu_control_t cw;
_FPU_GETCW(cw);
- cw &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM);
- _FPU_SETCW(cw);
+#ifdef RQD_FPU_CLEAR_MASK
+ cw &= ~ RQD_FPU_CLEAR_MASK;
+#else
+ cw |= RQD_FPU_MASK;
#endif
+ _FPU_SETCW(cw);
#endif
#else /* !_FPU_IEEE */
@@ -314,11 +400,11 @@ which we want*/
fflush(stderr);
#endif /* _FPU_IEEE */
-#endif /* __mc68k__ */
}
#endif /* __linux__ */
-#ifdef __alpha
+/* Specific to OSF/1 */
+#if (defined(__alpha)&&defined(__osf__))
#ifndef IEEE0_done
#define IEEE0_done
#include <machine/fpu.h>
@@ -328,7 +414,7 @@ ieee0(Void)
ieee_set_fp_control(IEEE_TRAP_ENABLE_INV);
}
#endif /*IEEE0_done*/
-#endif /*__alpha*/
+#endif /*__alpha OSF/1*/
#ifdef __hpux
#define IEEE0_done
|