mmx/prefetch implementation of plane_copy
[x262.git] / common / amd64 / mc-a2.asm
1 ;*****************************************************************************
2 ;* mc-a2.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2005 x264 project
5 ;*
6 ;* This program 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 of the License, or
9 ;* (at your option) any later version.
10 ;*
11 ;* This program 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 this program; if not, write to the Free Software
18 ;* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
19 ;*****************************************************************************
20
21 BITS 64
22
23 ;=============================================================================
24 ; Macros and other preprocessor constants
25 ;=============================================================================
26
27 %include "amd64inc.asm"
28
29 ;=============================================================================
30 ; Read only data
31 ;=============================================================================
32
33 SECTION .rodata
34
35 ALIGN 16
36 mmx_dw_one:
37     times 4 dw 16
38 mmx_dd_one:
39     times 2 dd 512
40 mmx_dw_20:
41     times 4 dw 20
42 mmx_dw_5:
43     times 4 dw -5
44
45 %assign tbuffer 0
46
47 ;=============================================================================
48 ; Macros
49 ;=============================================================================
50
51 %macro LOAD_4 9
52     movd %1, %5
53     movd %2, %6
54     movd %3, %7
55     movd %4, %8
56     punpcklbw %1, %9
57     punpcklbw %2, %9
58     punpcklbw %3, %9
59     punpcklbw %4, %9
60 %endmacro
61
62 %macro FILT_2 2
63     psubw %1, %2
64     psllw %2, 2
65     psubw %1, %2
66 %endmacro
67
68 %macro FILT_4 3
69     paddw %2, %3
70     psllw %2, 2
71     paddw %1, %2
72     psllw %2, 2
73     paddw %1, %2
74 %endmacro
75
76 %macro FILT_6 4
77     psubw %1, %2
78     psllw %2, 2
79     psubw %1, %2
80     paddw %1, %3
81     paddw %1, %4
82     psraw %1, 5
83 %endmacro
84
85 %macro FILT_ALL 1
86     LOAD_4      mm1, mm2, mm3, mm4, [%1], [%1 + rcx], [%1 + 2 * rcx], [%1 + rbx], mm0
87     FILT_2      mm1, mm2
88     movd        mm5, [%1 + 4 * rcx]
89     movd        mm6, [%1 + rdx]
90     FILT_4      mm1, mm3, mm4
91     punpcklbw   mm5, mm0
92     punpcklbw   mm6, mm0
93     psubw       mm1, mm5
94     psllw       mm5, 2
95     psubw       mm1, mm5
96     paddw       mm1, mm6
97 %endmacro
98
99
100
101
102 ;=============================================================================
103 ; Code
104 ;=============================================================================
105
106 SECTION .text
107
108 cglobal x264_horizontal_filter_mmxext
109 cglobal x264_center_filter_mmxext
110 cglobal x264_plane_copy_mmxext
111
112 ;-----------------------------------------------------------------------------
113 ;
114 ; void x264_center_filter_mmxext( uint8_t *dst1, int i_dst1_stride,
115 ;                                 uint8_t *dst2, int i_dst2_stride,
116 ;                                  uint8_t *src, int i_src_stride,
117 ;                                  int i_width, int i_height );
118 ;
119 ;-----------------------------------------------------------------------------
120
121 ALIGN 16
122 x264_center_filter_mmxext :
123
124     push        r15
125     pushreg     r15
126 %ifdef WIN64
127     push        rdi
128     pushreg     rdi
129     push        rsi
130     pushreg     rsi
131 %endif
132
133     push        rbp
134     pushreg     rbp
135     push        rbx
136     pushreg     rbx
137     push        r12
138     pushreg     r12
139     push        r13
140     pushreg     r13
141     push        r14
142     pushreg     r14
143     lea         rbp,    [rsp]
144     setframe    rbp, 0
145     endprolog
146
147 %ifdef WIN64
148     movsxd      r13,    dword [rsp+64+48]   ; src_stride
149     mov         r12,    [rsp+64+40]         ; src
150 %else
151     movsxd      r13,    r9d                 ; src_stride
152     mov         r12,    r8                  ; src
153 %endif
154     sub         r12,    r13
155     sub         r12,    r13                 ; tsrc = src - 2 * src_stride
156
157     ; use 24 instead of 18 (used in i386/mc-a2.asm) to keep rsp aligned
158     lea         rax,    [r13 + r13 + 24 + tbuffer]
159     sub         rsp,    rax
160
161     mov         r10,    parm3q                 ; dst2
162     movsxd      r11,    parm4d                 ; dst2_stride
163     mov         r8,     parm1q                 ; dst1
164     movsxd      r9,     parm2d                 ; dst1_stride
165 %ifdef WIN64
166     movsxd      r14,    dword [rbp + 64 + 56]  ; width
167     movsxd      r15,    dword [rbp + 64 + 64]  ; height
168 %else
169     movsxd      r14,    dword [rbp + 56]    ; width
170     movsxd      r15,    dword [rbp + 64]    ; height
171 %endif
172
173     mov         rcx,    r13                 ; src_stride
174     lea         rbx,    [r13 + r13 * 2]     ; 3 * src_stride
175     lea         rdx,    [r13 + r13 * 4]     ; 5 * src_stride
176
177     pxor        mm0,    mm0                 ; 0 ---> mm0
178     movq        mm7,    [mmx_dd_one GLOBAL] ; for rounding
179
180 .loopcy:
181
182     xor         rax,    rax
183     mov         rsi,    r12             ; tsrc
184
185     FILT_ALL    rsi
186
187     pshufw      mm2,    mm1, 0
188     movq        [rsp + tbuffer],  mm2
189     movq        [rsp + tbuffer + 8],  mm1
190     paddw       mm1,    [mmx_dw_one GLOBAL]
191     psraw       mm1,    5
192
193     packuswb    mm1,    mm1
194     movd        [r8],   mm1             ; dst1[0] = mm1
195
196     add         rax,    8
197     add         rsi,    4
198     lea         rdi,    [r8 - 4]        ; rdi = dst1 - 4
199
200 .loopcx1:
201
202     FILT_ALL    rsi
203
204     movq        [rsp + tbuffer + 2 * rax],  mm1
205     paddw       mm1,    [mmx_dw_one GLOBAL]
206     psraw       mm1,    5
207     packuswb    mm1,    mm1
208     movd        [rdi + rax],  mm1   ; dst1[rax - 4] = mm1
209
210     add         rsi,    4
211     add         rax,    4
212     cmp         rax,    r14         ; cmp rax, width
213     jnz         .loopcx1
214
215     FILT_ALL    rsi
216
217     pshufw      mm2,    mm1,  7
218     movq        [rsp + tbuffer + 2 * rax],  mm1
219     movq        [rsp + tbuffer + 2 * rax + 8],  mm2
220     paddw       mm1,    [mmx_dw_one GLOBAL]
221     psraw       mm1,    5
222     packuswb    mm1,    mm1
223     movd        [rdi + rax],  mm1   ; dst1[rax - 4] = mm1
224
225     add         r12,    r13         ; tsrc = tsrc + src_stride
226
227     add         r8,     r9          ; dst1 = dst1 + dst1_stride
228
229     xor         rax,    rax
230
231 .loopcx2:
232
233     movq        mm2,    [rsp + 2 * rax + 2  + 4 + tbuffer]
234     movq        mm3,    [rsp + 2 * rax + 4  + 4 + tbuffer]
235     movq        mm4,    [rsp + 2 * rax + 6  + 4 + tbuffer]
236     movq        mm5,    [rsp + 2 * rax + 8  + 4 + tbuffer]
237     movq        mm1,    [rsp + 2 * rax      + 4 + tbuffer]
238     movq        mm6,    [rsp + 2 * rax + 10 + 4 + tbuffer]
239     paddw       mm2,    mm5
240     paddw       mm3,    mm4
241     paddw       mm1,    mm6
242
243     movq        mm5,    [mmx_dw_20 GLOBAL]
244     movq        mm4,    [mmx_dw_5 GLOBAL]
245     movq        mm6,    mm1
246     pxor        mm7,    mm7
247
248     punpckhwd   mm5,    mm2
249     punpcklwd   mm4,    mm3
250     punpcklwd   mm2,    [mmx_dw_20 GLOBAL]
251     punpckhwd   mm3,    [mmx_dw_5 GLOBAL]
252
253     pcmpgtw     mm7,    mm1
254
255     pmaddwd     mm2,    mm4
256     pmaddwd     mm3,    mm5
257
258     punpcklwd   mm1,    mm7
259     punpckhwd   mm6,    mm7
260
261     paddd       mm2,    mm1
262     paddd       mm3,    mm6
263
264     paddd       mm2,    [mmx_dd_one GLOBAL]
265     paddd       mm3,    [mmx_dd_one GLOBAL]
266
267     psrad       mm2,    10
268     psrad       mm3,    10
269
270     packssdw    mm2,    mm3
271     packuswb    mm2,    mm0
272
273     movd        [r10 + rax], mm2    ; dst2[rax] = mm2
274
275     add         rax,    4
276     cmp         rax,    r14         ; cmp rax, width
277     jnz         .loopcx2
278
279     add         r10,    r11         ; dst2 += dst2_stride
280     dec         r15                 ; height
281     jnz         .loopcy
282
283     lea         rsp,    [rbp]
284
285     pop         r14
286     pop         r13
287     pop         r12
288     pop         rbx
289     pop         rbp
290 %ifdef WIN64
291     pop         rsi
292     pop         rdi
293 %endif
294     pop         r15
295
296     ret
297
298 ;-----------------------------------------------------------------------------
299 ;
300 ; void x264_horizontal_filter_mmxext( uint8_t *dst, int i_dst_stride,
301 ;                                     uint8_t *src, int i_src_stride,
302 ;                                     int i_width, int i_height );
303 ;
304 ;-----------------------------------------------------------------------------
305
306 ALIGN 16
307 x264_horizontal_filter_mmxext :
308     movsxd      r10,    parm2d               ; dst_stride
309     movsxd      r11,    parm4d               ; src_stride
310 %ifdef WIN64
311     mov         rdx,    r8                   ; src
312     mov         r9,     rcx                  ; dst
313     movsxd      rcx,    parm6d               ; height
314 %else
315     movsxd      rcx,    parm6d               ; height
316     mov         r9,     rdi                  ; dst
317 %endif
318     
319     movsxd      r8,     parm5d               ; width
320
321     pxor        mm0,    mm0
322     movq        mm7,    [mmx_dw_one GLOBAL]
323
324     sub         rdx,    2
325
326 loophy:
327
328     xor         rax,    rax
329
330 loophx:
331
332     prefetchnta [rdx + rax + 48]       
333
334     LOAD_4      mm1,    mm2, mm3, mm4, [rdx + rax], [rdx + rax + 1], [rdx + rax + 2], [rdx + rax + 3], mm0
335     FILT_2      mm1,    mm2
336     movd        mm5,    [rdx + rax + 4]
337     movd        mm6,    [rdx + rax + 5]
338     FILT_4      mm1,    mm3, mm4
339     movd        mm2,    [rdx + rax + 4]
340     movd        mm3,    [rdx + rax + 6]
341     punpcklbw   mm5,    mm0
342     punpcklbw   mm6,    mm0
343     FILT_6      mm1,    mm5, mm6, mm7
344     movd        mm4,    [rdx + rax + 7]
345     movd        mm5,    [rdx + rax + 8]
346     punpcklbw   mm2,    mm0
347     punpcklbw   mm3,    mm0                  ; mm2(1), mm3(20), mm6(-5) ready
348     FILT_2      mm2,    mm6
349     movd        mm6,    [rdx + rax + 9]
350     punpcklbw   mm4,    mm0
351     punpcklbw   mm5,    mm0                  ; mm2(1-5), mm3(20), mm4(20), mm5(-5) ready
352     FILT_4      mm2,    mm3, mm4
353     punpcklbw   mm6,    mm0
354     FILT_6      mm2,    mm5, mm6, mm7
355
356     packuswb    mm1,    mm2
357     movq        [r9 + rax],  mm1
358
359     add         rax,    8
360     cmp         rax,    r8                   ; cmp rax, width
361     jnz         loophx
362
363     add         rdx,    r11                  ; src_pitch
364     add         r9,     r10                  ; dst_pitch
365
366     dec         rcx
367     jnz         loophy
368
369     ret
370
371
372 ;-----------------------------------------------------------------------------
373 ; void x264_plane_copy_mmxext( uint8_t *dst, int i_dst,
374 ;                              uint8_t *src, int i_src, int w, int h)
375 ;-----------------------------------------------------------------------------
376 ALIGN 16
377 x264_plane_copy_mmxext:
378     movsxd parm2q, parm2d
379     movsxd parm4q, parm4d
380     add    parm5d, 3
381     and    parm5d, ~3
382     sub    parm2q, parm5q
383     sub    parm4q, parm5q
384     ; shuffle regs because movsd needs dst=rdi, src=rsi, w=ecx
385     xchg   rsi, rdx
386     mov    rax, parm4q
387 .loopy:
388     mov    ecx, parm5d
389     sub    ecx, 64
390     jl     .endx
391 .loopx:
392     prefetchnta [rsi+256]
393     movq   mm0, [rsi   ]
394     movq   mm1, [rsi+ 8]
395     movq   mm2, [rsi+16]
396     movq   mm3, [rsi+24]
397     movq   mm4, [rsi+32]
398     movq   mm5, [rsi+40]
399     movq   mm6, [rsi+48]
400     movq   mm7, [rsi+56]
401     movntq [rdi   ], mm0
402     movntq [rdi+ 8], mm1
403     movntq [rdi+16], mm2
404     movntq [rdi+24], mm3
405     movntq [rdi+32], mm4
406     movntq [rdi+40], mm5
407     movntq [rdi+48], mm6
408     movntq [rdi+56], mm7
409     add    rsi, 64
410     add    rdi, 64
411     sub    ecx, 64
412     jge    .loopx
413 .endx:
414     prefetchnta [rsi+256]
415     add    ecx, 64
416     shr    ecx, 2
417     rep movsd
418     add    rdi, rdx
419     add    rsi, rax
420     sub    parm6d, 1
421     jge    .loopy
422     rep ret
423