root/arch/csky/abiv2/strlen.S
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

#include <linux/linkage.h>
#include "sysdep.h"

ENTRY(strlen)
        /* Check if the start addr is aligned.  */
        mov     r3, r0
        andi    r1, r0, 3
        movi    r2, 4
        movi    r0, 0
        bnez    r1, .L_start_not_aligned

        LABLE_ALIGN
.L_start_addr_aligned:
        /* Check if all the bytes in the word are not zero.  */
        ldw     r1, (r3)
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 4)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 8)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 12)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 16)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 20)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 24)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        ldw     r1, (r3, 28)
        addi    r0, 4
        tstnbz  r1
        bf      .L_string_tail

        addi    r0, 4
        addi    r3, 32
        br      .L_start_addr_aligned

.L_string_tail:
# ifdef __CSKYBE__
        xtrb0   r3, r1
        bez     r3, .L_return
        addi    r0, 1
        xtrb1   r3, r1
        bez     r3, .L_return
        addi    r0, 1
        xtrb2   r3, r1
        bez     r3, .L_return
        addi    r0, 1
# else
        xtrb3   r3, r1
        bez     r3, .L_return
        addi    r0, 1
        xtrb2   r3, r1
        bez     r3, .L_return
        addi    r0, 1
        xtrb1   r3, r1
        bez     r3, .L_return
        addi    r0, 1
# endif /* !__CSKYBE__ */

.L_return:
        rts

.L_start_not_aligned:
        sub     r2, r2, r1
.L_start_not_aligned_loop:
        ldb     r1, (r3)
        PRE_BNEZAD (r2)
        addi    r3, 1
        bez     r1, .L_return
        addi    r0, 1
        BNEZAD (r2, .L_start_not_aligned_loop)
        br      .L_start_addr_aligned
ENDPROC(strlen)