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