comparison src/fftw-3.3.8/simd-support/x86-cpuid.h @ 167:bd3cc4d1df30

Add FFTW 3.3.8 source, and a Linux build
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 19 Nov 2019 14:52:55 +0000
parents
children
comparison
equal deleted inserted replaced
166:cbd6d7e562c7 167:bd3cc4d1df30
1 /*
2 * Copyright (c) 2003, 2007-14 Matteo Frigo
3 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21
22 /* this code was kindly donated by Eric J. Korpela */
23
24 #ifdef _MSC_VER
25 #ifndef inline
26 #define inline __inline
27 #endif
28 #endif
29
30 static inline int is_386()
31 {
32 #ifdef _MSC_VER
33 unsigned int result,tst;
34 _asm {
35 pushfd
36 pop eax
37 mov edx,eax
38 xor eax,40000h
39 push eax
40 popfd
41 pushfd
42 pop eax
43 push edx
44 popfd
45 mov tst,edx
46 mov result,eax
47 }
48 #else
49 register unsigned int result,tst;
50 __asm__ (
51 "pushfl\n\t"
52 "popl %0\n\t"
53 "movl %0,%1\n\t"
54 "xorl $0x40000,%0\n\t"
55 "pushl %0\n\t"
56 "popfl\n\t"
57 "pushfl\n\t"
58 "popl %0\n\t"
59 "pushl %1\n\t"
60 "popfl"
61 : "=r" (result), "=r" (tst) /* output */
62 : /* no inputs */
63 );
64 #endif
65 return (result == tst);
66 }
67
68 static inline int has_cpuid()
69 {
70 #ifdef _MSC_VER
71 unsigned int result,tst;
72 _asm {
73 pushfd
74 pop eax
75 mov edx,eax
76 xor eax,200000h
77 push eax
78 popfd
79 pushfd
80 pop eax
81 push edx
82 popfd
83 mov tst,edx
84 mov result,eax
85 }
86 #else
87 register unsigned int result,tst;
88 __asm__ (
89 "pushfl\n\t"
90 "pop %0\n\t"
91 "movl %0,%1\n\t"
92 "xorl $0x200000,%0\n\t"
93 "pushl %0\n\t"
94 "popfl\n\t"
95 "pushfl\n\t"
96 "popl %0\n\t"
97 "pushl %1\n\t"
98 "popfl"
99 : "=r" (result), "=r" (tst) /* output */
100 : /* no inputs */
101 );
102 #endif
103 return (result != tst);
104 }
105
106 /* cpuid version to get all registers. Donated by Erik Lindahl from Gromacs. */
107 static inline void
108 cpuid_all(int level, int ecxval, int *eax, int *ebx, int *ecx, int *edx)
109 {
110 #if (defined _MSC_VER)
111 int CPUInfo[4];
112
113 # if (_MSC_VER > 1500) || (_MSC_VER == 1500 & _MSC_FULL_VER >= 150030729)
114 /* MSVC 9.0 SP1 or later */
115 __cpuidex(CPUInfo, level, ecxval);
116 # else
117 __cpuid(CPUInfo, level);
118 /* Set an error code if the user wanted a non-zero ecxval, since we did not have cpuidex */
119 # endif
120 *eax = CPUInfo[0];
121 *ebx = CPUInfo[1];
122 *ecx = CPUInfo[2];
123 *edx = CPUInfo[3];
124
125 #else
126 /* Not MSVC */
127 *eax = level;
128 *ecx = ecxval;
129 *ebx = 0;
130 *edx = 0;
131 /* Avoid clobbering global offset table in 32-bit pic code (ebx) */
132 # if defined(__PIC__)
133 __asm__ ("xchgl %%ebx, %1 \n\t"
134 "cpuid \n\t"
135 "xchgl %%ebx, %1 \n\t"
136 : "+a" (*eax), "+r" (*ebx), "+c" (*ecx), "+d" (*edx));
137 # else
138 /* No need to save ebx if we are not in pic mode */
139 __asm__ ("cpuid \n\t"
140 : "+a" (*eax), "+b" (*ebx), "+c" (*ecx), "+d" (*edx));
141 # endif
142 #endif
143 }
144
145 static inline int cpuid_edx(int op)
146 {
147 # ifdef _MSC_VER
148 int result;
149 _asm {
150 push ebx
151 mov eax,op
152 cpuid
153 mov result,edx
154 pop ebx
155 }
156 return result;
157 # else
158 int eax, ecx, edx;
159
160 __asm__("push %%ebx\n\tcpuid\n\tpop %%ebx"
161 : "=a" (eax), "=c" (ecx), "=d" (edx)
162 : "a" (op));
163 return edx;
164 # endif
165 }
166
167 static inline int cpuid_ecx(int op)
168 {
169 # ifdef _MSC_VER
170 int result;
171 _asm {
172 push ebx
173 mov eax,op
174 cpuid
175 mov result,ecx
176 pop ebx
177 }
178 return result;
179 # else
180 int eax, ecx, edx;
181
182 __asm__("push %%ebx\n\tcpuid\n\tpop %%ebx"
183 : "=a" (eax), "=c" (ecx), "=d" (edx)
184 : "a" (op));
185 return ecx;
186 # endif
187 }
188
189 static inline int xgetbv_eax(int op)
190 {
191 # ifdef _MSC_VER
192 int veax, vedx;
193 _asm {
194 mov ecx,op
195 # if defined(__INTEL_COMPILER) || (_MSC_VER >= 1600)
196 xgetbv
197 # else
198 __emit 15
199 __emit 1
200 __emit 208
201 # endif
202 mov veax,eax
203 mov vedx,edx
204 }
205 return veax;
206 # else
207 int eax, edx;
208 __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c" (op));
209 return eax;
210 #endif
211 }