1/* 2 Copyright (c) 2015, Synopsys, Inc. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 7 1) Redistributions of source code must retain the above copyright notice, 8 this list of conditions and the following disclaimer. 9 10 2) Redistributions in binary form must reproduce the above copyright notice, 11 this list of conditions and the following disclaimer in the documentation 12 and/or other materials provided with the distribution. 13 14 3) Neither the name of the Synopsys, Inc., nor the names of its contributors 15 may be used to endorse or promote products derived from this software 16 without specific prior written permission. 17 18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 POSSIBILITY OF SUCH DAMAGE. 29*/ 30 31/* This implementation is optimized for performance. For code size a generic 32 implementation of this function from newlib/libc/string/strchr.c will be 33 used. */ 34#if !defined (__OPTIMIZE_SIZE__) && !defined (PREFER_SIZE_OVER_SPEED) 35 36#include "asm.h" 37 38/* In order to search for a zero in a W, we calculate 39 X := (W - 0x01010101) & ~W & 0x80808080; 40 In the little endian case: 41 If no byte in W is zero, X will be zero; otherwise, the least significant 42 byte of X which is nonzero indicates the least significant byte of W that 43 is zero. 44 In the big endian case: 45 X will be zero iff no byte in W is zero. 46 If X is nonzero, to find out which is the most significant zero byte 47 in W, we calculate: 48 Y := ~(((W | 0x80808080) - 0x01010101) | W) & 0x80808080; 49 Each byte in Y is 0x80 if the the corresponding byte in 50 W is zero, otherwise that byte of Y is 0. */ 51 52#if defined (__ARC_BARREL_SHIFTER__) && \ 53 (defined (__ARC600__) || (!defined (__ARC_NORM__) && !defined (__ARC601__))) 54 55ENTRY (strchr) 56 bmsk.f r2,r0,1 57 mov_s r3,0x01010101 58 extb_s r1,r1 59 asl r5,r1,8 60 or r5,r5,r1 61 beq.d .Laligned 62 asl r4,r5,16 63 sub_s r0,r0,r2 64 asl_s r2,r2,3 65#ifdef __LITTLE_ENDIAN__ 66 asl r7,r3,r2 67#else 68 lsr r7,r3,r2 69#endif 70 ld_s r2,[r0] 71 or r5,r5,r4 72 ror r4,r3 73 sub r12,r2,r7 74 bic_s r12,r12,r2 75 and r12,r12,r4 76 77 brne.d r12,0,.Lfound0_ua 78 xor r6,r2,r5 79 ld.a r2,[r0,4] 80 sub r12,r6,r7 81 bic r12,r12,r6 82#ifdef __LITTLE_ENDIAN__ 83 and.f r7,r12,r4 84 sub r12,r2,r3 85 bic_s r12,r12,r2 86 beq.d .Loop 87 and r12,r12,r4 88 b.d .Lfound_char_ua 89 btst r7,7 90#else 91 and.f r8,r12,r4 92 sub r12,r2,r3 93 bic_s r12,r12,r2 94 beq.d .Loop 95 and r12,r12,r4 96 bic r12,r7,r6 97 asl_s r12,r12,7 98 and.f r2,r8,r12 99 b.d .Lfound_char_ua 100 sub_s r0,r0,4 101#endif 102 103 .balign 4 104.Laligned: 105 ld_s r2,[r0] 106 or r5,r5,r4 107 ror r4,r3 108 sub r12,r2,r3 109 bic_s r12,r12,r2 110 and r12,r12,r4 111.Loop: 112 113 brne.d r12,0,.Lfound0 114 xor r6,r2,r5 115 ld.a r2,[r0,4] 116 sub r12,r6,r3 117 bic r12,r12,r6 118 and.f r7,r12,r4 119 sub r12,r2,r3 120 bic_s r12,r12,r2 121 beq.d .Loop 122 and r12,r12,r4 123; Found searched-for character. r0 has already advanced to next word. 124#ifdef __LITTLE_ENDIAN__ 125/* We only need the information about the first matching byte 126 (i.e. the least significant matching byte) to be exact, 127 hence there is no problem with carry effects. */ 128.Lfound_char: 129 btst r7,7 130.Lfound_char_ua: 131 sub_s r0,r0,4 132 add.eq r0,r0,1 133 btst.eq r7,15 134 add.eq r0,r0,1 135 btst.eq r7,23 136 j_s.d [blink] 137 add.eq r0,r0,1 138 139 .balign 4 140.Lfound0_ua: 141 mov_l r3,r7 142.Lfound0: 143 sub r2,r6,r3 144 bic r2,r2,r6 145 and r2,r2,r4 146 or r3,r12,r2 147 sub_s r12,r3,1 148 xor_s r3,r3,r12 149 tst_s r2,r3 150 lsr r2,r3,31 151 lsr r12,r3,16 152 jeq.d [blink] 153 mov.eq r0,0 154 lsr r3,r3,8 155 sub_s r2,r2,r12 156 sub_s r2,r2,r3 157 bmsk_s r2,r2,1 158 j_s.d [blink] 159 add_s r0,r0,r2 160#else /* BIG ENDIAN */ 161.Lfound_char: 162 asl r6,r6,7 163 sub_s r0,r0,4 164 bic.f r2,r7,r6 165.Lfound_char_ua: 166 add.pl r0,r0,1 167 jmi.d [blink] 168 btst_s r2,23 169 add.eq r0,r0,1 170 btst.eq r2,15 171 j_s.d [blink] 172 add.eq r0,r0,1 173 174; N.B. if we searched for a char zero and found it in the MSB, 175; and ignored matches are identical, we will take the early exit 176; like for an ordinary found zero - except for the extra stalls at jhi - 177; but still compute the right result. 178.Lfound0_ua: 179 mov_s r3,r7 180.Lfound0: 181 asl_s r2,r2,7 182 or r7,r6,r4 183 bic_s r12,r12,r2 184 sub r2,r7,r3 185 or r2,r2,r6 186 bic r2,r4,r2 187 cmp r12,r2 188 mov.hi r0,0 189 btst.ls r2,31 190 jhi.d [blink] 191 add.eq r0,r0,1 192 btst.eq r2,23 193 add.eq r0,r0,1 194 btst.eq r2,15 195 j_s.d [blink] 196 add.eq r0,r0,1 197#endif /* ENDIAN */ 198ENDFUNC (strchr) 199#endif /* __ARC_BARREL_SHIFTER__ && 200 (__ARC600__ || (!__ARC_NORM__ && !__ARC601__)) */ 201 202#endif /* !__OPTIMIZE_SIZE__ && !PREFER_SIZE_OVER_SPEED */ 203