]>
Commit | Line | Data |
---|---|---|
9a0a462c | 1 | /* Optimized strchr implementation for PowerPC. |
1d280d9f | 2 | Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. |
9a0a462c UD |
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 | |
41bdb6e2 AJ |
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. | |
9a0a462c UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
9a0a462c | 14 | |
41bdb6e2 AJ |
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 | |
18 | 02111-1307 USA. */ | |
9a0a462c UD |
19 | |
20 | #include <sysdep.h> | |
b1fc7a6a GM |
21 | #include <bp-sym.h> |
22 | #include <bp-asm.h> | |
9a0a462c UD |
23 | |
24 | /* See strlen.s for comments on how this works. */ | |
25 | ||
1d280d9f | 26 | /* char * [r3] strchr (const char *s [r3] , int c [r4] ) */ |
9a0a462c | 27 | |
b1fc7a6a | 28 | ENTRY (BP_SYM (strchr)) |
1d280d9f GM |
29 | |
30 | #define rTMP1 r0 | |
31 | #define rRTN r3 /* outgoing result */ | |
b1fc7a6a GM |
32 | #if __BOUNDED_POINTERS__ |
33 | # define rSTR r4 | |
34 | # define rCHR r5 /* byte we're looking for, spread over the whole word */ | |
35 | # define rWORD r8 /* the current word */ | |
36 | #else | |
dfef32ef | 37 | # define rSTR r8 /* current word pointer */ |
b1fc7a6a GM |
38 | # define rCHR r4 /* byte we're looking for, spread over the whole word */ |
39 | # define rWORD r5 /* the current word */ | |
40 | #endif | |
1d280d9f | 41 | #define rCLZB rCHR /* leading zero byte count */ |
1d280d9f GM |
42 | #define rFEFE r6 /* constant 0xfefefeff (-0x01010101) */ |
43 | #define r7F7F r7 /* constant 0x7f7f7f7f */ | |
1d280d9f GM |
44 | #define rTMP2 r9 |
45 | #define rIGN r10 /* number of bits we should ignore in the first word */ | |
46 | #define rMASK r11 /* mask with the bits to ignore set to 0 */ | |
47 | #define rTMP3 r12 | |
48 | ||
b1fc7a6a GM |
49 | CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2) |
50 | STORE_RETURN_BOUNDS (rTMP1, rTMP2) | |
51 | ||
1d280d9f GM |
52 | rlwimi rCHR, rCHR, 8, 16, 23 |
53 | li rMASK, -1 | |
54 | rlwimi rCHR, rCHR, 16, 0, 15 | |
dfef32ef | 55 | rlwinm rIGN, rRTN, 3, 27, 28 |
1d280d9f GM |
56 | lis rFEFE, -0x101 |
57 | lis r7F7F, 0x7f7f | |
dfef32ef | 58 | clrrwi rSTR, rRTN, 2 |
1d280d9f | 59 | addi rFEFE, rFEFE, -0x101 |
b1fc7a6a | 60 | addi r7F7F, r7F7F, 0x7f7f |
9a0a462c | 61 | /* Test the first (partial?) word. */ |
1d280d9f GM |
62 | lwz rWORD, 0(rSTR) |
63 | srw rMASK, rMASK, rIGN | |
64 | orc rWORD, rWORD, rMASK | |
65 | add rTMP1, rFEFE, rWORD | |
66 | nor rTMP2, r7F7F, rWORD | |
67 | and. rTMP1, rTMP1, rTMP2 | |
68 | xor rTMP3, rCHR, rWORD | |
69 | orc rTMP3, rTMP3, rMASK | |
70 | b L(loopentry) | |
9a0a462c UD |
71 | |
72 | /* The loop. */ | |
73 | ||
1d280d9f GM |
74 | L(loop):lwzu rWORD, 4(rSTR) |
75 | and. rTMP1, rTMP1, rTMP2 | |
76 | /* Test for 0. */ | |
77 | add rTMP1, rFEFE, rWORD | |
78 | nor rTMP2, r7F7F, rWORD | |
79 | bne L(foundit) | |
80 | and. rTMP1, rTMP1, rTMP2 | |
9a0a462c | 81 | /* Start test for the bytes we're looking for. */ |
1d280d9f | 82 | xor rTMP3, rCHR, rWORD |
9a0a462c | 83 | L(loopentry): |
1d280d9f GM |
84 | add rTMP1, rFEFE, rTMP3 |
85 | nor rTMP2, r7F7F, rTMP3 | |
86 | beq L(loop) | |
9a0a462c UD |
87 | /* There is a zero byte in the word, but may also be a matching byte (either |
88 | before or after the zero byte). In fact, we may be looking for a | |
89 | zero byte, in which case we return a match. We guess that this hasn't | |
90 | happened, though. */ | |
91 | L(missed): | |
1d280d9f | 92 | and. rTMP1, rTMP1, rTMP2 |
dfef32ef | 93 | li rRTN, 0 |
b1fc7a6a | 94 | STORE_RETURN_VALUE (rSTR) |
9a0a462c UD |
95 | beqlr |
96 | /* It did happen. Decide which one was first... | |
97 | I'm not sure if this is actually faster than a sequence of | |
98 | rotates, compares, and branches (we use it anyway because it's shorter). */ | |
1d280d9f GM |
99 | and rFEFE, r7F7F, rWORD |
100 | or rMASK, r7F7F, rWORD | |
101 | and rTMP1, r7F7F, rTMP3 | |
102 | or rIGN, r7F7F, rTMP3 | |
103 | add rFEFE, rFEFE, r7F7F | |
104 | add rTMP1, rTMP1, r7F7F | |
105 | nor rWORD, rMASK, rFEFE | |
106 | nor rTMP2, rIGN, rTMP1 | |
107 | cmplw rWORD, rTMP2 | |
9a0a462c | 108 | bgtlr |
1d280d9f GM |
109 | cntlzw rCLZB, rTMP2 |
110 | srwi rCLZB, rCLZB, 3 | |
dfef32ef | 111 | add rRTN, rSTR, rCLZB |
b1fc7a6a GM |
112 | CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge) |
113 | STORE_RETURN_VALUE (rSTR) | |
9a0a462c UD |
114 | blr |
115 | ||
116 | L(foundit): | |
1d280d9f GM |
117 | and rTMP1, r7F7F, rTMP3 |
118 | or rIGN, r7F7F, rTMP3 | |
119 | add rTMP1, rTMP1, r7F7F | |
120 | nor rTMP2, rIGN, rTMP1 | |
121 | cntlzw rCLZB, rTMP2 | |
122 | subi rSTR, rSTR, 4 | |
123 | srwi rCLZB, rCLZB, 3 | |
dfef32ef | 124 | add rRTN, rSTR, rCLZB |
b1fc7a6a GM |
125 | CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge) |
126 | STORE_RETURN_VALUE (rSTR) | |
9a0a462c | 127 | blr |
b1fc7a6a | 128 | END (BP_SYM (strchr)) |
9a0a462c | 129 | |
b1fc7a6a | 130 | weak_alias (BP_SYM (strchr), BP_SYM (index)) |