2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A .file "strchr.s"
2N/A
2N/A#include "SYS.h"
2N/A
2N/A ENTRY(strchr)
2N/A mov 4(%esp), %ecx / src string here
2N/A mov 8(%esp), %edx / character to find
2N/A mov %ecx, %eax / save src
2N/A and $3, %ecx / check if src is aligned
2N/A jz prepword / search wordwise if it is
2N/A
2N/A cmpb %dl, (%eax) / src == char?
2N/A jz done
2N/A cmpb $0, (%eax) / src == 0?
2N/A jz not_found
2N/A add $1, %eax / increment src
2N/A cmp $3, %ecx / check alignment
2N/A jz prepword
2N/A cmpb %dl, (%eax) / src byte contains char?
2N/A jz done
2N/A cmpb $0, (%eax) / src byte == 0?
2N/A jz not_found
2N/A add $1, %eax / increment src ptr
2N/A cmp $2, %ecx / check alignment
2N/A jz prepword
2N/A cmpb %dl, (%eax) / check this byte
2N/A jz done
2N/A cmpb $0, (%eax) / is byte zero?
2N/A jz not_found
2N/A add $1, %eax / increment src ptr
2N/A
2N/Aprepword:
2N/A push %ebx / save regs per calling convention
2N/A push %esi
2N/A and $0xff, %edx / only want 1st byte
2N/A mov %edx, %ebx / copy character across all bytes in wd
2N/A shl $8, %edx
2N/A or %ebx, %edx
2N/A mov %edx, %ebx
2N/A shl $16, %edx
2N/A or %ebx, %edx
2N/A
2N/A .align 16 / align loop for max performance
2N/A
2N/Asearchchar:
2N/A mov (%eax), %esi / load src word
2N/A add $4, %eax / increment src by four
2N/A mov %esi, %ebx / copy word
2N/A lea -0x01010101(%esi), %ecx / (word - 0x01010101)
2N/A xor %edx, %ebx / tmpword = word ^ char
2N/A not %esi / ~word
2N/A and $0x80808080, %esi / ~word & 0x80808080
2N/A and %ecx, %esi / (wd - 0x01010101) & ~wd & 0x80808080
2N/A jnz has_zero_byte
2N/A lea -0x01010101(%ebx), %ecx / repeat with tmpword
2N/A not %ebx
2N/A and $0x80808080, %ebx
2N/A and %ecx, %ebx
2N/A jz searchchar / repeat if char not found
2N/A
2N/Afound_char:
2N/A add $0x01010101, %ecx / restore tmpword
2N/A pop %esi / restore esi ebx as per calling cvntn
2N/A pop %ebx
2N/A test $0x000000ff, %ecx / look for character's position in word
2N/A jz done0
2N/A test $0x0000ff00, %ecx
2N/A jz done1
2N/A test $0x00ff0000, %ecx
2N/A jz done2
2N/Adone3:
2N/A sub $1, %eax
2N/A ret
2N/Adone2:
2N/A sub $2, %eax
2N/A ret
2N/Adone1:
2N/A sub $3, %eax
2N/A ret
2N/Adone0:
2N/A sub $4, %eax
2N/A ret
2N/Ahas_zero_byte:
2N/A add $0x01010101, %ecx / restore registers here
2N/A pop %esi
2N/A pop %ebx
2N/A cmpb %dl, %cl / check for character
2N/A je done0
2N/A testb %cl, %cl / check for null byte
2N/A jz not_found
2N/A cmpb %dh, %ch / continue checking for char, null
2N/A je done1
2N/A testb %ch, %ch
2N/A jz not_found
2N/A shr $16, %ecx / put bytes 2,3 into 8-but registers
2N/A cmpb %dl, %cl
2N/A je done2
2N/A testb %cl, %cl
2N/A jz not_found
2N/A cmpb %dh, %ch / repeat checking last 2 bytes
2N/A je done3
2N/A testb %ch, %ch
2N/A jz not_found
2N/A sub $1, %eax / correct for last loop iteration
2N/Adone:
2N/A ret
2N/Anot_found:
2N/A xor %eax, %eax
2N/A ret
2N/A SET_SIZE(strchr)