8000 musl files that replace functionality in stm/string0.c · micropython/micropython@7990eba · GitHub
[go: up one dir, main page]

Skip to content

Commit 7990eba

Browse files
author
Hagen Kaye
committed
musl files that replace functionality in stm/string0.c
c library functions: memcpy, memmove, memset, strlen, strcmp strncmp, strndup, strcpy, stpcpy, strcat, strnlen
1 parent 347280b commit 7990eba

File tree

12 files changed

+373
-0
lines changed

12 files changed

+373
-0
lines changed

micromusl/src/string/memchr.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <string.h>
2+
#include <stdint.h>
3+
#include <limits.h>
4+
5+
#define SS (sizeof(size_t))
6+
#define ALIGN (sizeof(size_t)-1)
7+
#define ONES ((size_t)-1/UCHAR_MAX)
8+
#define HIGHS (ONES * (UCHAR_MAX/2+1))
9+
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
10+
11+
void *memchr(const void *src, int c, size_t n)
12+
{
13+
const unsigned char *s = src;
14+
c = (unsigned char)c;
15+
for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
16+
if (n && *s != c) {
17+
const size_t *w;
18+
size_t k = ONES * c;
19+
for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
20+
for (s = (const void *)w; n && *s != c; s++, n--);
21+
}
22+
return n ? (void *)s : 0;
23+
}

micromusl/src/string/memcpy.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#include <string.h>
2+
#include <stdint.h>
3+
#include <endian.h>
4+
5+
void *memcpy(void *restrict dest, const void *restrict src, size_t n)
6+
{
7+
unsigned char *d = dest;
8+
const unsigned char *s = src;
9+
10+
#ifdef __GNUC__
11+
12+
#if __BYTE_ORDER == __LITTLE_ENDIAN
13+
#define LS >>
14+
#define RS <<
15+
#else
16+
#define LS <<
17+
#define RS >>
18+
#endif
19+
20+
typedef uint32_t __attribute__((__may_alias__)) u32;
21+
uint32_t w, x;
22+
23+
for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++;
24+
25+
if ((uintptr_t)d % 4 == 0) {
26+
for (; n>=16; s+=16, d+=16, n-=16) {
27+
*(u32 *)(d+0) = *(u32 *)(s+0);
28+
*(u32 *)(d+4) = *(u32 *)(s+4);
29+
*(u32 *)(d+8) = *(u32 *)(s+8);
30+
*(u32 *)(d+12) = *(u32 *)(s+12);
31+
}
32+
if (n&8) {
33+
*(u32 *)(d+0) = *(u32 *)(s+0);
34+
*(u32 *)(d+4) = *(u32 *)(s+4);
35+
d += 8; s += 8;
36+
}
37+
if (n&4) {
38+
*(u32 *)(d+0) = *(u32 *)(s+0);
39+
d += 4; s += 4;
40+
}
41+
if (n&2) {
42+
*d++ = *s++; *d++ = *s++;
43+
}
44+
if (n&1) {
45+
*d = *s;
46+
}
47+
return dest;
48+
}
49+
50+
if (n >= 32) switch ((uintptr_t)d % 4) {
51+
case 1:
52+
w = *(u32 *)s;
53+
*d++ = *s++;
54+
*d++ = *s++;
55+
*d++ = *s++;
56+
n -= 3;
57+
for (; n>=17; s+=16, d+=16, n-=16) {
58+
x = *(u32 *)(s+1);
59+
*(u32 *)(d+0) = (w LS 24) | (x RS 8);
60+
w = *(u32 *)(s+5);
61+
*(u32 *)(d+4) = (x LS 24) | (w RS 8);
62+
x = *(u32 *)(s+9);
63+
*(u32 *)(d+8) = (w LS 24) | (x RS 8);
64+
w = *(u32 *)(s+13);
65+
*(u32 *)(d+12) = (x LS 24) | (w RS 8);
66+
}
67+
break;
68+
case 2:
69+
w = *(u32 *)s;
70+
*d++ = *s++;
71+
*d++ = *s++;
72+
n -= 2;
73+
for (; n>=18; s+=16, d+=16, n-=16) {
74+
x = *(u32 *)(s+2);
75+
*(u32 *)(d+0) = (w LS 16) | (x RS 16);
76+
w = *(u32 *)(s+6);
77+
*(u32 *)(d+4) = (x LS 16) | (w RS 16);
78+
x = *(u32 *)(s+10);
79+
*(u32 *)(d+8) = (w LS 16) | (x RS 16);
80+
w = *(u32 *)(s+14);
81+
*(u32 *)(d+12) = (x LS 16) | (w RS 16);
82+
}
83+
break;
84+
case 3:
85+
w = *(u32 *)s;
86+
*d++ = *s++;
87+
n -= 1;
88+
for (; n>=19; s+=16, d+=16, n-=16) {
89+
x = *(u32 *)(s+3);
90+
*(u32 *)(d+0) = (w LS 8) | (x RS 24);
91+
w = *(u32 *)(s+7);
92+
*(u32 *)(d+4) = (x LS 8) | (w RS 24);
93+
x = *(u32 *)(s+11);
94+
*(u32 *)(d+8) = (w LS 8) | (x RS 24);
95+
w = *(u32 *)(s+15);
96+
*(u32 *)(d+12) = (x LS 8) | (w RS 24);
97+
}
98+
break;
99+
}
100+
if (n&16) {
101+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
102+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
103+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
104+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
105+
}
106+
if (n&8) {
107+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
108+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
109+
}
110+
if (n&4) {
111+
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
112+
}
113+
if (n&2) {
114+
*d++ = *s++; *d++ = *s++;
115+
}
116+
if (n&1) {
117+
*d = *s;
118+
}
119+
return dest;
120+
#endif
121+
122+
for (; n; n--) *d++ = *s++;
123+
return dest;
124+
}

