1 /* Optimized version of the standard memchr() function.
2 This file is part of the GNU C Library.
3 Copyright (C) 2000 Free Software Foundation, Inc.
4 Contributed by Dan Pop <Dan.Pop@cern.ch>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Return: the address of the first occurence of chr in str or NULL
28 This implementation assumes little endian mode. For big endian mode,
29 the instruction czx1.r should be replaced by czx1.l.
31 The algorithm is fairly straightforward: search byte by byte until we
32 we get to a word aligned address, then search word by word as much as
33 possible; the remaining few bytes are searched one at a time.
35 The word by word search is performed by xor-ing the word with a word
36 containing chr in every byte. If there is a hit, the result will
37 contain a zero byte in the corresponding position. The presence and
38 position of that zero byte is detected with a czx instruction.
40 All the loops in this function could have had the internal branch removed
41 if br.ctop and br.cloop could be predicated :-(. */
60 alloc saved_pfs = ar.pfs, 3, 0, 29, 32
62 .rotr value[MEMLAT+1], addr[MEMLAT+3], aux[2], poschr[2]
64 mov saved_lc = ar.lc // save the loop counter
65 mov saved_pr = pr // save the predicates
67 and tmp = 7, str // tmp = str % 8
68 cmp.ne p7, p0 = r0, r0 // clear p7
69 extr.u chr = in1, 0, 8 // chr = (unsigned char) in1
71 cmp.gtu p6, p0 = 16, in2 // use a simple loop for short
72 (p6) br.cond.spnt .srchfew ;; // searches
73 sub loopcnt = 8, tmp // loopcnt = 8 - tmp
74 cmp.eq p6, p0 = tmp, r0
75 (p6) br.cond.sptk .str_aligned;;
76 sub len = len, loopcnt
77 adds loopcnt = -1, loopcnt;;
82 cmp.eq p6, p0 = val, chr
83 (p6) br.cond.spnt .foundit
86 cmp.ne p6, p0 = r0, r0 // clear p6
87 shr.u loopcnt = len, 3 // loopcnt = len / 8
88 and len = 7, len ;; // remaining len = len & 7
89 adds loopcnt = -1, loopcnt
90 mov ar.ec = MEMLAT + 3
91 mux1 chrx8 = chr, @brcst ;; // get a word full of chr
93 mov pr.rot = 1 << 16 ;;
95 (p[0]) mov addr[0] = ret0
96 (p[0]) ld8 value[0] = [ret0], 8
97 (p[MEMLAT]) xor aux[0] = value[MEMLAT], chrx8
98 (p[MEMLAT+1]) czx1.r poschr[0] = aux[1]
99 (p[MEMLAT+2]) cmp.ne p7, p0 = 8, poschr[1]
100 (p7) br.cond.dpnt .foundit
103 adds loopcnt = -1, len
104 cmp.eq p6, p0 = len, r0
105 (p6) br.cond.spnt .notfound ;;
110 cmp.eq p6, p0 = val, chr
111 (p6) br.cond.dpnt .foundit
114 cmp.ne p6, p0 = r0, r0 // clear p6 (p7 was already 0 when we got here)
115 mov ret0 = r0 ;; // return NULL
117 (p6) adds ret0 = -1, ret0 // if we got here from l1 or l3
118 (p7) add ret0 = addr[MEMLAT+2], poschr[1] // if we got here from l2
119 mov pr = saved_pr, -1
120 mov ar.pfs = saved_pfs
126 weak_alias (__memchr, memchr)
127 #if !__BOUNDED_POINTERS__
128 weak_alias (__memchr, __ubp_memchr)