162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci/* ARC700 has a relatively long pipeline and branch prediction, so we want 762306a36Sopenharmony_ci to avoid branches that are hard to predict. On the other hand, the 862306a36Sopenharmony_ci presence of the norm instruction makes it easier to operate on whole 962306a36Sopenharmony_ci words branch-free. */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/linkage.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciENTRY_CFI(strchr) 1462306a36Sopenharmony_ci extb_s r1,r1 1562306a36Sopenharmony_ci asl r5,r1,8 1662306a36Sopenharmony_ci bmsk r2,r0,1 1762306a36Sopenharmony_ci or r5,r5,r1 1862306a36Sopenharmony_ci mov_s r3,0x01010101 1962306a36Sopenharmony_ci breq.d r2,r0,.Laligned 2062306a36Sopenharmony_ci asl r4,r5,16 2162306a36Sopenharmony_ci sub_s r0,r0,r2 2262306a36Sopenharmony_ci asl r7,r2,3 2362306a36Sopenharmony_ci ld_s r2,[r0] 2462306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN__ 2562306a36Sopenharmony_ci asl r7,r3,r7 2662306a36Sopenharmony_ci#else 2762306a36Sopenharmony_ci lsr r7,r3,r7 2862306a36Sopenharmony_ci#endif 2962306a36Sopenharmony_ci or r5,r5,r4 3062306a36Sopenharmony_ci ror r4,r3 3162306a36Sopenharmony_ci sub r12,r2,r7 3262306a36Sopenharmony_ci bic_s r12,r12,r2 3362306a36Sopenharmony_ci and r12,r12,r4 3462306a36Sopenharmony_ci brne.d r12,0,.Lfound0_ua 3562306a36Sopenharmony_ci xor r6,r2,r5 3662306a36Sopenharmony_ci ld.a r2,[r0,4] 3762306a36Sopenharmony_ci sub r12,r6,r7 3862306a36Sopenharmony_ci bic r12,r12,r6 3962306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN__ 4062306a36Sopenharmony_ci and r7,r12,r4 4162306a36Sopenharmony_ci breq r7,0,.Loop ; For speed, we want this branch to be unaligned. 4262306a36Sopenharmony_ci b .Lfound_char ; Likewise this one. 4362306a36Sopenharmony_ci#else 4462306a36Sopenharmony_ci and r12,r12,r4 4562306a36Sopenharmony_ci breq r12,0,.Loop ; For speed, we want this branch to be unaligned. 4662306a36Sopenharmony_ci lsr_s r12,r12,7 4762306a36Sopenharmony_ci bic r2,r7,r6 4862306a36Sopenharmony_ci b.d .Lfound_char_b 4962306a36Sopenharmony_ci and_s r2,r2,r12 5062306a36Sopenharmony_ci#endif 5162306a36Sopenharmony_ci; /* We require this code address to be unaligned for speed... */ 5262306a36Sopenharmony_ci.Laligned: 5362306a36Sopenharmony_ci ld_s r2,[r0] 5462306a36Sopenharmony_ci or r5,r5,r4 5562306a36Sopenharmony_ci ror r4,r3 5662306a36Sopenharmony_ci; /* ... so that this code address is aligned, for itself and ... */ 5762306a36Sopenharmony_ci.Loop: 5862306a36Sopenharmony_ci sub r12,r2,r3 5962306a36Sopenharmony_ci bic_s r12,r12,r2 6062306a36Sopenharmony_ci and r12,r12,r4 6162306a36Sopenharmony_ci brne.d r12,0,.Lfound0 6262306a36Sopenharmony_ci xor r6,r2,r5 6362306a36Sopenharmony_ci ld.a r2,[r0,4] 6462306a36Sopenharmony_ci sub r12,r6,r3 6562306a36Sopenharmony_ci bic r12,r12,r6 6662306a36Sopenharmony_ci and r7,r12,r4 6762306a36Sopenharmony_ci breq r7,0,.Loop /* ... so that this branch is unaligned. */ 6862306a36Sopenharmony_ci ; Found searched-for character. r0 has already advanced to next word. 6962306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN__ 7062306a36Sopenharmony_ci/* We only need the information about the first matching byte 7162306a36Sopenharmony_ci (i.e. the least significant matching byte) to be exact, 7262306a36Sopenharmony_ci hence there is no problem with carry effects. */ 7362306a36Sopenharmony_ci.Lfound_char: 7462306a36Sopenharmony_ci sub r3,r7,1 7562306a36Sopenharmony_ci bic r3,r3,r7 7662306a36Sopenharmony_ci norm r2,r3 7762306a36Sopenharmony_ci sub_s r0,r0,1 7862306a36Sopenharmony_ci asr_s r2,r2,3 7962306a36Sopenharmony_ci j.d [blink] 8062306a36Sopenharmony_ci sub_s r0,r0,r2 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci .balign 4 8362306a36Sopenharmony_ci.Lfound0_ua: 8462306a36Sopenharmony_ci mov r3,r7 8562306a36Sopenharmony_ci.Lfound0: 8662306a36Sopenharmony_ci sub r3,r6,r3 8762306a36Sopenharmony_ci bic r3,r3,r6 8862306a36Sopenharmony_ci and r2,r3,r4 8962306a36Sopenharmony_ci or_s r12,r12,r2 9062306a36Sopenharmony_ci sub_s r3,r12,1 9162306a36Sopenharmony_ci bic_s r3,r3,r12 9262306a36Sopenharmony_ci norm r3,r3 9362306a36Sopenharmony_ci add_s r0,r0,3 9462306a36Sopenharmony_ci asr_s r12,r3,3 9562306a36Sopenharmony_ci asl.f 0,r2,r3 9662306a36Sopenharmony_ci sub_s r0,r0,r12 9762306a36Sopenharmony_ci j_s.d [blink] 9862306a36Sopenharmony_ci mov.pl r0,0 9962306a36Sopenharmony_ci#else /* BIG ENDIAN */ 10062306a36Sopenharmony_ci.Lfound_char: 10162306a36Sopenharmony_ci lsr r7,r7,7 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci bic r2,r7,r6 10462306a36Sopenharmony_ci.Lfound_char_b: 10562306a36Sopenharmony_ci norm r2,r2 10662306a36Sopenharmony_ci sub_s r0,r0,4 10762306a36Sopenharmony_ci asr_s r2,r2,3 10862306a36Sopenharmony_ci j.d [blink] 10962306a36Sopenharmony_ci add_s r0,r0,r2 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci.Lfound0_ua: 11262306a36Sopenharmony_ci mov_s r3,r7 11362306a36Sopenharmony_ci.Lfound0: 11462306a36Sopenharmony_ci asl_s r2,r2,7 11562306a36Sopenharmony_ci or r7,r6,r4 11662306a36Sopenharmony_ci bic_s r12,r12,r2 11762306a36Sopenharmony_ci sub r2,r7,r3 11862306a36Sopenharmony_ci or r2,r2,r6 11962306a36Sopenharmony_ci bic r12,r2,r12 12062306a36Sopenharmony_ci bic.f r3,r4,r12 12162306a36Sopenharmony_ci norm r3,r3 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci add.pl r3,r3,1 12462306a36Sopenharmony_ci asr_s r12,r3,3 12562306a36Sopenharmony_ci asl.f 0,r2,r3 12662306a36Sopenharmony_ci add_s r0,r0,r12 12762306a36Sopenharmony_ci j_s.d [blink] 12862306a36Sopenharmony_ci mov.mi r0,0 12962306a36Sopenharmony_ci#endif /* ENDIAN */ 13062306a36Sopenharmony_ciEND_CFI(strchr) 131