1/* The assembly function for memory compare.  C-SKY ABIV2 version.
2   Copyright (C) 2018-2022 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library.  If not, see
17   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20
21ENTRY (memcmp)
22	/* Test if len less than 4 bytes.  */
23	mov	r3, r0
24	movi	r0, 0
25	mov	r12, r4
26	cmplti	r2, 4
27	jbt	.L_compare_by_byte
28
29	andi	r13, r0, 3
30	movi	r19, 4
31	/* Test if s1 is not 4 bytes aligned.  */
32	bnez	r13, .L_s1_not_aligned
33
34	LABLE_ALIGN
35.L_s1_aligned:
36	/* If dest is aligned, then copy.  */
37	zext	r18, r2, 31, 4
38	/* Test if len less than 16 bytes.  */
39	bez	r18, .L_compare_by_word
40
41.L_compare_by_4word:
42	/* If aligned, load word each time.  */
43	ldw	r20, (r3, 0)
44	ldw	r21, (r1, 0)
45	/* If s1[i] != s2[i], goto .L_byte_check.  */
46	cmpne	r20, r21
47	bt	.L_byte_check
48
49	ldw	r20, (r3, 4)
50	ldw	r21, (r1, 4)
51	cmpne	r20, r21
52	bt	.L_byte_check
53
54	ldw	r20, (r3, 8)
55	ldw	r21, (r1, 8)
56	cmpne	r20, r21
57	bt	.L_byte_check
58
59	ldw	r20, (r3, 12)
60	ldw	r21, (r1, 12)
61	cmpne	r20, r21
62	bt	.L_byte_check
63
64	PRE_BNEZAD (r18)
65	addi	a3, 16
66	addi	a1, 16
67
68	BNEZAD (r18, .L_compare_by_4word)
69
70.L_compare_by_word:
71	zext	r18, r2, 3, 2
72	bez	r18, .L_compare_by_byte
73.L_compare_by_word_loop:
74	ldw	r20, (r3, 0)
75	ldw	r21, (r1, 0)
76	addi	r3, 4
77	PRE_BNEZAD (r18)
78	cmpne	r20, r21
79	addi	r1, 4
80	bt	.L_byte_check
81	BNEZAD (r18, .L_compare_by_word_loop)
82
83.L_compare_by_byte:
84	zext	r18, r2, 1, 0
85	bez	r18, .L_return
86.L_compare_by_byte_loop:
87	ldb	r0, (r3, 0)
88	ldb	r4, (r1, 0)
89	addi	r3, 1
90	subu	r0, r4
91	PRE_BNEZAD (r18)
92	addi	r1, 1
93	bnez	r0, .L_return
94	BNEZAD (r18, .L_compare_by_byte_loop)
95
96.L_return:
97	mov	r4, r12
98	rts
99
100	/* s1[i] != s2[i] in word, so we check byte 3.  */
101.L_byte_check:
102	xtrb3	r0, r20
103	xtrb3	r2, r21
104	subu	r0, r2
105	bnez	r0, .L_return
106
107	/* check byte 2 */
108	xtrb2	r0, r20
109	xtrb2	r2, r21
110	subu	r0, r2
111	bnez	r0, .L_return
112
113	/* check byte 1 */
114	xtrb1	r0, r20
115	xtrb1	r2, r21
116	subu	r0, r2
117	bnez	r0, .L_return
118
119	/* check byte 0 */
120	xtrb0	r0, r20
121	xtrb0	r2, r21
122	subu	r0, r2
123	br	.L_return
124
125	/* Compare when s1 is not aligned.  */
126.L_s1_not_aligned:
127	sub	r13, r19, r13
128	sub	r2, r13
129.L_s1_not_aligned_loop:
130	ldb	r0, (r3, 0)
131	ldb	r4, (r1, 0)
132	addi	r3, 1
133	subu	r0, r4
134	PRE_BNEZAD (r13)
135	addi	r1, 1
136	bnez	r0, .L_return
137	BNEZAD (r13, .L_s1_not_aligned_loop)
138	br	.L_s1_aligned
139END (memcmp)
140weak_alias (memcmp, bcmp)
141strong_alias (memcmp, __memcmpeq)
142libc_hidden_def (memcmp)
143libc_hidden_def (__memcmpeq)
144.weak memcmp
145