123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- /*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- /* ARC700 has a relatively long pipeline and branch prediction, so we want
- to avoid branches that are hard to predict. On the other hand, the
- presence of the norm instruction makes it easier to operate on whole
- words branch-free. */
- #include <linux/linkage.h>
- ENTRY_CFI(strchr)
- extb_s r1,r1
- asl r5,r1,8
- bmsk r2,r0,1
- or r5,r5,r1
- mov_s r3,0x01010101
- breq.d r2,r0,.Laligned
- asl r4,r5,16
- sub_s r0,r0,r2
- asl r7,r2,3
- ld_s r2,[r0]
- #ifdef __LITTLE_ENDIAN__
- asl r7,r3,r7
- #else
- lsr r7,r3,r7
- #endif
- or r5,r5,r4
- ror r4,r3
- sub r12,r2,r7
- bic_s r12,r12,r2
- and r12,r12,r4
- brne.d r12,0,.Lfound0_ua
- xor r6,r2,r5
- ld.a r2,[r0,4]
- sub r12,r6,r7
- bic r12,r12,r6
- #ifdef __LITTLE_ENDIAN__
- and r7,r12,r4
- breq r7,0,.Loop ; For speed, we want this branch to be unaligned.
- b .Lfound_char ; Likewise this one.
- #else
- and r12,r12,r4
- breq r12,0,.Loop ; For speed, we want this branch to be unaligned.
- lsr_s r12,r12,7
- bic r2,r7,r6
- b.d .Lfound_char_b
- and_s r2,r2,r12
- #endif
- ; /* We require this code address to be unaligned for speed... */
- .Laligned:
- ld_s r2,[r0]
- or r5,r5,r4
- ror r4,r3
- ; /* ... so that this code address is aligned, for itself and ... */
- .Loop:
- sub r12,r2,r3
- bic_s r12,r12,r2
- and r12,r12,r4
- brne.d r12,0,.Lfound0
- xor r6,r2,r5
- ld.a r2,[r0,4]
- sub r12,r6,r3
- bic r12,r12,r6
- and r7,r12,r4
- breq r7,0,.Loop /* ... so that this branch is unaligned. */
- ; Found searched-for character. r0 has already advanced to next word.
- #ifdef __LITTLE_ENDIAN__
- /* We only need the information about the first matching byte
- (i.e. the least significant matching byte) to be exact,
- hence there is no problem with carry effects. */
- .Lfound_char:
- sub r3,r7,1
- bic r3,r3,r7
- norm r2,r3
- sub_s r0,r0,1
- asr_s r2,r2,3
- j.d [blink]
- sub_s r0,r0,r2
- .balign 4
- .Lfound0_ua:
- mov r3,r7
- .Lfound0:
- sub r3,r6,r3
- bic r3,r3,r6
- and r2,r3,r4
- or_s r12,r12,r2
- sub_s r3,r12,1
- bic_s r3,r3,r12
- norm r3,r3
- add_s r0,r0,3
- asr_s r12,r3,3
- asl.f 0,r2,r3
- sub_s r0,r0,r12
- j_s.d [blink]
- mov.pl r0,0
- #else /* BIG ENDIAN */
- .Lfound_char:
- lsr r7,r7,7
- bic r2,r7,r6
- .Lfound_char_b:
- norm r2,r2
- sub_s r0,r0,4
- asr_s r2,r2,3
- j.d [blink]
- add_s r0,r0,r2
- .Lfound0_ua:
- mov_s r3,r7
- .Lfound0:
- asl_s r2,r2,7
- or r7,r6,r4
- bic_s r12,r12,r2
- sub r2,r7,r3
- or r2,r2,r6
- bic r12,r2,r12
- bic.f r3,r4,r12
- norm r3,r3
- add.pl r3,r3,1
- asr_s r12,r3,3
- asl.f 0,r2,r3
- add_s r0,r0,r12
- j_s.d [blink]
- mov.mi r0,0
- #endif /* ENDIAN */
- END_CFI(strchr)
|