]> git.sesse.net Git - x264/blob - common/arm/pixel-a.S
arm: implement x264_pixel_var2_8x16_neon
[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 function x264_pixel_var2_8x16_neon
639     vld1.64         {d16}, [r0,:64], r1
640     vld1.64         {d17}, [r2,:64], r3
641     vld1.64         {d18}, [r0,:64], r1
642     vld1.64         {d19}, [r2,:64], r3
643     vsubl.u8        q10, d16, d17
644     vsubl.u8        q11, d18, d19
645     SQR_ACC         q1,  d20, d21,  vmull.s16
646     vld1.64         {d16}, [r0,:64], r1
647     vadd.s16        q0,  q10, q11
648     vld1.64         {d17}, [r2,:64], r3
649     SQR_ACC         q2,  d22, d23,  vmull.s16
650     mov             ip,  #14
651 1:  subs            ip,  ip,  #2
652     vld1.64         {d18}, [r0,:64], r1
653     vsubl.u8        q10, d16, d17
654     vld1.64         {d19}, [r2,:64], r3
655     vadd.s16        q0,  q0,  q10
656     SQR_ACC         q1,  d20, d21
657     vsubl.u8        q11, d18, d19
658     beq             2f
659     vld1.64         {d16}, [r0,:64], r1
660     vadd.s16        q0,  q0,  q11
661     vld1.64         {d17}, [r2,:64], r3
662     SQR_ACC         q2,  d22, d23
663     b               1b
664 2:
665     vadd.s16        q0,  q0,  q11
666     SQR_ACC         q2,  d22, d23
667
668     ldr             ip,  [sp]
669     vadd.s16        d0,  d0,  d1
670     vadd.s32        q1,  q1,  q2
671     vpaddl.s16      d0,  d0
672     vadd.s32        d1,  d2,  d3
673     vpadd.s32       d0,  d0,  d1
674
675     vmov            r0,  r1,  d0
676     vst1.32         {d0[1]}, [ip,:32]
677     mul             r0,  r0,  r0
678     sub             r0,  r1,  r0,  lsr #7
679     bx              lr
680 .endfunc
681
682 .macro LOAD_DIFF_8x4 q0 q1 q2 q3
683     vld1.32     {d1}, [r2], r3
684     vld1.32     {d0}, [r0,:64], r1
685     vsubl.u8    \q0, d0,  d1
686     vld1.32     {d3}, [r2], r3
687     vld1.32     {d2}, [r0,:64], r1
688     vsubl.u8    \q1, d2,  d3
689     vld1.32     {d5}, [r2], r3
690     vld1.32     {d4}, [r0,:64], r1
691     vsubl.u8    \q2, d4,  d5
692     vld1.32     {d7}, [r2], r3
693     vld1.32     {d6}, [r0,:64], r1
694     vsubl.u8    \q3, d6,  d7
695 .endm
696
697 function x264_pixel_satd_4x4_neon
698     vld1.32     {d1[]},  [r2], r3
699     vld1.32     {d0[]},  [r0,:32], r1
700     vld1.32     {d3[]},  [r2], r3
701     vld1.32     {d2[]},  [r0,:32], r1
702     vld1.32     {d1[1]}, [r2], r3
703     vld1.32     {d0[1]}, [r0,:32], r1
704     vld1.32     {d3[1]}, [r2], r3
705     vld1.32     {d2[1]}, [r0,:32], r1
706     vsubl.u8    q0,  d0,  d1
707     vsubl.u8    q1,  d2,  d3
708
709     SUMSUB_AB   q2, q3, q0, q1
710     SUMSUB_ABCD d0, d2, d1, d3, d4, d5, d6, d7
711     HADAMARD    1, sumsub, q2, q3, q0, q1
712     HADAMARD    2, amax,   q0,,    q2, q3
713
714     HORIZ_ADD   d0,  d0,  d1
715     vmov.32     r0,  d0[0]
716     bx          lr
717 .endfunc
718
719 function x264_pixel_satd_4x8_neon
720     vld1.32     {d1[]},  [r2], r3
721     vld1.32     {d0[]},  [r0,:32], r1
722     vld1.32     {d3[]},  [r2], r3
723     vld1.32     {d2[]},  [r0,:32], r1
724     vld1.32     {d5[]},  [r2], r3
725     vld1.32     {d4[]},  [r0,:32], r1
726     vld1.32     {d7[]},  [r2], r3
727     vld1.32     {d6[]},  [r0,:32], r1
728
729     vld1.32     {d1[1]}, [r2], r3
730     vld1.32     {d0[1]}, [r0,:32], r1
731     vsubl.u8    q0,  d0,  d1
732     vld1.32     {d3[1]}, [r2], r3
733     vld1.32     {d2[1]}, [r0,:32], r1
734     vsubl.u8    q1,  d2,  d3
735     vld1.32     {d5[1]}, [r2], r3
736     vld1.32     {d4[1]}, [r0,:32], r1
737     vsubl.u8    q2,  d4,  d5
738     vld1.32     {d7[1]}, [r2], r3
739     SUMSUB_AB   q8,  q9,  q0,  q1
740     vld1.32     {d6[1]}, [r0,:32], r1
741     vsubl.u8    q3,  d6,  d7
742     SUMSUB_AB   q10, q11, q2,  q3
743     b           x264_satd_4x8_8x4_end_neon
744 .endfunc
745
746 function x264_pixel_satd_8x4_neon
747     vld1.64     {d1}, [r2], r3
748     vld1.64     {d0}, [r0,:64], r1
749     vsubl.u8    q0,  d0,  d1
750     vld1.64     {d3}, [r2], r3
751     vld1.64     {d2}, [r0,:64], r1
752     vsubl.u8    q1,  d2,  d3
753     vld1.64     {d5}, [r2], r3
754     vld1.64     {d4}, [r0,:64], r1
755     vsubl.u8    q2,  d4,  d5
756     vld1.64     {d7}, [r2], r3
757     SUMSUB_AB   q8,  q9,  q0,  q1
758     vld1.64     {d6}, [r0,:64], r1
759     vsubl.u8    q3,  d6,  d7
760     SUMSUB_AB   q10, q11, q2,  q3
761 .endfunc
762
763 function x264_satd_4x8_8x4_end_neon
764     vadd.s16    q0,  q8,  q10
765     vadd.s16    q1,  q9,  q11
766     vsub.s16    q2,  q8,  q10
767     vsub.s16    q3,  q9,  q11
768
769     vtrn.16     q0,  q1
770     vadd.s16    q8,  q0,  q1
771     vtrn.16     q2,  q3
772     vsub.s16    q9,  q0,  q1
773     vadd.s16    q10, q2,  q3
774     vsub.s16    q11, q2,  q3
775     vtrn.32     q8,  q10
776     vabs.s16    q8,  q8
777     vtrn.32     q9,  q11
778     vabs.s16    q10, q10
779     vabs.s16    q9,  q9
780     vabs.s16    q11, q11
781     vmax.u16    q0,  q8,  q10
782     vmax.u16    q1,  q9,  q11
783
784     vadd.u16    q0,  q0,  q1
785     HORIZ_ADD   d0,  d0,  d1
786     vmov.32     r0,  d0[0]
787     bx          lr
788 .endfunc
789
790 function x264_pixel_satd_8x8_neon
791     mov         ip,  lr
792
793     bl x264_satd_8x8_neon
794     vadd.u16    q0,  q12, q13
795     vadd.u16    q1,  q14, q15
796
797     vadd.u16    q0,  q0,  q1
798     HORIZ_ADD   d0,  d0,  d1
799     mov         lr,  ip
800     vmov.32     r0,  d0[0]
801     bx          lr
802 .endfunc
803
804 function x264_pixel_satd_8x16_neon
805     vpush       {d8-d11}
806     mov         ip,  lr
807
808     bl x264_satd_8x8_neon
809     vadd.u16    q4,  q12, q13
810     vadd.u16    q5,  q14, q15
811
812     bl x264_satd_8x8_neon
813     vadd.u16    q4,  q4,  q12
814     vadd.u16    q5,  q5,  q13
815     vadd.u16    q4,  q4,  q14
816     vadd.u16    q5,  q5,  q15
817
818     vadd.u16    q0,  q4,  q5
819     HORIZ_ADD   d0,  d0,  d1
820     vpop        {d8-d11}
821     mov         lr,  ip
822     vmov.32     r0,  d0[0]
823     bx          lr
824 .endfunc
825
826 function x264_satd_8x8_neon
827     LOAD_DIFF_8x4 q8,  q9,  q10, q11
828     vld1.64     {d7}, [r2], r3
829     SUMSUB_AB   q0,  q1,  q8,  q9
830     vld1.64     {d6}, [r0,:64], r1
831     vsubl.u8    q12, d6,  d7
832     vld1.64     {d17}, [r2], r3
833     SUMSUB_AB   q2,  q3,  q10, q11
834     vld1.64     {d16}, [r0,:64], r1
835     vsubl.u8    q13, d16, d17
836     vld1.64     {d19}, [r2], r3
837     SUMSUB_AB   q8,  q10, q0,  q2
838     vld1.64     {d18}, [r0,:64], r1
839     vsubl.u8    q14, d18, d19
840     vld1.64     {d1}, [r2], r3
841     SUMSUB_AB   q9,  q11, q1,  q3
842     vld1.64     {d0}, [r0,:64], r1
843     vsubl.u8    q15, d0,  d1
844 .endfunc
845
846 // one vertical hadamard pass and two horizontal
847 function x264_satd_8x4v_8x8h_neon
848     SUMSUB_ABCD q0, q1, q2, q3, q12, q13, q14, q15
849     vtrn.16     q8,  q9
850     SUMSUB_AB   q12, q14, q0,  q2
851     vtrn.16     q10, q11
852     SUMSUB_AB   q13, q15, q1,  q3
853     SUMSUB_AB   q0,  q1,  q8,  q9
854     vtrn.16     q12, q13
855     SUMSUB_AB   q2,  q3,  q10, q11
856     vtrn.16     q14, q15
857     SUMSUB_AB   q8,  q9,  q12, q13
858     vtrn.32     q0,  q2
859     SUMSUB_AB   q10, q11, q14, q15
860
861     vtrn.32     q1,  q3
862     ABS2        q0,  q2
863     vtrn.32     q8,  q10
864     ABS2        q1,  q3
865     vtrn.32     q9,  q11
866     ABS2        q8,  q10
867     ABS2        q9,  q11
868     vmax.s16    q12, q0,  q2
869     vmax.s16    q13, q1,  q3
870     vmax.s16    q14, q8,  q10
871     vmax.s16    q15, q9,  q11
872     bx          lr
873 .endfunc
874
875 function x264_pixel_satd_16x8_neon
876     vpush       {d8-d11}
877     mov         ip, lr
878
879     bl          x264_satd_16x4_neon
880     vadd.u16    q4,  q12, q13
881     vadd.u16    q5,  q14, q15
882
883     bl          x264_satd_16x4_neon
884     vadd.u16    q4,  q4,  q12
885     vadd.u16    q5,  q5,  q13
886     vadd.u16    q4,  q4,  q14
887     vadd.u16    q5,  q5,  q15
888
889     vadd.u16    q0,  q4,  q5
890     HORIZ_ADD   d0,  d0,  d1
891     vpop        {d8-d11}
892     mov         lr,  ip
893     vmov.32     r0,  d0[0]
894     bx          lr
895 .endfunc
896
897 function x264_pixel_satd_16x16_neon
898     vpush       {d8-d11}
899     mov         ip, lr
900
901     bl          x264_satd_16x4_neon
902     vadd.u16    q4,  q12, q13
903     vadd.u16    q5,  q14, q15
904
905     bl          x264_satd_16x4_neon
906     vadd.u16    q4,  q4,  q12
907     vadd.u16    q5,  q5,  q13
908     vadd.u16    q4,  q4,  q14
909     vadd.u16    q5,  q5,  q15
910
911     bl          x264_satd_16x4_neon
912     vadd.u16    q4,  q4,  q12
913     vadd.u16    q5,  q5,  q13
914     vadd.u16    q4,  q4,  q14
915     vadd.u16    q5,  q5,  q15
916
917     bl          x264_satd_16x4_neon
918     vadd.u16    q4,  q4,  q12
919     vadd.u16    q5,  q5,  q13
920     vadd.u16    q4,  q4,  q14
921     vadd.u16    q5,  q5,  q15
922
923     vadd.u16    q0,  q4,  q5
924     HORIZ_ADD   d0,  d0,  d1
925     vpop        {d8-d11}
926     mov         lr,  ip
927     vmov.32     r0,  d0[0]
928     bx          lr
929 .endfunc
930
931 function x264_satd_16x4_neon
932     vld1.64     {d2-d3}, [r2], r3
933     vld1.64     {d0-d1}, [r0,:128], r1
934     vsubl.u8    q8,  d0,  d2
935     vld1.64     {d6-d7}, [r2], r3
936     vsubl.u8    q12, d1,  d3
937     vld1.64     {d4-d5}, [r0,:128], r1
938     vsubl.u8    q9,  d4,  d6
939     vld1.64     {d2-d3}, [r2], r3
940     vsubl.u8    q13, d5,  d7
941     vld1.64     {d0-d1}, [r0,:128], r1
942     vsubl.u8    q10, d0,  d2
943     vld1.64     {d6-d7}, [r2], r3
944     vsubl.u8    q14, d1,  d3
945     vadd.s16    q0,  q8,  q9
946     vld1.64     {d4-d5}, [r0,:128], r1
947     vsub.s16    q1,  q8,  q9
948     vsubl.u8    q11, d4,  d6
949     vsubl.u8    q15, d5,  d7
950     SUMSUB_AB   q2,  q3,  q10, q11
951     SUMSUB_ABCD q8,  q10, q9,  q11, q0,  q2,  q1,  q3
952     b           x264_satd_8x4v_8x8h_neon
953 .endfunc
954
955
956 function x264_pixel_sa8d_8x8_neon
957     mov             ip,  lr
958     bl              x264_sa8d_8x8_neon
959     vadd.u16        q0,  q8,  q9
960     HORIZ_ADD       d0,  d0,  d1
961     mov             lr,  ip
962     vmov.32         r0,  d0[0]
963     add             r0,  r0,  #1
964     lsr             r0,  r0,  #1
965     bx              lr
966 .endfunc
967
968 function x264_pixel_sa8d_16x16_neon
969     vpush           {d8-d11}
970     mov             ip,  lr
971     bl              x264_sa8d_8x8_neon
972     vpaddl.u16      q4,  q8
973     vpaddl.u16      q5,  q9
974     bl              x264_sa8d_8x8_neon
975     vpadal.u16      q4,  q8
976     vpadal.u16      q5,  q9
977     sub             r0,  r0,  r1,  lsl #4
978     sub             r2,  r2,  r3,  lsl #4
979     add             r0,  r0,  #8
980     add             r2,  r2,  #8
981     bl              x264_sa8d_8x8_neon
982     vpadal.u16      q4,  q8
983     vpadal.u16      q5,  q9
984     bl              x264_sa8d_8x8_neon
985     vpaddl.u16      q8,  q8
986     vpaddl.u16      q9,  q9
987     vadd.u32        q0,  q4,  q8
988     vadd.u32        q1,  q5,  q9
989     vadd.u32        q0,  q0,  q1
990     vadd.u32        d0,  d0,  d1
991     vpadd.u32       d0,  d0,  d0
992     vpop            {d8-d11}
993     mov             lr,  ip
994     vmov.32         r0,  d0[0]
995     add             r0,  r0,  #1
996     lsr             r0,  r0,  #1
997     bx              lr
998 .endfunc
999
1000 .macro HADAMARD4_V r1, r2, r3, r4, t1, t2, t3, t4
1001     SUMSUB_ABCD \t1, \t2, \t3, \t4, \r1, \r2, \r3, \r4
1002     SUMSUB_ABCD \r1, \r3, \r2, \r4, \t1, \t3, \t2, \t4
1003 .endm
1004
1005 function x264_sa8d_8x8_neon
1006     LOAD_DIFF_8x4   q8,  q9,  q10, q11
1007     vld1.64         {d7}, [r2], r3
1008     SUMSUB_AB       q0,  q1,  q8,  q9
1009     vld1.64         {d6}, [r0,:64], r1
1010     vsubl.u8        q12, d6,  d7
1011     vld1.64         {d17}, [r2], r3
1012     SUMSUB_AB       q2,  q3,  q10, q11
1013     vld1.64         {d16}, [r0,:64], r1
1014     vsubl.u8        q13, d16, d17
1015     vld1.64         {d19}, [r2], r3
1016     SUMSUB_AB       q8,  q10, q0,  q2
1017     vld1.64         {d18}, [r0,:64], r1
1018     vsubl.u8        q14, d18, d19
1019     vld1.64         {d1}, [r2], r3
1020     SUMSUB_AB       q9,  q11, q1,  q3
1021     vld1.64         {d0}, [r0,:64], r1
1022     vsubl.u8        q15, d0,  d1
1023
1024     HADAMARD4_V     q12, q13, q14, q15,  q0,  q1,  q2,  q3
1025     SUMSUB_ABCD     q0,  q8,  q1,  q9,   q8,  q12, q9,  q13
1026     SUMSUB_AB       q2,  q10, q10, q14
1027     vtrn.16         q8,  q9
1028     SUMSUB_AB       q3,  q11, q11, q15
1029     vtrn.16         q0,  q1
1030     SUMSUB_AB       q12, q13, q8,  q9
1031     vtrn.16         q10, q11
1032     SUMSUB_AB       q8,  q9,  q0,  q1
1033     vtrn.16         q2,  q3
1034     SUMSUB_AB       q14, q15, q10, q11
1035     vadd.i16        q10, q2,  q3
1036     vtrn.32         q12, q14
1037     vsub.i16        q11, q2,  q3
1038     vtrn.32         q13, q15
1039     SUMSUB_AB       q0,  q2,  q12, q14
1040     vtrn.32         q8,  q10
1041     SUMSUB_AB       q1,  q3,  q13, q15
1042     vtrn.32         q9,  q11
1043     SUMSUB_AB       q12, q14, q8,  q10
1044     SUMSUB_AB       q13, q15, q9,  q11
1045
1046     vswp            d1,  d24
1047     ABS2            q0,  q12
1048     vswp            d3,  d26
1049     ABS2            q1,  q13
1050     vswp            d5,  d28
1051     ABS2            q2,  q14
1052     vswp            d7,  d30
1053     ABS2            q3,  q15
1054     vmax.s16        q8,  q0,  q12
1055     vmax.s16        q9,  q1,  q13
1056     vmax.s16        q10, q2,  q14
1057     vmax.s16        q11, q3,  q15
1058     vadd.i16        q8,  q8,  q9
1059     vadd.i16        q9,  q10, q11
1060     bx              lr
1061 .endfunc
1062
1063
1064 .macro HADAMARD_AC w h
1065 function x264_pixel_hadamard_ac_\w\()x\h\()_neon
1066     vpush           {d8-d15}
1067     movrel          ip, mask_ac4
1068     vmov.i8         q4, #0
1069     // note: this assumes mask_ac8 is after mask_ac4 (so don't move it)
1070     vld1.64         {d12-d15}, [ip,:128]
1071     vmov.i8         q5, #0
1072
1073     mov             ip,  lr
1074     bl              x264_hadamard_ac_8x8_neon
1075 .if \h > 8
1076     bl              x264_hadamard_ac_8x8_neon
1077 .endif
1078 .if \w > 8
1079     sub             r0,  r0,  r1,  lsl #3
1080     add             r0,  r0,  #8
1081     bl              x264_hadamard_ac_8x8_neon
1082 .endif
1083 .if \w * \h == 256
1084     sub             r0,  r0,  r1,  lsl #4
1085     bl              x264_hadamard_ac_8x8_neon
1086 .endif
1087
1088     vadd.s32        d8,  d8,  d9
1089     vadd.s32        d10, d10, d11
1090     vpadd.s32       d0,  d8,  d10
1091     vpop            {d8-d15}
1092     mov             lr,  ip
1093     vmov            r0,  r1,  d0
1094     lsr             r0,  r0,  #1
1095     lsr             r1,  r1,  #2
1096     bx              lr
1097 .endfunc
1098 .endm
1099
1100 HADAMARD_AC  8, 8
1101 HADAMARD_AC  8, 16
1102 HADAMARD_AC 16, 8
1103 HADAMARD_AC 16, 16
1104
1105 // q4: satd  q5: sa8d  q6: mask_ac4  q7: mask_ac8
1106 function x264_hadamard_ac_8x8_neon
1107     vld1.64         {d2},  [r0,:64], r1
1108     vld1.64         {d3},  [r0,:64], r1
1109     vaddl.u8        q0,  d2,  d3
1110     vld1.64         {d6},  [r0,:64], r1
1111     vsubl.u8        q1,  d2,  d3
1112     vld1.64         {d7},  [r0,:64], r1
1113     vaddl.u8        q2,  d6,  d7
1114     vld1.64         {d18}, [r0,:64], r1
1115     vsubl.u8        q3,  d6,  d7
1116     vld1.64         {d19}, [r0,:64], r1
1117     vaddl.u8        q8,  d18, d19
1118     vld1.64         {d22}, [r0,:64], r1
1119     vsubl.u8        q9,  d18, d19
1120     vld1.64         {d23}, [r0,:64], r1
1121
1122     SUMSUB_ABCD     q12, q14, q13, q15, q0,  q2,  q1,  q3
1123     vaddl.u8        q10, d22, d23
1124     vsubl.u8        q11, d22, d23
1125     vtrn.16         q12, q13
1126     SUMSUB_ABCD     q0,  q2,  q1,  q3,  q8,  q10, q9,  q11
1127
1128     vtrn.16         q14, q15
1129     SUMSUB_AB       q8,  q9,  q12, q13
1130     vtrn.16         q0,  q1
1131     SUMSUB_AB       q10, q11, q14, q15
1132     vtrn.16         q2,  q3
1133     SUMSUB_AB       q12, q13, q0,  q1
1134     vtrn.32         q8,  q10
1135     SUMSUB_AB       q14, q15, q2,  q3
1136     vtrn.32         q9,  q11
1137     SUMSUB_AB       q0,  q2,  q8,  q10
1138     vtrn.32         q12, q14
1139     SUMSUB_AB       q1,  q3,  q9,  q11
1140     vtrn.32         q13, q15
1141     SUMSUB_ABCD     q8,  q10, q9,  q11, q12, q14, q13, q15
1142
1143     vabs.s16        q12, q0
1144     vabs.s16        q13, q8
1145     vabs.s16        q15, q1
1146     vadd.s16        q12, q12, q13
1147     vabs.s16        q14, q2
1148     vand.s16        q12, q12, q6
1149     vabs.s16        q13, q3
1150     vadd.s16        q12, q12, q15
1151     vabs.s16        q15, q9
1152     vadd.s16        q12, q12, q14
1153     vabs.s16        q14, q10
1154     vadd.s16        q12, q12, q13
1155     vabs.s16        q13, q11
1156     vadd.s16        q12, q12, q15
1157     vsub.s16        q15, q11, q3
1158     vadd.s16        q12, q12, q14
1159     vadd.s16        q14, q11, q3
1160     vadd.s16        q12, q12, q13
1161     vsub.s16        q13, q10, q2
1162     vadd.s16        q2,  q10, q2
1163     vpadal.u16      q4,  q12
1164
1165     SUMSUB_AB       q10, q11, q9,  q1
1166     SUMSUB_AB       q9,  q8,  q0,  q8
1167     vswp            d29, d30
1168     vabs.s16        q14, q14
1169     vabs.s16        q15, q15
1170     vswp            d5,  d26
1171     vabs.s16        q2,  q2
1172     vabs.s16        q13, q13
1173     vswp            d21, d22
1174     vabs.s16        q10, q10
1175     vabs.s16        q11, q11
1176     vmax.s16        q3,  q14, q15
1177     vmax.s16        q2,  q2,  q13
1178     vmax.s16        q1,  q10, q11
1179     vswp            d19, d16
1180     SUMSUB_AB       q14, q15, q9,  q8
1181
1182     vadd.s16        q2,  q2,  q3
1183     vadd.s16        q2,  q2,  q1
1184     vand            q14, q14, q7
1185     vadd.s16        q2,  q2,  q2
1186     vabs.s16        q15, q15
1187     vabs.s16        q14, q14
1188     vadd.s16        q2,  q2,  q15
1189     vadd.s16        q2,  q2,  q14
1190     vpadal.u16      q5,  q2
1191     bx              lr
1192 .endfunc
1193
1194
1195 .macro SSIM_ITER n ssa s12 ssb lastssa lasts12 lastssb da db dnext
1196     vld1.64     {\db}, [r2], r3
1197     vmull.u8    \ssa,  \da, \da
1198     vmull.u8    \s12,  \da, \db
1199 .if \n == 1
1200     vpaddl.u16  q2,  \lastssa
1201     vpaddl.u16  q3,  \lasts12
1202     vaddl.u8    q0,  d0,  \da
1203 .else
1204     vpadal.u16  q2,  \lastssa
1205     vpadal.u16  q3,  \lasts12
1206     vaddw.u8    q0,  q0,  \da
1207 .endif
1208     vpadal.u16  q2,  \lastssb
1209 .if \n < 3
1210     vld1.64     {\dnext}, [r0], r1
1211 .endif
1212 .if \n == 1
1213     vaddl.u8    q1,  d2,  \db
1214 .else
1215     vaddw.u8    q1,  q1,  \db
1216 .endif
1217     vmull.u8    \ssb, \db, \db
1218 .endm
1219
1220 function x264_pixel_ssim_4x4x2_core_neon
1221     ldr         ip, [sp]
1222     vld1.64     {d0}, [r0], r1
1223     vld1.64     {d2}, [r2], r3
1224     vmull.u8    q2,  d0,  d0
1225     vmull.u8    q3,  d0,  d2
1226     vld1.64     {d28}, [r0], r1
1227     vmull.u8    q15, d2,  d2
1228
1229     SSIM_ITER 1, q8, q9, q14,  q2, q3, q15,  d28, d29, d26
1230     SSIM_ITER 2, q10,q11,q13,  q8, q9, q14,  d26, d27, d28
1231     SSIM_ITER 3, q8, q9, q15,  q10,q11,q13,  d28, d29
1232
1233     vpadal.u16  q2,  q8
1234     vpaddl.u16  q0,  q0
1235     vpaddl.u16  q1,  q1
1236     vpadal.u16  q2,  q15
1237     vpadal.u16  q3,  q9
1238
1239     vpadd.u32   d0,  d0,  d1
1240     vpadd.u32   d1,  d2,  d3
1241     vpadd.u32   d2,  d4,  d5
1242     vpadd.u32   d3,  d6,  d7
1243
1244     vst4.32     {d0-d3}, [ip]
1245     bx          lr
1246 .endfunc
1247
1248 // FIXME: see about doing 16x16 -> 32 bit multiplies for s1/s2
1249 function x264_pixel_ssim_end4_neon
1250     vld1.32     {d16-d19}, [r0,:128]!
1251     vld1.32     {d20-d23}, [r1,:128]!
1252     vadd.s32    q0,  q8,  q10
1253     vadd.s32    q1,  q9,  q11
1254     vld1.32     {d24-d27}, [r0,:128]!
1255     vadd.s32    q0,  q0,  q1
1256     vld1.32     {d28-d31}, [r1,:128]!
1257     vadd.s32    q2,  q12, q14
1258     vadd.s32    q3,  q13, q15
1259     vld1.32     {d16-d17}, [r0,:128]
1260     vadd.s32    q1,  q1,  q2
1261     vld1.32     {d18-d19}, [r1,:128]
1262     vadd.s32    q8,  q8,  q9
1263     vadd.s32    q2,  q2,  q3
1264     vadd.s32    q3,  q3,  q8
1265
1266     vtrn.32     q0,  q1
1267     vtrn.32     q2,  q3
1268     vswp        d1,  d4
1269     vswp        d3,  d6
1270
1271 //  s1=q0, s2=q1, ss=q2, s12=q3
1272     vmul.s32    q8,  q0,  q1    // s1*s2
1273     vmul.s32    q0,  q0,  q0
1274     vmla.s32    q0,  q1,  q1    // s1*s1 + s2*s2
1275
1276     vshl.s32    q3,  q3,  #7
1277     vshl.s32    q2,  q2,  #6
1278     vadd.s32    q1,  q8,  q8
1279
1280     mov         r3, #416        // ssim_c1 = .01*.01*255*255*64
1281     movconst    ip, 235963      // ssim_c2 = .03*.03*255*255*64*63
1282     vdup.32     q14, r3
1283     vdup.32     q15, ip
1284
1285     vsub.s32    q2,  q2,  q0    // vars
1286     vsub.s32    q3,  q3,  q1    // covar*2
1287     vadd.s32    q0,  q0,  q14
1288     vadd.s32    q2,  q2,  q15
1289     vadd.s32    q1,  q1,  q14
1290     vadd.s32    q3,  q3,  q15
1291
1292     vcvt.f32.s32    q0,  q0
1293     vcvt.f32.s32    q2,  q2
1294     vcvt.f32.s32    q1,  q1
1295     vcvt.f32.s32    q3,  q3
1296
1297     vmul.f32    q0,  q0,  q2
1298     vmul.f32    q1,  q1,  q3
1299
1300     cmp         r2,  #4
1301
1302     vdiv.f32    s0,  s4,  s0
1303     vdiv.f32    s1,  s5,  s1
1304     vdiv.f32    s2,  s6,  s2
1305     vdiv.f32    s3,  s7,  s3
1306
1307     beq         ssim_skip
1308     movrel      r3,  mask_ff
1309     sub         r3,  r3,  r2,  lsl #2
1310     vld1.64     {d6-d7}, [r3]
1311     vand        q0,  q0,  q3
1312 ssim_skip:
1313     vadd.f32    d0,  d0,  d1
1314     vpadd.f32   d0,  d0,  d0
1315     vmov.32     r0,  d0[0]
1316     bx          lr
1317 .endfunc