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