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 <picolibc.h>
13
14#include "asm.h"
15
16.section .text.strcmp
17.globl strcmp
18.type  strcmp, @function
19strcmp:
20#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
211:
22  lbu   a2, 0(a0)
23  lbu   a3, 0(a1)
24  add   a0, a0, 1
25  add   a1, a1, 1
26  bne   a2, a3, 2f
27  bnez  a2, 1b
28
292:
30  sub   a0, a2, a3
31  ret
32
33.size	strcmp, .-strcmp
34#else
35  or    a4, a0, a1
36  li    t2, -1
37  and   a4, a4, SZREG-1
38  bnez  a4, .Lmisaligned
39
40#ifndef __riscv_zbb
41#if SZREG == 4
42  li a5, 0x7f7f7f7f
43#else
44  ld a5, mask
45#endif
46#endif
47
48  .macro check_one_word i n
49    REG_L a2, \i*SZREG(a0)
50    REG_L a3, \i*SZREG(a1)
51#ifdef __riscv_zbb
52    orc.b t0, a2
53#else
54    and   t0, a2, a5
55    or    t1, a2, a5
56    add   t0, t0, a5
57    or    t0, t0, t1
58#endif
59    bne   t0, t2, .Lnull\i
60    .if \i+1-\n
61      bne   a2, a3, .Lmismatch
62    .else
63      add   a0, a0, \n*SZREG
64      add   a1, a1, \n*SZREG
65      beq   a2, a3, .Lloop
66      # fall through to .Lmismatch
67    .endif
68  .endm
69
70  .macro foundnull i n
71    .ifne \i
72      .Lnull\i:
73      add   a0, a0, \i*SZREG
74      add   a1, a1, \i*SZREG
75      .ifeq \i-1
76        .Lnull0:
77      .endif
78      bne   a2, a3, .Lmisaligned
79      li    a0, 0
80      ret
81    .endif
82  .endm
83
84.Lloop:
85  # examine full words at a time, favoring strings of a couple dozen chars
86#if __riscv_xlen == 32
87  check_one_word 0 5
88  check_one_word 1 5
89  check_one_word 2 5
90  check_one_word 3 5
91  check_one_word 4 5
92#else
93  check_one_word 0 3
94  check_one_word 1 3
95  check_one_word 2 3
96#endif
97  # backwards branch to .Lloop contained above
98
99.Lmismatch:
100  # words don't match, but a2 has no null byte.
101
102#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
103
104#if __riscv_xlen == 64
105  sll   a4, a2, 48
106  sll   a5, a3, 48
107  bne   a4, a5, .Lmismatch_upper
108  sll   a4, a2, 32
109  sll   a5, a3, 32
110  bne   a4, a5, .Lmismatch_upper
111#endif
112  sll   a4, a2, 16
113  sll   a5, a3, 16
114  bne   a4, a5, .Lmismatch_upper
115
116  srl   a4, a2, 8*SZREG-16
117  srl   a5, a3, 8*SZREG-16
118  sub   a0, a4, a5
119  and   a1, a0, 0xff
120  bnez  a1, 1f
121  ret
122
123.Lmismatch_upper:
124  srl   a4, a4, 8*SZREG-16
125  srl   a5, a5, 8*SZREG-16
126  sub   a0, a4, a5
127  and   a1, a0, 0xff
128  bnez  a1, 1f
129  ret
130
1311:and   a4, a4, 0xff
132  and   a5, a5, 0xff
133  sub   a0, a4, a5
134  ret
135
136#else
137
138#if __riscv_xlen == 64
139  srl   a4, a2, 48
140  srl   a5, a3, 48
141  bne   a4, a5, .Lmismatch_lower
142  srl   a4, a2, 32
143  srl   a5, a3, 32
144  bne   a4, a5, .Lmismatch_lower
145#endif
146  srl   a4, a2, 16
147  srl   a5, a3, 16
148  bne   a4, a5, .Lmismatch_lower
149
150  srl	a4, a2, 8
151  srl   a5, a3, 8
152  bne   a4, a5, 1f
153  and   a4, a2, 0xff
154  and   a5, a3, 0xff
1551:sub	a0, a4, a5
156  ret
157
158.Lmismatch_lower:
159  srl	a2, a4, 8
160  srl   a3, a5, 8
161  bne   a2, a3, 1f
162  and   a2, a4, 0xff
163  and   a3, a5, 0xff
1641:sub	a0, a2, a3
165  ret
166
167#endif
168
169.Lmisaligned:
170  # misaligned
171  lbu   a2, 0(a0)
172  lbu   a3, 0(a1)
173  add   a0, a0, 1
174  add   a1, a1, 1
175  bne   a2, a3, 1f
176  bnez  a2, .Lmisaligned
177
1781:
179  sub   a0, a2, a3
180  ret
181
182  # cases in which a null byte was detected
183#if __riscv_xlen == 32
184  foundnull 0 5
185  foundnull 1 5
186  foundnull 2 5
187  foundnull 3 5
188  foundnull 4 5
189#else
190  foundnull 0 3
191  foundnull 1 3
192  foundnull 2 3
193#endif
194.size	strcmp, .-strcmp
195
196#if SZREG == 8 && !defined(__riscv_zbb)
197.section .srodata.cst8,"aM",@progbits,8
198.align 3
199mask:
200.dword 0x7f7f7f7f7f7f7f7f
201#endif
202#endif
203