improve logic flow
[ardour.git] / libs / pbd / msvc / fpu.cc
1 // Added by JE - 05-12-2009. Inline assembler instructions
2 // have been changed to Intel format and (in the case of
3 // cpuid) was replaced by the equivalent VC++ system call).
4
5 #if defined (COMPILER_MSVC) || defined (COMPILER_MINGW)
6
7 #define _XOPEN_SOURCE 600
8 #include <cstdlib>
9 #include <stdint.h>
10 #include <intrin.h>  // Added by JE - 05-12-2009
11 #include <assert.h>
12
13 #include <pbd/fpu.h>
14 #include <pbd/error.h>
15
16 #include "i18n.h"
17
18 using namespace PBD;
19 using namespace std;
20
21 FPU::FPU ()
22 {
23         unsigned long cpuflags = 0;
24
25         _flags = (Flags)0;
26
27 #ifndef USE_X86_64_ASM
28         return;
29 #endif
30
31         // Get CPU lfags using Microsof function
32         // It works for both 64 and 32 bit systems
33         // no need to use assembler for getting info from register, this function does this for us
34         int cpuInfo[4];
35         __cpuid (cpuInfo, 1);
36         cpuflags = cpuInfo[3];
37
38         if (cpuflags & (1<<25)) {
39                 _flags = Flags (_flags | (HasSSE|HasFlushToZero) );
40         }
41
42         if (cpuflags & (1<<26)) {
43                 _flags = Flags (_flags | HasSSE2);
44         }
45
46         if (cpuflags & (1 << 24)) {
47                 char** fxbuf = 0;
48
49                 // allocate alligned buffer
50                 fxbuf = (char **) malloc (sizeof (char *));
51                 assert (fxbuf);
52                 *fxbuf = (char *) malloc (512);
53                 assert (*fxbuf);
54
55                 // Verify that fxbuf is correctly aligned
56                 unsigned long long buf_addr = (unsigned long long)(void*)fxbuf;
57                 if ((0 == buf_addr) || (buf_addr % 16))
58                         error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg;
59                 else
60                 {
61                         memset(*fxbuf, 0, 512); // Initialize the buffer !!! Added by JE - 12-12-2009
62
63 #if defined (COMPILER_MINGW)
64                         asm volatile (
65                                 "fxsave (%0)"
66                                 :
67                                 : "r" (*fxbuf)
68                                 : "memory"
69                                 );
70 /*
71                         asm( ".intel_syntax noprefix\n" );
72
73                         asm volatile (
74                                  "mov eax, fxbuf\n"
75                                  "fxsave   [eax]\n" 
76                         );
77
78                         asm( ".att_syntax prefix\n" );
79 */
80
81 #elif defined (COMPILER_MSVC)
82                         __asm {
83                                 mov eax, fxbuf
84                                 fxsave   [eax]
85                         };
86 #endif
87                         uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]);
88
89                         /* if the mask is zero, set its default value (from intel specs) */
90
91                         if (mxcsr_mask == 0) {
92                                 mxcsr_mask = 0xffbf;
93                         }
94
95                         if (mxcsr_mask & (1<<6)) {
96                                 _flags = Flags (_flags | HasDenormalsAreZero);
97                         }
98
99                         free (*fxbuf);
100                         free (fxbuf);
101                 }
102         }
103 }
104
105 FPU::~FPU ()
106 {
107 }
108
109 #else  // !COMPILER_MSVC
110         const char* pbd_fpu = "original pbd/fpu.cc takes precedence over this file";
111 #endif // COMPILER_MSVC