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