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