summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/i386/gen/strchr.s
blob: d4a9830770896304e7b393194560929c10259bbd (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
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

	.file	"strchr.s"

#include "SYS.h"

	ENTRY(strchr)
	mov 4(%esp), %ecx		/ src string here
	mov 8(%esp), %edx		/ character to find
	mov %ecx, %eax			/ save src
	and $3, %ecx			/ check if src is aligned
	jz prepword			/ search wordwise if it is

	cmpb %dl, (%eax)		/ src == char?
	jz done
	cmpb $0, (%eax)			/ src == 0?
	jz not_found
	add $1, %eax			/ increment src
	cmp $3, %ecx			/ check alignment
	jz prepword
	cmpb %dl, (%eax)		/ src byte contains char?
	jz done
	cmpb $0, (%eax)			/ src byte == 0?
	jz not_found
	add $1, %eax			/ increment src ptr
	cmp $2, %ecx			/ check alignment
	jz prepword
	cmpb %dl, (%eax) 		/ check this byte
	jz done
	cmpb $0, (%eax)			/ is byte zero?
	jz not_found
	add $1, %eax			/ increment src ptr

prepword:
	push %ebx			/ save regs per calling convention
	push %esi
	and $0xff, %edx			/ only want 1st byte
	mov %edx, %ebx			/ copy character across all bytes in wd
	shl $8, %edx
	or %ebx, %edx
	mov %edx, %ebx
	shl $16, %edx
	or %ebx, %edx

	.align 16			/ align loop for max performance

searchchar:
	mov (%eax), %esi		/ load src word
	add $4, %eax			/ increment src by four
	mov %esi, %ebx			/ copy word
	lea -0x01010101(%esi), %ecx	/ (word - 0x01010101)
	xor %edx, %ebx			/ tmpword = word ^ char	
	not %esi			/ ~word
	and $0x80808080, %esi		/ ~word & 0x80808080
	and %ecx, %esi			/ (wd - 0x01010101) & ~wd & 0x80808080
	jnz has_zero_byte
	lea -0x01010101(%ebx), %ecx	/ repeat with tmpword
	not %ebx
	and $0x80808080, %ebx
	and %ecx, %ebx
	jz searchchar			/ repeat if char not found

found_char:
	add $0x01010101, %ecx		/ restore tmpword
	pop %esi			/ restore esi ebx as per calling cvntn
	pop %ebx
	test $0x000000ff, %ecx		/ look for character's position in word
	jz done0
	test $0x0000ff00, %ecx
	jz done1
	test $0x00ff0000, %ecx
	jz done2
done3:
	sub $1, %eax
	ret
done2:
	sub $2, %eax
	ret
done1:
	sub $3, %eax
	ret
done0:
	sub $4, %eax
	ret
has_zero_byte:
	add $0x01010101, %ecx		/ restore registers here
	pop %esi
	pop %ebx
	cmpb %dl, %cl			/ check for character
	je done0
	testb %cl, %cl			/ check for null byte
	jz not_found
	cmpb %dh, %ch			/ continue checking for char, null
	je done1
	testb %ch, %ch
	jz not_found
	shr $16, %ecx			/ put bytes 2,3 into 8-but registers
	cmpb %dl, %cl
	je done2
	testb %cl, %cl
	jz not_found
	cmpb %dh, %ch			/ repeat checking last 2 bytes
	je done3
	testb %ch, %ch
	jz not_found
	sub $1, %eax			/ correct for last loop iteration
done:
	ret
not_found:
	xor %eax, %eax
	ret
	SET_SIZE(strchr)