/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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. */ .ident "%Z%%M% %I% %E% SMI" .file "%M%" #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)