blob: 4791a0d383b3c5a12ae61a8920b656d3dbc38fdb [file] [log] [blame]
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +02001/*
Prashant Patilfcb877a2017-03-16 18:07:00 +05302 * Copyright (c) 2017 Imagination Technologies.
3 *
4 * All rights reserved.
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +02005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +02009 *
Prashant Patilfcb877a2017-03-16 18:07:00 +053010 * * 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.
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +020031 */
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
Prashant Patilfcb877a2017-03-16 18:07:00 +053047#if __mips64
48# define NSIZE 8
49# define LW ld
50# define EXT dext
51# define SRL dsrl
52# define SLL dsll
53# define SUBU dsubu
54#else
55# define NSIZE 4
56# define LW lw
57# define EXT ext
58# define SRL srl
59# define SLL sll
60# define SUBU subu
61#endif
62
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +020063/* Technically strcmp should not read past the end of the strings being
64 compared. We will read a full word that may contain excess bits beyond
65 the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
66 read the next word after the end of string. Setting ENABLE_READAHEAD will
67 improve performance but is technically illegal based on the definition of
68 strcmp. */
69#ifdef ENABLE_READAHEAD
70# define DELAY_READ
71#else
72# define DELAY_READ nop
73#endif
74
75/* Testing on a little endian machine showed using CLZ was a
76 performance loss, so we are not turning it on by default. */
77#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1)
78# define USE_CLZ
79#endif
80
81/* Some asm.h files do not have the L macro definition. */
82#ifndef L
83# if _MIPS_SIM == _ABIO32
84# define L(label) $L ## label
85# else
86# define L(label) .L ## label
87# endif
88#endif
89
90/* Some asm.h files do not have the PTR_ADDIU macro definition. */
91#ifndef PTR_ADDIU
92# if _MIPS_SIM == _ABIO32
93# define PTR_ADDIU addiu
94# else
95# define PTR_ADDIU daddiu
96# endif
97#endif
98
Prashant Patilfcb877a2017-03-16 18:07:00 +053099/* It might seem better to do the 'beq' instruction between the two 'lbu'
100 instructions so that the nop is not needed but testing showed that this
101 code is actually faster (based on glibc strcmp test). */
102#define BYTECMP01(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700103 lbu $v0, OFFSET($a0); \
104 lbu $v1, OFFSET($a1); \
105 beq $v0, $zero, L(bexit01); \
Prashant Patilfcb877a2017-03-16 18:07:00 +0530106 nop; \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700107 bne $v0, $v1, L(bexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530108
109#define BYTECMP89(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700110 lbu $t8, OFFSET($a0); \
111 lbu $t9, OFFSET($a1); \
112 beq $t8, $zero, L(bexit89); \
Prashant Patilfcb877a2017-03-16 18:07:00 +0530113 nop; \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700114 bne $t8, $t9, L(bexit89)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530115
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200116/* Allow the routine to be named something else if desired. */
117#ifndef STRCMP_NAME
118# define STRCMP_NAME strcmp
119#endif
120
121#ifdef __ANDROID__
122LEAF(STRCMP_NAME, 0)
123#else
124LEAF(STRCMP_NAME)
125#endif
Prashant Patilfcb877a2017-03-16 18:07:00 +0530126 .set nomips16
127 .set noreorder
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200128
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700129 andi $t1, $a1, (NSIZE - 1)
130 beqz $t1, L(exitalign)
131 or $t0, $zero, NSIZE
132 SUBU $t1, $t0, $t1 #process (NSIZE - 1) bytes at max
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200133
Prashant Patilfcb877a2017-03-16 18:07:00 +0530134L(alignloop): #do by bytes until a1 aligned
135 BYTECMP01(0)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700136 SUBU $t1, $t1, 0x1
137 PTR_ADDIU $a0, $a0, 0x1
138 bnez $t1, L(alignloop)
139 PTR_ADDIU $a1, $a1, 0x1
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200140
Prashant Patilfcb877a2017-03-16 18:07:00 +0530141L(exitalign):
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200142
Prashant Patilfcb877a2017-03-16 18:07:00 +0530143/* string a1 is NSIZE byte aligned at this point. */
144
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700145 lui $t8, 0x0101
146 ori $t8, 0x0101
147 lui $t9, 0x7f7f
148 ori $t9, 0x7f7f
Prashant Patilfcb877a2017-03-16 18:07:00 +0530149#if __mips64
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700150 dsll $t1, $t8, 32
151 or $t8, $t1
152 dsll $t1, $t9, 32
153 or $t9, $t1
Prashant Patilfcb877a2017-03-16 18:07:00 +0530154#endif
155
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700156 andi $t2, $a0, (NSIZE - 1) #check if a0 aligned
157 SUBU $t3, $t0, $t2 #t3 will be used as shifter
158 bnez $t2, L(uloopenter)
159 SUBU $a2, $a0, $t2 #bring back a0 to aligned position
Prashant Patilfcb877a2017-03-16 18:07:00 +0530160
161#define STRCMPW(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700162 LW $v0, OFFSET($a0); \
163 LW $v1, OFFSET($a1); \
164 SUBU $t0, $v0, $t8; \
165 bne $v0, $v1, L(worddiff); \
166 nor $t1, $v0, $t9; \
167 and $t0, $t0, $t1; \
168 bne $t0, $zero, L(returnzero);\
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200169
170L(wordloop):
Prashant Patilfcb877a2017-03-16 18:07:00 +0530171 STRCMPW(0 * NSIZE)
172 DELAY_READ
173 STRCMPW(1 * NSIZE)
174 DELAY_READ
175 STRCMPW(2 * NSIZE)
176 DELAY_READ
177 STRCMPW(3 * NSIZE)
178 DELAY_READ
179 STRCMPW(4 * NSIZE)
180 DELAY_READ
181 STRCMPW(5 * NSIZE)
182 DELAY_READ
183 STRCMPW(6 * NSIZE)
184 DELAY_READ
185 STRCMPW(7 * NSIZE)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700186 PTR_ADDIU $a0, $a0, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530187 b L(wordloop)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700188 PTR_ADDIU $a1, $a1, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530189
190#define USTRCMPW(OFFSET) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700191 LW $v1, OFFSET($a1); \
192 SUBU $t0, $v0, $t8; \
193 nor $t1, $v0, $t9; \
194 and $t0, $t0, $t1; \
195 bne $t0, $zero, L(worddiff); \
196 SRL $v0, $t2; \
197 LW $a3, (OFFSET + NSIZE)($a2); \
198 SUBU $t0, $v1, $t8; \
199 SLL $t1, $a3, $t3; \
200 or $v0, $v0, $t1; \
201 bne $v0, $v1, L(worddiff); \
202 nor $t1, $v1, $t9; \
203 and $t0, $t0, $t1; \
204 bne $t0, $zero, L(returnzero); \
205 move $v0, $a3;\
Prashant Patilfcb877a2017-03-16 18:07:00 +0530206
207L(uloopenter):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700208 LW $v0, 0($a2)
209 SLL $t2, 3 #multiply by 8
210 SLL $t3, 3 #multiply by 8
211 li $a3, -1 #all 1s
212 SRL $a3, $t3
213 or $v0, $a3 #replace with all 1s if zeros in unintented read
Prashant Patilfcb877a2017-03-16 18:07:00 +0530214
215L(uwordloop):
216 USTRCMPW(0 * NSIZE)
217 USTRCMPW(1 * NSIZE)
218 USTRCMPW(2 * NSIZE)
219 USTRCMPW(3 * NSIZE)
220 USTRCMPW(4 * NSIZE)
221 USTRCMPW(5 * NSIZE)
222 USTRCMPW(6 * NSIZE)
223 USTRCMPW(7 * NSIZE)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700224 PTR_ADDIU $a2, $a2, (8 * NSIZE)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530225 b L(uwordloop)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700226 PTR_ADDIU $a1, $a1, (8 * NSIZE)
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200227
228L(returnzero):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700229 j $ra
230 move $v0, $zero
Prashant Patilfcb877a2017-03-16 18:07:00 +0530231
232#if __mips_isa_rev > 1
233#define EXT_COMPARE01(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700234 EXT $t0, $v0, POS, 8; \
235 beq $t0, $zero, L(wexit01); \
236 EXT $t1, $v1, POS, 8; \
237 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530238#define EXT_COMPARE89(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700239 EXT $t8, $v0, POS, 8; \
240 beq $t8, $zero, L(wexit89); \
241 EXT $t9, $v1, POS, 8; \
242 bne $t8, $t9, L(wexit89)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530243#else
244#define EXT_COMPARE01(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700245 SRL $t0, $v0, POS; \
246 SRL $t1, $v1, POS; \
247 andi $t0, $t0, 0xff; \
248 beq $t0, $zero, L(wexit01); \
249 andi $t1, $t1, 0xff; \
250 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530251#define EXT_COMPARE89(POS) \
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700252 SRL $t8, $v0, POS; \
253 SRL $t9, $v1, POS; \
254 andi $t8, $t8, 0xff; \
255 beq $t8, $zero, L(wexit89); \
256 andi $t9, $t9, 0xff; \
257 bne $t8, $t9, L(wexit89)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530258#endif
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200259
260L(worddiff):
261#ifdef USE_CLZ
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700262 SUBU $t0, $v0, $t8
263 nor $t1, $v0, $t9
264 and $t1, $t0, $t1
265 xor $t0, $v0, $v1
266 or $t0, $t0, $t1
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200267# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700268 wsbh $t0, $t0
269 rotr $t0, $t0, 16
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200270# endif
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700271 clz $t1, $t0
272 and $t1, 0xf8
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200273# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700274 neg $t1
275 addu $t1, 24
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200276# endif
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700277 rotrv $v0, $v0, $t1
278 rotrv $v1, $v1, $t1
279 and $v0, $v0, 0xff
280 and $v1, $v1, 0xff
281 j $ra
282 SUBU $v0, $v0, $v1
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200283#else /* USE_CLZ */
284# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700285 andi $t0, $v0, 0xff
286 beq $t0, $zero, L(wexit01)
287 andi $t1, $v1, 0xff
288 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530289 EXT_COMPARE89(8)
290 EXT_COMPARE01(16)
291#ifndef __mips64
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700292 SRL $t8, $v0, 24
293 SRL $t9, $v1, 24
Prashant Patilfcb877a2017-03-16 18:07:00 +0530294#else
295 EXT_COMPARE89(24)
296 EXT_COMPARE01(32)
297 EXT_COMPARE89(40)
298 EXT_COMPARE01(48)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700299 SRL $t8, $v0, 56
300 SRL $t9, $v1, 56
Prashant Patilfcb877a2017-03-16 18:07:00 +0530301#endif
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200302
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200303# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
Prashant Patilfcb877a2017-03-16 18:07:00 +0530304#ifdef __mips64
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700305 SRL $t0, $v0, 56
306 beq $t0, $zero, L(wexit01)
307 SRL $t1, $v1, 56
308 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530309 EXT_COMPARE89(48)
310 EXT_COMPARE01(40)
311 EXT_COMPARE89(32)
312 EXT_COMPARE01(24)
313#else
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700314 SRL $t0, $v0, 24
315 beq $t0, $zero, L(wexit01)
316 SRL $t1, $v1, 24
317 bne $t0, $t1, L(wexit01)
Prashant Patilfcb877a2017-03-16 18:07:00 +0530318#endif
319 EXT_COMPARE89(16)
320 EXT_COMPARE01(8)
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200321
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700322 andi $t8, $v0, 0xff
323 andi $t9, $v1, 0xff
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200324# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
325
326L(wexit89):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700327 j $ra
328 SUBU $v0, $t8, $t9
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200329L(wexit01):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700330 j $ra
331 SUBU $v0, $t0, $t1
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200332#endif /* USE_CLZ */
333
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200334L(byteloop):
Prashant Patilfcb877a2017-03-16 18:07:00 +0530335 BYTECMP01(0)
336 BYTECMP89(1)
337 BYTECMP01(2)
338 BYTECMP89(3)
339 BYTECMP01(4)
340 BYTECMP89(5)
341 BYTECMP01(6)
342 BYTECMP89(7)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700343 PTR_ADDIU $a0, $a0, 8
Prashant Patilfcb877a2017-03-16 18:07:00 +0530344 b L(byteloop)
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700345 PTR_ADDIU $a1, $a1, 8
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200346
347L(bexit01):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700348 j $ra
349 SUBU $v0, $v0, $v1
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200350L(bexit89):
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700351 j $ra
352 SUBU $v0, $t8, $t9
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200353
Prashant Patilfcb877a2017-03-16 18:07:00 +0530354 .set at
355 .set reorder
Nikola Veljkovic38f2eaa2015-05-26 12:06:09 +0200356
357END(STRCMP_NAME)
358#ifndef __ANDROID__
359# ifdef _LIBC
360libc_hidden_builtin_def (STRCMP_NAME)
361# endif
362#endif