Cygwin: Add new APIs tc[gs]etwinsize()
[newlib-cygwin.git] / newlib / libc / machine / arc / memcmp.S
blob30b7a7450b7dd00f9b4557db8882b0b4b4fa7416
1 /*
2    Copyright (c) 2015-2024, Synopsys, Inc. All rights reserved.
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions are met:
7    1) Redistributions of source code must retain the above copyright notice,
8    this list of conditions and the following disclaimer.
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.
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.
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.
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     && !defined (__ARC_RF16__)
37 #include "asm.h"
39 #if defined (__ARC601__) || !defined (__ARC_NORM__) \
40     || !defined (__ARC_BARREL_SHIFTER__)
42 /* Addresses are unsigned, and at 0 is the vector table, so it's OK to assume
43    that we can subtract 8 from a source end address without underflow.  */
45 ENTRY (memcmp)
46         or      r12,r0,r1
47         tst     r12,3
48         breq    r2,0,.Lnil
49         add_s   r3,r0,r2
51 /* This algorithm for big endian targets sometimes works incorrectly
52    when sources are aligned. To be precise the last step is omitted.
53    Just use a simple bytewise variant until the algorithm is reviewed
54    and fixed.  */
56 #ifdef __LITTLE_ENDIAN__
57         bne_s   .Lbytewise
58 #else /* BIG ENDIAN */
59         b_s     .Lbytewise
60 #endif /* ENDIAN */
61         sub     r6,r3,8
62         ld      r4,[r0,0]
63         ld      r5,[r1,0]
65         brhs    r0,r6,.Loop_end
66         ld_s    r3,[r0,4]
67         ld_s    r12,[r1,4]
68         brne    r4,r5,.Leven
69         ld.a    r4,[r0,8]
70         breq.d  r3,r12,2b
71         ld.a    r5,[r1,8]
72 #ifdef __LITTLE_ENDIAN__
73         mov_s   r4,r3
74         b.d     .Lodd
75         mov_s   r5,r12
76 #else /* BIG ENDIAN */
77         cmp_s   r3,r12
78         j_s.d   [blink]
79         rrc     r0,2
80 #endif /* ENDIAN */
82         .balign 4
83 .Loop_end:
84         sub     r3,r0,r6
85         brhs    r3,4,.Last_cmp
86         brne    r4,r5,.Leven
87         ld      r4,[r0,4]
88         ld      r5,[r1,4]
89 #ifdef __LITTLE_ENDIAN__
90         .balign 4
91 .Last_cmp:
92         mov_l   r0,24
93         add3    r2,r0,r2
94         xor     r0,r4,r5
95         b.d     .Leven_cmp
96         bset    r0,r0,r2
97 .Lodd:
98 .Leven:
99         xor     r0,r4,r5
100 .Leven_cmp:
101         mov_s   r1,0x80808080
102         ; uses long immediate
103         sub_s   r12,r0,1
104         bic_s   r0,r0,r12
105         sub     r0,r1,r0
106         xor_s   r0,r0,r1
107         and     r1,r5,r0
108         and     r0,r4,r0
109 #else /* BIG ENDIAN */
110 .Last_cmp:
111         mov_s   r3,0
112         sub3    r2,r3,r2
113         sub_s   r3,r3,1
114         bclr    r3,r3,r2
115         add_l   r3,r3,1
116         and     r0,r4,r3
117         and     r1,r5,r3
118 .Leven:
119 #endif /* ENDIAN */
120         xor.f   0,r0,r1
121         sub_s   r0,r0,r1
122         j_s.d   [blink]
123         mov.mi  r0,r1
124         .balign 4
125 .Lbytewise:
126         ldb     r4,[r0,0]
127         ldb     r5,[r1,0]
128         sub     r6,r3,2
130         brhs    r0,r6,.Lbyte_end
131         ldb_s   r3,[r0,1]
132         ldb_s   r12,[r1,1]
133         brne    r4,r5,.Lbyte_even
134         ldb.a   r4,[r0,2]
135         breq.d  r3,r12,3b
136         ldb.a   r5,[r1,2]
137 .Lbyte_odd:
138         j_s.d   [blink]
139         sub     r0,r3,r12
140         .balign 4
141 .Lbyte_end:
142         bbit1   r2,0,.Lbyte_even
143         brne    r4,r5,.Lbyte_even
144         ldb     r4,[r0,1]
145         ldb     r5,[r1,1]
146 .Lbyte_even:
147         j_s.d   [blink]
148         sub     r0,r4,r5
149 .Lnil:
150         j_s.d   [blink]
151         mov_s   r0,0
152 ENDFUNC (memcmp)
153 #endif /* __ARC601__ || !__ARC_NORM__ || !__ARC_BARREL_SHIFTER__ */
155 #endif /* !__OPTIMIZE_SIZE__ && !PREFER_SIZE_OVER_SPEED */