1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Taken from Linux arch/riscv/lib/strncmp.S
4 */
5
6#include <linux/linkage.h>
7#include <asm/asm.h>
8
9ENTRY(__strncmp)
10WEAK(strncmp)
11.option push
12.option arch,+zbb
13	/*
14	 * Returns
15	 *   a0 - comparison result, 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, t3, t4, t5, t6
24	 */
25
26	or	t2, a0, a1
27	li	t5, -1
28	and	t2, t2, SZREG-1
29	add	t4, a0, a2
30	bnez	t2, 3f
31
32	/* Adjust limit for fast-path.  */
33	andi	t6, t4, -SZREG
34
35	/* Main loop for aligned string.  */
36	.p2align 3
371:
38	bge	a0, t6, 3f
39	REG_L	t0, 0(a0)
40	REG_L	t1, 0(a1)
41	orc.b	t3, t0
42	bne	t3, t5, 2f
43	orc.b	t3, t1
44	bne	t3, t5, 2f
45	addi	a0, a0, SZREG
46	addi	a1, a1, SZREG
47	beq	t0, t1, 1b
48
49	/*
50	 * Words don't match, and no null byte in the first
51	 * word. Get bytes in big-endian order and compare.
52	 */
53#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
54	rev8	t0, t0
55	rev8	t1, t1
56#endif
57
58	/* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence.  */
59	sltu	a0, t0, t1
60	neg	a0, a0
61	ori	a0, a0, 1
62	ret
63
642:
65	/*
66	 * Found a null byte.
67	 * If words don't match, fall back to simple loop.
68	 */
69	bne	t0, t1, 3f
70
71	/* Otherwise, strings are equal.  */
72	li	a0, 0
73	ret
74
75	/* Simple loop for misaligned strings.  */
76	.p2align 3
773:
78	bge	a0, t4, 5f
79	lbu	t0, 0(a0)
80	lbu	t1, 0(a1)
81	addi	a0, a0, 1
82	addi	a1, a1, 1
83	bne	t0, t1, 4f
84	bnez	t0, 3b
85
864:
87	sub	a0, t0, t1
88	ret
89
905:
91	li	a0, 0
92	ret
93.option pop
94END(__strncmp)
95