mirror of
https://github.com/ivoszbg/uniLoader.git
synced 2025-09-18 05:00:10 +00:00
With support for this board also come the following changes: - rework blobs handling to get past the 0 size bug - basic cpu "set up" in start.S - assembly memcpy - uart debugging
109 lines
2.9 KiB
C
109 lines
2.9 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
/*
|
|
* Copyright (c) 2024, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
|
*/
|
|
|
|
#ifndef STRING_H_ /* Include guard */
|
|
#define STRING_H_
|
|
|
|
#include "stddef.h"
|
|
#include "stdint.h"
|
|
|
|
#define LBLOCKSIZE (sizeof(long))
|
|
#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
|
|
#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
|
|
|
|
// C-driven unoptimized functions
|
|
int memcmp (const void *s1, const void *s2, size_t n);
|
|
void *memchr (const void *s, int c, size_t n);
|
|
char *strcpy (char *s1, const char *s2);
|
|
char *strncpy (char *d, char *s, long n);
|
|
char *strcat (char *d, char *s);
|
|
int strcmp (const char *s1, const char *s2);
|
|
int strncmp (const char *s1, const char *s2, size_t n);
|
|
size_t strlen (const char *s);
|
|
size_t strnlen (const char *s, size_t n);
|
|
char *strchr (const char *s, int c);
|
|
char *strrchr (const char *s, int c);
|
|
long atol (const char *s);
|
|
void writel (unsigned int value, void* address);
|
|
uint32_t readl(volatile uint32_t *addr);
|
|
|
|
// C-driven optimized functions
|
|
void *memset (void *m, int c, size_t n);
|
|
|
|
/* Nonzero if either X or Y is not aligned on a "long" boundary. */
|
|
#define UNALIGNED_CPY(X, Y) (((long)X & (sizeof (long) - 1)) | \
|
|
((long)Y & (sizeof (long) - 1)))
|
|
|
|
/* How many bytes are copied each iteration of the 4X unrolled loop. */
|
|
#define BIGBLOCKSIZE (sizeof(long) << 2)
|
|
|
|
static void *__optimized_memcpy (void *dst0, const void *src0, size_t len0) __attribute__((unused));
|
|
static void *__optimized_memcpy (void *dst0, const void *src0, size_t len0)
|
|
{
|
|
char *dst = dst0;
|
|
const char *src = src0;
|
|
long *aligned_dst;
|
|
const long *aligned_src;
|
|
|
|
/* If the size is small, or either SRC or DST is unaligned,
|
|
then punt into the byte copy loop. This should be rare. */
|
|
if (!(((len0) < BIGBLOCKSIZE)) && !UNALIGNED_CPY (src, dst)) {
|
|
aligned_dst = (long*)dst;
|
|
aligned_src = (long*)src;
|
|
/* Copy 4X long words at a time if possible. */
|
|
while (len0 >= BIGBLOCKSIZE) {
|
|
*aligned_dst++ = *aligned_src++;
|
|
*aligned_dst++ = *aligned_src++;
|
|
*aligned_dst++ = *aligned_src++;
|
|
*aligned_dst++ = *aligned_src++;
|
|
len0 -= BIGBLOCKSIZE;
|
|
}
|
|
/* Copy one long word at a time if possible. */
|
|
while (len0 >= LBLOCKSIZE) {
|
|
*aligned_dst++ = *aligned_src++;
|
|
len0 -= LBLOCKSIZE;
|
|
}
|
|
|
|
/* Pick up any residual with a byte copier. */
|
|
dst = (char*)aligned_dst;
|
|
src = (char*)aligned_src;
|
|
}
|
|
|
|
while (len0--)
|
|
*dst++ = *src++;
|
|
return dst0;
|
|
}
|
|
|
|
// Assembly-driven functions
|
|
#ifdef __aarch64__
|
|
|
|
void *memcpy (void *__restrict, const void *__restrict, size_t);
|
|
void *memmove (void *, const void *, size_t);
|
|
|
|
#elif __arm__
|
|
|
|
void *__memcpy_arm (void *__restrict, const void *__restrict, size_t);
|
|
#define memcpy __memcpy_arm
|
|
|
|
#endif
|
|
|
|
static inline int tolower (int c)
|
|
{
|
|
if (c >= 'A' && c <= 'Z')
|
|
return c - 'A' + 'a';
|
|
else
|
|
return c;
|
|
}
|
|
|
|
static inline int toupper (int c)
|
|
{
|
|
if (c >= 'a' && c <= 'z')
|
|
return c - 'a' + 'A';
|
|
else
|
|
return c;
|
|
}
|
|
|
|
#endif // STRING_H_
|