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