blob: 49250a07c4fdd2a6b9288def962bc351fa724f2e [file] [log] [blame]
Prashant Patilfcb877a2017-03-16 18:07:00 +05301/*
2 * Copyright (c) 2017 Imagination Technologies.
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with
15 * the distribution.
16 * * Neither the name of Imagination Technologies nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifdef __ANDROID__
34# include <private/bionic_asm.h>
35#elif _LIBC
36# include <sysdep.h>
37# include <regdef.h>
38# include <sys/asm.h>
39#elif _COMPILING_NEWLIB
40# include "machine/asm.h"
41# include "machine/regdef.h"
42#else
43# include <regdef.h>
44# include <sys/asm.h>
45#endif
46
47#if __mips64
48# define NSIZE 8
49# define LW ld
50# define LWR ldr
51# define LWL ldl
52# define EXT dext
53# define SRL dsrl
54# define SUBU dsubu
55#else
56# define NSIZE 4
57# define LW lw
58# define LWR lwr
59# define LWL lwl
60# define EXT ext
61# define SRL srl
62# define SUBU subu
63#endif
64
65/* Technically strcmp should not read past the end of the strings being
66 compared. We will read a full word that may contain excess bits beyond
67 the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
68 read the next word after the end of string. Setting ENABLE_READAHEAD will
69 improve performance but is technically illegal based on the definition of
70 strcmp. */
71#ifdef ENABLE_READAHEAD
72# define DELAY_READ
73#else
74# define DELAY_READ nop
75#endif
76
77/* Testing on a little endian machine showed using CLZ was a
78 performance loss, so we are not turning it on by default. */
79#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1) && (!__mips64)
80# define USE_CLZ
81#endif
82
83/* Some asm.h files do not have the L macro definition. */
84#ifndef L
85# if _MIPS_SIM == _ABIO32
86# define L(label) $L ## label
87# else
88# define L(label) .L ## label
89# endif
90#endif
91
92/* Some asm.h files do not have the PTR_ADDIU macro definition. */
93#ifndef PTR_ADDIU
94# if _MIPS_SIM == _ABIO32
95# define PTR_ADDIU addiu
96# else
97# define PTR_ADDIU daddiu
98# endif
99#endif
100
101/* It might seem better to do the 'beq' instruction between the two 'lbu'
102 instructions so that the nop is not needed but testing showed that this
103 code is actually faster (based on glibc strcmp test). */
104#define BYTECMP01(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700105 lbu $v0, OFFSET($a0); \
106 lbu $v1, OFFSET($a1); \
107 beq $v0, $zero, L(bexit01); \
Prashant Patilfcb877a2017-03-16 18:07:00 +0530108 nop; \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700109 bne $v0, $v1, L(bexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530110
111#define BYTECMP89(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700112 lbu $t8, OFFSET($a0); \
113 lbu $t9, OFFSET($a1); \
114 beq $t8, $zero, L(bexit89); \
Prashant Patilfcb877a2017-03-16 18:07:00 +0530115 nop; \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700116 bne $t8, $t9, L(bexit89)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530117
118/* Allow the routine to be named something else if desired. */
119#ifndef STRNCMP_NAME
120# define STRNCMP_NAME strncmp
121#endif
122
123#ifdef __ANDROID__
124LEAF(STRNCMP_NAME, 0)
125#else
126LEAF(STRNCMP_NAME)
127#endif
128 .set nomips16
129 .set noreorder
130
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700131 srl $t0, $a2, (2 + NSIZE / 4)
132 beqz $t0, L(byteloop) #process by bytes if less than (2 * NSIZE)
133 andi $t1, $a1, (NSIZE - 1)
134 beqz $t1, L(exitalign)
135 or $t0, $zero, NSIZE
136 SUBU $t1, $t0, $t1 #process (NSIZE - 1) bytes at max
137 SUBU $a2, $a2, $t1 #dec count by t1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530138
139L(alignloop): #do by bytes until a1 aligned
140 BYTECMP01(0)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700141 SUBU $t1, $t1, 0x1
142 PTR_ADDIU $a0, $a0, 0x1
143 bne $t1, $zero, L(alignloop)
144 PTR_ADDIU $a1, $a1, 0x1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530145
146L(exitalign):
147
148/* string a1 is NSIZE byte aligned at this point. */
149#ifndef __mips1
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700150 lui $t8, 0x0101
151 ori $t8, 0x0101
152 lui $t9, 0x7f7f
153 ori $t9, 0x7f7f
Prashant Patilfcb877a2017-03-16 18:07:00 +0530154#if __mips64
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700155 dsll $t0, $t8, 32
156 or $t8, $t0
157 dsll $t1, $t9, 32
158 or $t9, $t1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530159#endif
160#endif
161
162/* hardware or software alignment not supported for mips1
163 rev6 archs have h/w unaligned support
164 remainings archs need to implemented with unaligned instructions */
165
166#if __mips1
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700167 andi $t0, $a0, (NSIZE - 1)
168 bne $t0, $zero, L(byteloop)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530169#elif __mips_isa_rev < 6
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700170 andi $t0, $a0, (NSIZE - 1)
171 bne $t0, $zero, L(uwordloop)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530172#endif
173
174#define STRCMPW(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700175 LW $v0, (OFFSET)($a0); \
176 LW $v1, (OFFSET)($a1); \
177 SUBU $t0, $v0, $t8; \
178 bne $v0, $v1, L(worddiff); \
179 nor $t1, $v0, $t9; \
180 and $t0, $t0, $t1; \
181 bne $t0, $zero, L(returnzero);\
Prashant Patilfcb877a2017-03-16 18:07:00 +0530182
183L(wordloop):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700184 SUBU $t1, $a2, (8 * NSIZE)
185 bltz $t1, L(onewords)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530186 STRCMPW(0 * NSIZE)
187 DELAY_READ
188 STRCMPW(1 * NSIZE)
189 DELAY_READ
190 STRCMPW(2 * NSIZE)
191 DELAY_READ
192 STRCMPW(3 * NSIZE)
193 DELAY_READ
194 STRCMPW(4 * NSIZE)
195 DELAY_READ
196 STRCMPW(5 * NSIZE)
197 DELAY_READ
198 STRCMPW(6 * NSIZE)
199 DELAY_READ
200 STRCMPW(7 * NSIZE)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700201 SUBU $a2, $a2, (8 * NSIZE)
202 PTR_ADDIU $a0, $a0, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530203 b L(wordloop)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700204 PTR_ADDIU $a1, $a1, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530205
206L(onewords):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700207 SUBU $t1, $a2, NSIZE
208 bltz $t1, L(byteloop)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530209 STRCMPW(0)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700210 SUBU $a2, $a2, NSIZE
211 PTR_ADDIU $a0, $a0, NSIZE
Prashant Patilfcb877a2017-03-16 18:07:00 +0530212 b L(onewords)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700213 PTR_ADDIU $a1, $a1, NSIZE
Prashant Patilfcb877a2017-03-16 18:07:00 +0530214
215#if __mips_isa_rev < 6 && !__mips1
216#define USTRCMPW(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700217 LWR $v0, (OFFSET)($a0); \
218 LWL $v0, (OFFSET + NSIZE - 1)($a0); \
219 LW $v1, (OFFSET)($a1); \
220 SUBU $t0, $v0, $t8; \
221 bne $v0, $v1, L(worddiff); \
222 nor $t1, $v0, $t9; \
223 and $t0, $t0, $t1; \
224 bne $t0, $zero, L(returnzero);\
Prashant Patilfcb877a2017-03-16 18:07:00 +0530225
226L(uwordloop):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700227 SUBU $t1, $a2, (8 * NSIZE)
228 bltz $t1, L(uonewords)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530229 USTRCMPW(0 * NSIZE)
230 DELAY_READ
231 USTRCMPW(1 * NSIZE)
232 DELAY_READ
233 USTRCMPW(2 * NSIZE)
234 DELAY_READ
235 USTRCMPW(3 * NSIZE)
236 DELAY_READ
237 USTRCMPW(4 * NSIZE)
238 DELAY_READ
239 USTRCMPW(5 * NSIZE)
240 DELAY_READ
241 USTRCMPW(6 * NSIZE)
242 DELAY_READ
243 USTRCMPW(7 * NSIZE)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700244 SUBU $a2, $a2, (8 * NSIZE)
245 PTR_ADDIU $a0, $a0, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530246 b L(uwordloop)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700247 PTR_ADDIU $a1, $a1, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530248
249L(uonewords):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700250 SUBU $t1, $a2, NSIZE
251 bltz $t1, L(byteloop)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530252 USTRCMPW(0)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700253 SUBU $a2, $a2, NSIZE
254 PTR_ADDIU $a0, $a0, NSIZE
Prashant Patilfcb877a2017-03-16 18:07:00 +0530255 b L(uonewords)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700256 PTR_ADDIU $a1, $a1, NSIZE
Prashant Patilfcb877a2017-03-16 18:07:00 +0530257
258#endif
259
260L(returnzero):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700261 j $ra
262 move $v0, $zero
Prashant Patilfcb877a2017-03-16 18:07:00 +0530263
264#if __mips_isa_rev > 1
265#define EXT_COMPARE01(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700266 EXT $t0, $v0, POS, 8; \
267 beq $t0, $zero, L(wexit01); \
268 EXT $t1, $v1, POS, 8; \
269 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530270#define EXT_COMPARE89(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700271 EXT $t8, $v0, POS, 8; \
272 beq $t8, $zero, L(wexit89); \
273 EXT $t9, $v1, POS, 8; \
274 bne $t8, $t9, L(wexit89)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530275#else
276#define EXT_COMPARE01(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700277 SRL $t0, $v0, POS; \
278 SRL $t1, $v1, POS; \
279 andi $t0, $t0, 0xff; \
280 beq $t0, $zero, L(wexit01); \
281 andi $t1, $t1, 0xff; \
282 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530283#define EXT_COMPARE89(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700284 SRL $t8, $v0, POS; \
285 SRL $t9, $v1, POS; \
286 andi $t8, $t8, 0xff; \
287 beq $t8, $zero, L(wexit89); \
288 andi $t9, $t9, 0xff; \
289 bne $t8, $t9, L(wexit89)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530290#endif
291
292L(worddiff):
293#ifdef USE_CLZ
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700294 SUBU $t0, $v0, $t8
295 nor $t1, $v0, $t9
296 and $t1, $t0, $t1
297 xor $t0, $v0, $v1
298 or $t0, $t0, $t1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530299# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700300 wsbh $t0, $t0
301 rotr $t0, $t0, 16
Prashant Patilfcb877a2017-03-16 18:07:00 +0530302# endif
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700303 clz $t1, $t0
304 and $t1, 0xf8
Prashant Patilfcb877a2017-03-16 18:07:00 +0530305# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700306 neg $t1
307 addu $t1, 24
Prashant Patilfcb877a2017-03-16 18:07:00 +0530308# endif
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700309 rotrv $v0, $v0, $t1
310 rotrv $v1, $v1, $t1
311 and $v0, $v0, 0xff
312 and $v1, $v1, 0xff
313 j $ra
314 SUBU $v0, $v0, $v1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530315#else /* USE_CLZ */
316# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700317 andi $t0, $v0, 0xff
318 beq $t0, $zero, L(wexit01)
319 andi $t1, $v1, 0xff
320 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530321 EXT_COMPARE89(8)
322 EXT_COMPARE01(16)
323#ifndef __mips64
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700324 SRL $t8, $v0, 24
325 SRL $t9, $v1, 24
Prashant Patilfcb877a2017-03-16 18:07:00 +0530326#else
327 EXT_COMPARE89(24)
328 EXT_COMPARE01(32)
329 EXT_COMPARE89(40)
330 EXT_COMPARE01(48)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700331 SRL $t8, $v0, 56
332 SRL $t9, $v1, 56
Prashant Patilfcb877a2017-03-16 18:07:00 +0530333#endif
334
335# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
336#ifdef __mips64
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700337 SRL $t0, $v0, 56
338 beq $t0, $zero, L(wexit01)
339 SRL $t1, $v1, 56
340 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530341 EXT_COMPARE89(48)
342 EXT_COMPARE01(40)
343 EXT_COMPARE89(32)
344 EXT_COMPARE01(24)
345#else
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700346 SRL $t0, $v0, 24
347 beq $t0, $zero, L(wexit01)
348 SRL $t1, $v1, 24
349 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530350#endif
351 EXT_COMPARE89(16)
352 EXT_COMPARE01(8)
353
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700354 andi $t8, $v0, 0xff
355 andi $t9, $v1, 0xff
Prashant Patilfcb877a2017-03-16 18:07:00 +0530356# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
357
358L(wexit89):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700359 j $ra
360 SUBU $v0, $t8, $t9
Prashant Patilfcb877a2017-03-16 18:07:00 +0530361L(wexit01):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700362 j $ra
363 SUBU $v0, $t0, $t1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530364#endif /* USE_CLZ */
365
366L(byteloop):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700367 beq $a2, $zero, L(returnzero)
368 SUBU $a2, $a2, 1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530369 BYTECMP01(0)
370 nop
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700371 beq $a2, $zero, L(returnzero)
372 SUBU $a2, $a2, 1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530373 BYTECMP89(1)
374 nop
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700375 beq $a2, $zero, L(returnzero)
376 SUBU $a2, $a2, 1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530377 BYTECMP01(2)
378 nop
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700379 beq $a2, $zero, L(returnzero)
380 SUBU $a2, $a2, 1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530381 BYTECMP89(3)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700382 PTR_ADDIU $a0, $a0, 4
Prashant Patilfcb877a2017-03-16 18:07:00 +0530383 b L(byteloop)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700384 PTR_ADDIU $a1, $a1, 4
Prashant Patilfcb877a2017-03-16 18:07:00 +0530385
386L(bexit01):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700387 j $ra
388 SUBU $v0, $v0, $v1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530389L(bexit89):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700390 j $ra
391 SUBU $v0, $t8, $t9
Prashant Patilfcb877a2017-03-16 18:07:00 +0530392
393 .set at
394 .set reorder
395
396END(STRNCMP_NAME)
397#ifndef __ANDROID__
398# ifdef _LIBC
399libc_hidden_builtin_def (STRNCMP_NAME)
400# endif
401#endif