crt/misc/fesetenv.c: Do not clobber `env` with `FNSTENV`
... and do not involve `STMXCSR` unless SSE is supported.
This can be shown by the following program:
```
int main(void)
{
/* Compute 1.0/3.0 in default FPU mode */
volatile float somefloat = 1.0;
somefloat /= 3.0;
/* Output it in float and hex formats */
printf("%.9g\thex: %x\n", somefloat, *(int *)&somefloat);
fenv_t a, b;
fegetenv(&a); /* Save fpu env */
fesetround(FE_TOWARDZERO); /* Set round mode */
fesetenv(&a); /* Restore fpu env (round mode must also be restored) */
fegetenv(&b); /* Get current fpu env */
/* Compute 1.0/3.0 after changing and restoring fpu env */
volatile float somefloat2 = 1.0;
somefloat2 /= 3.0;
/* Output it in float and hex formats */
printf("%.9g\thex: %x\n", somefloat2, *(int *)&somefloat2);
/* Output FPU control words */
printf ("FPU control words: %x, %x\n", a.__control_word, b.__control_word);
return 0;
}
```
On Linux, compiling and running this program gives the following result:
```
lh_mouse@lhmouse-ideapad ~/Desktop $ gcc -v 2>&1 | egrep '^Target:'
Target: x86_64-linux-gnu
lh_mouse@lhmouse-ideapad ~/Desktop $ gcc test.c -lm -m32 && ./a.out
0.333333343 hex: 3eaaaaab
0.333333343 hex: 3eaaaaab
FPU control words: 37f, 37f
lh_mouse@lhmouse-ideapad ~/Desktop $ gcc test.c -lm -m64 && ./a.out
0.333333343 hex: 3eaaaaab
0.333333343 hex: 3eaaaaab
FPU control words: 37f, 37f
```
, while before this commit, our CRT produced wrong results because the FPU
control word would be clobbered:
```
E:\Desktop>gcc test.c && a.exe
0.333333343 hex: 3eaaaaab
0.333333313 hex: 3eaaaaaa
FPU control words: 37f, f7f
```
Reference: https://sourceforge.net/p/mingw-w64/mailman/message/36596484/
Signed-off-by: Liu Hao <lh_mouse@126.com>
1 file changed