1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7#include "internal.h"
8
9#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
10/* Internal MinGW version of MS __control87_2 with following differences:
11 * - Availability:
12 * - MinGW provides both i386 and x64 implementation
13 * - MS provides only i386 implementation and only for msvcr80+
14 * - Usage of x87 fwait instruction which triggers pending x87 exceptions:
15 * - MinGW does not call it
16 * - MS calls it before reading x87 cw
17 */
18int __mingw_control87_2( unsigned int newval, unsigned int mask,
19 unsigned int *x86_cw, unsigned int *sse2_cw )
20{
21 if (x86_cw)
22 {
23 *x86_cw = newval;
24 __mingw_setfp(x86_cw, mask, NULL, 0);
25 }
26
27 if (!sse2_cw) return 1;
28
29 if (__mingw_has_sse())
30 {
31 *sse2_cw = newval;
32 __mingw_setfp_sse(sse2_cw, mask, NULL, 0);
33 }
34 else *sse2_cw = 0;
35
36 return 1;
37}
38#endif
39
40/* Internal MinGW version of MS _control87 with following differences:
41 * - Usage of x87 fwait instruction which triggers pending x87 exceptions:
42 * - MinGW does not call it
43 * - MS x64 does not call it
44 * - MS i386 calls it before reading x87 cw
45 * - Source of the flags:
46 * - MinGW i386 and x64 returns from both x87 and SSE2
47 * - MS i386 msvcrt from Vista+ and msvcr80+ returns from both x87 and SSE2
48 * - MS i386 msvcrt before Vista and pre-msvcr80 returns from x87
49 * - MS x64 returns from SSE2
50 * This makes behavior of MinGW version same for all builds,
51 * always returns information from both x87 and SSE2 and
52 * never triggers pending x87 exceptions.
53 */
54unsigned int __mingw_controlfp(unsigned int newval, unsigned int mask)
55{
56 unsigned int flags = 0;
57#if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__))
58 unsigned int sse2_cw;
59
60 __mingw_control87_2( newval, mask, &flags, &sse2_cw );
61
62 if (__mingw_has_sse())
63 {
64 if ((flags ^ sse2_cw) & (_MCW_EM | _MCW_RC)) flags |= _EM_AMBIGUOUS;
65 flags |= sse2_cw;
66 }
67#else
68 flags = newval;
69 __mingw_setfp(&flags, mask, NULL, 0);
70#endif
71 return flags;
72}
73