You've already forked ultrasm64-2
mirror of
https://github.com/HackerN64/ultrasm64-2.git
synced 2026-01-21 10:38:08 -08:00
git subrepo clone https://gitlab.com/mpharoah/n64-libc lib/n64-libc
subrepo: subdir: "lib/n64-libc" merged: "70270d60" upstream: origin: "https://gitlab.com/mpharoah/n64-libc" branch: "main" commit: "70270d60" git-subrepo: version: "0.4.9" origin: "https://github.com/ingydotnet/git-subrepo" commit: "4f60dd7"
This commit is contained in:
2
lib/n64-libc/.gitignore
vendored
Normal file
2
lib/n64-libc/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/.vscode
|
||||
*.kate-swp
|
||||
12
lib/n64-libc/.gitrepo
Normal file
12
lib/n64-libc/.gitrepo
Normal file
@@ -0,0 +1,12 @@
|
||||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = https://gitlab.com/mpharoah/n64-libc
|
||||
branch = main
|
||||
commit = 70270d60f9b13d3cd896eaa8aa0a043992a823fd
|
||||
parent = 4c89989f6f2ef03e71fc89e33e4e94fa067fda04
|
||||
method = merge
|
||||
cmdver = 0.4.9
|
||||
5
lib/n64-libc/README.md
Normal file
5
lib/n64-libc/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# N64 libc
|
||||
|
||||
Provides a partial implementation of the C standard library for N64
|
||||
|
||||
WORK IN PROGRESS
|
||||
3
lib/n64-libc/n64-alloca.h
Normal file
3
lib/n64-libc/n64-alloca.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#ifndef n64_alloca
|
||||
#define n64_alloca( size ) __builtin_alloca_with_align( size, 64 )
|
||||
#endif
|
||||
9
lib/n64-libc/n64-assert.c
Normal file
9
lib/n64-libc/n64-assert.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "n64-assert.h"
|
||||
|
||||
#include "n64-stdlib.h"
|
||||
#include "n64-stdio.h"
|
||||
|
||||
void __n64_assert_fail( const char *assertion, const char *file, unsigned int line, const char *fcn ) {
|
||||
n64_printf( "%s:%u: %s: Assertion `%s' failed.\n", file, line, fcn, assertion );
|
||||
n64_abort();
|
||||
}
|
||||
32
lib/n64-libc/n64-assert.h
Normal file
32
lib/n64-libc/n64-assert.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef N64_STDLIB_N64_ASSERT_H_
|
||||
#define N64_STDLIB_N64_ASSERT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define n64_assert( expr ) (void)(0)
|
||||
#else
|
||||
|
||||
__attribute__((noreturn))
|
||||
void __n64_assert_fail( const char *assertion, const char *file, unsigned int line, const char *fcn );
|
||||
|
||||
#define n64_assert( expr ) ((expr) ? (void)(0) : __n64_assert_fail( #expr, __FILE__, __LINE__, __func__ ))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define n64_static_assert( expr ) static_assert( expr )
|
||||
#else
|
||||
#if __STDC_VERSION__ >= 202311L
|
||||
#define n64_static_assert( expr ) static_assert( expr )
|
||||
#else
|
||||
#define n64_static_assert( expr ) _Static_assert( expr )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
lib/n64-libc/n64-ctype.c
Normal file
20
lib/n64-libc/n64-ctype.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "n64-ctype.h"
|
||||
|
||||
unsigned short __n64_internal_charflag_table[256] = {
|
||||
/* 0x00 - 0x08 : control codes */ 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020,
|
||||
/* 0x09 : tab */ 0x0E0,
|
||||
/* 0x0A - 0x0D : whitespaces */ 0x060, 0x060, 0x060, 0x060,
|
||||
/* 0x0E - 0x1F : control codes */ 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020, 0x020,
|
||||
/* 0x20 : space */ 0x1C0,
|
||||
/* 0x21 - 0x2F : punctuation */ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
/* 0x30 - 0x39 : digits */ 0x105, 0x105, 0x105, 0x105, 0x105, 0x105, 0x105, 0x105, 0x105, 0x105,
|
||||
/* 0x3A - 0x40 : punctuation */ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
/* 0x41 - 0x46 : hex letters (U) */ 0x116, 0x116, 0x116, 0x116, 0x116, 0x116,
|
||||
/* 0x47 - 0x5A : letters (U) */ 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112, 0x112,
|
||||
/* 0x5B - 0x60 : punctuation */ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300,
|
||||
/* 0x61 - 0x66 : hex letters (L) */ 0x10E, 0x10E, 0x10E, 0x10E, 0x10E, 0x10E,
|
||||
/* 0x67 - 0x7A : letters (L) */ 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A, 0x10A,
|
||||
/* 0x7B - 0x7E : punctuation */ 0x300, 0x300, 0x300, 0x300,
|
||||
/* 0x7F : backspace */ 0x020,
|
||||
/* 0x80 - 0xFF : non-ASCII */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
89
lib/n64-libc/n64-ctype.h
Normal file
89
lib/n64-libc/n64-ctype.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef N64_STDLIB_N64_CTYPE_H_
|
||||
#define N64_STDLIB_N64_CTYPE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern unsigned short __n64_internal_charflag_table[256];
|
||||
|
||||
__attribute__((const, always_inline))
|
||||
static inline int __n64_internal_has_charflag( int ch, unsigned short flag ) {
|
||||
return __n64_internal_charflag_table[(unsigned int)ch & 0xFFu] & (int)flag;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isalnum( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x003 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isalpha( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x002 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_islower( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x008 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isupper( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x010 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isdigit( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x001 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isxdigit( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x004 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_iscntrl( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x020 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isgraph( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x203 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isspace( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x040 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isblank( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x080 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_isprint( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x100 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_ispunct( int ch ) {
|
||||
return __n64_internal_has_charflag( ch, 0x200 );
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_tolower( int ch ) {
|
||||
return (ch >= (int)'A' && ch <= (int)'Z') ? (ch + 32) : ch;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_toupper( int ch ) {
|
||||
return (ch >= (int)'a' && ch <= (int)'z') ? (ch - 32) : ch;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
72
lib/n64-libc/n64-fenv.c
Normal file
72
lib/n64-libc/n64-fenv.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "n64-fenv.h"
|
||||
|
||||
int n64_feclearexcept( int excepts ) {
|
||||
if( excepts & ~FE_ALL_EXCEPT ) return excepts;
|
||||
register unsigned int fcr31 = __builtin_mips_get_fcsr();
|
||||
fcr31 &= ~((unsigned int)excepts << 2);
|
||||
__builtin_mips_set_fcsr( fcr31 );
|
||||
return ((int)__builtin_mips_get_fcsr() >> 2) & excepts;
|
||||
}
|
||||
|
||||
int n64_fetestexcept( int excepts ) {
|
||||
return (int)(__builtin_mips_get_fcsr() >> 2) & FE_ALL_EXCEPT & excepts;
|
||||
}
|
||||
|
||||
int n64_feraiseexcept( int excepts ) {
|
||||
if( excepts & ~FE_ALL_EXCEPT ) return excepts;
|
||||
register unsigned int fcr31 = __builtin_mips_get_fcsr();
|
||||
fcr31 |= (unsigned int)excepts << 12;
|
||||
__builtin_mips_set_fcsr( fcr31 );
|
||||
return (((int)__builtin_mips_get_fcsr() >> 2) & excepts) ^ excepts;
|
||||
}
|
||||
|
||||
int n64_fegetexceptflag( n64_fexcept_t *flagp, int excepts ) {
|
||||
if( excepts & ~FE_ALL_EXCEPT ) return excepts;
|
||||
*flagp = (n64_fexcept_t)((__builtin_mips_get_fcsr() >> 2) & (unsigned int)excepts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n64_fesetexceptflag( const n64_fexcept_t *flagp, int excepts ) {
|
||||
if( excepts & ~FE_ALL_EXCEPT ) return excepts;
|
||||
register unsigned int fcr31 = __builtin_mips_get_fcsr();
|
||||
fcr31 &= ~((unsigned int)excepts << 2);
|
||||
fcr31 |= ((unsigned int)*flagp & (unsigned int)excepts) << 2;
|
||||
__builtin_mips_set_fcsr( fcr31 );
|
||||
return (((int)__builtin_mips_get_fcsr() >> 2) & excepts) ^ ((int)*flagp & excepts);
|
||||
}
|
||||
|
||||
int n64_fesetround( int round ) {
|
||||
if( round < 0 || round > 3 ) return round;
|
||||
register unsigned int fcr31 = __builtin_mips_get_fcsr() & ~3u;
|
||||
__builtin_mips_set_fcsr( fcr31 | (unsigned int)round );
|
||||
return (int)(__builtin_mips_get_fcsr() & 3u) ^ round;
|
||||
}
|
||||
|
||||
int n64_fegetround() {
|
||||
return (unsigned int)__builtin_mips_get_fcsr() & 3u;
|
||||
}
|
||||
|
||||
int n64_fegetenv( n64_fenv_t* envp ) {
|
||||
*envp = __builtin_mips_get_fcsr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n64_fesetenv( const n64_fenv_t* envp ) {
|
||||
register const unsigned int c = __builtin_mips_get_fcsr() & 0x00800000u;
|
||||
__builtin_mips_set_fcsr( (*envp & 0x01000FFFu) | c );
|
||||
return (int)((*envp ^ __builtin_mips_get_fcsr()) & 0x01000FFFu);
|
||||
}
|
||||
|
||||
int n64_feholdexcept( n64_fenv_t* envp ) {
|
||||
*envp = (n64_fenv_t)__builtin_mips_get_fcsr() & 0x0103FFFFu;
|
||||
__builtin_mips_set_fcsr( *envp & 0x01800003u );
|
||||
return (int)(__builtin_mips_get_fcsr() & 0x0003FFFCu);
|
||||
}
|
||||
|
||||
int n64_feupdateenv( const n64_fenv_t* envp ) {
|
||||
register const unsigned int e = __builtin_mips_get_fcsr() & 0x0083F000u;
|
||||
register const unsigned int c = e & 0x00800000u;
|
||||
__builtin_mips_set_fcsr( (*envp & 0x01000FFFu) | c );
|
||||
__builtin_mips_set_fcsr( (*envp & 0x01000FFFu) | e );
|
||||
return (int)((*envp ^ __builtin_mips_get_fcsr()) & 0x0103FFFFu);
|
||||
}
|
||||
39
lib/n64-libc/n64-fenv.h
Normal file
39
lib/n64-libc/n64-fenv.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef N64_STDLIB_N64_FENV_H_
|
||||
#define N64_STDLIB_N64_FENV_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FE_DIVBYZERO 0x08
|
||||
#define FE_INEXACT 0x01
|
||||
#define FE_INVALID 0x10
|
||||
#define FE_OVERFLOW 0x04
|
||||
#define FE_UNDERFLOW 0x02
|
||||
#define FE_ALL_EXCEPT 0x1F
|
||||
|
||||
#define FE_DOWNWARD 0x3
|
||||
#define FE_TONEAREST 0x0
|
||||
#define FE_TOWARDZERO 0x1
|
||||
#define FE_UPWARD 0x2
|
||||
|
||||
typedef unsigned int n64_fenv_t;
|
||||
typedef unsigned char n64_fexcept_t;
|
||||
|
||||
int n64_feclearexcept( int excepts );
|
||||
int n64_fetestexcept( int excepts ) __attribute__((warn_unused_result));
|
||||
int n64_feraiseexcept( int excepts );
|
||||
int n64_fegetexceptflag( n64_fexcept_t *flagp, int excepts ) __attribute__((nonnull(1), access(write_only, 1)));
|
||||
int n64_fesetexceptflag( const n64_fexcept_t *flagp, int excepts ) __attribute__((nonnull(1)));
|
||||
int n64_fesetround( int round );
|
||||
int n64_fegetround() __attribute__((warn_unused_result));
|
||||
int n64_fegetenv( n64_fenv_t* envp ) __attribute__((nonnull(1), access(write_only, 1)));
|
||||
int n64_fesetenv( const n64_fenv_t* envp ) __attribute__((nonnull(1)));
|
||||
int n64_feholdexcept( n64_fenv_t* envp ) __attribute__((nonnull(1), access(write_only, 1)));
|
||||
int n64_feupdateenv( const n64_fenv_t* envp ) __attribute__((nonnull(1)));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
111
lib/n64-libc/n64-float.h
Normal file
111
lib/n64-libc/n64-float.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef FLT_RADIX
|
||||
#define FLT_RADIX 2
|
||||
#endif
|
||||
|
||||
#ifndef FLT_DECIMAL_DIG
|
||||
#define FLT_DECIMAL_DIG 9
|
||||
#endif
|
||||
|
||||
#ifndef DBL_DECIMAL_DIG
|
||||
#define DBL_DECIMAL_DIG 17
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MIN
|
||||
#define FLT_MIN 1.1754944e-38f
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MIN
|
||||
#define DBL_MIN 2.2250738585072014e-308
|
||||
#endif
|
||||
|
||||
#ifndef FLT_TRUE_MIN
|
||||
#define FLT_TRUE_MIN 1e-45f
|
||||
#endif
|
||||
|
||||
#ifndef DBL_TRUE_MIN
|
||||
#define DBL_TRUE_MIN 5e-324
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MAX
|
||||
#define FLT_MAX 3.4028235e+38f
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MAX
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
#endif
|
||||
|
||||
#ifndef FLT_EPSILON
|
||||
#define FLT_EPSILON 1.1920929e-07f
|
||||
#endif
|
||||
|
||||
#ifndef DBL_EPSILON
|
||||
#define DBL_EPSILON 2.220446049250313e-16
|
||||
#endif
|
||||
|
||||
#ifndef FLT_DIG
|
||||
#define FLT_DIG 6
|
||||
#endif
|
||||
|
||||
#ifndef DBL_DIG
|
||||
#define DBL_DIG 15
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MANT_DIG
|
||||
#define FLT_MANT_DIG 24
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MANT_DIG
|
||||
#define DBL_MANT_DIG 53
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MIN_EXP
|
||||
#define FLT_MIN_EXP -125
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MIN_EXP
|
||||
#define DBL_MIN_EXP -1021
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MIN_10_EXP
|
||||
#define FLT_MIN_10_EXP -37
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MIN_10_EXP
|
||||
#define DBL_MIN_10_EXP -307
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MAX_EXP
|
||||
#define FLT_MAX_EXP 128
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MAX_EXP
|
||||
#define DBL_MAX_EXP 1024
|
||||
#endif
|
||||
|
||||
#ifndef FLT_MAX_10_EXP
|
||||
#define FLT_MAX_10_EXP 38
|
||||
#endif
|
||||
|
||||
#ifndef DBL_MAX_10_EXP
|
||||
#define DBL_MAX_10_EXP 308
|
||||
#endif
|
||||
|
||||
#ifndef FLT_EVAL_METHOD
|
||||
#define FLT_EVAL_METHOD 0
|
||||
#endif
|
||||
|
||||
#ifndef FLT_HAS_SUBNORM
|
||||
#define FLT_HAS_SUBNORM 1
|
||||
#endif
|
||||
|
||||
#ifndef DBL_HAS_SUBNORM
|
||||
#define DBL_HAS_SUBNORM 1
|
||||
#endif
|
||||
|
||||
#ifndef DECIMAL_DIG
|
||||
#if defined(_ABIO64) || defined(_ABIO32)
|
||||
#define DECIMAL_DIG DBL_DECIMAL_DIG
|
||||
#else
|
||||
#define DECIMAL_DIG 36
|
||||
#endif
|
||||
#endif
|
||||
15
lib/n64-libc/n64-libc.h
Normal file
15
lib/n64-libc/n64-libc.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "n64-alloca.h"
|
||||
#include "n64-assert.h"
|
||||
#include "n64-ctype.h"
|
||||
#include "n64-fenv.h"
|
||||
#include "n64-float.h"
|
||||
#include "n64-math.h"
|
||||
#include "n64-numbers.h"
|
||||
#include "n64-stdbool.h"
|
||||
#include "n64-stdckdint.h"
|
||||
#include "n64-stddef.h"
|
||||
#include "n64-stdio.h"
|
||||
#include "n64-stdlib.h"
|
||||
#include "n64-string.h"
|
||||
#include "n64-time.h"
|
||||
#include "n64-util.h"
|
||||
558
lib/n64-libc/n64-math.c
Normal file
558
lib/n64-libc/n64-math.c
Normal file
File diff suppressed because it is too large
Load Diff
275
lib/n64-libc/n64-math.h
Normal file
275
lib/n64-libc/n64-math.h
Normal file
@@ -0,0 +1,275 @@
|
||||
#ifndef N64_STDLIB_N64_MATH_H_
|
||||
#define N64_STDLIB_N64_MATH_H_
|
||||
|
||||
/* Only a subset of math.h is currently implemented */
|
||||
|
||||
#define N64_NAN __builtin_nanf( "0" )
|
||||
#define N64_HUGE_VALF __builtin_inff()
|
||||
#define N64_HUGE_VAL __builtin_inf()
|
||||
#define N64_INFINITY N64_HUGE_VALF
|
||||
|
||||
#ifndef NAN
|
||||
#define NAN N64_NAN
|
||||
#endif
|
||||
|
||||
#ifndef HUGE_VALF
|
||||
#define HUGE_VALF N64_HUGE_VALF
|
||||
#endif
|
||||
|
||||
#ifndef HUGE_VAL
|
||||
#define HUGE_VAL N64_HUGE_VAL
|
||||
#endif
|
||||
|
||||
#ifndef INFINITY
|
||||
#define INFINITY N64_INFINITY
|
||||
#endif
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_expf( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_exp2f( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_logf( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_log10f( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_log2f( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_powf( float base, float exponent );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_cbrtf( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_hypotf( float x, float y );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
double n64_hypot( double x, double y );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_sinf( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result))
|
||||
float n64_cosf( float arg );
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_sqrtf( float arg ) {
|
||||
float result;
|
||||
asm volatile( "sqrt.s %0, %1" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_sqrt( double arg ) {
|
||||
double result;
|
||||
asm volatile( "sqrt.d %0, %1" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_fabsf( float arg ) {
|
||||
float result;
|
||||
asm volatile( "abs.s %0, %1" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_fabs( double arg ) {
|
||||
double result;
|
||||
asm volatile( "abs.d %0, %1" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_floor( double arg ) {
|
||||
if( arg > 4503599627370496.0 || arg < -4503599627370496.0 ) return arg;
|
||||
double result;
|
||||
asm volatile( "floor.l.d %0, %1 \n\t cvt.d.l %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_ceil( double arg ) {
|
||||
if( arg > 4503599627370496.0 || arg < -4503599627370496.0 ) return arg;
|
||||
double result;
|
||||
asm volatile( "ceil.l.d %0, %1 \n\t cvt.d.l %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_trunc( double arg ) {
|
||||
if( arg > 4503599627370496.0 || arg < -4503599627370496.0 ) return arg;
|
||||
double result;
|
||||
asm volatile( "trunc.l.d %0, %1 \n\t cvt.d.l %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_round( double arg ) {
|
||||
if( arg > 4503599627370496.0 || arg < -4503599627370496.0 ) return arg;
|
||||
double result;
|
||||
asm volatile( "round.l.d %0, %1 \n\t cvt.d.l %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline double n64_rint( double arg ) {
|
||||
if( arg > 4503599627370496.0 || arg < -4503599627370496.0 ) return arg;
|
||||
double result;
|
||||
asm volatile( "cvt.l.d %0, %1 \n\t cvt.d.l %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_floorf( float arg ) {
|
||||
if( arg > 8388608.f || arg < -8388608.f ) return arg;
|
||||
float result;
|
||||
asm volatile( "floor.w.s %0, %1 \n\t cvt.s.w %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_ceilf( float arg ) {
|
||||
if( arg > 8388608.f || arg < -8388608.f ) return arg;
|
||||
float result;
|
||||
asm volatile( "ceil.w.s %0, %1 \n\t cvt.s.w %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_truncf( float arg ) {
|
||||
if( arg > 8388608.f || arg < -8388608.f ) return arg;
|
||||
float result;
|
||||
asm volatile( "trunc.w.s %0, %1 \n\t cvt.s.w %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_roundf( float arg ) {
|
||||
if( arg > 8388608.f || arg < -8388608.f ) return arg;
|
||||
float result;
|
||||
asm volatile( "round.w.s %0, %1 \n\t cvt.s.w %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline float n64_rintf( float arg ) {
|
||||
if( arg > 8388608.f || arg < -8388608.f ) return arg;
|
||||
float result;
|
||||
asm volatile( "cvt.w.s %0, %1 \n\t cvt.s.w %0, %0" : "=f"( result ) : "f"( arg ) );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline long long n64_llround( double arg ) {
|
||||
#ifdef _ABIO32
|
||||
double bits;
|
||||
asm volatile( "round.l.d %0, %1" : "=f"( bits ) : "f"( arg ) );
|
||||
union { double f; long long i; } b = { bits };
|
||||
return b.i;
|
||||
#else
|
||||
long long result;
|
||||
asm volatile( "round.l.d $f10, %1 \n\t dmfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline long long n64_llrint( double arg ) {
|
||||
#ifdef _ABIO32
|
||||
double bits;
|
||||
asm volatile( "cvt.l.d %0, %1" : "=f"( bits ) : "f"( arg ) );
|
||||
union { double f; long long i; } b = { bits };
|
||||
return b.i;
|
||||
#else
|
||||
long long result;
|
||||
asm volatile( "cvt.l.d $f10, %1 \n\t dmfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Extensions: fill in gaps in the C standard for rounding functions
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline long long n64_llfloor( double arg ) {
|
||||
#ifdef _ABIO32
|
||||
double bits;
|
||||
asm volatile( "floor.l.d %0, %1" : "=f"( bits ) : "f"( arg ) );
|
||||
union { double f; long long i; } b = { bits };
|
||||
return b.i;
|
||||
#else
|
||||
long long result;
|
||||
asm volatile( "floor.l.d $f10, %1 \n\t dmfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline long long n64_llceil( double arg ) {
|
||||
#ifdef _ABIO32
|
||||
double bits;
|
||||
asm volatile( "ceil.l.d %0, %1" : "=f"( bits ) : "f"( arg ) );
|
||||
union { double f; long long i; } b = { bits };
|
||||
return b.i;
|
||||
#else
|
||||
long long result;
|
||||
asm volatile( "ceil.l.d $f10, %1 \n\t dmfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline long long n64_lltrunc( double arg ) {
|
||||
#ifdef _ABIO32
|
||||
double bits;
|
||||
asm volatile( "trunc.l.d %0, %1" : "=f"( bits ) : "f"( arg ) );
|
||||
union { double f; long long i; } b = { bits };
|
||||
return b.i;
|
||||
#else
|
||||
long long result;
|
||||
asm volatile( "trunc.l.d $f10, %1 \n\t dmfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_ifloorf( float arg ) {
|
||||
int result;
|
||||
asm volatile( "floor.w.s $f10, %1 \n\t mfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_iceilf( float arg ) {
|
||||
int result;
|
||||
asm volatile( "ceil.w.s $f10, %1 \n\t mfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_itruncf( float arg ) {
|
||||
int result;
|
||||
asm volatile( "trunc.w.s $f10, %1 \n\t mfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_iroundf( float arg ) {
|
||||
int result;
|
||||
asm volatile( "round.w.s $f10, %1 \n\t mfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((const, warn_unused_result, always_inline))
|
||||
static inline int n64_irintf( float arg ) {
|
||||
int result;
|
||||
asm volatile( "cvt.w.s $f10, %1 \n\t mfc1 %0, $f10" : "=r"( result ) : "f"( arg ) : "f10" );
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
43
lib/n64-libc/n64-numbers.h
Normal file
43
lib/n64-libc/n64-numbers.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef N64_STDLIB_N64_NUMBERS_H_
|
||||
#define N64_STDLIB_N64_NUMBERS_H_
|
||||
|
||||
#define N64_E 2.7182818284590452
|
||||
#define N64_Ef 2.71828183f
|
||||
|
||||
#define N64_LOG2E 1.4426950408889634
|
||||
#define N64_LOG2Ef 1.44269504f
|
||||
|
||||
#define N64_LOG10E 0.43429448190325183
|
||||
#define N64_LOG10Ef 0.434294481f
|
||||
|
||||
#define N64_PI 3.1415926535897932
|
||||
#define N64_PIf 3.14159265f
|
||||
|
||||
#define N64_INV_PI 0.31830988618379067
|
||||
#define N64_INV_PIf 0.318309886f
|
||||
|
||||
#define N64_INV_SQRTPI 0.56418958354775629
|
||||
#define N64_INV_SQRTPIf 0.564189584f
|
||||
|
||||
#define N64_LN2 0.69314718055994531
|
||||
#define N64_LN2f 0.693147181f
|
||||
|
||||
#define N64_LN10 2.3025850929940457
|
||||
#define N64_LN10f 2.30258509f
|
||||
|
||||
#define N64_SQRT2 1.414213562373095
|
||||
#define N64_SQRT2f 1.41421356f
|
||||
|
||||
#define N64_SQRT3 1.7320508075688773
|
||||
#define N64_SQRT3f 1.73205081f
|
||||
|
||||
#define N64_INV_SQRT3 0.57735026918962576
|
||||
#define N64_INV_SQRT3f 0.577350269f
|
||||
|
||||
#define N64_EGAMMA 0.57721566490153286
|
||||
#define N64_EGAMMAf 0.577215665f
|
||||
|
||||
#define N64_PHI 1.6180339887498948
|
||||
#define N64_PHIf 1.61803399f
|
||||
|
||||
#endif
|
||||
34
lib/n64-libc/n64-stdbool.h
Normal file
34
lib/n64-libc/n64-stdbool.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef N64_STDLIB_N64_STDBOOL_H_
|
||||
#define N64_STDLIB_N64_STDBOOL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef bool n64_bool;
|
||||
#else
|
||||
#if __STDC_VERSION__ >= 202311L
|
||||
typedef bool n64_bool;
|
||||
#else
|
||||
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
typedef _Bool n64_bool;
|
||||
#elif __GNUC__ >= 15
|
||||
typedef unsigned char __attribute__((hardbool(0, 1))) n64_bool;
|
||||
#else
|
||||
typedef unsigned char n64_bool;
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __bool_true_false_are_defined
|
||||
#define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
8
lib/n64-libc/n64-stdckdint.h
Normal file
8
lib/n64-libc/n64-stdckdint.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef N64_STDLIB_N64_STDCKDINT_H_
|
||||
#define N64_STDLIB_N64_STDCKDINT_H_
|
||||
|
||||
#define n64_ckd_add( result, a, b ) __builtin_add_overflow( a, b, result )
|
||||
#define n64_ckd_sub( result, a, b ) __builtin_sub_overflow( a, b, result )
|
||||
#define n64_ckd_mul( result, a, b ) __builtin_mul_overflow( a, b, result )
|
||||
|
||||
#endif
|
||||
15
lib/n64-libc/n64-stddef.h
Normal file
15
lib/n64-libc/n64-stddef.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus >= 199711L
|
||||
#define NULL nullptr
|
||||
#else
|
||||
#define NULL 0
|
||||
#endif
|
||||
#else
|
||||
#if __STDC_VERSION__ >= 202311L
|
||||
#define NULL nullptr
|
||||
#else
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
432
lib/n64-libc/n64-stdio-bprint.c.inc
Normal file
432
lib/n64-libc/n64-stdio-bprint.c.inc
Normal file
@@ -0,0 +1,432 @@
|
||||
#include "n64-stddef.h"
|
||||
|
||||
#include "n64-stdio-format.c.inc"
|
||||
|
||||
typedef enum {
|
||||
CSI_ALIGNMENT,
|
||||
CSI_SIGN,
|
||||
CSI_SPACE,
|
||||
CSI_ALTERNATE,
|
||||
CSI_ZEROPAD,
|
||||
CSI_WIDTH,
|
||||
CSI_PRECISION,
|
||||
CSI_LENGTH,
|
||||
CSI_FORMAT
|
||||
} n64_csi;
|
||||
|
||||
#define PCS_VARIABLE 0xAAAAAAAAu
|
||||
#define PCS_DEFAULT 0xBBBBBBBBu
|
||||
|
||||
static const char *parse_conversion_specifier( const char *format, n64_format_args *args ) {
|
||||
n64_bool isLong = false;
|
||||
|
||||
args->width = 0u;
|
||||
args->dataSize = 4u;
|
||||
args->precision = PCS_DEFAULT;
|
||||
args->defaultPrecision = 1u;
|
||||
args->leftAligned = false;
|
||||
args->alternate = false;
|
||||
args->capitalize = false;
|
||||
args->padchar = ' ';
|
||||
args->poschar = '\0';
|
||||
|
||||
n64_csi csi = CSI_ALIGNMENT;
|
||||
while( *format != '\0' ) {
|
||||
switch( csi ) {
|
||||
case CSI_ALIGNMENT:
|
||||
if( *format == '-' ) {
|
||||
args->leftAligned = true;
|
||||
format++;
|
||||
}
|
||||
csi = CSI_SIGN;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_SIGN:
|
||||
if( *format == '+' ) {
|
||||
args->poschar = '+';
|
||||
format++;
|
||||
}
|
||||
csi = CSI_SPACE;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_SPACE:
|
||||
if( *format == ' ' ) {
|
||||
if( args->poschar != '+' ) args->poschar = ' ';
|
||||
format++;
|
||||
}
|
||||
csi = CSI_ALTERNATE;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_ALTERNATE:
|
||||
if( *format == '#' ) {
|
||||
args->alternate = true;
|
||||
format++;
|
||||
}
|
||||
csi = CSI_ZEROPAD;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_ZEROPAD:
|
||||
if( *format == '0' ) {
|
||||
args->padchar = '0';
|
||||
format++;
|
||||
}
|
||||
csi = CSI_WIDTH;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_WIDTH:
|
||||
if( *format == '-' ) {
|
||||
args->leftAligned = true;
|
||||
format++;
|
||||
continue;
|
||||
} else if( *format == '0' ) {
|
||||
format++;
|
||||
continue;
|
||||
} else if( *format == '*' ) {
|
||||
args->width = PCS_VARIABLE;
|
||||
format++;
|
||||
} else if( *format > '0' && *format <= '9' ) {
|
||||
int w = 0;
|
||||
while( *format >= '0' && *format <= '9' ) {
|
||||
w *= 10;
|
||||
if( w < 0 ) return NULL;
|
||||
w += (int)*format - (int)'0';
|
||||
format++;
|
||||
}
|
||||
args->width = (unsigned int)w;
|
||||
}
|
||||
csi = CSI_PRECISION;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_PRECISION:
|
||||
if( *format == '.' ) {
|
||||
format++;
|
||||
if( *format == '-' ) {
|
||||
format++;
|
||||
while( *format >= '0' && *format <= '9' ) format++;
|
||||
} else if( *format == '*' ) {
|
||||
args->precision = PCS_VARIABLE;
|
||||
format++;
|
||||
} else if( *format >= '0' && *format <= '9' ) {
|
||||
int p = 0;
|
||||
while( *format >= '0' && *format <= '9' ) {
|
||||
p *= 10;
|
||||
if( p < 0 ) return NULL;
|
||||
p += (int)*format - (int)'0';
|
||||
format++;
|
||||
}
|
||||
args->precision = (unsigned int)p;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
csi = CSI_LENGTH;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_LENGTH:
|
||||
switch( *format ) {
|
||||
case 'h':
|
||||
format++;
|
||||
if( *format == 'h' ) {
|
||||
args->dataSize = 1u;
|
||||
format++;
|
||||
} else {
|
||||
args->dataSize = 2u;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
isLong = true;
|
||||
args->dataSize = __SIZEOF_LONG__;
|
||||
format++;
|
||||
if( *format == 'l' ) {
|
||||
args->dataSize = 8u;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
case 'L':
|
||||
isLong = true;
|
||||
args->dataSize = 8u;
|
||||
format++;
|
||||
break;
|
||||
case 'z':
|
||||
args->dataSize = __SIZEOF_SIZE_T__;
|
||||
format++;
|
||||
break;
|
||||
case 't':
|
||||
args->dataSize = __SIZEOF_PTRDIFF_T__;
|
||||
format++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
csi = CSI_FORMAT;
|
||||
__attribute__((fallthrough));
|
||||
case CSI_FORMAT:
|
||||
switch( *format ) {
|
||||
case 'c':
|
||||
args->type = 'c';
|
||||
args->dataSize = 1;
|
||||
break;
|
||||
case 's':
|
||||
args->type = 's';
|
||||
args->dataSize = 1;
|
||||
args->defaultPrecision = 0xFFFFFFFFu;
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
args->type = 'd';
|
||||
if( args->precision != PCS_DEFAULT ) args->padchar = ' ';
|
||||
break;
|
||||
case 'o':
|
||||
args->type = 'o';
|
||||
args->poschar = '\0';
|
||||
if( args->precision != PCS_DEFAULT ) args->padchar = ' ';
|
||||
break;
|
||||
case 'X':
|
||||
args->capitalize = true;
|
||||
__attribute__((fallthrough));
|
||||
case 'x':
|
||||
args->type = 'x';
|
||||
args->poschar = '\0';
|
||||
if( args->precision != PCS_DEFAULT ) args->padchar = ' ';
|
||||
break;
|
||||
case 'B':
|
||||
args->capitalize = true;
|
||||
__attribute__((fallthrough));
|
||||
case 'b':
|
||||
args->type = 'b';
|
||||
args->poschar = '\0';
|
||||
if( args->precision != PCS_DEFAULT ) args->padchar = ' ';
|
||||
break;
|
||||
case 'u':
|
||||
args->type = 'u';
|
||||
args->poschar = '\0';
|
||||
if( args->precision != PCS_DEFAULT ) args->padchar = ' ';
|
||||
break;
|
||||
case 'F':
|
||||
args->capitalize = true;
|
||||
__attribute__((fallthrough));
|
||||
case 'f':
|
||||
args->type = 'f';
|
||||
args->dataSize = isLong ? 8u : 4u;
|
||||
args->defaultPrecision = 6u;
|
||||
break;
|
||||
case 'E':
|
||||
args->capitalize = true;
|
||||
__attribute__((fallthrough));
|
||||
case 'e':
|
||||
args->type = 'e';
|
||||
args->dataSize = isLong ? 8u : 4u;
|
||||
args->defaultPrecision = 6u;
|
||||
break;
|
||||
case 'A':
|
||||
args->capitalize = true;
|
||||
__attribute__((fallthrough));
|
||||
case 'a':
|
||||
args->type = 'a';
|
||||
args->dataSize = isLong ? 8u : 4u;
|
||||
args->defaultPrecision = 0xffffffffu;
|
||||
break;
|
||||
case 'G':
|
||||
args->capitalize = true;
|
||||
__attribute__((fallthrough));
|
||||
case 'g':
|
||||
args->type = 'g';
|
||||
args->dataSize = isLong ? 8u : 4u;
|
||||
args->defaultPrecision = 6u;
|
||||
break;
|
||||
case 'n':
|
||||
args->type = 'n';
|
||||
break;
|
||||
case 'p':
|
||||
args->type = 'p';
|
||||
args->dataSize = 4u;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return ++format;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int n64_vbprintf( char *_buffer, unsigned int bufsz, n64_bool(*callback)(void*, unsigned int), void *state, const char *format, __builtin_va_list args ) {
|
||||
n64_bprint_buffer buff = {
|
||||
/* start */ _buffer,
|
||||
/* head */ _buffer,
|
||||
/* end */ _buffer + bufsz,
|
||||
callback,
|
||||
state,
|
||||
0u
|
||||
};
|
||||
|
||||
while( *format != '\0' ) {
|
||||
if( *format != '%' ) {
|
||||
n64_putc( &buff, *format );
|
||||
format++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( format[1] == '%' ) {
|
||||
n64_putc( &buff, '%' );
|
||||
format += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
n64_format_args fmt;
|
||||
format = parse_conversion_specifier( ++format, &fmt );
|
||||
if( !format ) return -1;
|
||||
|
||||
if( fmt.width == PCS_VARIABLE ) {
|
||||
const int w = __builtin_va_arg( args, int );
|
||||
if( w < 0 ) {
|
||||
fmt.leftAligned = true;
|
||||
fmt.width = (unsigned int)-w;
|
||||
} else {
|
||||
fmt.width = (unsigned int)w;
|
||||
}
|
||||
}
|
||||
|
||||
if( fmt.precision == PCS_VARIABLE ) {
|
||||
const int p = __builtin_va_arg( args, int );
|
||||
fmt.precision = (p < 0) ? fmt.defaultPrecision : (unsigned int)p;
|
||||
} else if( fmt.precision == PCS_DEFAULT ) {
|
||||
fmt.precision = fmt.defaultPrecision;
|
||||
}
|
||||
|
||||
switch( fmt.type ) {
|
||||
case 'c': {
|
||||
const char c = (char)__builtin_va_arg( args, int );
|
||||
n64_format_char( &buff, &fmt, c );
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
const char *str = (const char*)__builtin_va_arg( args, const char* );
|
||||
n64_format_string( &buff, &fmt, str );
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
if( fmt.dataSize == 8 ) {
|
||||
const long long val = __builtin_va_arg( args, long long );
|
||||
n64_format_sdec64( &buff, &fmt, val );
|
||||
} else {
|
||||
int val = __builtin_va_arg( args, int );
|
||||
if( fmt.dataSize == 2 ) {
|
||||
val = (int)(short)val;
|
||||
} else if( fmt.dataSize == 1 ) {
|
||||
val = (int)(signed char)val;
|
||||
}
|
||||
n64_format_sdec32( &buff, &fmt, val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
if( fmt.dataSize == 8 ) {
|
||||
const unsigned long long val = __builtin_va_arg( args, unsigned long long );
|
||||
n64_format_udec64( &buff, &fmt, val );
|
||||
} else {
|
||||
unsigned int val = __builtin_va_arg( args, unsigned int );
|
||||
if( fmt.dataSize == 2 ) {
|
||||
val &= 0xFFFFu;
|
||||
} else if( fmt.dataSize == 1 ) {
|
||||
val &= 0xFFu;
|
||||
}
|
||||
n64_format_udec32( &buff, &fmt, val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'o': {
|
||||
if( fmt.dataSize == 8 ) {
|
||||
const unsigned long long val = __builtin_va_arg( args, unsigned long long );
|
||||
n64_format_oct64( &buff, &fmt, val );
|
||||
} else {
|
||||
unsigned int val = __builtin_va_arg( args, unsigned int );
|
||||
if( fmt.dataSize == 2 ) {
|
||||
val &= 0xFFFFu;
|
||||
} else if( fmt.dataSize == 1 ) {
|
||||
val &= 0xFFu;
|
||||
}
|
||||
n64_format_oct32( &buff, &fmt, val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
if( fmt.dataSize == 8 ) {
|
||||
const unsigned long long val = __builtin_va_arg( args, unsigned long long );
|
||||
n64_format_hex64( &buff, &fmt, val );
|
||||
} else {
|
||||
unsigned int val = __builtin_va_arg( args, unsigned int );
|
||||
if( fmt.dataSize == 2 ) {
|
||||
val &= 0xFFFFu;
|
||||
} else if( fmt.dataSize == 1 ) {
|
||||
val &= 0xFFu;
|
||||
}
|
||||
n64_format_hex32( &buff, &fmt, val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
if( fmt.dataSize == 8 ) {
|
||||
const unsigned long long val = __builtin_va_arg( args, unsigned long long );
|
||||
n64_format_bin64( &buff, &fmt, val );
|
||||
} else {
|
||||
unsigned int val = __builtin_va_arg( args, unsigned int );
|
||||
if( fmt.dataSize == 2 ) {
|
||||
val &= 0xFFFFu;
|
||||
} else if( fmt.dataSize == 1 ) {
|
||||
val &= 0xFFu;
|
||||
}
|
||||
n64_format_bin32( &buff, &fmt, val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'g': {
|
||||
const double val = __builtin_va_arg( args, double );
|
||||
if( fmt.dataSize == 8 ) {
|
||||
n64_format_double( &buff, &fmt, val );
|
||||
} else {
|
||||
n64_format_float( &buff, &fmt, (float)val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
const double val = __builtin_va_arg( args, double );
|
||||
if( fmt.dataSize == 8 ) {
|
||||
n64_format_hexdouble( &buff, &fmt, val );
|
||||
} else {
|
||||
n64_format_hexfloat( &buff, &fmt, (float)val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
const void *ptr = __builtin_va_arg( args, const void* );
|
||||
n64_format_pointer( &buff, &fmt, ptr );
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
switch( fmt.dataSize ) {
|
||||
case 1: *__builtin_va_arg( args, signed char* ) = (signed char)buff.total; break;
|
||||
case 2: *__builtin_va_arg( args, short* ) = (short)buff.total; break;
|
||||
case 4: *__builtin_va_arg( args, int* ) = (int)buff.total; break;
|
||||
case 8: *__builtin_va_arg( args, long long* ) = (long long)buff.total; break;
|
||||
default: return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if( buff.start != buff.end ) {
|
||||
buff.callback( buff.userdata, (unsigned int)(buff.head - buff.start) );
|
||||
}
|
||||
return (int)buff.total;
|
||||
}
|
||||
|
||||
int n64_bprintf( char *buffer, unsigned int bufsz, n64_bool(*callback)(void*, unsigned int), void *state, const char *format, ... ) {
|
||||
__builtin_va_list args;
|
||||
__builtin_va_start( args, format );
|
||||
register const int result = n64_vbprintf( buffer, bufsz, callback, state, format, args );
|
||||
__builtin_va_end( args );
|
||||
return result;
|
||||
}
|
||||
1030
lib/n64-libc/n64-stdio-format.c.inc
Normal file
1030
lib/n64-libc/n64-stdio-format.c.inc
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user