]> git.sesse.net Git - ffmpeg/blob - libavcodec/x86/dsputilenc.asm
avcodec/on2avc: Fix out of array access
[ffmpeg] / libavcodec / x86 / dsputilenc.asm
1 ;*****************************************************************************
2 ;* MMX optimized DSP utils
3 ;*****************************************************************************
4 ;* Copyright (c) 2000, 2001 Fabrice Bellard
5 ;* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 ;*
7 ;* This file is part of FFmpeg.
8 ;*
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.
13 ;*
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.
18 ;*
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 ;*****************************************************************************
23
24 %include "libavutil/x86/x86util.asm"
25
26 SECTION_RODATA
27
28 cextern pw_1
29
30 SECTION .text
31
32 %macro DIFF_PIXELS_1 4
33     movh            %1, %3
34     movh            %2, %4
35     punpcklbw       %2, %1
36     punpcklbw       %1, %1
37     psubw           %1, %2
38 %endmacro
39
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]
47     add             %1, %5
48     add             %2, %5
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]
53 %ifdef m8
54     DIFF_PIXELS_1   m7, m8, [%1+%4*4+%3], [%2+%4*4+%3]
55 %else
56     mova          [%6], m0
57     DIFF_PIXELS_1   m7, m0, [%1+%4*4+%3], [%2+%4*4+%3]
58     mova            m0, [%6]
59 %endif
60     sub             %1, %5
61     sub             %2, %5
62 %endmacro
63
64 %macro HADAMARD8 0
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
71 %endmacro
72
73 %macro ABS1_SUM 3
74     ABS1            %1, %2
75     paddusw         %3, %1
76 %endmacro
77
78 %macro ABS2_SUM 6
79     ABS2            %1, %2, %3, %4
80     paddusw         %5, %1
81     paddusw         %6, %2
82 %endmacro
83
84 %macro ABS_SUM_8x8_64 1
85     ABS2            m0, m1, m8, m9
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
89     paddusw         m0, m1
90 %endmacro
91
92 %macro ABS_SUM_8x8_32 1
93     mova          [%1], m7
94     ABS1            m0, m7
95     ABS1            m1, m7
96     ABS1_SUM        m2, m7, m0
97     ABS1_SUM        m3, m7, m1
98     ABS1_SUM        m4, m7, m0
99     ABS1_SUM        m5, m7, m1
100     ABS1_SUM        m6, m7, m0
101     mova            m2, [%1]
102     ABS1_SUM        m2, m7, m1
103     paddusw         m0, m1
104 %endmacro
105
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.
109 %macro HSUM 3
110 %if cpuflag(sse2)
111     movhlps         %2, %1
112     paddusw         %1, %2
113     pshuflw         %2, %1, 0xE
114     paddusw         %1, %2
115     pshuflw         %2, %1, 0x1
116     paddusw         %1, %2
117     movd            %3, %1
118 %elif cpuflag(mmxext)
119     pshufw          %2, %1, 0xE
120     paddusw         %1, %2
121     pshufw          %2, %1, 0x1
122     paddusw         %1, %2
123     movd            %3, %1
124 %elif cpuflag(mmx)
125     mova            %2, %1
126     psrlq           %1, 32
127     paddusw         %1, %2
128     mova            %2, %1
129     psrlq           %1, 16
130     paddusw         %1, %2
131     movd            %3, %1
132 %endif
133 %endmacro
134
135 %macro STORE4 5
136     mova [%1+mmsize*0], %2
137     mova [%1+mmsize*1], %3
138     mova [%1+mmsize*2], %4
139     mova [%1+mmsize*3], %5
140 %endmacro
141
142 %macro LOAD4 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]
147 %endmacro
148
149 %macro hadamard8_16_wrapper 2
150 cglobal hadamard8_diff, 4, 4, %1
151 %ifndef m8
152     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
153     SUB            rsp, pad
154 %endif
155     call hadamard8x8_diff %+ SUFFIX
156 %ifndef m8
157     ADD            rsp, pad
158 %endif
159     RET
160
161 cglobal hadamard8_diff16, 5, 6, %1
162 %ifndef m8
163     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
164     SUB            rsp, pad
165 %endif
166
167     call hadamard8x8_diff %+ SUFFIX
168     mov            r5d, eax
169
170     add             r1, 8
171     add             r2, 8
172     call hadamard8x8_diff %+ SUFFIX
173     add            r5d, eax
174
175     cmp            r4d, 16
176     jne .done
177
178     lea             r1, [r1+r3*8-8]
179     lea             r2, [r2+r3*8-8]
180     call hadamard8x8_diff %+ SUFFIX
181     add            r5d, eax
182
183     add             r1, 8
184     add             r2, 8
185     call hadamard8x8_diff %+ SUFFIX
186     add            r5d, eax
187
188 .done:
189     mov            eax, r5d
190 %ifndef m8
191     ADD            rsp, pad
192 %endif
193     RET
194 %endmacro
195
196 %macro HADAMARD8_DIFF 0-1
197 %if cpuflag(sse2)
198 hadamard8x8_diff %+ SUFFIX:
199     lea                          r0, [r3*3]
200     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize
201     HADAMARD8
202 %if ARCH_X86_64
203     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7,  8
204 %else
205     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7, [rsp+gprsize], [rsp+mmsize+gprsize]
206 %endif
207     HADAMARD8
208     ABS_SUM_8x8         rsp+gprsize
209     HSUM                        m0, m1, eax
210     and                         eax, 0xFFFF
211     ret
212
213 hadamard8_16_wrapper %1, 3
214 %elif cpuflag(mmx)
215 ALIGN 16
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:
223     lea                          r0, [r3*3]
224
225     ; first 4x8 pixels
226     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize+0x60
227     HADAMARD8
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
234
235     ; second 4x8 pixels
236     DIFF_PIXELS_8                r1, r2,  4, r3, r0, rsp+gprsize+0x60
237     HADAMARD8
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
243
244     LOAD4          rsp+gprsize+0x40, m0, m1, m2, m3
245     HADAMARD8
246     ABS_SUM_8x8_32 rsp+gprsize+0x60
247     mova         [rsp+gprsize+0x60], m0
248
249     LOAD4          rsp+gprsize     , m0, m1, m2, m3
250     LOAD4          rsp+gprsize+0x20, m4, m5, m6, m7
251     HADAMARD8
252     ABS_SUM_8x8_32 rsp+gprsize
253     paddusw                      m0, [rsp+gprsize+0x60]
254
255     HSUM                         m0, m1, eax
256     and                         rax, 0xFFFF
257     ret
258
259 hadamard8_16_wrapper 0, 14
260 %endif
261 %endmacro
262
263 INIT_MMX mmx
264 HADAMARD8_DIFF
265
266 INIT_MMX mmxext
267 HADAMARD8_DIFF
268
269 INIT_XMM sse2
270 %if ARCH_X86_64
271 %define ABS_SUM_8x8 ABS_SUM_8x8_64
272 %else
273 %define ABS_SUM_8x8 ABS_SUM_8x8_32
274 %endif
275 HADAMARD8_DIFF 10
276
277 INIT_XMM ssse3
278 %define ABS_SUM_8x8 ABS_SUM_8x8_64
279 HADAMARD8_DIFF 9
280
281 ; int ff_sse*_*(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
282 ;               int line_size, int h)
283
284 %macro SUM_SQUARED_ERRORS 1
285 cglobal sse%1, 5,5,8, v, pix1, pix2, lsize, h
286 %if %1 == mmsize
287     shr       hd, 1
288 %endif
289     pxor      m0, m0         ; mm0 = 0
290     pxor      m7, m7         ; mm7 holds the sum
291
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
295 %if %1 == mmsize
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]
301 %endif
302
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
306     mova      m5, m1
307     mova      m6, m3
308     psubusb   m1, m2
309     psubusb   m3, m4
310     psubusb   m2, m5
311     psubusb   m4, m6
312
313     por       m2, m1
314     por       m4, m3
315
316     ; now convert to 16-bit vectors so we can square them
317     mova      m1, m2
318     mova      m3, m4
319
320     punpckhbw m2, m0
321     punpckhbw m4, m0
322     punpcklbw m1, m0         ; mm1 not spread over (mm1,mm2)
323     punpcklbw m3, m0         ; mm4 not spread over (mm3,mm4)
324
325     pmaddwd   m2, m2
326     pmaddwd   m4, m4
327     pmaddwd   m1, m1
328     pmaddwd   m3, m3
329
330     paddd     m1, m2
331     paddd     m3, m4
332     paddd     m7, m1
333     paddd     m7, m3
334
335 %if %1 == mmsize
336     lea    pix1q, [pix1q + 2*lsizeq]
337     lea    pix2q, [pix2q + 2*lsizeq]
338 %else
339     add    pix1q, lsizeq
340     add    pix2q, lsizeq
341 %endif
342     dec       hd
343     jnz .next2lines
344
345     HADDD     m7, m1
346     movd     eax, m7         ; return value
347     RET
348 %endmacro
349
350 INIT_MMX mmx
351 SUM_SQUARED_ERRORS 8
352
353 INIT_MMX mmx
354 SUM_SQUARED_ERRORS 16
355
356 INIT_XMM sse2
357 SUM_SQUARED_ERRORS 16
358
359 INIT_MMX mmx
360 ; void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size)
361 cglobal get_pixels, 3,4
362     movsxdifnidn r2, r2d
363     add          r0, 128
364     mov          r3, -128
365     pxor         m7, m7
366 .loop:
367     mova         m0, [r1]
368     mova         m2, [r1+r2]
369     mova         m1, m0
370     mova         m3, m2
371     punpcklbw    m0, m7
372     punpckhbw    m1, m7
373     punpcklbw    m2, m7
374     punpckhbw    m3, m7
375     mova [r0+r3+ 0], m0
376     mova [r0+r3+ 8], m1
377     mova [r0+r3+16], m2
378     mova [r0+r3+24], m3
379     lea          r1, [r1+r2*2]
380     add          r3, 32
381     js .loop
382     REP_RET
383
384 INIT_XMM sse2
385 cglobal get_pixels, 3, 4, 5
386     movsxdifnidn r2, r2d
387     lea          r3, [r2*3]
388     pxor         m4, m4
389     movh         m0, [r1]
390     movh         m1, [r1+r2]
391     movh         m2, [r1+r2*2]
392     movh         m3, [r1+r3]
393     lea          r1, [r1+r2*4]
394     punpcklbw    m0, m4
395     punpcklbw    m1, m4
396     punpcklbw    m2, m4
397     punpcklbw    m3, m4
398     mova       [r0], m0
399     mova  [r0+0x10], m1
400     mova  [r0+0x20], m2
401     mova  [r0+0x30], m3
402     movh         m0, [r1]
403     movh         m1, [r1+r2*1]
404     movh         m2, [r1+r2*2]
405     movh         m3, [r1+r3]
406     punpcklbw    m0, m4
407     punpcklbw    m1, m4
408     punpcklbw    m2, m4
409     punpcklbw    m3, m4
410     mova  [r0+0x40], m0
411     mova  [r0+0x50], m1
412     mova  [r0+0x60], m2
413     mova  [r0+0x70], m3
414     RET
415
416 INIT_MMX mmx
417 ; void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2,
418 ;                         int stride);
419 cglobal diff_pixels, 4,5
420     movsxdifnidn r3, r3d
421     pxor         m7, m7
422     add          r0,  128
423     mov          r4, -128
424 .loop:
425     mova         m0, [r1]
426     mova         m2, [r2]
427     mova         m1, m0
428     mova         m3, m2
429     punpcklbw    m0, m7
430     punpckhbw    m1, m7
431     punpcklbw    m2, m7
432     punpckhbw    m3, m7
433     psubw        m0, m2
434     psubw        m1, m3
435     mova  [r0+r4+0], m0
436     mova  [r0+r4+8], m1
437     add          r1, r3
438     add          r2, r3
439     add          r4, 16
440     jne .loop
441     REP_RET
442
443 INIT_XMM sse2
444 cglobal diff_pixels, 4, 5, 5
445     movsxdifnidn r3, r3d
446     pxor         m4, m4
447     add          r0,  128
448     mov          r4, -128
449 .loop:
450     movh         m0, [r1]
451     movh         m2, [r2]
452     movh         m1, [r1+r3]
453     movh         m3, [r2+r3]
454     punpcklbw    m0, m4
455     punpcklbw    m1, m4
456     punpcklbw    m2, m4
457     punpcklbw    m3, m4
458     psubw        m0, m2
459     psubw        m1, m3
460     mova [r0+r4+0 ], m0
461     mova [r0+r4+16], m1
462     lea          r1, [r1+r3*2]
463     lea          r2, [r2+r3*2]
464     add          r4, 32
465     jne .loop
466     RET
467
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
472 %macro PIX_SUM16 4
473 cglobal pix_sum16, 2, %3, %1
474     movsxdifnidn r1, r1d
475     mov          r2, %2
476 %if cpuflag(xop)
477     lea          r3, [r1*3]
478 %else
479     pxor         m5, m5
480 %endif
481     pxor         m4, m4
482 .loop:
483 %if cpuflag(xop)
484     vphaddubq    m0, [r0]
485     vphaddubq    m1, [r0+r1]
486     vphaddubq    m2, [r0+r1*2]
487     vphaddubq    m3, [r0+r3]
488 %else
489     mova         m0, [r0]
490 %if mmsize == 8
491     mova         m1, [r0+8]
492 %else
493     mova         m1, [r0+r1]
494 %endif
495     punpckhbw    m2, m0, m5
496     punpcklbw    m0, m5
497     punpckhbw    m3, m1, m5
498     punpcklbw    m1, m5
499 %endif ; cpuflag(xop)
500     paddw        m1, m0
501     paddw        m3, m2
502     paddw        m3, m1
503     paddw        m4, m3
504 %if mmsize == 8
505     add          r0, r1
506 %else
507     lea          r0, [r0+r1*%4]
508 %endif
509     dec r2
510     jne .loop
511 %if cpuflag(xop)
512     pshufd       m0, m4, q0032
513     paddd        m4, m0
514 %else
515     HADDW        m4, m5
516 %endif
517     movd        eax, m4
518     RET
519 %endmacro
520
521 INIT_MMX mmx
522 PIX_SUM16 0, 16, 3, 0
523 INIT_XMM sse2
524 PIX_SUM16 6, 8,  3, 2
525 %if HAVE_XOP_EXTERNAL
526 INIT_XMM xop
527 PIX_SUM16 5, 4,  4, 4
528 %endif
529
530 ; int ff_pix_norm1_mmx(uint8_t *pix, int line_size)
531 ; %1 = number of xmm registers used
532 ; %2 = number of loops
533 %macro PIX_NORM1 2
534 cglobal pix_norm1, 2, 3, %1
535     movsxdifnidn r1, r1d
536     mov          r2, %2
537     pxor         m0, m0
538     pxor         m5, m5
539 .loop:
540     mova         m2, [r0+0]
541 %if mmsize == 8
542     mova         m3, [r0+8]
543 %else
544     mova         m3, [r0+r1]
545 %endif
546     punpckhbw    m1, m2, m0
547     punpcklbw    m2, m0
548     punpckhbw    m4, m3, m0
549     punpcklbw    m3, m0
550     pmaddwd      m1, m1
551     pmaddwd      m2, m2
552     pmaddwd      m3, m3
553     pmaddwd      m4, m4
554     paddd        m2, m1
555     paddd        m4, m3
556     paddd        m5, m2
557     paddd        m5, m4
558 %if mmsize == 8
559     add          r0, r1
560 %else
561     lea          r0, [r0+r1*2]
562 %endif
563     dec r2
564     jne .loop
565     HADDD        m5, m1
566     movd        eax, m5
567     RET
568 %endmacro
569
570 INIT_MMX mmx
571 PIX_NORM1 0, 16
572 INIT_XMM sse2
573 PIX_NORM1 6, 8
574
575 ;-----------------------------------------------
576 ;int ff_sum_abs_dctelem(int16_t *block)
577 ;-----------------------------------------------
578 ; %1 = number of xmm registers used
579 ; %2 = number of inline loops
580
581 %macro SUM_ABS_DCTELEM 2
582 cglobal sum_abs_dctelem, 1, 1, %1, block
583     pxor    m0, m0
584     pxor    m1, m1
585 %assign %%i 0
586 %rep %2
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)]
591     ABS1_SUM  m2, m6, m0
592     ABS1_SUM  m3, m6, m1
593     ABS1_SUM  m4, m6, m0
594     ABS1_SUM  m5, m6, m1
595 %assign %%i %%i+4
596 %endrep
597     paddusw m0, m1
598     HSUM    m0, m1, eax
599     and     eax, 0xFFFF
600     RET
601 %endmacro
602
603 INIT_MMX mmx
604 SUM_ABS_DCTELEM 0, 4
605 INIT_MMX mmxext
606 SUM_ABS_DCTELEM 0, 4
607 INIT_XMM sse2
608 SUM_ABS_DCTELEM 7, 2
609 INIT_XMM ssse3
610 SUM_ABS_DCTELEM 6, 2
611
612 ;------------------------------------------------------------------------------
613 ; int ff_hf_noise*_mmx(uint8_t *pix1, int lsize, int h)
614 ;------------------------------------------------------------------------------
615 ; %1 = 8/16. %2-5=m#
616 %macro HF_NOISE_PART1 5
617     mova      m%2, [pix1q]
618 %if %1 == 8
619     mova      m%3, m%2
620     psllq     m%2, 8
621     psrlq     m%3, 8
622     psrlq     m%2, 8
623 %else
624     mova      m%3, [pix1q+1]
625 %endif
626     mova      m%4, m%2
627     mova      m%5, m%3
628     punpcklbw m%2, m7
629     punpcklbw m%3, m7
630     punpckhbw m%4, m7
631     punpckhbw m%5, m7
632     psubw     m%2, m%3
633     psubw     m%4, m%5
634 %endmacro
635
636 ; %1-2 = m#
637 %macro HF_NOISE_PART2 4
638     psubw     m%1, m%3
639     psubw     m%2, m%4
640     pxor       m3, m3
641     pxor       m1, m1
642     pcmpgtw    m3, m%1
643     pcmpgtw    m1, m%2
644     pxor      m%1, m3
645     pxor      m%2, m1
646     psubw     m%1, m3
647     psubw     m%2, m1
648     paddw     m%2, m%1
649     paddw      m6, m%2
650 %endmacro
651
652 ; %1 = 8/16
653 %macro HF_NOISE 1
654 cglobal hf_noise%1, 3,3,0, pix1, lsize, h
655     movsxdifnidn lsizeq, lsized
656     sub        hd, 2
657     pxor       m7, m7
658     pxor       m6, m6
659     HF_NOISE_PART1 %1, 0, 1, 2, 3
660     add     pix1q, lsizeq
661     HF_NOISE_PART1 %1, 4, 1, 5, 3
662     HF_NOISE_PART2     0, 2, 4, 5
663     add     pix1q, lsizeq
664 .loop:
665     HF_NOISE_PART1 %1, 0, 1, 2, 3
666     HF_NOISE_PART2     4, 5, 0, 2
667     add     pix1q, lsizeq
668     HF_NOISE_PART1 %1, 4, 1, 5, 3
669     HF_NOISE_PART2     0, 2, 4, 5
670     add     pix1q, lsizeq
671     sub        hd, 2
672         jne .loop
673
674     mova       m0, m6
675     punpcklwd  m0, m7
676     punpckhwd  m6, m7
677     paddd      m6, m0
678     mova       m0, m6
679     psrlq      m6, 32
680     paddd      m0, m6
681     movd      eax, m0   ; eax = result of hf_noise8;
682     REP_RET                 ; return eax;
683 %endmacro
684
685 INIT_MMX mmx
686 HF_NOISE 8
687 HF_NOISE 16