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 * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * The strchr() function returns a pointer to the first occurrence of c 2N/A * (converted to a char) in string s, or a null pointer if c does not occur 2N/A ! string for a null byte. We have fast code for this, so it's
2N/A !
until we've reached a word boundary. Once this has happened 2N/A ! some zero-byte finding values are initialized and the string 2N/A ! is checked a word at a time 2N/A andcc %o1, 0xff, %o1 ! search only for this one byte 2N/A bz .searchnullbyte ! faster code for searching null 2N/A andcc %o0, 3, %o4 ! str word aligned ? 2N/A bz,a .prepword2 ! yup, prepare for word-wise search 2N/A sll %o1, 8, %g1 ! start spreading findchar across word 2N/A ldub [%o0], %o2 ! str[0] 2N/A cmp %o2, %o1 ! str[0] == findchar ? 2N/A be .done ! yup, done 2N/A tst %o2 ! str[0] == 0 ? 2N/A bz .notfound ! yup, return null pointer 2N/A cmp %o4, 3 ! only one byte needed to align? 2N/A bz .prepword ! yup, prepare for word-wise search 2N/A ldub [%o0], %o2 ! str[1] 2N/A cmp %o2, %o1 ! str[1] == findchar ? 2N/A be .done ! yup, done 2N/A tst %o2 ! str[1] == 0 ? 2N/A bz .notfound ! yup, return null pointer 2N/A cmp %o4, 2 ! only two bytes needed to align? 2N/A bz .prepword ! yup, prepare for word-wise search 2N/A ldub [%o0], %o2 ! str[2] 2N/A cmp %o2, %o1 ! str[2] == findchar ? 2N/A be .done ! yup, done 2N/A tst %o2 ! str[2] == 0 ? 2N/A bz .notfound ! yup, return null pointer 2N/A sll %o1, 8, %g1 ! spread findchar ------+ 2N/A sethi %hi(0x01010101), %o4 ! Alan Mycroft's
magic1 !
2N/A sll %o1, 16, %g1 ! four bytes <--------+ 2N/A or %o4, %lo(0x01010101), %o4 ! 2N/A or %o1, %g1, %o1 ! of a word <--------+ 2N/A or %o5, %lo(0x80808080), %o5 2N/A lduw [%o0], %o2 ! src word 2N/A andn %o5, %o2, %o3 ! ~word & 0x80808080 2N/A sub %o2, %o4, %g1 ! word = (word - 0x01010101) 2N/A andcc %o3, %g1, %g0 ! ((word - 0x01010101) & ~word & 0x80808080) 2N/A bnz .haszerobyte ! zero byte if magic expression != 0 2N/A xor %o2, %o1, %g1 ! tword = word ^ findchar 2N/A andn %o5, %g1, %o3 ! ~tword & 0x80808080 2N/A sub %g1, %o4, %o2 ! (tword - 0x01010101) 2N/A andcc %o3, %o2, %g0 ! ((tword - 0x01010101) & ~tword & 0x80808080) 2N/A bz,a .searchchar ! no findchar if magic expression == 0 2N/A add %o0, 4, %o0 ! str += 4 2N/A ! here we know "word" contains the searched character, but no null 2N/A ! byte. if there was a null byte, we would have gone to .haszerobyte 2N/A ! "tword" has null bytes where "word" had findchar. Examine "tword" 2N/A set 0xff000000, %o4 ! mask for 1st byte 2N/A andcc %g1, %o4, %g0 ! first byte zero (= found search char) ? 2N/A bz .done ! yup, done 2N/A set 0x00ff0000, %o5 ! mask for 2nd byte 2N/A andcc %g1, %o5, %g0 ! second byte zero (= found search char) ? 2N/A bz .done ! yup, done 2N/A srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte 2N/A andcc %g1, %o4, %g0 ! third byte zero (= found search char) ? 2N/A bnz,a .done ! nope, increment in delay slot 2N/A retl ! done with leaf function 2N/A ! Here we know that "word" contains a null byte indicating the 2N/A ! end of the string. However, "word" might also contain findchar 2N/A ! "tword" (in %g1) has null bytes where "word" had findchar. So 2N/A ! check both "tword" and "word" 2N/A set 0xff000000, %o4 ! mask for 1st byte 2N/A andcc %g1, %o4, %g0 ! first byte == findchar ? 2N/A bz .done ! yup, done 2N/A andcc %o2, %o4, %g0 ! first byte == 0 ? 2N/A bz .notfound ! yup, return null pointer 2N/A set 0x00ff0000, %o4 ! mask for 2nd byte 2N/A andcc %g1, %o4, %g0 ! second byte == findchar ? 2N/A bz .done ! yup, done 2N/A andcc %o2, %o4, %g0 ! second byte == 0 ? 2N/A bz .notfound ! yup, return null pointer 2N/A srl %o4, 8, %o4 ! mask for 3rd byte = 0x0000ff00 2N/A andcc %g1, %o4, %g0 ! third byte == findchar ? 2N/A bz .done ! yup, done 2N/A andcc %o2, %o4, %g0 ! third byte == 0 ? 2N/A bz .notfound ! yup, return null pointer 2N/A andcc %g1, 0xff, %g0 ! fourth byte == findchar ? 2N/A bz .done ! yup, done 2N/A retl ! done with leaf function 2N/A xor %o0, %o0, %o0 ! return null pointer 2N/A ! since findchar == 0, we only have to do one test per item 2N/A ! instead of two. This makes the search much faster. 2N/A bz .straligned ! str is word aligned 2N/A cmp %o4, 2 ! str halfword aligned ? 2N/A ldub [%o0], %o1 ! str[0] 2N/A tst %o1 ! byte zero? 2N/A bz .done2 ! yup, done 2N/A cmp %o4, 3 ! only one byte needed to align? 2N/A bz .straligned ! yup 2N/A sethi %hi(0x80808080), %o5 ! Alan Mycroft's
magic2