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