[MMEBUDDY]
[reactos.git] / reactos / lib / sdk / crt / float / i386 / cntrlfp.c
1 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
2
3 #include <precomp.h>
4 #include <float.h>
5
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 */
12
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 */
17
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) */
23
24 #define X87_CW_IC (1<<12) /* infinity control flag */
25
26 /*
27 * @implemented
28 */
29
30 unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
31 {
32 return _control87( newval, mask & ~_EM_DENORMAL );
33 }
34
35 /*********************************************************************
36 * _control87 (MSVCRT.@)
37 */
38 unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
39 {
40 unsigned int fpword = 0;
41 unsigned int flags = 0;
42
43 TRACE("(%08x, %08x): Called\n", newval, mask);
44
45 /* Get fp control word */
46 #if defined(__GNUC__)
47 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) : );
48 #else
49 __asm fstcw [fpword];
50 #endif
51
52 TRACE("Control word before : %08x\n", fpword);
53
54 /* Convert into mask constants */
55 if (fpword & 0x1) flags |= _EM_INVALID;
56 if (fpword & 0x2) flags |= _EM_DENORMAL;
57 if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
58 if (fpword & 0x8) flags |= _EM_OVERFLOW;
59 if (fpword & 0x10) flags |= _EM_UNDERFLOW;
60 if (fpword & 0x20) flags |= _EM_INEXACT;
61 switch(fpword & 0xC00) {
62 case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
63 case 0x800: flags |= _RC_UP; break;
64 case 0x400: flags |= _RC_DOWN; break;
65 }
66 switch(fpword & 0x300) {
67 case 0x0: flags |= _PC_24; break;
68 case 0x200: flags |= _PC_53; break;
69 case 0x300: flags |= _PC_64; break;
70 }
71 if (fpword & 0x1000) flags |= _IC_AFFINE;
72
73 /* Mask with parameters */
74 flags = (flags & ~mask) | (newval & mask);
75
76 /* Convert (masked) value back to fp word */
77 fpword = 0;
78 if (flags & _EM_INVALID) fpword |= 0x1;
79 if (flags & _EM_DENORMAL) fpword |= 0x2;
80 if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
81 if (flags & _EM_OVERFLOW) fpword |= 0x8;
82 if (flags & _EM_UNDERFLOW) fpword |= 0x10;
83 if (flags & _EM_INEXACT) fpword |= 0x20;
84 switch(flags & (_RC_UP | _RC_DOWN)) {
85 case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
86 case _RC_UP: fpword |= 0x800; break;
87 case _RC_DOWN: fpword |= 0x400; break;
88 }
89 switch (flags & (_PC_24 | _PC_53)) {
90 case _PC_64: fpword |= 0x300; break;
91 case _PC_53: fpword |= 0x200; break;
92 case _PC_24: fpword |= 0x0; break;
93 }
94 if (flags & _IC_AFFINE) fpword |= 0x1000;
95
96 TRACE("Control word after : %08x\n", fpword);
97
98 /* Put fp control word */
99 #if defined(__GNUC__)
100 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
101 #else
102 __asm fldcw [fpword];
103 #endif
104
105 return flags;
106 }
107
108 /*********************************************************************
109 * _controlfp_s (MSVCRT.@)
110 */
111 int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
112 {
113 #ifdef __i386__
114 unsigned int flags;
115
116 FIXME("(%p %u %u) semi-stub\n", cur, newval, mask);
117
118 flags = _control87( newval, mask & ~_EM_DENORMAL );
119
120 if(cur)
121 *cur = flags;
122
123 return 0;
124 #else
125 FIXME(":Not Implemented!\n");
126 return 0;
127 #endif
128 }