Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / lib / filter / float_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_4_float_blocks is != 0
25 #       
26 #
27 #  float 
28 #  float_dotprod_generic (const float *input,
29 #                         const float *taps, unsigned n_4_float_blocks)
30 #  {
31 #    float sum0 = 0;
32 #    float sum1 = 0;
33 #    float sum2 = 0;
34 #    float sum3 = 0;
35 #  
36 #    do {
37 #  
38 #      sum0 += input[0] * taps[0];
39 #      sum1 += input[1] * taps[1];
40 #      sum2 += input[2] * taps[2];
41 #      sum3 += input[3] * taps[3];
42 #  
43 #      input += 4;
44 #      taps += 4;
45 #  
46 #    } while (--n_4_float_blocks != 0);
47 #  
48 #  
49 #    return sum0 + sum1 + sum2 + sum3;
50 #  }
51 #               
52
53 #include "assembly.h"
54
55
56         .file   "float_dotprod_3dnow.S"
57         .version        "01.01"
58 .text
59         .p2align 4
60 .globl GLOB_SYMB(float_dotprod_3dnow)
61         DEF_FUNC_HEAD(float_dotprod_3dnow)
62 GLOB_SYMB(float_dotprod_3dnow):
63         pushl   %ebp
64         movl    %esp, %ebp
65         movl    8(%ebp), %edx
66         movl    12(%ebp), %eax
67         movl    16(%ebp), %ecx
68
69         # zero accumulators
70         
71         pxor    %mm4, %mm4              # mm4 = 0 0
72         pxor    %mm5, %mm5              # mm5 = 0 0 
73         pxor    %mm6, %mm6              # mm6 = 0 0 
74         pxor    %mm7, %mm7              # mm7 = 0 0
75
76         shrl    $1, %ecx                # ecx = n_4_float_blocks / 2
77         movq    0(%eax), %mm0
78         movq    8(%eax), %mm1
79         pxor    %mm2, %mm2
80         pxor    %mm3, %mm3
81         jmp     .L1_test
82
83         #
84         # 8 taps / loop
85         # something like 6 cycles / loop
86         #
87         
88         .p2align 4
89 .Loop1: 
90         pfmul   0(%edx), %mm0
91         pfadd   %mm2, %mm6
92         movq    16(%eax), %mm2
93         
94         pfmul   8(%edx), %mm1
95         pfadd   %mm3, %mm7
96         movq    24(%eax), %mm3
97
98         pfmul   16(%edx), %mm2
99         pfadd   %mm0, %mm4
100         movq    32(%eax), %mm0
101
102         pfmul   24(%edx), %mm3
103         pfadd   %mm1, %mm5
104         movq    40(%eax), %mm1
105
106         addl    $32, %edx
107         addl    $32, %eax
108 .L1_test:
109         decl    %ecx
110         jge     .Loop1
111
112         # We've handled the bulk of multiplies up to here.
113         # Now accumulate the final two additions and see if original
114         # n_4_float_blocks was odd.  If so, we've got 4 more
115         # taps to do.
116         
117         movl    16(%ebp), %ecx
118         pfadd   %mm2, %mm6
119         andl    $1, %ecx
120         pfadd   %mm3, %mm7
121         je      .Leven
122         
123         # The count was odd, do 4 more taps.
124         # Note that we've already got mm0 and mm1 preloaded
125         # from the main loop.
126         
127         pfmul   0(%edx), %mm0
128         pfadd   %mm0, %mm4
129         pfmul   8(%edx), %mm1
130         pfadd   %mm1, %mm5
131
132 .Leven:                 
133         # at this point mm4, mm5, mm6 and mm7 contain partial sums
134         
135         pfadd   %mm7, %mm6
136         pfadd   %mm5, %mm4
137         pfadd   %mm6, %mm4
138         pfacc   %mm4, %mm4
139         
140         movd    %mm4, 16(%ebp)
141         femms
142         flds    16(%ebp)
143
144         popl    %ebp
145         ret
146
147 FUNC_TAIL(float_dotprod_3dnow)
148         .ident  "Hand coded x86 3DNow! assembly"
149
150 #if defined(__linux__) && defined(__ELF__)
151 .section .note.GNU-stack,"",%progbits
152 #endif