micromusl/src/string/memmove.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <string.h>
2+
#include <stdint.h>
3+
4+
#define WT size_t
5+
#define WS (sizeof(WT))
6+
7+
void *memmove(void *dest, const void *src, size_t n)
8+
{
9+
char *d = dest;
10+
const char *s = src;
11+
12+
if (d==s) return d;
13+
if (s+n <= d || d+n <= s) return memcpy(d, s, n);
14+
15+
if (d<s) {
16+
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
17+
while ((uintptr_t)d % WS) {
18+
if (!n--) return dest;
19+
*d++ = *s++;
20+
}
21+
for (; n>=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(WT *)s;
22+
}
23+
for (; n; n--) *d++ = *s++;
24+
} else {
25+
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
26+
while ((uintptr_t)(d+n) % WS) {
27+
if (!n--) return dest;
28+
d[n] = s[n];
29+
}
30+
while (n>=WS) n-=WS, *(WT *)(d+n) = *(WT *)(s+n);
31+
}
32+
while (n) n--, d[n] = s[n];
33+
}
34+
35+
return dest;
36+
}

micromusl/src/string/memset.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include <string.h>
2+
#include <stdint.h>
3+
4+
void *memset(void *dest, int c, size_t n)
5+
{
6+
unsigned char *s = dest;
7+
size_t k;
8+
9+
/* Fill head and tail with minimal branching. Each
10+
* conditional ensures that all the subsequently used
11+
* offsets are well-defined and in the dest region. */
12+
13+
if (!n) return dest;
14+
s[0] = s[n-1] = c;
15+
if (n <= 2) return dest;
16+
s[1] = s[n-2] = c;
17+
s[2] = s[n-3] = c;
18+
if (n <= 6) return dest;
19+
s[3] = s[n-4] = c;
20+
if (n <= 8) return dest;
21+
22+
/* Advance pointer to align it at a 4-byte boundary,
23+
* and truncate n to a multiple of 4. The previous code
24+
* already took care of any head/tail that get cut off
25+
* by the alignment. */
26+
27+
k = -(uintptr_t)s & 3;
28+
s += k;
29+
n -= k;
30+
n &= -4;
31+
32+
#ifdef __GNUC__
33+
typedef uint32_t __attribute__((__may_alias__)) u32;
34+
typedef uint64_t __attribute__((__may_alias__)) u64;
35+
36+
u32 c32 = ((u32)-1)/255 * (unsigned char)c;
37+
38+
/* In preparation to copy 32 bytes at a time, aligned on
39+
* an 8-byte bounary, fill head/tail up to 28 bytes each.
40+
* As in the initial byte-based head/tail fill, each
41+
* conditional below ensures that the subsequent offsets
42+
* are valid (e.g. !(n<=24) implies n>=28). */
43+
44+
*(u32 *)(s+0) = c32;
45+
*(u32 *)(s+n-4) = c32;
46+
if (n <= 8) return dest;
47+
*(u32 *)(s+4) = c32;
48+
*(u32 *)(s+8) = c32;
49+
*(u32 *)(s+n-12) = c32;
50+
*(u32 *)(s+n-8) = c32;
51+
if (n <= 24) return dest;
52+
*(u32 *)(s+12) = c32;
53+
*(u32 *)(s+16) = c32;
54+
*(u32 *)(s+20) = c32;
55+
*(u32 *)(s+24) = c32;
56+
*(u32 *)(s+n-28) = c32;
57+
*(u32 *)(s+n-24) = c32;
58+
*(u32 *)(s+n-20) = c32;
59+
*(u32 *)(s+n-16) = c32;
60+
61+
/* Align to a multiple of 8 so we can fill 64 bits at a time,
62+
* and avoid writing the same bytes twice as much as is
63+
* practical without introducing additional branching. */
64+
65+
k = 24 + ((uintptr_t)s & 4);
66+
s += k;
67+
n -= k;
68+
69+
/* If this loop is reached, 28 tail bytes have already been
70+
* filled, so any remainder when n drops below 32 can be
71+
* safely ignored. */
72+
73+
u64 c64 = c32 | ((u64)c32 << 32);
74+
for (; n >= 32; n-=32, s+=32) {
75+
*(u64 *)(s+0) = c64;
76+
*(u64 *)(s+8) = c64;
77+
*(u64 *)(s+16) = c64;
78+
*(u64 *)(s+24) = c64;
79+
}
80+
#else
81+
/* Pure C fallback with no aliasing violations. */
82+
for (; n; n--, s++) *s = c;
83+
#endif
84+
85+
return dest;
86+
}

