Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/lib/strlen.S
26424 views
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) */
9
SYM_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
25
1:
26
lbu t0, 0(t1)
27
beqz t0, 2f
28
addi t1, t1, 1
29
j 1b
30
2:
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)
38
strlen_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
110
1:
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
128
2:
129
ret
130
131
.option pop
132
#endif
133
SYM_FUNC_END(strlen)
134
SYM_FUNC_ALIAS(__pi_strlen, strlen)
135
EXPORT_SYMBOL(strlen)
136
137