add fallback blas_lock implementation
[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 #define MB
45 #define WMB
46
47 #ifdef C_SUN
48 #define __asm__ __asm
49 #define __volatile__
50 #endif
51
52 static void __inline blas_lock(volatile BLASULONG *address){
53
54   int ret;
55
56   do {
57     while (*address) {YIELDING;};
58
59     __asm__ __volatile__(
60                          "xchgl %0, %1\n"
61                          : "=r"(ret), "=m"(*address)
62                          : "0"(1), "m"(*address)
63                          : "memory");
64
65   } while (ret);
66
67 }
68 #define BLAS_LOCK_DEFINED
69
70 static __inline unsigned long long rpcc(void){
71   unsigned int a, d;
72
73   __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d));
74
75   return ((unsigned long long)a + ((unsigned long long)d << 32));
76 };
77 #define RPCC_DEFINED
78
79 static __inline unsigned long getstackaddr(void){
80   unsigned long addr;
81
82   __asm__ __volatile__ ("mov %%esp, %0"
83                          : "=r"(addr) : : "memory");
84
85   return addr;
86 };
87
88
89 static __inline long double sqrt_long(long double val) {
90   long double result;
91
92   __asm__ __volatile__ ("fldt %1\n"
93                     "fsqrt\n"
94                     "fstpt %0\n" : "=m" (result) : "m"(val));
95   return result;
96 }
97
98 #define SQRT(a)  sqrt_long(a)
99
100 /* This is due to gcc's bug */
101 void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx);
102
103 #define WHEREAMI
104
105 static inline int WhereAmI(void){
106   int eax, ebx, ecx, edx;
107   int apicid;
108
109   cpuid(1, &eax, &ebx, &ecx, &edx);
110   apicid  = BITMASK(ebx, 24, 0xff);
111
112   return apicid;
113 }
114
115 #ifdef ENABLE_SSE_EXCEPTION
116
117 #define IDEBUG_START \
118 { \
119   unsigned int fp_sse_mode, new_fp_mode; \
120   __asm__ __volatile__ ("stmxcsr %0" : "=m" (fp_sse_mode) : ); \
121   new_fp_mode = fp_sse_mode & ~0xd00; \
122   __asm__ __volatile__ ("ldmxcsr %0" : : "m" (new_fp_mode) );
123
124 #define IDEBUG_END \
125   __asm__ __volatile__ ("ldmxcsr %0" : : "m" (fp_sse_mode) ); \
126 }
127
128 #endif
129
130 #ifdef XDOUBLE
131 #define GET_IMAGE(res)  __asm__ __volatile__("fstpt %0" : "=m"(res) : : "memory")
132 #elif defined(DOUBLE)
133 #define GET_IMAGE(res)  __asm__ __volatile__("fstpl %0" : "=m"(res) : : "memory")
134 #else
135 #define GET_IMAGE(res)  __asm__ __volatile__("fstps %0" : "=m"(res) : : "memory");
136 #endif
137
138 #define GET_IMAGE_CANCEL        __asm__ __volatile__ ("ffree %st")
139
140 #ifdef SMP
141 extern unsigned int blas_quick_divide_table[];
142
143 static __inline int blas_quickdivide(unsigned int x, unsigned int y){
144
145   unsigned int result;
146
147   if (y <= 1) return x;
148
149   y = blas_quick_divide_table[y];
150
151   __asm__ __volatile__  ("mull %0" :"=d" (result) :"a"(x), "0" (y));
152
153   return result;
154 }
155 #endif
156
157 #endif
158
159 #ifndef PAGESIZE
160 #define PAGESIZE        ( 4 << 10)
161 #endif
162 #define HUGE_PAGESIZE   ( 4 << 20)
163
164 #define BUFFER_SIZE     (16 << 20)
165
166 #define SEEK_ADDRESS
167
168 #if defined(DOUBLE) || defined(XDOUBLE)
169 #define MMXLOAD         movq
170 #define MMXSTORE        movq
171 #else
172 #define MMXLOAD         movd
173 #define MMXSTORE        movd
174 #endif
175
176 #if defined(PILEDRIVER) || defined(BULLDOZER) || defined(STEAMROLLER) || defined(EXCAVATOR)
177 //Enable some optimazation for barcelona.
178 #define BARCELONA_OPTIMIZATION
179 #endif
180
181 #if defined(HAVE_3DNOW)
182 #define EMMS    femms
183 #elif defined(HAVE_MMX)
184 #define EMMS    emms
185 #endif
186
187 #ifndef EMMS
188 #define EMMS
189 #endif
190
191 #if defined(CORE2) || defined(PENTIUM4)
192 #define movapd  movaps
193 #endif
194
195 #define BRANCH          .byte 0x3e
196 #define NOBRANCH        .byte 0x2e
197 #define PADDING         .byte 0x66;
198 #define HALT            hlt
199
200 #ifndef COMPLEX
201 #ifdef XDOUBLE
202 #define LOCAL_BUFFER_SIZE  QLOCAL_BUFFER_SIZE
203 #elif defined DOUBLE
204 #define LOCAL_BUFFER_SIZE  DLOCAL_BUFFER_SIZE
205 #else
206 #define LOCAL_BUFFER_SIZE  SLOCAL_BUFFER_SIZE
207 #endif
208 #else
209 #ifdef XDOUBLE
210 #define LOCAL_BUFFER_SIZE  XLOCAL_BUFFER_SIZE
211 #elif defined DOUBLE
212 #define LOCAL_BUFFER_SIZE  ZLOCAL_BUFFER_SIZE
213 #else
214 #define LOCAL_BUFFER_SIZE  CLOCAL_BUFFER_SIZE
215 #endif
216 #endif
217
218 #if defined(OS_WINDOWS)
219 #if   LOCAL_BUFFER_SIZE > 16384
220 #define STACK_TOUCHING \
221         movl    $0,  4096 * 4(%esp);\
222         movl    $0,  4096 * 3(%esp);\
223         movl    $0,  4096 * 2(%esp);\
224         movl    $0,  4096 * 1(%esp);
225 #elif LOCAL_BUFFER_SIZE > 12288
226 #define STACK_TOUCHING \
227         movl    $0,  4096 * 3(%esp);\
228         movl    $0,  4096 * 2(%esp);\
229         movl    $0,  4096 * 1(%esp);
230 #elif LOCAL_BUFFER_SIZE > 8192
231 #define STACK_TOUCHING \
232         movl    $0,  4096 * 2(%esp);\
233         movl    $0,  4096 * 1(%esp);
234 #elif LOCAL_BUFFER_SIZE > 4096
235 #define STACK_TOUCHING \
236         movl    $0,  4096 * 1(%esp);
237 #else
238 #define STACK_TOUCHING
239 #endif
240 #else
241 #define STACK_TOUCHING
242 #endif
243
244 #ifndef F_INTERFACE
245 #define REALNAME ASMNAME
246 #else
247 #define REALNAME ASMFNAME
248 #endif
249
250 #if defined(F_INTERFACE_PATHSCALE) || defined(F_INTERFACE_OPEN64)
251 #define RETURN_BY_STRUCT
252 #elif defined(F_INTERFACE_GFORT) || defined(F_INTERFACE_G95)
253 #define RETURN_BY_COMPLEX
254 #else
255 #define RETURN_BY_STACK
256 #endif
257
258 #ifdef OS_DARWIN
259 #define PROLOGUE .text;.align 5; .globl REALNAME; REALNAME:
260 #define EPILOGUE        .subsections_via_symbols
261 #define PROFCODE
262 #endif
263
264 #if defined(OS_WINNT) || defined(OS_CYGWIN_NT) || defined(OS_INTERIX)
265 #define SAVEREGISTERS \
266         subl    $32, %esp;\
267         movups  %xmm6,    0(%esp);\
268         movups  %xmm7,   16(%esp)
269
270 #define RESTOREREGISTERS \
271         movups     0(%esp), %xmm6;\
272         movups    16(%esp), %xmm7;\
273         addl    $32, %esp
274 #else
275 #define SAVEREGISTERS
276 #define RESTOREREGISTERS
277 #endif
278
279 #if defined(OS_WINNT) || defined(OS_CYGWIN_NT) || defined(OS_INTERIX)
280 #define PROLOGUE \
281         .text; \
282         .align 16; \
283         .globl REALNAME ;\
284         .def REALNAME;.scl      2;.type 32;.endef; \
285 REALNAME:
286
287 #define PROFCODE
288
289 #define EPILOGUE .end    REALNAME
290 #endif
291
292 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(__ELF__)
293 #define PROLOGUE \
294         .text; \
295         .align 16; \
296         .globl REALNAME ;\
297        .type REALNAME, @function; \
298 REALNAME:
299
300 #ifdef PROFILE
301 #define PROFCODE call mcount
302 #else
303 #define PROFCODE
304 #endif
305
306 #define EPILOGUE \
307         .size    REALNAME, .-REALNAME; \
308         .section .note.GNU-stack,"",@progbits
309
310 #endif
311
312 #ifdef XDOUBLE
313 #define FLD     fldt
314 #define FST     fstpt
315 #define FSTU    fstt
316 #define FMUL    fmult
317 #define FADD    faddt
318 #define FSUB    fsubt
319 #define FSUBR   fsubrt
320 #elif defined(DOUBLE)
321 #define FLD     fldl
322 #define FST     fstpl
323 #define FSTU    fstl
324 #define FMUL    fmull
325 #define FADD    faddl
326 #define FSUB    fsubl
327 #define FSUBR   fsubrl
328 #else
329 #define FLD     flds
330 #define FST     fstps
331 #define FSTU    fsts
332 #define FMUL    fmuls
333 #define FADD    fadds
334 #define FSUB    fsubs
335 #define FSUBR   fsubrs
336 #endif
337 #endif
338
339 #ifdef C_SUN
340 #define ffreep  fstp
341 #endif
342
343 #ifdef __APPLE__
344 #define ALIGN_2 .align 2
345 #define ALIGN_3 .align 3
346 #define ALIGN_4 .align 4
347 #define ALIGN_5 .align 5
348 #define ffreep  fstp
349 #endif
350
351 #ifndef ALIGN_2
352 #define ALIGN_2 .align 4
353 #endif
354
355 #ifndef ALIGN_3
356 #define ALIGN_3 .align 8
357 #endif
358
359 #ifndef ALIGN_4
360 #define ALIGN_4 .align 16
361 #endif
362
363 #ifndef ALIGN_5
364 #define ALIGN_5 .align 32
365 #endif
366
367 #ifndef ALIGN_6
368 #define ALIGN_6 .align 64
369 #endif
370 // ffreep %st(0).
371 // Because Clang didn't support ffreep, we directly use the opcode.
372 // Please check out http://www.sandpile.org/x86/opc_fpu.htm
373 #ifndef ffreep
374 #define ffreep .byte 0xdf, 0xc0 #
375 #endif