1/*
2   Copyright (c) 2015, Synopsys, Inc. All rights reserved.
3
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions are met:
6
7   1) Redistributions of source code must retain the above copyright notice,
8   this list of conditions and the following disclaimer.
9
10   2) Redistributions in binary form must reproduce the above copyright notice,
11   this list of conditions and the following disclaimer in the documentation
12   and/or other materials provided with the distribution.
13
14   3) Neither the name of the Synopsys, Inc., nor the names of its contributors
15   may be used to endorse or promote products derived from this software
16   without specific prior written permission.
17
18   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28   POSSIBILITY OF SUCH DAMAGE.
29*/
30
31/* This implementation is optimized for performance.  For code size a generic
32   implementation of this function from newlib/libc/string/memcmp.c will be
33   used.  */
34#if !defined (__OPTIMIZE_SIZE__) && !defined (PREFER_SIZE_OVER_SPEED)
35
36#include "asm.h"
37
38#if defined (__ARC601__) || !defined (__ARC_NORM__) \
39    || !defined (__ARC_BARREL_SHIFTER__)
40
41/* Addresses are unsigned, and at 0 is the vector table, so it's OK to assume
42   that we can subtract 8 from a source end address without underflow.  */
43
44ENTRY (memcmp)
45	or	r12,r0,r1
46	tst	r12,3
47	breq	r2,0,.Lnil
48	add_s	r3,r0,r2
49
50/* This algorithm for big endian targets sometimes works incorrectly
51   when sources are aligned. To be precise the last step is omitted.
52   Just use a simple bytewise variant until the algorithm is reviewed
53   and fixed.  */
54
55#ifdef __LITTLE_ENDIAN__
56	bne_s	.Lbytewise
57#else /* BIG ENDIAN */
58	b_s	.Lbytewise
59#endif /* ENDIAN */
60	sub	r6,r3,8
61	ld	r4,[r0,0]
62	ld	r5,[r1,0]
632:
64	brhs	r0,r6,.Loop_end
65	ld_s	r3,[r0,4]
66	ld_s	r12,[r1,4]
67	brne	r4,r5,.Leven
68	ld.a	r4,[r0,8]
69	breq.d	r3,r12,2b
70	ld.a	r5,[r1,8]
71#ifdef __LITTLE_ENDIAN__
72	mov_s	r4,r3
73	b.d	.Lodd
74	mov_s	r5,r12
75#else /* BIG ENDIAN */
76	cmp_s	r3,r12
77	j_s.d	[blink]
78	rrc	r0,2
79#endif /* ENDIAN */
80
81	.balign	4
82.Loop_end:
83	sub	r3,r0,r6
84	brhs	r3,4,.Last_cmp
85	brne	r4,r5,.Leven
86	ld	r4,[r0,4]
87	ld	r5,[r1,4]
88#ifdef __LITTLE_ENDIAN__
89	.balign	4
90.Last_cmp:
91	mov_l	r0,24
92	add3	r2,r0,r2
93	xor	r0,r4,r5
94	b.d	.Leven_cmp
95	bset	r0,r0,r2
96.Lodd:
97.Leven:
98	xor	r0,r4,r5
99.Leven_cmp:
100	mov_s	r1,0x80808080
101	; uses long immediate
102	sub_s	r12,r0,1
103	bic_s	r0,r0,r12
104	sub	r0,r1,r0
105	xor_s	r0,r0,r1
106	and	r1,r5,r0
107	and	r0,r4,r0
108#else /* BIG ENDIAN */
109.Last_cmp:
110	mov_s	r3,0
111	sub3	r2,r3,r2
112	sub_s	r3,r3,1
113	bclr	r3,r3,r2
114	add_l	r3,r3,1
115	and	r0,r4,r3
116	and	r1,r5,r3
117.Leven:
118#endif /* ENDIAN */
119	xor.f	0,r0,r1
120	sub_s	r0,r0,r1
121	j_s.d	[blink]
122	mov.mi	r0,r1
123	.balign	4
124.Lbytewise:
125	ldb	r4,[r0,0]
126	ldb	r5,[r1,0]
127	sub	r6,r3,2
1283:
129	brhs	r0,r6,.Lbyte_end
130	ldb_s	r3,[r0,1]
131	ldb_s	r12,[r1,1]
132	brne	r4,r5,.Lbyte_even
133	ldb.a	r4,[r0,2]
134	breq.d	r3,r12,3b
135	ldb.a	r5,[r1,2]
136.Lbyte_odd:
137	j_s.d	[blink]
138	sub	r0,r3,r12
139	.balign	4
140.Lbyte_end:
141	bbit1	r2,0,.Lbyte_even
142	brne	r4,r5,.Lbyte_even
143	ldb	r4,[r0,1]
144	ldb	r5,[r1,1]
145.Lbyte_even:
146	j_s.d	[blink]
147	sub	r0,r4,r5
148.Lnil:
149	j_s.d	[blink]
150	mov_s	r0,0
151ENDFUNC (memcmp)
152#endif /* __ARC601__ || !__ARC_NORM__ || !__ARC_BARREL_SHIFTER__ */
153
154#endif /* !__OPTIMIZE_SIZE__ && !PREFER_SIZE_OVER_SPEED */
155