x86: hpeldsp: implement SSE2 put_pixels16_xy2
[ffmpeg.git] / libavcodec / x86 / hpeldsp.asm
1 ;******************************************************************************
2 ;*
3 ;* Copyright (c) 2000-2001 Fabrice Bellard <fabrice@bellard.org>
4 ;* Copyright (c)      Nick Kurshev <nickols_k@mail.ru>
5 ;* Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
6 ;* Copyright (c) 2002 Zdenek Kabelac <kabi@informatics.muni.cz>
7 ;* Copyright (c) 2013 Daniel Kang
8 ;*
9 ;* SIMD-optimized halfpel functions
10 ;*
11 ;* This file is part of FFmpeg.
12 ;*
13 ;* FFmpeg is free software; you can redistribute it and/or
14 ;* modify it under the terms of the GNU Lesser General Public
15 ;* License as published by the Free Software Foundation; either
16 ;* version 2.1 of the License, or (at your option) any later version.
17 ;*
18 ;* FFmpeg is distributed in the hope that it will be useful,
19 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 ;* Lesser General Public License for more details.
22 ;*
23 ;* You should have received a copy of the GNU Lesser General Public
24 ;* License along with FFmpeg; if not, write to the Free Software
25 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 ;******************************************************************************
27
28 %include "libavutil/x86/x86util.asm"
29
30 SECTION_RODATA
31 cextern pb_1
32 cextern pw_2
33
34 SECTION_TEXT
35
36 ; void ff_put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
37 %macro PUT_PIXELS8_X2 0
38 %if cpuflag(sse2)
39 cglobal put_pixels16_x2, 4,5,4
40 %else
41 cglobal put_pixels8_x2, 4,5
42 %endif
43     lea          r4, [r2*2]
44 .loop:
45     movu         m0, [r1+1]
46     movu         m1, [r1+r2+1]
47 %if cpuflag(sse2)
48     movu         m2, [r1]
49     movu         m3, [r1+r2]
50     pavgb        m0, m2
51     pavgb        m1, m3
52 %else
53     PAVGB        m0, [r1]
54     PAVGB        m1, [r1+r2]
55 %endif
56     mova       [r0], m0
57     mova    [r0+r2], m1
58     add          r1, r4
59     add          r0, r4
60     movu         m0, [r1+1]
61     movu         m1, [r1+r2+1]
62 %if cpuflag(sse2)
63     movu         m2, [r1]
64     movu         m3, [r1+r2]
65     pavgb        m0, m2
66     pavgb        m1, m3
67 %else
68     PAVGB        m0, [r1]
69     PAVGB        m1, [r1+r2]
70 %endif
71     add          r1, r4
72     mova       [r0], m0
73     mova    [r0+r2], m1
74     add          r0, r4
75     sub         r3d, 4
76     jne .loop
77     REP_RET
78 %endmacro
79
80 INIT_MMX mmxext
81 PUT_PIXELS8_X2
82 INIT_MMX 3dnow
83 PUT_PIXELS8_X2
84
85
86 ; void ff_put_pixels16_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
87 %macro PUT_PIXELS_16 0
88 cglobal put_pixels16_x2, 4,5
89     lea          r4, [r2*2]
90 .loop:
91     mova         m0, [r1]
92     mova         m1, [r1+r2]
93     mova         m2, [r1+8]
94     mova         m3, [r1+r2+8]
95     PAVGB        m0, [r1+1]
96     PAVGB        m1, [r1+r2+1]
97     PAVGB        m2, [r1+9]
98     PAVGB        m3, [r1+r2+9]
99     mova       [r0], m0
100     mova    [r0+r2], m1
101     mova     [r0+8], m2
102     mova  [r0+r2+8], m3
103     add          r1, r4
104     add          r0, r4
105     mova         m0, [r1]
106     mova         m1, [r1+r2]
107     mova         m2, [r1+8]
108     mova         m3, [r1+r2+8]
109     PAVGB        m0, [r1+1]
110     PAVGB        m1, [r1+r2+1]
111     PAVGB        m2, [r1+9]
112     PAVGB        m3, [r1+r2+9]
113     add          r1, r4
114     mova       [r0], m0
115     mova    [r0+r2], m1
116     mova     [r0+8], m2
117     mova  [r0+r2+8], m3
118     add          r0, r4
119     sub         r3d, 4
120     jne .loop
121     REP_RET
122 %endmacro
123
124 INIT_MMX mmxext
125 PUT_PIXELS_16
126 INIT_MMX 3dnow
127 PUT_PIXELS_16
128 ; The 8_X2 macro can easily be used here
129 INIT_XMM sse2
130 PUT_PIXELS8_X2
131
132
133 ; void ff_put_no_rnd_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
134 %macro PUT_NO_RND_PIXELS8_X2 0
135 cglobal put_no_rnd_pixels8_x2, 4,5
136     mova         m6, [pb_1]
137     lea          r4, [r2*2]
138 .loop:
139     mova         m0, [r1]
140     mova         m2, [r1+r2]
141     mova         m1, [r1+1]
142     mova         m3, [r1+r2+1]
143     add          r1, r4
144     psubusb      m0, m6
145     psubusb      m2, m6
146     PAVGB        m0, m1
147     PAVGB        m2, m3
148     mova       [r0], m0
149     mova    [r0+r2], m2
150     mova         m0, [r1]
151     mova         m1, [r1+1]
152     mova         m2, [r1+r2]
153     mova         m3, [r1+r2+1]
154     add          r0, r4
155     add          r1, r4
156     psubusb      m0, m6
157     psubusb      m2, m6
158     PAVGB        m0, m1
159     PAVGB        m2, m3
160     mova       [r0], m0
161     mova    [r0+r2], m2
162     add          r0, r4
163     sub         r3d, 4
164     jne .loop
165     REP_RET
166 %endmacro
167
168 INIT_MMX mmxext
169 PUT_NO_RND_PIXELS8_X2
170 INIT_MMX 3dnow
171 PUT_NO_RND_PIXELS8_X2
172
173
174 ; void ff_put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
175 %macro PUT_NO_RND_PIXELS8_X2_EXACT 0
176 cglobal put_no_rnd_pixels8_x2_exact, 4,5
177     lea          r4, [r2*3]
178     pcmpeqb      m6, m6
179 .loop:
180     mova         m0, [r1]
181     mova         m2, [r1+r2]
182     mova         m1, [r1+1]
183     mova         m3, [r1+r2+1]
184     pxor         m0, m6
185     pxor         m2, m6
186     pxor         m1, m6
187     pxor         m3, m6
188     PAVGB        m0, m1
189     PAVGB        m2, m3
190     pxor         m0, m6
191     pxor         m2, m6
192     mova       [r0], m0
193     mova    [r0+r2], m2
194     mova         m0, [r1+r2*2]
195     mova         m1, [r1+r2*2+1]
196     mova         m2, [r1+r4]
197     mova         m3, [r1+r4+1]
198     pxor         m0, m6
199     pxor         m1, m6
200     pxor         m2, m6
201     pxor         m3, m6
202     PAVGB        m0, m1
203     PAVGB        m2, m3
204     pxor         m0, m6
205     pxor         m2, m6
206     mova  [r0+r2*2], m0
207     mova    [r0+r4], m2
208     lea          r1, [r1+r2*4]
209     lea          r0, [r0+r2*4]
210     sub         r3d, 4
211     jg .loop
212     REP_RET
213 %endmacro
214
215 INIT_MMX mmxext
216 PUT_NO_RND_PIXELS8_X2_EXACT
217 INIT_MMX 3dnow
218 PUT_NO_RND_PIXELS8_X2_EXACT
219
220
221 ; void ff_put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
222 %macro PUT_PIXELS8_Y2 0
223 %if cpuflag(sse2)
224 cglobal put_pixels16_y2, 4,5,3
225 %else
226 cglobal put_pixels8_y2, 4,5
227 %endif
228     lea          r4, [r2*2]
229     movu         m0, [r1]
230     sub          r0, r2
231 .loop:
232     movu         m1, [r1+r2]
233     movu         m2, [r1+r4]
234     add          r1, r4
235     PAVGB        m0, m1
236     PAVGB        m1, m2
237     mova    [r0+r2], m0
238     mova    [r0+r4], m1
239     movu         m1, [r1+r2]
240     movu         m0, [r1+r4]
241     add          r0, r4
242     add          r1, r4
243     PAVGB        m2, m1
244     PAVGB        m1, m0
245     mova    [r0+r2], m2
246     mova    [r0+r4], m1
247     add          r0, r4
248     sub         r3d, 4
249     jne .loop
250     REP_RET
251 %endmacro
252
253 INIT_MMX mmxext
254 PUT_PIXELS8_Y2
255 INIT_MMX 3dnow
256 PUT_PIXELS8_Y2
257 ; actually, put_pixels16_y2_sse2
258 INIT_XMM sse2
259 PUT_PIXELS8_Y2
260
261
262 ; void ff_put_no_rnd_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
263 %macro PUT_NO_RND_PIXELS8_Y2 0
264 cglobal put_no_rnd_pixels8_y2, 4,5
265     mova         m6, [pb_1]
266     lea          r4, [r2+r2]
267     mova         m0, [r1]
268     sub          r0, r2
269 .loop:
270     mova         m1, [r1+r2]
271     mova         m2, [r1+r4]
272     add          r1, r4
273     psubusb      m1, m6
274     PAVGB        m0, m1
275     PAVGB        m1, m2
276     mova    [r0+r2], m0
277     mova    [r0+r4], m1
278     mova         m1, [r1+r2]
279     mova         m0, [r1+r4]
280     add          r0, r4
281     add          r1, r4
282     psubusb      m1, m6
283     PAVGB        m2, m1
284     PAVGB        m1, m0
285     mova    [r0+r2], m2
286     mova    [r0+r4], m1
287     add          r0, r4
288     sub         r3d, 4
289     jne .loop
290     REP_RET
291 %endmacro
292
293 INIT_MMX mmxext
294 PUT_NO_RND_PIXELS8_Y2
295 INIT_MMX 3dnow
296 PUT_NO_RND_PIXELS8_Y2
297
298
299 ; void ff_put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
300 %macro PUT_NO_RND_PIXELS8_Y2_EXACT 0
301 cglobal put_no_rnd_pixels8_y2_exact, 4,5
302     lea          r4, [r2*3]
303     mova         m0, [r1]
304     pcmpeqb      m6, m6
305     add          r1, r2
306     pxor         m0, m6
307 .loop:
308     mova         m1, [r1]
309     mova         m2, [r1+r2]
310     pxor         m1, m6
311     pxor         m2, m6
312     PAVGB        m0, m1
313     PAVGB        m1, m2
314     pxor         m0, m6
315     pxor         m1, m6
316     mova       [r0], m0
317     mova    [r0+r2], m1
318     mova         m1, [r1+r2*2]
319     mova         m0, [r1+r4]
320     pxor         m1, m6
321     pxor         m0, m6
322     PAVGB        m2, m1
323     PAVGB        m1, m0
324     pxor         m2, m6
325     pxor         m1, m6
326     mova  [r0+r2*2], m2
327     mova    [r0+r4], m1
328     lea          r1, [r1+r2*4]
329     lea          r0, [r0+r2*4]
330     sub         r3d, 4
331     jg .loop
332     REP_RET
333 %endmacro
334
335 INIT_MMX mmxext
336 PUT_NO_RND_PIXELS8_Y2_EXACT
337 INIT_MMX 3dnow
338 PUT_NO_RND_PIXELS8_Y2_EXACT
339
340
341 ; void ff_avg_pixels8(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
342 %macro AVG_PIXELS8 0
343 cglobal avg_pixels8, 4,5
344     lea          r4, [r2*2]
345 .loop:
346     mova         m0, [r0]
347     mova         m1, [r0+r2]
348     PAVGB        m0, [r1]
349     PAVGB        m1, [r1+r2]
350     mova       [r0], m0
351     mova    [r0+r2], m1
352     add          r1, r4
353     add          r0, r4
354     mova         m0, [r0]
355     mova         m1, [r0+r2]
356     PAVGB        m0, [r1]
357     PAVGB        m1, [r1+r2]
358     add          r1, r4
359     mova       [r0], m0
360     mova    [r0+r2], m1
361     add          r0, r4
362     sub         r3d, 4
363     jne .loop
364     REP_RET
365 %endmacro
366
367 INIT_MMX 3dnow
368 AVG_PIXELS8
369
370
371 ; void ff_avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
372 %macro PAVGB_MMX 4
373     movu   %3, %1
374     por    %3, %2
375     pxor   %2, %1
376     pand   %2, %4
377     psrlq  %2, 1
378     psubb  %3, %2
379     SWAP   %2, %3
380 %endmacro
381
382 %macro AVG_PIXELS8_X2 0
383 %if cpuflag(sse2)
384 cglobal avg_pixels16_x2, 4,5,4
385 %else
386 cglobal avg_pixels8_x2, 4,5
387 %endif
388     lea          r4, [r2*2]
389 %if notcpuflag(mmxext)
390     pcmpeqd      m5, m5
391     paddb        m5, m5
392 %endif
393 .loop:
394     movu         m0, [r1]
395     movu         m2, [r1+r2]
396 %if notcpuflag(mmxext)
397     PAVGB_MMX    [r1+1], m0, m3, m5
398     PAVGB_MMX    [r1+r2+1], m2, m4, m5
399     PAVGB_MMX    [r0], m0, m3, m5
400     PAVGB_MMX    [r0+r2], m2, m4, m5
401 %else
402 %if cpuflag(sse2)
403     movu         m1, [r1+1]
404     movu         m3, [r1+r2+1]
405     pavgb        m0, m1
406     pavgb        m2, m3
407 %else
408     PAVGB        m0, [r1+1]
409     PAVGB        m2, [r1+r2+1]
410 %endif
411     PAVGB        m0, [r0]
412     PAVGB        m2, [r0+r2]
413 %endif
414     add          r1, r4
415     mova       [r0], m0
416     mova    [r0+r2], m2
417     movu         m0, [r1]
418     movu         m2, [r1+r2]
419 %if notcpuflag(mmxext)
420     PAVGB_MMX    [r1+1], m0, m3, m5
421     PAVGB_MMX    [r1+r2+1], m2, m4, m5
422 %elif cpuflag(sse2)
423     movu         m1, [r1+1]
424     movu         m3, [r1+r2+1]
425     pavgb        m0, m1
426     pavgb        m2, m3
427 %else
428     PAVGB        m0, [r1+1]
429     PAVGB        m2, [r1+r2+1]
430 %endif
431     add          r0, r4
432     add          r1, r4
433 %if notcpuflag(mmxext)
434     PAVGB_MMX    [r0], m0, m3, m5
435     PAVGB_MMX    [r0+r2], m2, m4, m5
436 %elif cpuflag(sse2)
437     pavgb        m0, [r0]
438     pavgb        m2, [r0+r2]
439 %else
440     PAVGB        m0, [r0]
441     PAVGB        m2, [r0+r2]
442 %endif
443     mova       [r0], m0
444     mova    [r0+r2], m2
445     add          r0, r4
446     sub         r3d, 4
447     jne .loop
448     REP_RET
449 %endmacro
450
451 INIT_MMX mmx
452 AVG_PIXELS8_X2
453 INIT_MMX mmxext
454 AVG_PIXELS8_X2
455 INIT_MMX 3dnow
456 AVG_PIXELS8_X2
457 ; actually avg_pixels16_x2
458 INIT_XMM sse2
459 AVG_PIXELS8_X2
460
461
462 ; void ff_avg_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
463 %macro AVG_PIXELS8_Y2 0
464 %if cpuflag(sse2)
465 cglobal avg_pixels16_y2, 4,5,3
466 %else
467 cglobal avg_pixels8_y2, 4,5
468 %endif
469     lea          r4, [r2*2]
470     movu         m0, [r1]
471     sub          r0, r2
472 .loop:
473     movu         m1, [r1+r2]
474     movu         m2, [r1+r4]
475     add          r1, r4
476     PAVGB        m0, m1
477     PAVGB        m1, m2
478     PAVGB        m0, [r0+r2]
479     PAVGB        m1, [r0+r4]
480     mova    [r0+r2], m0
481     mova    [r0+r4], m1
482     movu         m1, [r1+r2]
483     movu         m0, [r1+r4]
484     PAVGB        m2, m1
485     PAVGB        m1, m0
486     add          r0, r4
487     add          r1, r4
488     PAVGB        m2, [r0+r2]
489     PAVGB        m1, [r0+r4]
490     mova    [r0+r2], m2
491     mova    [r0+r4], m1
492     add          r0, r4
493     sub         r3d, 4
494     jne .loop
495     REP_RET
496 %endmacro
497
498 INIT_MMX mmxext
499 AVG_PIXELS8_Y2
500 INIT_MMX 3dnow
501 AVG_PIXELS8_Y2
502 ; actually avg_pixels16_y2
503 INIT_XMM sse2
504 AVG_PIXELS8_Y2
505
506
507 ; void ff_avg_pixels8_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
508 ; Note this is not correctly rounded, and is therefore used for
509 ; not-bitexact output
510 %macro AVG_APPROX_PIXELS8_XY2 0
511 cglobal avg_approx_pixels8_xy2, 4,5
512     mova         m6, [pb_1]
513     lea          r4, [r2*2]
514     mova         m0, [r1]
515     PAVGB        m0, [r1+1]
516 .loop:
517     mova         m2, [r1+r4]
518     mova         m1, [r1+r2]
519     psubusb      m2, m6
520     PAVGB        m1, [r1+r2+1]
521     PAVGB        m2, [r1+r4+1]
522     add          r1, r4
523     PAVGB        m0, m1
524     PAVGB        m1, m2
525     PAVGB        m0, [r0]
526     PAVGB        m1, [r0+r2]
527     mova       [r0], m0
528     mova    [r0+r2], m1
529     mova         m1, [r1+r2]
530     mova         m0, [r1+r4]
531     PAVGB        m1, [r1+r2+1]
532     PAVGB        m0, [r1+r4+1]
533     add          r0, r4
534     add          r1, r4
535     PAVGB        m2, m1
536     PAVGB        m1, m0
537     PAVGB        m2, [r0]
538     PAVGB        m1, [r0+r2]
539     mova       [r0], m2
540     mova    [r0+r2], m1
541     add          r0, r4
542     sub         r3d, 4
543     jne .loop
544     REP_RET
545 %endmacro
546
547 INIT_MMX mmxext
548 AVG_APPROX_PIXELS8_XY2
549 INIT_MMX 3dnow
550 AVG_APPROX_PIXELS8_XY2
551
552
553 ; void ff_avg_pixels16_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
554 %macro SET_PIXELS_XY2 1
555 %if cpuflag(sse2)
556 cglobal %1_pixels16_xy2, 4,5,8
557 %else
558 cglobal %1_pixels8_xy2, 4,5
559 %endif
560     pxor        m7, m7
561     mova        m6, [pw_2]
562     movu        m0, [r1]
563     movu        m4, [r1+1]
564     mova        m1, m0
565     mova        m5, m4
566     punpcklbw   m0, m7
567     punpcklbw   m4, m7
568     punpckhbw   m1, m7
569     punpckhbw   m5, m7
570     paddusw     m4, m0
571     paddusw     m5, m1
572     xor         r4, r4
573     add         r1, r2
574 .loop:
575     movu        m0, [r1+r4]
576     movu        m2, [r1+r4+1]
577     mova        m1, m0
578     mova        m3, m2
579     punpcklbw   m0, m7
580     punpcklbw   m2, m7
581     punpckhbw   m1, m7
582     punpckhbw   m3, m7
583     paddusw     m0, m2
584     paddusw     m1, m3
585     paddusw     m4, m6
586     paddusw     m5, m6
587     paddusw     m4, m0
588     paddusw     m5, m1
589     psrlw       m4, 2
590     psrlw       m5, 2
591 %ifidn %1, avg
592     mova        m3, [r0+r4]
593     packuswb    m4, m5
594     PAVGB       m4, m3
595 %else
596     packuswb    m4, m5
597 %endif
598     mova   [r0+r4], m4
599     add         r4, r2
600
601     movu        m2, [r1+r4]
602     movu        m4, [r1+r4+1]
603     mova        m3, m2
604     mova        m5, m4
605     punpcklbw   m2, m7
606     punpcklbw   m4, m7
607     punpckhbw   m3, m7
608     punpckhbw   m5, m7
609     paddusw     m4, m2
610     paddusw     m5, m3
611     paddusw     m0, m6
612     paddusw     m1, m6
613     paddusw     m0, m4
614     paddusw     m1, m5
615     psrlw       m0, 2
616     psrlw       m1, 2
617 %ifidn %1, avg
618     mova        m3, [r0+r4]
619     packuswb    m0, m1
620     PAVGB       m0, m3
621 %else
622     packuswb    m0, m1
623 %endif
624     mova   [r0+r4], m0
625     add         r4, r2
626     sub        r3d, 2
627     jnz .loop
628     REP_RET
629 %endmacro
630
631 INIT_MMX mmxext
632 SET_PIXELS_XY2 avg
633 INIT_MMX 3dnow
634 SET_PIXELS_XY2 avg
635 INIT_XMM sse2
636 SET_PIXELS_XY2 put
637 SET_PIXELS_XY2 avg