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