Update.
[platform/upstream/glibc.git] / sysdeps / powerpc / strchr.S
1 /* Optimized strchr implementation for PowerPC.
2    Copyright (C) 1997 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <sysdep.h>
21
22 /* See strlen.s for comments on how this works.  */
23
24 /* char * [r3] strchr (const char *s [r3] , int c [r4] )
25
26    r0:  a temporary
27    r3:  our return result.
28    r4:  byte we're looking for, spread over the whole word
29    r5:  the current word
30    r6:  the constant 0xfefefeff (-0x01010101)
31    r7:  the constant 0x7f7f7f7f
32    r8:  pointer to the current word.
33    r9:  a temporary
34    r10: the number of bits we should ignore in the first word
35    r11: a mask with the bits to ignore set to 0
36    r12: a temporary  */
37 ENTRY(strchr)
38         rlwimi %r4,%r4,8,16,23
39         li   %r11,-1
40         rlwimi %r4,%r4,16,0,15
41         lis  %r6,0xfeff
42         lis  %r7,0x7f7f
43         clrrwi %r8,%r3,2
44         addi %r7,%r7,0x7f7f
45         addi %r6,%r6,0xfffffeff
46         rlwinm %r10,%r3,3,27,28
47 /* Test the first (partial?) word.  */
48         lwz  %r5,0(%r8)
49         srw  %r11,%r11,%r10
50         orc  %r5,%r5,%r11
51         add  %r0,%r6,%r5
52         nor  %r9,%r7,%r5
53         and. %r0,%r0,%r9
54         xor  %r12,%r4,%r5
55         orc  %r12,%r12,%r11
56         b    L(loopentry)
57
58 /* The loop.  */
59
60 L(loop):lwzu %r5,4(%r8)
61         and. %r0,%r0,%r9
62 /* Test for 0.  */
63         add  %r0,%r6,%r5
64         nor  %r9,%r7,%r5
65         bne  L(foundit)
66         and. %r0,%r0,%r9
67 /* Start test for the bytes we're looking for.  */
68         xor  %r12,%r4,%r5
69 L(loopentry):
70         add  %r0,%r6,%r12
71         nor  %r9,%r7,%r12
72         beq  L(loop)
73 /* There is a zero byte in the word, but may also be a matching byte (either
74    before or after the zero byte).  In fact, we may be looking for a
75    zero byte, in which case we return a match.  We guess that this hasn't
76    happened, though.  */
77 L(missed):
78         and. %r0,%r0,%r9
79         li   %r3,0
80         beqlr
81 /* It did happen. Decide which one was first...
82    I'm not sure if this is actually faster than a sequence of
83    rotates, compares, and branches (we use it anyway because it's shorter).  */
84         and  %r6,%r7,%r5
85         or   %r11,%r7,%r5
86         and  %r0,%r7,%r12
87         or   %r10,%r7,%r12
88         add  %r6,%r6,%r7
89         add  %r0,%r0,%r7
90         nor  %r5,%r11,%r6
91         nor  %r9,%r10,%r0
92         cmplw %r5,%r9
93         bgtlr
94         cntlzw %r4,%r9
95         srwi %r4,%r4,3
96         add  %r3,%r8,%r4
97         blr
98
99 L(foundit):
100         and  %r0,%r7,%r12
101         or   %r10,%r7,%r12
102         add  %r0,%r0,%r7
103         nor  %r9,%r10,%r0
104         cntlzw %r4,%r9
105         subi %r8,%r8,4
106         srwi %r4,%r4,3
107         add  %r3,%r8,%r4
108         blr
109 END(strchr)
110
111 weak_alias(strchr,index)