1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2021 Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #define _GNU_SOURCE
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <limits.h>
41 #include <stdint.h>
42
43 #ifdef __arm__
44 void *__aeabi_memset(void *dest, size_t n, int c);
45 void *__aeabi_memset4(void *dest, size_t n, int c);
46 void *__aeabi_memset8(void *dest, size_t n, int c);
47 void __aeabi_memclr(void *dest, size_t n);
48 void __aeabi_memclr4(void *dest, size_t n);
49 void __aeabi_memclr8(void *dest, size_t n);
50 #endif
51
52 static uint8_t crc_table[256];
53
54 static uint8_t
crc8(uint8_t c)55 crc8(uint8_t c)
56 {
57 int i;
58 for (i = 0; i < 8; i++) {
59 if (c & 1)
60 c = 0x31 ^ (c >> 1);
61 else
62 c >>= 1;
63 }
64 return c;
65 }
66
67 static void
init_crc(void)68 init_crc(void)
69 {
70 int i;
71 for (i = 0; i < 256; i++)
72 crc_table[i] = crc8((uint8_t) i);
73 }
74
75 static char
expect(size_t pos)76 expect(size_t pos)
77 {
78 unsigned int i;
79 uint8_t c = 0xff;
80 for (i = 0; i < sizeof(size_t); i++)
81 c ^= crc_table[(uint8_t) (pos >> (i * 8))];
82 return (char) c;
83 }
84
85 size_t
check(char * label,void * buf,size_t size,size_t start,size_t end,int c)86 check(char *label, void *buf, size_t size, size_t start, size_t end, int c)
87 {
88 size_t p;
89 size_t error = 0;
90 char *b = buf;
91
92 for (p = 0; p < size; p++) {
93 char g = b[p];
94 char e = c;
95 if (p < start || end <= p)
96 e = expect(p);
97 if (g != e) {
98 fprintf(stderr, "%s(%zu, %zu):%zu expect 0x%02x got 0x%02x\n",
99 label, start, end, p, (uint8_t) e, (uint8_t) g);
100 error++;
101 }
102 }
103 return error;
104 }
105
106 size_t
randrange(size_t max)107 randrange(size_t max)
108 {
109 size_t pot;
110 size_t rnd;
111
112 for (pot = 1; pot && pot < max; pot <<= 1)
113 ;
114
115 for (;;) {
116 rnd = random() & (pot - 1);
117 if (rnd < max)
118 return rnd;
119 }
120 }
121
122
123 #define MAX_BUF 1024
124
125 #define NEND 64
126 #define NSTART 64
127
128 static char buf[MAX_BUF];
129
130 static void
fill(void)131 fill(void)
132 {
133 size_t p;
134
135 for (p = 0; p < MAX_BUF; p++)
136 buf[p] = expect(p);
137 }
138
139 static size_t
test(size_t start,size_t end,int c)140 test(size_t start, size_t end, int c)
141 {
142 size_t error = 0;
143 char *b = buf;
144 fill();
145 memset(b + start, c, end - start);
146 error += check("memset", buf, MAX_BUF, start, end, c);
147
148 fill();
149 bzero(b + start, end - start);
150 error += check("bzero", buf, MAX_BUF, start, end, 0);
151
152 #ifdef __arm__
153 fill();
154 __aeabi_memset(b + start, end - start, c);
155 error += check("__aeabi_memset", buf, MAX_BUF, start, end, c);
156
157 fill();
158 __aeabi_memclr(b + start, end - start);
159 error += check("__aeabi_memclr", buf, MAX_BUF, start, end, 0);
160
161 start &= ~3;
162 end &= ~3;
163
164 fill();
165 __aeabi_memset4(b + start, end - start, c);
166 error += check("__aeabi_memset4", buf, MAX_BUF, start, end, c);
167
168 fill();
169 __aeabi_memclr4(b + start, end - start);
170 error += check("__aeabi_memclr4", buf, MAX_BUF, start, end, 0);
171
172 start &= ~7;
173 end &= ~7;
174
175 fill();
176 __aeabi_memset8(b + start, end - start, c);
177 error += check("__aeabi_memset8", buf, MAX_BUF, start, end, c);
178
179 fill();
180 __aeabi_memclr8(b + start, end - start);
181 error += check("__aeabi_memclr8", buf, MAX_BUF, start, end, 0);
182 #endif
183
184 return error;
185
186 }
187
188 int
main(void)189 main(void)
190 {
191 size_t error;
192 size_t end;
193 size_t start;
194
195 int nend;
196 int nstart;
197 int ret = 0;
198
199 init_crc();
200 for (nend = 0; nend < NEND; nend++) {
201 end = randrange(MAX_BUF + 1);
202 for (nstart = 0; nstart < NSTART; nstart++) {
203 start = randrange(end + 1);
204 int c = randrange(INT_MAX);
205 error = test(start, end, c);
206 if (error)
207 ret = 1;
208 }
209 }
210
211 return ret;
212 }
213