about summary refs log tree commit diff
path: root/sysdeps/aarch64/memcmp.S
blob: 5176aeac8dc199d5fc3df5b278dade8fd50b8e8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* memcmp - compare memory

   Copyright (C) 2013-2020 Free Software Foundation, Inc.

   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library.  If not, see
   <https://www.gnu.org/licenses/>.  */

#include <sysdep.h>

/* Assumptions:
 *
 * ARMv8-a, AArch64, unaligned accesses.
 */

/* Parameters and result.  */
#define src1		x0
#define src2		x1
#define limit		x2
#define result		w0

/* Internal variables.  */
#define data1		x3
#define data1w		w3
#define data1h		x4
#define data2		x5
#define data2w		w5
#define data2h		x6
#define tmp1		x7
#define tmp2		x8

ENTRY_ALIGN (memcmp, 6)
	PTR_ARG (0)
	PTR_ARG (1)
	SIZE_ARG (2)

	subs	limit, limit, 16
	b.lo	L(less16)

	ldp	data1, data1h, [src1], 16
	ldp	data2, data2h, [src2], 16
	ccmp	data1, data2, 0, ne
	ccmp	data1h, data2h, 0, eq
	b.ne	L(return64)

	subs	limit, limit, 16
	b.ls	L(last_bytes)
	cmp	limit, 112
	b.lo	L(loop16)

	and	tmp1, src1, 15
	add	limit, limit, tmp1
	sub	src1, src1, tmp1
	sub	src2, src2, tmp1
	subs	limit, limit, 48

	/* Compare 128 up bytes using aligned access. */
	.p2align 4
L(loop64):
	ldp	data1, data1h, [src1]
	ldp	data2, data2h, [src2]
	cmp	data1, data2
	ccmp	data1h, data2h, 0, eq
	b.ne	L(return64)

	ldp	data1, data1h, [src1, 16]
	ldp	data2, data2h, [src2, 16]
	cmp	data1, data2
	ccmp	data1h, data2h, 0, eq
	b.ne	L(return64)

	ldp	data1, data1h, [src1, 32]
	ldp	data2, data2h, [src2, 32]
	cmp	data1, data2
	ccmp	data1h, data2h, 0, eq
	b.ne	L(return64)

	ldp	data1, data1h, [src1, 48]
	ldp	data2, data2h, [src2, 48]
	cmp	data1, data2
	ccmp	data1h, data2h, 0, eq
	b.ne	L(return64)

	subs	limit, limit, 64
	add	src1, src1, 64
	add	src2, src2, 64
	b.pl	L(loop64)
	adds	limit, limit, 48
	b.lo	L(last_bytes)

L(loop16):
	ldp	data1, data1h, [src1], 16
	ldp	data2, data2h, [src2], 16
	cmp	data1, data2
	ccmp	data1h, data2h, 0, eq
	b.ne	L(return64)

	subs	limit, limit, 16
	b.hi	L(loop16)
	/* Compare last 1-16 bytes using unaligned access.  */
L(last_bytes):
	add	src1, src1, limit
	add	src2, src2, limit
	ldp	data1, data1h, [src1]
	ldp	data2, data2h, [src2]

	/* Compare data bytes and set return value to 0, -1 or 1.  */
L(return64):
	cmp	data1, data2
	csel	data1, data1, data1h, ne
	csel	data2, data2, data2h, ne
L(return):
#ifndef __AARCH64EB__
	rev	data1, data1
	rev	data2, data2
#endif
	cmp	data1, data2
	cset	result, ne
	cneg	result, result, lo
	ret

	.p2align 4
L(less16):
	adds	limit, limit, 8
	b.lo	L(less8)		//lo:<
	ldr	data1, [src1]
	ldr	data2, [src2]
	/* equal 8 optimized */
	ccmp	data1, data2, 0, ne
	b.ne	L(return)

	ldr	data1, [src1, limit]
	ldr	data2, [src2, limit]
	b	L(return)

	.p2align 4
L(less8):
	adds	limit, limit, 4
	b.lo	L(less4)
	ldr	data1w, [src1]
	ldr	data2w, [src2]
	ccmp	data1w, data2w, 0, ne
	b.ne	L(return)
	ldr	data1w,	[src1, limit]
	ldr	data2w,	[src2, limit]
	b	L(return)

	.p2align 4
L(less4):
	adds	limit, limit, 4
	b.eq	L(ret_0)

L(byte_loop):
	ldrb	data1w, [src1], 1
	ldrb	data2w, [src2], 1
	subs	limit, limit, 1
	ccmp	data1w, data2w, 0, ne	/* NZCV = 0b0000.  */
	b.eq	L(byte_loop)
	sub	result, data1w, data2w
	ret
L(ret_0):
	mov	result, 0
	ret

END (memcmp)
#undef bcmp
weak_alias (memcmp, bcmp)
libc_hidden_builtin_def (memcmp)