Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52868 views
1
/*****************************************************************************
2
* mc.S: arm motion compensation
3
*****************************************************************************
4
* Copyright (C) 2009-2016 x264 project
5
*
6
* Authors: David Conrad <[email protected]>
7
* Mans Rullgard <[email protected]>
8
* Stefan Groenroos <[email protected]>
9
* Janne Grunau <[email protected]>
10
*
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
15
*
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
20
*
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
24
*
25
* This program is also available under a commercial proprietary license.
26
* For more information, contact us at [email protected].
27
*****************************************************************************/
28
29
#include "asm.S"
30
31
.section .rodata
32
.align 4
33
pw_0to15:
34
.short 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
35
36
.text
37
38
// note: prefetch stuff assumes 64-byte cacheline, true for the Cortex-A8
39
// They also use nothing above armv5te, but we don't care about pre-armv6
40
41
// void prefetch_ref( uint8_t *pix, intptr_t stride, int parity )
42
function x264_prefetch_ref_arm
43
sub r2, r2, #1
44
add r0, r0, #64
45
and r2, r2, r1
46
add r0, r0, r2, lsl #3
47
add r2, r1, r1, lsl #1
48
pld [r0]
49
pld [r0, r1]
50
pld [r0, r1, lsl #1]
51
add r3, r0, r1, lsl #2
52
pld [r0, r2]
53
pld [r3]
54
pld [r3, r1]
55
pld [r3, r1, lsl #1]
56
pld [r3, r2]
57
bx lr
58
endfunc
59
60
// void prefetch_fenc( uint8_t *pix_y, intptr_t stride_y,
61
// uint8_t *pix_uv, intptr_t stride_uv, int mb_x )
62
function x264_prefetch_fenc_arm
63
ldr ip, [sp]
64
push {lr}
65
and lr, ip, #3
66
smulbb lr, lr, r1 // note: this assumes stride_y is <= 16 bits signed
67
and ip, ip, #6
68
smulbb ip, ip, r3
69
add r0, r0, #64
70
add r2, r2, #64
71
add r0, r0, lr, lsl #2
72
pld [r0]
73
add lr, r0, r1, lsl #1
74
pld [r0, r1]
75
pld [lr]
76
add r2, r2, ip, lsl #2
77
pld [lr, r1]
78
pld [r2]
79
add ip, r2, r3, lsl #1
80
pld [r2, r3]
81
pld [ip]
82
pld [ip, r3]
83
pop {pc}
84
endfunc
85
86
87
// void *x264_memcpy_aligned( void *dst, const void *src, size_t n )
88
function x264_memcpy_aligned_neon
89
orr r3, r0, r1, lsr #1
90
movrel ip, memcpy_table
91
and r3, r3, #0xc
92
ldr pc, [ip, r3]
93
endfunc
94
95
.macro MEMCPY_ALIGNED srcalign dstalign
96
function memcpy_aligned_\dstalign\()_\srcalign\()_neon, export=0
97
mov r3, r0
98
.if \srcalign == 8 && \dstalign == 8
99
sub r2, #16
100
vld1.64 {d0}, [r1,:64]!
101
vst1.64 {d0}, [r3,:64]!
102
.set r1align, 128
103
.set r3align, 128
104
.else
105
.set r1align, \srcalign * 8
106
.set r3align, \dstalign * 8
107
.endif
108
tst r2, #16
109
beq 32f
110
sub r2, #16
111
vld1.64 {d0-d1}, [r1,:r1align]!
112
vst1.64 {d0-d1}, [r3,:r3align]!
113
32: // n is a multiple of 32
114
tst r2, #32
115
beq 640f
116
sub r2, #32
117
vld1.64 {d0-d3}, [r1,:r1align]!
118
vst1.64 {d0-d3}, [r3,:r3align]!
119
640: // n is a multiple of 64
120
cmp r2, #0
121
beq 1f
122
64:
123
subs r2, #64
124
vld1.64 {d0-d3}, [r1,:r1align]!
125
vld1.64 {d4-d7}, [r1,:r1align]!
126
vst1.64 {d0-d3}, [r3,:r3align]!
127
vst1.64 {d4-d7}, [r3,:r3align]!
128
bgt 64b
129
1: // end
130
.if \srcalign == 8 && \dstalign == 8
131
vld1.64 {d0}, [r1,:64]!
132
vst1.64 {d0}, [r3,:64]!
133
.endif
134
bx lr
135
endfunc
136
.endm
137
138
MEMCPY_ALIGNED 16, 16
139
MEMCPY_ALIGNED 16, 8
140
MEMCPY_ALIGNED 8, 16
141
MEMCPY_ALIGNED 8, 8
142
143
const memcpy_table align=2, relocate=1
144
.word memcpy_aligned_16_16_neon
145
.word memcpy_aligned_16_8_neon
146
.word memcpy_aligned_8_16_neon
147
.word memcpy_aligned_8_8_neon
148
endconst
149
150
.text
151
152
.ltorg
153
154
// void x264_memzero_aligned( void *dst, size_t n )
155
function x264_memzero_aligned_neon
156
vmov.i8 q0, #0
157
vmov.i8 q1, #0
158
memzero_loop:
159
subs r1, #128
160
.rept 4
161
vst1.64 {d0-d3}, [r0,:128]!
162
.endr
163
bgt memzero_loop
164
bx lr
165
endfunc
166
167
168
// void pixel_avg( uint8_t *dst, intptr_t dst_stride,
169
// uint8_t *src1, intptr_t src1_stride,
170
// uint8_t *src2, intptr_t src2_stride, int weight );
171
.macro AVGH w h
172
function x264_pixel_avg_\w\()x\h\()_neon
173
ldr ip, [sp, #8]
174
push {r4-r6,lr}
175
cmp ip, #32
176
ldrd r4, r5, [sp, #16]
177
mov lr, #\h
178
beq x264_pixel_avg_w\w\()_neon
179
rsbs r6, ip, #64
180
blt x264_pixel_avg_weight_w\w\()_add_sub_neon // weight > 64
181
cmp ip, #0
182
bge x264_pixel_avg_weight_w\w\()_add_add_neon
183
b x264_pixel_avg_weight_w\w\()_sub_add_neon // weight < 0
184
endfunc
185
.endm
186
187
AVGH 4, 2
188
AVGH 4, 4
189
AVGH 4, 8
190
AVGH 4, 16
191
AVGH 8, 4
192
AVGH 8, 8
193
AVGH 8, 16
194
AVGH 16, 8
195
AVGH 16, 16
196
197
// 0 < weight < 64
198
.macro load_weights_add_add
199
vdup.8 d30, ip
200
vdup.8 d31, r6
201
.endm
202
203
.macro load_add_add d1 d2
204
vld1.32 {\d1}, [r2], r3
205
vld1.32 {\d2}, [r4], r5
206
.endm
207
208
.macro weight_add_add dst s1 s2
209
vmull.u8 \dst, \s1, d30
210
vmlal.u8 \dst, \s2, d31
211
.endm
212
213
// weight > 64
214
.macro load_weights_add_sub
215
rsb r6, #0
216
vdup.8 d30, ip
217
vdup.8 d31, r6
218
.endm
219
220
.macro load_add_sub d1 d2
221
vld1.32 {\d1}, [r2], r3
222
vld1.32 {\d2}, [r4], r5
223
.endm
224
225
.macro weight_add_sub dst s1 s2
226
vmull.u8 \dst, \s1, d30
227
vmlsl.u8 \dst, \s2, d31
228
.endm
229
230
// weight < 0
231
.macro load_weights_sub_add
232
rsb ip, #0
233
vdup.8 d31, r6
234
vdup.8 d30, ip
235
.endm
236
237
.macro load_sub_add d1 d2
238
vld1.32 {\d2}, [r4], r5
239
vld1.32 {\d1}, [r2], r3
240
.endm
241
242
.macro weight_sub_add dst s1 s2
243
vmull.u8 \dst, \s2, d31
244
vmlsl.u8 \dst, \s1, d30
245
.endm
246
247
.macro AVG_WEIGHT ext
248
function x264_pixel_avg_weight_w4_\ext\()_neon, export=0
249
load_weights_\ext
250
1: // height loop
251
subs lr, lr, #2
252
load_\ext d0[], d1[]
253
weight_\ext q8, d0, d1
254
load_\ext d2[], d3[]
255
vqrshrun.s16 d0, q8, #6
256
weight_\ext q9, d2, d3
257
vst1.32 {d0[0]}, [r0,:32], r1
258
vqrshrun.s16 d1, q9, #6
259
vst1.32 {d1[0]}, [r0,:32], r1
260
bgt 1b
261
pop {r4-r6,pc}
262
endfunc
263
264
function x264_pixel_avg_weight_w8_\ext\()_neon, export=0
265
load_weights_\ext
266
1: // height loop
267
subs lr, lr, #4
268
load_\ext d0, d1
269
weight_\ext q8, d0, d1
270
load_\ext d2, d3
271
weight_\ext q9, d2, d3
272
load_\ext d4, d5
273
weight_\ext q10, d4, d5
274
load_\ext d6, d7
275
weight_\ext q11, d6, d7
276
vqrshrun.s16 d0, q8, #6
277
vqrshrun.s16 d1, q9, #6
278
vqrshrun.s16 d2, q10, #6
279
vqrshrun.s16 d3, q11, #6
280
vst1.64 {d0}, [r0,:64], r1
281
vst1.64 {d1}, [r0,:64], r1
282
vst1.64 {d2}, [r0,:64], r1
283
vst1.64 {d3}, [r0,:64], r1
284
bgt 1b
285
pop {r4-r6,pc}
286
endfunc
287
288
function x264_pixel_avg_weight_w16_\ext\()_neon, export=0
289
load_weights_\ext
290
1: // height loop
291
subs lr, lr, #2
292
load_\ext d0-d1, d2-d3
293
weight_\ext q8, d0, d2
294
weight_\ext q9, d1, d3
295
load_\ext d4-d5, d6-d7
296
weight_\ext q10, d4, d6
297
weight_\ext q11, d5, d7
298
vqrshrun.s16 d0, q8, #6
299
vqrshrun.s16 d1, q9, #6
300
vqrshrun.s16 d2, q10, #6
301
vqrshrun.s16 d3, q11, #6
302
vst1.64 {d0-d1}, [r0,:128], r1
303
vst1.64 {d2-d3}, [r0,:128], r1
304
bgt 1b
305
pop {r4-r6,pc}
306
endfunc
307
.endm
308
309
AVG_WEIGHT add_add
310
AVG_WEIGHT add_sub
311
AVG_WEIGHT sub_add
312
313
function x264_pixel_avg_w4_neon, export=0
314
subs lr, lr, #2
315
vld1.32 {d0[]}, [r2], r3
316
vld1.32 {d2[]}, [r4], r5
317
vrhadd.u8 d0, d0, d2
318
vld1.32 {d1[]}, [r2], r3
319
vld1.32 {d3[]}, [r4], r5
320
vrhadd.u8 d1, d1, d3
321
vst1.32 {d0[0]}, [r0,:32], r1
322
vst1.32 {d1[0]}, [r0,:32], r1
323
bgt x264_pixel_avg_w4_neon
324
pop {r4-r6,pc}
325
endfunc
326
327
function x264_pixel_avg_w8_neon, export=0
328
subs lr, lr, #4
329
vld1.64 {d0}, [r2], r3
330
vld1.64 {d2}, [r4], r5
331
vrhadd.u8 d0, d0, d2
332
vld1.64 {d1}, [r2], r3
333
vld1.64 {d3}, [r4], r5
334
vrhadd.u8 d1, d1, d3
335
vst1.64 {d0}, [r0,:64], r1
336
vld1.64 {d2}, [r2], r3
337
vld1.64 {d4}, [r4], r5
338
vrhadd.u8 d2, d2, d4
339
vst1.64 {d1}, [r0,:64], r1
340
vld1.64 {d3}, [r2], r3
341
vld1.64 {d5}, [r4], r5
342
vrhadd.u8 d3, d3, d5
343
vst1.64 {d2}, [r0,:64], r1
344
vst1.64 {d3}, [r0,:64], r1
345
bgt x264_pixel_avg_w8_neon
346
pop {r4-r6,pc}
347
endfunc
348
349
function x264_pixel_avg_w16_neon, export=0
350
subs lr, lr, #4
351
vld1.64 {d0-d1}, [r2], r3
352
vld1.64 {d2-d3}, [r4], r5
353
vrhadd.u8 q0, q0, q1
354
vld1.64 {d2-d3}, [r2], r3
355
vld1.64 {d4-d5}, [r4], r5
356
vrhadd.u8 q1, q1, q2
357
vst1.64 {d0-d1}, [r0,:128], r1
358
vld1.64 {d4-d5}, [r2], r3
359
vld1.64 {d6-d7}, [r4], r5
360
vrhadd.u8 q2, q2, q3
361
vst1.64 {d2-d3}, [r0,:128], r1
362
vld1.64 {d6-d7}, [r2], r3
363
vld1.64 {d0-d1}, [r4], r5
364
vrhadd.u8 q3, q3, q0
365
vst1.64 {d4-d5}, [r0,:128], r1
366
vst1.64 {d6-d7}, [r0,:128], r1
367
bgt x264_pixel_avg_w16_neon
368
pop {r4-r6,pc}
369
endfunc
370
371
372
function x264_pixel_avg2_w4_neon
373
ldr ip, [sp, #4]
374
push {lr}
375
ldr lr, [sp, #4]
376
avg2_w4_loop:
377
subs ip, ip, #2
378
vld1.32 {d0[]}, [r2], r3
379
vld1.32 {d2[]}, [lr], r3
380
vrhadd.u8 d0, d0, d2
381
vld1.32 {d1[]}, [r2], r3
382
vld1.32 {d3[]}, [lr], r3
383
vrhadd.u8 d1, d1, d3
384
vst1.32 {d0[0]}, [r0,:32], r1
385
vst1.32 {d1[0]}, [r0,:32], r1
386
bgt avg2_w4_loop
387
pop {pc}
388
endfunc
389
390
function x264_pixel_avg2_w8_neon
391
ldr ip, [sp, #4]
392
push {lr}
393
ldr lr, [sp, #4]
394
avg2_w8_loop:
395
subs ip, ip, #2
396
vld1.64 {d0}, [r2], r3
397
vld1.64 {d2}, [lr], r3
398
vrhadd.u8 d0, d0, d2
399
vld1.64 {d1}, [r2], r3
400
vld1.64 {d3}, [lr], r3
401
vrhadd.u8 d1, d1, d3
402
vst1.64 {d0}, [r0,:64], r1
403
vst1.64 {d1}, [r0,:64], r1
404
bgt avg2_w8_loop
405
pop {pc}
406
endfunc
407
408
function x264_pixel_avg2_w16_neon
409
ldr ip, [sp, #4]
410
push {lr}
411
ldr lr, [sp, #4]
412
avg2_w16_loop:
413
subs ip, ip, #2
414
vld1.64 {d0-d1}, [r2], r3
415
vld1.64 {d2-d3}, [lr], r3
416
vrhadd.u8 q0, q0, q1
417
vld1.64 {d4-d5}, [r2], r3
418
vld1.64 {d6-d7}, [lr], r3
419
vrhadd.u8 q2, q2, q3
420
vst1.64 {d0-d1}, [r0,:128], r1
421
vst1.64 {d4-d5}, [r0,:128], r1
422
bgt avg2_w16_loop
423
pop {pc}
424
endfunc
425
426
function x264_pixel_avg2_w20_neon
427
ldr ip, [sp, #4]
428
push {lr}
429
sub r1, r1, #16
430
ldr lr, [sp, #4]
431
avg2_w20_loop:
432
subs ip, ip, #2
433
vld1.64 {d0-d2}, [r2], r3
434
vld1.64 {d4-d6}, [lr], r3
435
vrhadd.u8 q0, q0, q2
436
vrhadd.u8 d2, d2, d6
437
vld1.64 {d4-d6}, [r2], r3
438
vld1.64 {d16-d18},[lr], r3
439
vrhadd.u8 q2, q2, q8
440
vst1.64 {d0-d1}, [r0,:128]!
441
vrhadd.u8 d6, d6, d18
442
vst1.32 {d2[0]}, [r0,:32], r1
443
vst1.64 {d4-d5}, [r0,:128]!
444
vst1.32 {d6[0]}, [r0,:32], r1
445
bgt avg2_w20_loop
446
pop {pc}
447
endfunc
448
449
450
.macro weight_prologue type
451
push {r4-r5,lr}
452
ldr r4, [sp, #4*3] // weight_t
453
ldr ip, [sp, #4*3+4] // h
454
.ifc \type, full
455
ldr lr, [r4, #32] // denom
456
.endif
457
ldrd r4, r5, [r4, #32+4] // scale, offset
458
vdup.8 d0, r4
459
vdup.16 q1, r5
460
.ifc \type, full
461
rsb lr, lr, #0
462
vdup.16 q2, lr
463
.endif
464
.endm
465
466
// void mc_weight( uint8_t *src, intptr_t src_stride, uint8_t *dst, intptr_t dst_stride,
467
// const x264_weight_t *weight, int height )
468
function x264_mc_weight_w20_neon
469
weight_prologue full
470
sub r1, #16
471
weight20_loop:
472
subs ip, #2
473
vld1.8 {d17-d19}, [r2], r3
474
vmull.u8 q10, d17, d0
475
vmull.u8 q11, d18, d0
476
vld1.8 {d16-d18}, [r2], r3
477
vmull.u8 q12, d16, d0
478
vmull.u8 q13, d17, d0
479
vtrn.32 d19, d18
480
vmull.u8 q14, d19, d0
481
vrshl.s16 q10, q10, q2
482
vrshl.s16 q11, q11, q2
483
vrshl.s16 q12, q12, q2
484
vrshl.s16 q13, q13, q2
485
vrshl.s16 q14, q14, q2
486
vadd.s16 q10, q10, q1
487
vadd.s16 q11, q11, q1
488
vadd.s16 q12, q12, q1
489
vadd.s16 q13, q13, q1
490
vadd.s16 q14, q14, q1
491
vqmovun.s16 d16, q10
492
vqmovun.s16 d17, q11
493
vqmovun.s16 d18, q12
494
vqmovun.s16 d19, q13
495
vqmovun.s16 d20, q14
496
vst1.8 {d16-d17}, [r0,:128]!
497
vst1.32 {d20[0]}, [r0,:32], r1
498
vst1.8 {d18-d19}, [r0,:128]!
499
vst1.32 {d20[1]}, [r0,:32], r1
500
bgt weight20_loop
501
pop {r4-r5,pc}
502
endfunc
503
504
function x264_mc_weight_w16_neon
505
weight_prologue full
506
weight16_loop:
507
subs ip, #2
508
vld1.8 {d16-d17}, [r2], r3
509
vld1.8 {d18-d19}, [r2], r3
510
vmull.u8 q10, d16, d0
511
vmull.u8 q11, d17, d0
512
vmull.u8 q12, d18, d0
513
vmull.u8 q13, d19, d0
514
vrshl.s16 q10, q10, q2
515
vrshl.s16 q11, q11, q2
516
vrshl.s16 q12, q12, q2
517
vrshl.s16 q13, q13, q2
518
vadd.s16 q10, q10, q1
519
vadd.s16 q11, q11, q1
520
vadd.s16 q12, q12, q1
521
vadd.s16 q13, q13, q1
522
vqmovun.s16 d16, q10
523
vqmovun.s16 d17, q11
524
vqmovun.s16 d18, q12
525
vqmovun.s16 d19, q13
526
vst1.8 {d16-d17}, [r0,:128], r1
527
vst1.8 {d18-d19}, [r0,:128], r1
528
bgt weight16_loop
529
pop {r4-r5,pc}
530
endfunc
531
532
function x264_mc_weight_w8_neon
533
weight_prologue full
534
weight8_loop:
535
subs ip, #2
536
vld1.8 {d16}, [r2], r3
537
vld1.8 {d18}, [r2], r3
538
vmull.u8 q8, d16, d0
539
vmull.u8 q9, d18, d0
540
vrshl.s16 q8, q8, q2
541
vrshl.s16 q9, q9, q2
542
vadd.s16 q8, q8, q1
543
vadd.s16 q9, q9, q1
544
vqmovun.s16 d16, q8
545
vqmovun.s16 d18, q9
546
vst1.8 {d16}, [r0,:64], r1
547
vst1.8 {d18}, [r0,:64], r1
548
bgt weight8_loop
549
pop {r4-r5,pc}
550
endfunc
551
552
function x264_mc_weight_w4_neon
553
weight_prologue full
554
weight4_loop:
555
subs ip, #2
556
vld1.32 {d16[0]}, [r2], r3
557
vld1.32 {d16[1]}, [r2], r3
558
vmull.u8 q8, d16, d0
559
vrshl.s16 q8, q8, q2
560
vadd.s16 q8, q8, q1
561
vqmovun.s16 d16, q8
562
vst1.32 {d16[0]}, [r0], r1
563
vst1.32 {d16[1]}, [r0], r1
564
bgt weight4_loop
565
pop {r4-r5,pc}
566
endfunc
567
568
function x264_mc_weight_w20_nodenom_neon
569
weight_prologue nodenom
570
sub r1, #16
571
weight20_nodenom_loop:
572
subs ip, #2
573
vld1.8 {d26-d28}, [r2], r3
574
vmov q8, q1
575
vmov q9, q1
576
vld1.8 {d29-d31}, [r2], r3
577
vmov q10, q1
578
vmov q11, q1
579
vmov q12, q1
580
vtrn.32 d28, d31
581
vmlal.u8 q8, d26, d0
582
vmlal.u8 q9, d27, d0
583
vmlal.u8 q10, d29, d0
584
vmlal.u8 q11, d30, d0
585
vmlal.u8 q12, d28, d0
586
vqmovun.s16 d16, q8
587
vqmovun.s16 d17, q9
588
vqmovun.s16 d18, q10
589
vqmovun.s16 d19, q11
590
vqmovun.s16 d20, q12
591
vst1.8 {d16-d17}, [r0,:128]!
592
vst1.32 {d20[0]}, [r0,:32], r1
593
vst1.8 {d18-d19}, [r0,:128]!
594
vst1.32 {d20[1]}, [r0,:32], r1
595
bgt weight20_nodenom_loop
596
pop {r4-r5,pc}
597
endfunc
598
599
function x264_mc_weight_w16_nodenom_neon
600
weight_prologue nodenom
601
weight16_nodenom_loop:
602
subs ip, #2
603
vld1.8 {d16-d17}, [r2], r3
604
vld1.8 {d18-d19}, [r2], r3
605
vmov q12, q1
606
vmov q13, q1
607
vmov q14, q1
608
vmov q15, q1
609
vmlal.u8 q12, d16, d0
610
vmlal.u8 q13, d17, d0
611
vmlal.u8 q14, d18, d0
612
vmlal.u8 q15, d19, d0
613
vqmovun.s16 d16, q12
614
vqmovun.s16 d17, q13
615
vqmovun.s16 d18, q14
616
vqmovun.s16 d19, q15
617
vst1.8 {d16-d17}, [r0,:128], r1
618
vst1.8 {d18-d19}, [r0,:128], r1
619
bgt weight16_nodenom_loop
620
pop {r4-r5,pc}
621
endfunc
622
623
function x264_mc_weight_w8_nodenom_neon
624
weight_prologue nodenom
625
weight8_nodenom_loop:
626
subs ip, #2
627
vld1.8 {d16}, [r2], r3
628
vld1.8 {d18}, [r2], r3
629
vmov q10, q1
630
vmov q11, q1
631
vmlal.u8 q10, d16, d0
632
vmlal.u8 q11, d18, d0
633
vqmovun.s16 d16, q10
634
vqmovun.s16 d17, q11
635
vst1.8 {d16}, [r0,:64], r1
636
vst1.8 {d17}, [r0,:64], r1
637
bgt weight8_nodenom_loop
638
pop {r4-r5,pc}
639
endfunc
640
641
function x264_mc_weight_w4_nodenom_neon
642
weight_prologue nodenom
643
weight4_nodenom_loop:
644
subs ip, #2
645
vld1.32 {d16[0]}, [r2], r3
646
vld1.32 {d16[1]}, [r2], r3
647
vmov q10, q1
648
vmlal.u8 q10, d16, d0
649
vqmovun.s16 d16, q10
650
vst1.32 {d16[0]}, [r0], r1
651
vst1.32 {d16[1]}, [r0], r1
652
bgt weight4_nodenom_loop
653
pop {r4-r5,pc}
654
endfunc
655
656
.macro weight_simple_prologue
657
push {lr}
658
ldr lr, [sp, #4] // weight_t
659
ldr ip, [sp, #8] // h
660
ldr lr, [lr] // offset
661
vdup.8 q1, lr
662
.endm
663
664
.macro weight_simple name op
665
function x264_mc_weight_w20_\name\()_neon
666
weight_simple_prologue
667
weight20_\name\()_loop:
668
subs ip, #2
669
vld1.8 {d16-d18}, [r2], r3
670
vld1.8 {d19-d21}, [r2], r3
671
\op q8, q8, q1
672
\op q9, q9, q1
673
\op q10, q10, q1
674
vst1.8 {d16-d18}, [r0,:64], r1
675
vst1.8 {d19-d21}, [r0,:64], r1
676
bgt weight20_\name\()_loop
677
pop {pc}
678
endfunc
679
680
function x264_mc_weight_w16_\name\()_neon
681
weight_simple_prologue
682
weight16_\name\()_loop:
683
subs ip, #2
684
vld1.8 {d16-d17}, [r2], r3
685
vld1.8 {d18-d19}, [r2], r3
686
\op q8, q8, q1
687
\op q9, q9, q1
688
vst1.8 {d16-d17}, [r0,:128], r1
689
vst1.8 {d18-d19}, [r0,:128], r1
690
bgt weight16_\name\()_loop
691
pop {pc}
692
endfunc
693
694
function x264_mc_weight_w8_\name\()_neon
695
weight_simple_prologue
696
weight8_\name\()_loop:
697
subs ip, #2
698
vld1.8 {d16}, [r2], r3
699
vld1.8 {d17}, [r2], r3
700
\op q8, q8, q1
701
vst1.8 {d16}, [r0,:64], r1
702
vst1.8 {d17}, [r0,:64], r1
703
bgt weight8_\name\()_loop
704
pop {pc}
705
endfunc
706
707
function x264_mc_weight_w4_\name\()_neon
708
weight_simple_prologue
709
weight4_\name\()_loop:
710
subs ip, #2
711
vld1.32 {d16[]}, [r2], r3
712
vld1.32 {d17[]}, [r2], r3
713
\op q8, q8, q1
714
vst1.32 {d16[0]}, [r0], r1
715
vst1.32 {d17[0]}, [r0], r1
716
bgt weight4_\name\()_loop
717
pop {pc}
718
endfunc
719
.endm
720
721
weight_simple offsetadd, vqadd.u8
722
weight_simple offsetsub, vqsub.u8
723
724
725
// void mc_copy( uint8_t *dst, intptr_t dst_stride, uint8_t *src, intptr_t src_stride, int height )
726
function x264_mc_copy_w4_neon
727
ldr ip, [sp]
728
copy_w4_loop:
729
subs ip, ip, #4
730
vld1.32 {d0[]}, [r2], r3
731
vld1.32 {d1[]}, [r2], r3
732
vld1.32 {d2[]}, [r2], r3
733
vld1.32 {d3[]}, [r2], r3
734
vst1.32 {d0[0]}, [r0,:32], r1
735
vst1.32 {d1[0]}, [r0,:32], r1
736
vst1.32 {d2[0]}, [r0,:32], r1
737
vst1.32 {d3[0]}, [r0,:32], r1
738
bgt copy_w4_loop
739
bx lr
740
endfunc
741
742
function x264_mc_copy_w8_neon
743
ldr ip, [sp]
744
copy_w8_loop:
745
subs ip, ip, #4
746
vld1.32 {d0}, [r2], r3
747
vld1.32 {d1}, [r2], r3
748
vld1.32 {d2}, [r2], r3
749
vld1.32 {d3}, [r2], r3
750
vst1.32 {d0}, [r0,:64], r1
751
vst1.32 {d1}, [r0,:64], r1
752
vst1.32 {d2}, [r0,:64], r1
753
vst1.32 {d3}, [r0,:64], r1
754
bgt copy_w8_loop
755
bx lr
756
endfunc
757
758
function x264_mc_copy_w16_neon
759
ldr ip, [sp]
760
copy_w16_loop:
761
subs ip, ip, #4
762
vld1.32 {d0-d1}, [r2], r3
763
vld1.32 {d2-d3}, [r2], r3
764
vld1.32 {d4-d5}, [r2], r3
765
vld1.32 {d6-d7}, [r2], r3
766
vst1.32 {d0-d1}, [r0,:128], r1
767
vst1.32 {d2-d3}, [r0,:128], r1
768
vst1.32 {d4-d5}, [r0,:128], r1
769
vst1.32 {d6-d7}, [r0,:128], r1
770
bgt copy_w16_loop
771
bx lr
772
endfunc
773
774
function x264_mc_copy_w16_aligned_neon
775
ldr ip, [sp]
776
copy_w16_aligned_loop:
777
subs ip, ip, #4
778
vld1.32 {d0-d1}, [r2,:128], r3
779
vld1.32 {d2-d3}, [r2,:128], r3
780
vld1.32 {d4-d5}, [r2,:128], r3
781
vld1.32 {d6-d7}, [r2,:128], r3
782
vst1.32 {d0-d1}, [r0,:128], r1
783
vst1.32 {d2-d3}, [r0,:128], r1
784
vst1.32 {d4-d5}, [r0,:128], r1
785
vst1.32 {d6-d7}, [r0,:128], r1
786
bgt copy_w16_aligned_loop
787
bx lr
788
endfunc
789
790
791
// void x264_mc_chroma_neon( uint8_t *dst, intptr_t i_dst_stride,
792
// uint8_t *src, intptr_t i_src_stride,
793
// int dx, int dy, int i_width, int i_height );
794
795
function x264_mc_chroma_neon
796
push {r4-r8, lr}
797
vpush {d8-d11}
798
ldrd r4, r5, [sp, #56]
799
ldrd r6, r7, [sp, #64]
800
801
asr lr, r6, #3
802
mul lr, r4, lr
803
add r3, r3, r5, asr #2
804
cmp r7, #4
805
806
and r5, r5, #7
807
and r6, r6, #7
808
809
add r3, r3, lr
810
bic r3, r3, #0x1
811
812
pld [r3]
813
pld [r3, r4]
814
815
bgt mc_chroma_w8
816
beq mc_chroma_w4
817
818
.macro CHROMA_MC_START r00, r01, r10, r11
819
muls lr, r5, r6
820
rsb r7, lr, r6, lsl #3
821
rsb ip, lr, r5, lsl #3
822
sub r5, lr, r5, lsl #3
823
sub r5, r5, r6, lsl #3
824
add r5, r5, #64
825
826
beq 2f
827
vld2.8 {\r00-\r01}, [r3], r4
828
829
vdup.8 d0, r5
830
vdup.8 d1, ip
831
832
vdup.8 d2, r7
833
vld2.8 {\r10-\r11}, [r3], r4
834
vdup.8 d3, lr
835
ldr r5, [sp, #72]
836
.endm
837
838
.macro CHROMA_MC width, align
839
mc_chroma_w\width:
840
CHROMA_MC_START d4, d5, d8, d9
841
vext.8 d6, d4, d6, #1
842
vext.8 d7, d5, d7, #1
843
vext.8 d10, d8, d10, #1
844
vext.8 d11, d9, d11, #1
845
// since the element size varies, there's a different index for the 2nd store
846
.if \width == 4
847
.set st2, 1
848
.else
849
.set st2, 2
850
.endif
851
852
vtrn.32 d4, d6
853
vtrn.32 d5, d7
854
vtrn.32 d8, d10
855
vtrn.32 d9, d11
856
857
vtrn.32 d0, d1
858
vtrn.32 d2, d3
859
860
1: // height loop, interpolate xy
861
862
vmull.u8 q8, d4, d0
863
vmlal.u8 q8, d8, d2
864
vmull.u8 q9, d5, d0
865
vmlal.u8 q9, d9, d2
866
867
vld2.8 {d4-d5}, [r3], r4
868
869
vext.8 d6, d4, d6, #1
870
vext.8 d7, d5, d7, #1
871
872
vadd.i16 d16, d16, d17
873
vadd.i16 d17, d18, d19
874
875
vtrn.32 d4, d6
876
vtrn.32 d5, d7
877
878
vmull.u8 q10, d8, d0
879
vmlal.u8 q10, d4, d2
880
vmull.u8 q11, d9, d0
881
vmlal.u8 q11, d5, d2
882
883
vld2.8 {d8-d9}, [r3], r4
884
885
vrshrn.u16 d16, q8, #6
886
887
vext.8 d10, d8, d10, #1
888
vext.8 d11, d9, d11, #1
889
890
vadd.i16 d18, d20, d21
891
vadd.i16 d19, d22, d23
892
893
vtrn.32 d8, d10
894
vtrn.32 d9, d11
895
896
vrshrn.u16 d18, q9, #6
897
898
subs r5, r5, #2
899
900
pld [r3]
901
pld [r3, r4]
902
903
vst1.\align {d16[0]}, [r0,:\align], r2
904
vst1.\align {d16[st2]}, [r1,:\align], r2
905
vst1.\align {d18[0]}, [r0,:\align], r2
906
vst1.\align {d18[st2]}, [r1,:\align], r2
907
bgt 1b
908
909
vpop {d8-d11}
910
pop {r4-r8, pc}
911
912
2: // dx or dy are 0
913
tst r7, r7
914
add ip, ip, r7
915
vdup.8 d0, r5
916
ldr r5, [sp, #72]
917
vdup.8 d1, ip
918
919
beq 4f
920
921
vld1.64 {d4}, [r3], r4
922
vld1.64 {d6}, [r3], r4
923
924
3: // vertical interpolation loop
925
926
vmull.u8 q8, d4, d0
927
vmlal.u8 q8, d6, d1
928
vmull.u8 q9, d6, d0
929
vld1.64 {d4}, [r3], r4
930
vmlal.u8 q9, d4, d1
931
vld1.64 {d6}, [r3], r4
932
933
vrshrn.u16 d16, q8, #6 // uvuvuvuv
934
vrshrn.u16 d17, q9, #6 // uvuvuvuv
935
subs r5, r5, #2
936
vuzp.8 d16, d17 // d16=uuuu|uuuu, d17=vvvv|vvvv
937
938
pld [r3]
939
pld [r3, r4]
940
941
vst1.\align {d16[0]}, [r0,:\align], r2
942
vst1.\align {d16[st2]}, [r0,:\align], r2
943
vst1.\align {d17[0]}, [r1,:\align], r2
944
vst1.\align {d17[st2]}, [r1,:\align], r2
945
bgt 3b
946
947
vpop {d8-d11}
948
pop {r4-r8, pc}
949
950
4: // dy is 0
951
952
vld1.64 {d4-d5}, [r3], r4
953
vld1.64 {d6-d7}, [r3], r4
954
955
vext.8 d5, d4, d5, #2
956
vext.8 d7, d6, d7, #2
957
958
5: // horizontal interpolation loop
959
960
vmull.u8 q8, d4, d0
961
vmlal.u8 q8, d5, d1
962
vmull.u8 q9, d6, d0
963
vmlal.u8 q9, d7, d1
964
965
subs r5, r5, #2
966
vld1.64 {d4-d5}, [r3], r4
967
vld1.64 {d6-d7}, [r3], r4
968
vext.8 d5, d4, d5, #2
969
vrshrn.u16 d16, q8, #6
970
vrshrn.u16 d17, q9, #6
971
vext.8 d7, d6, d7, #2
972
vuzp.8 d16, d17
973
974
pld [r3]
975
pld [r3, r4]
976
977
vst1.\align {d16[0]}, [r0,:\align], r2
978
vst1.\align {d16[st2]}, [r0,:\align], r2
979
vst1.\align {d17[0]}, [r1,:\align], r2
980
vst1.\align {d17[st2]}, [r1,:\align], r2
981
bgt 5b
982
983
vpop {d8-d11}
984
pop {r4-r8, pc}
985
.endm
986
987
CHROMA_MC 2, 16
988
CHROMA_MC 4, 32
989
990
mc_chroma_w8:
991
CHROMA_MC_START d4, d7, d8, d11
992
vext.8 d5, d4, d5, #1
993
vext.8 d9, d8, d9, #1
994
vext.8 d7, d6, d7, #1
995
vext.8 d11, d10, d11, #1
996
997
1: // height loop, interpolate xy
998
vmull.u8 q8, d4, d0
999
vmlal.u8 q8, d5, d1
1000
vmlal.u8 q8, d8, d2
1001
vmlal.u8 q8, d9, d3
1002
1003
vmull.u8 q9, d6, d0
1004
vmlal.u8 q9, d7, d1
1005
vmlal.u8 q9, d10, d2
1006
vmlal.u8 q9, d11, d3
1007
1008
vld2.8 {d4-d7}, [r3], r4
1009
1010
vext.8 d5, d4, d5, #1
1011
vext.8 d7, d6, d7, #1
1012
1013
vmull.u8 q10, d8, d0
1014
vmlal.u8 q10, d9, d1
1015
vmlal.u8 q10, d4, d2
1016
vmlal.u8 q10, d5, d3
1017
1018
vmull.u8 q11, d10, d0
1019
vmlal.u8 q11, d11, d1
1020
vmlal.u8 q11, d6, d2
1021
vmlal.u8 q11, d7, d3
1022
1023
subs r5, r5, #2
1024
vld2.8 {d8-d11}, [r3], r4
1025
1026
vrshrn.u16 d16, q8, #6
1027
vrshrn.u16 d17, q9, #6
1028
vrshrn.u16 d18, q10, #6
1029
vext.8 d9, d8, d9, #1
1030
vrshrn.u16 d19, q11, #6
1031
vext.8 d11, d10, d11, #1
1032
1033
pld [r3]
1034
pld [r3, r4]
1035
1036
vst1.64 {d16}, [r0,:64], r2
1037
vst1.64 {d17}, [r1,:64], r2
1038
vst1.64 {d18}, [r0,:64], r2
1039
vst1.64 {d19}, [r1,:64], r2
1040
1041
bgt 1b
1042
1043
vpop {d8-d11}
1044
pop {r4-r8, pc}
1045
1046
2: // dx or dy are 0
1047
tst r7, r7
1048
add ip, ip, r7
1049
vdup.8 d0, r5
1050
ldr r5, [sp, #72]
1051
vdup.8 d1, ip
1052
1053
beq 4f
1054
1055
vld2.8 {d4-d5}, [r3], r4
1056
vld2.8 {d6-d7}, [r3], r4
1057
1058
3: // vertical interpolation loop
1059
vmull.u8 q8, d4, d0 //U
1060
vmlal.u8 q8, d6, d1
1061
vmull.u8 q9, d5, d0 //V
1062
vmlal.u8 q9, d7, d1
1063
1064
vld2.8 {d4-d5}, [r3], r4
1065
1066
vmull.u8 q10, d6, d0
1067
vmlal.u8 q10, d4, d1
1068
vmull.u8 q11, d7, d0
1069
vmlal.u8 q11, d5, d1
1070
1071
vld2.8 {d6-d7}, [r3], r4
1072
1073
vrshrn.u16 d16, q8, #6
1074
vrshrn.u16 d17, q9, #6
1075
vrshrn.u16 d18, q10, #6
1076
vrshrn.u16 d19, q11, #6
1077
subs r5, r5, #2
1078
1079
pld [r3]
1080
pld [r3, r4]
1081
1082
vst1.64 {d16}, [r0,:64], r2
1083
vst1.64 {d17}, [r1,:64], r2
1084
vst1.64 {d18}, [r0,:64], r2
1085
vst1.64 {d19}, [r1,:64], r2
1086
1087
bgt 3b
1088
1089
vpop {d8-d11}
1090
pop {r4-r8, pc}
1091
1092
4: // dy is 0
1093
1094
vld2.8 {d4-d7}, [r3], r4
1095
vld2.8 {d8-d11}, [r3], r4
1096
vext.8 d5, d4, d5, #1
1097
vext.8 d7, d6, d7, #1
1098
vext.8 d9, d8, d9, #1
1099
vext.8 d11, d10, d11, #1
1100
1101
5: // horizontal interpolation loop
1102
subs r5, r5, #2
1103
vmull.u8 q8, d4, d0 //U
1104
vmlal.u8 q8, d5, d1
1105
vmull.u8 q9, d6, d0 //V
1106
vmlal.u8 q9, d7, d1
1107
1108
vld2.8 {d4-d7}, [r3], r4
1109
1110
vmull.u8 q10, d8, d0
1111
vmlal.u8 q10, d9, d1
1112
vmull.u8 q11, d10, d0
1113
vmlal.u8 q11, d11, d1
1114
1115
vld2.8 {d8-d11}, [r3], r4
1116
1117
vext.8 d5, d4, d5, #1
1118
vrshrn.u16 d16, q8, #6
1119
vext.8 d7, d6, d7, #1
1120
vrshrn.u16 d17, q9, #6
1121
vext.8 d9, d8, d9, #1
1122
vrshrn.u16 d18, q10, #6
1123
vext.8 d11, d10, d11, #1
1124
vrshrn.u16 d19, q11, #6
1125
1126
pld [r3]
1127
pld [r3, r4]
1128
1129
vst1.64 {d16}, [r0,:64], r2
1130
vst1.64 {d17}, [r1,:64], r2
1131
vst1.64 {d18}, [r0,:64], r2
1132
vst1.64 {d19}, [r1,:64], r2
1133
bgt 5b
1134
1135
vpop {d8-d11}
1136
pop {r4-r8, pc}
1137
1138
endfunc
1139
1140
1141
// hpel_filter_v( uint8_t *dst, uint8_t *src, int16_t *buf, intptr_t stride, int width )
1142
function x264_hpel_filter_v_neon
1143
ldr ip, [sp]
1144
sub r1, r1, r3, lsl #1
1145
push {lr}
1146
add lr, r1, ip
1147
vmov.u8 d30, #5
1148
vmov.u8 d31, #20
1149
1150
filter_v_loop:
1151
subs ip, ip, #16
1152
vld1.64 {d0-d1}, [r1,:128], r3
1153
vld1.64 {d2-d3}, [r1,:128], r3
1154
vld1.64 {d4-d5}, [r1,:128], r3
1155
vld1.64 {d6-d7}, [r1,:128], r3
1156
vld1.64 {d16-d17}, [r1,:128], r3
1157
vld1.64 {d18-d19}, [r1,:128], r3
1158
sub r1, lr, ip
1159
1160
vaddl.u8 q10, d0, d18
1161
vmlsl.u8 q10, d2, d30
1162
vmlal.u8 q10, d4, d31
1163
vmlal.u8 q10, d6, d31
1164
vmlsl.u8 q10, d16, d30
1165
1166
vaddl.u8 q11, d1, d19
1167
vmlsl.u8 q11, d3, d30
1168
vmlal.u8 q11, d5, d31
1169
vmlal.u8 q11, d7, d31
1170
vmlsl.u8 q11, d17, d30
1171
1172
vqrshrun.s16 d0, q10, #5
1173
vst1.64 {d20-d21}, [r2,:128]!
1174
vqrshrun.s16 d1, q11, #5
1175
vst1.64 {d22-d23}, [r2,:128]!
1176
vst1.64 {d0-d1}, [r0,:128]!
1177
bgt filter_v_loop
1178
pop {pc}
1179
endfunc
1180
1181
// hpel_filter_c( uint8_t *dst, int16_t *buf, int width );
1182
function x264_hpel_filter_c_neon
1183
sub r1, #16
1184
vld1.64 {d0-d3}, [r1,:128]!
1185
1186
// unrolled 2x: 4% faster
1187
filter_c_loop:
1188
subs r2, r2, #16
1189
vld1.64 {d4-d7}, [r1,:128]!
1190
vext.16 q8, q0, q1, #6
1191
vext.16 q12, q1, q2, #3
1192
vadd.s16 q8, q8, q12
1193
vext.16 q9, q0, q1, #7
1194
vext.16 q11, q1, q2, #2
1195
vadd.s16 q9, q9, q11
1196
vext.16 q10, q1, q2, #1
1197
vext.16 q11, q1, q2, #6
1198
vadd.s16 q10, q1, q10
1199
vsub.s16 q8, q8, q9 // a-b
1200
vext.16 q15, q2, q3, #3
1201
vsub.s16 q9, q9, q10 // b-c
1202
1203
vext.16 q12, q1, q2, #7
1204
vshr.s16 q8, q8, #2 // (a-b)/4
1205
vadd.s16 q11, q11, q15
1206
vext.16 q14, q2, q3, #2
1207
vsub.s16 q8, q8, q9 // (a-b)/4-b+c
1208
vadd.s16 q12, q12, q14
1209
vext.16 q13, q2, q3, #1
1210
1211
vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4
1212
vadd.s16 q13, q2, q13
1213
vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1214
vsub.s16 q11, q11, q12 // a-b
1215
vsub.s16 q12, q12, q13 // b-c
1216
vshr.s16 q11, q11, #2 // (a-b)/4
1217
vqrshrun.s16 d30, q8, #6
1218
vsub.s16 q11, q11, q12 // (a-b)/4-b+c
1219
vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4
1220
vld1.64 {d0-d3}, [r1,:128]!
1221
vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1222
1223
vext.16 q8, q2, q3, #6
1224
vqrshrun.s16 d31, q11, #6
1225
vext.16 q12, q3, q0, #3
1226
vadd.s16 q8, q8, q12
1227
vext.16 q9, q2, q3, #7
1228
vst1.64 {d30-d31}, [r0,:128]!
1229
bxle lr
1230
subs r2, r2, #16
1231
1232
vext.16 q11, q3, q0, #2
1233
vadd.s16 q9, q9, q11
1234
vext.16 q10, q3, q0, #1
1235
vext.16 q11, q3, q0, #6
1236
vadd.s16 q10, q3, q10
1237
vsub.s16 q8, q8, q9 // a-b
1238
vext.16 q15, q0, q1, #3
1239
vsub.s16 q9, q9, q10 // b-c
1240
1241
vext.16 q12, q3, q0, #7
1242
vshr.s16 q8, q8, #2 // (a-b)/4
1243
vadd.s16 q11, q11, q15
1244
vext.16 q14, q0, q1, #2
1245
vsub.s16 q8, q8, q9 // (a-b)/4-b+c
1246
vadd.s16 q12, q12, q14
1247
vext.16 q13, q0, q1, #1
1248
1249
vshr.s16 q8, q8, #2 // ((a-b)/4-b+c)/4
1250
vadd.s16 q13, q0, q13
1251
vadd.s16 q8, q8, q10 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1252
vsub.s16 q11, q11, q12 // a-b
1253
vsub.s16 q12, q12, q13 // b-c
1254
vshr.s16 q11, q11, #2 // (a-b)/4
1255
vqrshrun.s16 d30, q8, #6
1256
vsub.s16 q11, q11, q12 // (a-b)/4-b+c
1257
vshr.s16 q11, q11, #2 // ((a-b)/4-b+c)/4
1258
vadd.s16 q11, q11, q13 // ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16
1259
1260
vqrshrun.s16 d31, q11, #6
1261
vst1.64 {d30-d31}, [r0,:128]!
1262
bgt filter_c_loop
1263
bx lr
1264
endfunc
1265
1266
// hpel_filter_h( uint8_t *dst, uint8_t *src, int width );
1267
function x264_hpel_filter_h_neon
1268
sub r1, #16
1269
vmov.u8 d30, #5
1270
vld1.64 {d0-d3}, [r1,:128]!
1271
vmov.u8 d31, #20
1272
1273
// unrolled 3x because it's 5% faster, due to mitigating
1274
// the high latency of multiplication and vqrshrun
1275
filter_h_loop:
1276
subs r2, r2, #16
1277
vld1.64 {d4-d5}, [r1,:128]!
1278
vext.8 q8, q0, q1, #14
1279
vext.8 q12, q1, q2, #3
1280
vaddl.u8 q13, d16, d24
1281
vext.8 q9, q0, q1, #15
1282
vaddl.u8 q14, d17, d25
1283
1284
vext.8 q10, q1, q2, #1
1285
vmlal.u8 q13, d2, d31
1286
vmlsl.u8 q13, d18, d30
1287
vext.8 q11, q1, q2, #2
1288
vmlal.u8 q13, d20, d31
1289
vmlsl.u8 q13, d22, d30
1290
1291
vmlsl.u8 q14, d19, d30
1292
vmlal.u8 q14, d3, d31
1293
vmlal.u8 q14, d21, d31
1294
vmlsl.u8 q14, d23, d30
1295
vqrshrun.s16 d6, q13, #5
1296
1297
vld1.64 {d0-d1}, [r1,:128]!
1298
vext.8 q8, q1, q2, #14
1299
vext.8 q12, q2, q0, #3
1300
vaddl.u8 q13, d16, d24
1301
vqrshrun.s16 d7, q14, #5
1302
vext.8 q9, q1, q2, #15
1303
vaddl.u8 q14, d17, d25
1304
1305
vst1.64 {d6-d7}, [r0,:128]!
1306
bxle lr
1307
subs r2, r2, #16
1308
1309
vext.8 q10, q2, q0, #1
1310
vmlal.u8 q13, d4, d31
1311
vmlsl.u8 q13, d18, d30
1312
vext.8 q11, q2, q0, #2
1313
vmlal.u8 q13, d20, d31
1314
vmlsl.u8 q13, d22, d30
1315
1316
vmlsl.u8 q14, d19, d30
1317
vmlal.u8 q14, d5, d31
1318
vmlal.u8 q14, d21, d31
1319
vmlsl.u8 q14, d23, d30
1320
vqrshrun.s16 d6, q13, #5
1321
1322
vld1.64 {d2-d3}, [r1,:128]!
1323
vext.8 q8, q2, q0, #14
1324
vext.8 q12, q0, q1, #3
1325
vaddl.u8 q13, d16, d24
1326
vqrshrun.s16 d7, q14, #5
1327
vext.8 q9, q2, q0, #15
1328
vaddl.u8 q14, d17, d25
1329
1330
vst1.64 {d6-d7}, [r0,:128]!
1331
bxle lr
1332
subs r2, r2, #16
1333
1334
vext.8 q10, q0, q1, #1
1335
vmlal.u8 q13, d0, d31
1336
vmlsl.u8 q13, d18, d30
1337
vext.8 q11, q0, q1, #2
1338
vmlal.u8 q13, d20, d31
1339
vmlsl.u8 q13, d22, d30
1340
1341
vmlsl.u8 q14, d19, d30
1342
vmlal.u8 q14, d1, d31
1343
vmlal.u8 q14, d21, d31
1344
vmlsl.u8 q14, d23, d30
1345
1346
vqrshrun.s16 d6, q13, #5
1347
vqrshrun.s16 d7, q14, #5
1348
vst1.64 {d6-d7}, [r0,:128]!
1349
bgt filter_h_loop
1350
bx lr
1351
endfunc
1352
1353
1354
// frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv,
1355
// uint8_t *dstc, intptr_t src_stride, intptr_t dst_stride, int width,
1356
// int height )
1357
function x264_frame_init_lowres_core_neon
1358
push {r4-r10,lr}
1359
vpush {d8-d15}
1360
ldrd r4, r5, [sp, #96]
1361
ldrd r6, r7, [sp, #104]
1362
ldr lr, [sp, #112]
1363
sub r10, r6, r7 // dst_stride - width
1364
and r10, r10, #~15
1365
1366
lowres_yloop:
1367
mov ip, r7 // width
1368
mov r6, r0 // src0
1369
add r8, r0, r5 // src1 = src0 + src_stride
1370
add r9, r0, r5, lsl #1 // src2 = src1 + src_stride
1371
1372
vld2.8 {d8, d10}, [r6,:128]!
1373
vld2.8 {d12,d14}, [r8,:128]!
1374
vld2.8 {d16,d18}, [r9,:128]!
1375
1376
lowres_xloop:
1377
subs ip, ip, #16
1378
1379
vld2.8 {d9, d11}, [r6,:128]!
1380
vld2.8 {d13,d15}, [r8,:128]!
1381
vrhadd.u8 q0, q4, q6
1382
vld2.8 {d17,d19}, [r9,:128]!
1383
vrhadd.u8 q5, q5, q7
1384
vld2.8 {d20,d22}, [r6,:128]!
1385
vrhadd.u8 q1, q6, q8
1386
vld2.8 {d24,d26}, [r8,:128]!
1387
vrhadd.u8 q7, q7, q9
1388
vext.8 q4, q4, q10, #1
1389
vrhadd.u8 q0, q0, q5
1390
vext.8 q6, q6, q12, #1
1391
vrhadd.u8 q1, q1, q7
1392
vld2.8 {d28,d30}, [r9,:128]!
1393
vrhadd.u8 q4, q4, q6
1394
vext.8 q8, q8, q14, #1
1395
vrhadd.u8 q6, q6, q8
1396
vst1.64 {d0-d1}, [r1,:128]!
1397
vrhadd.u8 q2, q4, q5
1398
vst1.64 {d2-d3}, [r3,:128]!
1399
vrhadd.u8 q3, q6, q7
1400
vst1.64 {d4-d5}, [r2,:128]!
1401
vst1.64 {d6-d7}, [r4,:128]!
1402
1403
ble lowres_xloop_end
1404
subs ip, ip, #16
1405
1406
vld2.8 {d21,d23}, [r6,:128]!
1407
vld2.8 {d25,d27}, [r8,:128]!
1408
vrhadd.u8 q0, q10, q12
1409
vld2.8 {d29,d31}, [r9,:128]!
1410
vrhadd.u8 q11, q11, q13
1411
vld2.8 {d8, d10}, [r6,:128]!
1412
vrhadd.u8 q1, q12, q14
1413
vld2.8 {d12,d14}, [r8,:128]!
1414
vrhadd.u8 q13, q13, q15
1415
vext.8 q10, q10, q4, #1
1416
vrhadd.u8 q0, q0, q11
1417
vext.8 q12, q12, q6, #1
1418
vrhadd.u8 q1, q1, q13
1419
vld2.8 {d16,d18}, [r9,:128]!
1420
vrhadd.u8 q10, q10, q12
1421
vext.8 q14, q14, q8, #1
1422
vrhadd.u8 q12, q12, q14
1423
vst1.64 {d0-d1}, [r1,:128]!
1424
vrhadd.u8 q2, q10, q11
1425
vst1.64 {d2-d3}, [r3,:128]!
1426
vrhadd.u8 q3, q12, q13
1427
vst1.64 {d4-d5}, [r2,:128]!
1428
vst1.64 {d6-d7}, [r4,:128]!
1429
1430
bgt lowres_xloop
1431
1432
lowres_xloop_end:
1433
subs lr, lr, #1
1434
add r0, r0, r5, lsl #1
1435
add r1, r1, r10
1436
add r2, r2, r10
1437
add r3, r3, r10
1438
add r4, r4, r10
1439
bgt lowres_yloop
1440
1441
vpop {d8-d15}
1442
pop {r4-r10,pc}
1443
endfunc
1444
1445
function x264_load_deinterleave_chroma_fdec_neon
1446
mov ip, #FDEC_STRIDE/2
1447
1:
1448
vld2.8 {d0-d1}, [r1,:128], r2
1449
subs r3, r3, #1
1450
pld [r1]
1451
vst1.8 {d0}, [r0,:64], ip
1452
vst1.8 {d1}, [r0,:64], ip
1453
bgt 1b
1454
1455
bx lr
1456
endfunc
1457
1458
function x264_load_deinterleave_chroma_fenc_neon
1459
mov ip, #FENC_STRIDE/2
1460
1:
1461
vld2.8 {d0-d1}, [r1,:128], r2
1462
subs r3, r3, #1
1463
pld [r1]
1464
vst1.8 {d0}, [r0,:64], ip
1465
vst1.8 {d1}, [r0,:64], ip
1466
bgt 1b
1467
1468
bx lr
1469
endfunc
1470
1471
function x264_plane_copy_neon
1472
push {r4,lr}
1473
ldr r4, [sp, #8]
1474
ldr lr, [sp, #12]
1475
add r12, r4, #15
1476
bic r4, r12, #15
1477
sub r1, r1, r4
1478
sub r3, r3, r4
1479
1:
1480
mov r12, r4
1481
16:
1482
tst r12, #16
1483
beq 32f
1484
subs r12, r12, #16
1485
vld1.8 {q0}, [r2]!
1486
vst1.8 {q0}, [r0]!
1487
beq 0f
1488
32:
1489
subs r12, r12, #32
1490
vld1.8 {q0, q1}, [r2]!
1491
vst1.8 {q0, q1}, [r0]!
1492
bgt 32b
1493
0:
1494
subs lr, lr, #1
1495
add r2, r2, r3
1496
add r0, r0, r1
1497
bgt 1b
1498
1499
pop {r4,pc}
1500
endfunc
1501
1502
function x264_plane_copy_deinterleave_neon
1503
push {r4-r7, lr}
1504
ldrd r6, r7, [sp, #28]
1505
ldrd r4, r5, [sp, #20]
1506
add lr, r6, #15
1507
bic lr, lr, #15
1508
sub r1, r1, lr
1509
sub r3, r3, lr
1510
sub r5, r5, lr, lsl #1
1511
block:
1512
vld2.8 {d0-d3}, [r4,:128]!
1513
subs lr, lr, #16
1514
vst1.8 {q0}, [r0]!
1515
vst1.8 {q1}, [r2]!
1516
bgt block
1517
1518
add r4, r4, r5
1519
subs r7, r7, #1
1520
add r0, r0, r1
1521
add r2, r2, r3
1522
mov lr, r6
1523
bgt block
1524
1525
pop {r4-r7, pc}
1526
endfunc
1527
1528
function x264_plane_copy_deinterleave_rgb_neon
1529
push {r4-r8, r10, r11, lr}
1530
ldrd r4, r5, [sp, #32]
1531
ldrd r6, r7, [sp, #40]
1532
ldr r8, [sp, #48]
1533
ldrd r10, r11, [sp, #52]
1534
add lr, r10, #7
1535
subs r8, r8, #3
1536
bic lr, lr, #7
1537
sub r7, r7, lr, lsl #1
1538
sub r1, r1, lr
1539
sub r3, r3, lr
1540
sub r5, r5, lr
1541
subne r7, r7, lr, lsl #1
1542
subeq r7, r7, lr
1543
bne block4
1544
block3:
1545
vld3.8 {d0,d1,d2}, [r6]!
1546
subs lr, lr, #8
1547
vst1.8 {d0}, [r0]!
1548
vst1.8 {d1}, [r2]!
1549
vst1.8 {d2}, [r4]!
1550
bgt block3
1551
1552
subs r11, r11, #1
1553
add r0, r0, r1
1554
add r2, r2, r3
1555
add r4, r4, r5
1556
add r6, r6, r7
1557
mov lr, r10
1558
bgt block3
1559
1560
pop {r4-r8, r10, r11, pc}
1561
block4:
1562
vld4.8 {d0,d1,d2,d3}, [r6]!
1563
subs lr, lr, #8
1564
vst1.8 {d0}, [r0]!
1565
vst1.8 {d1}, [r2]!
1566
vst1.8 {d2}, [r4]!
1567
bgt block4
1568
1569
subs r11, r11, #1
1570
add r0, r0, r1
1571
add r2, r2, r3
1572
add r4, r4, r5
1573
add r6, r6, r7
1574
mov lr, r10
1575
bgt block4
1576
1577
pop {r4-r8, r10, r11, pc}
1578
endfunc
1579
1580
function x264_plane_copy_interleave_neon
1581
push {r4-r7, lr}
1582
ldrd r6, r7, [sp, #28]
1583
ldrd r4, r5, [sp, #20]
1584
add lr, r6, #15
1585
bic lr, lr, #15
1586
sub r1, r1, lr, lsl #1
1587
sub r3, r3, lr
1588
sub r5, r5, lr
1589
blocki:
1590
vld1.8 {q0}, [r2]!
1591
vld1.8 {q1}, [r4]!
1592
subs lr, lr, #16
1593
vst2.8 {d0,d2}, [r0]!
1594
vst2.8 {d1,d3}, [r0]!
1595
bgt blocki
1596
1597
subs r7, r7, #1
1598
add r0, r0, r1
1599
add r2, r2, r3
1600
add r4, r4, r5
1601
mov lr, r6
1602
bgt blocki
1603
1604
pop {r4-r7, pc}
1605
endfunc
1606
1607
function x264_plane_copy_swap_neon
1608
push {r4-r5, lr}
1609
ldrd r4, r5, [sp, #12]
1610
add lr, r4, #15
1611
bic lr, lr, #15
1612
sub r1, r1, lr, lsl #1
1613
sub r3, r3, lr, lsl #1
1614
1:
1615
vld1.8 {q0, q1}, [r2]!
1616
subs lr, lr, #16
1617
vrev16.8 q0, q0
1618
vrev16.8 q1, q1
1619
vst1.8 {q0, q1}, [r0]!
1620
bgt 1b
1621
1622
subs r5, r5, #1
1623
add r0, r0, r1
1624
add r2, r2, r3
1625
mov lr, r4
1626
bgt 1b
1627
1628
pop {r4-r5, pc}
1629
endfunc
1630
1631
function x264_store_interleave_chroma_neon
1632
push {lr}
1633
ldr lr, [sp, #4]
1634
mov ip, #FDEC_STRIDE
1635
1:
1636
vld1.8 {d0}, [r2], ip
1637
vld1.8 {d1}, [r3], ip
1638
subs lr, lr, #1
1639
vst2.8 {d0,d1}, [r0,:128], r1
1640
bgt 1b
1641
1642
pop {pc}
1643
endfunc
1644
1645
.macro integral4h p1, p2
1646
vext.8 d1, \p1, \p2, #1
1647
vext.8 d2, \p1, \p2, #2
1648
vext.8 d3, \p1, \p2, #3
1649
vaddl.u8 q0, \p1, d1
1650
vaddl.u8 q1, d2, d3
1651
vadd.u16 q0, q0, q1
1652
vadd.u16 q0, q0, q2
1653
.endm
1654
1655
function integral_init4h_neon
1656
sub r3, r0, r2, lsl #1
1657
vld1.8 {d6, d7}, [r1, :128]!
1658
1:
1659
subs r2, r2, #16
1660
vld1.16 {q2}, [r3, :128]!
1661
integral4h d6, d7
1662
vld1.8 {d6}, [r1, :64]!
1663
vld1.16 {q2}, [r3, :128]!
1664
vst1.16 {q0}, [r0, :128]!
1665
integral4h d7, d6
1666
vld1.8 {d7}, [r1, :64]!
1667
vst1.16 {q0}, [r0, :128]!
1668
bgt 1b
1669
bx lr
1670
endfunc
1671
1672
.macro integral8h p1, p2, s
1673
vext.8 d1, \p1, \p2, #1
1674
vext.8 d2, \p1, \p2, #2
1675
vext.8 d3, \p1, \p2, #3
1676
vext.8 d4, \p1, \p2, #4
1677
vext.8 d5, \p1, \p2, #5
1678
vext.8 d6, \p1, \p2, #6
1679
vext.8 d7, \p1, \p2, #7
1680
vaddl.u8 q0, \p1, d1
1681
vaddl.u8 q1, d2, d3
1682
vaddl.u8 q2, d4, d5
1683
vaddl.u8 q3, d6, d7
1684
vadd.u16 q0, q0, q1
1685
vadd.u16 q2, q2, q3
1686
vadd.u16 q0, q0, q2
1687
vadd.u16 q0, q0, \s
1688
.endm
1689
1690
function integral_init8h_neon
1691
sub r3, r0, r2, lsl #1
1692
vld1.8 {d16, d17}, [r1, :128]!
1693
1:
1694
subs r2, r2, #16
1695
vld1.16 {q9}, [r3, :128]!
1696
integral8h d16, d17, q9
1697
vld1.8 {d16}, [r1, :64]!
1698
vld1.16 {q9}, [r3, :128]!
1699
vst1.16 {q0}, [r0, :128]!
1700
integral8h d17, d16, q9
1701
vld1.8 {d17}, [r1, :64]!
1702
vst1.16 {q0}, [r0, :128]!
1703
bgt 1b
1704
bx lr
1705
endfunc
1706
1707
function integral_init4v_neon
1708
push {r4-r5}
1709
mov r3, r0
1710
add r4, r0, r2, lsl #3
1711
add r5, r0, r2, lsl #4
1712
sub r2, r2, #8
1713
vld1.16 {q11, q12}, [r3]!
1714
vld1.16 {q8, q9}, [r5]!
1715
vld1.16 {q13}, [r3]!
1716
vld1.16 {q10}, [r5]!
1717
1:
1718
subs r2, r2, #16
1719
vld1.16 {q14, q15}, [r4]!
1720
vext.8 q0, q11, q12, #8
1721
vext.8 q1, q12, q13, #8
1722
vext.8 q2, q8, q9, #8
1723
vext.8 q3, q9, q10, #8
1724
vsub.u16 q14, q14, q11
1725
vsub.u16 q15, q15, q12
1726
vadd.u16 q0, q0, q11
1727
vadd.u16 q1, q1, q12
1728
vadd.u16 q2, q2, q8
1729
vadd.u16 q3, q3, q9
1730
vst1.16 {q14}, [r1]!
1731
vst1.16 {q15}, [r1]!
1732
vmov q11, q13
1733
vmov q8, q10
1734
vsub.u16 q0, q2, q0
1735
vsub.u16 q1, q3, q1
1736
vld1.16 {q12, q13}, [r3]!
1737
vld1.16 {q9, q10}, [r5]!
1738
vst1.16 {q0}, [r0]!
1739
vst1.16 {q1}, [r0]!
1740
bgt 1b
1741
2:
1742
pop {r4-r5}
1743
bx lr
1744
endfunc
1745
1746
function integral_init8v_neon
1747
add r2, r0, r1, lsl #4
1748
sub r1, r1, #8
1749
ands r3, r1, #16 - 1
1750
beq 1f
1751
subs r1, r1, #8
1752
vld1.16 {q0}, [r0]
1753
vld1.16 {q2}, [r2]!
1754
vsub.u16 q8, q2, q0
1755
vst1.16 {q8}, [r0]!
1756
ble 2f
1757
1:
1758
subs r1, r1, #16
1759
vld1.16 {q0, q1}, [r0]
1760
vld1.16 {q2, q3}, [r2]!
1761
vsub.u16 q8, q2, q0
1762
vsub.u16 q9, q3, q1
1763
vst1.16 {q8}, [r0]!
1764
vst1.16 {q9}, [r0]!
1765
bgt 1b
1766
2:
1767
bx lr
1768
endfunc
1769
1770
function x264_mbtree_propagate_cost_neon
1771
push {r4-r5,lr}
1772
ldrd r4, r5, [sp, #12]
1773
ldr lr, [sp, #20]
1774
vld1.32 {d6[], d7[]}, [r5]
1775
8:
1776
subs lr, lr, #8
1777
vld1.16 {q8}, [r1]!
1778
vld1.16 {q9}, [r2]!
1779
vld1.16 {q10}, [r3]!
1780
vld1.16 {q11}, [r4]!
1781
vbic.u16 q10, #0xc000
1782
vmin.u16 q10, q9, q10
1783
vmull.u16 q12, d18, d22 @ propagate_intra
1784
vmull.u16 q13, d19, d23 @ propagate_intra
1785
vsubl.u16 q14, d18, d20 @ propagate_num
1786
vsubl.u16 q15, d19, d21 @ propagate_num
1787
vmovl.u16 q10, d18 @ propagate_denom
1788
vmovl.u16 q11, d19 @ propagate_denom
1789
vmovl.u16 q9, d17
1790
vmovl.u16 q8, d16
1791
vcvt.f32.s32 q12, q12
1792
vcvt.f32.s32 q13, q13
1793
vcvt.f32.s32 q14, q14
1794
vcvt.f32.s32 q15, q15
1795
vcvt.f32.s32 q10, q10
1796
vcvt.f32.s32 q11, q11
1797
vrecpe.f32 q0, q10
1798
vrecpe.f32 q1, q11
1799
vcvt.f32.s32 q8, q8
1800
vcvt.f32.s32 q9, q9
1801
vrecps.f32 q10, q0, q10
1802
vrecps.f32 q11, q1, q11
1803
vmla.f32 q8, q12, q3 @ propagate_amount
1804
vmla.f32 q9, q13, q3 @ propagate_amount
1805
vmul.f32 q0, q0, q10
1806
vmul.f32 q1, q1, q11
1807
vmul.f32 q8, q8, q14
1808
vmul.f32 q9, q9, q15
1809
vmul.f32 q0, q8, q0
1810
vmul.f32 q1, q9, q1
1811
vcvt.s32.f32 q0, q0
1812
vcvt.s32.f32 q1, q1
1813
vqmovn.s32 d0, q0
1814
vqmovn.s32 d1, q1
1815
vst1.16 {q0}, [r0]!
1816
bgt 8b
1817
pop {r4-r5,pc}
1818
endfunc
1819
1820
function x264_mbtree_propagate_list_internal_neon
1821
vld2.16 {d4[], d5[]}, [sp] @ bipred_weight, mb_y
1822
movrel r12, pw_0to15
1823
vmov.u16 q10, #0xc000
1824
vld1.16 {q0}, [r12, :128] @h->mb.i_mb_x,h->mb.i_mb_y
1825
vmov.u32 q11, #4
1826
vmov.u8 q3, #32
1827
vdup.u16 q8, d5[0] @ mb_y
1828
vzip.u16 q0, q8
1829
ldr r12, [sp, #8]
1830
8:
1831
subs r12, r12, #8
1832
vld1.16 {q14}, [r1, :128]! @ propagate_amount
1833
vld1.16 {q15}, [r2]! @ lowres_cost
1834
vld1.16 {q8, q9}, [r0]!
1835
vand q15, q15, q10
1836
vceq.u16 q1, q15, q10
1837
vmull.u16 q12, d28, d4
1838
vmull.u16 q13, d29, d4
1839
vrshrn.u32 d30, q12, #6
1840
vrshrn.u32 d31, q13, #6
1841
vbsl q1, q15, q14 @ if( lists_used == 3 )
1842
@ propagate_amount = (propagate_amount * bipred_weight + 32) >> 6
1843
vshr.s16 q12, q8, #5
1844
vshr.s16 q13, q9, #5
1845
vuzp.16 q8, q9 @ x & 31, y & 31
1846
vadd.s16 q12, q12, q0
1847
vadd.s16 q0, q0, q11
1848
vmovn.i16 d16, q8
1849
vmovn.i16 d17, q9
1850
vadd.s16 q13, q13, q0
1851
vbic.i16 q8, #128+64+32
1852
vadd.s16 q0, q0, q11
1853
vbic.i16 q8, #(128+64+32)<<8
1854
vst1.16 {q12, q13}, [r3, :128]!
1855
vsub.i8 q9, q3, q8
1856
vmull.u8 q12, d17, d16 @ idx3weight = y*x
1857
vmull.u8 q14, d19, d16 @ idx1weight = (32-y)*x
1858
vmull.u8 q15, d19, d18 @ idx0weight = (32-y)*(32-x)
1859
vmull.u8 q13, d17, d18 @ idx2weight = y*(32-x)
1860
vmull.u16 q9, d28, d2 @ idx1weight
1861
vmull.u16 q8, d29, d3
1862
vmull.u16 q14, d30, d2 @ idx0weight
1863
vmull.u16 q15, d31, d3
1864
vrshrn.u32 d18, q9, #10 @ idx1weight
1865
vrshrn.u32 d19, q8, #10
1866
vrshrn.u32 d16, q14, #10 @ idx0weight
1867
vrshrn.u32 d17, q15, #10
1868
vmull.u16 q14, d24, d2 @ idx3weight
1869
vmull.u16 q15, d25, d3
1870
vzip.16 q8, q9
1871
vmull.u16 q12, d26, d2 @ idx2weight
1872
vmull.u16 q13, d27, d3
1873
vst1.16 {q8, q9}, [r3, :128]!
1874
vrshrn.u32 d19, q15, #10 @ idx3weight
1875
vrshrn.u32 d18, q14, #10
1876
vrshrn.u32 d16, q12, #10 @ idx2weight
1877
vrshrn.u32 d17, q13, #10
1878
vzip.16 q8, q9
1879
vst1.16 {q8, q9}, [r3, :128]!
1880
bge 8b
1881
bx lr
1882
endfunc
1883
1884