xref: /freebsd/lib/libc/amd64/string/memcmp.S (revision d0b2dbfa)
1/*-
2 * Copyright (c) 2018 The FreeBSD Foundation
3 *
4 * This software was developed by Mateusz Guzik <mjg@FreeBSD.org>
5 * under sponsorship from the FreeBSD Foundation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <machine/asm.h>
30/*
31 * Note: this routine was written with kernel use in mind (read: no simd),
32 * it is only present in userspace as a temporary measure until something
33 * better gets imported.
34 */
35
36#define ALIGN_TEXT      .p2align 4,0x90 /* 16-byte alignment, nop filled */
37
38#ifdef BCMP
39ENTRY(bcmp)
40#else
41ENTRY(memcmp)
42#endif
43	xorl	%eax,%eax
4410:
45	cmpq	$16,%rdx
46	ja	101632f
47
48	cmpb	$8,%dl
49	jg	100816f
50
51	cmpb	$4,%dl
52	jg	100408f
53
54	cmpb	$2,%dl
55	jge	100204f
56
57	cmpb	$1,%dl
58	jl	100000f
59	movzbl	(%rdi),%eax
60	movzbl	(%rsi),%r8d
61	subl	%r8d,%eax
62100000:
63	ret
64
65	ALIGN_TEXT
66100816:
67	movq	(%rdi),%r8
68	movq	(%rsi),%r9
69	cmpq	%r8,%r9
70	jne	80f
71	movq	-8(%rdi,%rdx),%r8
72	movq	-8(%rsi,%rdx),%r9
73	cmpq	%r8,%r9
74	jne	10081608f
75	ret
76	ALIGN_TEXT
77100408:
78	movl	(%rdi),%r8d
79	movl	(%rsi),%r9d
80	cmpl	%r8d,%r9d
81	jne	80f
82	movl	-4(%rdi,%rdx),%r8d
83	movl	-4(%rsi,%rdx),%r9d
84	cmpl	%r8d,%r9d
85	jne	10040804f
86	ret
87	ALIGN_TEXT
88100204:
89	movzwl	(%rdi),%r8d
90	movzwl	(%rsi),%r9d
91	cmpl	%r8d,%r9d
92	jne	1f
93	movzwl	-2(%rdi,%rdx),%r8d
94	movzwl	-2(%rsi,%rdx),%r9d
95	cmpl	%r8d,%r9d
96	jne	1f
97	ret
98	ALIGN_TEXT
99101632:
100	cmpq	$32,%rdx
101	ja	103200f
102	movq	(%rdi),%r8
103	movq	(%rsi),%r9
104	cmpq	%r8,%r9
105	jne	80f
106	movq	8(%rdi),%r8
107	movq	8(%rsi),%r9
108	cmpq	%r8,%r9
109	jne	10163208f
110	movq	-16(%rdi,%rdx),%r8
111	movq	-16(%rsi,%rdx),%r9
112	cmpq	%r8,%r9
113	jne	10163216f
114	movq	-8(%rdi,%rdx),%r8
115	movq	-8(%rsi,%rdx),%r9
116	cmpq	%r8,%r9
117	jne	10163224f
118	ret
119	ALIGN_TEXT
120103200:
121	movq	(%rdi),%r8
122	movq	8(%rdi),%r9
123	subq	(%rsi),%r8
124	subq	8(%rsi),%r9
125	orq	%r8,%r9
126	jnz	10320000f
127
128	movq    16(%rdi),%r8
129	movq    24(%rdi),%r9
130	subq    16(%rsi),%r8
131	subq    24(%rsi),%r9
132	orq	%r8,%r9
133	jnz     10320016f
134
135	leaq	32(%rdi),%rdi
136	leaq	32(%rsi),%rsi
137	subq	$32,%rdx
138	cmpq	$32,%rdx
139	jae	103200b
140	cmpb	$0,%dl
141	jne	10b
142	ret
143
144/*
145 * Mismatch was found.
146 */
147#ifdef BCMP
148	ALIGN_TEXT
14910320016:
15010320000:
15110081608:
15210163224:
15310163216:
15410163208:
15510040804:
15680:
1571:
158	leal	1(%eax),%eax
159	ret
160END(bcmp)
161#else
162/*
163 * We need to compute the difference between strings.
164 * Start with narrowing the range down (16 -> 8 -> 4 bytes).
165 */
166	ALIGN_TEXT
16710320016:
168	leaq	16(%rdi),%rdi
169	leaq	16(%rsi),%rsi
17010320000:
171	movq	(%rdi),%r8
172	movq	(%rsi),%r9
173	cmpq	%r8,%r9
174	jne	80f
175	leaq	8(%rdi),%rdi
176	leaq	8(%rsi),%rsi
177	jmp	80f
178	ALIGN_TEXT
17910081608:
18010163224:
181	leaq	-8(%rdi,%rdx),%rdi
182	leaq	-8(%rsi,%rdx),%rsi
183	jmp	80f
184	ALIGN_TEXT
18510163216:
186	leaq	-16(%rdi,%rdx),%rdi
187	leaq	-16(%rsi,%rdx),%rsi
188	jmp	80f
189	ALIGN_TEXT
19010163208:
191	leaq	8(%rdi),%rdi
192	leaq	8(%rsi),%rsi
193	jmp	80f
194	ALIGN_TEXT
19510040804:
196	leaq	-4(%rdi,%rdx),%rdi
197	leaq	-4(%rsi,%rdx),%rsi
198	jmp	1f
199
200	ALIGN_TEXT
20180:
202	movl	(%rdi),%r8d
203	movl	(%rsi),%r9d
204	cmpl	%r8d,%r9d
205	jne	1f
206	leaq	4(%rdi),%rdi
207	leaq	4(%rsi),%rsi
208
209/*
210 * We have up to 4 bytes to inspect.
211 */
2121:
213	movzbl	(%rdi),%eax
214	movzbl	(%rsi),%r8d
215	cmpb	%r8b,%al
216	jne	2f
217
218	movzbl	1(%rdi),%eax
219	movzbl	1(%rsi),%r8d
220	cmpb	%r8b,%al
221	jne	2f
222
223	movzbl	2(%rdi),%eax
224	movzbl	2(%rsi),%r8d
225	cmpb	%r8b,%al
226	jne	2f
227
228	movzbl	3(%rdi),%eax
229	movzbl	3(%rsi),%r8d
2302:
231	subl	%r8d,%eax
232	ret
233END(memcmp)
234#endif
235
236	.section .note.GNU-stack,"",%progbits
237