1 /* Optimized strchr implementation for PowerPC64.
2 Copyright (C) 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 /* See strlen.s for comments on how this works. */
26 /* char * [r3] strchr (const char *s [r3] , int c [r4] ) */
28 ENTRY (BP_SYM (strchr))
32 #define rRTN r3 /* outgoing result */
33 /* Note: The Bounded pointer support in this code is broken. This code
34 was inherited from PPC32 and and that support was never completed.
35 Currently PPC gcc does not support -fbounds-check or -fbounded-pointers.
36 These artifacts are left in the code as a reminder in case we need
37 bounded pointer support in the future. */
38 #if __BOUNDED_POINTERS__
40 # define rCHR r5 /* byte we're looking for, spread over the whole word */
41 # define rWORD r8 /* the current word */
43 # define rSTR r8 /* current word pointer */
44 # define rCHR r4 /* byte we're looking for, spread over the whole word */
45 # define rWORD r5 /* the current word */
47 #define rCLZB rCHR /* leading zero byte count */
48 #define rFEFE r6 /* constant 0xfefefefefefefeff (-0x0101010101010101) */
49 #define r7F7F r7 /* constant 0x7f7f7f7f7f7f7f7f */
51 #define rIGN r10 /* number of bits we should ignore in the first word */
52 #define rMASK r11 /* mask with the bits to ignore set to 0 */
55 CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2)
56 STORE_RETURN_BOUNDS (rTMP1, rTMP2)
59 rlwimi rCHR, rCHR, 8, 16, 23
61 rlwimi rCHR, rCHR, 16, 0, 15
62 rlwinm rIGN, rRTN, 3, 26, 28
63 insrdi rCHR, rCHR, 32, 0
67 addi rFEFE, rFEFE, -0x101
68 addi r7F7F, r7F7F, 0x7f7f
70 insrdi r7F7F, r7F7F, 32, 0
71 add rFEFE, rFEFE, rTMP1
72 /* Test the first (partial?) word. */
74 srd rMASK, rMASK, rIGN
75 orc rWORD, rWORD, rMASK
76 add rTMP1, rFEFE, rWORD
77 nor rTMP2, r7F7F, rWORD
78 and. rTMP1, rTMP1, rTMP2
79 xor rTMP3, rCHR, rWORD
80 orc rTMP3, rTMP3, rMASK
85 L(loop):ldu rWORD, 8(rSTR)
86 and. rTMP1, rTMP1, rTMP2
88 add rTMP1, rFEFE, rWORD
89 nor rTMP2, r7F7F, rWORD
91 and. rTMP1, rTMP1, rTMP2
92 /* Start test for the bytes we're looking for. */
93 xor rTMP3, rCHR, rWORD
95 add rTMP1, rFEFE, rTMP3
96 nor rTMP2, r7F7F, rTMP3
98 /* There is a zero byte in the word, but may also be a matching byte (either
99 before or after the zero byte). In fact, we may be looking for a
100 zero byte, in which case we return a match. We guess that this hasn't
103 and. rTMP1, rTMP1, rTMP2
105 STORE_RETURN_VALUE (rSTR)
107 /* It did happen. Decide which one was first...
108 I'm not sure if this is actually faster than a sequence of
109 rotates, compares, and branches (we use it anyway because it's shorter). */
110 and rFEFE, r7F7F, rWORD
111 or rMASK, r7F7F, rWORD
112 and rTMP1, r7F7F, rTMP3
113 or rIGN, r7F7F, rTMP3
114 add rFEFE, rFEFE, r7F7F
115 add rTMP1, rTMP1, r7F7F
116 nor rWORD, rMASK, rFEFE
117 nor rTMP2, rIGN, rTMP1
122 add rRTN, rSTR, rCLZB
123 CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge)
124 STORE_RETURN_VALUE (rSTR)
128 and rTMP1, r7F7F, rTMP3
129 or rIGN, r7F7F, rTMP3
130 add rTMP1, rTMP1, r7F7F
131 nor rTMP2, rIGN, rTMP1
135 add rRTN, rSTR, rCLZB
136 CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge)
137 STORE_RETURN_VALUE (rSTR)
139 END (BP_SYM (strchr))
141 weak_alias (BP_SYM (strchr), BP_SYM (index))
142 libc_hidden_builtin_def (strchr)