/* 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) |