1 /* $OpenBSD: setjmp-fpu.c,v 1.5 2020/01/16 13:04:02 bluhm Exp $ */ 2 3 #include <err.h> 4 #include <fenv.h> 5 #include <setjmp.h> 6 7 int 8 TEST_SETJMP(void) 9 { 10 JMP_BUF env; 11 fexcept_t flag; 12 int rv; 13 14 /* Set up the FPU control word register. */ 15 rv = fesetround(FE_UPWARD); 16 if (rv != 0) 17 errx(2, "fesetround FE_UPWARD returned %d", rv); 18 fedisableexcept(FE_ALL_EXCEPT); 19 feenableexcept(FE_DIVBYZERO); 20 21 rv = SETJMP(env, 0); 22 23 switch(rv) { 24 case 0: { 25 /* Mess with the FPU control word. */ 26 rv = fesetround(FE_DOWNWARD); 27 if (rv != 0) 28 errx(2, "fesetround FE_DOWNWARD returned %d", rv); 29 fedisableexcept(FE_DIVBYZERO); 30 31 /* Set the FPU exception flags. */ 32 flag = FE_OVERFLOW; 33 rv = fesetexceptflag(&flag, FE_ALL_EXCEPT); 34 if (rv != 0) 35 errx(2, "fesetexceptflag returned %d", rv); 36 37 LONGJMP(env, 1); 38 errx(2, "longjmp returned"); 39 } 40 case 1: { 41 /* Verify that the FPU control word is preserved. */ 42 rv = fegetround(); 43 if (rv != FE_UPWARD) 44 errx(1, "fegetround returned %d, not FE_UPWARD", rv); 45 rv = fegetexcept(); 46 if (rv != FE_DIVBYZERO) 47 errx(1, "fegetexcept returned %d, not FE_DIVBYZERO", 48 rv); 49 50 /* Verify that the FPU exception flags weren't clobbered. */ 51 flag = 0; 52 rv = fegetexceptflag(&flag, FE_ALL_EXCEPT); 53 if (rv != 0) 54 errx(2, "fegetexceptflag returned %d", rv); 55 if (flag != FE_OVERFLOW) 56 errx(1, "except flag is %d, no FE_OVERFLOW", rv); 57 58 return (0); 59 } 60 default: 61 errx(2, "setjmp returned %d", rv); 62 } 63 } 64