Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / filter / complex_dotprod_3dnowext.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 2, 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_3dnowext.S"
56         .version        "01.01"
57 .text
58         .p2align 4
59 .globl GLOB_SYMB(complex_dotprod_3dnowext)
60         DEF_FUNC_HEAD(complex_dotprod_3dnowext)
61 GLOB_SYMB(complex_dotprod_3dnowext):
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         movd    0(%eax), %mm0
79         pshufw  $0x55, %mm0, %mm1               # b01010101
80         pshufw  $0, %mm0, %mm0
81
82         pxor    %mm2, %mm2
83         pxor    %mm3, %mm3
84
85         pi2fw   %mm1, %mm1
86         pi2fw   %mm0, %mm0
87
88         jmp     .L1_test
89
90         #
91         # 4 taps / loop
92         # something like ?? cycles / loop
93         #
94         
95         .p2align 4
96 .loop1: 
97         pfmul   0(%edx), %mm0
98         pfadd   %mm2, %mm6
99
100         pshufw  $0, 4(%eax), %mm2
101
102         pfmul   8(%edx), %mm1
103         pfadd   %mm3, %mm7
104         pi2fw   %mm2, %mm2
105
106         pshufw  $0x55, 4(%eax), %mm3            # b01010101
107
108         pfmul   16(%edx), %mm2
109         pi2fw   %mm3, %mm3
110         pfadd   %mm0, %mm4
111
112         pshufw  $0, 8(%eax), %mm0
113
114         pfmul   24(%edx), %mm3
115         pfadd   %mm1, %mm5
116
117         pshufw  $0x55, 8(%eax), %mm1    # b01010101
118         pi2fw   %mm0, %mm0
119
120 #TODO: add prefetch
121
122         addl    $32, %edx
123         addl    $8, %eax
124         pi2fw   %mm1, %mm1
125
126 .L1_test:
127         decl    %ecx
128         jge     .loop1
129
130         # We've handled the bulk of multiplies up to here.
131         # Now accumulate the final two additions and see if original
132         # n_2_complex_blocks was odd.  If so, we've got 2 more
133         # taps to do.
134         
135         movl    16(%ebp), %ecx
136         pfadd   %mm2, %mm6
137         andl    $1, %ecx
138         pfadd   %mm3, %mm7
139         je      .Leven
140         
141         # The count was odd, do 2 more taps.
142         # Note that we've already got mm0 and mm1 preloaded
143         # from the main loop.
144         
145         pfmul   0(%edx), %mm0
146         pfadd   %mm0, %mm4
147         pfmul   8(%edx), %mm1
148         pfadd   %mm1, %mm5
149
150 .Leven:
151         # at this point mm4, mm5, mm6 and mm7 contain partial sums
152         
153         pfadd   %mm7, %mm6
154         pfadd   %mm5, %mm4
155
156         movl    20(%ebp), %eax          # result
157         pfadd   %mm6, %mm4
158         movq    %mm4, (%eax)
159
160         femms
161
162         popl    %ebp
163         ret
164
165 FUNC_TAIL(complex_dotprod_3dnowext)
166         .ident  "Hand coded x86 3DNow!Ext assembly"
167