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/* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29 .file "%M%" 30 31/* 32 * The strchr() function returns a pointer to the first occurrence of c 33 * (converted to a char) in string s, or a null pointer if c does not occur 34 * in the string. 35 */ 36 37#include <sys/asm_linkage.h> 38 39 ! Here, we start by checking to see if we're searching the dest 40 ! string for a null byte. We have fast code for this, so it's 41 ! an important special case. Otherwise, if the string is not 42 ! word aligned, we check a for the search char a byte at a time 43 ! until we've reached a word boundary. Once this has happened 44 ! some zero-byte finding values are initialized and the string 45 ! is checked a word at a time 46 47 ENTRY(strchr) 48 49 .align 32 50 51 andcc %o1, 0xff, %o1 ! search only for this one byte 52 bz,pn %ncc, .searchnullbyte ! faster code for searching null 53 andcc %o0, 3, %o4 ! str word aligned ? 54 bz,a,pn %ncc, .prepword2 ! yup, prepare for word-wise search 55 sll %o1, 8, %g1 ! start spreading findchar across word 56 57 ldub [%o0], %o2 ! str[0] 58 cmp %o2, %o1 ! str[0] == findchar ? 59 be,pn %ncc, .done ! yup, done 60 tst %o2 ! str[0] == 0 ? 61 bz,pn %ncc, .notfound ! yup, return null pointer 62 cmp %o4, 3 ! only one byte needed to align? 63 bz,pn %ncc, .prepword ! yup, prepare for word-wise search 64 inc %o0 ! str++ 65 ldub [%o0], %o2 ! str[1] 66 cmp %o2, %o1 ! str[1] == findchar ? 67 be,pn %ncc, .done ! yup, done 68 tst %o2 ! str[1] == 0 ? 69 bz,pn %ncc, .notfound ! yup, return null pointer 70 cmp %o4, 2 ! only two bytes needed to align? 71 bz,pn %ncc, .prepword ! yup, prepare for word-wise search 72 inc %o0 ! str++ 73 ldub [%o0], %o2 ! str[2] 74 cmp %o2, %o1 ! str[2] == findchar ? 75 be,pn %ncc, .done ! yup, done 76 tst %o2 ! str[2] == 0 ? 77 bz,pn %ncc, .notfound ! yup, return null pointer 78 inc %o0 ! str++ 79 80.prepword: 81 sll %o1, 8, %g1 ! spread findchar ------+ 82.prepword2: ! 83 sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1 ! 84 or %o1, %g1, %o1 ! across all <---------+ 85 sethi %hi(0x80808080), %o5 ! Alan Mycroft's magic2 ! 86 sll %o1, 16, %g1 ! four bytes <--------+ 87 or %o4, %lo(0x01010101), %o4 ! 88 or %o1, %g1, %o1 ! of a word <--------+ 89 or %o5, %lo(0x80808080), %o5 90 91.searchchar: 92 lduw [%o0], %o2 ! src word 93 andn %o5, %o2, %o3 ! ~word & 0x80808080 94 sub %o2, %o4, %g1 ! word = (word - 0x01010101) 95 andcc %o3, %g1, %g0 ! ((word - 0x01010101) & ~word & 0x80808080) 96 bnz,pn %ncc, .haszerobyte ! zero byte if magic expression != 0 97 xor %o2, %o1, %g1 ! tword = word ^ findchar 98 andn %o5, %g1, %o3 ! ~tword & 0x80808080 99 sub %g1, %o4, %o2 ! (tword - 0x01010101) 100 andcc %o3, %o2, %g0 ! ((tword - 0x01010101) & ~tword & 0x80808080) 101 bz,a,pt %ncc, .searchchar ! no findchar if magic expression == 0 102 add %o0, 4, %o0 ! str += 4 103 104 ! here we know "word" contains the searched character, but no null 105 ! byte. if there was a null byte, we would have gone to .haszerobyte 106 ! "tword" has null bytes where "word" had findchar. Examine "tword" 107 108.foundchar: 109 set 0xff000000, %o4 ! mask for 1st byte 110 andcc %g1, %o4, %g0 ! first byte zero (= found search char) ? 111 bz,pn %ncc, .done ! yup, done 112 set 0x00ff0000, %o5 ! mask for 2nd byte 113 inc %o0 ! str++ 114 andcc %g1, %o5, %g0 ! second byte zero (= found search char) ? 115 bz,pn %ncc, .done ! yup, done 116 srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte 117 inc %o0 ! str++ 118 andcc %g1, %o4, %g0 ! third byte zero (= found search char) ? 119 bnz,a %ncc, .done ! nope, increment in delay slot 120 inc %o0 ! str++ 121 122.done: 123 retl ! done with leaf function 124 nop ! padding 125 126 ! Here we know that "word" contains a null byte indicating the 127 ! end of the string. However, "word" might also contain findchar 128 ! "tword" (in %g1) has null bytes where "word" had findchar. So 129 ! check both "tword" and "word" 130 131.haszerobyte: 132 set 0xff000000, %o4 ! mask for 1st byte 133 andcc %g1, %o4, %g0 ! first byte == findchar ? 134 bz,pn %ncc, .done ! yup, done 135 andcc %o2, %o4, %g0 ! first byte == 0 ? 136 bz,pn %ncc, .notfound ! yup, return null pointer 137 set 0x00ff0000, %o4 ! mask for 2nd byte 138 inc %o0 ! str++ 139 andcc %g1, %o4, %g0 ! second byte == findchar ? 140 bz,pn %ncc, .done ! yup, done 141 andcc %o2, %o4, %g0 ! second byte == 0 ? 142 bz,pn %ncc, .notfound ! yup, return null pointer 143 srl %o4, 8, %o4 ! mask for 3rd byte = 0x0000ff00 144 inc %o0 ! str++ 145 andcc %g1, %o4, %g0 ! third byte == findchar ? 146 bz,pn %ncc, .done ! yup, done 147 andcc %o2, %o4, %g0 ! third byte == 0 ? 148 bz,pn %ncc, .notfound ! yup, return null pointer 149 andcc %g1, 0xff, %g0 ! fourth byte == findchar ? 150 bz,pn %ncc, .done ! yup, done 151 inc %o0 ! str++ 152 153.notfound: 154 retl ! done with leaf function 155 xor %o0, %o0, %o0 ! return null pointer 156 157 ! since findchar == 0, we only have to do one test per item 158 ! instead of two. This makes the search much faster. 159 160.searchnullbyte: 161 bz,pn %ncc, .straligned ! str is word aligned 162 nop ! padding 163 164 cmp %o4, 2 ! str halfword aligned ? 165 be,pn %ncc, .s2aligned ! yup 166 ldub [%o0], %o1 ! str[0] 167 tst %o1 ! byte zero? 168 bz,pn %ncc, .done ! yup, done 169 cmp %o4, 3 ! only one byte needed to align? 170 bz,pn %ncc, .straligned ! yup 171 inc %o0 ! str++ 172 173 ! check to see if we're half word aligned, which it better than 174 ! not being aligned at all. Search the first half of the word 175 ! if we are, and then search by whole word. 176 177.s2aligned: 178 lduh [%o0], %o1 ! str[] 179 srl %o1, 8, %o4 ! %o4<7:0> = first byte 180 tst %o4 ! first byte zero ? 181 bz,pn %ncc, .done2 ! yup, done 182 andcc %o1, 0xff, %g0 ! second byte zero ? 183 bz,a,pn %ncc, .done2 ! yup, done 184 inc %o0 ! str++ 185 add %o0, 2, %o0 ! str+=2 186 187.straligned: 188 sethi %hi(0x01010101), %o4 ! Alan Mycroft's magic1 189 sethi %hi(0x80808080), %o5 ! Alan Mycroft's magic2 190 or %o4, %lo(0x01010101), %o4 191 or %o5, %lo(0x80808080), %o5 192 193.searchword: 194 lduw [%o0], %o1 ! src word 195 andn %o5, %o1, %o3 ! ~word & 0x80808080 196 sub %o1, %o4, %g1 ! word = (word - 0x01010101) 197 andcc %o3, %g1, %g0 ! ((word - 0x01010101) & ~word & 0x80808080) 198 bz,a,pt %ncc, .searchword ! no zero byte if magic expression == 0 199 add %o0, 4, %o0 ! str += 4 200 201.zerobyte: 202 set 0xff000000, %o4 ! mask for 1st byte 203 andcc %o1, %o4, %g0 ! first byte zero? 204 bz,pn %ncc, .done2 ! yup, done 205 set 0x00ff0000, %o5 ! mask for 2nd byte 206 inc %o0 ! str++ 207 andcc %o1, %o5, %g0 ! second byte zero? 208 bz,pn %ncc, .done2 ! yup, done 209 srl %o4, 16, %o4 ! 0x0000ff00 = mask for 3rd byte 210 inc %o0 ! str++ 211 andcc %o1, %o4, %g0 ! third byte zero? 212 bnz,a %ncc, .done2 ! nope, increment in delay slot 213 inc %o0 ! str++ 214.done2: 215 retl ! return from leaf function 216 nop ! padding 217 218 SET_SIZE(strchr) 219