]> git.sesse.net Git - x264/blob - common/arm/pixel-a.S
41559b8daa6a9205e35a825cd56dfc37b841c865
[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 .macro integrated_satd dst, s0, s1, s2, s3
1134     vmov            q0,  \s0
1135     vmov            q1,  \s1
1136     vmov            q2,  \s2
1137     vmov            q3,  \s3
1138
1139     vtrn.16         q0,  q1
1140     vtrn.16         q2,  q3
1141
1142     SUMSUB_AB       q6,  q7,  q0,  q1
1143     SUMSUB_AB       q0,  q1,  q2,  q3
1144
1145     vtrn.32         q6,  q0
1146     vtrn.32         q7,  q1
1147
1148     vabs.s16        q6,  q6
1149     vabs.s16        q0,  q0
1150     vabs.s16        q7,  q7
1151     vabs.s16        q1,  q1
1152
1153     vmax.u16        q6,  q6,  q0
1154     vmax.u16        q7,  q7,  q1
1155
1156     vadd.i16        q6,  q6,  q7
1157     vpadal.u16      \dst,  q6
1158 .endm
1159
1160 .macro sa8d_satd_8x8 satd=
1161 function x264_sa8d_\satd\()8x8_neon, export=0
1162     LOAD_DIFF_8x4   q8,  q9,  q10, q11
1163     vld1.64         {d7}, [r2], r3
1164     SUMSUB_AB       q0,  q1,  q8,  q9
1165     vld1.64         {d6}, [r0,:64], r1
1166     vsubl.u8        q12, d6,  d7
1167     vld1.64         {d17}, [r2], r3
1168     SUMSUB_AB       q2,  q3,  q10, q11
1169     vld1.64         {d16}, [r0,:64], r1
1170     vsubl.u8        q13, d16, d17
1171     vld1.64         {d19}, [r2], r3
1172     SUMSUB_AB       q8,  q10, q0,  q2
1173     vld1.64         {d18}, [r0,:64], r1
1174     vsubl.u8        q14, d18, d19
1175     vld1.64         {d1}, [r2], r3
1176     SUMSUB_AB       q9,  q11, q1,  q3
1177     vld1.64         {d0}, [r0,:64], r1
1178     vsubl.u8        q15, d0,  d1
1179
1180     HADAMARD4_V     q12, q13, q14, q15,  q0,  q1,  q2,  q3
1181
1182 .ifc \satd, satd_
1183     integrated_satd q4,  q8,  q9,  q10, q11
1184     integrated_satd q4,  q12, q13, q14, q15
1185 .endif
1186
1187     SUMSUB_ABCD     q0,  q8,  q1,  q9,   q8,  q12, q9,  q13
1188     SUMSUB_AB       q2,  q10, q10, q14
1189     vtrn.16         q8,  q9
1190     SUMSUB_AB       q3,  q11, q11, q15
1191     vtrn.16         q0,  q1
1192     SUMSUB_AB       q12, q13, q8,  q9
1193     vtrn.16         q10, q11
1194     SUMSUB_AB       q8,  q9,  q0,  q1
1195     vtrn.16         q2,  q3
1196     SUMSUB_AB       q14, q15, q10, q11
1197     vadd.i16        q10, q2,  q3
1198     vtrn.32         q12, q14
1199     vsub.i16        q11, q2,  q3
1200     vtrn.32         q13, q15
1201     SUMSUB_AB       q0,  q2,  q12, q14
1202     vtrn.32         q8,  q10
1203     SUMSUB_AB       q1,  q3,  q13, q15
1204     vtrn.32         q9,  q11
1205     SUMSUB_AB       q12, q14, q8,  q10
1206     SUMSUB_AB       q13, q15, q9,  q11
1207
1208     vswp            d1,  d24
1209     ABS2            q0,  q12
1210     vswp            d3,  d26
1211     ABS2            q1,  q13
1212     vswp            d5,  d28
1213     ABS2            q2,  q14
1214     vswp            d7,  d30
1215     ABS2            q3,  q15
1216     vmax.s16        q8,  q0,  q12
1217     vmax.s16        q9,  q1,  q13
1218     vmax.s16        q10, q2,  q14
1219     vmax.s16        q11, q3,  q15
1220     vadd.i16        q8,  q8,  q9
1221     vadd.i16        q9,  q10, q11
1222 .ifc \satd, satd_
1223     vpadal.u16      q5,  q8
1224     vpadal.u16      q5,  q9
1225 .endif
1226     bx              lr
1227 endfunc
1228 .endm
1229
1230 sa8d_satd_8x8
1231 sa8d_satd_8x8 satd_
1232
1233 function x264_pixel_sa8d_satd_16x16_neon
1234     push            {lr}
1235     vpush           {q4-q7}
1236     vmov.u32        q4,  #0
1237     vmov.u32        q5,  #0
1238     bl              x264_sa8d_satd_8x8_neon
1239     bl              x264_sa8d_satd_8x8_neon
1240     sub             r0,  r0,  r1,  lsl #4
1241     sub             r2,  r2,  r3,  lsl #4
1242     add             r0,  r0,  #8
1243     add             r2,  r2,  #8
1244     bl              x264_sa8d_satd_8x8_neon
1245     bl              x264_sa8d_satd_8x8_neon
1246     vadd.u32        d1,  d10, d11
1247     vadd.u32        d0,  d8,  d9
1248     vpadd.u32       d1,  d1,  d1
1249     vpadd.u32       d0,  d0,  d0
1250     vrshr.u32       d1,  d1,  #1
1251     vmov.32         r1,  d0[0]
1252     vmov.32         r0,  d1[0]
1253     vpop            {q4-q7}
1254     pop             {pc}
1255 endfunc
1256
1257
1258 .macro HADAMARD_AC w h
1259 function x264_pixel_hadamard_ac_\w\()x\h\()_neon
1260     vpush           {d8-d15}
1261     movrel          ip, mask_ac4
1262     vmov.i8         q4, #0
1263     // note: this assumes mask_ac8 is after mask_ac4 (so don't move it)
1264     vld1.64         {d12-d15}, [ip,:128]
1265     vmov.i8         q5, #0
1266
1267     mov             ip,  lr
1268     bl              x264_hadamard_ac_8x8_neon
1269 .if \h > 8
1270     bl              x264_hadamard_ac_8x8_neon
1271 .endif
1272 .if \w > 8
1273     sub             r0,  r0,  r1,  lsl #3
1274     add             r0,  r0,  #8
1275     bl              x264_hadamard_ac_8x8_neon
1276 .endif
1277 .if \w * \h == 256
1278     sub             r0,  r0,  r1,  lsl #4
1279     bl              x264_hadamard_ac_8x8_neon
1280 .endif
1281
1282     vadd.s32        d8,  d8,  d9
1283     vadd.s32        d10, d10, d11
1284     vpadd.s32       d0,  d8,  d10
1285     vpop            {d8-d15}
1286     mov             lr,  ip
1287     vmov            r0,  r1,  d0
1288     lsr             r0,  r0,  #1
1289     lsr             r1,  r1,  #2
1290     bx              lr
1291 endfunc
1292 .endm
1293
1294 HADAMARD_AC  8, 8
1295 HADAMARD_AC  8, 16
1296 HADAMARD_AC 16, 8
1297 HADAMARD_AC 16, 16
1298
1299 // q4: satd  q5: sa8d  q6: mask_ac4  q7: mask_ac8
1300 function x264_hadamard_ac_8x8_neon, export=0
1301     vld1.64         {d2},  [r0,:64], r1
1302     vld1.64         {d3},  [r0,:64], r1
1303     vaddl.u8        q0,  d2,  d3
1304     vld1.64         {d6},  [r0,:64], r1
1305     vsubl.u8        q1,  d2,  d3
1306     vld1.64         {d7},  [r0,:64], r1
1307     vaddl.u8        q2,  d6,  d7
1308     vld1.64         {d18}, [r0,:64], r1
1309     vsubl.u8        q3,  d6,  d7
1310     vld1.64         {d19}, [r0,:64], r1
1311     vaddl.u8        q8,  d18, d19
1312     vld1.64         {d22}, [r0,:64], r1
1313     vsubl.u8        q9,  d18, d19
1314     vld1.64         {d23}, [r0,:64], r1
1315
1316     SUMSUB_ABCD     q12, q14, q13, q15, q0,  q2,  q1,  q3
1317     vaddl.u8        q10, d22, d23
1318     vsubl.u8        q11, d22, d23
1319     vtrn.16         q12, q13
1320     SUMSUB_ABCD     q0,  q2,  q1,  q3,  q8,  q10, q9,  q11
1321
1322     vtrn.16         q14, q15
1323     SUMSUB_AB       q8,  q9,  q12, q13
1324     vtrn.16         q0,  q1
1325     SUMSUB_AB       q10, q11, q14, q15
1326     vtrn.16         q2,  q3
1327     SUMSUB_AB       q12, q13, q0,  q1
1328     vtrn.32         q8,  q10
1329     SUMSUB_AB       q14, q15, q2,  q3
1330     vtrn.32         q9,  q11
1331     SUMSUB_AB       q0,  q2,  q8,  q10
1332     vtrn.32         q12, q14
1333     SUMSUB_AB       q1,  q3,  q9,  q11
1334     vtrn.32         q13, q15
1335     SUMSUB_ABCD     q8,  q10, q9,  q11, q12, q14, q13, q15
1336
1337     vabs.s16        q12, q0
1338     vabs.s16        q13, q8
1339     vabs.s16        q15, q1
1340     vadd.s16        q12, q12, q13
1341     vabs.s16        q14, q2
1342     vand.s16        q12, q12, q6
1343     vabs.s16        q13, q3
1344     vadd.s16        q12, q12, q15
1345     vabs.s16        q15, q9
1346     vadd.s16        q12, q12, q14
1347     vabs.s16        q14, q10
1348     vadd.s16        q12, q12, q13
1349     vabs.s16        q13, q11
1350     vadd.s16        q12, q12, q15
1351     vsub.s16        q15, q11, q3
1352     vadd.s16        q12, q12, q14
1353     vadd.s16        q14, q11, q3
1354     vadd.s16        q12, q12, q13
1355     vsub.s16        q13, q10, q2
1356     vadd.s16        q2,  q10, q2
1357     vpadal.u16      q4,  q12
1358
1359     SUMSUB_AB       q10, q11, q9,  q1
1360     SUMSUB_AB       q9,  q8,  q0,  q8
1361     vswp            d29, d30
1362     vabs.s16        q14, q14
1363     vabs.s16        q15, q15
1364     vswp            d5,  d26
1365     vabs.s16        q2,  q2
1366     vabs.s16        q13, q13
1367     vswp            d21, d22
1368     vabs.s16        q10, q10
1369     vabs.s16        q11, q11
1370     vmax.s16        q3,  q14, q15
1371     vmax.s16        q2,  q2,  q13
1372     vmax.s16        q1,  q10, q11
1373     vswp            d19, d16
1374     SUMSUB_AB       q14, q15, q9,  q8
1375
1376     vadd.s16        q2,  q2,  q3
1377     vadd.s16        q2,  q2,  q1
1378     vand            q14, q14, q7
1379     vadd.s16        q2,  q2,  q2
1380     vabs.s16        q15, q15
1381     vabs.s16        q14, q14
1382     vadd.s16        q2,  q2,  q15
1383     vadd.s16        q2,  q2,  q14
1384     vpadal.u16      q5,  q2
1385     bx              lr
1386 endfunc
1387
1388
1389 .macro SSIM_ITER n ssa s12 ssb lastssa lasts12 lastssb da db dnext
1390     vld1.64     {\db}, [r2], r3
1391     vmull.u8    \ssa,  \da, \da
1392     vmull.u8    \s12,  \da, \db
1393 .if \n == 1
1394     vpaddl.u16  q2,  \lastssa
1395     vpaddl.u16  q3,  \lasts12
1396     vaddl.u8    q0,  d0,  \da
1397 .else
1398     vpadal.u16  q2,  \lastssa
1399     vpadal.u16  q3,  \lasts12
1400     vaddw.u8    q0,  q0,  \da
1401 .endif
1402     vpadal.u16  q2,  \lastssb
1403 .if \n < 3
1404     vld1.64     {\dnext}, [r0], r1
1405 .endif
1406 .if \n == 1
1407     vaddl.u8    q1,  d2,  \db
1408 .else
1409     vaddw.u8    q1,  q1,  \db
1410 .endif
1411     vmull.u8    \ssb, \db, \db
1412 .endm
1413
1414 function x264_pixel_ssim_4x4x2_core_neon
1415     ldr         ip, [sp]
1416     vld1.64     {d0}, [r0], r1
1417     vld1.64     {d2}, [r2], r3
1418     vmull.u8    q2,  d0,  d0
1419     vmull.u8    q3,  d0,  d2
1420     vld1.64     {d28}, [r0], r1
1421     vmull.u8    q15, d2,  d2
1422
1423     SSIM_ITER 1, q8, q9, q14,  q2, q3, q15,  d28, d29, d26
1424     SSIM_ITER 2, q10,q11,q13,  q8, q9, q14,  d26, d27, d28
1425     SSIM_ITER 3, q8, q9, q15,  q10,q11,q13,  d28, d29
1426
1427     vpadal.u16  q2,  q8
1428     vpaddl.u16  q0,  q0
1429     vpaddl.u16  q1,  q1
1430     vpadal.u16  q2,  q15
1431     vpadal.u16  q3,  q9
1432
1433     vpadd.u32   d0,  d0,  d1
1434     vpadd.u32   d1,  d2,  d3
1435     vpadd.u32   d2,  d4,  d5
1436     vpadd.u32   d3,  d6,  d7
1437
1438     vst4.32     {d0-d3}, [ip]
1439     bx          lr
1440 endfunc
1441
1442 // FIXME: see about doing 16x16 -> 32 bit multiplies for s1/s2
1443 function x264_pixel_ssim_end4_neon
1444     vld1.32     {d16-d19}, [r0,:128]!
1445     vld1.32     {d20-d23}, [r1,:128]!
1446     vadd.s32    q0,  q8,  q10
1447     vadd.s32    q1,  q9,  q11
1448     vld1.32     {d24-d27}, [r0,:128]!
1449     vadd.s32    q0,  q0,  q1
1450     vld1.32     {d28-d31}, [r1,:128]!
1451     vadd.s32    q2,  q12, q14
1452     vadd.s32    q3,  q13, q15
1453     vld1.32     {d16-d17}, [r0,:128]
1454     vadd.s32    q1,  q1,  q2
1455     vld1.32     {d18-d19}, [r1,:128]
1456     vadd.s32    q8,  q8,  q9
1457     vadd.s32    q2,  q2,  q3
1458     vadd.s32    q3,  q3,  q8
1459
1460     vtrn.32     q0,  q1
1461     vtrn.32     q2,  q3
1462     vswp        d1,  d4
1463     vswp        d3,  d6
1464
1465 //  s1=q0, s2=q1, ss=q2, s12=q3
1466     vmul.s32    q8,  q0,  q1    // s1*s2
1467     vmul.s32    q0,  q0,  q0
1468     vmla.s32    q0,  q1,  q1    // s1*s1 + s2*s2
1469
1470     vshl.s32    q3,  q3,  #7
1471     vshl.s32    q2,  q2,  #6
1472     vadd.s32    q1,  q8,  q8
1473
1474     mov         r3, #416        // ssim_c1 = .01*.01*255*255*64
1475     movconst    ip, 235963      // ssim_c2 = .03*.03*255*255*64*63
1476     vdup.32     q14, r3
1477     vdup.32     q15, ip
1478
1479     vsub.s32    q2,  q2,  q0    // vars
1480     vsub.s32    q3,  q3,  q1    // covar*2
1481     vadd.s32    q0,  q0,  q14
1482     vadd.s32    q2,  q2,  q15
1483     vadd.s32    q1,  q1,  q14
1484     vadd.s32    q3,  q3,  q15
1485
1486     vcvt.f32.s32    q0,  q0
1487     vcvt.f32.s32    q2,  q2
1488     vcvt.f32.s32    q1,  q1
1489     vcvt.f32.s32    q3,  q3
1490
1491     vmul.f32    q0,  q0,  q2
1492     vmul.f32    q1,  q1,  q3
1493
1494     cmp         r2,  #4
1495
1496     vdiv.f32    s0,  s4,  s0
1497     vdiv.f32    s1,  s5,  s1
1498     vdiv.f32    s2,  s6,  s2
1499     vdiv.f32    s3,  s7,  s3
1500
1501     beq         ssim_skip
1502     movrel      r3,  mask_ff
1503     sub         r3,  r3,  r2,  lsl #2
1504     vld1.64     {d6-d7}, [r3]
1505     vand        q0,  q0,  q3
1506 ssim_skip:
1507     vadd.f32    d0,  d0,  d1
1508     vpadd.f32   d0,  d0,  d0
1509     vmov.32     r0,  d0[0]
1510     bx          lr
1511 endfunc