18745eaaf6fb1f8b3c28a174828e9e3c19567d35
1 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
6 #define X87_CW_IM (1<<0) /* Invalid operation mask */
7 #define X87_CW_DM (1<<1) /* Denormal operand mask */
8 #define X87_CW_ZM (1<<2) /* Zero divide mask */
9 #define X87_CW_OM (1<<3) /* Overflow mask */
10 #define X87_CW_UM (1<<4) /* Underflow mask */
11 #define X87_CW_PM (1<<5) /* Precision mask */
13 #define X87_CW_PC_MASK (3<<8) /* precision control mask */
14 #define X87_CW_PC24 (0<<8) /* 24 bit precision */
15 #define X87_CW_PC53 (2<<8) /* 53 bit precision */
16 #define X87_CW_PC64 (3<<8) /* 64 bit precision */
18 #define X87_CW_RC_MASK (3<<10) /* rounding control mask */
19 #define X87_CW_RC_NEAREST (0<<10) /* round to nearest */
20 #define X87_CW_RC_DOWN (1<<10) /* round down */
21 #define X87_CW_RC_UP (2<<10) /* round up */
22 #define X87_CW_RC_ZERO (3<<10) /* round toward zero (chop) */
24 #define X87_CW_IC (1<<12) /* infinity control flag */
27 unsigned int __getfpcw87(void);
28 void __setfpcw87(unsigned int);
35 unsigned int CDECL
_controlfp(unsigned int newval
, unsigned int mask
)
37 return _control87( newval
, mask
& ~_EM_DENORMAL
);
40 /*********************************************************************
41 * _control87 (MSVCRT.@)
43 unsigned int CDECL
_control87(unsigned int newval
, unsigned int mask
)
45 unsigned int fpword
= 0;
46 unsigned int flags
= 0;
48 TRACE("(%08x, %08x): Called\n", newval
, mask
);
50 /* Get fp control word */
52 fpword
= __getfpcw87();
53 #elif defined(__GNUC__)
54 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) : );
59 TRACE("Control word before : %08x\n", fpword
);
61 /* Convert into mask constants */
62 if (fpword
& 0x1) flags
|= _EM_INVALID
;
63 if (fpword
& 0x2) flags
|= _EM_DENORMAL
;
64 if (fpword
& 0x4) flags
|= _EM_ZERODIVIDE
;
65 if (fpword
& 0x8) flags
|= _EM_OVERFLOW
;
66 if (fpword
& 0x10) flags
|= _EM_UNDERFLOW
;
67 if (fpword
& 0x20) flags
|= _EM_INEXACT
;
68 switch(fpword
& 0xC00) {
69 case 0xC00: flags
|= _RC_UP
|_RC_DOWN
; break;
70 case 0x800: flags
|= _RC_UP
; break;
71 case 0x400: flags
|= _RC_DOWN
; break;
73 switch(fpword
& 0x300) {
74 case 0x0: flags
|= _PC_24
; break;
75 case 0x200: flags
|= _PC_53
; break;
76 case 0x300: flags
|= _PC_64
; break;
78 if (fpword
& 0x1000) flags
|= _IC_AFFINE
;
80 /* Mask with parameters */
81 flags
= (flags
& ~mask
) | (newval
& mask
);
83 /* Convert (masked) value back to fp word */
85 if (flags
& _EM_INVALID
) fpword
|= 0x1;
86 if (flags
& _EM_DENORMAL
) fpword
|= 0x2;
87 if (flags
& _EM_ZERODIVIDE
) fpword
|= 0x4;
88 if (flags
& _EM_OVERFLOW
) fpword
|= 0x8;
89 if (flags
& _EM_UNDERFLOW
) fpword
|= 0x10;
90 if (flags
& _EM_INEXACT
) fpword
|= 0x20;
91 switch(flags
& (_RC_UP
| _RC_DOWN
)) {
92 case _RC_UP
|_RC_DOWN
: fpword
|= 0xC00; break;
93 case _RC_UP
: fpword
|= 0x800; break;
94 case _RC_DOWN
: fpword
|= 0x400; break;
96 switch (flags
& (_PC_24
| _PC_53
)) {
97 case _PC_64
: fpword
|= 0x300; break;
98 case _PC_53
: fpword
|= 0x200; break;
99 case _PC_24
: fpword
|= 0x0; break;
101 if (flags
& _IC_AFFINE
) fpword
|= 0x1000;
103 TRACE("Control word after : %08x\n", fpword
);
105 /* Put fp control word */
108 #elif defined(__GNUC__)
109 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
111 __asm fldcw
[fpword
];
117 /*********************************************************************
118 * _controlfp_s (MSVCRT.@)
120 int CDECL
_controlfp_s(unsigned int *cur
, unsigned int newval
, unsigned int mask
)
125 FIXME("(%p %u %u) semi-stub\n", cur
, newval
, mask
);
127 flags
= _control87( newval
, mask
& ~_EM_DENORMAL
);
134 FIXME(":Not Implemented!\n");