micromusl/src/string/stpcpy.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <string.h>
2+
#include <stdint.h>
3+
#include <limits.h>
4+
#include "libc.h"
5+
6+
#define ALIGN (sizeof(size_t))
7+
#define ONES ((size_t)-1/UCHAR_MAX)
8+
#define HIGHS (ONES * (UCHAR_MAX/2+1))
9+
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
10+
11+
char *__stpcpy(char *restrict d, const char *restrict s)
12+
{
13+
size_t *wd;
14+
const size_t *ws;
15+
16+
if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
17+
for (; (uintptr_t)s % ALIGN; s++, d++)
18+
if (!(*d=*s)) return d;
19+
wd=(void *)d; ws=(const void *)s;
20+
for (; !HASZERO(*ws); *wd++ = *ws++);
21+
d=(void *)wd; s=(const void *)ws;
22+
}
23+
for (; (*d=*s); s++, d++);
24+
25+
return d;
26+
}
27+
28+
weak_alias(__stpcpy, stpcpy);

micromusl/src/string/strcat.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <string.h>
2+
3+
char *strcat(char *restrict dest, const char *restrict src)
4+
{
5+
strcpy(dest + strlen(dest), src);
6+
return dest;
7+
}

micromusl/src/string/strcmp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <string.h>
2+
3+
int strcmp(const char *l, const char *r)
4+
{
5+
for (; *l==*r && *l; l++, r++);
6+
return *(unsigned char *)l - *(unsigned char *)r;
7+
}

micromusl/src/string/strcpy.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <string.h>
2+
3+
char *__stpcpy(char *, const char *);
4+
5+
char *strcpy(char *restrict dest, const char *restrict src)
6+
{
7+
#if 1
8+
__stpcpy(dest, src);
9+
return dest;
10+
#else
11+
const unsigned char *s = src;
12+
unsigned char *d = dest;
13+
while ((*d++ = *s++));
14+
return dest;
15+
#endif
16+
}

micromusl/src/string/strlen.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <string.h>
2+
#include <stdint.h>
3+
#include <limits.h>
4+
5+
#define ALIGN (sizeof(size_t))
6+
#define ONES ((size_t)-1/UCHAR_MAX)
7+
#define HIGHS (ONES * (UCHAR_MAX/2+1))
8+
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
9+
10+
size_t strlen(const char *s)
11+
{
12+
const char *a = s;
13+
const size_t *w;
14+
for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
15+
for (w = (const void *)s; !HASZERO(*w); w++);
16+
for (s = (const void *)w; *s; s++);
17+
return s-a;
18+
}

micromusl/src/string/strncmp.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <string.h>
2+
3+
int strncmp(const char *_l, const char *_r, size_t n)
4+
{
5+
const unsigned char *l=(void *)_l, *r=(void *)_r;
6+
if (!n--) return 0;
7+
for (; *l && *r && n && *l == *r ; l++, r++, n--);
8+
return *l - *r;
9+
}

micromusl/src/string/strndup.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <stdlib.h>
2+
#include <string.h>
3+
4+
char *strndup(const char *s, size_t n)
5+
{
6+
size_t l = strnlen(s, n);
7+
char *d = malloc(l+1);
8+
if (!d) return NULL;
9+
memcpy(d, s, l);
10+
d[l] = 0;
11+
return d;
12+
}

micromusl/src/string/strnlen.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <string.h>
2+
3+
size_t strnlen(const char *s, size_t n)
4+
{
5+
const char *p = memchr(s, 0, n);
6+
return p ? p-s : n;
7+
}

0 commit comments

Comments
 (0)
0