/***************************************************************************** * Copyright (C) 2013-2020 MulticoreWare, Inc * * Authors: David Conrad * Janne Grunau * Dnyaneshwar G * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. * * This program is also available under a commercial proprietary license. * For more information, contact us at license @ x265.com. *****************************************************************************/ #include "asm.S" .section .rodata .align 4 sad12_mask: .byte 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0 .text /* sad4x4(pixel* dst, intptr_t dstStride, const pixel* src, intptr_t srcStride) * * r0 - dst * r1 - dstStride * r2 - src * r3 - srcStride */ .macro SAD4_ARMV6 h function x265_pixel_sad_4x\h\()_armv6 push {r4-r6,lr} ldr r4, [r2], r3 ldr r5, [r0], r1 ldr r6, [r2], r3 ldr lr, [r0], r1 usad8 ip, r4, r5 .rept (\h - 2)/2 ldr r4, [r2], r3 ldr r5, [r0], r1 usada8 ip, r6, lr, ip ldr r6, [r2], r3 ldr lr, [r0], r1 usada8 ip, r4, r5, ip .endr usada8 r0, r6, lr, ip pop {r4-r6,pc} endfunc .endm SAD4_ARMV6 4 SAD4_ARMV6 8 SAD4_ARMV6 16 .macro SAD8_NEON h function x265_pixel_sad_8x\h\()_neon vld1.8 d0, [r0], r1 // row 0 vld1.8 d1, [r2], r3 // row 1 vabdl.u8 q1, d0, d1 .rept \h-1 vld1.8 d0, [r0], r1 // row 2,4,6 vld1.8 d1, [r2], r3 // row 3,5,7 vabal.u8 q1, d0, d1 .endr vadd.u16 d2, d2, d3 vpadd.u16 d0, d2, d2 vpaddl.u16 d0, d0 vmov.u32 r0, d0[0] bx lr endfunc .endm SAD8_NEON 4 SAD8_NEON 8 SAD8_NEON 16 SAD8_NEON 32 .macro SAD16_NEON h function x265_pixel_sad_16x\h\()_neon vld1.8 {q0}, [r0], r1 // row 0 vld1.8 {q1}, [r2], r3 vld1.8 {q2}, [r0], r1 // row 1 vld1.8 {q3}, [r2], r3 vabdl.u8 q8, d0, d2 vabdl.u8 q9, d1, d3 vabal.u8 q8, d4, d6 vabal.u8 q9, d5, d7 mov r12, #(\h-2)/2 .Loop_16x\h: subs r12, #1 vld1.8 {q0}, [r0], r1 vld1.8 {q1}, [r2], r3 vld1.8 {q2}, [r0], r1 vld1.8 {q3}, [r2], r3 vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q8, d4, d6 vabal.u8 q9, d5, d7 bne .Loop_16x\h vadd.u16 q8, q8, q9 .if \h == 64 vaddl.u16 q0, d16, d17 vpadd.u32 d0, d0, d1 vpadd.u32 d0, d0 .else vadd.u16 d16, d16, d17 vpadd.u16 d0, d16, d16 vpaddl.u16 d0, d0 .endif vmov.u32 r0, d0[0] bx lr endfunc .endm SAD16_NEON 4 SAD16_NEON 8 SAD16_NEON 16 SAD16_NEON 12 SAD16_NEON 32 SAD16_NEON 64 .macro SAD32_NEON h function x265_pixel_sad_32x\h\()_neon veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 mov r12, #\h/8 .Loop_32x\h: subs r12, #1 .rept 4 vld1.8 {q0, q1}, [r0], r1 // row 0 vld1.8 {q2, q3}, [r2], r3 // row 0 vld1.8 {q12, q13}, [r0], r1 // row 1 vld1.8 {q14, q15}, [r2], r3 // row 1 vabal.u8 q8, d0, d4 vabal.u8 q9, d1, d5 vabal.u8 q10, d2, d6 vabal.u8 q11, d3, d7 vabal.u8 q8, d24, d28 vabal.u8 q9, d25, d29 vabal.u8 q10, d26, d30 vabal.u8 q11, d27, d31 .endr bne .Loop_32x\h vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 .if \h == 64 vaddl.u16 q0, d16, d17 vpadd.u32 d0, d0, d1 vpaddl.u32 d0, d0 vaddl.u16 q1, d20, d21 vpadd.u32 d2, d2, d3 vpaddl.u32 d2, d2 vadd.u32 d0,d0,d2 .else vadd.u16 d16, d16, d17 vpadd.u16 d0, d16, d16 vpaddl.u16 d0, d0 vadd.u16 d20, d20, d21 vpadd.u16 d1, d20, d20 vpaddl.u16 d1, d1 vadd.u32 d0,d0,d1 .endif vmov.u32 r0, d0[0] bx lr endfunc .endm SAD32_NEON 8 SAD32_NEON 16 SAD32_NEON 24 SAD32_NEON 32 SAD32_NEON 64 .macro SAD64_NEON h function x265_pixel_sad_64x\h\()_neon veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 mov r12, #32 sub r1, r12 sub r3, r12 mov r12, #\h/8 .Loop_64x\h: subs r12, #1 .rept 4 // Columns 0-32 vld1.8 {q0, q1}, [r0]! vld1.8 {q2, q3}, [r2]! vabal.u8 q8, d0, d4 vabal.u8 q9, d1, d5 vabal.u8 q10, d2, d6 vabal.u8 q11, d3, d7 // Columns 32-64 vld1.8 {q0, q1}, [r0],r1 vld1.8 {q2, q3}, [r2],r3 vabal.u8 q8, d0, d4 vabal.u8 q9, d1, d5 vabal.u8 q10, d2, d6 vabal.u8 q11, d3, d7 // Columns 0-32 vld1.8 {q12, q13}, [r0]! vld1.8 {q14, q15}, [r2]! vabal.u8 q8, d24, d28 vabal.u8 q9, d25, d29 vabal.u8 q10, d26, d30 vabal.u8 q11, d27, d31 // Columns 32-64 vld1.8 {q12, q13}, [r0],r1 vld1.8 {q14, q15}, [r2],r3 vabal.u8 q8, d24, d28 vabal.u8 q9, d25, d29 vabal.u8 q10, d26, d30 vabal.u8 q11, d27, d31 .endr bne .Loop_64x\h vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 vaddl.u16 q0, d16, d17 vpadd.u32 d0, d0, d1 vpaddl.u32 d0, d0 vaddl.u16 q1, d20, d21 vpadd.u32 d2, d2, d3 vpaddl.u32 d2, d2 vadd.u32 d0,d0,d2 vmov.u32 r0, d0[0] bx lr endfunc .endm SAD64_NEON 16 SAD64_NEON 32 SAD64_NEON 48 SAD64_NEON 64 function x265_pixel_sad_24x32_neon veor.u8 q0, q0 veor.u8 q1, q1 veor.u8 q2, q2 veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 mov r12, #16 sub r1, #16 sub r3, #16 mov r12, #8 .Loop_24x32: subs r12, #1 .rept 4 vld1.8 {q0}, [r0]! vld1.8 {q1}, [r2]! vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vld1.8 {d0}, [r0], r1 vld1.8 {d1}, [r2], r3 vabal.u8 q10, d0, d1 .endr bne .Loop_24x32 vadd.u16 q8, q8, q9 vadd.u16 d16, d16, d17 vpadd.u16 d0, d16, d16 vpaddl.u16 d0, d0 vadd.u16 d20, d20, d21 vpadd.u16 d1, d20, d20 vpaddl.u16 d1, d1 vadd.u32 d0,d0,d1 vmov.u32 r0, d0[0] bx lr endfunc function x265_pixel_sad_48x64_neon veor.u8 q3, q3 veor.u8 q11, q11 veor.u8 q12, q12 veor.u8 q13, q13 veor.u8 q14, q14 veor.u8 q15, q15 mov r12, #32 sub r1, #32 sub r3, #32 mov r12, #16 .Loop_48x64: subs r12, #1 .rept 4 vld1.8 {q0,q1}, [r0]! vld1.8 {q2}, [r0], r1 vld1.8 {q8,q9}, [r2]! vld1.8 {q10}, [r2], r3 vabal.u8 q3, d0, d16 vabal.u8 q11, d1, d17 vabal.u8 q12, d2, d18 vabal.u8 q13, d3, d19 vabal.u8 q14, d4, d20 vabal.u8 q15, d5, d21 .endr bne .Loop_48x64 vadd.u16 q3, q3, q11 vadd.u16 d6, d6, d7 vpaddl.u16 d0, d6 vpadd.u32 d0, d0 vadd.u16 q12, q12, q13 vadd.u16 d24, d24, d25 vpaddl.u16 d1, d24 vpadd.u32 d1, d1 vadd.u16 q14,q14,q15 vadd.u16 d28, d28, d29 vpaddl.u16 d2, d28 vpadd.u32 d2, d2 vadd.u32 d0, d0, d1 vadd.u32 d0, d0, d2 vmov.u32 r0, d0[0] bx lr endfunc // SAD_X3 and SAD_X4 code start .macro SAD_X_START_4 x vld1.32 {d0[]}, [r0], r12 vld1.32 {d1[]}, [r1], r4 vld1.32 {d2[]}, [r2], r4 vld1.32 {d3[]}, [r3], r4 .if \x == 4 vld1.32 {d4[]}, [lr], r4 .endif vabdl.u8 q8, d0, d1 vabdl.u8 q9, d0, d2 vabdl.u8 q10, d0, d3 .if \x == 4 vabdl.u8 q11, d0, d4 .endif .endm .macro SAD_X_4 x vld1.32 {d0[]}, [r0], r12 vld1.32 {d1[]}, [r1], r4 vld1.32 {d2[]}, [r2], r4 vld1.32 {d3[]}, [r3], r4 .if \x == 4 vld1.32 {d4[]}, [lr], r4 .endif vabal.u8 q8, d0, d1 vabal.u8 q9, d0, d2 vabal.u8 q10, d0, d3 .if \x == 4 vabal.u8 q11, d0, d4 .endif .endm .macro SAD_X_4xN x, h function x265_sad_x\x\()_4x\h\()_neon push {r4, r5, lr} .if \x == 3 ldrd r4, r5, [sp, #12] .else ldr lr, [sp, #12] ldrd r4, r5, [sp, #16] .endif mov r12, #FENC_STRIDE SAD_X_START_4 \x .rept \h - 1 SAD_X_4 \x .endr vpadd.u16 d0, d16, d18 vpadd.u16 d1, d20, d22 vpaddl.u16 q0, q0 .if \x == 3 vst1.32 {d0}, [r5]! vst1.32 {d1[0]}, [r5, :32] .else vst1.32 {d0-d1}, [r5] .endif pop {r4, r5, lr} bx lr endfunc .endm SAD_X_4xN 3 4 SAD_X_4xN 3 8 SAD_X_4xN 3 16 SAD_X_4xN 4 4 SAD_X_4xN 4 8 SAD_X_4xN 4 16 .macro SAD_X_START_8 x vld1.8 {d0}, [r0], r12 vld1.8 {d1}, [r1], r4 vld1.8 {d2}, [r2], r4 vld1.8 {d3}, [r3], r4 .if \x == 4 vld1.8 {d4}, [lr], r4 .endif vabdl.u8 q8, d0, d1 vabdl.u8 q9, d0, d2 vabdl.u8 q10, d0, d3 .if \x == 4 vabdl.u8 q11, d0, d4 .endif .endm .macro SAD_X_8 x vld1.8 {d0}, [r0], r12 vld1.8 {d1}, [r1], r4 vld1.8 {d2}, [r2], r4 vld1.8 {d3}, [r3], r4 .if \x == 4 vld1.8 {d4}, [lr], r4 .endif vabal.u8 q8, d0, d1 vabal.u8 q9, d0, d2 vabal.u8 q10, d0, d3 .if \x == 4 vabal.u8 q11, d0, d4 .endif .endm .macro SAD_X_8xN x, h function x265_sad_x\x\()_8x\h\()_neon push {r4, r5, lr} .if \x == 3 ldrd r4, r5, [sp, #12] .else ldr lr, [sp, #12] ldrd r4, r5, [sp, #16] .endif mov r12, #FENC_STRIDE SAD_X_START_8 \x .rept \h - 1 SAD_X_8 \x .endr vadd.u16 d16, d16, d17 vadd.u16 d18, d18, d19 vadd.u16 d20, d20, d21 vadd.u16 d22, d22, d23 vpadd.u16 d0, d16, d18 vpadd.u16 d1, d20, d22 vpaddl.u16 q0, q0 .if \x == 3 vst1.32 {d0}, [r5]! vst1.32 {d1[0]}, [r5, :32] .else vst1.32 {d0-d1}, [r5] .endif pop {r4, r5, lr} bx lr endfunc .endm SAD_X_8xN 3 4 SAD_X_8xN 3 8 SAD_X_8xN 3 16 SAD_X_8xN 3 32 SAD_X_8xN 4 4 SAD_X_8xN 4 8 SAD_X_8xN 4 16 SAD_X_8xN 4 32 .macro SAD_X_START_16 x vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vabdl.u8 q8, d0, d2 vabdl.u8 q9, d1, d3 vabdl.u8 q10, d0, d4 vabdl.u8 q11, d1, d5 vabdl.u8 q12, d0, d6 vabdl.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vabdl.u8 q14, d0, d6 vabdl.u8 q15, d1, d7 .endif .endm .macro SAD_X_16 x vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif .endm .macro SAD_X_16xN x, h function x265_sad_x\x\()_16x\h\()_neon push {r4, r5, lr} .if \x == 3 ldrd r4, r5, [sp, #12] .else ldr lr, [sp, #12] ldrd r4, r5, [sp, #16] .endif mov r12, #FENC_STRIDE SAD_X_START_16 \x .rept \h - 1 SAD_X_16 \x .endr vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 vadd.u16 q12, q12, q13 .if \x == 4 vadd.u16 q14, q14, q15 .endif vadd.u16 d16, d16, d17 vadd.u16 d20, d20, d21 vadd.u16 d24, d24, d25 .if \x == 4 vadd.u16 d28, d28, d29 .endif .if \h <= 32 vpadd.u16 d0, d16, d20 vpadd.u16 d1, d24, d28 vpaddl.u16 q0, q0 .if \x == 3 vst1.32 {d0}, [r5]! vst1.32 {d1[0]}, [r5, :32] .else vst1.32 {d0-d1}, [r5] .endif .else vpaddl.u16 d16, d16 vpaddl.u16 d20, d20 vpaddl.u16 d24, d24 .if \x == 4 vpaddl.u16 d28, d28 .endif vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif .endif pop {r4, r5, lr} bx lr endfunc .endm SAD_X_16xN 3 4 SAD_X_16xN 3 12 SAD_X_16xN 4 4 SAD_X_16xN 4 12 .macro SAD_X_16xN_LOOP x, h function x265_sad_x\x\()_16x\h\()_neon push {r4-r6, lr} .if \x == 3 ldrd r4, r5, [sp, #16] .else ldr lr, [sp, #16] ldrd r4, r5, [sp, #20] .endif mov r12, #FENC_STRIDE mov r6, #\h/8 veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 veor.u8 q12, q12 veor.u8 q13, q13 .if \x == 4 veor.u8 q14, q14 veor.u8 q15, q15 .endif .Loop_sad_x\x\()_16x\h: .rept 8 SAD_X_16 \x .endr subs r6, #1 bne .Loop_sad_x\x\()_16x\h vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 vadd.u16 q12, q12, q13 .if \x == 4 vadd.u16 q14, q14, q15 .endif vadd.u16 d16, d16, d17 vadd.u16 d20, d20, d21 vadd.u16 d24, d24, d25 .if \x == 4 vadd.u16 d28, d28, d29 .endif .if \h <= 32 vpadd.u16 d0, d16, d20 vpadd.u16 d1, d24, d28 vpaddl.u16 q0, q0 .if \x == 3 vst1.32 {d0}, [r5]! vst1.32 {d1[0]}, [r5, :32] .else vst1.32 {d0-d1}, [r5] .endif .else vpaddl.u16 d16, d16 vpaddl.u16 d20, d20 vpaddl.u16 d24, d24 .if \x == 4 vpaddl.u16 d28, d28 .endif vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif .endif pop {r4-r6, lr} bx lr endfunc .endm SAD_X_16xN_LOOP 3 8 SAD_X_16xN_LOOP 3 16 SAD_X_16xN_LOOP 3 32 SAD_X_16xN_LOOP 3 64 SAD_X_16xN_LOOP 4 8 SAD_X_16xN_LOOP 4 16 SAD_X_16xN_LOOP 4 32 SAD_X_16xN_LOOP 4 64 .macro SAD_X_32 x vld1.8 {q0}, [r0]! vld1.8 {q1}, [r1]! vld1.8 {q2}, [r2]! vld1.8 {q3}, [r3]! vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr]! vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif .endm .macro SAD_X_32xN x, h function x265_sad_x\x\()_32x\h\()_neon push {r4-r6, lr} .if \x == 3 ldrd r4, r5, [sp, #16] .else ldr lr, [sp, #16] ldrd r4, r5, [sp, #20] .endif mov r12, #FENC_STRIDE sub r12, #16 sub r4, #16 mov r6, #\h/8 veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 veor.u8 q12, q12 veor.u8 q13, q13 .if \x == 4 veor.u8 q14, q14 veor.u8 q15, q15 .endif loop_sad_x\x\()_32x\h: .rept 8 SAD_X_32 \x .endr subs r6, #1 bgt loop_sad_x\x\()_32x\h .if \h <= 32 vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 vadd.u16 q12, q12, q13 .if \x == 4 vadd.u16 q14, q14, q15 .endif vadd.u16 d16, d16, d17 vadd.u16 d20, d20, d21 vadd.u16 d24, d24, d25 .if \x == 4 vadd.u16 d28, d28, d29 .endif .else vpaddl.u16 q8, q8 vpaddl.u16 q9, q9 vpaddl.u16 q10, q10 vpaddl.u16 q11, q11 vpaddl.u16 q12, q12 vpaddl.u16 q13, q13 .if \x == 4 vpaddl.u16 q14, q14 vpaddl.u16 q15, q15 .endif vadd.u32 q8, q8, q9 vadd.u32 q10, q10, q11 vadd.u32 q12, q12, q13 .if \x == 4 vadd.u32 q14, q14, q15 .endif vadd.u32 d16, d16, d17 vadd.u32 d20, d20, d21 vadd.u32 d24, d24, d25 .if \x == 4 vadd.u32 d28, d28, d29 .endif .endif .if \h <= 16 vpadd.u16 d0, d16, d20 vpadd.u16 d1, d24, d28 vpaddl.u16 q0, q0 .if \x == 3 vst1.32 {d0}, [r5]! vst1.32 {d1[0]}, [r5, :32] .else vst1.32 {d0-d1}, [r5] .endif .elseif \h <= 32 vpaddl.u16 d16, d16 vpaddl.u16 d20, d20 vpaddl.u16 d24, d24 .if \x == 4 vpaddl.u16 d28, d28 .endif vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif .elseif \h <= 64 vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif .endif pop {r4-r6, lr} bx lr endfunc .endm SAD_X_32xN 3 8 SAD_X_32xN 3 16 SAD_X_32xN 3 24 SAD_X_32xN 3 32 SAD_X_32xN 3 64 SAD_X_32xN 4 8 SAD_X_32xN 4 16 SAD_X_32xN 4 24 SAD_X_32xN 4 32 SAD_X_32xN 4 64 .macro SAD_X_64 x .rept 3 vld1.8 {q0}, [r0]! vld1.8 {q1}, [r1]! vld1.8 {q2}, [r2]! vld1.8 {q3}, [r3]! vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr]! vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif .endr vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif .endm .macro SAD_X_64xN x, h function x265_sad_x\x\()_64x\h\()_neon push {r4-r6, lr} .if \x == 3 ldrd r4, r5, [sp, #16] .else ldr lr, [sp, #16] ldrd r4, r5, [sp, #20] .endif mov r12, #FENC_STRIDE sub r12, #48 sub r4, #48 mov r6, #\h/8 veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 veor.u8 q12, q12 veor.u8 q13, q13 .if \x == 4 veor.u8 q14, q14 veor.u8 q15, q15 .endif .Loop_sad_x\x\()_64x\h: .rept 8 SAD_X_64 \x .endr subs r6, #1 bne .Loop_sad_x\x\()_64x\h .if \h <= 16 vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 vadd.u16 q12, q12, q13 .if \x == 4 vadd.u16 q14, q14, q15 .endif vadd.u16 d16, d16, d17 vadd.u16 d20, d20, d21 vadd.u16 d24, d24, d25 .if \x == 4 vadd.u16 d28, d28, d29 .endif .else vpaddl.u16 q8, q8 vpaddl.u16 q9, q9 vpaddl.u16 q10, q10 vpaddl.u16 q11, q11 vpaddl.u16 q12, q12 vpaddl.u16 q13, q13 .if \x == 4 vpaddl.u16 q14, q14 vpaddl.u16 q15, q15 .endif vadd.u32 q8, q8, q9 vadd.u32 q10, q10, q11 vadd.u32 q12, q12, q13 .if \x == 4 vadd.u32 q14, q14, q15 .endif vadd.u32 d16, d16, d17 vadd.u32 d20, d20, d21 vadd.u32 d24, d24, d25 .if \x == 4 vadd.u32 d28, d28, d29 .endif .endif .if \h <= 16 vpaddl.u16 d16, d16 vpaddl.u16 d20, d20 vpaddl.u16 d24, d24 .if \x == 4 vpaddl.u16 d28, d28 .endif .endif vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif pop {r4-r6, lr} bx lr endfunc .endm SAD_X_64xN 3 16 SAD_X_64xN 3 32 SAD_X_64xN 3 48 SAD_X_64xN 3 64 SAD_X_64xN 4 16 SAD_X_64xN 4 32 SAD_X_64xN 4 48 SAD_X_64xN 4 64 .macro SAD_X_48 x .rept 2 vld1.8 {q0}, [r0]! vld1.8 {q1}, [r1]! vld1.8 {q2}, [r2]! vld1.8 {q3}, [r3]! vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr]! vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif .endr vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif .endm .macro SAD_X_48x64 x function x265_sad_x\x\()_48x64_neon push {r4-r6, lr} .if \x == 3 ldrd r4, r5, [sp, #16] .else ldr lr, [sp, #16] ldrd r4, r5, [sp, #20] .endif mov r12, #FENC_STRIDE sub r12, #32 sub r4, #32 mov r6, #8 veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 veor.u8 q12, q12 veor.u8 q13, q13 .if \x == 4 veor.u8 q14, q14 veor.u8 q15, q15 .endif .Loop_sad_x\x\()_48x64: .rept 8 SAD_X_48 \x .endr subs r6, #1 bne .Loop_sad_x\x\()_48x64 vpaddl.u16 q8, q8 vpaddl.u16 q9, q9 vpaddl.u16 q10, q10 vpaddl.u16 q11, q11 vpaddl.u16 q12, q12 vpaddl.u16 q13, q13 .if \x == 4 vpaddl.u16 q14, q14 vpaddl.u16 q15, q15 .endif vadd.u32 q8, q8, q9 vadd.u32 q10, q10, q11 vadd.u32 q12, q12, q13 .if \x == 4 vadd.u32 q14, q14, q15 .endif vadd.u32 d16, d16, d17 vadd.u32 d20, d20, d21 vadd.u32 d24, d24, d25 .if \x == 4 vadd.u32 d28, d28, d29 .endif vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 vpaddl.u32 d28, d28 .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif pop {r4-r6, lr} bx lr endfunc .endm SAD_X_48x64 3 SAD_X_48x64 4 .macro SAD_X_24 x vld1.8 {q0}, [r0]! vld1.8 {q1}, [r1]! vld1.8 {q2}, [r2]! vld1.8 {q3}, [r3]! vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q10, d0, d4 vabal.u8 q11, d1, d5 vabal.u8 q12, d0, d6 vabal.u8 q13, d1, d7 .if \x == 4 vld1.8 {q3}, [lr]! vabal.u8 q14, d0, d6 vabal.u8 q15, d1, d7 .endif vld1.8 {d0}, [r0], r12 vld1.8 {d1}, [r1], r4 vld1.8 {d2}, [r2], r4 vld1.8 {d3}, [r3], r4 .if \x == 4 vld1.8 {d8}, [lr], r4 .endif vabal.u8 q8, d0, d1 vabal.u8 q10, d0, d2 vabal.u8 q12, d0, d3 .if \x == 4 vabal.u8 q14, d0, d8 .endif .endm .macro SAD_X_24x32 x function x265_sad_x\x\()_24x32_neon push {r4-r6, lr} .if \x == 3 ldrd r4, r5, [sp, #16] .else ldr lr, [sp, #16] ldrd r4, r5, [sp, #20] .endif mov r12, #FENC_STRIDE sub r12, #16 sub r4, #16 mov r6, #4 veor.u8 q8, q8 veor.u8 q9, q9 veor.u8 q10, q10 veor.u8 q11, q11 veor.u8 q12, q12 veor.u8 q13, q13 .if \x == 4 veor.u8 q14, q14 veor.u8 q15, q15 .endif .Loop_sad_x\x\()_24x32: .rept 8 SAD_X_24 \x .endr subs r6, #1 bne .Loop_sad_x\x\()_24x32 vadd.u16 q8, q8, q9 vadd.u16 q10, q10, q11 vadd.u16 q12, q12, q13 .if \x == 4 vadd.u16 q14, q14, q15 .endif vadd.u16 d16, d16, d17 vadd.u16 d20, d20, d21 vadd.u16 d24, d24, d25 .if \x == 4 vadd.u16 d28, d28, d29 .endif vpaddl.u16 d16, d16 vpaddl.u16 d20, d20 vpaddl.u16 d24, d24 .if \x == 4 vpaddl.u16 d28, d28 .endif vpaddl.u32 d16, d16 vpaddl.u32 d20, d20 vpaddl.u32 d24, d24 .if \x == 4 vpaddl.u32 d28, d28 .endif .if \x == 4 vpaddl.u32 d28, d28 .endif vst1.32 {d16[0]}, [r5]! vst1.32 {d20[0]}, [r5]! .if \x == 3 vst1.32 {d24[0]}, [r5] .endif .if \x == 4 vst1.32 {d24[0]}, [r5]! vst1.32 {d28[0]}, [r5] .endif pop {r4-r6, lr} bx lr endfunc .endm SAD_X_24x32 3 SAD_X_24x32 4 // SAD_X3 and SAD_X4 code end .macro SAD_X_START_12 x vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vand.u8 q0, q15 vand.u8 q1, q15 vand.u8 q2, q15 vand.u8 q3, q15 vabdl.u8 q5, d0, d2 vabdl.u8 q8, d1, d3 vabdl.u8 q9, d0, d4 vabdl.u8 q10, d1, d5 vabdl.u8 q11, d0, d6 vabdl.u8 q12, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vand.u8 q3, q15 vabdl.u8 q13, d0, d6 vabdl.u8 q14, d1, d7 .endif .endm .macro SAD_X_12 x vld1.8 {q0}, [r0], r12 vld1.8 {q1}, [r1], r4 vld1.8 {q2}, [r2], r4 vld1.8 {q3}, [r3], r4 vand.u8 q0, q15 vand.u8 q1, q15 vand.u8 q2, q15 vand.u8 q3, q15 vabal.u8 q5, d0, d2 vabal.u8 q8, d1, d3 vabal.u8 q9, d0, d4 vabal.u8 q10, d1, d5 vabal.u8 q11, d0, d6 vabal.u8 q12, d1, d7 .if \x == 4 vld1.8 {q3}, [lr], r4 vand.u8 q3, q15 vabal.u8 q13, d0, d6 vabal.u8 q14, d1, d7 .endif .endm .macro SAD_X_12x16 x function x265_sad_x\x\()_12x16_neon push {r4-r5, lr} vpush {q5} .if \x == 3 ldrd r4, r5, [sp, #28] .else ldr lr, [sp, #28] ldrd r4, r5, [sp, #32] .endif movrel r12, sad12_mask vld1.8 {q15}, [r12] mov r12, #FENC_STRIDE SAD_X_START_12 \x .rept 15 SAD_X_12 \x .endr vadd.u16 q5, q5, q8 vadd.u16 q9, q9, q10 vadd.u16 q11, q11, q12 .if \x == 4 vadd.u16 q13, q13, q14 .endif vadd.u16 d10, d10, d11 vadd.u16 d18, d18, d19 vadd.u16 d22, d22, d23 .if \x == 4 vadd.u16 d26, d26, d27 .endif vpadd.u16 d0, d10, d18 vpadd.u16 d1, d22, d26 vpaddl.u16 q0, q0 .if \x == 3 vst1.32 {d0}, [r5]! vst1.32 {d1[0]}, [r5, :32] .else vst1.32 {d0-d1}, [r5] .endif vpop {q5} pop {r4-r5, lr} bx lr endfunc .endm SAD_X_12x16 3 SAD_X_12x16 4 function x265_pixel_sad_12x16_neon veor.u8 q8, q8 veor.u8 q9, q9 movrel r12, sad12_mask vld1.8 {q15}, [r12] .rept 8 vld1.8 {q0}, [r0], r1 vld1.8 {q1}, [r2], r3 vand.u8 q0, q15 vand.u8 q1, q15 vld1.8 {q2}, [r0], r1 vld1.8 {q3}, [r2], r3 vand.u8 q2, q15 vand.u8 q3, q15 vabal.u8 q8, d0, d2 vabal.u8 q9, d1, d3 vabal.u8 q8, d4, d6 vabal.u8 q9, d5, d7 .endr vadd.u16 q8, q8, q9 vadd.u16 d16, d16, d17 vpadd.u16 d0, d16, d16 vpaddl.u16 d0, d0 vmov.u32 r0, d0[0] bx lr endfunc