Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / lib / filter / complex_dotprod_3dnow.S
1 #
2 # Copyright 2002 Free Software Foundation, Inc.
3
4 # This file is part of GNU Radio
5
6 # GNU Radio is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
9 # any later version.
10
11 # GNU Radio is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with GNU Radio; see the file COPYING.  If not, write to
18 # the Free Software Foundation, Inc., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
20
21
22
23 # input and taps are guarenteed to be 16 byte aligned.
24 # n_2_complex_blocks is != 0
25 #       
26 #
27 #  complex_dotprod_generic (const short *input,
28 #                         const float *taps, unsigned n_2_complex_blocks, float *result)
29 #  {
30 #    float sum0 = 0;
31 #    float sum1 = 0;
32 #    float sum2 = 0;
33 #    float sum3 = 0;
34 #  
35 #    do {
36 #  
37 #      sum0 += input[0] * taps[0];
38 #      sum1 += input[0] * taps[1];
39 #      sum2 += input[1] * taps[2];
40 #      sum3 += input[1] * taps[3];
41 #  
42 #      input += 2;
43 #      taps += 4;
44 #  
45 #    } while (--n_2_complex_blocks != 0);
46 #  
47 #  
48 #    result[0] = sum0 + sum2;
49 #    result[1] = sum1 + sum3;
50 #  }
51 #               
52
53 #include "assembly.h"
54
55         .file   "complex_dotprod_3dnow.S"
56         .version        "01.01"
57 .text
58         .p2align 4
59 .globl GLOB_SYMB(complex_dotprod_3dnow)
60         DEF_FUNC_HEAD(complex_dotprod_3dnow)
61 GLOB_SYMB(complex_dotprod_3dnow):
62         pushl   %ebp
63         movl    %esp, %ebp
64         movl    8(%ebp), %eax           # input
65         movl    12(%ebp), %edx          # taps
66         movl    16(%ebp), %ecx
67
68         # zero accumulators
69         
70         pxor    %mm4, %mm4              # mm4 = 0 0
71         pxor    %mm5, %mm5              # mm5 = 0 0 
72         pxor    %mm6, %mm6              # mm6 = 0 0 
73         pxor    %mm7, %mm7              # mm7 = 0 0
74
75
76         shrl    $1, %ecx                # ecx = n_2_complex_blocks / 2
77
78         # pshufw & pi2fw
79         pxor    %mm0, %mm0
80         punpcklwd       0(%eax), %mm0
81         psrad   $16, %mm0
82         punpckldq       %mm0, %mm0
83         pi2fd   %mm0, %mm0
84
85         pxor    %mm1, %mm1
86         punpcklwd       0(%eax), %mm1
87         psrad   $16, %mm1
88         punpckhdq       %mm1, %mm1
89         pi2fd   %mm1, %mm1
90
91         pxor    %mm2, %mm2
92         pxor    %mm3, %mm3
93
94
95         jmp     .L1_test
96
97         #
98         # 4 taps / loop
99         # something like ?? cycles / loop
100         #
101         
102         .p2align 4
103 .Loop1: 
104         pfmul   0(%edx), %mm0
105         pfadd   %mm2, %mm6
106
107         pxor    %mm2, %mm2
108         punpcklwd       4(%eax), %mm2
109         psrad   $16, %mm2
110         punpckldq       %mm2, %mm2
111
112         pfmul   8(%edx), %mm1
113         pfadd   %mm3, %mm7
114         pi2fd   %mm2, %mm2
115
116         pxor    %mm3, %mm3
117         punpcklwd       4(%eax), %mm3
118         psrad   $16, %mm3
119         punpckhdq       %mm3, %mm3
120
121         pfmul   16(%edx), %mm2
122         pfadd   %mm0, %mm4
123         pi2fd   %mm3, %mm3
124
125         pxor    %mm0, %mm0
126         punpcklwd       8(%eax), %mm0
127         psrad   $16, %mm0
128         punpckldq       %mm0, %mm0
129
130         pfmul   24(%edx), %mm3
131         pfadd   %mm1, %mm5
132
133         pxor    %mm1, %mm1
134         punpcklwd       8(%eax), %mm1
135         psrad   $16, %mm1
136         punpckhdq       %mm1, %mm1
137
138         pi2fd   %mm0, %mm0
139         pi2fd   %mm1, %mm1
140
141 #TODO: add prefetch
142
143         addl    $32, %edx
144         addl    $8, %eax
145
146 .L1_test:
147         decl    %ecx
148         jge     .Loop1
149
150         # We've handled the bulk of multiplies up to here.
151         # Now accumulate the final two additions and see if original
152         # n_2_complex_blocks was odd.  If so, we've got 2 more
153         # taps to do.
154         
155         movl    16(%ebp), %ecx
156         pfadd   %mm2, %mm6
157         andl    $1, %ecx
158         pfadd   %mm3, %mm7
159         je      .Leven
160         
161         # The count was odd, do 2 more taps.
162         # Note that we've already got mm0 and mm1 preloaded
163         # from the main loop.
164         
165         pfmul   0(%edx), %mm0
166         pfadd   %mm0, %mm4
167         pfmul   8(%edx), %mm1
168         pfadd   %mm1, %mm5
169
170 .Leven:
171         # at this point mm4, mm5, mm6 and mm7 contain partial sums
172         
173         pfadd   %mm7, %mm6
174         pfadd   %mm5, %mm4
175
176         movl    20(%ebp), %eax          # result
177
178         pfadd   %mm6, %mm4
179
180         movq    %mm4, (%eax)
181         femms
182
183         popl    %ebp
184         ret
185
186 FUNC_TAIL(complex_dotprod_3dnow)
187         .ident  "Hand coded x86 3DNow! assembly"
188
189
190 #if defined(__linux__) && defined(__ELF__)
191 .section .note.GNU-stack,"",%progbits
192 #endif