1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2009-2014 DreamWorks Animation LLC.
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met:
10 // *       Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // *       Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 // *       Neither the name of DreamWorks Animation nor the names of
17 // its contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 //
32 ///////////////////////////////////////////////////////////////////////////
33 
34 #include "ImfSimd.h"
35 #include "ImfSystemSpecific.h"
36 #include "ImfNamespace.h"
37 #include "OpenEXRConfig.h"
38 
39 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
40 
41 namespace {
42 #if defined(IMF_HAVE_SSE2) &&  defined(__GNUC__)
43 
44     // Helper functions for gcc + SSE enabled
cpuid(int n,int & eax,int & ebx,int & ecx,int & edx)45     void cpuid(int n, int &eax, int &ebx, int &ecx, int &edx)
46     {
47         __asm__ __volatile__ (
48             "cpuid"
49             : /* Output  */ "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
50             : /* Input   */ "a"(n)
51             : /* Clobber */);
52     }
53 
54 #else // IMF_HAVE_SSE2 && __GNUC__
55 
56     // Helper functions for generic compiler - all disabled
57     void cpuid(int n, int &eax, int &ebx, int &ecx, int &edx)
58     {
59         eax = ebx = ecx = edx = 0;
60     }
61 
62 #endif // IMF_HAVE_SSE2 && __GNUC__
63 
64 
65 #ifdef OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX
66 
xgetbv(int n,int & eax,int & edx)67     void xgetbv(int n, int &eax, int &edx)
68     {
69         __asm__ __volatile__ (
70             "xgetbv"
71             : /* Output  */ "=a"(eax), "=d"(edx)
72             : /* Input   */ "c"(n)
73             : /* Clobber */);
74     }
75 
76 #else //  OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX
77 
xgetbv(int n,int & eax,int & edx)78     void xgetbv(int n, int &eax, int &edx)
79     {
80         eax = edx = 0;
81     }
82 
83 #endif //  OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX
84 
85 } // namespace
86 
CpuId()87 CpuId::CpuId():
88     sse2(false),
89     sse3(false),
90     ssse3(false),
91     sse4_1(false),
92     sse4_2(false),
93     avx(false),
94     f16c(false)
95 {
96     bool osxsave = false;
97     int  max     = 0;
98     int  eax, ebx, ecx, edx;
99 
100     cpuid(0, max, ebx, ecx, edx);
101     if (max > 0)
102     {
103         cpuid(1, eax, ebx, ecx, edx);
104         sse2    = ( edx & (1<<26) );
105         sse3    = ( ecx & (1<< 0) );
106         ssse3   = ( ecx & (1<< 9) );
107         sse4_1  = ( ecx & (1<<19) );
108         sse4_2  = ( ecx & (1<<20) );
109         osxsave = ( ecx & (1<<27) );
110         avx     = ( ecx & (1<<28) );
111         f16c    = ( ecx & (1<<29) );
112 
113         if (!osxsave)
114         {
115             avx = f16c = false;
116         }
117         else
118         {
119             xgetbv(0, eax, edx);
120             // eax bit 1 - SSE managed, bit 2 - AVX managed
121             if ((eax & 6) != 6)
122             {
123                 avx = f16c = false;
124             }
125         }
126     }
127 }
128 
129 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
130