Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / filter / gr_fir_sysconfig_x86.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2002 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <gr_fir_sysconfig_x86.h>
26 #include <gr_cpu.h>
27
28 #include <gr_fir_ccf.h>
29 #include <gr_fir_ccf_generic.h>
30 #include <gr_fir_ccf_x86.h>
31 #include <gr_fir_fcc.h>
32 #include <gr_fir_fcc_generic.h>
33 #include <gr_fir_fcc_x86.h>
34 #include <gr_fir_fff.h>
35 #include <gr_fir_fff_generic.h>
36 #include <gr_fir_fff_x86.h>
37 #include <gr_fir_fsf.h>
38 #include <gr_fir_fsf_generic.h>
39 #include <gr_fir_fsf_x86.h>
40 #include <gr_fir_ccc.h>
41 #include <gr_fir_ccc_generic.h>
42 #include <gr_fir_ccc_x86.h>
43 #include <gr_fir_scc.h>
44 #include <gr_fir_scc_generic.h>
45 #include <gr_fir_scc_x86.h>
46 // #include <gr_fir_sss.h>
47 // #include <gr_fir_sss_generic.h>
48 // #include <gr_fir_sss_mmx.h>
49 // #include <gr_fir_sss_sse2.h>
50
51 #include <iostream>
52 using std::cerr;
53
54 /*
55  * ----------------------------------------------------------------
56  * static functions that serve as constructors...
57  * Is it possible to take the address of a normal constructor?
58  * ----------------------------------------------------------------
59  */
60
61 static gr_fir_ccf *
62 make_gr_fir_ccf_3dnow(const std::vector<float> &taps)
63 {
64   return new gr_fir_ccf_3dnow(taps);
65 }
66
67 static gr_fir_ccf *
68 make_gr_fir_ccf_sse(const std::vector<float> &taps)
69 {
70   return new gr_fir_ccf_sse(taps);
71 }
72
73 static gr_fir_fcc *
74 make_gr_fir_fcc_3dnow(const std::vector<gr_complex> &taps)
75 {
76   return new gr_fir_fcc_3dnow(taps);
77 }
78
79 static gr_fir_fcc *
80 make_gr_fir_fcc_sse(const std::vector<gr_complex> &taps)
81 {
82   return new gr_fir_fcc_sse(taps);
83 }
84
85 static gr_fir_ccc *
86 make_gr_fir_ccc_3dnow (const std::vector<gr_complex> &taps)
87 {
88   return new gr_fir_ccc_3dnow (taps);
89 }
90
91 static gr_fir_ccc *
92 make_gr_fir_ccc_3dnowext (const std::vector<gr_complex> &taps)
93 {
94   return new gr_fir_ccc_3dnowext (taps);
95 }
96
97 static gr_fir_ccc *
98 make_gr_fir_ccc_sse (const std::vector<gr_complex> &taps)
99 {
100   return new gr_fir_ccc_sse (taps);
101 }
102
103 static gr_fir_fff *
104 make_gr_fir_fff_3dnow (const std::vector<float> &taps)
105 {
106   return new gr_fir_fff_3dnow (taps);
107 }
108
109 static gr_fir_fff *
110 make_gr_fir_fff_sse (const std::vector<float> &taps)
111 {
112   return new gr_fir_fff_sse (taps);
113 }
114
115 static gr_fir_fsf *
116 make_gr_fir_fsf_3dnow (const std::vector<float> &taps)
117 {
118   return new gr_fir_fsf_3dnow (taps);
119 }
120
121 static gr_fir_fsf *
122 make_gr_fir_fsf_sse (const std::vector<float> &taps)
123 {
124   return new gr_fir_fsf_sse (taps);
125 }
126
127 #if 0
128 static gr_fir_sss *
129 make_gr_fir_sss_mmx (const std::vector<short> &taps)
130 {
131   return new gr_fir_sss_mmx (taps);
132 }
133
134 static gr_fir_sss *
135 make_gr_fir_sss_sse2 (const std::vector<short> &taps)
136 {
137   return new gr_fir_sss_sse2 (taps);
138 }
139 #endif
140
141 static gr_fir_scc *
142 make_gr_fir_scc_3dnow(const std::vector<gr_complex> &taps)
143 {
144   return new gr_fir_scc_3dnow(taps);
145 }
146
147 static gr_fir_scc *
148 make_gr_fir_scc_3dnowext(const std::vector<gr_complex> &taps)
149 {
150   return new gr_fir_scc_3dnowext(taps);
151 }
152
153 static gr_fir_scc *
154 make_gr_fir_scc_sse(const std::vector<gr_complex> &taps)
155 {
156   return new gr_fir_scc_sse(taps);
157 }
158
159 /*
160  * ----------------------------------------------------------------
161  * Return instances of the fastest x86 versions of these classes.
162  *
163  * check CPUID, if has 3DNowExt, return 3DNow!Ext version,
164  *              else if 3DNow, return 3DNow! version,
165  *              else if SSE2, return SSE2 version,
166  *              else if SSE, return SSE version,
167  *              else if MMX, return MMX version,
168  *              else return generic version.
169  *
170  * FIXME: benchmark, store result, use stored result to
171  *   select the fastest version.
172  * ----------------------------------------------------------------
173  */
174
175 gr_fir_ccf *
176 gr_fir_sysconfig_x86::create_gr_fir_ccf (const std::vector<float> &taps)
177 {
178   static bool first = true;
179
180   if (gr_cpu::has_3dnow ()){
181     if (first){
182       cerr << ">>> gr_fir_ccf: using 3DNow!\n";
183       first = false;
184     }
185     return make_gr_fir_ccf_3dnow (taps);
186   }
187
188   if (gr_cpu::has_sse ()){
189     if (first){
190       cerr << ">>> gr_fir_ccf: using SSE\n";
191       first = false;
192     }
193     return make_gr_fir_ccf_sse (taps);
194   }
195
196   if (first){
197     cerr << ">>> gr_fir_ccf: handing off to parent class\n";
198     first = false;
199   }
200   return gr_fir_sysconfig_generic::create_gr_fir_ccf (taps);
201 }
202
203 gr_fir_fcc *
204 gr_fir_sysconfig_x86::create_gr_fir_fcc (const std::vector<gr_complex> &taps)
205 {
206   static bool first = true;
207
208   if (gr_cpu::has_3dnow ()){
209     if (first){
210       cerr << ">>> gr_fir_fcc: using 3DNow!\n";
211       first = false;
212     }
213     return make_gr_fir_fcc_3dnow (taps);
214   }
215
216   if (gr_cpu::has_sse ()){
217     if (first){
218       cerr << ">>> gr_fir_fcc: using SSE\n";
219       first = false;
220     }
221     return make_gr_fir_fcc_sse (taps);
222   }
223
224   if (first){
225     cerr << ">>> gr_fir_fcc: handing off to parent class\n";
226     first = false;
227   }
228   return gr_fir_sysconfig_generic::create_gr_fir_fcc (taps);
229 }
230
231 gr_fir_ccc *
232 gr_fir_sysconfig_x86::create_gr_fir_ccc (const std::vector<gr_complex> &taps)
233 {
234   static bool first = true;
235
236   if (gr_cpu::has_3dnowext ()){
237     if (first) {
238       cerr << ">>> gr_fir_ccc: using 3DNow!Ext\n";
239       first = false;
240     }
241     return make_gr_fir_ccc_3dnowext (taps);
242   }
243
244   if (gr_cpu::has_3dnow ()){
245     if (first) {
246       cerr << ">>> gr_fir_ccc: using 3DNow!\n";
247       first = false;
248     }
249     return make_gr_fir_ccc_3dnow (taps);
250   }
251
252   if (gr_cpu::has_sse ()){
253     if (first){
254       cerr << ">>> gr_fir_ccc: using SSE\n";
255       first = false;
256     }
257     return make_gr_fir_ccc_sse (taps);
258   }
259   
260   if (first){
261     cerr << ">>> gr_fir_ccc: handing off to parent class\n";
262     first = false;
263   }
264   return gr_fir_sysconfig_generic::create_gr_fir_ccc (taps);
265 }
266
267 gr_fir_fff *
268 gr_fir_sysconfig_x86::create_gr_fir_fff (const std::vector<float> &taps)
269 {
270   static bool first = true;
271
272   if (gr_cpu::has_3dnow ()){
273     if (first) {
274       cerr << ">>> gr_fir_fff: using 3DNow!\n";
275       first = false;
276     }
277     return make_gr_fir_fff_3dnow (taps);
278   }
279
280   if (gr_cpu::has_sse ()){
281     if (first){
282       cerr << ">>> gr_fir_fff: using SSE\n";
283       first = false;
284     }
285     return make_gr_fir_fff_sse (taps);
286   }
287   
288   if (first){
289     cerr << ">>> gr_fir_fff: handing off to parent class\n";
290     first = false;
291   }
292   return gr_fir_sysconfig_generic::create_gr_fir_fff (taps);
293 }
294
295 gr_fir_fsf *
296 gr_fir_sysconfig_x86::create_gr_fir_fsf (const std::vector<float> &taps)
297 {
298   static bool first = true;
299
300   if (gr_cpu::has_3dnow ()){
301     if (first) {
302       cerr << ">>> gr_fir_fsf: using 3DNow!\n";
303       first = false;
304     }
305     return make_gr_fir_fsf_3dnow (taps);
306   }
307
308   if (gr_cpu::has_sse ()){
309     if (first){
310       cerr << ">>> gr_fir_fsf: using SSE\n";
311       first = false;
312     }
313     return make_gr_fir_fsf_sse (taps);
314   }
315   
316   if (first){
317     cerr << ">>> gr_fir_fsf: handing off to parent class\n";
318     first = false;
319   }
320   return gr_fir_sysconfig_generic::create_gr_fir_fsf (taps);
321 }
322
323 #if 0
324 gr_fir_sss *
325 gr_fir_sysconfig_x86::create_gr_fir_sss (const std::vector<short> &taps)
326 {
327   // FIXME -- probably want to figure out best answer for Athlon and code
328   // add code to select it here...
329
330   if (gr_cpu::has_sse2 ()){
331     cerr << ">>> gr_fir_sss: using SSE2\n";
332     return make_gr_fir_sss_sse2 (taps);
333   }
334   
335   if (gr_cpu::has_mmx ()){
336     cerr << ">>> gr_fir_sss: using MMX\n";
337     return make_gr_fir_sss_mmx (taps);
338   }
339   
340   cerr << ">>> gr_fir_sss: handing off to parent class\n";
341   return gr_fir_sysconfig_generic::create_gr_fir_sss (taps);
342 }
343 #endif
344
345 gr_fir_scc *
346 gr_fir_sysconfig_x86::create_gr_fir_scc (const std::vector<gr_complex> &taps)
347 {
348   static bool first = true;
349
350   if (gr_cpu::has_3dnowext ()){
351     if (first){
352       cerr << ">>> gr_fir_scc: using 3DNow!Ext\n";
353       first = false;
354     }
355     return make_gr_fir_scc_3dnowext (taps);
356   }
357
358   if (gr_cpu::has_3dnow ()){
359     if (first){
360       cerr << ">>> gr_fir_scc: using 3DNow!\n";
361       first = false;
362     }
363     return make_gr_fir_scc_3dnow (taps);
364   }
365
366   if (gr_cpu::has_sse ()){
367     if (first){
368       cerr << ">>> gr_fir_scc: using SSE\n";
369       first = false;
370     }
371     return make_gr_fir_scc_sse (taps);
372   }
373
374   if (first){
375     cerr << ">>> gr_fir_scc: handing off to parent class\n";
376     first = false;
377   }
378   return gr_fir_sysconfig_generic::create_gr_fir_scc (taps);
379 }
380
381 /*
382  * ----------------------------------------------------------------
383  *         Return info about available implementations
384  * ----------------------------------------------------------------
385  */
386
387 void 
388 gr_fir_sysconfig_x86::get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info)
389 {
390   gr_fir_ccf_info       t;
391
392   // invoke parent..
393   gr_fir_sysconfig_generic::get_gr_fir_ccf_info (info);
394
395   // add our stuff...
396   if (gr_cpu::has_3dnow ()){
397     t.name = "3DNow!";
398     t.create = make_gr_fir_ccf_3dnow;
399     (*info).push_back (t);
400   }
401
402   if (gr_cpu::has_sse ()){
403     t.name = "SSE";
404     t.create = make_gr_fir_ccf_sse;
405     (*info).push_back (t);
406   }
407 }
408
409 void 
410 gr_fir_sysconfig_x86::get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info)
411 {
412   gr_fir_fcc_info       t;
413
414   // invoke parent..
415   gr_fir_sysconfig_generic::get_gr_fir_fcc_info (info);
416
417   // add our stuff...
418   if (gr_cpu::has_3dnow ()){
419     t.name = "3DNow!";
420     t.create = make_gr_fir_fcc_3dnow;
421     (*info).push_back (t);
422   }
423
424   if (gr_cpu::has_sse ()){
425     t.name = "SSE";
426     t.create = make_gr_fir_fcc_sse;
427     (*info).push_back (t);
428   }
429 }
430
431 void 
432 gr_fir_sysconfig_x86::get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info)
433 {
434   gr_fir_ccc_info       t;
435   
436   // invoke parent..
437   gr_fir_sysconfig_generic::get_gr_fir_ccc_info (info);
438
439   // add our stuff...
440   if (gr_cpu::has_3dnowext ()){
441     t.name = "3DNow!Ext";
442     t.create = make_gr_fir_ccc_3dnowext;
443     (*info).push_back (t);
444   }
445
446   if (gr_cpu::has_3dnow ()){
447     t.name = "3DNow!";
448     t.create = make_gr_fir_ccc_3dnow;
449     (*info).push_back (t);
450   }
451
452   if (gr_cpu::has_sse ()){
453     t.name = "SSE";
454     t.create = make_gr_fir_ccc_sse;
455     (*info).push_back (t);
456   }
457 }
458
459 void 
460 gr_fir_sysconfig_x86::get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info)
461 {
462   gr_fir_fff_info       t;
463   
464   // invoke parent..
465   gr_fir_sysconfig_generic::get_gr_fir_fff_info (info);
466
467   // add our stuff...
468   if (gr_cpu::has_3dnow ()){
469     t.name = "3DNow!";
470     t.create = make_gr_fir_fff_3dnow;
471     (*info).push_back (t);
472   }
473
474   if (gr_cpu::has_sse ()){
475     t.name = "SSE";
476     t.create = make_gr_fir_fff_sse;
477     (*info).push_back (t);
478   }
479 }
480
481 void 
482 gr_fir_sysconfig_x86::get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info)
483 {
484   gr_fir_fsf_info       t;
485   
486   // invoke parent..
487   gr_fir_sysconfig_generic::get_gr_fir_fsf_info (info);
488
489   // add our stuff...
490   if (gr_cpu::has_3dnow ()){
491     t.name = "3DNow!";
492     t.create = make_gr_fir_fsf_3dnow;
493     (*info).push_back (t);
494   }
495
496   if (gr_cpu::has_sse ()){
497     t.name = "SSE";
498     t.create = make_gr_fir_fsf_sse;
499     (*info).push_back (t);
500   }
501 }
502
503 void 
504 gr_fir_sysconfig_x86::get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info)
505 {
506   gr_fir_scc_info       t;
507
508   // invoke parent..
509   gr_fir_sysconfig_generic::get_gr_fir_scc_info (info);
510
511   // add our stuff...
512   if (gr_cpu::has_3dnowext ()){
513     t.name = "3DNow!Ext";
514     t.create = make_gr_fir_scc_3dnowext;
515     (*info).push_back (t);
516   }
517
518   if (gr_cpu::has_3dnow ()){
519     t.name = "3DNow!";
520     t.create = make_gr_fir_scc_3dnow;
521     (*info).push_back (t);
522   }
523
524   if (gr_cpu::has_sse ()){
525     t.name = "SSE";
526     t.create = make_gr_fir_scc_sse;
527     (*info).push_back (t);
528   }
529 }
530
531 #if 0
532 void 
533 gr_fir_sysconfig_x86::get_gr_fir_sss_info (std::vector<gr_fir_sss_info> *info)
534 {
535   gr_fir_sss_info       t;
536   
537   // invoke parent..
538   gr_fir_sysconfig_generic::get_gr_fir_sss_info (info);
539
540   // add our stuff...
541   if (gr_cpu::has_mmx ()){
542     t.name = "MMX";
543     t.create = make_gr_fir_sss_mmx;
544     (*info).push_back (t);
545   }
546
547   if (gr_cpu::has_sse2 ()){
548     t.name = "SSE2";
549     t.create = make_gr_fir_sss_sse2;
550     (*info).push_back (t);
551   }
552 }
553 #endif