move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_cpu.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include "evas_common.h"
6
7 #if defined BUILD_MMX || defined BUILD_SSE
8 #include "evas_mmx.h"
9 #endif
10
11 #include <setjmp.h>
12
13 #ifndef _WIN32
14 static sigjmp_buf detect_buf;
15 #endif
16
17 static int cpu_feature_mask = 0;
18
19 #ifndef _WIN32
20 static void evas_common_cpu_catch_ill(int sig);
21 static void evas_common_cpu_catch_segv(int sig);
22
23 static void
24 evas_common_cpu_catch_ill(int sig)
25 {
26    siglongjmp(detect_buf, 1);
27 }
28
29 static void
30 evas_common_cpu_catch_segv(int sig)
31 {
32    siglongjmp(detect_buf, 1);
33 }
34 #endif
35
36 void
37 evas_common_cpu_mmx_test(void)
38 {
39 #ifdef BUILD_MMX
40    pxor_r2r(mm4, mm4);
41 #endif
42 }
43
44 void
45 evas_common_cpu_mmx2_test(void)
46 {
47 #ifdef BUILD_MMX
48    char data[16];
49
50    data[0] = 0;
51    mmx_r2m(movntq, mm0, data);
52    data[0] = 0;
53 #endif
54 }
55
56 void
57 evas_common_cpu_sse_test(void)
58 {
59 #ifdef BUILD_SSE
60    int blah[16];
61
62    movntq_r2m(mm0, blah);
63 #endif
64 }
65
66 void
67 evas_common_cpu_altivec_test(void)
68 {
69 #ifdef __POWERPC__
70 #ifdef __VEC__
71    vector unsigned int zero;
72
73    zero = vec_splat_u32(0);
74 #endif /* __VEC__ */
75 #endif /* __POWERPC__ */
76 }
77
78 void
79 evas_common_cpu_vis_test(void)
80 {
81 #ifdef __SPARC__
82 #endif /* __SPARC__ */
83 }
84
85 int
86 evas_common_cpu_feature_test(void (*feature)(void))
87 {
88 #ifndef _WIN32
89    int enabled = 1;
90    struct sigaction act, oact, oact2;
91
92    act.sa_handler = evas_common_cpu_catch_ill;
93    act.sa_flags = SA_RESTART;
94    sigemptyset(&act.sa_mask);
95    sigaction(SIGILL, &act, &oact);
96
97    act.sa_handler = evas_common_cpu_catch_segv;
98    act.sa_flags = SA_RESTART;
99    sigemptyset(&act.sa_mask);
100    sigaction(SIGSEGV, &act, &oact2);
101
102    if (sigsetjmp(detect_buf, 1))
103      {
104         sigaction(SIGILL, &oact, NULL);
105         sigaction(SIGSEGV, &oact2, NULL);
106         return 0;
107      }
108
109    feature();
110
111    sigaction(SIGILL, &oact, NULL);
112    sigaction(SIGSEGV, &oact2, NULL);
113    return enabled;
114 #else
115    return 0;
116 #endif
117 }
118
119 EAPI void
120 evas_common_cpu_init(void)
121 {
122    static int called = 0;
123
124    if (called) return;
125    called = 1;
126 #ifdef BUILD_MMX
127    cpu_feature_mask |= CPU_FEATURE_MMX *
128      evas_common_cpu_feature_test(evas_common_cpu_mmx_test);
129    evas_common_cpu_end_opt();
130    cpu_feature_mask |= CPU_FEATURE_MMX2 *
131      evas_common_cpu_feature_test(evas_common_cpu_mmx2_test);
132    evas_common_cpu_end_opt();
133 #ifdef BUILD_SSE
134    cpu_feature_mask |= CPU_FEATURE_SSE *
135      evas_common_cpu_feature_test(evas_common_cpu_sse_test);
136    evas_common_cpu_end_opt();
137 #endif /* BUILD_SSE */
138 #endif /* BUILD_MMX */
139 #ifdef __POWERPC__
140 #ifdef __VEC__
141    cpu_feature_mask |= CPU_FEATURE_ALTIVEC *
142      evas_common_cpu_feature_test(evas_common_cpu_altivec_test);
143    evas_common_cpu_end_opt();
144 #endif /* __VEC__ */
145 #endif /* __POWERPC__ */
146 #ifdef __SPARC__
147    cpu_feature_mask |= CPU_FEATURE_VIS *
148      evas_common_cpu_feature_test(evas_common_cpu_vis_test);
149    evas_common_cpu_end_opt();
150 #endif /* __SPARC__ */
151 }
152
153 int
154 evas_common_cpu_has_feature(unsigned int feature)
155 {
156    return (cpu_feature_mask & feature);
157 }
158
159 int
160 evas_common_cpu_have_cpuid(void)
161 {
162    return 0;
163 /*
164 #ifdef BUILD_MMX
165    unsigned int have_cpu_id;
166
167    have_cpu_id = 0;
168    have_cpuid(have_cpu_id);
169    return have_cpu_id;
170 #else
171    return 0;
172 #endif
173  */
174 }
175
176 EAPI void
177 evas_common_cpu_can_do(int *mmx, int *sse, int *sse2)
178 {
179    static int do_mmx = 0, do_sse = 0, do_sse2 = 0, done = 0;
180
181    if (!done)
182      {
183 # ifdef HARD_CODED_P3
184         cpu_feature_mask |= CPU_FEATURE_MMX;
185         cpu_feature_mask |= CPU_FEATURE_SSE;
186 #endif
187 #ifdef HARD_CODED_P2
188         cpu_feature_mask |= CPU_FEATURE_MMX;
189 #endif
190         if (cpu_feature_mask & CPU_FEATURE_MMX) do_mmx = 1;
191         if (cpu_feature_mask & CPU_FEATURE_MMX2) do_sse = 1;
192         if (cpu_feature_mask & CPU_FEATURE_SSE) do_sse = 1;
193      }
194 //   printf("%i %i %i\n", do_mmx, do_sse, do_sse2);
195    *mmx = do_mmx;
196    *sse = do_sse;
197    *sse2 = do_sse2;
198    done = 1;
199 }
200
201 #ifdef BUILD_MMX
202 EAPI void
203 evas_common_cpu_end_opt(void)
204 {
205    if (cpu_feature_mask &
206        (CPU_FEATURE_MMX | CPU_FEATURE_MMX2))
207      {
208         emms();
209      }
210 }
211 #else
212 EAPI void
213 evas_common_cpu_end_opt(void)
214 {
215 }
216 #endif
217
218 EAPI int
219 evas_common_cpu_count(void)
220 {
221 #ifdef BUILD_PTHREAD
222    cpu_set_t cpu;
223    int i;
224    static int cpus = 0;
225
226    if (cpus != 0) return cpus;
227
228    sched_getaffinity(getpid(), sizeof(cpu), &cpu);
229    for (i = 0; i < TH_MAX; i++)
230      {
231         if (CPU_ISSET(i, &cpu)) cpus = i + 1;
232         else break;
233      }
234    return cpus;
235 #else
236    return 1;
237 #endif
238 }