1;*****************************************************************************
2;* x86util.asm
3;*****************************************************************************
4;* Copyright (C) 2008-2010 x264 project
5;*
6;* Authors: Loren Merritt <lorenm@u.washington.edu>
7;*          Holger Lubitz <holger@lubitz.org>
8;*
9;* This file is part of Libav.
10;*
11;* Libav is free software; you can redistribute it and/or
12;* modify it under the terms of the GNU Lesser General Public
13;* License as published by the Free Software Foundation; either
14;* version 2.1 of the License, or (at your option) any later version.
15;*
16;* Libav is distributed in the hope that it will be useful,
17;* but WITHOUT ANY WARRANTY; without even the implied warranty of
18;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19;* Lesser General Public License for more details.
20;*
21;* You should have received a copy of the GNU Lesser General Public
22;* License along with Libav; if not, write to the Free Software
23;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24;******************************************************************************
25
26%define private_prefix ff
27%define public_prefix  avpriv
28%define cpuflags_mmxext cpuflags_mmx2
29
30%include "libavutil/x86/x86inc.asm"
31
32%macro SBUTTERFLY 4
33%if avx_enabled == 0
34    mova      m%4, m%2
35    punpckl%1 m%2, m%3
36    punpckh%1 m%4, m%3
37%else
38    punpckh%1 m%4, m%2, m%3
39    punpckl%1 m%2, m%3
40%endif
41    SWAP %3, %4
42%endmacro
43
44%macro SBUTTERFLY2 4
45    punpckl%1 m%4, m%2, m%3
46    punpckh%1 m%2, m%2, m%3
47    SWAP %2, %4, %3
48%endmacro
49
50%macro SBUTTERFLYPS 3
51    unpcklps m%3, m%1, m%2
52    unpckhps m%1, m%1, m%2
53    SWAP %1, %3, %2
54%endmacro
55
56%macro TRANSPOSE4x4B 5
57    SBUTTERFLY bw, %1, %2, %5
58    SBUTTERFLY bw, %3, %4, %5
59    SBUTTERFLY wd, %1, %3, %5
60    SBUTTERFLY wd, %2, %4, %5
61    SWAP %2, %3
62%endmacro
63
64%macro TRANSPOSE4x4W 5
65    SBUTTERFLY wd, %1, %2, %5
66    SBUTTERFLY wd, %3, %4, %5
67    SBUTTERFLY dq, %1, %3, %5
68    SBUTTERFLY dq, %2, %4, %5
69    SWAP %2, %3
70%endmacro
71
72%macro TRANSPOSE2x4x4W 5
73    SBUTTERFLY wd,  %1, %2, %5
74    SBUTTERFLY wd,  %3, %4, %5
75    SBUTTERFLY dq,  %1, %3, %5
76    SBUTTERFLY dq,  %2, %4, %5
77    SBUTTERFLY qdq, %1, %2, %5
78    SBUTTERFLY qdq, %3, %4, %5
79%endmacro
80
81%macro TRANSPOSE4x4D 5
82    SBUTTERFLY dq,  %1, %2, %5
83    SBUTTERFLY dq,  %3, %4, %5
84    SBUTTERFLY qdq, %1, %3, %5
85    SBUTTERFLY qdq, %2, %4, %5
86    SWAP %2, %3
87%endmacro
88
89; identical behavior to TRANSPOSE4x4D, but using SSE1 float ops
90%macro TRANSPOSE4x4PS 5
91    SBUTTERFLYPS %1, %2, %5
92    SBUTTERFLYPS %3, %4, %5
93    movlhps m%5, m%1, m%3
94    movhlps m%3, m%1
95    SWAP %5, %1
96    movlhps m%5, m%2, m%4
97    movhlps m%4, m%2
98    SWAP %5, %2, %3
99%endmacro
100
101%macro TRANSPOSE8x8W 9-11
102%if ARCH_X86_64
103    SBUTTERFLY wd,  %1, %2, %9
104    SBUTTERFLY wd,  %3, %4, %9
105    SBUTTERFLY wd,  %5, %6, %9
106    SBUTTERFLY wd,  %7, %8, %9
107    SBUTTERFLY dq,  %1, %3, %9
108    SBUTTERFLY dq,  %2, %4, %9
109    SBUTTERFLY dq,  %5, %7, %9
110    SBUTTERFLY dq,  %6, %8, %9
111    SBUTTERFLY qdq, %1, %5, %9
112    SBUTTERFLY qdq, %2, %6, %9
113    SBUTTERFLY qdq, %3, %7, %9
114    SBUTTERFLY qdq, %4, %8, %9
115    SWAP %2, %5
116    SWAP %4, %7
117%else
118; in:  m0..m7, unless %11 in which case m6 is in %9
119; out: m0..m7, unless %11 in which case m4 is in %10
120; spills into %9 and %10
121%if %0<11
122    movdqa %9, m%7
123%endif
124    SBUTTERFLY wd,  %1, %2, %7
125    movdqa %10, m%2
126    movdqa m%7, %9
127    SBUTTERFLY wd,  %3, %4, %2
128    SBUTTERFLY wd,  %5, %6, %2
129    SBUTTERFLY wd,  %7, %8, %2
130    SBUTTERFLY dq,  %1, %3, %2
131    movdqa %9, m%3
132    movdqa m%2, %10
133    SBUTTERFLY dq,  %2, %4, %3
134    SBUTTERFLY dq,  %5, %7, %3
135    SBUTTERFLY dq,  %6, %8, %3
136    SBUTTERFLY qdq, %1, %5, %3
137    SBUTTERFLY qdq, %2, %6, %3
138    movdqa %10, m%2
139    movdqa m%3, %9
140    SBUTTERFLY qdq, %3, %7, %2
141    SBUTTERFLY qdq, %4, %8, %2
142    SWAP %2, %5
143    SWAP %4, %7
144%if %0<11
145    movdqa m%5, %10
146%endif
147%endif
148%endmacro
149
150; PABSW macro assumes %1 != %2, while ABS1/2 macros work in-place
151%macro PABSW 2
152%if cpuflag(ssse3)
153    pabsw      %1, %2
154%elif cpuflag(mmxext)
155    pxor    %1, %1
156    psubw   %1, %2
157    pmaxsw  %1, %2
158%else
159    pxor       %1, %1
160    pcmpgtw    %1, %2
161    pxor       %2, %1
162    psubw      %2, %1
163    SWAP       %1, %2
164%endif
165%endmacro
166
167%macro PSIGNW_MMX 2
168    pxor       %1, %2
169    psubw      %1, %2
170%endmacro
171
172%macro PSIGNW_SSSE3 2
173    psignw     %1, %2
174%endmacro
175
176%macro ABS1 2
177%if cpuflag(ssse3)
178    pabsw   %1, %1
179%elif cpuflag(mmxext) ; a, tmp
180    pxor    %2, %2
181    psubw   %2, %1
182    pmaxsw  %1, %2
183%else ; a, tmp
184    pxor       %2, %2
185    pcmpgtw    %2, %1
186    pxor       %1, %2
187    psubw      %1, %2
188%endif
189%endmacro
190
191%macro ABS2 4
192%if cpuflag(ssse3)
193    pabsw   %1, %1
194    pabsw   %2, %2
195%elif cpuflag(mmxext) ; a, b, tmp0, tmp1
196    pxor    %3, %3
197    pxor    %4, %4
198    psubw   %3, %1
199    psubw   %4, %2
200    pmaxsw  %1, %3
201    pmaxsw  %2, %4
202%else ; a, b, tmp0, tmp1
203    pxor       %3, %3
204    pxor       %4, %4
205    pcmpgtw    %3, %1
206    pcmpgtw    %4, %2
207    pxor       %1, %3
208    pxor       %2, %4
209    psubw      %1, %3
210    psubw      %2, %4
211%endif
212%endmacro
213
214%macro ABSB 2 ; source mmreg, temp mmreg (unused for ssse3)
215%if cpuflag(ssse3)
216    pabsb   %1, %1
217%else
218    pxor    %2, %2
219    psubb   %2, %1
220    pminub  %1, %2
221%endif
222%endmacro
223
224%macro ABSB2 4 ; src1, src2, tmp1, tmp2 (tmp1/2 unused for SSSE3)
225%if cpuflag(ssse3)
226    pabsb   %1, %1
227    pabsb   %2, %2
228%else
229    pxor    %3, %3
230    pxor    %4, %4
231    psubb   %3, %1
232    psubb   %4, %2
233    pminub  %1, %3
234    pminub  %2, %4
235%endif
236%endmacro
237
238%macro ABSD2_MMX 4
239    pxor    %3, %3
240    pxor    %4, %4
241    pcmpgtd %3, %1
242    pcmpgtd %4, %2
243    pxor    %1, %3
244    pxor    %2, %4
245    psubd   %1, %3
246    psubd   %2, %4
247%endmacro
248
249%macro ABS4 6
250    ABS2 %1, %2, %5, %6
251    ABS2 %3, %4, %5, %6
252%endmacro
253
254%macro SPLATB_LOAD 3
255%if cpuflag(ssse3)
256    movd      %1, [%2-3]
257    pshufb    %1, %3
258%else
259    movd      %1, [%2-3] ;to avoid crossing a cacheline
260    punpcklbw %1, %1
261    SPLATW    %1, %1, 3
262%endif
263%endmacro
264
265%macro SPLATB_REG 3
266%if cpuflag(ssse3)
267    movd      %1, %2d
268    pshufb    %1, %3
269%else
270    movd      %1, %2d
271    punpcklbw %1, %1
272    SPLATW    %1, %1, 0
273%endif
274%endmacro
275
276%macro PALIGNR 4-5
277%if cpuflag(ssse3)
278%if %0==5
279    palignr %1, %2, %3, %4
280%else
281    palignr %1, %2, %3
282%endif
283%elif cpuflag(mmx) ; [dst,] src1, src2, imm, tmp
284    %define %%dst %1
285%if %0==5
286%ifnidn %1, %2
287    mova    %%dst, %2
288%endif
289    %rotate 1
290%endif
291%ifnidn %4, %2
292    mova    %4, %2
293%endif
294%if mmsize==8
295    psllq   %%dst, (8-%3)*8
296    psrlq   %4, %3*8
297%else
298    pslldq  %%dst, 16-%3
299    psrldq  %4, %3
300%endif
301    por     %%dst, %4
302%endif
303%endmacro
304
305%macro PAVGB 2
306%if cpuflag(mmxext)
307    pavgb   %1, %2
308%elif cpuflag(3dnow)
309    pavgusb %1, %2
310%endif
311%endmacro
312
313%macro PSHUFLW 1+
314    %if mmsize == 8
315        pshufw %1
316    %else
317        pshuflw %1
318    %endif
319%endmacro
320
321%macro PSWAPD 2
322%if cpuflag(mmxext)
323    pshufw    %1, %2, q1032
324%elif cpuflag(3dnowext)
325    pswapd    %1, %2
326%elif cpuflag(3dnow)
327    movq      %1, %2
328    psrlq     %1, 32
329    punpckldq %1, %2
330%endif
331%endmacro
332
333%macro DEINTB 5 ; mask, reg1, mask, reg2, optional src to fill masks from
334%ifnum %5
335    pand   m%3, m%5, m%4 ; src .. y6 .. y4
336    pand   m%1, m%5, m%2 ; dst .. y6 .. y4
337%else
338    mova   m%1, %5
339    pand   m%3, m%1, m%4 ; src .. y6 .. y4
340    pand   m%1, m%1, m%2 ; dst .. y6 .. y4
341%endif
342    psrlw  m%2, 8        ; dst .. y7 .. y5
343    psrlw  m%4, 8        ; src .. y7 .. y5
344%endmacro
345
346%macro SUMSUB_BA 3-4
347%if %0==3
348    padd%1  m%2, m%3
349    padd%1  m%3, m%3
350    psub%1  m%3, m%2
351%else
352%if avx_enabled == 0
353    mova    m%4, m%2
354    padd%1  m%2, m%3
355    psub%1  m%3, m%4
356%else
357    padd%1  m%4, m%2, m%3
358    psub%1  m%3, m%2
359    SWAP    %2, %4
360%endif
361%endif
362%endmacro
363
364%macro SUMSUB_BADC 5-6
365%if %0==6
366    SUMSUB_BA %1, %2, %3, %6
367    SUMSUB_BA %1, %4, %5, %6
368%else
369    padd%1  m%2, m%3
370    padd%1  m%4, m%5
371    padd%1  m%3, m%3
372    padd%1  m%5, m%5
373    psub%1  m%3, m%2
374    psub%1  m%5, m%4
375%endif
376%endmacro
377
378%macro SUMSUB2_AB 4
379%ifnum %3
380    psub%1  m%4, m%2, m%3
381    psub%1  m%4, m%3
382    padd%1  m%2, m%2
383    padd%1  m%2, m%3
384%else
385    mova    m%4, m%2
386    padd%1  m%2, m%2
387    padd%1  m%2, %3
388    psub%1  m%4, %3
389    psub%1  m%4, %3
390%endif
391%endmacro
392
393%macro SUMSUB2_BA 4
394%if avx_enabled == 0
395    mova    m%4, m%2
396    padd%1  m%2, m%3
397    padd%1  m%2, m%3
398    psub%1  m%3, m%4
399    psub%1  m%3, m%4
400%else
401    padd%1  m%4, m%2, m%3
402    padd%1  m%4, m%3
403    psub%1  m%3, m%2
404    psub%1  m%3, m%2
405    SWAP     %2,  %4
406%endif
407%endmacro
408
409%macro SUMSUBD2_AB 5
410%ifnum %4
411    psra%1  m%5, m%2, 1  ; %3: %3>>1
412    psra%1  m%4, m%3, 1  ; %2: %2>>1
413    padd%1  m%4, m%2     ; %3: %3>>1+%2
414    psub%1  m%5, m%3     ; %2: %2>>1-%3
415    SWAP     %2, %5
416    SWAP     %3, %4
417%else
418    mova    %5, m%2
419    mova    %4, m%3
420    psra%1  m%3, 1  ; %3: %3>>1
421    psra%1  m%2, 1  ; %2: %2>>1
422    padd%1  m%3, %5 ; %3: %3>>1+%2
423    psub%1  m%2, %4 ; %2: %2>>1-%3
424%endif
425%endmacro
426
427%macro DCT4_1D 5
428%ifnum %5
429    SUMSUB_BADC w, %4, %1, %3, %2, %5
430    SUMSUB_BA   w, %3, %4, %5
431    SUMSUB2_AB  w, %1, %2, %5
432    SWAP %1, %3, %4, %5, %2
433%else
434    SUMSUB_BADC w, %4, %1, %3, %2
435    SUMSUB_BA   w, %3, %4
436    mova     [%5], m%2
437    SUMSUB2_AB  w, %1, [%5], %2
438    SWAP %1, %3, %4, %2
439%endif
440%endmacro
441
442%macro IDCT4_1D 6-7
443%ifnum %6
444    SUMSUBD2_AB %1, %3, %5, %7, %6
445    ; %3: %3>>1-%5 %5: %3+%5>>1
446    SUMSUB_BA   %1, %4, %2, %7
447    ; %4: %2+%4 %2: %2-%4
448    SUMSUB_BADC %1, %5, %4, %3, %2, %7
449    ; %5: %2+%4 + (%3+%5>>1)
450    ; %4: %2+%4 - (%3+%5>>1)
451    ; %3: %2-%4 + (%3>>1-%5)
452    ; %2: %2-%4 - (%3>>1-%5)
453%else
454%ifidn %1, w
455    SUMSUBD2_AB %1, %3, %5, [%6], [%6+16]
456%else
457    SUMSUBD2_AB %1, %3, %5, [%6], [%6+32]
458%endif
459    SUMSUB_BA   %1, %4, %2
460    SUMSUB_BADC %1, %5, %4, %3, %2
461%endif
462    SWAP %2, %5, %4
463    ; %2: %2+%4 + (%3+%5>>1) row0
464    ; %3: %2-%4 + (%3>>1-%5) row1
465    ; %4: %2-%4 - (%3>>1-%5) row2
466    ; %5: %2+%4 - (%3+%5>>1) row3
467%endmacro
468
469
470%macro LOAD_DIFF 5
471%ifidn %3, none
472    movh       %1, %4
473    movh       %2, %5
474    punpcklbw  %1, %2
475    punpcklbw  %2, %2
476    psubw      %1, %2
477%else
478    movh       %1, %4
479    punpcklbw  %1, %3
480    movh       %2, %5
481    punpcklbw  %2, %3
482    psubw      %1, %2
483%endif
484%endmacro
485
486%macro STORE_DCT 6
487    movq   [%5+%6+ 0], m%1
488    movq   [%5+%6+ 8], m%2
489    movq   [%5+%6+16], m%3
490    movq   [%5+%6+24], m%4
491    movhps [%5+%6+32], m%1
492    movhps [%5+%6+40], m%2
493    movhps [%5+%6+48], m%3
494    movhps [%5+%6+56], m%4
495%endmacro
496
497%macro LOAD_DIFF_8x4P 7-10 r0,r2,0 ; 4x dest, 2x temp, 2x pointer, increment?
498    LOAD_DIFF m%1, m%5, m%7, [%8],      [%9]
499    LOAD_DIFF m%2, m%6, m%7, [%8+r1],   [%9+r3]
500    LOAD_DIFF m%3, m%5, m%7, [%8+2*r1], [%9+2*r3]
501    LOAD_DIFF m%4, m%6, m%7, [%8+r4],   [%9+r5]
502%if %10
503    lea %8, [%8+4*r1]
504    lea %9, [%9+4*r3]
505%endif
506%endmacro
507
508%macro DIFFx2 6-7
509    movh       %3, %5
510    punpcklbw  %3, %4
511    psraw      %1, 6
512    paddsw     %1, %3
513    movh       %3, %6
514    punpcklbw  %3, %4
515    psraw      %2, 6
516    paddsw     %2, %3
517    packuswb   %2, %1
518%endmacro
519
520%macro STORE_DIFF 4
521    movh       %2, %4
522    punpcklbw  %2, %3
523    psraw      %1, 6
524    paddsw     %1, %2
525    packuswb   %1, %1
526    movh       %4, %1
527%endmacro
528
529%macro STORE_DIFFx2 8 ; add1, add2, reg1, reg2, zero, shift, source, stride
530    movh       %3, [%7]
531    movh       %4, [%7+%8]
532    psraw      %1, %6
533    psraw      %2, %6
534    punpcklbw  %3, %5
535    punpcklbw  %4, %5
536    paddw      %3, %1
537    paddw      %4, %2
538    packuswb   %3, %5
539    packuswb   %4, %5
540    movh     [%7], %3
541    movh  [%7+%8], %4
542%endmacro
543
544%macro PMINUB 3 ; dst, src, ignored
545%if cpuflag(mmxext)
546    pminub   %1, %2
547%else ; dst, src, tmp
548    mova     %3, %1
549    psubusb  %3, %2
550    psubb    %1, %3
551%endif
552%endmacro
553
554%macro SPLATW 2-3 0
555%if mmsize == 16
556    pshuflw    %1, %2, (%3)*0x55
557    punpcklqdq %1, %1
558%elif cpuflag(mmxext)
559    pshufw     %1, %2, (%3)*0x55
560%else
561    %ifnidn %1, %2
562        mova       %1, %2
563    %endif
564    %if %3 & 2
565        punpckhwd  %1, %1
566    %else
567        punpcklwd  %1, %1
568    %endif
569    %if %3 & 1
570        punpckhwd  %1, %1
571    %else
572        punpcklwd  %1, %1
573    %endif
574%endif
575%endmacro
576
577%macro SPLATD 1
578%if mmsize == 8
579    punpckldq  %1, %1
580%elif cpuflag(sse2)
581    pshufd  %1, %1, 0
582%elif cpuflag(sse)
583    shufps  %1, %1, 0
584%endif
585%endmacro
586
587%macro CLIPW 3 ;(dst, min, max)
588    pmaxsw %1, %2
589    pminsw %1, %3
590%endmacro
591
592%macro PMINSD_MMX 3 ; dst, src, tmp
593    mova      %3, %2
594    pcmpgtd   %3, %1
595    pxor      %1, %2
596    pand      %1, %3
597    pxor      %1, %2
598%endmacro
599
600%macro PMAXSD_MMX 3 ; dst, src, tmp
601    mova      %3, %1
602    pcmpgtd   %3, %2
603    pand      %1, %3
604    pandn     %3, %2
605    por       %1, %3
606%endmacro
607
608%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp
609    PMINSD_MMX %1, %3, %4
610    PMAXSD_MMX %1, %2, %4
611%endmacro
612
613%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused
614    cvtdq2ps  %1, %1
615    minps     %1, %3
616    maxps     %1, %2
617    cvtps2dq  %1, %1
618%endmacro
619
620%macro CLIPD_SSE41 3-4 ;  src/dst, min, max, unused
621    pminsd  %1, %3
622    pmaxsd  %1, %2
623%endmacro
624
625%macro VBROADCASTSS 2 ; dst xmm/ymm, src m32
626%if cpuflag(avx)
627    vbroadcastss %1, %2
628%else ; sse
629    movss        %1, %2
630    shufps       %1, %1, 0
631%endif
632%endmacro
633
634%macro VBROADCASTSD 2 ; dst xmm/ymm, src m64
635%if cpuflag(avx) && mmsize == 32
636    vbroadcastsd %1, %2
637%elif cpuflag(sse3)
638    movddup      %1, %2
639%else ; sse2
640    movsd        %1, %2
641    movlhps      %1, %1
642%endif
643%endmacro
644
645%macro SHUFFLE_MASK_W 8
646    %rep 8
647        %if %1>=0x80
648            db %1, %1
649        %else
650            db %1*2
651            db %1*2+1
652        %endif
653        %rotate 1
654    %endrep
655%endmacro
656
657%macro PMOVSXWD 2; dst, src
658%if cpuflag(sse4)
659    pmovsxwd     %1, %2
660%else
661    %ifnidn %1, %2
662    mova         %1, %2
663    %endif
664    punpcklwd    %1, %1
665    psrad        %1, 16
666%endif
667%endmacro
668
669; Wrapper for non-FMA version of fmaddps
670%macro FMULADD_PS 5
671    %if cpuflag(fma3) || cpuflag(fma4)
672        fmaddps %1, %2, %3, %4
673    %elifidn %1, %4
674        mulps   %5, %2, %3
675        addps   %1, %4, %5
676    %else
677        mulps   %1, %2, %3
678        addps   %1, %4
679    %endif
680%endmacro
681