aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/machine/i386/strchr.S
blob: 43ee0fbbf06160afb4228076e4c2f63dcd0fe787 (plain)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * ====================================================
 * Copyright (C) 1998, 2002, 2008 by Red Hat Inc. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

	#include "i386mach.h"

	.global SYM (strchr)
       SOTYPE_FUNCTION(strchr)

SYM (strchr):

#ifdef __iamcu__
	xorl ecx,ecx
	movb dl,cl

/* loop while (*s && *s++ != c) */
	leal -1(eax),eax
L15:
	incl eax
	movb (eax),dl
	testb dl,dl
	je L14
	cmpb cl,dl
	jne L15

L14:
/*  if (*s == c) return address otherwise return NULL */
	cmpb cl,(eax)
	je L19
	xorl eax,eax

L19:
	ret
#else
	pushl ebp
	movl esp,ebp
	pushl edi
	pushl ebx
	xorl ebx,ebx
	movl 8(ebp),edi
	addb 12(ebp),bl

#ifndef __OPTIMIZE_SIZE__
/* Special case strchr(p,0).  */
	je L25

/* Do byte-wise checks until string is aligned.  */
	test $3,edi
	je L5
	movl edi,eax
	movb (eax),cl
	testb cl,cl
	je L14
	cmpb bl,cl
	je L19
	incl edi

	test $3,edi
	je L5
	movl edi,eax
	movb (eax),cl
	testb cl,cl
	je L14
	cmpb bl,cl
	je L19
	incl edi

	test $3,edi
	je L5
	movl edi,eax
	movb (eax),cl
	testb cl,cl
	je L14
	cmpb bl,cl
	je L19
	incl edi

/* create 4 byte mask which is just the desired byte repeated 4 times */
L5:
	movl ebx,ecx
	sall $8,ebx
	subl $4,edi
	orl ecx,ebx
	movl ebx,edx
	sall $16,ebx
	orl edx,ebx

/* loop performing 4 byte mask checking for 0 byte or desired byte */
	.p2align 4,,7
L10:
	addl $4,edi
	movl (edi),ecx
	leal -16843009(ecx),edx
	movl ecx,eax
	notl eax
	andl eax,edx
	testl $-2139062144,edx
	jne L9

	xorl ebx,ecx
	leal -16843009(ecx),edx
	notl ecx
	andl ecx,edx
	testl $-2139062144,edx
	je L10
#endif /* not __OPTIMIZE_SIZE__ */

/* loop while (*s && *s++ != c) */
L9:
	leal -1(edi),eax
	.p2align 4,,7
L15:
	incl eax
	movb (eax),dl
	testb dl,dl
	je L14
	cmpb bl,dl
	jne L15

L14:
/*  if (*s == c) return address otherwise return NULL */
	cmpb bl,(eax)
	je L19
	xorl eax,eax

L19:
	leal -8(ebp),esp
	popl ebx
	popl edi
	leave
	ret

#ifndef __OPTIMIZE_SIZE__
/* Special case strchr(p,0).  */
#if 0
	/* Hideous performance on modern machines.  */
L25:
	cld
	movl $-1,ecx
	xor eax,eax
	repnz
	scasb
	leal -1(edi),eax
	jmp L19
#endif
L25:
/* Do byte-wise checks until string is aligned.  */
	test $3,edi
	je L26
	movl edi,eax
	movb (eax),cl
	testb cl,cl
	je L19
	incl edi

	test $3,edi
	je L26
	movl edi,eax
	movb (eax),cl
	testb cl,cl
	je L19
	incl edi

	test $3,edi
	je L26
	movl edi,eax
	movb (eax),cl
	testb cl,cl
	je L19
	incl edi

L26:
	subl $4,edi

/* loop performing 4 byte mask checking for desired 0 byte */
	.p2align 4,,7
L27:
	addl $4,edi
	movl (edi),ecx
	leal -16843009(ecx),edx
	movl ecx,eax
	notl eax
	andl eax,edx
	testl $-2139062144,edx
	je L27

	jmp L9

#endif /* !__OPTIMIZE_SIZE__ */

#endif /* __iamcu__ */