| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 | !    Copyright (C) 2013 Imagination Technologies Ltd.!!    Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.	.text	.global	_memchr	.type	_memchr,function! D0Ar6 src! D0Ar2 c! D1Ar3 n_memchr:	CMP     D1Ar3, #0	BEQ	$Lexit_fail	!! convert c to unsigned char	AND     D0Ar2,D0Ar2,#0xff	MOV	D0Ar6, D1Ar1	MOV	D1Ar5, D0Ar6	!! test alignment	AND	D1Ar5, D1Ar5, #7	CMP	D1Ar5, #0	BNZ	$Lunaligned_loop	!! length must be greater than or equal to 8 for aligned loop	CMP     D1Ar3, #8	BGE     $Laligned_setup$Lunaligned_loop:	!! get 1 char from s	GETB	D0Re0, [D0Ar6++]	!! increase alignment counter	ADD	D1Ar5, D1Ar5, #1	!! decrement n	SUB     D1Ar3, D1Ar3, #1	!! exit if we have a match	CMP	D0Re0, D0Ar2	BZ	$Lexit_success1	!! exit if we have hit the end of the string	CMP	D1Ar3, #0	BZ	$Lexit_fail	!! fall through if the buffer is aligned now	CMP	D1Ar5, #8	BNE	$Lunaligned_loop	!! fall through if there is more than 8 bytes left	CMP	D1Ar3, #8	BLT	$Lunaligned_loop$Laligned_setup:	!! fill the c into 4 bytes	MOV	D0Ar4, D0Ar2	LSL	D0Ar4, D0Ar4, #8	ADD	D0Ar4, D0Ar4, D0Ar2	LSL	D0Ar4, D0Ar4, #8	ADD	D0Ar4, D0Ar4, D0Ar2	LSL	D0Ar4, D0Ar4, #8	ADD	D0Ar4, D0Ar4, D0Ar2	!! divide n by 8	MOV	D1Ar5, D1Ar3	LSR	D1Ar5, D1Ar5, #3$Laligned_loop:	!! get 8 chars from s	GETL	D0Re0, D1Re0, [D0Ar6++]	!! decrement loop counter	SUB	D1Ar5, D1Ar5, #1	!! test first 4 chars	XOR	D0Re0, D0Re0, D0Ar4	!! test second 4 chars	MOV	D0Ar2, D1Re0	XOR	D1Re0, D0Ar2, D0Ar4	!! check for matches in the first 4 chars	MOV	D0Ar2, D0Re0	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	$Lmatch_word1	!! check for matches in the second 4 chars	MOV	D1Ar1, D1Re0	ADDT	D1Re0, D1Re0, #HI(0xfefefeff)	ADD	D1Re0, D1Re0, #LO(0xfefefeff)	XOR	D1Ar1, D1Ar1, #-1	AND	D1Re0, D1Re0, D1Ar1	ANDMT	D1Re0, D1Re0, #HI(0x80808080)	ANDMB	D1Re0, D1Re0, #LO(0x80808080)	CMP	D1Re0, #0	BNZ	$Lmatch_word2	!! check if we have reached the end of the buffer	CMP	D1Ar5, #0	BNE	$Laligned_loop	!! exit if there are no chars left to check	AND	D1Ar3, D1Ar3, #7	CMP	D1Ar3, #0	BZ	$Lexit_fail	!! recover c	AND	D0Ar2, D0Ar4, #0xff$Lbyte_loop:	!! get 1 char from s	GETB	D0Re0, [D0Ar6++]	!! decrement n	SUB	D1Ar3, D1Ar3, #1	!! exit if we have a match	CMP	D0Re0, D0Ar2	BZ	$Lexit_success1	!! fall through if we have run out of chars	CMP	D1Ar3, #0	BNE	$Lbyte_loop$Lexit_fail:	MOV	D0Re0, #0	B	$Lend$Lmatch_word1:	!! move the match word into D1Re0	MOV	D1Re0, D0Re0	!! roll back the buffer pointer by 4 chars	SUB	D0Ar6, D0Ar6, #4$Lmatch_word2:	!! roll back the buffer pointer by 4 chars	SUB	D0Ar6, D0Ar6, #4	!! exit if lowest byte is 0	MOV	D1Ar1, D1Re0	AND	D1Ar1, D1Ar1, #0xff	CMP	D1Ar1, #0	BNE	$Lexit_success2	!! advance buffer pointer to the next char	ADD	D0Ar6, D0Ar6, #1	!! shift in the next lowest byte	LSR	D1Re0, D1Re0, #8	!! exit if lowest byte is 0	MOV	D1Ar1, D1Re0	AND	D1Ar1, D1Ar1, #0xff	CMP	D1Ar1, #0	BNE	$Lexit_success2	!! advance buffer pointer to the next char	ADD	D0Ar6, D0Ar6, #1	!! shift in the next lowest byte	LSR	D1Re0, D1Re0, #8	!! exit if lowest byte is 0	MOV	D1Ar1, D1Re0	AND	D1Ar1, D1Ar1, #0xff	CMP	D1Ar1, #0	BNE	$Lexit_success2	!! the match must be in the last byte, exit	ADD	D0Ar6, D0Ar6, #1	B	$Lexit_success2$Lexit_success1:	SUB	D0Ar6, D0Ar6, #1$Lexit_success2:	!! return the buffer pointer	MOV	D0Re0, D0Ar6$Lend:	MOV	PC, D1RtP	.size _memchr,.-_memchrlibc_hidden_def(memchr)
 |