~ubuntu-branches/ubuntu/vivid/atlas/vivid

« back to all changes in this revision

Viewing changes to tune/blas/level1/AXPY/caxpy_sse3.c

  • Committer: Bazaar Package Importer
  • Author(s): Sylvestre Ledru
  • Date: 2009-09-17 23:31:54 UTC
  • mto: (2.2.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20090917233154-9esw88ub02twbuab
Tags: upstream-3.8.3
ImportĀ upstreamĀ versionĀ 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "atlas_asm.h"
 
2
 
 
3
#ifndef ATL_SSE3
 
4
   #error "This kernel requires SSE3"
 
5
#endif
 
6
#ifdef ATL_GAS_x8632
 
7
   #define movq movl
 
8
   #define addq addl
 
9
   #define subq subl
 
10
   #define X    %eax
 
11
   #define Y    %edx
 
12
   #define N    %ecx
 
13
   #define Nr   %ebp
 
14
#elif defined(ATL_GAS_x8664)
 
15
   #define N    %rdi
 
16
   #define X    %rdx
 
17
   #define Y    %rcx
 
18
   #define Nr   %rax
 
19
#else
 
20
   #error "This kernel requires x86 assembly!"
 
21
#endif
 
22
 
 
23
#define alp1    %xmm0
 
24
#define alp2    %xmm1
 
25
#define rY0     %xmm2
 
26
#define rX0     %xmm3
 
27
#define rX1     %xmm4
 
28
#define salp    %xmm5
 
29
#ifndef PFDIST
 
30
   #ifdef ATL_ARCH_P4E
 
31
      #define PFDIST 256   /* optimized for 32-bit P4E */
 
32
   #else
 
33
      #define PFDIST 512  /* opt for Athlon 64 X2 */
 
34
   #endif
 
35
#endif
 
36
 
 
37
# byte offset       %rdi   4          %rsi     8     %rdx    12      %rcx    16
 
38
# void ATL_UAXPY(const int N, const SCALAR alpha, const TYPE *X, const int incX,
 
39
#                TYPE *Y, const int incY)
 
40
#                %r8
 
41
        .text
 
42
.global ATL_asmdecor(ATL_UAXPY)
 
43
ATL_asmdecor(ATL_UAXPY):
 
44
#ifdef ATL_GAS_x8632
 
45
   #define OFF 8
 
46
        subl    $OFF, %esp
 
47
#
 
48
#       Put hi{1.0,-1.0}lo in rX0
 
49
#
 
50
        fld1
 
51
        fldz
 
52
        fsub    %st(1), %st
 
53
        fstps   0(%esp)
 
54
        fstps   4(%esp)
 
55
        movlps  (%esp), rX0        # rX0 = {XXX, XXX, 1.0, -1.0}
 
56
#
 
57
#       Store regs to stack and load parameters
 
58
#
 
59
        movl    %ebp, (%esp)
 
60
        movl    %ebx, 4(%esp)
 
61
 
 
62
        movl    OFF+4(%esp), N
 
63
        movl    OFF+8(%esp), Nr   # address of alpha
 
64
        movlps  (Nr),  alp1
 
65
        movl    OFF+12(%esp), X
 
66
        movl    OFF+20(%esp), Y
 
67
#else
 
68
        movq    %r8, Y
 
69
        movlps  (%rsi), alp1     # Load alpha
 
70
#
 
71
#       Put hi{1.0,-1.0}lo in rX0
 
72
#
 
73
        fld1
 
74
        fldz
 
75
        fsub    %st(1), %st
 
76
        fstps   -8(%rsp)
 
77
        fstps   -4(%rsp)
 
78
        movlps  -8(%rsp), rX0        # rX0 = {XXX, XXX, 1.0, -1.0}
 
79
#endif
 
80
        movlhps alp1, alp1             # alp1 = {ialpha, ralpha, ialpha, ralpha}
 
81
        prefetchw (Y)
 
82
        prefetchnta (X)
 
83
        movlhps rX0, rX0               # rX0  = {1.0   , -1.0  , 1.0   , -1.0  }
 
84
        pshufd  $0x11,alp1,alp2        # alp2 = {ralpha, ialpha, ralpha, ialpha}
 
85
        movaps  alp2, salp             # salp = {ralpha, ialpha, ralpha, ialpha}
 
86
        mulps   rX0, alp2              # alp2 = {ralpha, -ialph, ralpha, -ialph}
 
87
        mulss   rX0, salp              # salp = {ralpha, ialpha, ralpha, -ialph}
 
88
        pshufd  $0xE1,salp,salp        # salp = {ralpha, ialpha, -ialph, ralpha}
 
89
#
 
90
#       If X is only 4-byte aligned, it's alignment cannot be fixed,
 
91
#       so go to crap code
 
92
#
 
93
        test    $0x7, X
 
94
        jnz     NOXALIGN
 
95
#
 
96
#       Force X to 16-byte boundary so we can use MOVSxDUP
 
97
#
 
98
        test    $0xF, X
 
99
        jz      XALIGNED
 
100
#
 
101
#       One peeled iteration to force X to 16-byte alignment
 
102
#
 
103
                                # salp = { ra,  ia, -ia,  ra}
 
104
        movlps  (X), rX0        # rX0  = { XX,  XX,  ix,  rx}
 
105
        xorps   rY0, rY0        # get rid of junk in top 64 bits
 
106
        movlhps rX0, rX0        # rX0  = { ix,  rx,  ix,  rx}
 
107
        movlps  (Y), rY0        # rY0  = {  0,   0,  iy,  ry}
 
108
        mulps   salp, rX0       # rX0  = {ra*ix, ia*rx, -ia*ix, ra*rx}
 
109
        haddps  rX0, rX0        # rX0  = {XX,XX, ra*ix+ia*rx, ra*rx-iaix}
 
110
        addps   rX0, rY0        # rY0  = {XX,XX, iyN, ryN}
 
111
        movlps  rY0, (Y)
 
112
        sub     $1, N
 
113
        add     $8, X
 
114
        add     $8, Y
 
115
XALIGNED:
 
116
        test    $0xF, Y
 
117
        jnz     YUNALIGNED
 
118
 
 
119
        mov     N, Nr
 
120
        shr     $1, N
 
121
        shl     $1, N
 
122
        lea     (X, N, 8), X
 
123
        lea     (Y, N, 8), Y
 
124
        neg     N
 
125
        add     N, Nr
 
126
        cmp     $0, N
 
127
        je      CLEANUP
 
128
        ALIGN16
 
129
NLOOP:
 
130
                                        # alp1 = {ia,   ra,  ia,  ra}
 
131
                                        # alp2 = {ra,  -ia,  ra, -ia}
 
132
        movsldup (X,N,8), rX0           # rX0  = {rx1, rx1, rx0, rx0}
 
133
        movshdup (X,N,8), rX1           # rX1  = {ix1, ix1, ix0, ix0}
 
134
        movaps  (Y,N,8), rY0            # rY0  = {iy1, ry1, iy0, ry0}
 
135
        mulps   alp1, rX0               # rX0  = {ia*rx1,ra*rx1,ia*rx0,ra*rx0}
 
136
        prefetchw      PFDIST(Y,N,8)
 
137
        addps   rX0, rY0                # rY0  gets 1st part of results
 
138
        mulps   alp2, rX1               # rX1  = {ra*ix1,-ia*ix1,ra*ix0,-ia*ix0}
 
139
        prefetcht0     PFDIST(X,N,8)
 
140
        addps   rX1, rY0                # rY0 gets last part of results
 
141
        movapd  rY0, (Y,N,8)
 
142
        addq    $2, N
 
143
        jnz     NLOOP
 
144
#
 
145
#       Do one more scalar iteration if there's a remainder
 
146
#
 
147
CLEANUP:
 
148
        cmp     $0, Nr
 
149
        je      DONE
 
150
                                # salp = { ra,  ia, -ia,  ra}
 
151
        movlps  (X), rX0        # rX0  = { XX,  XX,  ix,  rx}
 
152
        xorps   rY0, rY0        # get rid of junk in top 64 bits
 
153
        movlhps rX0, rX0        # rX0  = { ix,  rx,  ix,  rx}
 
154
        movlps  (Y), rY0        # rY0  = {  0,   0,  iy,  ry}
 
155
        mulps   salp, rX0       # rX0  = {ra*ix, ia*rx, -ia*ix, ra*rx}
 
156
        haddps  rX0, rX0        # rX0  = {XX,XX, ra*ix+ia*rx, ra*rx-iaix}
 
157
        addps   rX0, rY0        # rY0  = {XX,XX, iyN, ryN}
 
158
        movlps  rY0, (Y)
 
159
#
 
160
#       Epilogue
 
161
#
 
162
DONE:
 
163
#ifdef ATL_GAS_x8632
 
164
        movl    (%esp), %ebp
 
165
        movl    4(%esp), %ebx
 
166
        addl    $OFF, %esp
 
167
#endif
 
168
        ret
 
169
#
 
170
# This code assumes aligned X, but unaligned Y
 
171
#
 
172
YUNALIGNED:
 
173
        mov     N, Nr
 
174
        shr     $1, N
 
175
        shl     $1, N
 
176
        lea     (X,N,8), X
 
177
        lea     (Y,N,8), Y
 
178
        neg     N
 
179
        add     N, Nr
 
180
        cmp     $0, N
 
181
        je      CLEANUP
 
182
YUNLOOP:
 
183
                                        # alp1 = {ia,   ra,  ia,  ra}
 
184
                                        # alp2 = {ra,  -ia,  ra, -ia}
 
185
        movsldup (X,N,8), rX0           # rX0  = {rx1, rx1, rx0, rx0}
 
186
        movshdup (X,N,8), rX1           # rX1  = {ix1, ix1, ix0, ix0}
 
187
        movups  (Y,N,8), rY0            # rY0  = {iy1, ry1, iy0, ry0}
 
188
        mulps   alp1, rX0               # rX0  = {ia*rx1,ra*rx1,ia*rx0,ra*rx0}
 
189
        prefetchw      PFDIST(Y,N,8)
 
190
        addps   rX0, rY0                # rY0  gets 1st part of results
 
191
        mulps   alp2, rX1               # rX1  = {ra*ix1,-ia*ix1,ra*ix0,-ia*ix0}
 
192
        prefetcht0     PFDIST(X,N,8)
 
193
        addps   rX1, rY0                # rY0 gets last part of results
 
194
        movupd  rY0, (Y,N,8)
 
195
        addq    $2, N
 
196
        jnz     YUNLOOP
 
197
        jmp     CLEANUP
 
198
#
 
199
# X is not aligned even on 8-byte boundary, so cannot align it at all
 
200
# This shouldn't happen much, so just implement the unaligned Y case,
 
201
# so this case implements neither vector aligned
 
202
#
 
203
NOXALIGN:
 
204
        mov     N, Nr
 
205
        shr     $1, N
 
206
        shl     $1, N
 
207
        lea     (X, N, 8), X
 
208
        lea     (Y, N, 8), Y
 
209
        neg     N
 
210
        add     N, Nr
 
211
        cmp     $0, N           # alp1 = { ia,  ra,  ia,  ra}
 
212
        je      CLEANUP         # salp = { ra,  ia, -ia,  ra}
 
213
 
 
214
        movsldup alp1, alp1     # alp1 = { ra,  ra,  ra,  ra}
 
215
        pshufd  $0x99,salp,alp2 # alp2 = { ia, -ia,  ia, -ia}
 
216
NOALOOP:
 
217
        movups  (X,N,8), rX0    # rX0  = {ix1, rx1, ix0, rx0}
 
218
        pshufd  $0xB1,rX0,rX1   # rX1  = {rx1, ix1, rx0, ix0}
 
219
        movups  (Y,N,8), rY0    # rY0  = {iy1, ry1, iy0, ry0}
 
220
        mulps   alp1, rX0       # rX0  = {ix1*ra, rx1*ra,ix0*ra, rx1*ra}
 
221
        prefetchw      PFDIST(Y,N,8)
 
222
        addps   rX0, rY0
 
223
        mulps   alp2, rX1       # rX1  = {rx1*ia,-ix1*ia,rx0*ia,-ix0*ia}
 
224
        prefetcht0     PFDIST(X,N,8)
 
225
        addps   rX1, rY0
 
226
        movups  rY0, (Y,N,8)
 
227
        add     $2, N
 
228
        jnz     NOALOOP
 
229
        jmp     CLEANUP