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
main(int argc,char * argv[])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