merge essej's fix for OS X
[ardour.git] / libs / pbd / fpu.cc
1 #define _XOPEN_SOURCE 600
2 #include <stdlib.h>
3 #include <stdint.h>
4
5 #include <pbd/fpu.h>
6 #include <pbd/error.h>
7
8 #include "i18n.h"
9
10 using namespace PBD;
11 using namespace std;
12
13 FPU::FPU ()
14 {
15         unsigned long cpuflags = 0;
16
17         _flags = Flags (0);
18
19 #ifndef ARCH_X86
20         return;
21 #endif
22         
23 #ifndef USE_X86_64_ASM
24         asm volatile (
25                 "mov $1, %%eax\n"
26                 "pushl %%ebx\n"
27                 "cpuid\n"
28                 "movl %%edx, %0\n"
29                 "popl %%ebx\n"
30                 : "=r" (cpuflags)
31                 : 
32                 : "%eax", "%ecx", "%edx", "memory"
33                 );
34         
35 #else
36         
37         asm volatile (
38                 "pushq %%rbx\n"
39                 "movq $1, %%rax\n"
40                 "cpuid\n"
41                 "movq %%rdx, %0\n"
42                 "popq %%rbx\n"
43                 : "=r" (cpuflags)
44                 : 
45                 : "%rax", "%rcx", "%rdx", "memory"
46                 );
47
48 #endif /* USE_X86_64_ASM */
49         
50         if (cpuflags & (1<<25)) {
51                 _flags = Flags (_flags | (HasSSE|HasFlushToZero));
52         }
53
54         if (cpuflags & (1<<26)) {
55                 _flags = Flags (_flags | HasSSE2);
56         }
57
58         if (cpuflags & (1 << 24)) {
59                 
60                 char* fxbuf = 0;
61                 
62 #ifdef NO_POSIX_MEMALIGN
63                 if ((fxbuf = (char *) malloc(512)) == 0)
64 #else
65                 if (posix_memalign ((void**)&fxbuf, 16, 512)) 
66 #endif                  
67                 {
68                         error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg;
69                 } else {
70                         
71                         asm volatile (
72                                 "fxsave (%0)"
73                                 :
74                                 : "r" (fxbuf)
75                                 : "memory"
76                                 );
77                         
78                         uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]);
79                         
80                         /* if the mask is zero, set its default value (from intel specs) */
81                         
82                         if (mxcsr_mask == 0) {
83                                 mxcsr_mask = 0xffbf;
84                         }
85                         
86                         if (mxcsr_mask & (1<<6)) {
87                                 _flags = Flags (_flags | HasDenormalsAreZero);
88                         } 
89
90                         free (fxbuf);
91                 }
92         }
93 }                       
94
95 FPU::~FPU ()
96 {
97 }