Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_sse2_single / nb_kernel_sse2_single.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_single.h"
30
31 /* Include single precision SSE intrinsics kernel headers in local directory */
32 #include "nb_kernel400_sse2_single.h"
33 #include "nb_kernel410_sse2_single.h"
34 #include "nb_kernel430_sse2_single.h"
35
36 #include <stdlib.h>
37 #include <stdio.h>
38
39 #ifdef _MSC_VER
40 /* MSVC definition for __cpuid() */
41 #include <intrin.h>
42 #endif
43
44 #include "../nb_kerneltype.h"
45 #include "nb_kernel_sse2_single.h"
46
47 static nb_kernel_t *
48 kernellist_sse2_single[eNR_NBKERNEL_NR] = 
49 {
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     NULL,
109     NULL,
110     NULL,
111     NULL,
112     NULL,
113     nb_kernel400_sse2_single,
114     nb_kernel410_sse2_single,
115     nb_kernel430_sse2_single
116 };
117
118
119 /* Return 0 if SSE support is present, or
120  * non-zero on failure.
121  */
122 int 
123 nb_kernel_sse2_single_test(FILE *                log)
124 {
125         unsigned int level;
126         unsigned int _eax,_ebx,_ecx,_edx;
127         int status;
128         int CPUInfo[4];
129         
130         if(NULL != log)
131     {
132                 fprintf(log,"Checking CPU SSE2 support... ");
133     }
134         
135         level = 1;
136 #ifdef _MSC_VER
137         __cpuid(CPUInfo,1);
138         
139         _eax=CPUInfo[0];
140         _ebx=CPUInfo[1];
141         _ecx=CPUInfo[2];
142         _edx=CPUInfo[3];
143         
144 #elif defined(__x86_64__)
145         /* GCC 64-bit inline asm */
146         __asm__ ("push %%rbx\n\tcpuid\n\tpop %%rbx\n"                 \
147                          : "=a" (_eax), "=S" (_ebx), "=c" (_ecx), "=d" (_edx) \
148                          : "0" (level));
149 #elif defined(__i386__)
150         __asm__ ("push %%ebx\n\tcpuid\n\tpop %%ebx\n"                 \
151                          : "=a" (_eax), "=S" (_ebx), "=c" (_ecx), "=d" (_edx) \
152                          : "0" (level));
153 #else
154         if(NULL != log)
155         {
156                 fprintf(log,"Don't know how to call cpuid() on this system!\n");
157         }
158         _eax=_ebx=_ecx=_edx=0;
159 #endif
160         
161         /* Features:                                                                                                       
162          *                                                                                                                 
163          * SSE      Bit 25 of edx should be set                                                                            
164          * SSE2     Bit 26 of edx should be set                                                                            
165          * SSE3     Bit  0 of ecx should be set                                                                            
166          * SSE4.1   Bit 19 of ecx should be set                                                                            
167          */
168         status =  (_edx & (1 << 26)) != 0;
169
170         if(NULL != log)
171         {
172                 fprintf(log,"%s present.", (status==0) ? "not" : "");
173         }
174         
175         /* Return SSE2 status */
176         return status;
177 }
178
179
180
181
182 void
183 nb_kernel_setup_sse2_single(FILE *log,nb_kernel_t **list)
184 {
185     int i;
186     nb_kernel_t *p;
187     
188     if(nb_kernel_sse2_single_test(log) == 0)
189     {
190                 return;
191     }
192         
193     for(i=0;i<eNR_NBKERNEL_NR;i++)
194     {
195         p = kernellist_sse2_single[i];
196         if(p!=NULL)
197                 {
198                         list[i] = p; 
199                 }
200     }
201 }    
202
203
204         
205
206