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