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