root/arch/arc/lib/strlen.S
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */

#include <linux/linkage.h>

ENTRY_CFI(strlen)
        or      r3,r0,7
        ld      r2,[r3,-7]
        ld.a    r6,[r3,-3]
        mov     r4,0x01010101
        ; uses long immediate
#ifdef __LITTLE_ENDIAN__
        asl_s   r1,r0,3
        btst_s  r0,2
        asl     r7,r4,r1
        ror     r5,r4
        sub     r1,r2,r7
        bic_s   r1,r1,r2
        mov.eq  r7,r4
        sub     r12,r6,r7
        bic     r12,r12,r6
        or.eq   r12,r12,r1
        and     r12,r12,r5
        brne    r12,0,.Learly_end
#else /* BIG ENDIAN */
        ror     r5,r4
        btst_s  r0,2
        mov_s   r1,31
        sub3    r7,r1,r0
        sub     r1,r2,r4
        bic_s   r1,r1,r2
        bmsk    r1,r1,r7
        sub     r12,r6,r4
        bic     r12,r12,r6
        bmsk.ne r12,r12,r7
        or.eq   r12,r12,r1
        and     r12,r12,r5
        brne    r12,0,.Learly_end
#endif /* ENDIAN */

.Loop:
        ld_s    r2,[r3,4]
        ld.a    r6,[r3,8]
        ; stall for load result
        sub     r1,r2,r4
        bic_s   r1,r1,r2
        sub     r12,r6,r4
        bic     r12,r12,r6
        or      r12,r12,r1
        and     r12,r12,r5
        breq r12,0,.Loop
.Lend:
        and.f   r1,r1,r5
        sub.ne  r3,r3,4
        mov.eq  r1,r12
#ifdef __LITTLE_ENDIAN__
        sub_s   r2,r1,1
        bic_s   r2,r2,r1
        norm    r1,r2
        sub_s   r0,r0,3
        lsr_s   r1,r1,3
        sub         r0,r3,r0
        j_s.d   [blink]
        sub         r0,r0,r1
#else /* BIG ENDIAN */
        lsr_s   r1,r1,7
        mov.eq  r2,r6
        bic_s   r1,r1,r2
        norm    r1,r1
        sub         r0,r3,r0
        lsr_s   r1,r1,3
        j_s.d   [blink]
        add         r0,r0,r1
#endif /* ENDIAN */
.Learly_end:
        b.d     .Lend
        sub_s.ne r1,r1,r1
END_CFI(strlen)