Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_sse2_double / nb_kernel_sse2_double.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*- 
2  *
3  * This file is part of Gromacs        Copyright (c) 1991-2004
4  * David van der Spoel, Erik Lindahl, University of Groningen.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * To help us fund GROMACS development, we humbly ask that you cite
12  * the research papers on the package. Check out http://www.gromacs.org
13  * 
14  * And Hey:
15  * Gnomes, ROck Monsters And Chili Sauce
16  */
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 /* Must come directly after config.h */
22 #ifdef GMX_THREAD_SHM_FDECOMP
23 #include <thread_mpi.h>
24 #endif
25
26 #include <types/simple.h>
27 #include <types/nrnb.h>
28
29 #include "nb_kernel_sse2_double.h"
30
31 /* Include double precision SSE intrinsics kernel headers in local directory */
32 #include "nb_kernel400_sse2_double.h"
33 #include "nb_kernel410_sse2_double.h"
34 #include "nb_kernel430_sse2_double.h"
35
36 #include <stdlib.h>
37 #include <stdio.h>
38
39 #include "../nb_kerneltype.h"
40 #include "nb_kernel_sse2_double.h"
41
42 static nb_kernel_t *
43 kernellist_sse2_double[eNR_NBKERNEL_NR] = 
44 {
45     NULL,
46     NULL,
47     NULL,
48     NULL,
49     NULL,
50     NULL,
51     NULL,
52     NULL,
53     NULL,
54     NULL,
55     NULL,
56     NULL,
57     NULL,
58     NULL,
59     NULL,
60     NULL,
61     NULL,
62     NULL,
63     NULL,
64     NULL,
65     NULL,
66     NULL,
67     NULL,
68     NULL,
69     NULL,
70     NULL,
71     NULL,
72     NULL,
73     NULL,
74     NULL,
75     NULL,
76     NULL,
77     NULL,
78     NULL,
79     NULL,
80     NULL,
81     NULL,
82     NULL,
83     NULL,
84     NULL,
85     NULL,
86     NULL,
87     NULL,
88     NULL,
89     NULL,
90     NULL,
91     NULL,
92     NULL,
93     NULL,
94     NULL,
95     NULL,
96     NULL,
97     NULL,
98     NULL,
99     NULL,
100     NULL,
101     NULL,
102     NULL,
103     NULL,
104     NULL,
105     NULL,
106     NULL,
107     NULL,
108     nb_kernel400_sse2_double,
109     nb_kernel410_sse2_double,
110     nb_kernel430_sse2_double
111 };
112
113
114 /* Return 0 if SSE support is present, or
115  * non-zero on failure.
116  */
117 int 
118 nb_kernel_sse2_double_test(FILE *                log)
119 {
120         unsigned int level;
121         unsigned int _eax,_ebx,_ecx,_edx;
122         int status;
123         int CPUInfo[4];
124         
125         if(NULL != log)
126     {
127                 fprintf(log,"Checking CPU SSE2 support... ");
128     }
129         
130         level = 1;
131 #ifdef _MSC_VER
132         __cpuid(CPUInfo,1);
133         
134         _eax=CPUInfo[0];
135         _ebx=CPUInfo[1];
136         _ecx=CPUInfo[2];
137         _edx=CPUInfo[3];
138         
139 #elif defined(__x86_64__)
140         /* GCC 64-bit inline asm */
141         __asm__ ("push %%rbx\n\tcpuid\n\tpop %%rbx\n"                 \
142                          : "=a" (_eax), "=S" (_ebx), "=c" (_ecx), "=d" (_edx) \
143                          : "0" (level));
144 #elif defined(__i386__)
145         __asm__ ("push %%ebx\n\tcpuid\n\tpop %%ebx\n"                 \
146                          : "=a" (_eax), "=S" (_ebx), "=c" (_ecx), "=d" (_edx) \
147                          : "0" (level));
148 #else
149         if(NULL != log)
150         {
151                 fprintf(log,"Don't know how to call cpuid() on this system!\n");
152         }
153         _eax=_ebx=_ecx=_edx=0;
154 #endif
155         
156         /* Features:                                                                                                       
157          *                                                                                                                 
158          * SSE      Bit 25 of edx should be set                                                                            
159          * SSE2     Bit 26 of edx should be set                                                                            
160          * SSE3     Bit  0 of ecx should be set                                                                            
161          * SSE4.1   Bit 19 of ecx should be set                                                                            
162          */
163         status =  (_edx & (1 << 26)) != 0;
164         
165         if(NULL != log)
166         {
167                 fprintf(log,"%s present.", (status==0) ? "not" : "");
168         }
169         
170         /* Return SSE2 status */
171         return status;
172 }
173
174
175
176
177 void
178 nb_kernel_setup_sse2_double(FILE *log,nb_kernel_t **list)
179 {
180     int i;
181     nb_kernel_t *p;
182     
183     if(nb_kernel_sse2_double_test(log) == 0)
184     {
185                 return;
186     }
187         
188     for(i=0;i<eNR_NBKERNEL_NR;i++)
189     {
190         p = kernellist_sse2_double[i];
191         if(p!=NULL)
192                 {
193                         list[i] = p; 
194                 }
195     }
196 }    
197
198
199         
200
201