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 .text 6 .global _memchr 7 .type _memchr,function 8! D0Ar6 src 9! D0Ar2 c 10! D1Ar3 n 11_memchr: 12 CMP D1Ar3, #0 13 BEQ $Lexit_fail 14 !! convert c to unsigned char 15 AND D0Ar2,D0Ar2,#0xff 16 MOV D0Ar6, D1Ar1 17 MOV D1Ar5, D0Ar6 18 !! test alignment 19 AND D1Ar5, D1Ar5, #7 20 CMP D1Ar5, #0 21 BNZ $Lunaligned_loop 22 !! length must be greater than or equal to 8 for aligned loop 23 CMP D1Ar3, #8 24 BGE $Laligned_setup 25$Lunaligned_loop: 26 !! get 1 char from s 27 GETB D0Re0, [D0Ar6++] 28 !! increase alignment counter 29 ADD D1Ar5, D1Ar5, #1 30 !! decrement n 31 SUB D1Ar3, D1Ar3, #1 32 !! exit if we have a match 33 CMP D0Re0, D0Ar2 34 BZ $Lexit_success1 35 !! exit if we have hit the end of the string 36 CMP D1Ar3, #0 37 BZ $Lexit_fail 38 !! fall through if the buffer is aligned now 39 CMP D1Ar5, #8 40 BNE $Lunaligned_loop 41 !! fall through if there is more than 8 bytes left 42 CMP D1Ar3, #8 43 BLT $Lunaligned_loop 44$Laligned_setup: 45 !! fill the c into 4 bytes 46 MOV D0Ar4, D0Ar2 47 LSL D0Ar4, D0Ar4, #8 48 ADD D0Ar4, D0Ar4, D0Ar2 49 LSL D0Ar4, D0Ar4, #8 50 ADD D0Ar4, D0Ar4, D0Ar2 51 LSL D0Ar4, D0Ar4, #8 52 ADD D0Ar4, D0Ar4, D0Ar2 53 !! divide n by 8 54 MOV D1Ar5, D1Ar3 55 LSR D1Ar5, D1Ar5, #3 56$Laligned_loop: 57 !! get 8 chars from s 58 GETL D0Re0, D1Re0, [D0Ar6++] 59 !! decrement loop counter 60 SUB D1Ar5, D1Ar5, #1 61 !! test first 4 chars 62 XOR D0Re0, D0Re0, D0Ar4 63 !! test second 4 chars 64 MOV D0Ar2, D1Re0 65 XOR D1Re0, D0Ar2, D0Ar4 66 !! check for matches in the first 4 chars 67 MOV D0Ar2, D0Re0 68 ADDT D0Re0, D0Re0, #HI(0xfefefeff) 69 ADD D0Re0, D0Re0, #LO(0xfefefeff) 70 XOR D0Ar2, D0Ar2, #-1 71 AND D0Re0, D0Re0, D0Ar2 72 ANDMT D0Re0, D0Re0, #HI(0x80808080) 73 ANDMB D0Re0, D0Re0, #LO(0x80808080) 74 CMP D0Re0, #0 75 BNZ $Lmatch_word1 76 !! check for matches in the second 4 chars 77 MOV D1Ar1, D1Re0 78 ADDT D1Re0, D1Re0, #HI(0xfefefeff) 79 ADD D1Re0, D1Re0, #LO(0xfefefeff) 80 XOR D1Ar1, D1Ar1, #-1 81 AND D1Re0, D1Re0, D1Ar1 82 ANDMT D1Re0, D1Re0, #HI(0x80808080) 83 ANDMB D1Re0, D1Re0, #LO(0x80808080) 84 CMP D1Re0, #0 85 BNZ $Lmatch_word2 86 !! check if we have reached the end of the buffer 87 CMP D1Ar5, #0 88 BNE $Laligned_loop 89 !! exit if there are no chars left to check 90 AND D1Ar3, D1Ar3, #7 91 CMP D1Ar3, #0 92 BZ $Lexit_fail 93 !! recover c 94 AND D0Ar2, D0Ar4, #0xff 95$Lbyte_loop: 96 !! get 1 char from s 97 GETB D0Re0, [D0Ar6++] 98 !! decrement n 99 SUB D1Ar3, D1Ar3, #1 100 !! exit if we have a match 101 CMP D0Re0, D0Ar2 102 BZ $Lexit_success1 103 !! fall through if we have run out of chars 104 CMP D1Ar3, #0 105 BNE $Lbyte_loop 106 107$Lexit_fail: 108 MOV D0Re0, #0 109 B $Lend 110 111$Lmatch_word1: 112 !! move the match word into D1Re0 113 MOV D1Re0, D0Re0 114 !! roll back the buffer pointer by 4 chars 115 SUB D0Ar6, D0Ar6, #4 116$Lmatch_word2: 117 !! roll back the buffer pointer by 4 chars 118 SUB D0Ar6, D0Ar6, #4 119 !! exit if lowest byte is 0 120 MOV D1Ar1, D1Re0 121 AND D1Ar1, D1Ar1, #0xff 122 CMP D1Ar1, #0 123 BNE $Lexit_success2 124 !! advance buffer pointer to the next char 125 ADD D0Ar6, D0Ar6, #1 126 !! shift in the next lowest byte 127 LSR D1Re0, D1Re0, #8 128 !! exit if lowest byte is 0 129 MOV D1Ar1, D1Re0 130 AND D1Ar1, D1Ar1, #0xff 131 CMP D1Ar1, #0 132 BNE $Lexit_success2 133 !! advance buffer pointer to the next char 134 ADD D0Ar6, D0Ar6, #1 135 !! shift in the next lowest byte 136 LSR D1Re0, D1Re0, #8 137 !! exit if lowest byte is 0 138 MOV D1Ar1, D1Re0 139 AND D1Ar1, D1Ar1, #0xff 140 CMP D1Ar1, #0 141 BNE $Lexit_success2 142 !! the match must be in the last byte, exit 143 ADD D0Ar6, D0Ar6, #1 144 B $Lexit_success2 145 146$Lexit_success1: 147 SUB D0Ar6, D0Ar6, #1 148$Lexit_success2: 149 !! return the buffer pointer 150 MOV D0Re0, D0Ar6 151$Lend: 152 MOV PC, D1RtP 153 154 .size _memchr,.-_memchr 155 156libc_hidden_def(memchr) 157