]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/powerpc64/string/strcmp.S
twsi: Calculate the clock param based on the bus frequency
[FreeBSD/FreeBSD.git] / lib / libc / powerpc64 / string / strcmp.S
1 /*-
2  * Copyright (c) 2018 Instituto de Pesquisas Eldorado
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
29
30 #if 0
31         RCSID("$NetBSD: strcmp.S,v 1.0 2018/05/10 12:33:02 alexandre Exp $")
32 #endif
33
34 /* Alignment mask. */
35 #define STRCMP_MULTI_ALIGNMENT_BYTES 8
36 #define STRCMP_MULTI_ALIGNMENT_MASK (STRCMP_MULTI_ALIGNMENT_BYTES - 1)
37
38 ENTRY(strcmp)
39         /* Starting alignment even if aligned, avoiding performance
40          * degradation for short strings.
41          */
42         lbz     %r5,0(%r3)              /* Load chars. */
43         lbz     %r6,0(%r4)
44         cmpd    %r5,%r6                 /* Check if chars are different. */
45         bne     .Lstrcmp_end
46         cmpdi   %r5,0                   /* Check if char is zero. */
47         beq     .Lstrcmp_end
48
49         /* Checking if addresses can be aligned, otherwise copy by byte */
50         xor     %r7,%r3,%r4
51         andi.   %r7,%r7,STRCMP_MULTI_ALIGNMENT_MASK
52         bne     .Lstrcmp_compare_by_byte_loop
53
54 .Lstrcmp_param1_align_loop:
55         lbzu    %r5,1(%r3)              /* Load chars. */
56         lbzu    %r6,1(%r4)
57         cmpd    %r5,%r6                 /* Check if chars are different. */
58         bne     .Lstrcmp_end
59         cmpdi   %r5,0                   /* Check if char is zero. */
60         beq     .Lstrcmp_end
61         andi.   %r7,%r3,STRCMP_MULTI_ALIGNMENT_MASK     /* Check alignment. */
62         bne     .Lstrcmp_param1_align_loop
63
64 .Lstrcmp_param1_aligned:
65         /* If parameter 2 is aligned compare by qword/word,
66          * else compare by byte. */
67         andi.   %r7,%r4,STRCMP_MULTI_ALIGNMENT_MASK
68         beq     .Lstrcmp_compare_by_word
69         lbz     %r5,0(%r3)      /* Load chars. */
70         lbz     %r6,0(%r4)
71         cmpd    %r5,%r6         /* Check if chars are different. */
72         bne+    .Lstrcmp_end
73         cmpdi   %r5,0           /* Check if char is zero. */
74         beq+    .Lstrcmp_end
75
76 .Lstrcmp_compare_by_byte_loop:
77         lbzu    %r5,1(%r3)
78         lbzu    %r6,1(%r4)
79         cmpdi   %r5,0
80         beq     .Lstrcmp_end
81         cmpd    %r5,%r6
82         beq     .Lstrcmp_compare_by_byte_loop
83
84 .Lstrcmp_end:
85         sub     %r3,%r5,%r6
86         blr
87
88 .Lstrcmp_compare_by_word:
89         ld      %r5,0(%r3)      /* Load double words. */
90         ld      %r6,0(%r4)
91         xor     %r8,%r8,%r8     /* %r8 <- Zero. */
92         xor     %r0,%r5,%r6     /* Check if double words are different. */
93         cmpb    %r7,%r5,%r8     /* Check if double words contain zero. */
94
95         /*
96          * If double words are different or contain zero,
97          * find what byte is different or contains zero,
98          * else load next double words.
99          */
100         or.     %r9,%r7,%r0
101         bne     .Lstrcmp_check_zeros_differences
102
103 .Lstrcmp_compare_by_word_loop:
104         ldu     %r5,8(%r3)      /* Load double words. */
105         ldu     %r6,8(%r4)
106         xor     %r0,%r5,%r6     /* Check if double words are different. */
107         cmpb    %r7,%r5,%r8     /* Check if double words contain zero. */
108
109         /*
110          * If double words are different or contain zero,
111          * find what byte is different or contains zero,
112          * else load next double words.
113          */
114         or.     %r9,%r7,%r0
115         beq     .Lstrcmp_compare_by_word_loop
116
117 .Lstrcmp_check_zeros_differences:
118         /* Find what byte is different or contains zero. */
119
120         /* Check 1st byte. */
121         rldicr. %r0,%r9,0,7
122         bne     .Lstrcmp_found_zero_difference_in_1
123
124         /* Check 2nd byte. */
125         rldicr. %r0,%r9,8,7
126         bne     .Lstrcmp_found_zero_difference_in_2
127
128         /* Check 3rd byte. */
129         rldicr. %r0,%r9,16,7
130         bne     .Lstrcmp_found_zero_difference_in_3
131
132         /* Check 4th byte. */
133         rldicr. %r0,%r9,24,7
134         bne     .Lstrcmp_found_zero_difference_in_4
135
136         /* Check 5th byte. */
137         andis.  %r0,%r9,0xff00
138         bne     .Lstrcmp_found_zero_difference_in_5
139
140         /* Check 6th byte. */
141         andis.  %r0,%r9,0xff
142         bne     .Lstrcmp_found_zero_difference_in_6
143
144         /* Check 7th byte. */
145         andi.   %r0,%r9,0xff00
146         bne     .Lstrcmp_found_zero_difference_in_7
147
148 .Lstrcmp_found_zero_difference_in_8:
149         /* 8th byte is different or contains zero. */
150         andi.   %r5,%r5,0xff
151         andi.   %r6,%r6,0xff
152         sub     %r3,%r5,%r6
153         blr
154
155 .Lstrcmp_found_zero_difference_in_1:
156         /* 1st byte is different or contains zero. */
157         lbz     %r5,0(%r3)
158         lbz     %r6,0(%r4)
159         sub     %r3,%r5,%r6
160         blr
161
162 .Lstrcmp_found_zero_difference_in_2:
163         /* 2nd byte is different or contains zero. */
164         lbz     %r5,1(%r3)
165         lbz     %r6,1(%r4)
166         sub     %r3,%r5,%r6
167         blr
168
169 .Lstrcmp_found_zero_difference_in_3:
170         /* 3rd byte is different or contains zero. */
171         lbz     %r5,2(%r3)
172         lbz     %r6,2(%r4)
173         sub     %r3,%r5,%r6
174         blr
175
176 .Lstrcmp_found_zero_difference_in_4:
177         /* 4th byte is different or contains zero. */
178         lbz     %r5,3(%r3)
179         lbz     %r6,3(%r4)
180         sub     %r3,%r5,%r6
181         blr
182
183 .Lstrcmp_found_zero_difference_in_5:
184         /* 5th byte is different or contains zero. */
185         lbz     %r5,4(%r3)
186         lbz     %r6,4(%r4)
187         sub     %r3,%r5,%r6
188         blr
189
190 .Lstrcmp_found_zero_difference_in_6:
191         /* 6th byte is different or contains zero. */
192         lbz     %r5,5(%r3)
193         lbz     %r6,5(%r4)
194         sub     %r3,%r5,%r6
195         blr
196
197 .Lstrcmp_found_zero_difference_in_7:
198         /* 7th byte is different or contains zero. */
199         lbz     %r5,6(%r3)
200         lbz     %r6,6(%r4)
201         sub     %r3,%r5,%r6
202         blr
203
204 END(strcmp)
205
206         .section .note.GNU-stack,"",%progbits
207