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