blob: bd8fa4c0bd02a32d960bc852bf306e8545a2e348 [file] [log] [blame]
Yu Chien Peter Linbc5a5042023-08-09 18:49:30 +08001/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Taken from Linux arch/riscv/lib/strlen.S
4 */
5
6#include <linux/linkage.h>
7#include <asm/asm.h>
8
9#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
10# define CZ ctz
11# define SHIFT srl
12#else
13# define CZ clz
14# define SHIFT sll
15#endif
16
17ENTRY(__strlen)
18WEAK(strlen)
19.option push
20.option arch,+zbb
21 /*
22 * Returns
23 * a0 - string length
24 *
25 * Parameters
26 * a0 - String to measure
27 *
28 * Clobbers
29 * t0, t1, t2, t3
30 */
31
32 /* Number of irrelevant bytes in the first word. */
33 andi t2, a0, SZREG-1
34
35 /* Align pointer. */
36 andi t0, a0, -SZREG
37
38 li t3, SZREG
39 sub t3, t3, t2
40 slli t2, t2, 3
41
42 /* Get the first word. */
43 REG_L t1, 0(t0)
44
45 /*
46 * Shift away the partial data we loaded to remove the irrelevant bytes
47 * preceding the string with the effect of adding NUL bytes at the
48 * end of the string's first word.
49 */
50 SHIFT t1, t1, t2
51
52 /* Convert non-NUL into 0xff and NUL into 0x00. */
53 orc.b t1, t1
54
55 /* Convert non-NUL into 0x00 and NUL into 0xff. */
56 not t1, t1
57
58 /*
59 * Search for the first set bit (corresponding to a NUL byte in the
60 * original chunk).
61 */
62 CZ t1, t1
63
64 /*
65 * The first chunk is special: compare against the number
66 * of valid bytes in this chunk.
67 */
68 srli a0, t1, 3
69 bgtu t3, a0, 2f
70
71 /* Prepare for the word comparison loop. */
72 addi t2, t0, SZREG
73 li t3, -1
74
75 /*
76 * Our critical loop is 4 instructions and processes data in
77 * 4 byte or 8 byte chunks.
78 */
79 .p2align 3
801:
81 REG_L t1, SZREG(t0)
82 addi t0, t0, SZREG
83 orc.b t1, t1
84 beq t1, t3, 1b
85
86 not t1, t1
87 CZ t1, t1
88 srli t1, t1, 3
89
90 /* Get number of processed bytes. */
91 sub t2, t0, t2
92
93 /* Add number of characters in the first word. */
94 add a0, a0, t2
95
96 /* Add number of characters in the last word. */
97 add a0, a0, t1
982:
99 ret
100.option pop
101END(__strlen)