00001 #ifndef FFT_3DNOW_H
00002 #define FFT_3DNOW_H
00003
00004
00005 #include <math.h>
00006
00007
00008 void fft_initCosSinTables_3dnow(complex<float> *w, int *bits, int M)
00009 {
00010 int i,j;
00011 int tmp;
00012 int size = 1 << M;
00013 for (i=0;i<size;i++)
00014 {
00015 bits[i]=0;
00016 tmp=i;
00017 for (j=0;j<M;j+=2)
00018 {
00019 bits[i] <<= 2;
00020 bits[i] += tmp&3;
00021 tmp>>=2;
00022 }
00023 }
00024
00025 while (size)
00026 {
00027 int k;
00028 float tmp, p = (2.0 * M_PI) / size;
00029 complex<float> tmp2;
00030 for (k = 0; k < (size>>1); k++) {
00031 tmp = k * p;
00032 tmp2.re=cos(tmp);
00033 tmp2.im=-sin(tmp);
00034 *w++ = tmp2;
00035 }
00036 for (k = 0; k < (size>>2); k++) {
00037 tmp = 2*k * p;
00038 tmp2.re=cos(tmp);
00039 tmp2.im=-sin(tmp);
00040 *w++ = tmp2;
00041 }
00042 for (k = 0; k < (size>>2); k++) {
00043 tmp = 3*k * p;
00044 tmp2.re=cos(tmp);
00045 tmp2.im=-sin(tmp);
00046 *w++ = tmp2;
00047 }
00048 size >>= 1;
00049 }
00050 }
00051
00052
00053
00054 class _negmask {
00055 int a;
00056 int b;
00057 public:
00058 _negmask() : a(0x80000000) , b(0x00000000) {}
00059 };
00060
00061 inline void fft_3dnow(complex<float> *in, complex<float> *_x, int _M, complex<float> *_w, int *bits)
00062 {
00063 complex<float> *w=_w+(1<<(_M+1))-2-6;
00064 _negmask mask;
00065 int rep = 1<<(_M-2);
00066
00067 __asm__ __volatile__ (
00068 "
00069 push %0
00070 push %1
00071 push %3
00072 push %4
00073 movq %2, %%mm7
00074 .align 16
00075 .loop%=:
00076 mov (%4), %%edx
00077 movq (%3,%%edx,8), %%mm0
00078 mov 8(%4), %%edx
00079 movq (%3,%%edx,8), %%mm1
00080
00081 movq %%mm0, %%mm4
00082 pfadd %%mm1, %%mm0
00083 pfsub %%mm1, %%mm4
00084
00085 mov 4(%4), %%edx
00086 movq (%3,%%edx,8), %%mm2
00087 mov 12(%4), %%edx
00088 movq (%3,%%edx,8), %%mm3
00089
00090 movq %%mm2, %%mm5
00091 pfadd %%mm3, %%mm2
00092
00093 mov 16(%4), %%edx
00094 pfsub %%mm3, %%mm5
00095
00096 movq %%mm0, %%mm1
00097 pfsub %%mm2, %%mm0
00098 pfadd %%mm2, %%mm1
00099 pswapd %%mm5, %%mm5
00100 movq %%mm0, 16(%0)
00101 movq %%mm1, (%0)
00102
00103 movq (%3,%%edx,8), %%mm0
00104
00105 pxor %%mm7, %%mm5
00106 movq %%mm4, %%mm6
00107 mov 24(%4), %%edx
00108 pfsub %%mm5, %%mm4
00109 pfadd %%mm5, %%mm6
00110
00111 movq (%3,%%edx,8), %%mm1
00112
00113 movq %%mm4, 8(%0)
00114
00115
00116
00117 movq %%mm6, 24(%0)
00118 mov 20(%4), %%edx
00119 movq (%3,%%edx,8), %%mm2
00120 mov 28(%4), %%edx
00121 movq (%3,%%edx,8), %%mm3
00122
00123 movq %%mm0, %%mm4
00124 pfadd %%mm1, %%mm0
00125
00126 movq %%mm2, %%mm5
00127 pfadd %%mm3, %%mm2
00128
00129 pfsub %%mm1, %%mm4
00130 pfsub %%mm3, %%mm5
00131
00132 movq %%mm0, %%mm1
00133 pfsub %%mm2, %%mm0
00134 pfadd %%mm2, %%mm1
00135 pswapd %%mm5, %%mm5
00136 movq %%mm0, 48(%0)
00137 movq %%mm1, 32(%0)
00138
00139 pxor %%mm7, %%mm5
00140 movq %%mm4, %%mm6
00141 pfsub %%mm5, %%mm4
00142 pfadd %%mm5, %%mm6
00143
00144 movq %%mm6, 56(%0)
00145 movq %%mm4, 40(%0)
00146
00147 add $64, %0
00148 add $32, %4
00149
00150
00151
00152
00153
00154
00155
00156 dec %1
00157 jne .loop%=
00158 pop %4
00159 pop %3
00160 pop %1
00161 pop %0
00162 "
00163 : : "r" (_x), "q" (rep>>1), "m" (mask), "r" (in), "r" (bits)
00164 : "edx", "memory", "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)");
00165
00166 for (int M=4;M<=_M;M+=2)
00167 {
00168 complex<float> *x=_x;
00169 rep >>= 2;
00170 int repeat = rep;
00171 int mul=repeat;
00172 int N = 1 << M;
00173 int N2 = N >> 1;
00174 int N4 = N >> 2;
00175 w-=(N+N2);
00176
00177
00178 while (repeat--)
00179 {
00180 {
00181 __asm__ __volatile__ (
00182 "
00183 push %0
00184 push %1
00185 push %6
00186
00187 movq %5, %%mm7
00188
00189 movq (%0), %%mm0
00190 movq (%3), %%mm1
00191 movq (%0,%2,8), %%mm2
00192 movq (%3,%2,8), %%mm3
00193
00194 movq %%mm0, %%mm4 ;//x0
00195 movq %%mm1, %%mm5 ;//x1
00196 pfadd %%mm2, %%mm0 ;//es
00197 pfadd %%mm3, %%mm1 ;//os
00198 pfsub %%mm2, %%mm4 ;//ed
00199 pfsub %%mm3, %%mm5 ;//od
00200 pswapd %%mm5, %%mm5 ;//od'
00201 pxor %%mm7, %%mm5 ;//od'
00202
00203 movq %%mm0, %%mm2 ;//es
00204 movq %%mm4, %%mm3 ;//ed
00205
00206 pfadd %%mm1, %%mm0 ;//x0
00207 pfadd %%mm5, %%mm4 ;//x3
00208 pfsub %%mm1, %%mm2 ;//x2
00209 pfsub %%mm5, %%mm3 ;//x1
00210 movq %%mm0, (%0)
00211 movq %%mm4, (%3,%2,8)
00212 movq %%mm2, (%0,%2,8)
00213 movq %%mm3, (%3)
00214
00215 .align 16
00216 loop%=:
00217 add $8, %3
00218 movq (%3), %%mm1
00219 add $8, %1
00220 movq (%1), %%mm4
00221 pswapd %%mm4, %%mm0
00222 add $8, %4
00223 add $8, %0
00224
00225 movq (%4), %%mm5
00226 movq (%0,%2,8), %%mm2
00227 movq (%3,%2,8), %%mm3
00228
00229
00230 pfmul %%mm1, %%mm4
00231 pfmul %%mm0, %%mm1
00232 movq (%4,%2,4), %%mm6
00233 pswapd %%mm5, %%mm7
00234 pswapd %%mm6, %%mm0
00235 pfmul %%mm2, %%mm5
00236 pfmul %%mm7, %%mm2
00237 pfmul %%mm3, %%mm6
00238 pfmul %%mm0, %%mm3
00239 pfpnacc %%mm1, %%mm4
00240 pfpnacc %%mm2, %%mm5
00241
00242 pfpnacc %%mm3, %%mm6
00243
00244 movq (%0), %%mm0
00245 movq %5, %%mm7
00246
00247 //1-4 2-5 3-6
00248 movq %%mm0, %%mm1 ;//x0
00249 movq %%mm4, %%mm2 ;//x1
00250 pfadd %%mm5, %%mm0 ;//es
00251 pfadd %%mm6, %%mm4 ;//os
00252 pfsub %%mm5, %%mm1 ;//ed
00253 pfsub %%mm6, %%mm2 ;//od
00254 pswapd %%mm2, %%mm2 ;//od'
00255 pxor %%mm7, %%mm2 ;//od'
00256
00257
00258 pfadd %%mm4, %%mm0 ;//x0
00259 pfsub %%mm4, %%mm5 ;//x2
00260 pfadd %%mm2, %%mm1 ;//x3
00261 pfsub %%mm2, %%mm6 ;//x1
00262 movq %%mm0, (%0)
00263 movq %%mm5, (%0,%2,8)
00264 movq %%mm1, (%3,%2,8)
00265 movq %%mm6, (%3)
00266
00267 dec %6
00268 jne loop%=
00269 pop %6
00270 pop %1
00271 pop %0
00272 "
00273 : : "r" (x), "r" (w), "q" (N2), "q" (x+N4), "q" (w+N2), "m" (mask), "q" (N4-1)
00274 : "memory", "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)");
00275 }
00276 x+=N;
00277
00278 }
00279
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 __asm__ __volatile__ ("femms" : : : "memory", "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)");
00342 }
00343
00344
00345 #endif