xref: /titanic_51/usr/src/lib/libc/i386/gen/strlen.s (revision 6a72db4a7fa12c3e0d1c1cf91a07390739fa0fbf)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26	.file	"strlen.s"
27
28/
29/ strlen(s)
30/
31/ Returns the number of non-NULL bytes in string argument.
32/
33/
34/ Fast assembly language version of the following C-program strlen
35/ which represents the `standard' for the C-library.
36/
37/	size_t
38/	strlen(const char *s)
39/	{
40/		const char	*s0 = s + 1;
41/
42/		while (*s++ != '\0')
43/			;
44/		return (s - s0);
45/	}
46/
47/ In this assembly language version, the following expression is used
48/ to check if a 32-bit word data contains a null byte or not:
49/	(((A & 0x7f7f7f7f) + 0x7f7f7f7f) | A) & 0x80808080
50/ If the above expression geneates a value other than 0x80808080,
51/ that means the 32-bit word data contains a null byte.
52/
53
54#include "SYS.h"
55
56	ENTRY(strlen)
57	mov	4(%esp), %edx		/ src in %edx
58	mov	%edx, %eax		/ cpy src to %eax
59
60	and	$3, %edx		/ is src aligned?
61	jz	countbytes
62					/ work byte-wise until aligned
63	cmpb	$0, (%eax)		/ is *src == 0 ?
64	jz	done
65	inc	%eax			/ increment src
66	cmp	$3, %edx		/ if aligned, jump to word-wise check
67	jz	countbytes
68	cmpb	$0, (%eax)
69	jz	done
70	inc	%eax
71	cmp	$2, %edx
72	jz	countbytes
73	cmpb	$0, (%eax)
74	jz	done
75	inc	%eax
76
77	.align    16
78
79countbytes:
80	mov	(%eax), %ecx		/ load wrd
81	add	$4, %eax		/ increment src by 4 (bytes in word)
82	lea	-0x01010101(%ecx), %edx	/ (wrd - 0x01010101)
83	not	%ecx			/ ~wrd
84	and	$0x80808080, %ecx	/ ~wrd & 0x80808080
85	and	%edx, %ecx		/ (wrd - 0x01010101) & ~wrd & 0x80808080
86	jz	countbytes		/ if zero, no null byte found -- cont
87
88has_zero_byte:
89	bsfl	%ecx, %ecx		/ find first set bit (null byte)
90	shr	$3, %ecx		/ switch bit position to byte posn
91	lea	-4(%eax, %ecx, 1), %eax	/ undo pre-increment and count bytes
92done:
93	sub	4(%esp), %eax		/ return (src - old_src)
94	ret
95	SET_SIZE(strlen)
96