1 /* $OpenBSD: setjmp-fpu.c,v 1.7 2021/06/17 12:55:38 kettenis 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 #if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv) 46 rv = fegetexcept(); 47 if (rv != FE_DIVBYZERO) 48 errx(1, "fegetexcept returned %d, not FE_DIVBYZERO", 49 rv); 50 #endif 51 52 /* Verify that the FPU exception flags weren't clobbered. */ 53 flag = 0; 54 rv = fegetexceptflag(&flag, FE_ALL_EXCEPT); 55 if (rv != 0) 56 errx(2, "fegetexceptflag returned %d", rv); 57 if (flag != FE_OVERFLOW) 58 errx(1, "except flag is %d, no FE_OVERFLOW", rv); 59 60 return (0); 61 } 62 default: 63 errx(2, "setjmp returned %d", rv); 64 } 65 } 66