1 ;*****************************************************************************
2 ;* MMX optimized DSP utils
3 ;*****************************************************************************
4 ;* Copyright (c) 2000, 2001 Fabrice Bellard
5 ;* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
7 ;* This file is part of FFmpeg.
9 ;* FFmpeg is free software; you can redistribute it and/or
10 ;* modify it under the terms of the GNU Lesser General Public
11 ;* License as published by the Free Software Foundation; either
12 ;* version 2.1 of the License, or (at your option) any later version.
14 ;* FFmpeg is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ;* Lesser General Public License for more details.
19 ;* You should have received a copy of the GNU Lesser General Public
20 ;* License along with FFmpeg; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 ;*****************************************************************************
24 %include "libavutil/x86/x86util.asm"
32 %macro DIFF_PIXELS_1 4
40 ; %1=uint8_t *pix1, %2=uint8_t *pix2, %3=static offset, %4=stride, %5=stride*3
41 ; %6=temporary storage location
42 ; this macro requires $mmsize stack space (aligned) on %6 (except on SSE+x86-64)
43 %macro DIFF_PIXELS_8 6
44 DIFF_PIXELS_1 m0, m7, [%1 +%3], [%2 +%3]
45 DIFF_PIXELS_1 m1, m7, [%1+%4 +%3], [%2+%4 +%3]
46 DIFF_PIXELS_1 m2, m7, [%1+%4*2+%3], [%2+%4*2+%3]
49 DIFF_PIXELS_1 m3, m7, [%1 +%3], [%2 +%3]
50 DIFF_PIXELS_1 m4, m7, [%1+%4 +%3], [%2+%4 +%3]
51 DIFF_PIXELS_1 m5, m7, [%1+%4*2+%3], [%2+%4*2+%3]
52 DIFF_PIXELS_1 m6, m7, [%1+%5 +%3], [%2+%5 +%3]
54 DIFF_PIXELS_1 m7, m8, [%1+%4*4+%3], [%2+%4*4+%3]
57 DIFF_PIXELS_1 m7, m0, [%1+%4*4+%3], [%2+%4*4+%3]
65 SUMSUB_BADC w, 0, 1, 2, 3
66 SUMSUB_BADC w, 4, 5, 6, 7
67 SUMSUB_BADC w, 0, 2, 1, 3
68 SUMSUB_BADC w, 4, 6, 5, 7
69 SUMSUB_BADC w, 0, 4, 1, 5
70 SUMSUB_BADC w, 2, 6, 3, 7
84 %macro ABS_SUM_8x8_64 1
86 ABS2_SUM m2, m3, m8, m9, m0, m1
87 ABS2_SUM m4, m5, m8, m9, m0, m1
88 ABS2_SUM m6, m7, m8, m9, m0, m1
92 %macro ABS_SUM_8x8_32 1
106 ; FIXME: HSUM saturates at 64k, while an 8x8 hadamard or dct block can get up to
107 ; about 100k on extreme inputs. But that's very unlikely to occur in natural video,
108 ; and it's even more unlikely to not have any alternative mvs/modes with lower cost.
118 %elif cpuflag(mmxext)
136 mova [%1+mmsize*0], %2
137 mova [%1+mmsize*1], %3
138 mova [%1+mmsize*2], %4
139 mova [%1+mmsize*3], %5
143 mova %2, [%1+mmsize*0]
144 mova %3, [%1+mmsize*1]
145 mova %4, [%1+mmsize*2]
146 mova %5, [%1+mmsize*3]
149 %macro hadamard8_16_wrapper 2
150 cglobal hadamard8_diff, 4, 4, %1
152 %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
155 call hadamard8x8_diff %+ SUFFIX
161 cglobal hadamard8_diff16, 5, 6, %1
163 %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
167 call hadamard8x8_diff %+ SUFFIX
172 call hadamard8x8_diff %+ SUFFIX
180 call hadamard8x8_diff %+ SUFFIX
185 call hadamard8x8_diff %+ SUFFIX
196 %macro HADAMARD8_DIFF 0-1
198 hadamard8x8_diff %+ SUFFIX:
200 DIFF_PIXELS_8 r1, r2, 0, r3, r0, rsp+gprsize
203 TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8
205 TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, [rsp+gprsize], [rsp+mmsize+gprsize]
208 ABS_SUM_8x8 rsp+gprsize
213 hadamard8_16_wrapper %1, 3
216 ; int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,
217 ; uint8_t *src2, int stride, int h)
218 ; r0 = void *s = unused, int h = unused (always 8)
219 ; note how r1, r2 and r3 are not clobbered in this function, so 16x16
220 ; can simply call this 2x2x (and that's why we access rsp+gprsize
221 ; everywhere, which is rsp of calling func
222 hadamard8x8_diff %+ SUFFIX:
226 DIFF_PIXELS_8 r1, r2, 0, r3, r0, rsp+gprsize+0x60
228 mova [rsp+gprsize+0x60], m7
229 TRANSPOSE4x4W 0, 1, 2, 3, 7
230 STORE4 rsp+gprsize, m0, m1, m2, m3
231 mova m7, [rsp+gprsize+0x60]
232 TRANSPOSE4x4W 4, 5, 6, 7, 0
233 STORE4 rsp+gprsize+0x40, m4, m5, m6, m7
236 DIFF_PIXELS_8 r1, r2, 4, r3, r0, rsp+gprsize+0x60
238 mova [rsp+gprsize+0x60], m7
239 TRANSPOSE4x4W 0, 1, 2, 3, 7
240 STORE4 rsp+gprsize+0x20, m0, m1, m2, m3
241 mova m7, [rsp+gprsize+0x60]
242 TRANSPOSE4x4W 4, 5, 6, 7, 0
244 LOAD4 rsp+gprsize+0x40, m0, m1, m2, m3
246 ABS_SUM_8x8_32 rsp+gprsize+0x60
247 mova [rsp+gprsize+0x60], m0
249 LOAD4 rsp+gprsize , m0, m1, m2, m3
250 LOAD4 rsp+gprsize+0x20, m4, m5, m6, m7
252 ABS_SUM_8x8_32 rsp+gprsize
253 paddusw m0, [rsp+gprsize+0x60]
259 hadamard8_16_wrapper 0, 14
271 %define ABS_SUM_8x8 ABS_SUM_8x8_64
273 %define ABS_SUM_8x8 ABS_SUM_8x8_32
278 %define ABS_SUM_8x8 ABS_SUM_8x8_64
281 ; int ff_sse*_*(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
282 ; int line_size, int h)
284 %macro SUM_SQUARED_ERRORS 1
285 cglobal sse%1, 5,5,8, v, pix1, pix2, lsize, h
289 pxor m0, m0 ; mm0 = 0
290 pxor m7, m7 ; mm7 holds the sum
292 .next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned
293 movu m1, [pix1q] ; m1 = pix1[0][0-15], [0-7] for mmx
294 movu m2, [pix2q] ; m2 = pix2[0][0-15], [0-7] for mmx
296 movu m3, [pix1q+lsizeq] ; m3 = pix1[1][0-15], [0-7] for mmx
297 movu m4, [pix2q+lsizeq] ; m4 = pix2[1][0-15], [0-7] for mmx
298 %else ; %1 / 2 == mmsize; mmx only
299 mova m3, [pix1q+8] ; m3 = pix1[0][8-15]
300 mova m4, [pix2q+8] ; m4 = pix2[0][8-15]
303 ; todo: mm1-mm2, mm3-mm4
304 ; algo: subtract mm1 from mm2 with saturation and vice versa
305 ; OR the result to get the absolute difference
316 ; now convert to 16-bit vectors so we can square them
322 punpcklbw m1, m0 ; mm1 not spread over (mm1,mm2)
323 punpcklbw m3, m0 ; mm4 not spread over (mm3,mm4)
336 lea pix1q, [pix1q + 2*lsizeq]
337 lea pix2q, [pix2q + 2*lsizeq]
346 movd eax, m7 ; return value
354 SUM_SQUARED_ERRORS 16
357 SUM_SQUARED_ERRORS 16
360 ; void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size)
361 cglobal get_pixels, 3,4
385 cglobal get_pixels, 3, 4, 5
417 ; void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2,
419 cglobal diff_pixels, 4,5
444 cglobal diff_pixels, 4, 5, 5
468 ; int ff_pix_sum16_mmx(uint8_t *pix, int line_size)
469 ; %1 = number of xmm registers used
470 ; %2 = number of loops
471 ; %3 = number of GPRs used
473 cglobal pix_sum16, 2, %3, %1
485 vphaddubq m1, [r0+r1]
486 vphaddubq m2, [r0+r1*2]
487 vphaddubq m3, [r0+r3]
499 %endif ; cpuflag(xop)
522 PIX_SUM16 0, 16, 3, 0
525 %if HAVE_XOP_EXTERNAL
530 ; int ff_pix_norm1_mmx(uint8_t *pix, int line_size)
531 ; %1 = number of xmm registers used
532 ; %2 = number of loops
534 cglobal pix_norm1, 2, 3, %1
575 ;-----------------------------------------------
576 ;int ff_sum_abs_dctelem(int16_t *block)
577 ;-----------------------------------------------
578 ; %1 = number of xmm registers used
579 ; %2 = number of inline loops
581 %macro SUM_ABS_DCTELEM 2
582 cglobal sum_abs_dctelem, 1, 1, %1, block
587 mova m2, [blockq+mmsize*(0+%%i)]
588 mova m3, [blockq+mmsize*(1+%%i)]
589 mova m4, [blockq+mmsize*(2+%%i)]
590 mova m5, [blockq+mmsize*(3+%%i)]
612 ;------------------------------------------------------------------------------
613 ; int ff_hf_noise*_mmx(uint8_t *pix1, int lsize, int h)
614 ;------------------------------------------------------------------------------
616 %macro HF_NOISE_PART1 5
637 %macro HF_NOISE_PART2 4
654 cglobal hf_noise%1, 3,3,0, pix1, lsize, h
655 movsxdifnidn lsizeq, lsized
659 HF_NOISE_PART1 %1, 0, 1, 2, 3
661 HF_NOISE_PART1 %1, 4, 1, 5, 3
662 HF_NOISE_PART2 0, 2, 4, 5
665 HF_NOISE_PART1 %1, 0, 1, 2, 3
666 HF_NOISE_PART2 4, 5, 0, 2
668 HF_NOISE_PART1 %1, 4, 1, 5, 3
669 HF_NOISE_PART2 0, 2, 4, 5
681 movd eax, m0 ; eax = result of hf_noise8;
682 REP_RET ; return eax;