1/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <linux/linkage.h>
4#include <asm/asm.h>
5#include <asm/alternative-macros.h>
6#include <asm/hwcap.h>
7
8/* int strlen(const char *s) */
9SYM_FUNC_START(strlen)
10
11 __ALTERNATIVE_CFG("nop", "j strlen_zbb", 0, RISCV_ISA_EXT_ZBB,
12 IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZBB))
13
14 /*
15 * Returns
16 * a0 - string length
17 *
18 * Parameters
19 * a0 - String to measure
20 *
21 * Clobbers:
22 * t0, t1
23 */
24 mv t1, a0
251:
26 lbu t0, 0(t1)
27 beqz t0, 2f
28 addi t1, t1, 1
29 j 1b
302:
31 sub a0, t1, a0
32 ret
33
34/*
35 * Variant of strlen using the ZBB extension if available
36 */
37#if defined(CONFIG_RISCV_ISA_ZBB) && defined(CONFIG_TOOLCHAIN_HAS_ZBB)
38strlen_zbb:
39
40#ifdef CONFIG_CPU_BIG_ENDIAN
41# define CZ clz
42# define SHIFT sll
43#else
44# define CZ ctz
45# define SHIFT srl
46#endif
47
48.option push
49.option arch,+zbb
50
51 /*
52 * Returns
53 * a0 - string length
54 *
55 * Parameters
56 * a0 - String to measure
57 *
58 * Clobbers
59 * t0, t1, t2, t3
60 */
61
62 /* Number of irrelevant bytes in the first word. */
63 andi t2, a0, SZREG-1
64
65 /* Align pointer. */
66 andi t0, a0, -SZREG
67
68 li t3, SZREG
69 sub t3, t3, t2
70 slli t2, t2, 3
71
72 /* Get the first word. */
73 REG_L t1, 0(t0)
74
75 /*
76 * Shift away the partial data we loaded to remove the irrelevant bytes
77 * preceding the string with the effect of adding NUL bytes at the
78 * end of the string's first word.
79 */
80 SHIFT t1, t1, t2
81
82 /* Convert non-NUL into 0xff and NUL into 0x00. */
83 orc.b t1, t1
84
85 /* Convert non-NUL into 0x00 and NUL into 0xff. */
86 not t1, t1
87
88 /*
89 * Search for the first set bit (corresponding to a NUL byte in the
90 * original chunk).
91 */
92 CZ t1, t1
93
94 /*
95 * The first chunk is special: compare against the number
96 * of valid bytes in this chunk.
97 */
98 srli a0, t1, 3
99 bgtu t3, a0, 2f
100
101 /* Prepare for the word comparison loop. */
102 addi t2, t0, SZREG
103 li t3, -1
104
105 /*
106 * Our critical loop is 4 instructions and processes data in
107 * 4 byte or 8 byte chunks.
108 */
109 .p2align 3
1101:
111 REG_L t1, SZREG(t0)
112 addi t0, t0, SZREG
113 orc.b t1, t1
114 beq t1, t3, 1b
115
116 not t1, t1
117 CZ t1, t1
118 srli t1, t1, 3
119
120 /* Get number of processed bytes. */
121 sub t2, t0, t2
122
123 /* Add number of characters in the first word. */
124 add a0, a0, t2
125
126 /* Add number of characters in the last word. */
127 add a0, a0, t1
1282:
129 ret
130
131.option pop
132#endif
133SYM_FUNC_END(strlen)
134SYM_FUNC_ALIAS(__pi_strlen, strlen)
135EXPORT_SYMBOL(strlen)
136

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of linux/arch/riscv/lib/strlen.S