]> git.sesse.net Git - x264/blob - common/arm/pixel-a.S
6bc904d86093105b154c70b6903adc6771d90412
[x264] / common / arm / pixel-a.S
1 /*****************************************************************************
2  * pixel.S: arm pixel metrics
3  *****************************************************************************
4  * Copyright (C) 2009-2014 x264 project
5  *
6  * Authors: David Conrad <lessen42@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
21  *
22  * This program is also available under a commercial proprietary license.
23  * For more information, contact us at licensing@x264.com.
24  *****************************************************************************/
25
26 #include "asm.S"
27
28 .fpu neon
29 .section .rodata
30 .align 4
31
32 .rept 16 .byte 0xff
33 .endr
34 mask_ff:
35 .rept 16 .byte 0
36 .endr
37
38 mask_ac4:
39 .short 0, -1, -1, -1,  0, -1, -1, -1
40 mask_ac8:
41 .short 0, -1, -1, -1, -1, -1, -1, -1
42
43 .text
44
45 .macro SAD4_ARMV6 h
46 function x264_pixel_sad_4x\h\()_armv6
47     push        {r4-r6,lr}
48     ldr         r4, [r2], r3
49     ldr         r5, [r0], r1
50     ldr         r6, [r2], r3
51     ldr         lr, [r0], r1
52     usad8       ip, r4, r5
53 .rept (\h - 2)/2
54     ldr         r4, [r2], r3
55     ldr         r5, [r0], r1
56     usada8      ip, r6, lr, ip
57     ldr         r6, [r2], r3
58     ldr         lr, [r0], r1
59     usada8      ip, r4, r5, ip
60 .endr
61     usada8      r0, r6, lr, ip
62     pop         {r4-r6,pc}
63 .endfunc
64 .endm
65
66 SAD4_ARMV6 4
67 SAD4_ARMV6 8
68
69
70 .macro SAD_START_4 align:vararg
71     vld1.32     {d1[]}, [r2\align], r3
72     vld1.32     {d0[]}, [r0,:32], r1
73     vabdl.u8    q8,  d0,  d1
74 .endm
75
76 .macro SAD_4 align:vararg
77     vld1.32     {d1[]}, [r2\align], r3
78     vld1.32     {d0[]}, [r0,:32], r1
79     vabal.u8    q8,  d0,  d1
80 .endm
81
82 .macro SAD_START_8 align:vararg
83     vld1.64     {d1}, [r2\align], r3
84     vld1.64     {d0}, [r0,:64], r1
85     vabdl.u8    q8,  d0,  d1
86 .endm
87
88 .macro SAD_8 align:vararg
89     vld1.64     {d1}, [r2\align], r3
90     vld1.64     {d0}, [r0,:64], r1
91     vabal.u8    q8,  d0,  d1
92 .endm
93
94 .macro SAD_START_16 align:vararg
95     vld1.64     {d2-d3}, [r2\align], r3
96     vld1.64     {d0-d1}, [r0,:128], r1
97     vabdl.u8    q8,  d0,  d2
98     vld1.64     {d6-d7}, [r2\align], r3
99     vabdl.u8    q9,  d1,  d3
100     vld1.64     {d4-d5}, [r0,:128], r1
101 .endm
102
103 .macro SAD_16 align:vararg
104     vabal.u8    q8,  d4,  d6
105     vld1.64     {d2-d3}, [r2\align], r3
106     vabal.u8    q9,  d5,  d7
107     vld1.64     {d0-d1}, [r0,:128], r1
108     vabal.u8    q8,  d0,  d2
109     vld1.64     {d6-d7}, [r2\align], r3
110     vabal.u8    q9,  d1,  d3
111     vld1.64     {d4-d5}, [r0,:128], r1
112 .endm
113
114 .macro SAD_FUNC w, h, name, align:vararg
115 function x264_pixel_sad\name\()_\w\()x\h\()_neon
116     SAD_START_\w \align
117
118 .if \w == 16
119 .rept \h / 2 - 1
120     SAD_\w \align
121 .endr
122 .else
123 .rept \h - 1
124     SAD_\w \align
125 .endr
126 .endif
127
128 .if \w > 8
129     vabal.u8    q8,  d4,  d6
130     vabal.u8    q9,  d5,  d7
131     vadd.u16    q8,  q8,  q9
132 .endif
133 .if \w > 4
134     vadd.u16    d16, d16, d17
135 .endif
136     vpadd.u16   d0,  d16, d16
137     vpaddl.u16  d0,  d0
138     vmov.u32    r0,  d0[0]
139     bx          lr
140 .endfunc
141 .endm
142
143 SAD_FUNC  4,  4
144 SAD_FUNC  4,  8
145 SAD_FUNC  8,  4
146 SAD_FUNC  8,  8
147 SAD_FUNC  8,  16
148 SAD_FUNC  16, 8
149 SAD_FUNC  16, 16
150
151 SAD_FUNC  4,  4,  _aligned, ,:32
152 SAD_FUNC  4,  8,  _aligned, ,:32
153 SAD_FUNC  8,  4,  _aligned, ,:64
154 SAD_FUNC  8,  8,  _aligned, ,:64
155 SAD_FUNC  8,  16, _aligned, ,:64
156 SAD_FUNC  16, 8,  _aligned, ,:128
157 SAD_FUNC  16, 16, _aligned, ,:128
158
159 // If dual issue is possible, use additional accumulators to avoid
160 // stalls from vadal's latency. This only matters for aligned.
161 .macro SAD_DUAL_START_8
162     SAD_START_8 ,:64
163     vld1.64     {d3}, [r2,:64], r3
164     vld1.64     {d2}, [r0,:64], r1
165     vabdl.u8    q9,  d2,  d3
166 .endm
167
168 .macro SAD_DUAL_8 align:vararg
169     vld1.64     {d1}, [r2,:64], r3
170     vld1.64     {d0}, [r0,:64], r1
171     vabal.u8    q8,  d0,  d1
172     vld1.64     {d3}, [r2,:64], r3
173     vld1.64     {d2}, [r0,:64], r1
174     vabal.u8    q9,  d2,  d3
175 .endm
176
177 .macro SAD_DUAL_START_16
178     SAD_START_16 ,:128
179     vabdl.u8    q10, d4,  d6
180     vld1.64     {d2-d3}, [r2,:128], r3
181     vabdl.u8    q11, d5,  d7
182     vld1.64     {d0-d1}, [r0,:128], r1
183 .endm
184
185 .macro SAD_DUAL_16
186     vabal.u8    q8,  d0,  d2
187     vld1.64     {d6-d7}, [r2,:128], r3
188     vabal.u8    q9,  d1,  d3
189     vld1.64     {d4-d5}, [r0,:128], r1
190     vabal.u8    q10, d4,  d6
191     vld1.64     {d2-d3}, [r2,:128], r3
192     vabal.u8    q11, d5,  d7
193     vld1.64     {d0-d1}, [r0,:128], r1
194 .endm
195
196 .macro SAD_DUAL_END_16
197     vabal.u8    q8,  d0,  d2
198     vld1.64     {d6-d7}, [r2,:128], r3
199     vabal.u8    q9,  d1,  d3
200     vld1.64     {d4-d5}, [r0,:128], r1
201     vabal.u8    q10, d4,  d6
202     vabal.u8    q11, d5,  d7
203 .endm
204
205 .macro SAD_FUNC_DUAL w, h
206 function x264_pixel_sad_aligned_\w\()x\h\()_neon_dual
207     SAD_DUAL_START_\w
208 .rept \h / 2 - \w / 8
209     SAD_DUAL_\w
210 .endr
211
212 .if \w > 8
213     SAD_DUAL_END_16
214     vadd.u16    q8,  q8,  q9
215     vadd.u16    q9,  q10, q11
216 .endif
217 .if \w > 4
218     vadd.u16    q8,  q8,  q9
219     vadd.u16    d16, d16, d17
220 .endif
221     vpadd.u16   d0,  d16, d16
222     vpaddl.u16  d0,  d0
223     vmov.u32    r0,  d0[0]
224     bx          lr
225 .endfunc
226 .endm
227
228 SAD_FUNC_DUAL  8,  4
229 SAD_FUNC_DUAL  8,  8
230 SAD_FUNC_DUAL  8,  16
231 SAD_FUNC_DUAL  16, 8
232 SAD_FUNC_DUAL  16, 16
233
234
235 .macro SAD_X_START_4 x
236     vld1.32     {d0[]}, [r0,:32], lr
237     vld1.32     {d1[]}, [r1], r6
238     vabdl.u8    q8,  d1,  d0
239     vld1.32     {d2[]}, [r2], r6
240     vabdl.u8    q9,  d2,  d0
241     vld1.32     {d3[]}, [r3], r6
242     vabdl.u8    q10, d3,  d0
243 .if \x == 4
244     vld1.32     {d4[]}, [r12], r6
245     vabdl.u8    q11, d4,  d0
246 .endif
247 .endm
248
249 .macro SAD_X_4 x
250     vld1.32     {d0[]}, [r0,:32], lr
251     vld1.32     {d1[]}, [r1], r6
252     vabal.u8    q8,  d1,  d0
253     vld1.32     {d2[]}, [r2], r6
254     vabal.u8    q9,  d2,  d0
255     vld1.32     {d3[]}, [r3], r6
256     vabal.u8    q10, d3,  d0
257 .if \x == 4
258     vld1.32     {d4[]}, [r12], r6
259     vabal.u8    q11, d4,  d0
260 .endif
261 .endm
262
263 .macro SAD_X_START_8 x
264     vld1.64     {d0}, [r0,:64], lr
265     vld1.64     {d1}, [r1], r6
266     vabdl.u8    q8,  d1,  d0
267     vld1.64     {d2}, [r2], r6
268     vabdl.u8    q9,  d2,  d0
269     vld1.64     {d3}, [r3], r6
270     vabdl.u8    q10, d3,  d0
271 .if \x == 4
272     vld1.64     {d4}, [r12], r6
273     vabdl.u8    q11, d4,  d0
274 .endif
275 .endm
276
277 .macro SAD_X_8 x
278     vld1.64     {d0}, [r0,:64], lr
279     vld1.64     {d1}, [r1], r6
280     vabal.u8    q8,  d1,  d0
281     vld1.64     {d2}, [r2], r6
282     vabal.u8    q9,  d2,  d0
283     vld1.64     {d3}, [r3], r6
284     vabal.u8    q10, d3,  d0
285 .if \x == 4
286     vld1.64     {d4}, [r12], r6
287     vabal.u8    q11, d4,  d0
288 .endif
289 .endm
290
291 .macro SAD_X_START_16 x
292     vld1.64     {d0-d1}, [r0,:128], lr
293     vld1.64     {d2-d3}, [r1], r6
294     vabdl.u8    q8,  d2,  d0
295     vabdl.u8    q12, d3,  d1
296     vld1.64     {d4-d5}, [r2], r6
297     vabdl.u8    q9,  d4,  d0
298     vabdl.u8    q13, d5,  d1
299     vld1.64     {d6-d7}, [r3], r6
300     vabdl.u8    q10, d6,  d0
301     vabdl.u8    q14, d7,  d1
302 .if \x == 4
303     vld1.64     {d2-d3}, [r12], r6
304     vabdl.u8    q11, d2,  d0
305     vabdl.u8    q15, d3,  d1
306 .endif
307 .endm
308
309 .macro SAD_X_16 x
310     vld1.64     {d0-d1}, [r0,:128], lr
311     vld1.64     {d2-d3}, [r1], r6
312     vabal.u8    q8,  d2,  d0
313     vabal.u8    q12, d3,  d1
314     vld1.64     {d4-d5}, [r2], r6
315     vabal.u8    q9,  d4,  d0
316     vabal.u8    q13, d5,  d1
317     vld1.64     {d6-d7}, [r3], r6
318     vabal.u8    q10, d6,  d0
319     vabal.u8    q14, d7,  d1
320 .if \x == 4
321     vld1.64     {d2-d3}, [r12], r6
322     vabal.u8    q11, d2,  d0
323     vabal.u8    q15, d3,  d1
324 .endif
325 .endm
326
327 .macro SAD_X_FUNC x, w, h
328 function x264_pixel_sad_x\x\()_\w\()x\h\()_neon
329     push        {r6-r7,lr}
330 .if \x == 3
331     ldrd        r6,  r7,  [sp, #12]
332 .else
333     ldrd        r6,  r7,  [sp, #16]
334     ldr         r12, [sp, #12]
335 .endif
336     mov         lr,  #FENC_STRIDE
337
338     SAD_X_START_\w \x
339 .rept \h - 1
340     SAD_X_\w \x
341 .endr
342
343 // add up the sads
344 .if \w > 8
345     vadd.u16    q8,  q8,  q12
346     vadd.u16    q9,  q9,  q13
347     vadd.u16    q10, q10, q14
348 .if \x == 4
349     vadd.u16    q11, q11, q15
350 .endif
351 .endif
352 .if \w > 4
353     vadd.u16    d16, d16, d17
354     vadd.u16    d18, d18, d19
355     vadd.u16    d20, d20, d21
356 .if \x == 4
357     vadd.u16    d22, d22, d23
358 .endif
359 .endif
360     vpadd.u16   d0,  d16, d18
361     vpadd.u16   d1,  d20, d22
362     vpaddl.u16  q0,  q0
363
364 .if \x == 3
365     vst1.32     {d0},    [r7]!
366     vst1.32     {d1[0]}, [r7,:32]
367 .else
368     vst1.32     {d0-d1}, [r7]
369 .endif
370     pop         {r6-r7,pc}
371 .endfunc
372 .endm
373
374 SAD_X_FUNC  3, 4,  4
375 SAD_X_FUNC  3, 4,  8
376 SAD_X_FUNC  3, 8,  4
377 SAD_X_FUNC  3, 8,  8
378 SAD_X_FUNC  3, 8,  16
379 SAD_X_FUNC  3, 16, 8
380 SAD_X_FUNC  3, 16, 16
381
382 SAD_X_FUNC  4, 4,  4
383 SAD_X_FUNC  4, 4,  8
384 SAD_X_FUNC  4, 8,  4
385 SAD_X_FUNC  4, 8,  8
386 SAD_X_FUNC  4, 8,  16
387 SAD_X_FUNC  4, 16, 8
388 SAD_X_FUNC  4, 16, 16
389
390
391 .macro SSD_START_4
392     vld1.32     {d16[]}, [r0,:32], r1
393     vld1.32     {d17[]}, [r2,:32], r3
394     vsubl.u8    q2, d16, d17
395     vld1.32     {d16[]}, [r0,:32], r1
396     vmull.s16   q0, d4, d4
397     vld1.32     {d17[]}, [r2,:32], r3
398 .endm
399
400 .macro SSD_4
401     vsubl.u8    q2, d16, d17
402     vld1.32     {d16[]}, [r0,:32], r1
403     vmlal.s16   q0, d4, d4
404     vld1.32     {d17[]}, [r2,:32], r3
405 .endm
406
407 .macro SSD_END_4
408     vsubl.u8    q2, d16, d17
409     vmlal.s16   q0, d4, d4
410 .endm
411
412 .macro SSD_START_8
413     vld1.64     {d16}, [r0,:64], r1
414     vld1.64     {d17}, [r2,:64], r3
415     vsubl.u8    q2, d16, d17
416     vld1.64     {d16}, [r0,:64], r1
417     vmull.s16   q0, d4, d4
418     vmlal.s16   q0, d5, d5
419     vld1.64     {d17}, [r2,:64], r3
420 .endm
421
422 .macro SSD_8
423     vsubl.u8    q2, d16, d17
424     vld1.64     {d16}, [r0,:64], r1
425     vmlal.s16   q0, d4, d4
426     vmlal.s16   q0, d5, d5
427     vld1.64     {d17}, [r2,:64], r3
428 .endm
429
430 .macro SSD_END_8
431     vsubl.u8    q2, d16, d17
432     vmlal.s16   q0, d4, d4
433     vmlal.s16   q0, d5, d5
434 .endm
435
436 .macro SSD_START_16
437     vld1.64     {d16-d17}, [r0,:128], r1
438     vld1.64     {d18-d19}, [r2,:128], r3
439     vsubl.u8    q2, d16, d18
440     vsubl.u8    q3, d17, d19
441     vld1.64     {d16-d17}, [r0,:128], r1
442     vmull.s16   q0, d4, d4
443     vmlal.s16   q0, d5, d5
444     vld1.64     {d18-d19}, [r2,:128], r3
445     vmlal.s16   q0, d6, d6
446     vmlal.s16   q0, d7, d7
447 .endm
448
449 .macro SSD_16
450     vsubl.u8    q2, d16, d18
451     vsubl.u8    q3, d17, d19
452     vld1.64     {d16-d17}, [r0,:128], r1
453     vmlal.s16   q0, d4, d4
454     vmlal.s16   q0, d5, d5
455     vld1.64     {d18-d19}, [r2,:128], r3
456     vmlal.s16   q0, d6, d6
457     vmlal.s16   q0, d7, d7
458 .endm
459
460 .macro SSD_END_16
461     vsubl.u8    q2, d16, d18
462     vsubl.u8    q3, d17, d19
463     vmlal.s16   q0, d4, d4
464     vmlal.s16   q0, d5, d5
465     vmlal.s16   q0, d6, d6
466     vmlal.s16   q0, d7, d7
467 .endm
468
469 .macro SSD_FUNC w h
470 function x264_pixel_ssd_\w\()x\h\()_neon
471     SSD_START_\w
472 .rept \h-2
473     SSD_\w
474 .endr
475     SSD_END_\w
476     vadd.s32    d0, d0, d1
477     vpadd.s32   d0, d0, d0
478     vmov.32     r0, d0[0]
479     bx          lr
480 .endfunc
481 .endm
482
483 SSD_FUNC   4, 4
484 SSD_FUNC   4, 8
485 SSD_FUNC   8, 4
486 SSD_FUNC   8, 8
487 SSD_FUNC   8, 16
488 SSD_FUNC  16, 8
489 SSD_FUNC  16, 16
490
491
492 .macro VAR_SQR_SUM qsqr_sum qsqr_last qsqr dsrc vpadal=vpadal.u16
493     vmull.u8        \qsqr, \dsrc, \dsrc
494     vaddw.u8        q0, q0, \dsrc
495     \vpadal         \qsqr_sum, \qsqr_last
496 .endm
497
498 function x264_pixel_var_8x8_neon
499     vld1.64         {d16}, [r0,:64], r1
500     vmull.u8        q1,  d16, d16
501     vmovl.u8        q0,  d16
502     vld1.64         {d18}, [r0,:64], r1
503     vmull.u8        q2,  d18, d18
504     vaddw.u8        q0,  q0,  d18
505
506     vld1.64         {d20}, [r0,:64], r1
507     VAR_SQR_SUM     q1,  q1,   q3,  d20, vpaddl.u16
508     vld1.64         {d22}, [r0,:64], r1
509     VAR_SQR_SUM     q2,  q2,   q8,  d22, vpaddl.u16
510
511     vld1.64         {d24}, [r0,:64], r1
512     VAR_SQR_SUM     q1,  q3,   q9,  d24
513     vld1.64         {d26}, [r0,:64], r1
514     VAR_SQR_SUM     q2,  q8,   q10, d26
515     vld1.64         {d24}, [r0,:64], r1
516     VAR_SQR_SUM     q1,  q9,   q14, d24
517     vld1.64         {d26}, [r0,:64], r1
518     VAR_SQR_SUM     q2,  q10,  q15, d26
519     b               x264_var_end
520 .endfunc
521
522 function x264_pixel_var_8x16_neon
523     vld1.64         {d16}, [r0,:64], r1
524     vld1.64         {d18}, [r0,:64], r1
525     vmull.u8        q1,  d16, d16
526     vmovl.u8        q0,  d16
527     vld1.64         {d20}, [r0,:64], r1
528     vmull.u8        q2,  d18, d18
529     vaddw.u8        q0,  q0,  d18
530
531     mov             ip,  #12
532
533     vld1.64         {d22}, [r0,:64], r1
534     VAR_SQR_SUM     q1,  q1,   q14,  d20, vpaddl.u16
535     vld1.64         {d16}, [r0,:64], r1
536     VAR_SQR_SUM     q2,  q2,   q15,  d22, vpaddl.u16
537
538 1:  subs            ip,  ip,  #4
539     vld1.64         {d18}, [r0,:64], r1
540     VAR_SQR_SUM     q1,  q14,  q12, d16
541     vld1.64         {d20}, [r0,:64], r1
542     VAR_SQR_SUM     q2,  q15,  q13, d18
543     vld1.64         {d22}, [r0,:64], r1
544     VAR_SQR_SUM     q1,  q12,  q14, d20
545     beq             2f
546     vld1.64         {d16}, [r0,:64], r1
547     VAR_SQR_SUM     q2,  q13,  q15, d22
548     b               1b
549 2:
550     VAR_SQR_SUM     q2,  q13,  q15, d22
551     b               x264_var_end
552 .endfunc
553
554 function x264_pixel_var_16x16_neon
555     vld1.64         {d16-d17}, [r0,:128], r1
556     vmull.u8        q12, d16, d16
557     vmovl.u8        q0,  d16
558     vmull.u8        q13, d17, d17
559     vaddw.u8        q0,  q0,  d17
560
561     vld1.64         {d18-d19}, [r0,:128], r1
562     VAR_SQR_SUM     q1,  q12,  q14, d18, vpaddl.u16
563     VAR_SQR_SUM     q2,  q13,  q15, d19, vpaddl.u16
564
565     mov             ip,  #7
566 var16_loop:
567     subs            ip,  ip,  #1
568     vld1.64         {d16-d17}, [r0,:128], r1
569     VAR_SQR_SUM     q1,  q14,  q12, d16
570     VAR_SQR_SUM     q2,  q15,  q13, d17
571
572     vld1.64         {d18-d19}, [r0,:128], r1
573     VAR_SQR_SUM     q1,  q12,  q14, d18
574     VAR_SQR_SUM     q2,  q13,  q15, d19
575     bgt             var16_loop
576 .endfunc
577
578 function x264_var_end
579     vpaddl.u16      q8,  q14
580     vpaddl.u16      q9,  q15
581     vadd.u32        q1,  q1,  q8
582     vadd.u16        d0,  d0,  d1
583     vadd.u32        q1,  q1,  q9
584     vadd.u32        q1,  q1,  q2
585     vpaddl.u16      d0,  d0
586     vadd.u32        d2,  d2,  d3
587     vpadd.u32       d0,  d0,  d2
588
589     vmov            r0,  r1,  d0
590     bx              lr
591 .endfunc
592
593 .macro DIFF_SUM diff da db lastdiff
594     vld1.64         {\da}, [r0,:64], r1
595     vld1.64         {\db}, [r2,:64], r3
596 .ifnb \lastdiff
597     vadd.s16        q0,  q0,  \lastdiff
598 .endif
599     vsubl.u8        \diff, \da, \db
600 .endm
601
602 .macro SQR_ACC acc d0 d1 vmlal=vmlal.s16
603     \vmlal          \acc, \d0, \d0
604     vmlal.s16       \acc, \d1, \d1
605 .endm
606
607 function x264_pixel_var2_8x8_neon
608     DIFF_SUM        q0,  d0,  d1
609     DIFF_SUM        q8,  d16, d17
610     SQR_ACC         q1,  d0,  d1,  vmull.s16
611     DIFF_SUM        q9,  d18, d19, q8
612     SQR_ACC         q2,  d16, d17, vmull.s16
613 .rept 2
614     DIFF_SUM        q8,  d16, d17, q9
615     SQR_ACC         q1,  d18, d19
616     DIFF_SUM        q9,  d18, d19, q8
617     SQR_ACC         q2,  d16, d17
618 .endr
619     DIFF_SUM        q8,  d16, d17, q9
620     SQR_ACC         q1,  d18, d19
621     vadd.s16        q0,  q0,  q8
622     SQR_ACC         q2,  d16, d17
623
624     ldr             ip,  [sp]
625     vadd.s16        d0,  d0,  d1
626     vadd.s32        q1,  q1,  q2
627     vpaddl.s16      d0,  d0
628     vadd.s32        d1,  d2,  d3
629     vpadd.s32       d0,  d0,  d1
630
631     vmov            r0,  r1,  d0
632     vst1.32         {d0[1]}, [ip,:32]
633     mul             r0,  r0,  r0
634     sub             r0,  r1,  r0,  lsr #6
635     bx              lr
636 .endfunc
637
638
639 .macro LOAD_DIFF_8x4 q0 q1 q2 q3
640     vld1.32     {d1}, [r2], r3
641     vld1.32     {d0}, [r0,:64], r1
642     vsubl.u8    \q0, d0,  d1
643     vld1.32     {d3}, [r2], r3
644     vld1.32     {d2}, [r0,:64], r1
645     vsubl.u8    \q1, d2,  d3
646     vld1.32     {d5}, [r2], r3
647     vld1.32     {d4}, [r0,:64], r1
648     vsubl.u8    \q2, d4,  d5
649     vld1.32     {d7}, [r2], r3
650     vld1.32     {d6}, [r0,:64], r1
651     vsubl.u8    \q3, d6,  d7
652 .endm
653
654 function x264_pixel_satd_4x4_neon
655     vld1.32     {d1[]},  [r2], r3
656     vld1.32     {d0[]},  [r0,:32], r1
657     vld1.32     {d3[]},  [r2], r3
658     vld1.32     {d2[]},  [r0,:32], r1
659     vld1.32     {d1[1]}, [r2], r3
660     vld1.32     {d0[1]}, [r0,:32], r1
661     vld1.32     {d3[1]}, [r2], r3
662     vld1.32     {d2[1]}, [r0,:32], r1
663     vsubl.u8    q0,  d0,  d1
664     vsubl.u8    q1,  d2,  d3
665
666     SUMSUB_AB   q2, q3, q0, q1
667     SUMSUB_ABCD d0, d2, d1, d3, d4, d5, d6, d7
668     HADAMARD    1, sumsub, q2, q3, q0, q1
669     HADAMARD    2, amax,   q0,,    q2, q3
670
671     HORIZ_ADD   d0,  d0,  d1
672     vmov.32     r0,  d0[0]
673     bx          lr
674 .endfunc
675
676 function x264_pixel_satd_4x8_neon
677     vld1.32     {d1[]},  [r2], r3
678     vld1.32     {d0[]},  [r0,:32], r1
679     vld1.32     {d3[]},  [r2], r3
680     vld1.32     {d2[]},  [r0,:32], r1
681     vld1.32     {d5[]},  [r2], r3
682     vld1.32     {d4[]},  [r0,:32], r1
683     vld1.32     {d7[]},  [r2], r3
684     vld1.32     {d6[]},  [r0,:32], r1
685
686     vld1.32     {d1[1]}, [r2], r3
687     vld1.32     {d0[1]}, [r0,:32], r1
688     vsubl.u8    q0,  d0,  d1
689     vld1.32     {d3[1]}, [r2], r3
690     vld1.32     {d2[1]}, [r0,:32], r1
691     vsubl.u8    q1,  d2,  d3
692     vld1.32     {d5[1]}, [r2], r3
693     vld1.32     {d4[1]}, [r0,:32], r1
694     vsubl.u8    q2,  d4,  d5
695     vld1.32     {d7[1]}, [r2], r3
696     SUMSUB_AB   q8,  q9,  q0,  q1
697     vld1.32     {d6[1]}, [r0,:32], r1
698     vsubl.u8    q3,  d6,  d7
699     SUMSUB_AB   q10, q11, q2,  q3
700     b           x264_satd_4x8_8x4_end_neon
701 .endfunc
702
703 function x264_pixel_satd_8x4_neon
704     vld1.64     {d1}, [r2], r3
705     vld1.64     {d0}, [r0,:64], r1
706     vsubl.u8    q0,  d0,  d1
707     vld1.64     {d3}, [r2], r3
708     vld1.64     {d2}, [r0,:64], r1
709     vsubl.u8    q1,  d2,  d3
710     vld1.64     {d5}, [r2], r3
711     vld1.64     {d4}, [r0,:64], r1
712     vsubl.u8    q2,  d4,  d5
713     vld1.64     {d7}, [r2], r3
714     SUMSUB_AB   q8,  q9,  q0,  q1
715     vld1.64     {d6}, [r0,:64], r1
716     vsubl.u8    q3,  d6,  d7
717     SUMSUB_AB   q10, q11, q2,  q3
718 .endfunc
719
720 function x264_satd_4x8_8x4_end_neon
721     vadd.s16    q0,  q8,  q10
722     vadd.s16    q1,  q9,  q11
723     vsub.s16    q2,  q8,  q10
724     vsub.s16    q3,  q9,  q11
725
726     vtrn.16     q0,  q1
727     vadd.s16    q8,  q0,  q1
728     vtrn.16     q2,  q3
729     vsub.s16    q9,  q0,  q1
730     vadd.s16    q10, q2,  q3
731     vsub.s16    q11, q2,  q3
732     vtrn.32     q8,  q10
733     vabs.s16    q8,  q8
734     vtrn.32     q9,  q11
735     vabs.s16    q10, q10
736     vabs.s16    q9,  q9
737     vabs.s16    q11, q11
738     vmax.u16    q0,  q8,  q10
739     vmax.u16    q1,  q9,  q11
740
741     vadd.u16    q0,  q0,  q1
742     HORIZ_ADD   d0,  d0,  d1
743     vmov.32     r0,  d0[0]
744     bx          lr
745 .endfunc
746
747 function x264_pixel_satd_8x8_neon
748     mov         ip,  lr
749
750     bl x264_satd_8x8_neon
751     vadd.u16    q0,  q12, q13
752     vadd.u16    q1,  q14, q15
753
754     vadd.u16    q0,  q0,  q1
755     HORIZ_ADD   d0,  d0,  d1
756     mov         lr,  ip
757     vmov.32     r0,  d0[0]
758     bx          lr
759 .endfunc
760
761 function x264_pixel_satd_8x16_neon
762     vpush       {d8-d11}
763     mov         ip,  lr
764
765     bl x264_satd_8x8_neon
766     vadd.u16    q4,  q12, q13
767     vadd.u16    q5,  q14, q15
768
769     bl x264_satd_8x8_neon
770     vadd.u16    q4,  q4,  q12
771     vadd.u16    q5,  q5,  q13
772     vadd.u16    q4,  q4,  q14
773     vadd.u16    q5,  q5,  q15
774
775     vadd.u16    q0,  q4,  q5
776     HORIZ_ADD   d0,  d0,  d1
777     vpop        {d8-d11}
778     mov         lr,  ip
779     vmov.32     r0,  d0[0]
780     bx          lr
781 .endfunc
782
783 function x264_satd_8x8_neon
784     LOAD_DIFF_8x4 q8,  q9,  q10, q11
785     vld1.64     {d7}, [r2], r3
786     SUMSUB_AB   q0,  q1,  q8,  q9
787     vld1.64     {d6}, [r0,:64], r1
788     vsubl.u8    q12, d6,  d7
789     vld1.64     {d17}, [r2], r3
790     SUMSUB_AB   q2,  q3,  q10, q11
791     vld1.64     {d16}, [r0,:64], r1
792     vsubl.u8    q13, d16, d17
793     vld1.64     {d19}, [r2], r3
794     SUMSUB_AB   q8,  q10, q0,  q2
795     vld1.64     {d18}, [r0,:64], r1
796     vsubl.u8    q14, d18, d19
797     vld1.64     {d1}, [r2], r3
798     SUMSUB_AB   q9,  q11, q1,  q3
799     vld1.64     {d0}, [r0,:64], r1
800     vsubl.u8    q15, d0,  d1
801 .endfunc
802
803 // one vertical hadamard pass and two horizontal
804 function x264_satd_8x4v_8x8h_neon
805     SUMSUB_ABCD q0, q1, q2, q3, q12, q13, q14, q15
806     vtrn.16     q8,  q9
807     SUMSUB_AB   q12, q14, q0,  q2
808     vtrn.16     q10, q11
809     SUMSUB_AB   q13, q15, q1,  q3
810     SUMSUB_AB   q0,  q1,  q8,  q9
811     vtrn.16     q12, q13
812     SUMSUB_AB   q2,  q3,  q10, q11
813     vtrn.16     q14, q15
814     SUMSUB_AB   q8,  q9,  q12, q13
815     vtrn.32     q0,  q2
816     SUMSUB_AB   q10, q11, q14, q15
817
818     vtrn.32     q1,  q3
819     ABS2        q0,  q2
820     vtrn.32     q8,  q10
821     ABS2        q1,  q3
822     vtrn.32     q9,  q11
823     ABS2        q8,  q10
824     ABS2        q9,  q11
825     vmax.s16    q12, q0,  q2
826     vmax.s16    q13, q1,  q3
827     vmax.s16    q14, q8,  q10
828     vmax.s16    q15, q9,  q11
829     bx          lr
830 .endfunc
831
832 function x264_pixel_satd_16x8_neon
833     vpush       {d8-d11}
834     mov         ip, lr
835
836     bl          x264_satd_16x4_neon
837     vadd.u16    q4,  q12, q13
838     vadd.u16    q5,  q14, q15
839
840     bl          x264_satd_16x4_neon
841     vadd.u16    q4,  q4,  q12
842     vadd.u16    q5,  q5,  q13
843     vadd.u16    q4,  q4,  q14
844     vadd.u16    q5,  q5,  q15
845
846     vadd.u16    q0,  q4,  q5
847     HORIZ_ADD   d0,  d0,  d1
848     vpop        {d8-d11}
849     mov         lr,  ip
850     vmov.32     r0,  d0[0]
851     bx          lr
852 .endfunc
853
854 function x264_pixel_satd_16x16_neon
855     vpush       {d8-d11}
856     mov         ip, lr
857
858     bl          x264_satd_16x4_neon
859     vadd.u16    q4,  q12, q13
860     vadd.u16    q5,  q14, q15
861
862     bl          x264_satd_16x4_neon
863     vadd.u16    q4,  q4,  q12
864     vadd.u16    q5,  q5,  q13
865     vadd.u16    q4,  q4,  q14
866     vadd.u16    q5,  q5,  q15
867
868     bl          x264_satd_16x4_neon
869     vadd.u16    q4,  q4,  q12
870     vadd.u16    q5,  q5,  q13
871     vadd.u16    q4,  q4,  q14
872     vadd.u16    q5,  q5,  q15
873
874     bl          x264_satd_16x4_neon
875     vadd.u16    q4,  q4,  q12
876     vadd.u16    q5,  q5,  q13
877     vadd.u16    q4,  q4,  q14
878     vadd.u16    q5,  q5,  q15
879
880     vadd.u16    q0,  q4,  q5
881     HORIZ_ADD   d0,  d0,  d1
882     vpop        {d8-d11}
883     mov         lr,  ip
884     vmov.32     r0,  d0[0]
885     bx          lr
886 .endfunc
887
888 function x264_satd_16x4_neon
889     vld1.64     {d2-d3}, [r2], r3
890     vld1.64     {d0-d1}, [r0,:128], r1
891     vsubl.u8    q8,  d0,  d2
892     vld1.64     {d6-d7}, [r2], r3
893     vsubl.u8    q12, d1,  d3
894     vld1.64     {d4-d5}, [r0,:128], r1
895     vsubl.u8    q9,  d4,  d6
896     vld1.64     {d2-d3}, [r2], r3
897     vsubl.u8    q13, d5,  d7
898     vld1.64     {d0-d1}, [r0,:128], r1
899     vsubl.u8    q10, d0,  d2
900     vld1.64     {d6-d7}, [r2], r3
901     vsubl.u8    q14, d1,  d3
902     vadd.s16    q0,  q8,  q9
903     vld1.64     {d4-d5}, [r0,:128], r1
904     vsub.s16    q1,  q8,  q9
905     vsubl.u8    q11, d4,  d6
906     vsubl.u8    q15, d5,  d7
907     SUMSUB_AB   q2,  q3,  q10, q11
908     SUMSUB_ABCD q8,  q10, q9,  q11, q0,  q2,  q1,  q3
909     b           x264_satd_8x4v_8x8h_neon
910 .endfunc
911
912
913 function x264_pixel_sa8d_8x8_neon
914     mov             ip,  lr
915     bl              x264_sa8d_8x8_neon
916     vadd.u16        q0,  q8,  q9
917     HORIZ_ADD       d0,  d0,  d1
918     mov             lr,  ip
919     vmov.32         r0,  d0[0]
920     add             r0,  r0,  #1
921     lsr             r0,  r0,  #1
922     bx              lr
923 .endfunc
924
925 function x264_pixel_sa8d_16x16_neon
926     vpush           {d8-d11}
927     mov             ip,  lr
928     bl              x264_sa8d_8x8_neon
929     vpaddl.u16      q4,  q8
930     vpaddl.u16      q5,  q9
931     bl              x264_sa8d_8x8_neon
932     vpadal.u16      q4,  q8
933     vpadal.u16      q5,  q9
934     sub             r0,  r0,  r1,  lsl #4
935     sub             r2,  r2,  r3,  lsl #4
936     add             r0,  r0,  #8
937     add             r2,  r2,  #8
938     bl              x264_sa8d_8x8_neon
939     vpadal.u16      q4,  q8
940     vpadal.u16      q5,  q9
941     bl              x264_sa8d_8x8_neon
942     vpaddl.u16      q8,  q8
943     vpaddl.u16      q9,  q9
944     vadd.u32        q0,  q4,  q8
945     vadd.u32        q1,  q5,  q9
946     vadd.u32        q0,  q0,  q1
947     vadd.u32        d0,  d0,  d1
948     vpadd.u32       d0,  d0,  d0
949     vpop            {d8-d11}
950     mov             lr,  ip
951     vmov.32         r0,  d0[0]
952     add             r0,  r0,  #1
953     lsr             r0,  r0,  #1
954     bx              lr
955 .endfunc
956
957 .macro HADAMARD4_V r1, r2, r3, r4, t1, t2, t3, t4
958     SUMSUB_ABCD \t1, \t2, \t3, \t4, \r1, \r2, \r3, \r4
959     SUMSUB_ABCD \r1, \r3, \r2, \r4, \t1, \t3, \t2, \t4
960 .endm
961
962 function x264_sa8d_8x8_neon
963     LOAD_DIFF_8x4   q8,  q9,  q10, q11
964     vld1.64         {d7}, [r2], r3
965     SUMSUB_AB       q0,  q1,  q8,  q9
966     vld1.64         {d6}, [r0,:64], r1
967     vsubl.u8        q12, d6,  d7
968     vld1.64         {d17}, [r2], r3
969     SUMSUB_AB       q2,  q3,  q10, q11
970     vld1.64         {d16}, [r0,:64], r1
971     vsubl.u8        q13, d16, d17
972     vld1.64         {d19}, [r2], r3
973     SUMSUB_AB       q8,  q10, q0,  q2
974     vld1.64         {d18}, [r0,:64], r1
975     vsubl.u8        q14, d18, d19
976     vld1.64         {d1}, [r2], r3
977     SUMSUB_AB       q9,  q11, q1,  q3
978     vld1.64         {d0}, [r0,:64], r1
979     vsubl.u8        q15, d0,  d1
980
981     HADAMARD4_V     q12, q13, q14, q15,  q0,  q1,  q2,  q3
982     SUMSUB_ABCD     q0,  q8,  q1,  q9,   q8,  q12, q9,  q13
983     SUMSUB_AB       q2,  q10, q10, q14
984     vtrn.16         q8,  q9
985     SUMSUB_AB       q3,  q11, q11, q15
986     vtrn.16         q0,  q1
987     SUMSUB_AB       q12, q13, q8,  q9
988     vtrn.16         q10, q11
989     SUMSUB_AB       q8,  q9,  q0,  q1
990     vtrn.16         q2,  q3
991     SUMSUB_AB       q14, q15, q10, q11
992     vadd.i16        q10, q2,  q3
993     vtrn.32         q12, q14
994     vsub.i16        q11, q2,  q3
995     vtrn.32         q13, q15
996     SUMSUB_AB       q0,  q2,  q12, q14
997     vtrn.32         q8,  q10
998     SUMSUB_AB       q1,  q3,  q13, q15
999     vtrn.32         q9,  q11
1000     SUMSUB_AB       q12, q14, q8,  q10
1001     SUMSUB_AB       q13, q15, q9,  q11
1002
1003     vswp            d1,  d24
1004     ABS2            q0,  q12
1005     vswp            d3,  d26
1006     ABS2            q1,  q13
1007     vswp            d5,  d28
1008     ABS2            q2,  q14
1009     vswp            d7,  d30
1010     ABS2            q3,  q15
1011     vmax.s16        q8,  q0,  q12
1012     vmax.s16        q9,  q1,  q13
1013     vmax.s16        q10, q2,  q14
1014     vmax.s16        q11, q3,  q15
1015     vadd.i16        q8,  q8,  q9
1016     vadd.i16        q9,  q10, q11
1017     bx              lr
1018 .endfunc
1019
1020
1021 .macro HADAMARD_AC w h
1022 function x264_pixel_hadamard_ac_\w\()x\h\()_neon
1023     vpush           {d8-d15}
1024     movrel          ip, mask_ac4
1025     vmov.i8         q4, #0
1026     // note: this assumes mask_ac8 is after mask_ac4 (so don't move it)
1027     vld1.64         {d12-d15}, [ip,:128]
1028     vmov.i8         q5, #0
1029
1030     mov             ip,  lr
1031     bl              x264_hadamard_ac_8x8_neon
1032 .if \h > 8
1033     bl              x264_hadamard_ac_8x8_neon
1034 .endif
1035 .if \w > 8
1036     sub             r0,  r0,  r1,  lsl #3
1037     add             r0,  r0,  #8
1038     bl              x264_hadamard_ac_8x8_neon
1039 .endif
1040 .if \w * \h == 256
1041     sub             r0,  r0,  r1,  lsl #4
1042     bl              x264_hadamard_ac_8x8_neon
1043 .endif
1044
1045     vadd.s32        d8,  d8,  d9
1046     vadd.s32        d10, d10, d11
1047     vpadd.s32       d0,  d8,  d10
1048     vpop            {d8-d15}
1049     mov             lr,  ip
1050     vmov            r0,  r1,  d0
1051     lsr             r0,  r0,  #1
1052     lsr             r1,  r1,  #2
1053     bx              lr
1054 .endfunc
1055 .endm
1056
1057 HADAMARD_AC  8, 8
1058 HADAMARD_AC  8, 16
1059 HADAMARD_AC 16, 8
1060 HADAMARD_AC 16, 16
1061
1062 // q4: satd  q5: sa8d  q6: mask_ac4  q7: mask_ac8
1063 function x264_hadamard_ac_8x8_neon
1064     vld1.64         {d2},  [r0,:64], r1
1065     vld1.64         {d3},  [r0,:64], r1
1066     vaddl.u8        q0,  d2,  d3
1067     vld1.64         {d6},  [r0,:64], r1
1068     vsubl.u8        q1,  d2,  d3
1069     vld1.64         {d7},  [r0,:64], r1
1070     vaddl.u8        q2,  d6,  d7
1071     vld1.64         {d18}, [r0,:64], r1
1072     vsubl.u8        q3,  d6,  d7
1073     vld1.64         {d19}, [r0,:64], r1
1074     vaddl.u8        q8,  d18, d19
1075     vld1.64         {d22}, [r0,:64], r1
1076     vsubl.u8        q9,  d18, d19
1077     vld1.64         {d23}, [r0,:64], r1
1078
1079     SUMSUB_ABCD     q12, q14, q13, q15, q0,  q2,  q1,  q3
1080     vaddl.u8        q10, d22, d23
1081     vsubl.u8        q11, d22, d23
1082     vtrn.16         q12, q13
1083     SUMSUB_ABCD     q0,  q2,  q1,  q3,  q8,  q10, q9,  q11
1084
1085     vtrn.16         q14, q15
1086     SUMSUB_AB       q8,  q9,  q12, q13
1087     vtrn.16         q0,  q1
1088     SUMSUB_AB       q10, q11, q14, q15
1089     vtrn.16         q2,  q3
1090     SUMSUB_AB       q12, q13, q0,  q1
1091     vtrn.32         q8,  q10
1092     SUMSUB_AB       q14, q15, q2,  q3
1093     vtrn.32         q9,  q11
1094     SUMSUB_AB       q0,  q2,  q8,  q10
1095     vtrn.32         q12, q14
1096     SUMSUB_AB       q1,  q3,  q9,  q11
1097     vtrn.32         q13, q15
1098     SUMSUB_ABCD     q8,  q10, q9,  q11, q12, q14, q13, q15
1099
1100     vabs.s16        q12, q0
1101     vabs.s16        q13, q8
1102     vabs.s16        q15, q1
1103     vadd.s16        q12, q12, q13
1104     vabs.s16        q14, q2
1105     vand.s16        q12, q12, q6
1106     vabs.s16        q13, q3
1107     vadd.s16        q12, q12, q15
1108     vabs.s16        q15, q9
1109     vadd.s16        q12, q12, q14
1110     vabs.s16        q14, q10
1111     vadd.s16        q12, q12, q13
1112     vabs.s16        q13, q11
1113     vadd.s16        q12, q12, q15
1114     vsub.s16        q15, q11, q3
1115     vadd.s16        q12, q12, q14
1116     vadd.s16        q14, q11, q3
1117     vadd.s16        q12, q12, q13
1118     vsub.s16        q13, q10, q2
1119     vadd.s16        q2,  q10, q2
1120     vpadal.u16      q4,  q12
1121
1122     SUMSUB_AB       q10, q11, q9,  q1
1123     SUMSUB_AB       q9,  q8,  q0,  q8
1124     vswp            d29, d30
1125     vabs.s16        q14, q14
1126     vabs.s16        q15, q15
1127     vswp            d5,  d26
1128     vabs.s16        q2,  q2
1129     vabs.s16        q13, q13
1130     vswp            d21, d22
1131     vabs.s16        q10, q10
1132     vabs.s16        q11, q11
1133     vmax.s16        q3,  q14, q15
1134     vmax.s16        q2,  q2,  q13
1135     vmax.s16        q1,  q10, q11
1136     vswp            d19, d16
1137     SUMSUB_AB       q14, q15, q9,  q8
1138
1139     vadd.s16        q2,  q2,  q3
1140     vadd.s16        q2,  q2,  q1
1141     vand            q14, q14, q7
1142     vadd.s16        q2,  q2,  q2
1143     vabs.s16        q15, q15
1144     vabs.s16        q14, q14
1145     vadd.s16        q2,  q2,  q15
1146     vadd.s16        q2,  q2,  q14
1147     vpadal.u16      q5,  q2
1148     bx              lr
1149 .endfunc
1150
1151
1152 .macro SSIM_ITER n ssa s12 ssb lastssa lasts12 lastssb da db dnext
1153     vld1.64     {\db}, [r2], r3
1154     vmull.u8    \ssa,  \da, \da
1155     vmull.u8    \s12,  \da, \db
1156 .if \n == 1
1157     vpaddl.u16  q2,  \lastssa
1158     vpaddl.u16  q3,  \lasts12
1159     vaddl.u8    q0,  d0,  \da
1160 .else
1161     vpadal.u16  q2,  \lastssa
1162     vpadal.u16  q3,  \lasts12
1163     vaddw.u8    q0,  q0,  \da
1164 .endif
1165     vpadal.u16  q2,  \lastssb
1166 .if \n < 3
1167     vld1.64     {\dnext}, [r0], r1
1168 .endif
1169 .if \n == 1
1170     vaddl.u8    q1,  d2,  \db
1171 .else
1172     vaddw.u8    q1,  q1,  \db
1173 .endif
1174     vmull.u8    \ssb, \db, \db
1175 .endm
1176
1177 function x264_pixel_ssim_4x4x2_core_neon
1178     ldr         ip, [sp]
1179     vld1.64     {d0}, [r0], r1
1180     vld1.64     {d2}, [r2], r3
1181     vmull.u8    q2,  d0,  d0
1182     vmull.u8    q3,  d0,  d2
1183     vld1.64     {d28}, [r0], r1
1184     vmull.u8    q15, d2,  d2
1185
1186     SSIM_ITER 1, q8, q9, q14,  q2, q3, q15,  d28, d29, d26
1187     SSIM_ITER 2, q10,q11,q13,  q8, q9, q14,  d26, d27, d28
1188     SSIM_ITER 3, q8, q9, q15,  q10,q11,q13,  d28, d29
1189
1190     vpadal.u16  q2,  q8
1191     vpaddl.u16  q0,  q0
1192     vpaddl.u16  q1,  q1
1193     vpadal.u16  q2,  q15
1194     vpadal.u16  q3,  q9
1195
1196     vpadd.u32   d0,  d0,  d1
1197     vpadd.u32   d1,  d2,  d3
1198     vpadd.u32   d2,  d4,  d5
1199     vpadd.u32   d3,  d6,  d7
1200
1201     vst4.32     {d0-d3}, [ip]
1202     bx          lr
1203 .endfunc
1204
1205 // FIXME: see about doing 16x16 -> 32 bit multiplies for s1/s2
1206 function x264_pixel_ssim_end4_neon
1207     vld1.32     {d16-d19}, [r0,:128]!
1208     vld1.32     {d20-d23}, [r1,:128]!
1209     vadd.s32    q0,  q8,  q10
1210     vadd.s32    q1,  q9,  q11
1211     vld1.32     {d24-d27}, [r0,:128]!
1212     vadd.s32    q0,  q0,  q1
1213     vld1.32     {d28-d31}, [r1,:128]!
1214     vadd.s32    q2,  q12, q14
1215     vadd.s32    q3,  q13, q15
1216     vld1.32     {d16-d17}, [r0,:128]
1217     vadd.s32    q1,  q1,  q2
1218     vld1.32     {d18-d19}, [r1,:128]
1219     vadd.s32    q8,  q8,  q9
1220     vadd.s32    q2,  q2,  q3
1221     vadd.s32    q3,  q3,  q8
1222
1223     vtrn.32     q0,  q1
1224     vtrn.32     q2,  q3
1225     vswp        d1,  d4
1226     vswp        d3,  d6
1227
1228 //  s1=q0, s2=q1, ss=q2, s12=q3
1229     vmul.s32    q8,  q0,  q1    // s1*s2
1230     vmul.s32    q0,  q0,  q0
1231     vmla.s32    q0,  q1,  q1    // s1*s1 + s2*s2
1232
1233     vshl.s32    q3,  q3,  #7
1234     vshl.s32    q2,  q2,  #6
1235     vadd.s32    q1,  q8,  q8
1236
1237     mov         r3, #416        // ssim_c1 = .01*.01*255*255*64
1238     movconst    ip, 235963      // ssim_c2 = .03*.03*255*255*64*63
1239     vdup.32     q14, r3
1240     vdup.32     q15, ip
1241
1242     vsub.s32    q2,  q2,  q0    // vars
1243     vsub.s32    q3,  q3,  q1    // covar*2
1244     vadd.s32    q0,  q0,  q14
1245     vadd.s32    q2,  q2,  q15
1246     vadd.s32    q1,  q1,  q14
1247     vadd.s32    q3,  q3,  q15
1248
1249     vcvt.f32.s32    q0,  q0
1250     vcvt.f32.s32    q2,  q2
1251     vcvt.f32.s32    q1,  q1
1252     vcvt.f32.s32    q3,  q3
1253
1254     vmul.f32    q0,  q0,  q2
1255     vmul.f32    q1,  q1,  q3
1256
1257     cmp         r2,  #4
1258
1259     vdiv.f32    s0,  s4,  s0
1260     vdiv.f32    s1,  s5,  s1
1261     vdiv.f32    s2,  s6,  s2
1262     vdiv.f32    s3,  s7,  s3
1263
1264     beq         ssim_skip
1265     movrel      r3,  mask_ff
1266     sub         r3,  r3,  r2,  lsl #2
1267     vld1.64     {d6-d7}, [r3]
1268     vand        q0,  q0,  q3
1269 ssim_skip:
1270     vadd.f32    d0,  d0,  d1
1271     vpadd.f32   d0,  d0,  d0
1272     vmov.32     r0,  d0[0]
1273     bx          lr
1274 .endfunc