96f32fd42726c487aefc98de6477fa908ec5ca74
[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
111 ;-----------------------------------------------------------------------------
112 ;
113 ; void x264_center_filter_mmxext( uint8_t *dst1, int i_dst1_stride,
114 ;                                 uint8_t *dst2, int i_dst2_stride,
115 ;                                  uint8_t *src, int i_src_stride,
116 ;                                  int i_width, int i_height );
117 ;
118 ;-----------------------------------------------------------------------------
119
120 ALIGN 16
121 x264_center_filter_mmxext :
122
123     push        r15
124     pushreg     r15
125 %ifdef WIN64
126     push        rdi
127     pushreg     rdi
128     push        rsi
129     pushreg     rsi
130 %endif
131
132     push        rbp
133     pushreg     rbp
134     push        rbx
135     pushreg     rbx
136     push        r12
137     pushreg     r12
138     push        r13
139     pushreg     r13
140     push        r14
141     pushreg     r14
142     lea         rbp,    [rsp]
143     setframe    rbp, 0
144     endprolog
145
146 %ifdef WIN64
147     movsxd      r13,    dword [rsp+64+48]   ; src_stride
148     mov         r12,    [rsp+64+40]         ; src
149 %else
150     movsxd      r13,    r9d                 ; src_stride
151     mov         r12,    r8                  ; src
152 %endif
153     sub         r12,    r13
154     sub         r12,    r13                 ; tsrc = src - 2 * src_stride
155
156     ; use 24 instead of 18 (used in i386/mc-a2.asm) to keep rsp aligned
157     lea         rax,    [r13 + r13 + 24 + tbuffer]
158     sub         rsp,    rax
159
160     mov         r10,    parm3q                 ; dst2
161     movsxd      r11,    parm4d                 ; dst2_stride
162     mov         r8,     parm1q                 ; dst1
163     movsxd      r9,     parm2d                 ; dst1_stride
164 %ifdef WIN64
165     movsxd      r14,    dword [rbp + 64 + 56]  ; width
166     movsxd      r15,    dword [rbp + 64 + 64]  ; height
167 %else
168     movsxd      r14,    dword [rbp + 56]    ; width
169     movsxd      r15,    dword [rbp + 64]    ; height
170 %endif
171
172     mov         rcx,    r13                 ; src_stride
173     lea         rbx,    [r13 + r13 * 2]     ; 3 * src_stride
174     lea         rdx,    [r13 + r13 * 4]     ; 5 * src_stride
175
176     pxor        mm0,    mm0                 ; 0 ---> mm0
177     movq        mm7,    [mmx_dd_one GLOBAL] ; for rounding
178
179 .loopcy:
180
181     xor         rax,    rax
182     mov         rsi,    r12             ; tsrc
183
184     FILT_ALL    rsi
185
186     pshufw      mm2,    mm1, 0
187     movq        [rsp + tbuffer],  mm2
188     movq        [rsp + tbuffer + 8],  mm1
189     paddw       mm1,    [mmx_dw_one GLOBAL]
190     psraw       mm1,    5
191
192     packuswb    mm1,    mm1
193     movd        [r8],   mm1             ; dst1[0] = mm1
194
195     add         rax,    8
196     add         rsi,    4
197     lea         rdi,    [r8 - 4]        ; rdi = dst1 - 4
198
199 .loopcx1:
200
201     FILT_ALL    rsi
202
203     movq        [rsp + tbuffer + 2 * rax],  mm1
204     paddw       mm1,    [mmx_dw_one GLOBAL]
205     psraw       mm1,    5
206     packuswb    mm1,    mm1
207     movd        [rdi + rax],  mm1   ; dst1[rax - 4] = mm1
208
209     add         rsi,    4
210     add         rax,    4
211     cmp         rax,    r14         ; cmp rax, width
212     jnz         .loopcx1
213
214     FILT_ALL    rsi
215
216     pshufw      mm2,    mm1,  7
217     movq        [rsp + tbuffer + 2 * rax],  mm1
218     movq        [rsp + tbuffer + 2 * rax + 8],  mm2
219     paddw       mm1,    [mmx_dw_one GLOBAL]
220     psraw       mm1,    5
221     packuswb    mm1,    mm1
222     movd        [rdi + rax],  mm1   ; dst1[rax - 4] = mm1
223
224     add         r12,    r13         ; tsrc = tsrc + src_stride
225
226     add         r8,     r9          ; dst1 = dst1 + dst1_stride
227
228     xor         rax,    rax
229
230 .loopcx2:
231
232     movq        mm2,    [rsp + 2 * rax + 2  + 4 + tbuffer]
233     movq        mm3,    [rsp + 2 * rax + 4  + 4 + tbuffer]
234     movq        mm4,    [rsp + 2 * rax + 6  + 4 + tbuffer]
235     movq        mm5,    [rsp + 2 * rax + 8  + 4 + tbuffer]
236     movq        mm1,    [rsp + 2 * rax      + 4 + tbuffer]
237     movq        mm6,    [rsp + 2 * rax + 10 + 4 + tbuffer]
238     paddw       mm2,    mm5
239     paddw       mm3,    mm4
240     paddw       mm1,    mm6
241
242     movq        mm5,    [mmx_dw_20 GLOBAL]
243     movq        mm4,    [mmx_dw_5 GLOBAL]
244     movq        mm6,    mm1
245     pxor        mm7,    mm7
246
247     punpckhwd   mm5,    mm2
248     punpcklwd   mm4,    mm3
249     punpcklwd   mm2,    [mmx_dw_20 GLOBAL]
250     punpckhwd   mm3,    [mmx_dw_5 GLOBAL]
251
252     pcmpgtw     mm7,    mm1
253
254     pmaddwd     mm2,    mm4
255     pmaddwd     mm3,    mm5
256
257     punpcklwd   mm1,    mm7
258     punpckhwd   mm6,    mm7
259
260     paddd       mm2,    mm1
261     paddd       mm3,    mm6
262
263     paddd       mm2,    [mmx_dd_one GLOBAL]
264     paddd       mm3,    [mmx_dd_one GLOBAL]
265
266     psrad       mm2,    10
267     psrad       mm3,    10
268
269     packssdw    mm2,    mm3
270     packuswb    mm2,    mm0
271
272     movd        [r10 + rax], mm2    ; dst2[rax] = mm2
273
274     add         rax,    4
275     cmp         rax,    r14         ; cmp rax, width
276     jnz         .loopcx2
277
278     add         r10,    r11         ; dst2 += dst2_stride
279     dec         r15                 ; height
280     jnz         .loopcy
281
282     lea         rsp,    [rbp]
283
284     pop         r14
285     pop         r13
286     pop         r12
287     pop         rbx
288     pop         rbp
289 %ifdef WIN64
290     pop         rsi
291     pop         rdi
292 %endif
293     pop         r15
294
295     ret
296
297 ;-----------------------------------------------------------------------------
298 ;
299 ; void x264_horizontal_filter_mmxext( uint8_t *dst, int i_dst_stride,
300 ;                                     uint8_t *src, int i_src_stride,
301 ;                                     int i_width, int i_height );
302 ;
303 ;-----------------------------------------------------------------------------
304
305 ALIGN 16
306 x264_horizontal_filter_mmxext :
307     movsxd      r10,    parm2d               ; dst_stride
308     movsxd      r11,    parm4d               ; src_stride
309 %ifdef WIN64
310     mov         rdx,    r8                   ; src
311     mov         r9,     rcx                  ; dst
312     movsxd      rcx,    parm6d               ; height
313 %else
314     movsxd      rcx,    parm6d               ; height
315     mov         r9,     rdi                  ; dst
316 %endif
317     
318     movsxd      r8,     parm5d               ; width
319
320     pxor        mm0,    mm0
321     movq        mm7,    [mmx_dw_one GLOBAL]
322
323     sub         rdx,    2
324
325 loophy:
326
327     xor         rax,    rax
328
329 loophx:
330
331     prefetchnta [rdx + rax + 48]       
332
333     LOAD_4      mm1,    mm2, mm3, mm4, [rdx + rax], [rdx + rax + 1], [rdx + rax + 2], [rdx + rax + 3], mm0
334     FILT_2      mm1,    mm2
335     movd        mm5,    [rdx + rax + 4]
336     movd        mm6,    [rdx + rax + 5]
337     FILT_4      mm1,    mm3, mm4
338     movd        mm2,    [rdx + rax + 4]
339     movd        mm3,    [rdx + rax + 6]
340     punpcklbw   mm5,    mm0
341     punpcklbw   mm6,    mm0
342     FILT_6      mm1,    mm5, mm6, mm7
343     movd        mm4,    [rdx + rax + 7]
344     movd        mm5,    [rdx + rax + 8]
345     punpcklbw   mm2,    mm0
346     punpcklbw   mm3,    mm0                  ; mm2(1), mm3(20), mm6(-5) ready
347     FILT_2      mm2,    mm6
348     movd        mm6,    [rdx + rax + 9]
349     punpcklbw   mm4,    mm0
350     punpcklbw   mm5,    mm0                  ; mm2(1-5), mm3(20), mm4(20), mm5(-5) ready
351     FILT_4      mm2,    mm3, mm4
352     punpcklbw   mm6,    mm0
353     FILT_6      mm2,    mm5, mm6, mm7
354
355     packuswb    mm1,    mm2
356     movq        [r9 + rax],  mm1
357
358     add         rax,    8
359     cmp         rax,    r8                   ; cmp rax, width
360     jnz         loophx
361
362     add         rdx,    r11                  ; src_pitch
363     add         r9,     r10                  ; dst_pitch
364
365     dec         rcx
366     jnz         loophy
367
368     ret