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