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