^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /* ARC700 has a relatively long pipeline and branch prediction, so we want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) to avoid branches that are hard to predict. On the other hand, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) presence of the norm instruction makes it easier to operate on whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) words branch-free. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ENTRY_CFI(strchr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) extb_s r1,r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) asl r5,r1,8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) bmsk r2,r0,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) or r5,r5,r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) mov_s r3,0x01010101
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) breq.d r2,r0,.Laligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) asl r4,r5,16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) sub_s r0,r0,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) asl r7,r2,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ld_s r2,[r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #ifdef __LITTLE_ENDIAN__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) asl r7,r3,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) lsr r7,r3,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) or r5,r5,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ror r4,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) sub r12,r2,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) bic_s r12,r12,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) and r12,r12,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) brne.d r12,0,.Lfound0_ua
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) xor r6,r2,r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ld.a r2,[r0,4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) sub r12,r6,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) bic r12,r12,r6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #ifdef __LITTLE_ENDIAN__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) and r7,r12,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) breq r7,0,.Loop ; For speed, we want this branch to be unaligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) b .Lfound_char ; Likewise this one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) and r12,r12,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) breq r12,0,.Loop ; For speed, we want this branch to be unaligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) lsr_s r12,r12,7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bic r2,r7,r6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) b.d .Lfound_char_b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) and_s r2,r2,r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ; /* We require this code address to be unaligned for speed... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .Laligned:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ld_s r2,[r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) or r5,r5,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ror r4,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ; /* ... so that this code address is aligned, for itself and ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .Loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) sub r12,r2,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) bic_s r12,r12,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) and r12,r12,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) brne.d r12,0,.Lfound0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) xor r6,r2,r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ld.a r2,[r0,4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) sub r12,r6,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bic r12,r12,r6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) and r7,r12,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) breq r7,0,.Loop /* ... so that this branch is unaligned. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ; Found searched-for character. r0 has already advanced to next word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #ifdef __LITTLE_ENDIAN__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* We only need the information about the first matching byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) (i.e. the least significant matching byte) to be exact,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hence there is no problem with carry effects. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .Lfound_char:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) sub r3,r7,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bic r3,r3,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) norm r2,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) sub_s r0,r0,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) asr_s r2,r2,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) j.d [blink]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) sub_s r0,r0,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .balign 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .Lfound0_ua:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) mov r3,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .Lfound0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) sub r3,r6,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) bic r3,r3,r6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) and r2,r3,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) or_s r12,r12,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sub_s r3,r12,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bic_s r3,r3,r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) norm r3,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) add_s r0,r0,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) asr_s r12,r3,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) asl.f 0,r2,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) sub_s r0,r0,r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) j_s.d [blink]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) mov.pl r0,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #else /* BIG ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .Lfound_char:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) lsr r7,r7,7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) bic r2,r7,r6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .Lfound_char_b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) norm r2,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sub_s r0,r0,4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) asr_s r2,r2,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) j.d [blink]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) add_s r0,r0,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .Lfound0_ua:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) mov_s r3,r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .Lfound0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) asl_s r2,r2,7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) or r7,r6,r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) bic_s r12,r12,r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sub r2,r7,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) or r2,r2,r6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) bic r12,r2,r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) bic.f r3,r4,r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) norm r3,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) add.pl r3,r3,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) asr_s r12,r3,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) asl.f 0,r2,r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) add_s r0,r0,r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) j_s.d [blink]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) mov.mi r0,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #endif /* ENDIAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) END_CFI(strchr)