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