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