xref: /freebsd/lib/libc/amd64/string/memcmp.S (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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 * $FreeBSD$
29 */
30
31#include <machine/asm.h>
32__FBSDID("$FreeBSD$");
33
34/*
35 * Note: this routine was written with kernel use in mind (read: no simd),
36 * it is only present in userspace as a temporary measure until something
37 * better gets imported.
38 */
39
40#define ALIGN_TEXT      .p2align 4,0x90 /* 16-byte alignment, nop filled */
41
42#ifdef BCMP
43ENTRY(bcmp)
44#else
45ENTRY(memcmp)
46#endif
47	xorl	%eax,%eax
4810:
49	cmpq	$16,%rdx
50	ja	101632f
51
52	cmpb	$8,%dl
53	jg	100816f
54
55	cmpb	$4,%dl
56	jg	100408f
57
58	cmpb	$2,%dl
59	jge	100204f
60
61	cmpb	$1,%dl
62	jl	100000f
63	movzbl	(%rdi),%eax
64	movzbl	(%rsi),%r8d
65	subl	%r8d,%eax
66100000:
67	ret
68
69	ALIGN_TEXT
70100816:
71	movq	(%rdi),%r8
72	movq	(%rsi),%r9
73	cmpq	%r8,%r9
74	jne	80f
75	movq	-8(%rdi,%rdx),%r8
76	movq	-8(%rsi,%rdx),%r9
77	cmpq	%r8,%r9
78	jne	10081608f
79	ret
80	ALIGN_TEXT
81100408:
82	movl	(%rdi),%r8d
83	movl	(%rsi),%r9d
84	cmpl	%r8d,%r9d
85	jne	80f
86	movl	-4(%rdi,%rdx),%r8d
87	movl	-4(%rsi,%rdx),%r9d
88	cmpl	%r8d,%r9d
89	jne	10040804f
90	ret
91	ALIGN_TEXT
92100204:
93	movzwl	(%rdi),%r8d
94	movzwl	(%rsi),%r9d
95	cmpl	%r8d,%r9d
96	jne	1f
97	movzwl	-2(%rdi,%rdx),%r8d
98	movzwl	-2(%rsi,%rdx),%r9d
99	cmpl	%r8d,%r9d
100	jne	1f
101	ret
102	ALIGN_TEXT
103101632:
104	cmpq	$32,%rdx
105	ja	103200f
106	movq	(%rdi),%r8
107	movq	(%rsi),%r9
108	cmpq	%r8,%r9
109	jne	80f
110	movq	8(%rdi),%r8
111	movq	8(%rsi),%r9
112	cmpq	%r8,%r9
113	jne	10163208f
114	movq	-16(%rdi,%rdx),%r8
115	movq	-16(%rsi,%rdx),%r9
116	cmpq	%r8,%r9
117	jne	10163216f
118	movq	-8(%rdi,%rdx),%r8
119	movq	-8(%rsi,%rdx),%r9
120	cmpq	%r8,%r9
121	jne	10163224f
122	ret
123	ALIGN_TEXT
124103200:
125	movq	(%rdi),%r8
126	movq	8(%rdi),%r9
127	subq	(%rsi),%r8
128	subq	8(%rsi),%r9
129	orq	%r8,%r9
130	jnz	10320000f
131
132	movq    16(%rdi),%r8
133	movq    24(%rdi),%r9
134	subq    16(%rsi),%r8
135	subq    24(%rsi),%r9
136	orq	%r8,%r9
137	jnz     10320016f
138
139	leaq	32(%rdi),%rdi
140	leaq	32(%rsi),%rsi
141	subq	$32,%rdx
142	cmpq	$32,%rdx
143	jae	103200b
144	cmpb	$0,%dl
145	jne	10b
146	ret
147
148/*
149 * Mismatch was found.
150 */
151#ifdef BCMP
152	ALIGN_TEXT
15310320016:
15410320000:
15510081608:
15610163224:
15710163216:
15810163208:
15910040804:
16080:
1611:
162	leal	1(%eax),%eax
163	ret
164END(bcmp)
165#else
166/*
167 * We need to compute the difference between strings.
168 * Start with narrowing the range down (16 -> 8 -> 4 bytes).
169 */
170	ALIGN_TEXT
17110320016:
172	leaq	16(%rdi),%rdi
173	leaq	16(%rsi),%rsi
17410320000:
175	movq	(%rdi),%r8
176	movq	(%rsi),%r9
177	cmpq	%r8,%r9
178	jne	80f
179	leaq	8(%rdi),%rdi
180	leaq	8(%rsi),%rsi
181	jmp	80f
182	ALIGN_TEXT
18310081608:
18410163224:
185	leaq	-8(%rdi,%rdx),%rdi
186	leaq	-8(%rsi,%rdx),%rsi
187	jmp	80f
188	ALIGN_TEXT
18910163216:
190	leaq	-16(%rdi,%rdx),%rdi
191	leaq	-16(%rsi,%rdx),%rsi
192	jmp	80f
193	ALIGN_TEXT
19410163208:
195	leaq	8(%rdi),%rdi
196	leaq	8(%rsi),%rsi
197	jmp	80f
198	ALIGN_TEXT
19910040804:
200	leaq	-4(%rdi,%rdx),%rdi
201	leaq	-4(%rsi,%rdx),%rsi
202	jmp	1f
203
204	ALIGN_TEXT
20580:
206	movl	(%rdi),%r8d
207	movl	(%rsi),%r9d
208	cmpl	%r8d,%r9d
209	jne	1f
210	leaq	4(%rdi),%rdi
211	leaq	4(%rsi),%rsi
212
213/*
214 * We have up to 4 bytes to inspect.
215 */
2161:
217	movzbl	(%rdi),%eax
218	movzbl	(%rsi),%r8d
219	cmpb	%r8b,%al
220	jne	2f
221
222	movzbl	1(%rdi),%eax
223	movzbl	1(%rsi),%r8d
224	cmpb	%r8b,%al
225	jne	2f
226
227	movzbl	2(%rdi),%eax
228	movzbl	2(%rsi),%r8d
229	cmpb	%r8b,%al
230	jne	2f
231
232	movzbl	3(%rdi),%eax
233	movzbl	3(%rsi),%r8d
2342:
235	subl	%r8d,%eax
236	ret
237END(memcmp)
238#endif
239
240	.section .note.GNU-stack,"",%progbits
241