xref: /openbsd/regress/lib/libc/setjmp-fpu/fpu.c (revision 5a38ef86)
1 /*	$OpenBSD: fpu.c,v 1.3 2021/06/17 12:55:38 kettenis Exp $	*/
2 
3 #include <err.h>
4 #include <fenv.h>
5 #include <stdlib.h>
6 
7 int
8 main(int argc, char *argv[])
9 {
10 	fexcept_t flag;
11 	int rv;
12 
13 	/* Set up the FPU control word register. */
14 	rv = fesetround(FE_UPWARD);
15 	if (rv != 0)
16 		errx(2, "fesetround FE_UPWARD returned %d", rv);
17 	fedisableexcept(FE_ALL_EXCEPT);
18 	feenableexcept(FE_DIVBYZERO);
19 
20 	/* Set the FPU exception flags. */
21 	flag = FE_OVERFLOW;
22 	rv = fesetexceptflag(&flag, FE_ALL_EXCEPT);
23 	if (rv != 0)
24 		errx(2, "fesetexceptflag returned %d", rv);
25 
26 	/* Schedule another process, to check if kernel preserves state. */
27 	rv = system("true");
28 	if (rv == -1)
29 		err(2, "system");
30 	if (rv != 0)
31 		errx(2, "true: %d", rv);
32 
33 	/* Verify that the FPU control word is preserved. */
34 	rv = fegetround();
35 	if (rv != FE_UPWARD)
36 		errx(1, "fegetround returned %d, not FE_UPWARD", rv);
37 #if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv)
38 	rv = fegetexcept();
39 	if (rv != FE_DIVBYZERO)
40 		errx(1, "fegetexcept returned %d, not FE_DIVBYZERO",
41 		    rv);
42 #endif
43 
44 	/* Verify that the FPU exception flags weren't clobbered. */
45 	flag = 0;
46 	rv = fegetexceptflag(&flag, FE_ALL_EXCEPT);
47 	if (rv != 0)
48 		errx(2, "fegetexceptflag returned %d", rv);
49 	if (flag != FE_OVERFLOW)
50 		errx(1, "except flag is %d, no FE_OVERFLOW", rv);
51 
52 	return (0);
53 }
54