1/* Copyright (c) 2017  SiFive Inc. All rights reserved.
2
3   This copyrighted material is made available to anyone wishing to use,
4   modify, copy, or redistribute it subject to the terms and conditions
5   of the FreeBSD License.   This program is distributed in the hope that
6   it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
7   including the implied warranties of MERCHANTABILITY or FITNESS FOR
8   A PARTICULAR PURPOSE.  A copy of this license is available at
9   http://www.opensource.org/licenses.
10*/
11
12#include <sys/asm.h>
13
14.section .text.strcmp
15.globl strcmp
16.type  strcmp, @function
17strcmp:
18#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
191:
20  lbu   a2, 0(a0)
21  lbu   a3, 0(a1)
22  add   a0, a0, 1
23  add   a1, a1, 1
24  bne   a2, a3, 2f
25  bnez  a2, 1b
26
272:
28  sub   a0, a2, a3
29  ret
30
31.size	strcmp, .-strcmp
32#else
33  or    a4, a0, a1
34  li    t2, -1
35  and   a4, a4, SZREG-1
36  bnez  a4, .Lmisaligned
37
38#if SZREG == 4
39  li a5, 0x7f7f7f7f
40#else
41  ld a5, mask
42#endif
43
44  .macro check_one_word i n
45    REG_L a2, \i*SZREG(a0)
46    REG_L a3, \i*SZREG(a1)
47
48    and   t0, a2, a5
49    or    t1, a2, a5
50    add   t0, t0, a5
51    or    t0, t0, t1
52
53    bne   t0, t2, .Lnull\i
54    .if \i+1-\n
55      bne   a2, a3, .Lmismatch
56    .else
57      add   a0, a0, \n*SZREG
58      add   a1, a1, \n*SZREG
59      beq   a2, a3, .Lloop
60      # fall through to .Lmismatch
61    .endif
62  .endm
63
64  .macro foundnull i n
65    .ifne \i
66      .Lnull\i:
67      add   a0, a0, \i*SZREG
68      add   a1, a1, \i*SZREG
69      .ifeq \i-1
70        .Lnull0:
71      .endif
72      bne   a2, a3, .Lmisaligned
73      li    a0, 0
74      ret
75    .endif
76  .endm
77
78.Lloop:
79  # examine full words at a time, favoring strings of a couple dozen chars
80#if __riscv_xlen == 32
81  check_one_word 0 5
82  check_one_word 1 5
83  check_one_word 2 5
84  check_one_word 3 5
85  check_one_word 4 5
86#else
87  check_one_word 0 3
88  check_one_word 1 3
89  check_one_word 2 3
90#endif
91  # backwards branch to .Lloop contained above
92
93.Lmismatch:
94  # words don't match, but a2 has no null byte.
95
96#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
97
98#if __riscv_xlen == 64
99  sll   a4, a2, 48
100  sll   a5, a3, 48
101  bne   a4, a5, .Lmismatch_upper
102  sll   a4, a2, 32
103  sll   a5, a3, 32
104  bne   a4, a5, .Lmismatch_upper
105#endif
106  sll   a4, a2, 16
107  sll   a5, a3, 16
108  bne   a4, a5, .Lmismatch_upper
109
110  srl   a4, a2, 8*SZREG-16
111  srl   a5, a3, 8*SZREG-16
112  sub   a0, a4, a5
113  and   a1, a0, 0xff
114  bnez  a1, 1f
115  ret
116
117.Lmismatch_upper:
118  srl   a4, a4, 8*SZREG-16
119  srl   a5, a5, 8*SZREG-16
120  sub   a0, a4, a5
121  and   a1, a0, 0xff
122  bnez  a1, 1f
123  ret
124
1251:and   a4, a4, 0xff
126  and   a5, a5, 0xff
127  sub   a0, a4, a5
128  ret
129
130#else
131
132#if __riscv_xlen == 64
133  srl   a4, a2, 48
134  srl   a5, a3, 48
135  bne   a4, a5, .Lmismatch_lower
136  srl   a4, a2, 32
137  srl   a5, a3, 32
138  bne   a4, a5, .Lmismatch_lower
139#endif
140  srl   a4, a2, 16
141  srl   a5, a3, 16
142  bne   a4, a5, .Lmismatch_lower
143
144  srl	a4, a2, 8
145  srl   a5, a3, 8
146  bne   a4, a5, 1f
147  and   a4, a2, 0xff
148  and   a5, a3, 0xff
1491:sub	a0, a4, a5
150  ret
151
152.Lmismatch_lower:
153  srl	a2, a4, 8
154  srl   a3, a5, 8
155  bne   a2, a3, 1f
156  and   a2, a4, 0xff
157  and   a3, a5, 0xff
1581:sub	a0, a2, a3
159  ret
160
161#endif
162
163.Lmisaligned:
164  # misaligned
165  lbu   a2, 0(a0)
166  lbu   a3, 0(a1)
167  add   a0, a0, 1
168  add   a1, a1, 1
169  bne   a2, a3, 1f
170  bnez  a2, .Lmisaligned
171
1721:
173  sub   a0, a2, a3
174  ret
175
176  # cases in which a null byte was detected
177#if __riscv_xlen == 32
178  foundnull 0 5
179  foundnull 1 5
180  foundnull 2 5
181  foundnull 3 5
182  foundnull 4 5
183#else
184  foundnull 0 3
185  foundnull 1 3
186  foundnull 2 3
187#endif
188.size	strcmp, .-strcmp
189
190#if SZREG == 8
191.section .srodata.cst8,"aM",@progbits,8
192.align 3
193mask:
194.dword 0x7f7f7f7f7f7f7f7f
195#endif
196#endif
197