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 strcmp(const char *cs, const char *ct) */ |
9 | SYM_FUNC_START(strcmp) |
10 | |
11 | ALTERNATIVE("nop" , "j strcmp_zbb" , 0, RISCV_ISA_EXT_ZBB, CONFIG_RISCV_ISA_ZBB) |
12 | |
13 | /* |
14 | * Returns |
15 | * a0 - comparison result, value like strcmp |
16 | * |
17 | * Parameters |
18 | * a0 - string1 |
19 | * a1 - string2 |
20 | * |
21 | * Clobbers |
22 | * t0, t1 |
23 | */ |
24 | 1: |
25 | lbu t0, 0(a0) |
26 | lbu t1, 0(a1) |
27 | addi a0, a0, 1 |
28 | addi a1, a1, 1 |
29 | bne t0, t1, 2f |
30 | bnez t0, 1b |
31 | li a0, 0 |
32 | ret |
33 | 2: |
34 | /* |
35 | * strcmp only needs to return (< 0, 0, > 0) values |
36 | * not necessarily -1, 0, +1 |
37 | */ |
38 | sub a0, t0, t1 |
39 | ret |
40 | |
41 | /* |
42 | * Variant of strcmp using the ZBB extension if available. |
43 | * The code was published as part of the bitmanip manual |
44 | * in Appendix A. |
45 | */ |
46 | #ifdef CONFIG_RISCV_ISA_ZBB |
47 | strcmp_zbb: |
48 | |
49 | .option push |
50 | .option arch,+zbb |
51 | |
52 | /* |
53 | * Returns |
54 | * a0 - comparison result, value like strcmp |
55 | * |
56 | * Parameters |
57 | * a0 - string1 |
58 | * a1 - string2 |
59 | * |
60 | * Clobbers |
61 | * t0, t1, t2, t3, t4 |
62 | */ |
63 | |
64 | or t2, a0, a1 |
65 | li t4, -1 |
66 | and t2, t2, SZREG-1 |
67 | bnez t2, 3f |
68 | |
69 | /* Main loop for aligned string. */ |
70 | .p2align 3 |
71 | 1: |
72 | REG_L t0, 0(a0) |
73 | REG_L t1, 0(a1) |
74 | orc.b t3, t0 |
75 | bne t3, t4, 2f |
76 | addi a0, a0, SZREG |
77 | addi a1, a1, SZREG |
78 | beq t0, t1, 1b |
79 | |
80 | /* |
81 | * Words don't match, and no null byte in the first |
82 | * word. Get bytes in big-endian order and compare. |
83 | */ |
84 | #ifndef CONFIG_CPU_BIG_ENDIAN |
85 | rev8 t0, t0 |
86 | rev8 t1, t1 |
87 | #endif |
88 | |
89 | /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */ |
90 | sltu a0, t0, t1 |
91 | neg a0, a0 |
92 | ori a0, a0, 1 |
93 | ret |
94 | |
95 | 2: |
96 | /* |
97 | * Found a null byte. |
98 | * If words don't match, fall back to simple loop. |
99 | */ |
100 | bne t0, t1, 3f |
101 | |
102 | /* Otherwise, strings are equal. */ |
103 | li a0, 0 |
104 | ret |
105 | |
106 | /* Simple loop for misaligned strings. */ |
107 | .p2align 3 |
108 | 3: |
109 | lbu t0, 0(a0) |
110 | lbu t1, 0(a1) |
111 | addi a0, a0, 1 |
112 | addi a1, a1, 1 |
113 | bne t0, t1, 4f |
114 | bnez t0, 3b |
115 | |
116 | 4: |
117 | sub a0, t0, t1 |
118 | ret |
119 | |
120 | .option pop |
121 | #endif |
122 | SYM_FUNC_END(strcmp) |
123 | |