Add a regression test to verify that the FPU control word state is
authormartynas <martynas@openbsd.org>
Sun, 29 Dec 2013 01:39:44 +0000 (01:39 +0000)
committermartynas <martynas@openbsd.org>
Sun, 29 Dec 2013 01:39:44 +0000 (01:39 +0000)
preserved by setjmp.  Currently under REGRESS_FULL as this fails
on certain archs.

regress/lib/libc/Makefile
regress/lib/libc/setjmp-fpu/Makefile [new file with mode: 0644]
regress/lib/libc/setjmp-fpu/setjmp-fpu.c [new file with mode: 0644]

index 016255e..3109c0c 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.37 2013/08/01 21:26:30 kettenis Exp $
+#      $OpenBSD: Makefile,v 1.38 2013/12/29 01:39:44 martynas Exp $
 
 SUBDIR+= _setjmp alloca atexit basename cephes cxa-atexit db dirname env
 SUBDIR+= fmemopen fnmatch fpclassify getcap getopt_long glob
@@ -10,6 +10,7 @@ SUBDIR+= telldir time vis
 
 .if defined(REGRESS_FULL)
 SUBDIR+= getaddrinfo
+SUBDIR+= setjmp-fpu
 .endif
 
 .if (${MACHINE_ARCH} != "vax")
diff --git a/regress/lib/libc/setjmp-fpu/Makefile b/regress/lib/libc/setjmp-fpu/Makefile
new file mode 100644 (file)
index 0000000..471de48
--- /dev/null
@@ -0,0 +1,8 @@
+#      $OpenBSD: Makefile,v 1.1 2013/12/29 01:39:44 martynas Exp $
+
+PROG=  setjmp-fpu
+SRCS=  setjmp-fpu.c
+
+LDADD= -lm
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/libc/setjmp-fpu/setjmp-fpu.c b/regress/lib/libc/setjmp-fpu/setjmp-fpu.c
new file mode 100644 (file)
index 0000000..bbc562d
--- /dev/null
@@ -0,0 +1,34 @@
+#include <fenv.h>
+#include <setjmp.h>
+
+int
+main(int argc, char *argv[])
+{
+       jmp_buf env;
+       int rv;
+
+       /* Set up the FPU control word register. */
+       fesetround(FE_UPWARD);
+       fedisableexcept(FE_ALL_EXCEPT);
+       feenableexcept(FE_DIVBYZERO);
+
+       rv = setjmp(env);
+
+       /* Mess with the FPU control word. */
+       if (rv == 0) {
+               fesetround(FE_DOWNWARD);
+               fedisableexcept(FE_DIVBYZERO);
+               longjmp(env, 1);
+       /* Verify that the FPU control word is preserved. */
+       } else if (rv == 1) {
+               if (fegetround() != FE_UPWARD
+                   || fegetexcept() != FE_DIVBYZERO)
+                       return (1);
+               return (0);
+       /* This is not supposed to happen. */
+       } else {
+               return (1);
+       }
+
+       return (1);
+}