/* * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. * * SPDX-License-Identifier: GPL-2.0+ */ /* * 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. */ .global strchr .align 4 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 /* __BIG_ENDIAN__ */ lsr %r7, %r3, %r7 #endif /* _ENDIAN__ */ 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 /* For speed, we want this branch to be unaligned. */ breq %r7, 0, .Loop /* Likewise this one */ b .Lfound_char #else /* __BIG_ENDIAN__ */ and %r12, %r12, %r4 /* For speed, we want this branch to be unaligned. */ breq %r12, 0, .Loop lsr_s %r12, %r12, 7 bic %r2, %r7, %r6 b.d .Lfound_char_b and_s %r2, %r2, %r12 #endif /* _ENDIAN__ */ /* 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__ */