1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-08-11 17:30:25 +00:00

libc cleanup (#1568)

* libc cleanup

* Suggested changes, small alloca tweak

* Remove printf include
This commit is contained in:
Tharo 2023-10-27 15:06:44 +01:00 committed by GitHub
parent 4e55168eaa
commit 3475651701
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 571 additions and 432 deletions

View file

@ -1,5 +1,9 @@
#include "global.h"
f32 absf(f32 a) {
return fabsf(a);
float absf(float n) {
#ifndef __GNUC__
return fabsf(n);
#else
return __builtin_fabsf(n);
#endif
}

View file

@ -1,6 +1,6 @@
#include "global.h"
#include "stdlib.h"
ldiv_t ldiv(s32 num, s32 denom) {
ldiv_t ldiv(long num, long denom) {
ldiv_t ret;
ret.quot = num / denom;
@ -13,7 +13,7 @@ ldiv_t ldiv(s32 num, s32 denom) {
return ret;
}
lldiv_t lldiv(s64 num, s64 denom) {
lldiv_t lldiv(long long num, long long denom) {
lldiv_t ret;
ret.quot = num / denom;

View file

@ -1,47 +1,48 @@
#include "global.h"
// IDO Compiler Intrinsics for 64-bit arithmetic
s64 __ull_rshift(u64 l, s64 r) {
return l >> r;
long long __ull_rshift(unsigned long long left, long long right) {
return left >> right;
}
u64 __ull_rem(u64 l, u64 r) {
return l % r;
unsigned long long __ull_rem(unsigned long long left, unsigned long long right) {
return left % right;
}
u64 __ull_div(u64 l, u64 r) {
return l / r;
unsigned long long __ull_div(unsigned long long left, unsigned long long right) {
return left / right;
}
s64 __ll_lshift(s64 l, s64 r) {
return l << r;
long long __ll_lshift(long long left, long long right) {
return left << right;
}
s64 __ll_rem(s64 l, u64 r) {
return l % r;
long long __ll_rem(long long left, unsigned long long right) {
return left % right;
}
s64 __ll_div(s64 l, s64 r) {
return l / r;
long long __ll_div(long long left, long long right) {
return left / right;
}
s64 __ll_mul(s64 l, s64 r) {
return l * r;
long long __ll_mul(long long left, long long right) {
return left * right;
}
void __ull_divremi(u64* quotient, u64* remainder, u64 dividend, u16 divisor) {
void __ull_divremi(unsigned long long int* quotient, unsigned long long int* remainder,
unsigned long long dividend, unsigned short divisor) {
*quotient = dividend / divisor;
*remainder = dividend % divisor;
}
s64 __ll_mod(s64 l, s64 r) {
s64 remainder = l % r;
long long __ll_mod(long long left, long long right) {
long long rem = left % right;
if (((remainder < 0) && (r > 0)) || ((remainder > 0) && (r < 0))) {
remainder += r;
if ((rem < 0 && right > 0) || (rem > 0 && right < 0)) {
rem += right;
}
return remainder;
return rem;
}
s64 __ll_rshift(s64 l, s64 r) {
return l >> r;
long long __ll_rshift(long long left, long long right) {
return left >> right;
}

View file

@ -1,33 +1,33 @@
#include "global.h"
// IDO Compiler Intrinsics for 64-bit conversion
s64 __d_to_ll(f64 d) {
long long __d_to_ll(double d) {
return d;
}
s64 __f_to_ll(f32 f) {
long long __f_to_ll(float f) {
return f;
}
u64 __d_to_ull(f64 d) {
unsigned long long __d_to_ull(double d) {
return d;
}
u64 __f_to_ull(f32 f) {
unsigned long long __f_to_ull(float f) {
return f;
}
f64 __ll_to_d(s64 l) {
double __ll_to_d(long long l) {
return l;
}
f32 __ll_to_f(s64 l) {
float __ll_to_f(long long l) {
return l;
}
f64 __ull_to_d(u64 l) {
double __ull_to_d(unsigned long long l) {
return l;
}
f32 __ull_to_f(u64 l) {
float __ull_to_f(unsigned long long l) {
return l;
}

View file

@ -0,0 +1,32 @@
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
#include "ultra64/xstdio.h"
void* proutSprintf(void* dst, const char* fmt, size_t size) {
return (char*)memcpy(dst, fmt, size) + size;
}
int vsprintf(char* dst, const char* fmt, va_list args) {
int ret = _Printf(proutSprintf, dst, fmt, args);
if (ret > -1) {
dst[ret] = '\0';
}
return ret;
}
int sprintf(char* dst, const char* fmt, ...) {
int ret;
va_list args;
va_start(args, fmt);
ret = _Printf(proutSprintf, dst, fmt, args);
if (ret > -1) {
dst[ret] = '\0';
}
va_end(args);
return ret;
}

View file

@ -1,9 +1,9 @@
#include "global.h"
double sqrt(double f) {
#ifndef __GNUC__
#define __builtin_sqrt sqrt
#endif
f64 sqrt(f64 f) {
return sqrt(f);
#else
return __builtin_sqrt(f);
#endif
}

View file

@ -1,18 +1,18 @@
#include "global.h"
#include "string.h"
const char* strchr(const char* str, s32 ch) {
u8 c = ch;
char* strchr(const char* str, int c) {
char ch = c;
while (*str != c) {
while (*str != ch) {
if (*str == 0) {
return NULL;
}
str++;
}
return str;
return (char*)str;
}
u32 strlen(const char* str) {
size_t strlen(const char* str) {
const char* ptr = str;
while (*ptr) {
@ -21,13 +21,13 @@ u32 strlen(const char* str) {
return ptr - str;
}
void* memcpy(void* dst, const void* src, size_t size) {
u8* _dst = dst;
const u8* _src = src;
void* memcpy(void* dst, const void* src, size_t n) {
char* _dst = dst;
const char* _src = src;
while (size > 0) {
while (n > 0) {
*_dst++ = *_src++;
size--;
n--;
}
return dst;
}

282
src/libultra/libc/xldtob.c Normal file
View file

@ -0,0 +1,282 @@
#include "stdlib.h"
#include "string.h"
#include "ultra64/xstdio.h"
#define BUFF_LEN 0x20
short _Ldunscale(short*, _Pft*);
void _Genld(_Pft*, char, char*, short, short);
static const double pows[] = { 10e0L, 10e1L, 10e3L, 10e7L, 10e15L, 10e31L, 10e63L, 10e127L, 10e255L };
// float properties
#define _D0 0
#define _DBIAS 0x3FF
#define _DLONG 1
#define _DOFF 4
#define _FBIAS 0x7E
#define _FOFF 7
#define _FRND 1
#define _LBIAS 0x3FFE
#define _LOFF 15
// integer properties
#define _C2 1
#define _CSIGN 1
#define _ILONG 0
#define _MBMAX 8
#define NAN 2
#define INF 1
#define FINITE -1
#define _DFRAC ((1 << _DOFF) - 1)
#define _DMASK (0x7FFF & ~_DFRAC)
#define _DMAX ((1 << (15 - _DOFF)) - 1)
#define _DNAN (0x8000 | _DMAX << _DOFF | 1 << (_DOFF - 1))
#define _DSIGN 0x8000
#if _D0 == 3
#define _D1 2 // little-endian order
#define _D2 1
#define _D3 0
#else
#define _D1 1 // big-endian order
#define _D2 2
#define _D3 3
#endif
void _Ldtob(_Pft* args, char code) {
char buff[BUFF_LEN];
char* ptr = buff;
LONG_DOUBLE_TYPE val = args->v.ld;
short err;
short nsig;
short exp;
if (args->prec < 0) {
args->prec = 6;
} else if (args->prec == 0 && (code == 'g' || code == 'G')) {
args->prec = 1;
}
err = _Ldunscale(&exp, (_Pft*)args);
if (err > 0) {
memcpy(args->s, err == 2 ? "NaN" : "Inf", args->n1 = 3);
return;
}
if (err == 0) {
nsig = 0;
exp = 0;
} else {
int i;
int n;
double factor;
int gen;
if (val < 0) {
val = -val;
}
exp = exp * 30103 / 100000 - 4;
if (exp < 0) {
n = (3 - exp) & ~3;
exp = -n;
for (i = 0; n > 0; n >>= 1, i++) {
if ((n & 1) != 0) {
val *= pows[i];
}
}
} else if (exp > 0) {
factor = 1;
exp &= ~3;
for (n = exp, i = 0; n > 0; n >>= 1, i++) {
if ((n & 1) != 0) {
factor *= pows[i];
}
}
val /= factor;
}
gen = ((code == 'f') ? exp + 10 : 6) + args->prec;
if (gen > 0x13) {
gen = 0x13;
}
*ptr++ = '0';
while (gen > 0 && 0 < val) {
int j;
int lo = val;
if ((gen -= 8) > 0) {
val = (val - lo) * 1.0e8;
}
ptr += 8;
for (j = 8; lo > 0 && --j >= 0;) {
ldiv_t qr = ldiv(lo, 10);
*--ptr = qr.rem + '0';
lo = qr.quot;
}
while (--j >= 0) {
ptr--;
*ptr = '0';
}
ptr += 8;
}
gen = ptr - &buff[1];
for (ptr = &buff[1], exp += 7; *ptr == '0'; ptr++) {
--gen, --exp;
}
nsig = ((code == 'f') ? exp + 1 : ((code == 'e' || code == 'E') ? 1 : 0)) + args->prec;
if (gen < nsig) {
nsig = gen;
}
if (nsig > 0) {
char drop;
int n2;
if (nsig < gen && ptr[nsig] > '4') {
drop = '9';
} else {
drop = '0';
}
for (n2 = nsig; ptr[--n2] == drop;) {
nsig--;
}
if (drop == '9') {
ptr[n2]++;
}
if (n2 < 0) {
--ptr, ++nsig, ++exp;
}
}
}
_Genld((_Pft*)args, code, ptr, nsig, exp);
}
short _Ldunscale(short* pex, _Pft* px) {
unsigned short* ps = (unsigned short*)px;
short xchar = (ps[_D0] & _DMASK) >> _DOFF;
if (xchar == _DMAX) { /* NaN or INF */
*pex = 0;
return (short)(ps[_D0] & _DFRAC || ps[_D1] || ps[_D2] || ps[_D3] ? NAN : INF);
} else if (0 < xchar) {
ps[_D0] = (ps[_D0] & ~_DMASK) | (_DBIAS << _DOFF);
*pex = xchar - (_DBIAS - 1);
return FINITE;
}
if (0 > xchar) {
return NAN;
} else {
*pex = 0;
return 0;
}
}
void _Genld(_Pft* px, char code, char* p, short nsig, short xexp) {
const char point = '.';
if (nsig <= 0) {
nsig = 1,
p = (char*)"0";
}
if (code == 'f' || ((code == 'g' || code == 'G') && (-4 <= xexp) && (xexp < px->prec))) { /* 'f' format */
++xexp; /* change to leading digit count */
if (code != 'f') { /* fixup for 'g' */
if (!(px->flags & FLAGS_HASH) && nsig < px->prec) {
px->prec = nsig;
}
if ((px->prec -= xexp) < 0) {
px->prec = 0;
}
}
if (xexp <= 0) { /* digits only to right of point */
px->s[px->n1++] = '0';
if (0 < px->prec || px->flags & FLAGS_HASH) {
px->s[px->n1++] = point;
}
if (px->prec < -xexp) {
xexp = -px->prec;
}
px->nz1 = -xexp;
px->prec += xexp;
if (px->prec < nsig) {
nsig = px->prec;
}
memcpy(&px->s[px->n1], p, px->n2 = nsig);
px->nz2 = px->prec - nsig;
} else if (nsig < xexp) { /* zeros before point */
memcpy(&px->s[px->n1], p, nsig);
px->n1 += nsig;
px->nz1 = xexp - nsig;
if (0 < px->prec || px->flags & FLAGS_HASH) {
px->s[px->n1] = point, ++px->n2;
}
px->nz2 = px->prec;
} else { /* enough digits before point */
memcpy(&px->s[px->n1], p, xexp);
px->n1 += xexp;
nsig -= xexp;
if (0 < px->prec || px->flags & FLAGS_HASH) {
px->s[px->n1++] = point;
}
if (px->prec < nsig) {
nsig = px->prec;
}
memcpy(&px->s[px->n1], p + xexp, nsig);
px->n1 += nsig;
px->nz1 = px->prec - nsig;
}
} else { /* 'e' format */
if (code == 'g' || code == 'G') { /* fixup for 'g' */
if (nsig < px->prec) {
px->prec = nsig;
}
if (--px->prec < 0) {
px->prec = 0;
}
code = code == 'g' ? 'e' : 'E';
}
px->s[px->n1++] = *p++;
if (0 < px->prec || px->flags & FLAGS_HASH) {
px->s[px->n1++] = point;
}
if (0 < px->prec) { /* put fraction digits */
if (px->prec < --nsig) {
nsig = px->prec;
}
memcpy(&px->s[px->n1], p, nsig);
px->n1 += nsig;
px->nz1 = px->prec - nsig;
}
p = &px->s[px->n1]; /* put exponent */
*p++ = code;
if (0 <= xexp) {
*p++ = '+';
} else { /* negative exponent */
*p++ = '-';
xexp = -xexp;
}
if (100 <= xexp) { /* put oversize exponent */
if (1000 <= xexp) {
*p++ = xexp / 1000 + '0', xexp %= 1000;
}
*p++ = xexp / 100 + '0', xexp %= 100;
}
*p++ = xexp / 10 + '0', xexp %= 10;
*p++ = xexp + '0';
px->n2 = p - &px->s[px->n1];
}
if ((px->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) { /* pad with leading zeros */
int n = px->n0 + px->n1 + px->nz1 + px->n2 + px->nz2;
if (n < px->width) {
px->nz0 = px->width - n;
}
}
}

View file

@ -0,0 +1,58 @@
#include "stdlib.h"
#include "string.h"
#include "ultra64/xstdio.h"
#define BUFF_LEN 0x18
static char ldigs[] = "0123456789abcdef";
static char udigs[] = "0123456789ABCDEF";
void _Litob(_Pft* args, char type) {
char buff[BUFF_LEN];
const char* digs;
int base;
int i;
unsigned long long num;
if (type == 'X') {
digs = udigs;
} else {
digs = ldigs;
}
base = (type == 'o') ? 8 : ((type != 'x' && type != 'X') ? 10 : 16);
i = BUFF_LEN;
num = args->v.ll;
if ((type == 'd' || type == 'i') && args->v.ll < 0) {
num = -num;
}
if (num != 0 || args->prec != 0) {
buff[--i] = digs[num % base];
}
args->v.ll = num / base;
while (args->v.ll > 0 && i > 0) {
lldiv_t quotrem = lldiv(args->v.ll, base);
args->v.ll = quotrem.quot;
buff[--i] = digs[quotrem.rem];
}
args->n1 = BUFF_LEN - i;
memcpy(args->s, buff + i, args->n1);
if (args->n1 < args->prec) {
args->nz0 = args->prec - args->n1;
}
if (args->prec < 0 && (args->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) {
i = args->width - args->n0 - args->nz0 - args->n1;
if (i > 0) {
args->nz0 += i;
}
}
}

240
src/libultra/libc/xprintf.c Normal file
View file

@ -0,0 +1,240 @@
#include "stdarg.h"
#include "stdbool.h"
#include "stdint.h"
#include "stdlib.h"
#include "string.h"
#include "ultra64/xstdio.h"
#define isdigit(x) (((x) >= '0' && (x) <= '9'))
#define LDSIGN(x) (((unsigned short*)&(x))[0] & 0x8000)
#define ATOI(i, a) \
for (i = 0; isdigit(*a); a++) \
if (i < 999) \
i = *a + i * 10 - '0';
#define PUT(fmt, _size) \
if (_size > 0) { \
arg = pfn(arg, fmt, _size); \
if (arg != NULL) \
x.nchar += _size; \
else \
return x.nchar; \
}
#define MAX_PAD ((int)sizeof(spaces) - 1)
#define PAD(src, m) \
if (m > 0) { \
int i; \
int j; \
for (j = m; j > 0; j -= i) { \
if ((unsigned)j > MAX_PAD) \
i = MAX_PAD; \
else \
i = j; \
PUT(src, i); \
} \
}
char spaces[] = " ";
char zeroes[] = "00000000000000000000000000000000";
void _Putfld(_Pft*, va_list*, char, char*);
int _Printf(PrintCallback pfn, void* arg, const char* fmt, va_list ap) {
_Pft x;
x.nchar = 0;
while (true) {
static const char fchar[] = " +-#0";
static const unsigned int fbit[] = { FLAGS_SPACE, FLAGS_PLUS, FLAGS_MINUS, FLAGS_HASH, FLAGS_ZERO, 0 };
const char* s = fmt;
char c;
const char* t;
char ac[0x20];
while ((c = *s) != 0 && c != '%') {
s++;
}
PUT(fmt, s - fmt);
if (c == 0) {
return x.nchar;
}
fmt = ++s;
for (x.flags = 0; (t = strchr(fchar, *s)) != NULL; s++) {
x.flags |= fbit[t - fchar];
}
if (*s == '*') {
x.width = va_arg(ap, int);
if (x.width < 0) {
x.width = -x.width;
x.flags |= FLAGS_MINUS;
}
s++;
} else {
ATOI(x.width, s);
}
if (*s != '.') {
x.prec = -1;
} else {
s++;
if (*s == '*') {
x.prec = va_arg(ap, int);
s++;
} else {
ATOI(x.prec, s);
}
}
if (strchr("hlL", *s) != NULL) {
x.qual = *s++;
} else {
x.qual = '\0';
}
if (x.qual == 'l' && *s == 'l') {
x.qual = 'L';
s++;
}
_Putfld(&x, &ap, *s, ac);
x.width -= x.n0 + x.nz0 + x.n1 + x.nz1 + x.n2 + x.nz2;
if (!(x.flags & FLAGS_MINUS)) {
PAD(spaces, x.width);
}
PUT(ac, x.n0);
PAD(zeroes, x.nz0);
PUT(x.s, x.n1);
PAD(zeroes, x.nz1);
PUT(&x.s[x.n1], x.n2)
PAD(zeroes, x.nz2);
if (x.flags & FLAGS_MINUS) {
PAD(spaces, x.width);
}
fmt = s + 1;
}
}
void _Putfld(_Pft* px, va_list* pap, char code, char* ac) {
px->n0 = px->nz0 = px->n1 = px->nz1 = px->n2 = px->nz2 = 0;
switch (code) {
case 'c':
ac[px->n0++] = va_arg(*pap, unsigned int);
break;
case 'd':
case 'i':
if (px->qual == 'l') {
px->v.ll = va_arg(*pap, long);
} else if (px->qual == 'L') {
px->v.ll = va_arg(*pap, long long);
} else {
px->v.ll = va_arg(*pap, int);
}
if (px->qual == 'h') {
px->v.ll = (short)px->v.ll;
}
if (px->v.ll < 0) {
ac[px->n0++] = '-';
} else if (px->flags & FLAGS_PLUS) {
ac[px->n0++] = '+';
} else if (px->flags & FLAGS_SPACE) {
ac[px->n0++] = ' ';
}
px->s = &ac[px->n0];
_Litob(px, code);
break;
case 'x':
case 'X':
case 'u':
case 'o':
if (px->qual == 'l') {
px->v.ll = va_arg(*pap, long);
} else if (px->qual == 'L') {
px->v.ll = va_arg(*pap, long long);
} else {
px->v.ll = va_arg(*pap, int);
}
if (px->qual == 'h') {
px->v.ll = (unsigned short)px->v.ll;
} else if (px->qual == '\0') {
px->v.ll = (unsigned int)px->v.ll;
}
if (px->flags & FLAGS_HASH) {
ac[px->n0++] = '0';
if (code == 'x' || code == 'X') {
ac[px->n0++] = code;
}
}
px->s = &ac[px->n0];
_Litob(px, code);
break;
case 'e':
case 'f':
case 'g':
case 'E':
case 'G':
px->v.ld = px->qual == 'L' ? va_arg(*pap, LONG_DOUBLE_TYPE) : va_arg(*pap, double);
if (LDSIGN(px->v.ld)) {
ac[px->n0++] = '-';
} else if (px->flags & FLAGS_PLUS) {
ac[px->n0++] = '+';
} else if (px->flags & FLAGS_SPACE) {
ac[px->n0++] = ' ';
}
px->s = &ac[px->n0];
_Ldtob(px, code);
break;
case 'n':
if (px->qual == 'h') {
*(va_arg(*pap, unsigned short*)) = px->nchar;
} else if (px->qual == 'l') {
*va_arg(*pap, unsigned long*) = px->nchar;
} else if (px->qual == 'L') {
*va_arg(*pap, unsigned long long*) = px->nchar;
} else {
*va_arg(*pap, unsigned int*) = px->nchar;
}
break;
case 'p':
px->v.ll = (intptr_t)va_arg(*pap, void*);
px->s = &ac[px->n0];
_Litob(px, 'x');
break;
case 's':
px->s = va_arg(*pap, char*);
px->n1 = strlen(px->s);
if (px->prec >= 0 && px->n1 > px->prec) {
px->n1 = px->prec;
}
break;
case '%':
ac[px->n0++] = '%';
break;
default:
ac[px->n0++] = code;
break;
}
}