ReactOS  0.4.13-dev-249-gcba1a2f
cntrlfp.c
Go to the documentation of this file.
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 #ifdef _M_AMD64
27 unsigned int __getfpcw87(void);
28 void __setfpcw87(unsigned int);
29 #endif
30 
31 /*
32  * @implemented
33  */
34 
35 unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
36 {
37  return _control87( newval, mask & ~_EM_DENORMAL );
38 }
39 
40 /*********************************************************************
41  * _control87 (MSVCRT.@)
42  */
43 unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
44 {
45  unsigned short fpword = 0;
46  unsigned int flags = 0;
47 
48  TRACE("(%08x, %08x): Called\n", newval, mask);
49 
50  /* Get fp control word */
51 #ifdef _M_AMD64
52  fpword = __getfpcw87();
53 #elif defined(__GNUC__)
54  __asm__ __volatile__( "fstcw %0" : "=m" (fpword) : );
55 #else
56  __asm fstcw [fpword];
57 #endif
58 
59  TRACE("Control word before : %08x\n", fpword);
60 
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;
72  }
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;
77  }
78  if (fpword & 0x1000) flags |= _IC_AFFINE;
79 
80  /* Mask with parameters */
81  flags = (flags & ~mask) | (newval & mask);
82 
83  /* Convert (masked) value back to fp word */
84  fpword = 0;
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;
95  }
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;
100  }
101  if (flags & _IC_AFFINE) fpword |= 0x1000;
102 
103  TRACE("Control word after : %08x\n", fpword);
104 
105  /* Put fp control word */
106 #ifdef _M_AMD64
107  __setfpcw87(fpword);
108 #elif defined(__GNUC__)
109  __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
110 #else
111  __asm fldcw [fpword];
112 #endif
113 
114  return flags;
115 }
116 
117 /*********************************************************************
118  * _controlfp_s (MSVCRT.@)
119  */
120 int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
121 {
122 #ifdef __i386__
123  unsigned int val;
124 
125  if (!MSVCRT_CHECK_PMT( !(newval & mask & ~(_MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC | _MCW_DN))))
126  {
127  if (cur) *cur = _controlfp( 0, 0 ); /* retrieve it anyway */
128  return EINVAL;
129  }
130  val = _controlfp( newval, mask );
131  if (cur) *cur = val;
132  return 0;
133 #else
134  FIXME(":Not Implemented!\n");
135  return 0;
136 #endif
137 }
#define _PC_24
Definition: float.h:59
#define _EM_DENORMAL
Definition: float.h:48
Definition: arc.h:39
#define _PC_53
Definition: float.h:60
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
#define _EM_INVALID
Definition: float.h:47
#define _MCW_EM
Definition: float.h:40
unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
Definition: cntrlfp.c:35
#define _MCW_IC
Definition: float.h:41
#define _EM_ZERODIVIDE
Definition: float.h:49
GLenum GLint GLuint mask
Definition: glext.h:6028
__asm__("\t.globl GetPhys\n" "GetPhys:\t\n" "mflr 0\n\t" "stwu 0,-16(1)\n\t" "mfmsr 5\n\t" "andi. 6,5,0xffef\n\t" "mtmsr 6\n\t" "isync\n\t" "sync\n\t" "lwz 3,0(3)\n\t" "mtmsr 5\n\t" "isync\n\t" "sync\n\t" "lwz 0,0(1)\n\t" "addi 1,1,16\n\t" "mtlr 0\n\t" "blr")
#define FIXME(fmt,...)
Definition: debug.h:110
unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
Definition: cntrlfp.c:43
GLuint GLfloat * val
Definition: glext.h:7180
int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
Definition: cntrlfp.c:120
#define _RC_UP
Definition: float.h:56
#define TRACE(s)
Definition: solgame.cpp:4
#define _MCW_DN
Definition: float.h:44
#define _IC_AFFINE
Definition: float.h:53
GLbitfield flags
Definition: glext.h:7161
#define MSVCRT_CHECK_PMT(x)
Definition: mbstowcs_s.c:26
#define _EM_INEXACT
Definition: float.h:52
#define _MCW_RC
Definition: float.h:42
#define _PC_64
Definition: float.h:61
#define CDECL
Definition: compat.h:21
#define _MCW_PC
Definition: float.h:43
#define _EM_OVERFLOW
Definition: float.h:50
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
#define _RC_DOWN
Definition: float.h:57
#define _EM_UNDERFLOW
Definition: float.h:51