fix build error
[platform/upstream/openblas.git] / common_x86.h
1 /*********************************************************************/
2 /* Copyright 2009, 2010 The University of Texas at Austin.           */
3 /* All rights reserved.                                              */
4 /*                                                                   */
5 /* Redistribution and use in source and binary forms, with or        */
6 /* without modification, are permitted provided that the following   */
7 /* conditions are met:                                               */
8 /*                                                                   */
9 /*   1. Redistributions of source code must retain the above         */
10 /*      copyright notice, this list of conditions and the following  */
11 /*      disclaimer.                                                  */
12 /*                                                                   */
13 /*   2. Redistributions in binary form must reproduce the above      */
14 /*      copyright notice, this list of conditions and the following  */
15 /*      disclaimer in the documentation and/or other materials       */
16 /*      provided with the distribution.                              */
17 /*                                                                   */
18 /*    THIS  SOFTWARE IS PROVIDED  BY THE  UNIVERSITY OF  TEXAS AT    */
19 /*    AUSTIN  ``AS IS''  AND ANY  EXPRESS OR  IMPLIED WARRANTIES,    */
20 /*    INCLUDING, BUT  NOT LIMITED  TO, THE IMPLIED  WARRANTIES OF    */
21 /*    MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR  PURPOSE ARE    */
22 /*    DISCLAIMED.  IN  NO EVENT SHALL THE UNIVERSITY  OF TEXAS AT    */
23 /*    AUSTIN OR CONTRIBUTORS BE  LIABLE FOR ANY DIRECT, INDIRECT,    */
24 /*    INCIDENTAL,  SPECIAL, EXEMPLARY,  OR  CONSEQUENTIAL DAMAGES    */
25 /*    (INCLUDING, BUT  NOT LIMITED TO,  PROCUREMENT OF SUBSTITUTE    */
26 /*    GOODS  OR  SERVICES; LOSS  OF  USE,  DATA,  OR PROFITS;  OR    */
27 /*    BUSINESS INTERRUPTION) HOWEVER CAUSED  AND ON ANY THEORY OF    */
28 /*    LIABILITY, WHETHER  IN CONTRACT, STRICT  LIABILITY, OR TORT    */
29 /*    (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY WAY OUT    */
30 /*    OF  THE  USE OF  THIS  SOFTWARE,  EVEN  IF ADVISED  OF  THE    */
31 /*    POSSIBILITY OF SUCH DAMAGE.                                    */
32 /*                                                                   */
33 /* The views and conclusions contained in the software and           */
34 /* documentation are those of the authors and should not be          */
35 /* interpreted as representing official policies, either expressed   */
36 /* or implied, of The University of Texas at Austin.                 */
37 /*********************************************************************/
38
39 #ifndef COMMON_X86
40 #define COMMON_X86
41
42 #ifndef ASSEMBLER
43
44 #ifdef C_MSVC
45 #include <intrin.h>
46 #endif
47
48 #define MB
49 #define WMB
50
51 #ifdef C_SUN
52 #define __asm__ __asm
53 #define __volatile__
54 #endif
55
56 static void __inline blas_lock(volatile BLASULONG *address){
57
58   int ret;
59
60   do {
61     while (*address) {YIELDING;};
62
63 #if defined(_MSC_VER) && !defined(__clang__)
64         // use intrinsic instead of inline assembly
65         ret = _InterlockedExchange((volatile LONG *)address, 1);
66         // inline assembly
67         /*__asm {
68                 mov eax, address
69                 mov ebx, 1
70                 xchg [eax], ebx
71                 mov ret, ebx
72         }*/
73 #else
74     __asm__ __volatile__(
75                          "xchgl %0, %1\n"
76                          : "=r"(ret), "=m"(*address)
77                          : "0"(1), "m"(*address)
78                          : "memory");
79 #endif
80
81   } while (ret);
82
83 }
84 #define BLAS_LOCK_DEFINED
85
86 static __inline unsigned long long rpcc(void){
87 #if defined(_MSC_VER) && !defined(__clang__)
88   return __rdtsc(); // use MSVC intrinsic
89 #else
90   unsigned int a, d;
91
92   __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d));
93
94   return ((unsigned long long)a + ((unsigned long long)d << 32));
95 #endif
96 };
97 #define RPCC_DEFINED
98
99 static __inline unsigned long getstackaddr(void){
100 #if defined(_MSC_VER) && !defined(__clang__)
101   return (unsigned long)_ReturnAddress(); // use MSVC intrinsic
102 #else
103   unsigned long addr;
104
105   __asm__ __volatile__ ("mov %%esp, %0"
106                          : "=r"(addr) : : "memory");
107
108   return addr;
109 #endif
110 };
111
112
113 static __inline long double sqrt_long(long double val) {
114 #if defined(_MSC_VER) && !defined(__clang__)
115   return sqrt(val); // not sure if this will use fsqrt
116 #else
117   long double result;
118
119   __asm__ __volatile__ ("fldt %1\n"
120                     "fsqrt\n"
121                     "fstpt %0\n" : "=m" (result) : "m"(val));
122   return result;
123 #endif
124 }
125
126 #define SQRT(a)  sqrt_long(a)
127
128 /* This is due to gcc's bug */
129 void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx);
130
131 #define WHEREAMI
132
133 static __inline int WhereAmI(void){
134   int eax, ebx, ecx, edx;
135   int apicid;
136
137   cpuid(1, &eax, &ebx, &ecx, &edx);
138   apicid  = BITMASK(ebx, 24, 0xff);
139
140   return apicid;
141 }
142
143 #ifdef ENABLE_SSE_EXCEPTION
144
145 #define IDEBUG_START \
146 { \
147   unsigned int fp_sse_mode, new_fp_mode; \
148   __asm__ __volatile__ ("stmxcsr %0" : "=m" (fp_sse_mode) : ); \
149   new_fp_mode = fp_sse_mode & ~0xd00; \
150   __asm__ __volatile__ ("ldmxcsr %0" : : "m" (new_fp_mode) );
151
152 #define IDEBUG_END \
153   __asm__ __volatile__ ("ldmxcsr %0" : : "m" (fp_sse_mode) ); \
154 }
155
156 #endif
157
158 #ifdef XDOUBLE
159 #define GET_IMAGE(res)  __asm__ __volatile__("fstpt %0" : "=m"(res) : : "memory")
160 #elif defined(DOUBLE)
161 #define GET_IMAGE(res)  __asm__ __volatile__("fstpl %0" : "=m"(res) : : "memory")
162 #else
163 #define GET_IMAGE(res)  __asm__ __volatile__("fstps %0" : "=m"(res) : : "memory");
164 #endif
165
166 #define GET_IMAGE_CANCEL        __asm__ __volatile__ ("ffree %st")
167
168 #ifdef SMP
169 extern unsigned int blas_quick_divide_table[];
170
171 static __inline int blas_quickdivide(unsigned int x, unsigned int y){
172
173   unsigned int result;
174
175   if (y <= 1) return x;
176
177 #if defined(_MSC_VER) && !defined(__clang__)
178   result = x/y;
179   return result;
180 #else
181 #if (MAX_CPU_NUMBER > 64)
182   if ( y > 64) {
183           result = x/y;
184           return result;
185   }
186 #endif
187         
188   y = blas_quick_divide_table[y];
189
190   __asm__ __volatile__  ("mull %0" :"=d" (result), "+a"(x): "0" (y));
191
192   return result;
193 #endif
194 }
195 #endif
196
197 #endif
198
199 #ifndef PAGESIZE
200 #define PAGESIZE        ( 4 << 10)
201 #endif
202 #define HUGE_PAGESIZE   ( 4 << 20)
203
204 #define BUFFER_SIZE     (16 << 20)
205
206 #define SEEK_ADDRESS
207
208 #if defined(DOUBLE) || defined(XDOUBLE)
209 #define MMXLOAD         movq
210 #define MMXSTORE        movq
211 #else
212 #define MMXLOAD         movd
213 #define MMXSTORE        movd
214 #endif
215
216 #if defined(PILEDRIVER) || defined(BULLDOZER) || defined(STEAMROLLER) || defined(EXCAVATOR)
217 //Enable some optimization for barcelona.
218 #define BARCELONA_OPTIMIZATION
219 #endif
220
221 #if defined(HAVE_3DNOW)
222 #define EMMS    femms
223 #elif defined(HAVE_MMX)
224 #define EMMS    emms
225 #endif
226
227 #ifndef EMMS
228 #define EMMS
229 #endif
230
231 #if defined(CORE2) || defined(PENTIUM4)
232 #define movapd  movaps
233 #endif
234
235 #define BRANCH          .byte 0x3e
236 #define NOBRANCH        .byte 0x2e
237 #define PADDING         .byte 0x66;
238 #define HALT            hlt
239
240 #ifndef COMPLEX
241 #ifdef XDOUBLE
242 #define LOCAL_BUFFER_SIZE  QLOCAL_BUFFER_SIZE
243 #elif defined DOUBLE
244 #define LOCAL_BUFFER_SIZE  DLOCAL_BUFFER_SIZE
245 #else
246 #define LOCAL_BUFFER_SIZE  SLOCAL_BUFFER_SIZE
247 #endif
248 #else
249 #ifdef XDOUBLE
250 #define LOCAL_BUFFER_SIZE  XLOCAL_BUFFER_SIZE
251 #elif defined DOUBLE
252 #define LOCAL_BUFFER_SIZE  ZLOCAL_BUFFER_SIZE
253 #else
254 #define LOCAL_BUFFER_SIZE  CLOCAL_BUFFER_SIZE
255 #endif
256 #endif
257
258 #if defined(OS_WINDOWS)
259 #if   LOCAL_BUFFER_SIZE > 16384
260 #define STACK_TOUCHING \
261         movl    $0,  4096 * 4(%esp);\
262         movl    $0,  4096 * 3(%esp);\
263         movl    $0,  4096 * 2(%esp);\
264         movl    $0,  4096 * 1(%esp);
265 #elif LOCAL_BUFFER_SIZE > 12288
266 #define STACK_TOUCHING \
267         movl    $0,  4096 * 3(%esp);\
268         movl    $0,  4096 * 2(%esp);\
269         movl    $0,  4096 * 1(%esp);
270 #elif LOCAL_BUFFER_SIZE > 8192
271 #define STACK_TOUCHING \
272         movl    $0,  4096 * 2(%esp);\
273         movl    $0,  4096 * 1(%esp);
274 #elif LOCAL_BUFFER_SIZE > 4096
275 #define STACK_TOUCHING \
276         movl    $0,  4096 * 1(%esp);
277 #else
278 #define STACK_TOUCHING
279 #endif
280 #else
281 #define STACK_TOUCHING
282 #endif
283
284 #ifndef F_INTERFACE
285 #define REALNAME ASMNAME
286 #else
287 #define REALNAME ASMFNAME
288 #endif
289
290 #if defined(F_INTERFACE_PATHSCALE) || defined(F_INTERFACE_OPEN64)
291 #define RETURN_BY_STRUCT
292 #elif defined(F_INTERFACE_GFORT) || defined(F_INTERFACE_G95)
293 #define RETURN_BY_COMPLEX
294 #else
295 #define RETURN_BY_STACK
296 #endif
297
298 #ifdef OS_DARWIN
299 #define PROLOGUE .text;.align 5; .globl REALNAME; REALNAME:
300 #define EPILOGUE        .subsections_via_symbols
301 #define PROFCODE
302 #endif
303
304 #if defined(OS_WINNT) || defined(OS_CYGWIN_NT) || defined(OS_INTERIX)
305 #define SAVEREGISTERS \
306         subl    $32, %esp;\
307         movups  %xmm6,    0(%esp);\
308         movups  %xmm7,   16(%esp)
309
310 #define RESTOREREGISTERS \
311         movups     0(%esp), %xmm6;\
312         movups    16(%esp), %xmm7;\
313         addl    $32, %esp
314 #else
315 #define SAVEREGISTERS
316 #define RESTOREREGISTERS
317 #endif
318
319 #if defined(OS_WINNT) || defined(OS_CYGWIN_NT) || defined(OS_INTERIX)
320 #define PROLOGUE \
321         .text; \
322         .align 16; \
323         .globl REALNAME ;\
324         .def REALNAME;.scl      2;.type 32;.endef; \
325 REALNAME:
326
327 #define PROFCODE
328
329 #ifdef __clang__
330 #define EPILOGUE .end
331 #else
332 #define EPILOGUE .end    REALNAME
333 #endif
334 #endif
335
336 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(__ELF__)
337 #define PROLOGUE \
338         .text; \
339         .align 16; \
340         .globl REALNAME ;\
341        .type REALNAME, @function; \
342 REALNAME:
343
344 #ifdef PROFILE
345 #define PROFCODE call mcount
346 #else
347 #define PROFCODE
348 #endif
349
350 #define EPILOGUE \
351         .size    REALNAME, .-REALNAME; \
352         .section .note.GNU-stack,"",@progbits
353
354 #endif
355
356 #ifdef XDOUBLE
357 #define FLD     fldt
358 #define FST     fstpt
359 #define FSTU    fstt
360 #define FMUL    fmult
361 #define FADD    faddt
362 #define FSUB    fsubt
363 #define FSUBR   fsubrt
364 #elif defined(DOUBLE)
365 #define FLD     fldl
366 #define FST     fstpl
367 #define FSTU    fstl
368 #define FMUL    fmull
369 #define FADD    faddl
370 #define FSUB    fsubl
371 #define FSUBR   fsubrl
372 #else
373 #define FLD     flds
374 #define FST     fstps
375 #define FSTU    fsts
376 #define FMUL    fmuls
377 #define FADD    fadds
378 #define FSUB    fsubs
379 #define FSUBR   fsubrs
380 #endif
381 #endif
382
383 #ifdef C_SUN
384 #define ffreep  fstp
385 #endif
386
387 #ifdef __APPLE__
388 #define ALIGN_2 .align 2
389 #define ALIGN_3 .align 3
390 #define ALIGN_4 .align 4
391 #define ALIGN_5 .align 5
392 #define ffreep  fstp
393 #endif
394
395 #ifndef ALIGN_2
396 #define ALIGN_2 .align 4
397 #endif
398
399 #ifndef ALIGN_3
400 #define ALIGN_3 .align 8
401 #endif
402
403 #ifndef ALIGN_4
404 #define ALIGN_4 .align 16
405 #endif
406
407 #ifndef ALIGN_5
408 #define ALIGN_5 .align 32
409 #endif
410
411 #ifndef ALIGN_6
412 #define ALIGN_6 .align 64
413 #endif
414 // ffreep %st(0).
415 // Because Clang didn't support ffreep, we directly use the opcode.
416 // Please check out http://www.sandpile.org/x86/opc_fpu.htm
417 #ifndef ffreep
418 #define ffreep .byte 0xdf, 0xc0 #
419 #endif