]> git.sesse.net Git - x264/blob - common/x86/mc-a2.asm
ad78dd6cb6b94f68cb21ccc12185cc070c0b9610
[x264] / common / x86 / mc-a2.asm
1 ;*****************************************************************************
2 ;* mc-a2.asm: x86 motion compensation
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2010 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Fiona Glaser <fiona@x264.com>
8 ;*          Holger Lubitz <holger@lubitz.org>
9 ;*          Mathieu Monnier <manao@melix.net>
10 ;*
11 ;* This program is free software; you can redistribute it and/or modify
12 ;* it under the terms of the GNU General Public License as published by
13 ;* the Free Software Foundation; either version 2 of the License, or
14 ;* (at your option) any later version.
15 ;*
16 ;* This program 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
19 ;* GNU General Public License for more details.
20 ;*
21 ;* You should have received a copy of the GNU General Public License
22 ;* along with this program; if not, write to the Free Software
23 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
24 ;*
25 ;* This program is also available under a commercial proprietary license.
26 ;* For more information, contact us at licensing@x264.com.
27 ;*****************************************************************************
28
29 %include "x86inc.asm"
30 %include "x86util.asm"
31
32 SECTION_RODATA
33
34 filt_mul20: times 16 db 20
35 filt_mul15: times 8 db 1, -5
36 filt_mul51: times 8 db -5, 1
37 hpel_shuf: db 0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15
38 deinterleave_shuf: db 0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15
39
40 SECTION .text
41
42 cextern pw_1
43 cextern pw_16
44 cextern pw_32
45 cextern pw_00ff
46 cextern pw_3fff
47 cextern pd_128
48
49 %macro LOAD_ADD 4
50     movh       %4, %3
51     movh       %1, %2
52     punpcklbw  %4, m0
53     punpcklbw  %1, m0
54     paddw      %1, %4
55 %endmacro
56
57 %macro LOAD_ADD_2 6
58     mova       %5, %3
59     mova       %1, %4
60     mova       %6, %5
61     mova       %2, %1
62     punpcklbw  %5, m0
63     punpcklbw  %1, m0
64     punpckhbw  %6, m0
65     punpckhbw  %2, m0
66     paddw      %1, %5
67     paddw      %2, %6
68 %endmacro
69
70 %macro FILT_V2 6
71     psubw  %1, %2  ; a-b
72     psubw  %4, %5
73     psubw  %2, %3  ; b-c
74     psubw  %5, %6
75     psllw  %2, 2
76     psllw  %5, 2
77     psubw  %1, %2  ; a-5*b+4*c
78     psllw  %3, 4
79     psubw  %4, %5
80     psllw  %6, 4
81     paddw  %1, %3  ; a-5*b+20*c
82     paddw  %4, %6
83 %endmacro
84
85 %macro FILT_H 3
86     psubw  %1, %2  ; a-b
87     psraw  %1, 2   ; (a-b)/4
88     psubw  %1, %2  ; (a-b)/4-b
89     paddw  %1, %3  ; (a-b)/4-b+c
90     psraw  %1, 2   ; ((a-b)/4-b+c)/4
91     paddw  %1, %3  ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
92 %endmacro
93
94 %macro FILT_H2 6
95     psubw  %1, %2
96     psubw  %4, %5
97     psraw  %1, 2
98     psraw  %4, 2
99     psubw  %1, %2
100     psubw  %4, %5
101     paddw  %1, %3
102     paddw  %4, %6
103     psraw  %1, 2
104     psraw  %4, 2
105     paddw  %1, %3
106     paddw  %4, %6
107 %endmacro
108
109 %macro FILT_PACK 4
110     paddw     %1, %4
111     paddw     %2, %4
112     psraw     %1, %3
113     psraw     %2, %3
114     packuswb  %1, %2
115 %endmacro
116
117 ;The hpel_filter routines use non-temporal writes for output.
118 ;The following defines may be uncommented for testing.
119 ;Doing the hpel_filter temporal may be a win if the last level cache
120 ;is big enough (preliminary benching suggests on the order of 4* framesize).
121
122 ;%define movntq movq
123 ;%define movntps movaps
124 ;%define sfence
125
126 INIT_MMX
127
128 %macro HPEL_V 1-2 0
129 ;-----------------------------------------------------------------------------
130 ; void hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width );
131 ;-----------------------------------------------------------------------------
132 cglobal hpel_filter_v_%1, 5,6,%2
133 %ifdef WIN64
134     movsxd   r4, r4d
135 %endif
136     lea r5, [r1+r3]
137     sub r1, r3
138     sub r1, r3
139     add r0, r4
140     lea r2, [r2+r4*2]
141     neg r4
142 %ifnidn %1, ssse3
143     pxor m0, m0
144 %else
145     mova m0, [filt_mul15]
146 %endif
147 .loop:
148 %ifidn %1, ssse3
149     mova m1, [r1]
150     mova m4, [r1+r3]
151     mova m2, [r5+r3*2]
152     mova m5, [r5+r3]
153     mova m3, [r1+r3*2]
154     mova m6, [r5]
155     SBUTTERFLY bw, 1, 4, 7
156     SBUTTERFLY bw, 2, 5, 7
157     SBUTTERFLY bw, 3, 6, 7
158     pmaddubsw m1, m0
159     pmaddubsw m4, m0
160     pmaddubsw m2, m0
161     pmaddubsw m5, m0
162     pmaddubsw m3, [filt_mul20]
163     pmaddubsw m6, [filt_mul20]
164     paddw  m1, m2
165     paddw  m4, m5
166     paddw  m1, m3
167     paddw  m4, m6
168 %else
169     LOAD_ADD_2 m1, m4, [r1     ], [r5+r3*2], m6, m7            ; a0 / a1
170     LOAD_ADD_2 m2, m5, [r1+r3  ], [r5+r3  ], m6, m7            ; b0 / b1
171     LOAD_ADD   m3,     [r1+r3*2], [r5     ], m7                ; c0
172     LOAD_ADD   m6,     [r1+r3*2+mmsize/2], [r5+mmsize/2], m7 ; c1
173     FILT_V2 m1, m2, m3, m4, m5, m6
174 %endif
175     mova      m7, [pw_16]
176     mova      [r2+r4*2], m1
177     mova      [r2+r4*2+mmsize], m4
178     FILT_PACK m1, m4, 5, m7
179     movnta    [r0+r4], m1
180     add r1, mmsize
181     add r5, mmsize
182     add r4, mmsize
183     jl .loop
184     REP_RET
185 %endmacro
186 HPEL_V mmxext
187
188 ;-----------------------------------------------------------------------------
189 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
190 ;-----------------------------------------------------------------------------
191 cglobal hpel_filter_c_mmxext, 3,3
192     add r0, r2
193     lea r1, [r1+r2*2]
194     neg r2
195     %define src r1+r2*2
196     movq m7, [pw_32]
197 .loop:
198     movq   m1, [src-4]
199     movq   m2, [src-2]
200     movq   m3, [src  ]
201     movq   m4, [src+4]
202     movq   m5, [src+6]
203     paddw  m3, [src+2]  ; c0
204     paddw  m2, m4       ; b0
205     paddw  m1, m5       ; a0
206     movq   m6, [src+8]
207     paddw  m4, [src+14] ; a1
208     paddw  m5, [src+12] ; b1
209     paddw  m6, [src+10] ; c1
210     FILT_H2 m1, m2, m3, m4, m5, m6
211     FILT_PACK m1, m4, 6, m7
212     movntq [r0+r2], m1
213     add r2, 8
214     jl .loop
215     REP_RET
216
217 ;-----------------------------------------------------------------------------
218 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
219 ;-----------------------------------------------------------------------------
220 cglobal hpel_filter_h_mmxext, 3,3
221     add r0, r2
222     add r1, r2
223     neg r2
224     %define src r1+r2
225     pxor m0, m0
226 .loop:
227     movd       m1, [src-2]
228     movd       m2, [src-1]
229     movd       m3, [src  ]
230     movd       m6, [src+1]
231     movd       m4, [src+2]
232     movd       m5, [src+3]
233     punpcklbw  m1, m0
234     punpcklbw  m2, m0
235     punpcklbw  m3, m0
236     punpcklbw  m6, m0
237     punpcklbw  m4, m0
238     punpcklbw  m5, m0
239     paddw      m3, m6 ; c0
240     paddw      m2, m4 ; b0
241     paddw      m1, m5 ; a0
242     movd       m7, [src+7]
243     movd       m6, [src+6]
244     punpcklbw  m7, m0
245     punpcklbw  m6, m0
246     paddw      m4, m7 ; c1
247     paddw      m5, m6 ; b1
248     movd       m7, [src+5]
249     movd       m6, [src+4]
250     punpcklbw  m7, m0
251     punpcklbw  m6, m0
252     paddw      m6, m7 ; a1
253     movq       m7, [pw_1]
254     FILT_H2 m1, m2, m3, m4, m5, m6
255     FILT_PACK m1, m4, 1, m7
256     movntq     [r0+r2], m1
257     add r2, 8
258     jl .loop
259     REP_RET
260
261 INIT_XMM
262
263 %macro HPEL_C 1
264 ;-----------------------------------------------------------------------------
265 ; void hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
266 ;-----------------------------------------------------------------------------
267 cglobal hpel_filter_c_%1, 3,3,9
268     add r0, r2
269     lea r1, [r1+r2*2]
270     neg r2
271     %define src r1+r2*2
272 %ifnidn %1, sse2
273     mova    m7, [pw_32]
274     %define tpw_32 m7
275 %elifdef ARCH_X86_64
276     mova    m8, [pw_32]
277     %define tpw_32 m8
278 %else
279     %define tpw_32 [pw_32]
280 %endif
281 %ifidn %1,sse2_misalign
282 .loop:
283     movu    m4, [src-4]
284     movu    m5, [src-2]
285     mova    m6, [src]
286     movu    m3, [src+12]
287     movu    m2, [src+14]
288     mova    m1, [src+16]
289     paddw   m4, [src+6]
290     paddw   m5, [src+4]
291     paddw   m6, [src+2]
292     paddw   m3, [src+22]
293     paddw   m2, [src+20]
294     paddw   m1, [src+18]
295     FILT_H2 m4, m5, m6, m3, m2, m1
296 %else
297     mova      m0, [src-16]
298     mova      m1, [src]
299 .loop:
300     mova      m2, [src+16]
301     mova      m4, m1
302     PALIGNR   m4, m0, 12, m7
303     mova      m5, m1
304     PALIGNR   m5, m0, 14, m0
305     mova      m0, m2
306     PALIGNR   m0, m1, 6, m7
307     paddw     m4, m0
308     mova      m0, m2
309     PALIGNR   m0, m1, 4, m7
310     paddw     m5, m0
311     mova      m6, m2
312     PALIGNR   m6, m1, 2, m7
313     paddw     m6, m1
314     FILT_H    m4, m5, m6
315
316     mova      m0, m2
317     mova      m5, m2
318     PALIGNR   m2, m1, 12, m7
319     PALIGNR   m5, m1, 14, m1
320     mova      m1, [src+32]
321     mova      m3, m1
322     PALIGNR   m3, m0, 6, m7
323     paddw     m3, m2
324     mova      m6, m1
325     PALIGNR   m6, m0, 4, m7
326     paddw     m5, m6
327     mova      m6, m1
328     PALIGNR   m6, m0, 2, m7
329     paddw     m6, m0
330     FILT_H    m3, m5, m6
331 %endif
332     FILT_PACK m4, m3, 6, tpw_32
333     movntps [r0+r2], m4
334     add r2, 16
335     jl .loop
336     REP_RET
337 %endmacro
338
339 ;-----------------------------------------------------------------------------
340 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
341 ;-----------------------------------------------------------------------------
342 cglobal hpel_filter_h_sse2, 3,3,8
343     add r0, r2
344     add r1, r2
345     neg r2
346     %define src r1+r2
347     pxor m0, m0
348 .loop:
349     movh       m1, [src-2]
350     movh       m2, [src-1]
351     movh       m3, [src  ]
352     movh       m4, [src+1]
353     movh       m5, [src+2]
354     movh       m6, [src+3]
355     punpcklbw  m1, m0
356     punpcklbw  m2, m0
357     punpcklbw  m3, m0
358     punpcklbw  m4, m0
359     punpcklbw  m5, m0
360     punpcklbw  m6, m0
361     paddw      m3, m4 ; c0
362     paddw      m2, m5 ; b0
363     paddw      m1, m6 ; a0
364     movh       m4, [src+6]
365     movh       m5, [src+7]
366     movh       m6, [src+10]
367     movh       m7, [src+11]
368     punpcklbw  m4, m0
369     punpcklbw  m5, m0
370     punpcklbw  m6, m0
371     punpcklbw  m7, m0
372     paddw      m5, m6 ; b1
373     paddw      m4, m7 ; a1
374     movh       m6, [src+8]
375     movh       m7, [src+9]
376     punpcklbw  m6, m0
377     punpcklbw  m7, m0
378     paddw      m6, m7 ; c1
379     mova       m7, [pw_1] ; FIXME xmm8
380     FILT_H2 m1, m2, m3, m4, m5, m6
381     FILT_PACK m1, m4, 1, m7
382     movntps    [r0+r2], m1
383     add r2, 16
384     jl .loop
385     REP_RET
386
387 %ifndef ARCH_X86_64
388 ;-----------------------------------------------------------------------------
389 ; void hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
390 ;-----------------------------------------------------------------------------
391 cglobal hpel_filter_h_ssse3, 3,3
392     add r0, r2
393     add r1, r2
394     neg r2
395     %define src r1+r2
396     mova      m0, [src-16]
397     mova      m1, [src]
398     mova      m7, [pw_16]
399 .loop:
400     mova      m2, [src+16]
401     mova      m3, m1
402     palignr   m3, m0, 14
403     mova      m4, m1
404     palignr   m4, m0, 15
405     mova      m0, m2
406     palignr   m0, m1, 2
407     pmaddubsw m3, [filt_mul15]
408     pmaddubsw m4, [filt_mul15]
409     pmaddubsw m0, [filt_mul51]
410     mova      m5, m2
411     palignr   m5, m1, 1
412     mova      m6, m2
413     palignr   m6, m1, 3
414     paddw     m3, m0
415     mova      m0, m1
416     pmaddubsw m1, [filt_mul20]
417     pmaddubsw m5, [filt_mul20]
418     pmaddubsw m6, [filt_mul51]
419     paddw     m3, m1
420     paddw     m4, m5
421     paddw     m4, m6
422     FILT_PACK m3, m4, 5, m7
423     pshufb    m3, [hpel_shuf]
424     mova      m1, m2
425     movntps [r0+r2], m3
426     add r2, 16
427     jl .loop
428     RET
429 %endif
430
431 %define PALIGNR PALIGNR_MMX
432 %ifndef ARCH_X86_64
433 HPEL_C sse2
434 %endif
435 HPEL_V sse2, 8
436 HPEL_C sse2_misalign
437 %define PALIGNR PALIGNR_SSSE3
438 HPEL_C ssse3
439 HPEL_V ssse3
440
441 %ifdef ARCH_X86_64
442
443 %macro DO_FILT_V 6
444     ;The optimum prefetch distance is difficult to determine in checkasm:
445     ;any prefetch seems slower than not prefetching.
446     ;In real use, the prefetch seems to be a slight win.
447     ;+16 is picked somewhat arbitrarily here based on the fact that even one
448     ;loop iteration is going to take longer than the prefetch.
449     prefetcht0 [r1+r2*2+16]
450 %ifidn %6, ssse3
451     mova m1, [r3]
452     mova m2, [r3+r2]
453     mova %3, [r3+r2*2]
454     mova m3, [r1]
455     mova %1, [r1+r2]
456     mova %2, [r1+r2*2]
457     mova m4, m1
458     punpcklbw m1, m2
459     punpckhbw m4, m2
460     mova m2, %1
461     punpcklbw %1, %2
462     punpckhbw m2, %2
463     mova %2, m3
464     punpcklbw m3, %3
465     punpckhbw %2, %3
466
467     pmaddubsw m1, m12
468     pmaddubsw m4, m12
469     pmaddubsw %1, m0
470     pmaddubsw m2, m0
471     pmaddubsw m3, m14
472     pmaddubsw %2, m14
473
474     paddw m1, %1
475     paddw m4, m2
476     paddw m1, m3
477     paddw m4, %2
478 %else
479     LOAD_ADD_2 m1, m4, [r3     ], [r1+r2*2], m2, m5            ; a0 / a1
480     LOAD_ADD_2 m2, m5, [r3+r2  ], [r1+r2  ], m3, m6            ; b0 / b1
481     LOAD_ADD_2 m3, m6, [r3+r2*2], [r1     ], %3, %4            ; c0 / c1
482     packuswb %3, %4
483     FILT_V2 m1, m2, m3, m4, m5, m6
484 %endif
485     add       r3, 16
486     add       r1, 16
487     mova      %1, m1
488     mova      %2, m4
489     FILT_PACK m1, m4, 5, m15
490     movntps  [r11+r4+%5], m1
491 %endmacro
492
493 %macro FILT_C 4
494     mova      m1, %2
495     PALIGNR   m1, %1, 12, m2
496     mova      m2, %2
497     PALIGNR   m2, %1, 14, %1
498     mova      m3, %3
499     PALIGNR   m3, %2, 4, %1
500     mova      m4, %3
501     PALIGNR   m4, %2, 2, %1
502     paddw     m3, m2
503     mova      %1, %3
504     PALIGNR   %3, %2, 6, m2
505     paddw     m4, %2
506     paddw     %3, m1
507     FILT_H    %3, m3, m4
508 %endmacro
509
510 %macro DO_FILT_C 4
511     FILT_C %1, %2, %3, 6
512     FILT_C %2, %1, %4, 6
513     FILT_PACK %3, %4, 6, m15
514     movntps   [r5+r4], %3
515 %endmacro
516
517 %macro ADD8TO16 5
518     mova      %3, %1
519     mova      %4, %2
520     punpcklbw %1, %5
521     punpckhbw %2, %5
522     punpckhbw %3, %5
523     punpcklbw %4, %5
524     paddw     %2, %3
525     paddw     %1, %4
526 %endmacro
527
528 %macro DO_FILT_H 4
529     mova      m1, %2
530     PALIGNR   m1, %1, 14, m3
531     mova      m2, %2
532     PALIGNR   m2, %1, 15, m3
533     mova      m4, %3
534     PALIGNR   m4, %2, 1 , m3
535     mova      m5, %3
536     PALIGNR   m5, %2, 2 , m3
537     mova      m6, %3
538     PALIGNR   m6, %2, 3 , m3
539     mova      %1, %2
540 %ifidn %4, sse2
541     ADD8TO16  m1, m6, m12, m3, m0 ; a
542     ADD8TO16  m2, m5, m12, m3, m0 ; b
543     ADD8TO16  %2, m4, m12, m3, m0 ; c
544     FILT_V2   m1, m2, %2, m6, m5, m4
545     FILT_PACK m1, m6, 5, m15
546 %else ; ssse3
547     pmaddubsw m1, m12
548     pmaddubsw m2, m12
549     pmaddubsw %2, m14
550     pmaddubsw m4, m14
551     pmaddubsw m5, m0
552     pmaddubsw m6, m0
553     paddw     m1, %2
554     paddw     m2, m4
555     paddw     m1, m5
556     paddw     m2, m6
557     FILT_PACK m1, m2, 5, m15
558     pshufb    m1, [hpel_shuf]
559 %endif
560     movntps [r0+r4], m1
561     mova      %2, %3
562 %endmacro
563
564 %macro HPEL 1
565 ;-----------------------------------------------------------------------------
566 ; void hpel_filter( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
567 ;                   uint8_t *src, int stride, int width, int height)
568 ;-----------------------------------------------------------------------------
569 cglobal hpel_filter_%1, 7,7,16
570 %ifdef WIN64
571     movsxd   r4, r4d
572     movsxd   r5, r5d
573 %endif
574     mov      r10, r3
575     sub       r5, 16
576     mov      r11, r1
577     and      r10, 15
578     sub       r3, r10
579     add       r0, r5
580     add      r11, r5
581     add      r10, r5
582     add       r5, r2
583     mov       r2, r4
584     neg      r10
585     lea       r1, [r3+r2]
586     sub       r3, r2
587     sub       r3, r2
588     mov       r4, r10
589     mova     m15, [pw_16]
590 %ifidn %1, sse2
591     pxor      m0, m0
592 %else ; ssse3
593     mova      m0, [filt_mul51]
594     mova     m12, [filt_mul15]
595     mova     m14, [filt_mul20]
596 %endif
597 ;ALIGN 16
598 .loopy:
599 ; first filter_v
600     DO_FILT_V m8, m7, m13, m12, 0, %1
601 ;ALIGN 16
602 .loopx:
603     DO_FILT_V m6, m5, m11, m12, 16, %1
604 .lastx:
605     paddw   m15, m15 ; pw_32
606     DO_FILT_C m9, m8, m7, m6
607     psrlw   m15, 1 ; pw_16
608     movdqa   m7, m5
609     DO_FILT_H m10, m13, m11, %1
610     add      r4, 16
611     jl .loopx
612     cmp      r4, 16
613     jl .lastx
614 ; setup regs for next y
615     sub      r4, r10
616     sub      r4, r2
617     sub      r1, r4
618     sub      r3, r4
619     add      r0, r2
620     add     r11, r2
621     add      r5, r2
622     mov      r4, r10
623     sub     r6d, 1
624     jg .loopy
625     sfence
626     RET
627 %endmacro
628
629 %define PALIGNR PALIGNR_MMX
630 HPEL sse2
631 %define PALIGNR PALIGNR_SSSE3
632 HPEL ssse3
633 %endif
634
635 %undef movntq
636 %undef movntps
637 %undef sfence
638
639 ;-----------------------------------------------------------------------------
640 ; void plane_copy_core( uint8_t *dst, int i_dst,
641 ;                       uint8_t *src, int i_src, int w, int h)
642 ;-----------------------------------------------------------------------------
643 ; assumes i_dst and w are multiples of 16, and i_dst>w
644 cglobal plane_copy_core_mmxext, 6,7
645     movsxdifnidn r1, r1d
646     movsxdifnidn r3, r3d
647     movsxdifnidn r4, r4d
648     sub    r1,  r4
649     sub    r3,  r4
650 .loopy:
651     mov    r6d, r4d
652     sub    r6d, 63
653 .loopx:
654     prefetchnta [r2+256]
655     movq   mm0, [r2   ]
656     movq   mm1, [r2+ 8]
657     movntq [r0   ], mm0
658     movntq [r0+ 8], mm1
659     movq   mm2, [r2+16]
660     movq   mm3, [r2+24]
661     movntq [r0+16], mm2
662     movntq [r0+24], mm3
663     movq   mm4, [r2+32]
664     movq   mm5, [r2+40]
665     movntq [r0+32], mm4
666     movntq [r0+40], mm5
667     movq   mm6, [r2+48]
668     movq   mm7, [r2+56]
669     movntq [r0+48], mm6
670     movntq [r0+56], mm7
671     add    r2,  64
672     add    r0,  64
673     sub    r6d, 64
674     jg .loopx
675     prefetchnta [r2+256]
676     add    r6d, 63
677     jle .end16
678 .loop16:
679     movq   mm0, [r2  ]
680     movq   mm1, [r2+8]
681     movntq [r0  ], mm0
682     movntq [r0+8], mm1
683     add    r2,  16
684     add    r0,  16
685     sub    r6d, 16
686     jg .loop16
687 .end16:
688     add    r0, r1
689     add    r2, r3
690     dec    r5d
691     jg .loopy
692     sfence
693     emms
694     RET
695
696
697 %macro INTERLEAVE 4-5 ; dst, srcu, srcv, is_aligned, nt_hint
698     movq   m0, [%2]
699 %if mmsize==16
700 %if %4
701     punpcklbw m0, [%3]
702 %else
703     movq   m1, [%3]
704     punpcklbw m0, m1
705 %endif
706     mov%5a [%1], m0
707 %else
708     movq   m1, [%3]
709     mova   m2, m0
710     punpcklbw m0, m1
711     punpckhbw m2, m1
712     mov%5a [%1], m0
713     mov%5a [%1+8], m2
714 %endif
715 %endmacro
716
717 %macro DEINTERLEAVE 6 ; dstu, dstv, src, dstv==dstu+8, cpu, shuffle constant
718 %if mmsize==16
719     mova   m0, [%3]
720 %ifidn %5, ssse3
721     pshufb m0, %6
722 %else
723     mova   m1, m0
724     pand   m0, %6
725     psrlw  m1, 8
726     packuswb m0, m1
727 %endif
728 %if %4
729     mova   [%1], m0
730 %else
731     movq   [%1], m0
732     movhps [%2], m0
733 %endif
734 %else
735     mova   m0, [%3]
736     mova   m1, [%3+8]
737     mova   m2, m0
738     mova   m3, m1
739     pand   m0, %6
740     pand   m1, %6
741     psrlw  m2, 8
742     psrlw  m3, 8
743     packuswb m0, m1
744     packuswb m2, m3
745     mova   [%1], m0
746     mova   [%2], m2
747 %endif
748 %endmacro
749
750 %macro PLANE_INTERLEAVE 1
751 ;-----------------------------------------------------------------------------
752 ; void plane_copy_interleave_core( uint8_t *dst, int i_dst,
753 ;                                  uint8_t *srcu, int i_srcu,
754 ;                                  uint8_t *srcv, int i_srcv, int w, int h )
755 ;-----------------------------------------------------------------------------
756 ; assumes i_dst and w are multiples of 16, and i_dst>2*w
757 cglobal plane_copy_interleave_core_%1, 6,7
758     mov    r6d, r6m
759     movsxdifnidn r1, r1d
760     movsxdifnidn r3, r3d
761     movsxdifnidn r5, r5d
762     lea    r0, [r0+r6*2]
763     add    r2,  r6
764     add    r4,  r6
765 %ifdef ARCH_X86_64
766     DECLARE_REG_TMP 10,11
767 %else
768     DECLARE_REG_TMP 1,3
769 %endif
770     mov  t0d, r7m
771     mov  t1d, r1d
772     shr  t1d, 1
773     sub  t1d, r6d
774 .loopy:
775     mov    r6d, r6m
776     neg    r6
777 .prefetch:
778     prefetchnta [r2+r6]
779     prefetchnta [r4+r6]
780     add    r6, 64
781     jl .prefetch
782     mov    r6d, r6m
783     neg    r6
784 .loopx:
785     INTERLEAVE r0+r6*2,    r2+r6,   r4+r6,   0, nt
786     INTERLEAVE r0+r6*2+16, r2+r6+8, r4+r6+8, 0, nt
787     add    r6, 16
788     jl .loopx
789 .pad:
790 %if mmsize==8
791     movntq [r0+r6*2], m0
792     movntq [r0+r6*2+8], m0
793     movntq [r0+r6*2+16], m0
794     movntq [r0+r6*2+24], m0
795 %else
796     movntdq [r0+r6*2], m0
797     movntdq [r0+r6*2+16], m0
798 %endif
799     add    r6, 16
800     cmp    r6, t1
801     jl .pad
802     add    r0, r1mp
803     add    r2, r3mp
804     add    r4, r5
805     dec    t0d
806     jg .loopy
807     sfence
808     emms
809     RET
810
811 ;-----------------------------------------------------------------------------
812 ; void store_interleave_8x8x2( uint8_t *dst, int i_dst, uint8_t *srcu, uint8_t *srcv )
813 ;-----------------------------------------------------------------------------
814 cglobal store_interleave_8x8x2_%1, 4,5
815     mov    r4d, 4
816 .loop:
817     INTERLEAVE r0, r2, r3, 1
818     INTERLEAVE r0+r1, r2+FDEC_STRIDE, r3+FDEC_STRIDE, 1
819     add    r2, FDEC_STRIDE*2
820     add    r3, FDEC_STRIDE*2
821     lea    r0, [r0+r1*2]
822     dec    r4d
823     jg .loop
824     REP_RET
825 %endmacro ; PLANE_INTERLEAVE
826
827 %macro DEINTERLEAVE_START 1
828 %ifidn %1, ssse3
829     mova   m4, [deinterleave_shuf]
830 %else
831     mova   m4, [pw_00ff]
832 %endif
833 %endmacro
834
835 %macro PLANE_DEINTERLEAVE 1
836 ;-----------------------------------------------------------------------------
837 ; void plane_copy_deinterleave( uint8_t *dstu, int i_dstu,
838 ;                               uint8_t *dstv, int i_dstv,
839 ;                               uint8_t *src, int i_src, int w, int h )
840 ;-----------------------------------------------------------------------------
841 cglobal plane_copy_deinterleave_%1, 6,7
842     DEINTERLEAVE_START %1
843     mov    r6d, r6m
844     movsxdifnidn r1, r1d
845     movsxdifnidn r3, r3d
846     movsxdifnidn r5, r5d
847     add    r0,  r6
848     add    r2,  r6
849     lea    r4, [r4+r6*2]
850 .loopy:
851     mov    r6d, r6m
852     neg    r6
853 .loopx:
854     DEINTERLEAVE r0+r6,   r2+r6,   r4+r6*2,    0, %1, m4
855     DEINTERLEAVE r0+r6+8, r2+r6+8, r4+r6*2+16, 0, %1, m4
856     add    r6, 16
857     jl .loopx
858     add    r0, r1
859     add    r2, r3
860     add    r4, r5
861     dec dword r7m
862     jg .loopy
863     REP_RET
864
865 ;-----------------------------------------------------------------------------
866 ; void load_deinterleave_8x8x2_fenc( uint8_t *dst, uint8_t *src, int i_src )
867 ;-----------------------------------------------------------------------------
868 cglobal load_deinterleave_8x8x2_fenc_%1, 3,4
869     DEINTERLEAVE_START %1
870     mov    r3d, 4
871 .loop:
872     DEINTERLEAVE r0, r0+FENC_STRIDE/2, r1, 1, %1, m4
873     DEINTERLEAVE r0+FENC_STRIDE, r0+FENC_STRIDE*3/2, r1+r2, 1, %1, m4
874     add    r0, FENC_STRIDE*2
875     lea    r1, [r1+r2*2]
876     dec    r3d
877     jg .loop
878     REP_RET
879
880 ;-----------------------------------------------------------------------------
881 ; void load_deinterleave_8x8x2_fdec( uint8_t *dst, uint8_t *src, int i_src )
882 ;-----------------------------------------------------------------------------
883 cglobal load_deinterleave_8x8x2_fdec_%1, 3,4
884     DEINTERLEAVE_START %1
885     mov    r3d, 4
886 .loop:
887     DEINTERLEAVE r0, r0+FDEC_STRIDE/2, r1, 0, %1, m4
888     DEINTERLEAVE r0+FDEC_STRIDE, r0+FDEC_STRIDE*3/2, r1+r2, 0, %1, m4
889     add    r0, FDEC_STRIDE*2
890     lea    r1, [r1+r2*2]
891     dec    r3d
892     jg .loop
893     REP_RET
894 %endmacro ; PLANE_DEINTERLEAVE
895
896 INIT_MMX
897 PLANE_INTERLEAVE mmxext
898 PLANE_DEINTERLEAVE mmx
899 INIT_XMM
900 PLANE_INTERLEAVE sse2
901 PLANE_DEINTERLEAVE sse2
902 PLANE_DEINTERLEAVE ssse3
903
904
905 ; These functions are not general-use; not only do the SSE ones require aligned input,
906 ; but they also will fail if given a non-mod16 size or a size less than 64.
907 ; memzero SSE will fail for non-mod128.
908
909 ;-----------------------------------------------------------------------------
910 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
911 ;-----------------------------------------------------------------------------
912 cglobal memcpy_aligned_mmx, 3,3
913     test r2d, 16
914     jz .copy32
915     sub r2d, 16
916     movq mm0, [r1 + r2 + 0]
917     movq mm1, [r1 + r2 + 8]
918     movq [r0 + r2 + 0], mm0
919     movq [r0 + r2 + 8], mm1
920 .copy32:
921     sub r2d, 32
922     movq mm0, [r1 + r2 +  0]
923     movq mm1, [r1 + r2 +  8]
924     movq mm2, [r1 + r2 + 16]
925     movq mm3, [r1 + r2 + 24]
926     movq [r0 + r2 +  0], mm0
927     movq [r0 + r2 +  8], mm1
928     movq [r0 + r2 + 16], mm2
929     movq [r0 + r2 + 24], mm3
930     jg .copy32
931     REP_RET
932
933 ;-----------------------------------------------------------------------------
934 ; void *memcpy_aligned( void *dst, const void *src, size_t n );
935 ;-----------------------------------------------------------------------------
936 cglobal memcpy_aligned_sse2, 3,3
937     test r2d, 16
938     jz .copy32
939     sub r2d, 16
940     movdqa xmm0, [r1 + r2]
941     movdqa [r0 + r2], xmm0
942 .copy32:
943     test r2d, 32
944     jz .copy64
945     sub r2d, 32
946     movdqa xmm0, [r1 + r2 +  0]
947     movdqa [r0 + r2 +  0], xmm0
948     movdqa xmm1, [r1 + r2 + 16]
949     movdqa [r0 + r2 + 16], xmm1
950 .copy64:
951     sub r2d, 64
952     movdqa xmm0, [r1 + r2 +  0]
953     movdqa [r0 + r2 +  0], xmm0
954     movdqa xmm1, [r1 + r2 + 16]
955     movdqa [r0 + r2 + 16], xmm1
956     movdqa xmm2, [r1 + r2 + 32]
957     movdqa [r0 + r2 + 32], xmm2
958     movdqa xmm3, [r1 + r2 + 48]
959     movdqa [r0 + r2 + 48], xmm3
960     jg .copy64
961     REP_RET
962
963 ;-----------------------------------------------------------------------------
964 ; void *memzero_aligned( void *dst, size_t n );
965 ;-----------------------------------------------------------------------------
966 %macro MEMZERO 1
967 cglobal memzero_aligned_%1, 2,2
968     add  r0, r1
969     neg  r1
970     pxor m0, m0
971 .loop:
972 %assign i 0
973 %rep 8
974     mova [r0 + r1 + i], m0
975 %assign i i+mmsize
976 %endrep
977     add r1, mmsize*8
978     jl .loop
979     REP_RET
980 %endmacro
981
982 INIT_MMX
983 MEMZERO mmx
984 INIT_XMM
985 MEMZERO sse2
986
987
988
989 ;-----------------------------------------------------------------------------
990 ; void integral_init4h( uint16_t *sum, uint8_t *pix, int stride )
991 ;-----------------------------------------------------------------------------
992 cglobal integral_init4h_sse4, 3,4
993     lea     r3, [r0+r2*2]
994     add     r1, r2
995     neg     r2
996     pxor    m4, m4
997 .loop:
998     movdqa  m0, [r1+r2]
999     movdqa  m1, [r1+r2+16]
1000     palignr m1, m0, 8
1001     mpsadbw m0, m4, 0
1002     mpsadbw m1, m4, 0
1003     paddw   m0, [r0+r2*2]
1004     paddw   m1, [r0+r2*2+16]
1005     movdqa  [r3+r2*2   ], m0
1006     movdqa  [r3+r2*2+16], m1
1007     add     r2, 16
1008     jl .loop
1009     REP_RET
1010
1011 cglobal integral_init8h_sse4, 3,4
1012     lea     r3, [r0+r2*2]
1013     add     r1, r2
1014     neg     r2
1015     pxor    m4, m4
1016 .loop:
1017     movdqa  m0, [r1+r2]
1018     movdqa  m1, [r1+r2+16]
1019     palignr m1, m0, 8
1020     movdqa  m2, m0
1021     movdqa  m3, m1
1022     mpsadbw m0, m4, 0
1023     mpsadbw m1, m4, 0
1024     mpsadbw m2, m4, 4
1025     mpsadbw m3, m4, 4
1026     paddw   m0, [r0+r2*2]
1027     paddw   m1, [r0+r2*2+16]
1028     paddw   m0, m2
1029     paddw   m1, m3
1030     movdqa  [r3+r2*2   ], m0
1031     movdqa  [r3+r2*2+16], m1
1032     add     r2, 16
1033     jl .loop
1034     REP_RET
1035
1036 %macro INTEGRAL_INIT_8V 1
1037 ;-----------------------------------------------------------------------------
1038 ; void integral_init8v( uint16_t *sum8, int stride )
1039 ;-----------------------------------------------------------------------------
1040 cglobal integral_init8v_%1, 3,3
1041     shl   r1, 1
1042     add   r0, r1
1043     lea   r2, [r0+r1*8]
1044     neg   r1
1045 .loop:
1046     mova  m0, [r2+r1]
1047     mova  m1, [r2+r1+mmsize]
1048     psubw m0, [r0+r1]
1049     psubw m1, [r0+r1+mmsize]
1050     mova  [r0+r1], m0
1051     mova  [r0+r1+mmsize], m1
1052     add   r1, 2*mmsize
1053     jl .loop
1054     REP_RET
1055 %endmacro
1056
1057 INIT_MMX
1058 INTEGRAL_INIT_8V mmx
1059 INIT_XMM
1060 INTEGRAL_INIT_8V sse2
1061
1062 ;-----------------------------------------------------------------------------
1063 ; void integral_init4v( uint16_t *sum8, uint16_t *sum4, int stride )
1064 ;-----------------------------------------------------------------------------
1065 INIT_MMX
1066 cglobal integral_init4v_mmx, 3,5
1067     shl   r2, 1
1068     lea   r3, [r0+r2*4]
1069     lea   r4, [r0+r2*8]
1070     mova  m0, [r0+r2]
1071     mova  m4, [r4+r2]
1072 .loop:
1073     sub   r2, 8
1074     mova  m1, m4
1075     psubw m1, m0
1076     mova  m4, [r4+r2]
1077     mova  m0, [r0+r2]
1078     paddw m1, m4
1079     mova  m3, [r3+r2]
1080     psubw m1, m0
1081     psubw m3, m0
1082     mova  [r0+r2], m1
1083     mova  [r1+r2], m3
1084     jge .loop
1085     REP_RET
1086
1087 INIT_XMM
1088 cglobal integral_init4v_sse2, 3,5
1089     shl     r2, 1
1090     add     r0, r2
1091     add     r1, r2
1092     lea     r3, [r0+r2*4]
1093     lea     r4, [r0+r2*8]
1094     neg     r2
1095 .loop:
1096     mova    m0, [r0+r2]
1097     mova    m1, [r4+r2]
1098     mova    m2, m0
1099     mova    m4, m1
1100     shufpd  m0, [r0+r2+16], 1
1101     shufpd  m1, [r4+r2+16], 1
1102     paddw   m0, m2
1103     paddw   m1, m4
1104     mova    m3, [r3+r2]
1105     psubw   m1, m0
1106     psubw   m3, m2
1107     mova  [r0+r2], m1
1108     mova  [r1+r2], m3
1109     add     r2, 16
1110     jl .loop
1111     REP_RET
1112
1113 cglobal integral_init4v_ssse3, 3,5
1114     shl     r2, 1
1115     add     r0, r2
1116     add     r1, r2
1117     lea     r3, [r0+r2*4]
1118     lea     r4, [r0+r2*8]
1119     neg     r2
1120 .loop:
1121     mova    m2, [r0+r2]
1122     mova    m0, [r0+r2+16]
1123     mova    m4, [r4+r2]
1124     mova    m1, [r4+r2+16]
1125     palignr m0, m2, 8
1126     palignr m1, m4, 8
1127     paddw   m0, m2
1128     paddw   m1, m4
1129     mova    m3, [r3+r2]
1130     psubw   m1, m0
1131     psubw   m3, m2
1132     mova  [r0+r2], m1
1133     mova  [r1+r2], m3
1134     add     r2, 16
1135     jl .loop
1136     REP_RET
1137
1138 %macro FILT8x4 7
1139     mova      %3, [r0+%7]
1140     mova      %4, [r0+r5+%7]
1141     pavgb     %3, %4
1142     pavgb     %4, [r0+r5*2+%7]
1143     PALIGNR   %1, %3, 1, m6
1144     PALIGNR   %2, %4, 1, m6
1145     pavgb     %1, %3
1146     pavgb     %2, %4
1147     mova      %5, %1
1148     mova      %6, %2
1149     pand      %1, m7
1150     pand      %2, m7
1151     psrlw     %5, 8
1152     psrlw     %6, 8
1153 %endmacro
1154
1155 %macro FILT16x2 4
1156     mova      m3, [r0+%4+mmsize]
1157     mova      m2, [r0+%4]
1158     pavgb     m3, [r0+%4+r5+mmsize]
1159     pavgb     m2, [r0+%4+r5]
1160     PALIGNR   %1, m3, 1, m6
1161     pavgb     %1, m3
1162     PALIGNR   m3, m2, 1, m6
1163     pavgb     m3, m2
1164     mova      m5, m3
1165     mova      m4, %1
1166     pand      m3, m7
1167     pand      %1, m7
1168     psrlw     m5, 8
1169     psrlw     m4, 8
1170     packuswb  m3, %1
1171     packuswb  m5, m4
1172     mova    [%2], m3
1173     mova    [%3], m5
1174     mova      %1, m2
1175 %endmacro
1176
1177 %macro FILT8x2U 3
1178     mova      m3, [r0+%3+8]
1179     mova      m2, [r0+%3]
1180     pavgb     m3, [r0+%3+r5+8]
1181     pavgb     m2, [r0+%3+r5]
1182     mova      m1, [r0+%3+9]
1183     mova      m0, [r0+%3+1]
1184     pavgb     m1, [r0+%3+r5+9]
1185     pavgb     m0, [r0+%3+r5+1]
1186     pavgb     m1, m3
1187     pavgb     m0, m2
1188     mova      m3, m1
1189     mova      m2, m0
1190     pand      m1, m7
1191     pand      m0, m7
1192     psrlw     m3, 8
1193     psrlw     m2, 8
1194     packuswb  m0, m1
1195     packuswb  m2, m3
1196     mova    [%1], m0
1197     mova    [%2], m2
1198 %endmacro
1199
1200 ;-----------------------------------------------------------------------------
1201 ; void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
1202 ;                              int src_stride, int dst_stride, int width, int height )
1203 ;-----------------------------------------------------------------------------
1204 %macro FRAME_INIT_LOWRES 1-2 0 ; FIXME
1205 cglobal frame_init_lowres_core_%1, 6,7,%2
1206 %ifdef WIN64
1207     movsxd   r5, r5d
1208 %endif
1209     ; src += 2*(height-1)*stride + 2*width
1210     mov      r6d, r8m
1211     dec      r6d
1212     imul     r6d, r5d
1213     add      r6d, r7m
1214     lea       r0, [r0+r6*2]
1215     ; dst += (height-1)*stride + width
1216     mov      r6d, r8m
1217     dec      r6d
1218     imul     r6d, r6m
1219     add      r6d, r7m
1220     add       r1, r6
1221     add       r2, r6
1222     add       r3, r6
1223     add       r4, r6
1224     ; gap = stride - width
1225     mov      r6d, r6m
1226     sub      r6d, r7m
1227     PUSH      r6
1228     %define dst_gap [rsp+gprsize]
1229     mov      r6d, r5d
1230     sub      r6d, r7m
1231     shl      r6d, 1
1232     PUSH      r6
1233     %define src_gap [rsp]
1234 %if mmsize == 16
1235     ; adjust for the odd end case
1236     mov      r6d, r7m
1237     and      r6d, 8
1238     sub       r1, r6
1239     sub       r2, r6
1240     sub       r3, r6
1241     sub       r4, r6
1242     add  dst_gap, r6d
1243 %endif ; mmsize
1244     pcmpeqb   m7, m7
1245     psrlw     m7, 8
1246 .vloop:
1247     mov      r6d, r7m
1248 %ifnidn %1, mmxext
1249     mova      m0, [r0]
1250     mova      m1, [r0+r5]
1251     pavgb     m0, m1
1252     pavgb     m1, [r0+r5*2]
1253 %endif
1254 %if mmsize == 16
1255     test     r6d, 8
1256     jz .hloop
1257     sub       r0, 16
1258     FILT8x4   m0, m1, m2, m3, m4, m5, 0
1259     packuswb  m0, m4
1260     packuswb  m1, m5
1261     movq    [r1], m0
1262     movhps  [r2], m0
1263     movq    [r3], m1
1264     movhps  [r4], m1
1265     mova      m0, m2
1266     mova      m1, m3
1267     sub      r6d, 8
1268 %endif ; mmsize
1269 .hloop:
1270     sub       r0, mmsize*2
1271     sub       r1, mmsize
1272     sub       r2, mmsize
1273     sub       r3, mmsize
1274     sub       r4, mmsize
1275 %ifdef m8
1276     FILT8x4   m0, m1, m2, m3, m10, m11, mmsize
1277     mova      m8, m0
1278     mova      m9, m1
1279     FILT8x4   m2, m3, m0, m1, m4, m5, 0
1280     packuswb  m2, m8
1281     packuswb  m3, m9
1282     packuswb  m4, m10
1283     packuswb  m5, m11
1284     mova    [r1], m2
1285     mova    [r2], m4
1286     mova    [r3], m3
1287     mova    [r4], m5
1288 %elifidn %1, mmxext
1289     FILT8x2U  r1, r2, 0
1290     FILT8x2U  r3, r4, r5
1291 %else
1292     FILT16x2  m0, r1, r2, 0
1293     FILT16x2  m1, r3, r4, r5
1294 %endif
1295     sub      r6d, mmsize
1296     jg .hloop
1297 .skip:
1298     mov       r6, dst_gap
1299     sub       r0, src_gap
1300     sub       r1, r6
1301     sub       r2, r6
1302     sub       r3, r6
1303     sub       r4, r6
1304     dec    dword r8m
1305     jg .vloop
1306     ADD      rsp, 2*gprsize
1307     emms
1308     RET
1309 %endmacro ; FRAME_INIT_LOWRES
1310
1311 INIT_MMX
1312 %define PALIGNR PALIGNR_MMX
1313 FRAME_INIT_LOWRES mmxext
1314 %ifndef ARCH_X86_64
1315 FRAME_INIT_LOWRES cache32_mmxext
1316 %endif
1317 INIT_XMM
1318 FRAME_INIT_LOWRES sse2, 12
1319 %define PALIGNR PALIGNR_SSSE3
1320 FRAME_INIT_LOWRES ssse3, 12
1321
1322 ;-----------------------------------------------------------------------------
1323 ; void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
1324 ;                             uint16_t *inter_costs, uint16_t *inv_qscales, int len )
1325 ;-----------------------------------------------------------------------------
1326 cglobal mbtree_propagate_cost_sse2, 6,6,7
1327     shl r5d, 1
1328     lea r0, [r0+r5*2]
1329     add r1, r5
1330     add r2, r5
1331     add r3, r5
1332     add r4, r5
1333     neg r5
1334     pxor      xmm5, xmm5
1335     movdqa    xmm6, [pw_3fff]
1336     movdqa    xmm4, [pd_128]
1337 .loop:
1338     movq      xmm2, [r2+r5] ; intra
1339     movq      xmm0, [r4+r5] ; invq
1340     movq      xmm3, [r3+r5] ; inter
1341     movq      xmm1, [r1+r5] ; prop
1342     punpcklwd xmm2, xmm5
1343     punpcklwd xmm0, xmm5
1344     pmaddwd   xmm0, xmm2
1345     pand      xmm3, xmm6
1346     punpcklwd xmm1, xmm5
1347     punpcklwd xmm3, xmm5
1348     paddd     xmm0, xmm4
1349     psrld     xmm0, 8       ; intra*invq>>8
1350     paddd     xmm0, xmm1    ; prop + (intra*invq>>8)
1351     cvtdq2ps  xmm1, xmm2    ; intra
1352     psubd     xmm2, xmm3    ; intra - inter
1353     rcpps     xmm3, xmm1    ; 1 / intra 1st approximation
1354     cvtdq2ps  xmm0, xmm0
1355     mulps     xmm1, xmm3    ; intra * (1/intra 1st approx)
1356     cvtdq2ps  xmm2, xmm2
1357     mulps     xmm1, xmm3    ; intra * (1/intra 1st approx)^2
1358     mulps     xmm0, xmm2    ; (prop + (intra*invq>>8)) * (intra - inter)
1359     addps     xmm3, xmm3    ; 2 * (1/intra 1st approx)
1360     subps     xmm3, xmm1    ; 2nd approximation for 1/intra
1361     mulps     xmm0, xmm3    ; / intra
1362     cvttps2dq xmm0, xmm0    ; truncation isn't really desired, but matches the integer implementation
1363     movdqa [r0+r5*2], xmm0
1364     add r5, 8
1365     jl .loop
1366     REP_RET
1367