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