Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | ! Copyright (C) 2013 Imagination Technologies Ltd. ! Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. #include <features.h> .text .global _strchr .type _strchr, function ! D1Ar1 src ! D0Ar2 c _strchr: AND D0Ar2,D0Ar2,#0xff ! Drop all but 8 bits of c MOV D1Ar5, D1Ar1 ! Copy src to D1Ar5 AND D1Ar5, D1Ar5, #7 ! Check 64 bit alignment CMP D1Ar5, #0 BZ $Laligned64bit ! Jump to 64 bit aligned strchr $Lalign64bit: GETB D0Re0, [D1Ar1++] ! Get the next character ADD D1Ar5, D1Ar5, #1 ! Increment alignment counter CMP D0Re0, D0Ar2 ! Is the char c BZ $Lcharatprevious ! If so exit returning position CMP D0Re0, #0 ! End of string? BZ $Lnotfound ! If so exit CMP D1Ar5, #8 ! Are we aligned 64bit yet? BNZ $Lalign64bit ! If not keep aligning $Laligned64bit: ! src is 64bit aligned MOV D0Ar4, D0Ar2 ! put c into D0Ar4 LSL D0Ar4, D0Ar4, #8 ! Shift it up ADD D0Ar4, D0Ar4, D0Ar2 ! another c LSL D0Ar4, D0Ar4, #8 ! shift ADD D0Ar4, D0Ar4, D0Ar2 ! another c LSL D0Ar4, D0Ar4, #8 ! shift ADD D0Ar4, D0Ar4, D0Ar2 ! 4 copies of c $Lcheck8bytes: GETL D0Re0, D1Re0, [D1Ar1++] ! grab 16 bytes MOV A0.3, D0Re0 ! save for later use ! first word ! check for \0 MOV D0Ar2, D0Re0 ! D0Ar2 is a scratch now ADDT D0Re0, D0Re0, #HI(0xfefefeff) ! Do 4 1-byte compares ADD D0Re0, D0Re0, #LO(0xfefefeff) XOR D0Ar2, D0Ar2, #-1 AND D0Re0, D0Re0, D0Ar2 ANDMT D0Re0, D0Re0, #HI(0x80808080) ANDMB D0Re0, D0Re0, #LO(0x80808080) CMP D0Re0, #0 BNZ $Lnullinword1 ! found \0 (or c if c==\0) ! Check for c MOV D0Re0, A0.3 ! restore the first word XOR D0Re0, D0Re0, D0Ar4 MOV D0Ar2, D0Re0 ! DO 4 1-byte compares ADDT D0Re0, D0Re0, #HI(0xfefefeff) ADD D0Re0, D0Re0, #LO(0xfefefeff) XOR D0Ar2, D0Ar2, #-1 AND D0Re0, D0Re0, D0Ar2 ANDMT D0Re0, D0Re0, #HI(0x80808080) ANDMB D0Re0, D0Re0, #LO(0x80808080) CMP D0Re0, #0 BNZ $Lcharinword1 ! found c ! second word ! check for \0 MOV A0.3, D1Re0 ! save for later use MOV D1Ar3, D1Re0 ADDT D1Re0, D1Re0, #HI(0xfefefeff) ! Do 4 1-byte compares ADD D1Re0, D1Re0, #LO(0xfefefeff) XOR D1Ar3, D1Ar3, #-1 AND D1Re0, D1Re0, D1Ar3 ANDMT D1Re0, D1Re0, #HI(0x80808080) ANDMB D1Re0, D1Re0, #LO(0x80808080) CMP D1Re0, #0 BNZ $Lnullinword2 ! Found \0 (or c if c==\0) MOV D0.4, A0.3 ! restore the second word XOR D1Re0, D0.4, D0Ar4 ! test c MOV D1Ar3, D1Re0 ADDT D1Re0, D1Re0, #HI(0xfefefeff) ! Do 4 1-byte compares ADD D1Re0, D1Re0, #LO(0xfefefeff) XOR D1Ar3, D1Ar3, #-1 AND D1Re0, D1Re0, D1Ar3 ANDMT D1Re0, D1Re0, #HI(0x80808080) ANDMB D1Re0, D1Re0, #LO(0x80808080) CMP D1Re0, #0 BNZ $Lcharinword2 ! found c B $Lcheck8bytes ! Keep checking $Lnullinword1: ! found \0 somewhere, check for c too SUB D1Ar1, D1Ar1, #4 $Lnullinword2: SUB D1Ar1, D1Ar1, #4 AND D0Ar2, D0Ar4, #0xff ! restore c MOV D0Re0, A0.3 ! restore the word MOV D0.4, D0Re0 ! for shifting later AND D0Re0, D0Re0, #0xff ! take first byte of word CMP D0Re0, D0Ar2 BZ $Lcharatcurrent ! found c CMP D0Re0, #0! BZ $Lnotfound ! found \0 ADD D1Ar1, D1Ar1, #1 LSR D0.4, D0.4, #8 MOV D0Re0, D0.4 AND D0Re0, D0Re0, #0xff ! take second byte of word CMP D0Re0, D0Ar2 BZ $Lcharatcurrent ! found c CMP D0Re0, #0 BZ $Lnotfound ! found \0 ADD D1Ar1, D1Ar1, #1 LSR D0.4, D0.4, #8 MOV D0Re0, D0.4 AND D0Re0, D0Re0, #0xff ! take third byte of word CMP D0Re0, D0Ar2 BZ $Lcharatcurrent ! found c CMP D0Re0, #0 BZ $Lnotfound ! found \0 ADD D1Ar1, D1Ar1, #1 ! move to 4th byte CMP D0Ar2, #0 ! If c was \0 BZ $Lcharatcurrent ! c has been found! $Lnotfound: MOV D0Re0, #0 ! End of string c not found B $Lend $Lcharinword1: ! found c in first word MOV D1Re0, D0Re0 SUB D1Ar1, D1Ar1, #4 $Lcharinword2: ! found c in second word SUB D1Ar1, D1Ar1, #4 AND D0Re0, D1Re0, #0xff ! First byte CMP D0Re0, #0 ! Test c (zero indicates c due ! to the 4 1-byte compare code) BNE $Lcharatcurrent ADD D1Ar1, D1Ar1, #1 LSR D1Re0, D1Re0, #8 AND D0Re0, D1Re0, #0xff ! Second byte CMP D0Re0, #0 ! Test c (indicated by zero) BNE $Lcharatcurrent ADD D1Ar1, D1Ar1, #1 LSR D1Re0, D1Re0, #8 AND D0Re0, D1Re0, #0xff ! Third byte CMP D0Re0, #0 ! Test c (indicated by zero) BNE $Lcharatcurrent ADD D1Ar1, D1Ar1, #1 ! Must be the fourth byte B $Lcharatcurrent $Lcharatprevious: SUB D1Ar1, D1Ar1, #1 ! Fix-up pointer $Lcharatcurrent: MOV D0Re0, D1Ar1 ! Return the string pointer $Lend: MOV PC, D1RtP .size _strchr,.-_strchr libc_hidden_def(strchr) #ifdef __UCLIBC_SUSV3_LEGACY__ strong_alias(strchr,index) #endif |