more bpmpfw shenanigans

This commit is contained in:
souldbminersmwc committed 2026-08-25 13:37:05 -04:00
1 parent 7660650129
commit b20d20edff
54 files changed
+1275 -30

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-2016 Jurģis Brigmanis <velko.x@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,6 @@
#ifndef _STD_ASSERT_H
#define _STD_ASSERT_H
#include "fslc/fslc_assert.h"
#endif /* _STD_ASSERT_H */
@@ -0,0 +1,35 @@
#ifndef FSLC_ASSERT_H
#define FSLC_ASSERT_H
#ifndef ALT_FSLC_NAMES
#define fslc_assert assert
#endif /* ALT_FSLC_NAMES */
#ifdef NDEBUG
#define fslc_assert(expr) ((void)0)
#else /* NDEBUG */
/* Note: __PRETTY_FUNCTION__ is GCC specific */
#define fslc_assert(expr) ((expr) ? (void)0 : __fslc_assert_fail(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__))
#endif /* NDEBUG */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void __fslc_assert_fail(const char *expr, const char *file, unsigned int line, const char *func);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FSLC_ASSERT_H */
@@ -0,0 +1,74 @@
#ifndef FSLC_STDIO_H
#define FSLC_STDIO_H
#include <stdarg.h>
#include <stddef.h>
#ifndef ALT_FSLC_NAMES
#define FSLC_FILE FILE
#define fslc_stdout stdout
#define fslc_stdin stdin
#define fslc_putchar putchar
#define fslc_fputc fputc
#define fslc_fputs fputs
#define fslc_puts puts
#define fslc_vfprintf vfprintf
#define fslc_vprintf vprintf
#define fslc_fprintf fprintf
#define fslc_printf printf
#define fslc_fwrite fwrite
#define fslc_fread fread
#define fslc_getc getc
#define fslc_getchar getchar
#define fslc_ungetc ungetc
#define fslc_fgets fgets
#endif /* ALT_FSLC_NAMES */
typedef struct _FSLC_FILE FSLC_FILE;
struct _FSLC_FILE
{
void *user_ptr;
int (*putc)(int c, FSLC_FILE *stream);
int (*getc)(FSLC_FILE *stream);
void (*pre_output)(FSLC_FILE *stream);
void (*post_output)(FSLC_FILE *stream);
int ungetc_buf;
};
extern FSLC_FILE *fslc_stdout;
extern FSLC_FILE *fslc_stdin;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int fslc_putchar(int c);
int fslc_fputc(int c, FSLC_FILE *stream);
int fslc_fputs(const char *str, FSLC_FILE *stream);
int fslc_puts(const char *str);
int fslc_vfprintf(FSLC_FILE *stream, const char *format, va_list arg);
int fslc_vprintf(const char *format, va_list arg);
int fslc_fprintf(FSLC_FILE *stream, const char *format, ...);
int fslc_printf(const char *format, ...);
size_t fslc_fwrite(const void *ptr, size_t size, size_t count, FSLC_FILE *stream);
size_t fslc_fread(void *ptr, size_t size, size_t count, FSLC_FILE *stream);
int fslc_getc(FSLC_FILE *stream);
int fslc_getchar(void);
int fslc_ungetc(int c, FSLC_FILE *stream);
char *fslc_fgets(char *str, int num, FSLC_FILE *stream);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FSLC_STDIO_H */
@@ -0,0 +1,25 @@
#ifndef FSLC_STDLIB_H
#define FSLC_STDLIB_H
#include <stddef.h>
#ifndef ALT_FSLC_NAMES
#define fslc_bsearch bsearch
#endif /* ALT_FSLC_NAMES */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void *fslc_bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *));
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FSLC_STDLIB_H */
@@ -0,0 +1,50 @@
#ifndef FSLC_STRING_H
#define FSLC_STRING_H
#include <stddef.h>
#ifndef ALT_FSLC_NAMES
#define fslc_memset memset
#define fslc_memcpy memcpy
#define fslc_memmove memmove
#define fslc_memcmp memcmp
#define fslc_strlen strlen
#define fslc_strcpy strcpy
#define fslc_strncpy strncpy
#define fslc_strcmp strcmp
#define fslc_strncmp strncmp
#define fslc_strchr strchr
#define fslc_strstr strstr
#define fslc_strpbrk strpbrk
#define fslc_strspn strspn
#define fslc_strtok_r strtok_r
#endif /* ALT_FSLC_NAMES */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void *fslc_memset(void *ptr, int value, size_t num);
void *fslc_memcpy(void *dest, const void *src, size_t len);
void *fslc_memmove(void *dest, const void *src, size_t len);
int fslc_memcmp(const void *ptr1, const void *ptr2, size_t num);
size_t fslc_strlen(const char *str);
char *fslc_strcpy(char *dest, const char *src);
char *fslc_strncpy(char *dest, const char *src, size_t len);
int fslc_strcmp(const char *str1, const char *str2);
int fslc_strncmp(const char *str1, const char *str2, size_t num);
char *fslc_strchr(const char *str, int c);
char *fslc_strstr(const char *search_in, const char *search_for);
char *fslc_strpbrk(const char *str, const char *delim);
size_t fslc_strspn(const char *str, const char *delim);
char *fslc_strtok_r(char *str, const char *delim, char **save_p);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FSLC_STRING_H */
@@ -0,0 +1,23 @@
#ifndef FSLC_STDLIBX_H
#define FSLC_STDLIBX_H
#include <stddef.h>
#ifndef ALT_FSLC_NAMES
#define fslc_bsearch_i bsearch_i
#endif /* ALT_FSLC_NAMES */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int fslc_bsearch_i(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *));
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FSLC_STDLIBX_H */
@@ -0,0 +1,33 @@
#ifndef FSLC_STRINGX_H
#define FSLC_STRINGX_H
#include <stddef.h>
#ifndef ALT_FSLC_NAMES
#define fslc_memset_l memset_l
#define fslc_strcpy_e strcpy_e
#define fslc_strncpy_e strncpy_e
#endif /* ALT_FSLC_NAMES */
#if __SIZEOF_LONG__ == 4
#define memset_32 memset_l
#elif __SIZEOF_LONG__ == 8
#define memset_32(A, V, S) memset_l(A, (((unsigned long)(V)<<32)|(V)), S)
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void *fslc_memset_l(void *ptr, unsigned long value, size_t num);
char *fslc_strcpy_e(char *dest, const char *src);
char *fslc_strncpy_e(char *dest, const char *src, size_t len);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FSLC_STRINGX_H */
@@ -0,0 +1,6 @@
#ifndef _STD_STDIO_H
#define _STD_STDIO_H
#include "fslc/fslc_stdio.h"
#endif /* _STD_STDIO_H */
@@ -0,0 +1,6 @@
#ifndef _STD_STDLIB_H
#define _STD_STDLIB_H
#include "fslc/fslc_stdlib.h"
#endif /* _STD_STDLIB_H */
@@ -0,0 +1,6 @@
#ifndef _STD_STRING_H
#define _STD_STRING_H
#include "fslc/fslc_string.h"
#endif /* _STD_STRING_H */
@@ -0,0 +1,12 @@
#include "fslc_stdlib.h"
#include "stdlibx.h"
void *fslc_bsearch(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *))
{
int sidx = fslc_bsearch_i(key, base, num, size, cmp_proc);
if (sidx < 0)
return NULL;
return (char *)base + (sidx * size);
}
@@ -0,0 +1,31 @@
#include <stddef.h>
int fslc_bsearch_i(const void *key, const void *base, size_t num, size_t size, int (*cmp_proc)(const void *, const void *))
{
int lo = 0;
int hi = num - 1;
char *cbase = (char *)base;
while (lo <= hi)
{
int i = lo + ((hi - lo) >> 1);
char *ptr = cbase + (i * size);
int cmp = cmp_proc(key, ptr);
if (cmp == 0)
return i;
if (cmp > 0)
{
lo = i + 1;
}
else
{
hi = i - 1;
}
}
return ~lo;
}
@@ -0,0 +1,10 @@
#include "fslc_stdio.h"
int fslc_fprintf(FSLC_FILE *stream, const char *format, ...)
{
va_list args;
va_start(args, format);
int r = fslc_vfprintf(stream, format, args);
va_end(args);
return r;
}
@@ -0,0 +1,12 @@
#include "fslc_stdio.h"
int fslc_fputc(int c, FSLC_FILE *stream)
{
if (stream->pre_output) stream->pre_output(stream);
int r = stream->putc(c, stream);
if (stream->post_output) stream->post_output(stream);
return r;
}
@@ -0,0 +1,15 @@
#include "fslc_stdio.h"
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream);
int fslc_fputs(const char *str, FSLC_FILE *stream)
{
if (stream->pre_output) stream->pre_output(stream);
int r = _fslc_fputs_impl(str, stream);
if (stream->post_output) stream->post_output(stream);
return r;
}
@@ -0,0 +1,13 @@
#include "fslc_stdio.h"
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream)
{
int res = 0;
for (;*str; ++str)
{
int pr = stream->putc(*str, stream);
if (pr < 0) return pr;
++res;
}
return res;
}
@@ -0,0 +1,38 @@
#include "fslc_string.h"
#include <stdint.h>
int fslc_memcmp(const void *ptr1, const void *ptr2, size_t num)
{
unsigned char *b_p1 = (unsigned char *)ptr1;
unsigned char *b_p2 = (unsigned char *)ptr2;
for (;((uintptr_t)b_p1 & (sizeof(long)-1)) && num > 0; ++b_p1, ++b_p2, --num)
{
if (*b_p1 != *b_p2)
{
return *b_p1 > *b_p2 ? 1 : -1;
}
}
unsigned long *w_p1 = (unsigned long *)b_p1;
unsigned long *w_p2 = (unsigned long *)b_p2;
for (;num >= sizeof(unsigned long); ++w_p1, ++w_p2, num -= sizeof(unsigned long))
{
if (*w_p1 != *w_p2)
{
return *w_p1 > *w_p2 ? 1 : -1;
}
}
b_p1 = (unsigned char *)w_p1;
b_p2 = (unsigned char *)w_p2;
for (; num > 0; ++b_p1, ++b_p2, --num)
{
if (*b_p1 != *b_p2)
{
return *b_p1 > *b_p2 ? 1 : -1;
}
}
return 0;
}
@@ -0,0 +1,40 @@
#include "fslc_string.h"
#include <stdint.h>
void *fslc_memcpy(void *dest, const void *src, size_t len)
{
/* Copy byte-by-byte up to word-aligned.
*
* There's a possibility, that src and dest have different offsets
* to word boundary and can not both be used efficiently.
*
* In this case we use align to dest argument, because it then can be
* written in one operation, instead of read-modify-write of 2 words.
*
* Most of the time both parameters should be word-aligned, however.
*/
unsigned char *b_src = (unsigned char *)src;
unsigned char *b_dst = (unsigned char *)dest;
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && len > 0; b_src++, b_dst++, len--)
{
*b_dst = *b_src;
}
/* Then all word-aligned */
unsigned long *w_src = (unsigned long*)b_src;
unsigned long *w_dst = (unsigned long*)b_dst;
for (;len >= sizeof(unsigned long); w_src++, w_dst++, len -= sizeof(unsigned long))
{
*w_dst = *w_src;
}
/* And byte-by-byte the rest */
b_src = (unsigned char *)w_src;
b_dst = (unsigned char *)w_dst;
for (; len > 0; b_src++, b_dst++, len--)
{
*b_dst = *b_src;
}
return dest;
}
@@ -0,0 +1,69 @@
#include "fslc_string.h"
#include <stdint.h>
void *fslc_memmove(void *dest, const void *src, size_t len)
{
unsigned char *b_dst = (unsigned char *)dest;
unsigned char *b_src = (unsigned char *)src;
/* Need to check if memory regions overlaps. Then if the dest address is
* larger than source, we need to copy backwards (or else source regions
* ending will be overwritten by writes to dest, before they are read).
*
* In other cases it works identically as memcpy(). Same considerations
* about address alignment applies here.
*/
if ( b_dst < b_src + len && b_dst > b_src)
{
b_src += len;
b_dst += len;
/* Byte-by-byte down to word-aligned. */
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && len > 0; )
{
b_src--, b_dst--, len--;
*b_dst = *b_src;
}
/* Then all word-aligned */
unsigned long *w_src = (unsigned long*)b_src;
unsigned long *w_dst = (unsigned long*)b_dst;
for (;len >= sizeof(unsigned long); )
{
w_src--, w_dst--, len -= sizeof(unsigned long);
*w_dst = *w_src;
}
/* And byte-by-byte the rest */
b_src = (unsigned char *)w_src;
b_dst = (unsigned char *)w_dst;
for (; len > 0; )
{
b_src--, b_dst--, len--;
*b_dst = *b_src;
}
} else {
/* Byte-by-byte up to word-aligned. */
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && len > 0; b_src++, b_dst++, len--)
{
*b_dst = *b_src;
}
/* Then all word-aligned */
unsigned long *w_src = (unsigned long *)b_src;
unsigned long *w_dst = (unsigned long *)b_dst;
for (;len >= sizeof(unsigned long); w_src++, w_dst++, len -= sizeof(unsigned long))
{
*w_dst = *w_src;
}
/* And byte-by-byte the rest */
b_src = (unsigned char *)w_src;
b_dst = (unsigned char *)w_dst;
for (; len > 0; b_src++, b_dst++, len--)
{
*b_dst = *b_src;
}
}
return dest;
}
@@ -0,0 +1,22 @@
#include "fslc_string.h"
#include "stringx.h"
void *fslc_memset(void *ptr, int value, size_t num)
{
/* Will use memset_l() to actually fill the memory region. If value is non-zero, we need
* to replicate lowest byte to all the long's bytes.
*/
if (value)
{
unsigned char c_val = value;
unsigned long l_val = (c_val << 0) | (c_val << 8) | (c_val << 16) | (c_val << 24);
#if __SIZEOF_LONG__ == 8
l_val |= l_val << 32;
#endif
return fslc_memset_l(ptr, l_val, num);
}
else
return fslc_memset_l(ptr, value, num);
}
@@ -0,0 +1,31 @@
#include "stringx.h"
#include <stdint.h>
void *fslc_memset_l(void *ptr, unsigned long value, size_t num)
{
unsigned char *b_src = (unsigned char *)&value;
unsigned char *b_dst = (unsigned char *)ptr;
/* Byte by byte - to aligned word address */
b_src += ((uintptr_t)b_dst & (sizeof(unsigned long)-1));
for (;((uintptr_t)b_dst & (sizeof(unsigned long)-1)) && num > 0; b_dst++,b_src++,num--)
{
*b_dst = *b_src;
}
/* All aligned */
unsigned long *w_dst = (unsigned long *)b_dst;
for (;num >= sizeof(unsigned long); w_dst++,num -= sizeof(unsigned long))
{
*w_dst= value;
}
/* Unaligned ending */
b_src = (unsigned char *)&value;
b_dst = (unsigned char *)w_dst;
for (; num > 0; b_dst++,b_src++,num--)
{
*b_dst = *b_src;
}
return ptr;
}
@@ -0,0 +1,10 @@
#include "fslc_stdio.h"
int fslc_printf(const char *format, ...)
{
va_list args;
va_start(args, format);
int r = fslc_vfprintf(fslc_stdout, format, args);
va_end(args);
return r;
}
@@ -0,0 +1,6 @@
#include "fslc_stdio.h"
int fslc_putchar(int c)
{
return fslc_fputc(c, fslc_stdout);
}
@@ -0,0 +1,21 @@
#include "fslc_stdio.h"
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream);
int fslc_puts(const char *str)
{
if (fslc_stdout->pre_output) fslc_stdout->pre_output(fslc_stdout);
int r = _fslc_fputs_impl(str, fslc_stdout);
if (r >= 0)
{
int nlr = fslc_stdout->putc('\n', fslc_stdout);
if (nlr < 0)
r = nlr;
}
if (fslc_stdout->post_output) fslc_stdout->post_output(fslc_stdout);
return r;
}
@@ -0,0 +1,3 @@
#include "fslc_stdio.h"
FSLC_FILE *fslc_stdout;
@@ -0,0 +1,10 @@
#include "fslc_string.h"
char *fslc_strchr(const char *str, int c)
{
for (;*str; ++str)
if (*str == c)
return (char *)str;
return NULL;
}
@@ -0,0 +1,8 @@
#include "fslc_string.h"
int fslc_strcmp(const char *str1, const char *str2)
{
for( ; *str1 && *str1 == *str2; ++str1, ++str2);
return *((unsigned char *)str1) - *((unsigned char *)str2);
}
@@ -0,0 +1,8 @@
#include "fslc_string.h"
#include "stringx.h"
char *fslc_strcpy(char *dest, const char *src)
{
fslc_strcpy_e(dest, src);
return dest;
}
@@ -0,0 +1,10 @@
#include "stringx.h"
char *fslc_strcpy_e(char *dest, const char *src)
{
for(; *src; ++src, ++dest)
*dest = *src;
*dest = 0;
return dest;
}
@@ -0,0 +1,9 @@
#include "fslc_string.h"
size_t fslc_strlen(const char *str)
{
size_t res = 0;
for(; *str; ++str) ++res;
return res;
}
@@ -0,0 +1,8 @@
#include "fslc_string.h"
int fslc_strncmp(const char *str1, const char *str2, size_t num)
{
for( ; *str1 && *str1 == *str2 && num > 1; ++str1, ++str2, --num);
return *((unsigned char *)str1) - *((unsigned char *)str2);
}
@@ -0,0 +1,9 @@
#include "fslc_string.h"
char *_fslc_strncpy_impl(char *dest, const char *src, size_t len);
char *fslc_strncpy(char *dest, const char *src, size_t len)
{
_fslc_strncpy_impl(dest, src, len);
return dest;
}
@@ -0,0 +1,9 @@
#include "stringx.h"
char *_fslc_strncpy_impl(char *dest, const char *src, size_t len);
char *fslc_strncpy_e(char *dest, const char *src, size_t len)
{
char *r = _fslc_strncpy_impl(dest, src, len);
return *r ? r + 1: r;
}
@@ -0,0 +1,10 @@
#include <stddef.h>
char *_fslc_strncpy_impl(char *dest, const char *src, size_t len)
{
for(; *src && len > 1; ++src, ++dest, --len)
*dest = *src;
*dest = *src;
return dest;
}
@@ -0,0 +1,14 @@
#include "fslc_string.h"
char *fslc_strpbrk(const char *str, const char *delim)
{
for (; *str; ++str)
{
const char *d;
for (d = delim; *d; ++d)
if (*str == *d)
return (char *)str;
}
return NULL;
}
@@ -0,0 +1,18 @@
#include "fslc_string.h"
size_t fslc_strspn(const char *str, const char *delim)
{
size_t r;
for (r = 0; *str; ++str, ++r)
{
const char *d;
for (d = delim; *d; ++d)
if (*str == *d) // skip to next if found
break;
if (*d == 0) // inner loop exited on \0 - char was not there
break;
}
return r;
}
@@ -0,0 +1,23 @@
#include "fslc_string.h"
char *fslc_strstr(const char *search_in, const char *search_for)
{
while (*search_in)
{
char *rc = fslc_strchr(search_in, search_for[0]); // find first char
if (rc)
{
const char *si = rc + 1, *sf = search_for + 1; // search strcmp-style from second char
for( ; *si && *si == *sf; ++si, ++sf);
if (*sf == 0) return rc; // end of search-for - found result
search_in = rc + 1; // not this one, continue from next char
}
else
return NULL; // did not find first char - exit
}
return NULL; // reached end of source - did not find
}
@@ -0,0 +1,27 @@
#include "fslc_string.h"
char *fslc_strtok_r(char *str, const char *delim, char **save_p)
{
if (str)
*save_p = str;
if (*save_p == NULL)
return NULL;
char *r = *save_p + fslc_strspn(*save_p, delim);
char *p = fslc_strpbrk(r, delim);
if (p)
{
*(p++) = 0;
*save_p = p;
}
else
{
if (*r == 0) r = NULL;
*save_p = NULL;
}
return r;
}
@@ -0,0 +1,347 @@
#include "fslc_stdio.h"
/* There'a a funny behaviour of va_list and va_arg() macros:
* - on x86_64 compiler generates a branch of some sort for each va_arg() macro. Normally it is not a problem,
* however it kinda screws up branch coverage analysis. Therefore I decided to move va_arg() accesses into
* dedicated functions, minimizing the issue to one untaken branch per access function.
* - passing va_list by value works fine on x86_64, but makes some tests to fail on i386. It seems that modifications
* done by va_arg() is not passed back to caller. Subsequent calls to va_arg() or access functions returns wrong
* values on that platform.
* - OK, then. Let's pass pointer to va_list instead. Not so fast. Works fine on i386, but fails to compile on
* x86_64. Fine! Wrapping va_list into a dedicated struct and passing around pointer to it.
*
* Why such a fuss about a few untaken branches in tests? Well, just because! Also, if I ever decide to refactor
* _fslc_vfprintf_impl() - the case statement is getting a bit long and messy, it should make things easier if
* argument list can be passed around freely (as opposed to using it from single function).
*/
struct va_list_w
{
va_list arg;
};
/* Prototype for printf's internal implementation */
static int _fslc_vfprintf_impl(FSLC_FILE *stream, const char *format, struct va_list_w *args);
/* Main exported function */
int fslc_vfprintf(FSLC_FILE *stream, const char *format, va_list arg)
{
if (stream->pre_output) stream->pre_output(stream);
struct va_list_w argw;
va_copy(argw.arg, arg); // can not assign directly, should make a copy
int res = _fslc_vfprintf_impl(stream, format, &argw);
va_end(argw.arg); // and free it after use
if (stream->post_output) stream->post_output(stream);
return res;
}
/* Prototype to private FSLIBC function - implemented elsewhere */
int _fslc_fputs_impl(const char *str, FSLC_FILE *stream);
/* Prototypes for internal functions */
static int _fslc_put_sint_l(signed long v, FSLC_FILE *stream);
static int _fslc_put_uint_l(unsigned long v, FSLC_FILE *stream);
static int _fslc_put_hex_l(unsigned long v, FSLC_FILE *stream, char alpha);
static int _get_sint_arg(struct va_list_w *arg);
static unsigned _get_uint_arg(struct va_list_w *arg);
static long long _get_slonglong_arg(struct va_list_w *arg);
static unsigned long long _get_ulonglong_arg(struct va_list_w *arg);
static void *_get_ptr_arg(struct va_list_w *arg);
/* There are some considerations when formatting Integers for output:
* - on 32-bit systems integers will mostly be 32 bits long, except when one REALLY
* wants to print long long. It should be more optimal to use 32-bit calculations
* when possible and invoke 64-bit only when needed. To support that we provide 2
* separate implementations.
* - on 64-bit systems may be 32 or 64 bits, but there is no real benefit from
* using shorter bit size. Hence common implementation.
* - this library does not aim to support systems with shorter integer sizes (like 16-bit)
* but it it did, it would probably make sense to provide optimized ports for these cases
* as well.
*
* Buffer size calculations:
* Max UInt32 fits in 10 bytes (+1 for zero terminator) decimal
* 2**32 - 1 == 4294967295z
* FFFFFFFFz
* 01234567890
*
* Max UInt64 fits in 10 bytes (and +1 for \0)
* 2**64 -1 == 18446744073709551615z
* FFFFFFFFFFFFFFFFz
* 012345678901234567890
*/
#define BUFSIZE_LONG_LONG_DECIMAL 20
#define BUFSIZE_LONG_HEX (__SIZEOF_LONG__ * 2)
#define BUFSIZE_LONG_LONG_HEX (__SIZEOF_LONG_LONG__ * 2)
#if __SIZEOF_LONG__ == 4
#define BUFSIZE_LONG_DECIMAL 10
static int _fslc_put_sint_ll(signed long long v, FSLC_FILE *stream);
static int _fslc_put_uint_ll(unsigned long long v, FSLC_FILE *stream);
static int _fslc_put_hex_ll(unsigned long long v, FSLC_FILE *stream, char alpha);
#define _get_slong_arg _get_sint_arg
#define _get_ulong_arg _get_uint_arg
#elif __SIZEOF_LONG__ == 8
#define BUFSIZE_LONG_DECIMAL BUFSIZE_LONG_LONG_DECIMAL
#define _fslc_put_sint_ll _fslc_put_sint_l
#define _fslc_put_uint_ll _fslc_put_uint_l
#define _fslc_put_hex_ll _fslc_put_hex_l
#define _get_slong_arg _get_slonglong_arg
#define _get_ulong_arg _get_ulonglong_arg
#endif
#define FLAG_LONG 1
#define FLAG_VERYLONG 3
static int _fslc_vfprintf_impl(FSLC_FILE *stream, const char *format, struct va_list_w *arg)
{
int res = 0;
int pr;
const char *c;
for (c = format; *c; ++c)
{
if (*c == '%')
{
int flags = 0;
for (;;)
{
++c;
switch (*c)
{
case 's':
pr = _fslc_fputs_impl((const char *)_get_ptr_arg(arg), stream);
if (pr < 0) return pr;
res += pr;
break;
case 'c':
pr = stream->putc(_get_sint_arg(arg), stream);
if (pr < 0) return pr;
++res;
break;
case '%':
pr = stream->putc('%', stream);
if (pr < 0) return pr;
++res;
break;
case 'i':
case 'd':
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
pr = _fslc_put_sint_ll(_get_slonglong_arg(arg), stream);
else if (flags & FLAG_LONG)
pr = _fslc_put_sint_l(_get_slong_arg(arg), stream);
else
pr = _fslc_put_sint_l(_get_sint_arg(arg), stream);
if (pr < 0) return pr;
res += pr;
break;
case 'u':
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
pr = _fslc_put_uint_ll(_get_ulonglong_arg(arg), stream);
else if (flags & FLAG_LONG)
pr = _fslc_put_uint_l(_get_ulong_arg(arg), stream);
else
pr = _fslc_put_uint_l(_get_uint_arg(arg), stream);
if (pr < 0) return pr;
res += pr;
break;
case 'x':
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
pr = _fslc_put_hex_ll(_get_ulonglong_arg(arg), stream, 'a');
else if (flags & FLAG_LONG)
pr = _fslc_put_hex_l(_get_ulong_arg(arg), stream, 'a');
else
pr = _fslc_put_hex_l(_get_uint_arg(arg), stream, 'a');
if (pr < 0) return pr;
res += pr;
break;
case 'X':
if ((flags & FLAG_VERYLONG) == FLAG_VERYLONG)
pr = _fslc_put_hex_ll(_get_ulonglong_arg(arg), stream, 'A');
else if (flags & FLAG_LONG)
pr = _fslc_put_hex_l(_get_ulong_arg(arg), stream, 'A');
else
pr = _fslc_put_hex_l(_get_uint_arg(arg), stream, 'A');
if (pr < 0) return pr;
res += pr;
break;
case 'p':
pr = _fslc_fputs_impl("0x", stream);
if (pr < 0) return pr;
res += pr;
pr = _fslc_put_hex_l(_get_ulong_arg(arg), stream, 'a');
if (pr < 0) return pr;
res += pr;
break;
case 'l':
if (flags & FLAG_LONG)
flags |= FLAG_VERYLONG;
else
flags |= FLAG_LONG;
continue;
}
break;
}
} else {
pr = stream->putc(*c, stream);
if (pr < 0) return pr;
++res;
}
}
return res;
}
static int _get_sint_arg(struct va_list_w *arg)
{
return va_arg(arg->arg, signed int);
}
static unsigned _get_uint_arg(struct va_list_w *arg)
{
return va_arg(arg->arg, unsigned int);
}
static long long _get_slonglong_arg(struct va_list_w *arg)
{
return va_arg(arg->arg, signed long long);
}
static unsigned long long _get_ulonglong_arg(struct va_list_w *arg)
{
return va_arg(arg->arg, unsigned long long);
}
static void *_get_ptr_arg(struct va_list_w *arg)
{
return va_arg(arg->arg, void *);
}
static int _fslc_put_sint_l(signed long v, FSLC_FILE *stream)
{
if (v < 0)
{
int pr = stream->putc('-', stream);
if (pr < 0) return pr;
pr = _fslc_put_uint_l(-v, stream);
if (pr < 0) return pr;
return pr+1;
} else
return _fslc_put_uint_l(v, stream);
}
static int _fslc_put_uint_l(unsigned long v, FSLC_FILE *stream)
{
char dbuff[BUFSIZE_LONG_DECIMAL+1], *p;
dbuff[BUFSIZE_LONG_DECIMAL] = 0;
for (p = dbuff + BUFSIZE_LONG_DECIMAL; v ; v /= 10)
{
*(--p) = (v % 10) + '0';
}
if (*p == 0) *(--p) = '0';
return _fslc_fputs_impl(p, stream);
}
static int _fslc_put_hex_l(unsigned long v, FSLC_FILE *stream, char alpha)
{
char dbuff[BUFSIZE_LONG_HEX+1], *p;
dbuff[BUFSIZE_LONG_HEX] = 0;
for (p = dbuff + BUFSIZE_LONG_HEX; v ; v >>= 4)
{
char digit = (v & 0xF);
*(--p) = digit < 10 ? digit + '0' : digit - 10 + alpha;
}
if (*p == 0) *(--p) = '0';
return _fslc_fputs_impl(p, stream);
}
#if __SIZEOF_LONG__ == 4
static int _fslc_put_sint_ll(signed long long v, FSLC_FILE *stream)
{
if (v < 0)
{
int pr = stream->putc('-', stream);
if (pr < 0) return pr;
pr = _fslc_put_uint_ll(-v, stream);
if (pr < 0) return pr;
return pr+1;
} else
return _fslc_put_uint_ll(v, stream);
}
static int _fslc_put_uint_ll(unsigned long long v, FSLC_FILE *stream)
{
char dbuff[BUFSIZE_LONG_LONG_DECIMAL+1], *p;
dbuff[BUFSIZE_LONG_LONG_DECIMAL] = 0;
for (p = dbuff + BUFSIZE_LONG_LONG_DECIMAL; v ; v /= 10)
{
*(--p) = (v % 10) + '0';
}
if (*p == 0) *(--p) = '0';
return _fslc_fputs_impl(p, stream);
}
static int _fslc_put_hex_ll(unsigned long long v, FSLC_FILE *stream, char alpha)
{
char dbuff[BUFSIZE_LONG_LONG_HEX+1], *p;
dbuff[BUFSIZE_LONG_LONG_HEX] = 0;
for (p = dbuff + BUFSIZE_LONG_LONG_HEX; v ; v >>= 4)
{
char digit = (v & 0xF);
*(--p) = digit < 10 ? digit + '0' : digit - 10 + alpha;
}
if (*p == 0) *(--p) = '0';
return _fslc_fputs_impl(p, stream);
}
#endif
@@ -0,0 +1,6 @@
#include "fslc_stdio.h"
int fslc_vprintf(const char *format, va_list arg)
{
return fslc_vfprintf(fslc_stdout, format, arg);
}
@@ -0,0 +1,18 @@
#include <stdio.h>
#include "regs.hpp"
namespace {
int UartStreamPutc(int c, FILE *) {
UartPutc(static_cast<char>(c));
return c;
}
FILE g_uartStdout = { nullptr, UartStreamPutc, nullptr, nullptr, nullptr, -1 };
} // namespace
void InitializeLibc() {
stdout = &g_uartStdout;
}
@@ -0,0 +1,3 @@
#pragma once
void InitializeLibc();
+6 -1
View File
@@ -1,7 +1,12 @@
#include <stdio.h>
#include "libc_platform.hpp"
#include "regs.hpp"
extern "C" void main() {
UartPuts("[bpmpfw]: Hello from BPMP-FW\n");
InitializeLibc();
printf("[hoc-bpmpfw] Starting bpmpfw\n");
for (;;);
}
+5
View File
@@ -7,6 +7,11 @@ using u32 = std::uint32_t;
#define MMIO32(addr) (*reinterpret_cast<volatile u32 *>(addr))
constexpr u32 FwRamStart = 0x40004000;
constexpr u32 FwRamEnd = 0x4000C000;
constexpr u32 WorkRamStart = FwRamEnd;
constexpr u32 WorkRamEnd = 0x40010000;
constexpr u32 FlowCtlrBase = 0x60007000;
constexpr u32 FlowCtlrHaltCopEvents = 0x004;