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