Compare commits

...

8 Commits

Author SHA1 Message Date
Lephe 73ab18e457
bump version to 2.5.2 2021-06-08 11:01:27 +02:00
Lephe 8e730c2f78
replace gint/std headers with standard ones 2021-06-08 11:01:27 +02:00
Lephe 20b7238057
std: move endian.h to fxlibc 2021-06-08 10:05:33 +02:00
Lephe edcebff311
bopti: fix a VRAM overflow through the rightmost column
The checks for VRAM access account for image columns intersecting the
longword before the start of a VRAM line, but not the longword after the
start of a VRAM line. This is now fixed.
2021-06-08 09:38:09 +02:00
Lephe fc6fb9dc09
std: remove the malloc impl and string header 2021-06-07 21:52:52 +02:00
Lephe 3a6165f026
std: remove the TinyMT-based rand implementation 2021-06-07 19:16:58 +02:00
Lephe b25924d740
std: remove the asprintf/vasprintf implementation 2021-06-07 19:04:48 +02:00
Lephe 991b616a10
std: remove the printf implementation 2021-06-07 18:53:05 +02:00
41 changed files with 51 additions and 1912 deletions

View File

@ -1,7 +1,7 @@
# Build system for the gint unikernel
cmake_minimum_required(VERSION 3.15)
project(Gint VERSION 2.5.1 LANGUAGES C ASM)
project(Gint VERSION 2.5.2 LANGUAGES C ASM)
include(GitVersionNumber)
include(Fxconv)
@ -51,8 +51,6 @@ set(SOURCES_COMMON
src/kmalloc/arena_gint.c
src/kmalloc/arena_osheap.c
src/kmalloc/kmalloc.c
src/kprint/kprint.c
src/kprint/kformat_fp.c
src/mmu/mmu.c
src/render/dhline.c
src/render/dimage.c
@ -65,9 +63,6 @@ set(SOURCES_COMMON
src/rtc/rtc.c
src/rtc/rtc_ticks.c
src/spu/spu.c
src/std/aprint.c
src/std/malloc.c
src/std/print.c
src/tmu/inth-etmu.s
src/tmu/inth-tmu.s
src/tmu/sleep.c
@ -78,9 +73,6 @@ set(SOURCES_COMMON
src/usb/setup.c
src/usb/string.c
src/usb/usb.c
src/3rdparty/tinymt32/rand.c
src/3rdparty/tinymt32/tinymt32.c
src/3rdparty/grisu2b_59_56/grisu2b_59_56.c
)
set(SOURCES_FX
src/gray/engine.c
@ -132,10 +124,6 @@ include_directories(
"${FXSDK_COMPILER_INSTALL}/include/openlibm")
add_compile_options(-Wall -Wextra -std=c11 -Os -fstrict-volatile-bitfields -mtas)
# Silence extended warnings on Grisu2b code
set_source_files_properties(src/3rdparty/grisu2b_59_56/grisu2b_59_56.c PROPERTIES
COMPILE_OPTIONS "-Wno-all;-Wno-extra")
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
add_compile_definitions(FX9860G)
add_library(gint-fx STATIC ${SOURCES_COMMON} ${SOURCES_FX} ${ASSETS_FX})

View File

@ -12,16 +12,9 @@ new, richer API that takes advantage of the full capabilities of the machine.
This is free software: you may use it for any purpose, share it, modify it, and
share your changes. Credit is not required, but please let me know!
gint also includes third-party code that is distributed under its own license.
Currently, this includes:
* A stripped-down version of the [TinyMT random number generator](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html)
([GitHub repository](https://github.com/MersenneTwister-Lab/TinyMT)) by
Mutsuo Saito and Makoto Matsumoto. See `src/3rdparty/tinymt32/LICENSE.txt`.
* A stripped-down version of the [Grisu2b floating-point representation
algorithm](https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf)
with α=-59 and γ=-56, by Florian Loitsch. See `src/3rdparty/grisu2b_59_56/README`
for details, and [the original code here](https://drive.google.com/open?id=0BwvYOx00EwKmejFIMjRORTFLcTA).
gint used to include third-party code that has now been moved to the FxLibc. If
you stumble upon it in the history, check the README file at that time for
license details.
## Programming interface

View File

@ -1,155 +0,0 @@
//---
// gint:kprint - gint's printf(3)-like formatted printer
//---
#ifndef GINT_KPRINT
#define GINT_KPRINT
#include <gint/defs/types.h>
#include <gint/defs/attributes.h>
#include <stdarg.h>
//---
// Formatted printing
//---
/* kvsprint(): Formatted print to string
This function is similar to vsnprintf(3), except that variadic arguments are
passed as a pointer to va_list. For standard functions like vsnprintf(3),
see <stdio.h>. */
size_t kvsprint(char *output, size_t len, char const *format, va_list *args);
/* kprint_enable_fp(): Enable and load floating-point formats
Loads floating-point formats %e, %E, %f, %F, %g and %G. By default these
formats are not enabled because the formatting code takes a large amount of
space. Calling this function pulls the floating-point formatter from the
gint library at link time. */
void kprint_enable_fp(void);
//---
// Printer extensions
//---
/* Arguments passed to formatters */
#define KFORMAT_ARGS \
GUNUSED int spec, /* Specifier letter */ \
GUNUSED kprint_options_t *opt, /* Other options in format */ \
va_list *args /* Vararg list to read from */
/* kprint_options_t: Standard format options */
typedef struct {
/* Minimal length of formatted string (padding can be added) */
uint16_t length;
/* How much significant characters of data, meaning varies */
int16_t precision;
/* Size specifier for integers (%o, %x, %i, %d, %u), may be one of:
(0) char (8-bit)
(1) short (16-bit)
(2) int (32-bit)
(3) long (32-bit)
(4) long long (64-bit) */
uint8_t size;
/* (#) Alternative form: base prefixes, decimal point */
uint alternative :1;
/* ( ) Add a blank sign before nonnegative numbers */
uint blank_sign :1;
/* (+) Always add a sign before a number (overrides ' ') */
uint force_sign :1;
/* Alignment options: each option overrides all others before itself
NUL By default, align right
(0) Left-pad numerical values with zeros
(-) Align left by adding space on the right, dropping zeros */
uint8_t alignment;
} GPACKED(2) kprint_options_t;
/* kprint_formatter_t: Type of format function */
typedef void (*kprint_formatter_t)(KFORMAT_ARGS);
/* kprint_register(): Register a formatter
The formatter designated by the specified lowercase letter (eg 'q') is
registered. It will handle formats for both the lowercase and uppercase
formats (eg "%q" and "%Q").
Default formatters can be overridden (although not advised), but formatters
for "h" and "l" and "z" cannot be set because these letters are used as size
specifiers (eg in "%hd" or "%zu").
A formatter can be removed or disabled by registering NULL.
@spec Specifier to use, should be a lowercase letter
@kformat Format function */
void kprint_register(int spec, kprint_formatter_t kformat);
/* kprint_out(): Output a single character to the kprint buffer */
void kprint_out(int byte);
/* kprint_outn(): Output the same character <n> times */
void kprint_outn(int byte, int n);
/* kprint_outstr(): Output a string to the kprint buffer */
void kprint_outstr(char const *str, int n);
//---
// Helper functions for formatters
//---
/* kprint_geometry_t: General geometry for a format
This helper defines the structure of a format as follows:
sign v |< zeros >| |< content >|
_ _ _ _ _ _ _ _ _ + 0 x 0 0 0 0 0 0 8 a c 7 . 3 c _ _ _ _ _ _ _ _ _ _
|< left_spaces >| ^^^ prefix |< right_spaces >|
The sign character is absent if sign=0, the prefix is specified by length
and is also absent if prefix=0. */
typedef struct
{
uint16_t left_spaces; /* Spaces before content */
uint8_t sign; /* Sign character (NUL, ' ', '+' or '-') */
uint8_t prefix; /* Base prefix ('0', '0x', etc) length */
uint16_t zeros; /* For integer displays, number of zeros */
uint16_t content; /* Content length in bytes */
uint16_t right_spaces; /* Spaces after content */
/* Style of display:
KPRINT_GENERIC Sign ignored, 0-padding ignored
KPRINT_INTEGER .precision causes 0-padding
KPRINT_NUMERIC No effect */
enum { KPRINT_GENERIC = 0, KPRINT_INTEGER, KPRINT_NUMERIC } style;
} GPACKED(2) kprint_geometry_t;
/* kformat_geometry(): Calculate the geometry of a format
The caller provides as input:
* opt, as passed by the main kprint() routine
* g->prefix, the length of the desired prefix (if unused, 0)
* g->content, the natural content length for the provided data
* g->sign, the sign of the input ("+" or "-"); for KPRINT_GENERIC, 0
* g->style, which affects the meaning of options
This function outputs:
* g->sign, which will be changed to " " or NUL (0) depending on options
* All fields of g that are not part of the input
The algorithm for laying out the format is as follows.
1. For numerical and integer formats, turn a "+" sign into " " if
opt->blank_sign is set, "+" if opt->force_sign is set, NUL otherwise.
2. Compute the total amount of padding needed to reach opt->length.
3. In integer style, if a precision is specified and more than content
length plus sign and prefix, turn some padding into zeros.
4. If numerical and integer styles, if opt->alignment == '0' turn all the
padding into zeros.
5. Turn remaining padding into spaces at the left (if opt->alignment == NUL)
or right (if opt->alignment == '-').
@opt Options provided by the main kprint() routine
@g Format geometry (input/output) */
void kformat_geometry(kprint_options_t *opt, kprint_geometry_t *g);
#endif /* GINT_KPRINT */

View File

@ -1,28 +1,2 @@
//---
// gint:std:endian - Endianness conversion
//---
#ifndef GINT_STD_ENDIAN
#define GINT_STD_ENDIAN
#include <gint/defs/types.h>
#include <gint/defs/attributes.h>
/* CASIO calculators are configured as big-endian. */
#define htobe16(x) (x)
#define htole16(x) (__builtin_bswap16(x))
#define be16toh(x) (x)
#define le16toh(x) (__builtin_bswap16(x))
#define htobe32(x) (x)
#define htole32(x) (__builtin_bswap32(x))
#define be32toh(x) (x)
#define le32toh(x) (__builtin_bswap32(x))
#define htobe64(x) (x)
#define htole64(x) (__builtin_bswap64(x))
#define be64toh(x) (x)
#define le64toh(x) (__builtin_bswap64(x))
#endif /* GINT_STD_ENDIAN */
/* Now provided by fxlibc. */
#include <endian.h>

View File

@ -1,49 +1,2 @@
//---
// gint:std:stdio - a few <stdio.h> functions provided by gint
//---
#ifndef GINT_STD_STDIO
#define GINT_STD_STDIO
#include <stddef.h>
#include <stdarg.h>
/* Formatted printing functions
These functions implement most of printf(3)'s features, including:
* Signed and unsigned integer formats (%d, %i, %o, %u, %x, %X)
* Character, string and pointer formats (%c, %s, %p)
* Format options (0, #, -, (space), length, precision)
* Parameter length (hh, h, l, ll, z)
* Limiting the size of the output and still returning the whole length
* If kprint_enable_fp() from <gint/kprint.h> is called: floating-point
formats (%e, %E, %f, %F, %g, %G) (disabled by default to save space)
They do not support:
* Hexadecimal floating-point (%a, %A)
* The strerror() shorthand, since there is no errno (%m)
* Some size modifiers: long double (L), intmax_t (j), ptrdiff_t (t), and the
nonstandard synonyms q (ll) and Z (z)
* Dynamic length field (*)
* Thousands separators (') and locale-aware digits (I)
* Nonstandard synonyms %C (%lc) and %S (%ls)
A new fixed-point format %j has been added; it behaves like %d but includes
a decimal point. The number of decimal places is specified by the precision
field. For instance %.3j with 12345 prints "123.45". This can be used for
decimal fixed-point values. */
/* Print to string from var args */
int sprintf(char *str, char const *format, ...);
/* Print to string from va_list */
int vsprintf(char *str, char const *format, va_list args);
/* Print to string with limited size from var args */
int snprintf(char *str, size_t n, char const *format, ...);
/* Print to string with limited size from va_list */
int vsnprintf(char *str, size_t n, char const *format, va_list args);
/* Print to auto-allocated string */
int asprintf(char **strp, char const *format, ...);
/* Print to auto-allocated string from va_list */
int vasprintf(char **strp, char const *format, va_list args);
#endif /* GINT_STD_STDIO */
/* Now provided by fxlibc. */
#include <stdio.h>

View File

@ -1,30 +1,2 @@
//---
// gint:std:stdlib - a few <stdlib.h> functions provided by gint
//---
#ifndef GINT_STD_STDLIB
#define GINT_STD_STDLIB
#include <stddef.h>
/* malloc(): Allocate dynamic memory */
void *malloc(size_t size);
/* free(): Free dynamic memory */
void free(void *ptr);
/* calloc(): Allocate and initialize dynamic memory */
void *calloc(size_t nmemb, size_t size);
/* realloc(): Reallocate dynamic memory */
void *realloc(void *ptr, size_t size);
#define RAND_MAX 0x7fffffff
/* srand(): Seed the PRNG */
void srand(unsigned int seed);
/* rand(): Generate a pseudo-random number between 0 and RAND_MAX */
int rand(void);
#endif /* GINT_STD_STDLIB */
/* Now provided by fxlibc. */
#include <stdlib.h>

View File

@ -1,43 +1,2 @@
//---
// gint:std:string - a few <string.h> functions provided by gint
//---
#ifndef GINT_STD_STRING
#define GINT_STD_STRING
#include <stddef.h>
/* memcpy(): Copy a chunk of memory to a non-overlapping destination */
void *memcpy(void * __restrict dest, void const * __restrict src, size_t n);
/* memset(): Fill a chunk of memory with a single byte */
void *memset(void *dest, int byte, size_t n);
/* memcmp(): Compare two chunks of memory */
int memcmp(void const *s1, void const *s2, size_t n);
/* memmove(): Copy a chunk of memory to a possibly overlapping destination */
void *memmove(void *dest, void const *src, size_t n);
/* strlen(): Length of a NUL-terminated string */
size_t strlen(char const *str);
/* strncpy(): Copy a string with a size limit */
char *strncpy(char *dst, char const *src, size_t n);
/* strcat(): Concatenation a string to a pre-allocated space */
char *strcat(char *dest, const char *src);
/* strcmp(): Compare NUL-terminated strings */
int strcmp(char const *s1, char const *s2);
/* strchr(): Find the first occurrence of a character in a string */
char *strchr(char const *s, int c);
/* strrchr(): Find the last occurrence of a character in a string */
char *strrchr(char const *s, int c);
/* strchrnul(): Like strchr(), but returns end-of-string instead of NUL */
char *strchrnul(char const *s, int c);
#endif /* GINT_STD_STRING */
/* Now provided by fxlibc. */
#include <string.h>

View File

@ -1,22 +0,0 @@
Copyright (c) 2009 Florian Loitsch
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.

View File

@ -1,14 +0,0 @@
Grisu is an algorithm by Florian Loitsch to print the decimal representation of
floating-point numbers.
The original code from which this folder is extracted can be found at
<https://drive.google.com/open?id=0BwvYOx00EwKmejFIMjRORTFLcTA>.
Only a minimal variation, the Grisu2 rounding algorithm with α=-59 and γ=-56,
is present here. The code has been adapted to fit the limited runtime as well
as the use of OpenLibm.
See the original paper at <https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf>
and Florian Loitsch's home page at <https://florian.loitsch.com/publications>.
The files are licensed under the permissive conditions of the attached LICENSE.

View File

@ -1,58 +0,0 @@
/*
Copyright (c) 2009 Florian Loitsch
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.
*/
#pragma once
#include <stdint.h>
typedef struct diy_fp_t {
uint64_t f;
int e;
} diy_fp_t;
static diy_fp_t minus(diy_fp_t x, diy_fp_t y) {
diy_fp_t r = {.f = x.f - y.f, .e = x.e};
return r;
}
/*
static diy_fp_t minus(diy_fp_t x, diy_fp_t y) {
assert(x.e == y.e);
assert(x.f >= y.f);
diy_fp_t r = {.f = x.f - y.f, .e = x.e};
return r;
}
*/
static diy_fp_t multiply(diy_fp_t x, diy_fp_t y) {
uint64_t a,b,c,d,ac,bc,ad,bd,tmp,h;
diy_fp_t r; uint64_t M32 = 0xFFFFFFFF;
a = x.f >> 32; b = x.f & M32;
c = y.f >> 32; d = y.f & M32;
ac = a*c; bc = b*c; ad = a*d; bd = b*d;
tmp = (bd>>32) + (ad&M32) + (bc&M32);
tmp += 1U << 31; /// mult_round
r.f = ac+(ad>>32)+(bc>>32)+(tmp >>32);
r.e = x.e + y.e + 64;
return r;
}

View File

@ -1,110 +0,0 @@
/*
Copyright (c) 2009 Florian Loitsch
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.
*/
#pragma once
#include "diy_fp.h"
#include "powers.h"
#include <stdbool.h>
typedef union {
double d;
uint64_t n;
} converter_t;
static uint64_t double_to_uint64(double d) { converter_t tmp; tmp.d = d; return tmp.n; }
static double uint64_to_double(uint64_t d64) { converter_t tmp; tmp.n = d64; return tmp.d; }
#define DP_SIGNIFICAND_SIZE 52
#define DP_EXPONENT_BIAS (0x3FF + DP_SIGNIFICAND_SIZE)
#define DP_MIN_EXPONENT (-DP_EXPONENT_BIAS)
#define DP_EXPONENT_MASK 0x7FF0000000000000
#define DP_SIGNIFICAND_MASK 0x000FFFFFFFFFFFFF
#define DP_HIDDEN_BIT 0x0010000000000000
static diy_fp_t normalize_diy_fp(diy_fp_t in) {
diy_fp_t res = in;
/* Normalize now */
/* the original number could have been a denormal. */
while (! (res.f & DP_HIDDEN_BIT))
{
res.f <<= 1;
res.e--;
}
/* do the final shifts in one go. Don't forget the hidden bit (the '-1') */
res.f <<= (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 1);
res.e = res.e - (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 1);
return res;
}
static diy_fp_t double2diy_fp(double d) {
uint64_t d64 = double_to_uint64(d);
int biased_e = (d64 & DP_EXPONENT_MASK) >> DP_SIGNIFICAND_SIZE;
uint64_t significand = (d64 & DP_SIGNIFICAND_MASK);
diy_fp_t res;
if (biased_e != 0)
{
res.f = significand + DP_HIDDEN_BIT;
res.e = biased_e - DP_EXPONENT_BIAS;
} else {
res.f = significand;
res.e = DP_MIN_EXPONENT + 1;
}
return res;
}
static diy_fp_t normalize_boundary(diy_fp_t in) {
diy_fp_t res = in;
/* Normalize now */
/* the original number could have been a denormal. */
while (! (res.f & (DP_HIDDEN_BIT << 1)))
{
res.f <<= 1;
res.e--;
}
/* do the final shifts in one go. Don't forget the hidden bit (the '-1') */
res.f <<= (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2);
res.e = res.e - (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2);
return res;
}
static void normalized_boundaries(double d, diy_fp_t* out_m_minus, diy_fp_t* out_m_plus) {
diy_fp_t v = double2diy_fp(d);
diy_fp_t pl, mi;
bool significand_is_zero = v.f == DP_HIDDEN_BIT;
pl.f = (v.f << 1) + 1; pl.e = v.e - 1;
pl = normalize_boundary(pl);
if (significand_is_zero)
{
mi.f = (v.f << 2) - 1;
mi.e = v.e - 2;
} else {
mi.f = (v.f << 1) - 1;
mi.e = v.e - 1;
}
mi.f <<= mi.e - pl.e;
mi.e = pl.e;
*out_m_plus = pl;
*out_m_minus = mi;
}

View File

@ -1,27 +0,0 @@
/*
Copyright (c) 2009 Florian Loitsch
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.
*/
#pragma once
void grisu2(double v, char* buffer, int* length, int* K);

View File

@ -1,95 +0,0 @@
/*
Copyright (c) 2009 Florian Loitsch
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.
*/
#include "diy_fp.h"
#include "k_comp.h"
#include "double.h"
#include "powers.h"
#include <stdbool.h>
#include "grisu2.h"
#include <stdint.h>
#define TEN9 1000000000
void grisu_round(char* buffer, int len,
uint64_t delta, uint64_t rest,
uint64_t ten_kappa, uint64_t wp_w) {
while (rest < wp_w &&
delta - rest >= ten_kappa &&
(rest + ten_kappa < wp_w || /// closer
wp_w - rest > rest+ten_kappa - wp_w))
{
buffer[len-1]--; rest += ten_kappa;
}
}
void digit_gen(diy_fp_t W, diy_fp_t Mp, diy_fp_t delta,
char* buffer, int* len, int* K) {
uint32_t div; int d,kappa; diy_fp_t one, wp_w;
wp_w = minus(Mp, W);
one.f = ((uint64_t) 1) << -Mp.e; one.e = Mp.e;
uint32_t p1 = Mp.f >> -one.e; /// Mp_cut
uint64_t p2 = Mp.f & (one.f - 1);
*len = 0; kappa = 10; div = TEN9;
while (kappa > 0) {
d = p1 / div;
if (d || *len) buffer[(*len)++] = '0' + d; /// Mp_inv1
p1 %= div; kappa--;
uint64_t tmp = (((uint64_t)p1)<<-one.e)+p2;
if (tmp <= delta.f) { /// Mp_delta
*K += kappa;
grisu_round(buffer, *len, delta.f, tmp, ((uint64_t)div) << -one.e, wp_w.f);
return;
}
div /= 10;
}
uint64_t unit = 1;
while (1) {
p2 *= 10; delta.f *= 10; unit *= 10;
d = p2 >> -one.e;
if (d || *len) buffer[(*len)++] = '0' + d;
p2 &= one.f - 1; kappa--;
if (p2 < delta.f) {
*K += kappa;
grisu_round(buffer, *len, delta.f, p2, one.f, wp_w.f*unit);
return;
}
}
}
void grisu2(double v, char* buffer, int* length, int* K) {
diy_fp_t w_m, w_p;
int q = 64, alpha = -59, gamma = -56; int pos;
normalized_boundaries(v, &w_m, &w_p);
diy_fp_t w = normalize_diy_fp(double2diy_fp(v));
int mk = k_comp(w_p.e + q, alpha, gamma);
diy_fp_t c_mk = cached_power(mk);
diy_fp_t W = multiply(w, c_mk);
diy_fp_t Wp = multiply(w_p, c_mk);
diy_fp_t Wm = multiply(w_m, c_mk);
Wm.f++; Wp.f--;
diy_fp_t delta = minus(Wp, Wm);
*K = -mk;
digit_gen(W, Wp, delta, buffer, length, K);
}

View File

@ -1,32 +0,0 @@
/*
Copyright (c) 2009 Florian Loitsch
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.
*/
#pragma once
#include <openlibm.h>
#define D_1_LOG2_10 0.30102999566398114 // 1 / lg(10)
static int k_comp(int e, int alpha, int gamma) {
return ceil((alpha-e+63) * D_1_LOG2_10);
}

View File

@ -1,27 +0,0 @@
/*
Copyright (c) 2009 Florian Loitsch
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.
*/
#pragma once
#include "diy_fp.h"
#include "powers_ten_round64.h"

File diff suppressed because one or more lines are too long

View File

@ -1,29 +0,0 @@
Copyright (c) 2011 Mutsuo Saito, Makoto Matsumoto, Hiroshima
University and The University of Tokyo. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the Hiroshima University nor the names of
its contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,14 +0,0 @@
#include <gint/std/stdlib.h>
#include "tinymt32.h"
static tinymt32_t random;
void srand(unsigned int seed)
{
tinymt32_init(&random, seed);
}
int rand(void)
{
return tinymt32_generate_uint32(&random) & 0x7fffffff;
}

View File

@ -1,121 +0,0 @@
/**
* @file tinymt32.c
*
* @brief Tiny Mersenne Twister only 127 bit internal state
*
* @author Mutsuo Saito (Hiroshima University)
* @author Makoto Matsumoto (The University of Tokyo)
*
* Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
* Hiroshima University and The University of Tokyo.
* All rights reserved.
*
* The 3-clause BSD License is applied to this software, see
* LICENSE.txt
*/
/* Note: this is a stripped-down version of TinyMT that only includes the
32-bit integer generator. For the full version, please see
<https://github.com/MersenneTwister-Lab/TinyMT>. */
#include "tinymt32.h"
#define TINYMT32_SH0 1
#define TINYMT32_SH1 10
#define TINYMT32_SH8 8
#define TINYMT32_MASK 0x7fffffff
/**
* This function changes internal state of tinymt32.
* Users should not call this function directly.
* @param random tinymt internal status
*/
static void tinymt32_next_state(tinymt32_t * random) {
uint32_t x;
uint32_t y;
y = random->status[3];
x = (random->status[0] & TINYMT32_MASK)
^ random->status[1]
^ random->status[2];
x ^= (x << TINYMT32_SH0);
y ^= (y >> TINYMT32_SH0) ^ x;
random->status[0] = random->status[1];
random->status[1] = random->status[2];
random->status[2] = x ^ (y << TINYMT32_SH1);
random->status[3] = y;
random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
}
/**
* This function outputs 32-bit unsigned integer from internal state.
* Users should not call this function directly.
* @param random tinymt internal status
* @return 32-bit unsigned pseudorandom number
*/
static uint32_t tinymt32_temper(tinymt32_t * random) {
uint32_t t0, t1;
t0 = random->status[3];
#if defined(LINEARITY_CHECK)
t1 = random->status[0]
^ (random->status[2] >> TINYMT32_SH8);
#else
t1 = random->status[0]
+ (random->status[2] >> TINYMT32_SH8);
#endif
t0 ^= t1;
t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
return t0;
}
/**
* This function outputs 32-bit unsigned integer from internal state.
* @param random tinymt internal status
* @return 32-bit unsigned integer r (0 <= r < 2^32)
*/
uint32_t tinymt32_generate_uint32(tinymt32_t * random) {
tinymt32_next_state(random);
return tinymt32_temper(random);
}
#define MIN_LOOP 8
#define PRE_LOOP 8
/**
* This function certificate the period of 2^127-1.
* @param random tinymt state vector.
*/
static void period_certification(tinymt32_t * random) {
if ((random->status[0] & TINYMT32_MASK) == 0 &&
random->status[1] == 0 &&
random->status[2] == 0 &&
random->status[3] == 0) {
random->status[0] = 'T';
random->status[1] = 'I';
random->status[2] = 'N';
random->status[3] = 'Y';
}
}
/**
* This function initializes the internal state array with a 32-bit
* unsigned integer seed.
* @param random tinymt state vector.
* @param seed a 32-bit unsigned integer used as a seed.
*/
void tinymt32_init(tinymt32_t * random, uint32_t seed) {
random->status[0] = seed;
random->status[1] = random->mat1;
random->status[2] = random->mat2;
random->status[3] = random->tmat;
for (int i = 1; i < MIN_LOOP; i++) {
random->status[i & 3] ^= i + UINT32_C(1812433253)
* (random->status[(i - 1) & 3]
^ (random->status[(i - 1) & 3] >> 30));
}
period_certification(random);
for (int i = 0; i < PRE_LOOP; i++) {
tinymt32_next_state(random);
}
}

View File

@ -1,40 +0,0 @@
#ifndef TINYMT32_H
#define TINYMT32_H
/**
* @file tinymt32.h
*
* @brief Tiny Mersenne Twister only 127 bit internal state
*
* @author Mutsuo Saito (Hiroshima University)
* @author Makoto Matsumoto (University of Tokyo)
*
* Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
* Hiroshima University and The University of Tokyo.
* All rights reserved.
*
* The 3-clause BSD License is applied to this software, see
* LICENSE.txt
*/
/* Note: this is a stripped-down version of TinyMT that only includes the
32-bit integer generator. For the full version, please see
<https://github.com/MersenneTwister-Lab/TinyMT>. */
#include <stdint.h>
/**
* tinymt32 internal state vector and parameters
*/
struct TINYMT32_T {
uint32_t status[4];
uint32_t mat1;
uint32_t mat2;
uint32_t tmat;
};
typedef struct TINYMT32_T tinymt32_t;
uint32_t tinymt32_generate_uint32(tinymt32_t *random);
void tinymt32_init(tinymt32_t *random, uint32_t seed);
#endif

View File

@ -3,13 +3,13 @@
//---
#include <gint/defs/types.h>
#include <gint/std/stdlib.h>
#include <gint/drivers/t6k11.h>
#include <gint/gray.h>
#include <gint/display.h>
#include <gint/timer.h>
#include <stdlib.h>
#include "../render-fx/render-fx.h"
/* Three additional video RAMS, allocated statically if --static-gray was set

View File

@ -5,7 +5,8 @@
#include <gint/hardware.h>
#include <gint/cpu.h>
#include <gint/mpu/intc.h>
#include <gint/std/string.h>
#include <string.h>
//---
// Interrupt controllers

View File

@ -8,7 +8,8 @@
#include <gint/defs/types.h>
#include <gint/defs/util.h>
#include <gint/mpu/pfc.h>
#include <gint/std/string.h>
#include <string.h>
/* Holds information about the current platform */
GBSS uint32_t gint[HW_KEYS];

View File

@ -4,14 +4,15 @@
#include <gint/gint.h>
#include <gint/drivers.h>
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/hardware.h>
#include <gint/mmu.h>
#include <gint/mpu/intc.h>
#include <gint/kmalloc.h>
#include <gint/cpu.h>
#include <string.h>
#include <stdlib.h>
#include "vbr.h"
#include "kernel.h"

View File

@ -1,6 +1,7 @@
#include <gint/gint.h>
#include <gint/display.h>
#include <gint/std/string.h>
#include <string.h>
int __Timer_Install(int id, void (*handler)(void), int delay);
int __Timer_Start(int id);

View File

@ -2,7 +2,8 @@
#include <gint/cpu.h>
#include <gint/gint.h>
#include <gint/defs/call.h>
#include <gint/std/stdlib.h>
#include <stdlib.h>
//---
// World buffer

View File

@ -6,7 +6,8 @@
#include <gint/drivers/keydev.h>
#include <gint/defs/types.h>
#include <gint/defs/util.h>
#include <gint/std/string.h>
#include <string.h>
#include <stdarg.h>
void keydev_init(keydev_t *d)

View File

@ -3,10 +3,11 @@
//---
#include <gint/kmalloc.h>
#include <gint/std/string.h>
#include <gint/defs/attributes.h>
#include <gint/defs/util.h>
#include <string.h>
/* block_t: A memory block managed by the heap.
The heap is a sequence of blocks made of a block_t header (4 bytes) and raw

View File

@ -4,9 +4,10 @@
#include <gint/kmalloc.h>
#include <gint/defs/util.h>
#include <gint/std/string.h>
#include <gint/config.h>
#include <string.h>
/* Maximum number of arenas */
#define KMALLOC_ARENA_MAX 8

View File

@ -1,282 +0,0 @@
//---
// gint:kprint:kformat-fp: Floating-point formatted printing
//
// This object file provides floating-point formatters. It can be linked in by
// calling kprint_enable_fp() and will automatically register floating-point
// formatters that use the Grisu2b algorithm.
//---
#include <gint/defs/types.h>
#include <gint/defs/util.h>
#include <gint/kprint.h>
#include "../3rdparty/grisu2b_59_56/grisu2.h"
//---
// String generation for doubles
//---
/* The grisu2() function does not have a size limit so we generate into a
buffer large enough to hold the result. */
static char digit_buffer[50];
/* Round a number at the specified place (which can be out of bounds). An extra
byte before the buffer should be secured to leave room for a new digit in
case a carry reaches there. Returns the new start-of-buffer.
@buffer Buffer with generated digits, updated if needed
@length Number of digits generated in the buffer, updated if needed
@e Location of decimal dot relative to integer in buffer
@place Decimal to place to round to */
static void round_str(char **buffer_ptr, int *length, int e, int place)
{
char *buffer = *buffer_ptr;
/* Interpret place as relative to buffer indices */
place += *length + e - 1;
/* Specified place is out-of-bounds */
if(place < 0 || place >= *length - 1) return;
/* Next digit is 0..4 so rounding has no effect */
if(buffer[place + 1] < '5') return;
/* Propagate carries if needed */
while(place >= -1)
{
buffer[place]++;
if(buffer[place] <= '9') break;
buffer[place] = '0';
place--;
}
/* Add one digit if needed */
if(place >= 0) return;
(*buffer_ptr)--;
(*length)++;
}
/* Remove zeros at the end of the digits, reducing [length] accordingly. */
static int remove_zeros(char *buffer, int length, int unremovable)
{
int removed = 0;
while(length > unremovable && buffer[length - 1] == '0')
{
buffer[length - 1] = 0;
length--;
removed++;
}
return removed;
}
/* Handles infinities and NaNs. */
static int special_notation(double v, int upper)
{
if(__builtin_isinf(v) && v < 0)
{
kprint_outstr(upper ? "-INF" : "-inf", 4);
return 1;
}
if(__builtin_isinf(v))
{
kprint_outstr(upper ? "INF" : "inf", 3);
return 1;
}
if(__builtin_isnan(v))
{
kprint_outstr(upper ? "NAN" : "nan", 3);
return 1;
}
return 0;
}
/* Prints decimal explicitly for %f and %g. */
static void direct_notation(kprint_options_t *opt, kprint_geometry_t g,
char *digits, int length, int e)
{
/* Number of characters for decimal part, including dot */
int dec_chars = opt->precision + (opt->precision > 0);
/* See case discussion below */
g.content = (length + e >= 0) ? length + e + dec_chars : 1 + dec_chars;
kformat_geometry(opt, &g);
kprint_outn(' ', g.left_spaces);
if(g.sign) kprint_out(g.sign);
kprint_outn('0', g.zeros);
int pre = opt->precision;
if(e >= 0) /* xxxxxx00[.00] */
{
/* Decimal dot is after digits; rounding never occurs */
kprint_outstr(digits, length);
kprint_outn('0', e);
if(pre > 0)
{
kprint_out('.');
kprint_outn('0', pre);
}
}
else if(length + e > 0) /* xxxy(.xx), xx.xy(xx), xx.xxxx[00] */
{
/* Decimal dot is within the digits; we might have rounded */
kprint_outstr(digits, length + e);
if(pre > 0)
{
kprint_out('.');
kprint_outstr(digits + length + e, min(-e, pre));
kprint_outn('0', pre + e);
}
}
else if(length + e <= 0) /* 0.00(00xxxx), 0.00xy(xx), 0.00xxxx00 */
{
/* Decimal dot is before the digits; we might have rounded */
kprint_out('0');
if(pre > 0)
{
kprint_out('.');
kprint_outn('0', min(-e - length, pre));
kprint_outstr(digits, min(length, pre + length + e));
kprint_outn('0', pre + e);
}
}
kprint_outn(' ', g.right_spaces);
}
/* Prints exponent notation for %e and %g. */
static void exponent_notation(kprint_options_t *opt, kprint_geometry_t g,
char *digits, int length, int e, int uppercase)
{
int true_e = e + length - 1;
/* Number of characters for decimal part and for exponent */
int dec_chars = opt->precision + (opt->precision > 0);
int exp_chars = 4 + (true_e >= 100 || true_e <= -100);
g.content = 1 + dec_chars + exp_chars;
kformat_geometry(opt, &g);
kprint_outn(' ', g.left_spaces);
if(g.sign) kprint_out(g.sign);
kprint_outn('0', g.zeros);
/* Digits */
kprint_out(digits[0]);
if(opt->precision > 0)
{
kprint_out('.');
kprint_outstr(digits + 1, min(length - 1, opt->precision));
kprint_outn('0', opt->precision - (length - 1));
}
/* Exponent */
kprint_out(uppercase ? 'E' : 'e');
kprint_out(true_e >= 0 ? '+' : '-');
if(true_e < 0) true_e = -true_e;
if(true_e >= 100)
{
kprint_out(true_e / 100 + '0');
true_e %= 100;
}
kprint_out(true_e / 10 + '0');
kprint_out(true_e % 10 + '0');
kprint_outn(' ', g.right_spaces);
}
//---
// Formatters for kprint
//---
static void kformat_fp(KFORMAT_ARGS)
{
double v = va_arg(*args, double);
digit_buffer[0] = '0';
char *digits = digit_buffer + 1;
int length = 0, e = 0;
int is_e = (spec | 0x20) == 'e';
int is_f = (spec | 0x20) == 'f';
int is_g = (spec | 0x20) == 'g';
/* In %e and %f, default to 6 decimals. In %g, default to 6 significant
digits, and force to at least 1 */
if(opt->precision < 0) opt->precision = 6;
if(opt->precision == 0 && is_g) opt->precision = 1;
if(special_notation(v, (spec & 0x20) == 0)) return;
/* fabs(v) = int(digits) * 10^e */
if(v == 0.0) digits[length++] = '0';
else grisu2(v, digits, &length, &e);
digits[length] = 0;
/* In %f and %e, .precision is the number of decimal places; in %g, it
is the number of significant digits. Determine the number of decimal
places for the rounding (which is one more than the final number if
a carry creates a new significant digit on the left) */
int round_place = opt->precision;
if(is_e) round_place -= (length + e - 1);
if(is_g) round_place -= (length + e);
/* Round off to the specified number of decimal places. digits and
length may extend one place left because of carries */
round_str(&digits, &length, e, round_place);
kprint_geometry_t g = {
.sign = (v < 0) ? '-' : '+',
.prefix = 0,
.style = KPRINT_NUMERIC,
};
if(is_f) return direct_notation(opt, g, digits, length, e);
if(is_e) return exponent_notation(opt, g, digits, length, e,spec=='E');
int true_e = length + e - 1;
int extreme = (true_e < -4) || (true_e >= opt->precision);
/* %g is left. Remove decimal zeros at the end of the digit string,
starting from the last-shown digit. Keep all figits before the
point, the amount of which depends on the mode */
int removed = remove_zeros(digits, min(length, opt->precision),
extreme ? 1 : true_e + 1);
opt->precision -= removed;
if(extreme)
{
/* Don't print more significant digits than we have digits
(elimination of trailing zeros) */
opt->precision = min(opt->precision, length);
/* There is one leading digit and this many decimal places */
opt->precision--;
return exponent_notation(opt, g, digits, length, e, spec=='G');
}
else
{
/* Number of digits before the point */
int leading_digits = true_e + 1;
/* Eliminate trailing zeros after the point */
opt->precision = min(opt->precision, length);
/* Remove leading digits from decimal place count */
opt->precision -= leading_digits;
return direct_notation(opt, g, digits, length, e);
}
}
/* kprint_enable_fp(): Enable and load floating-point formats */
void kprint_enable_fp(void)
{
kprint_register('e', kformat_fp);
kprint_register('f', kformat_fp);
kprint_register('g', kformat_fp);
}

View File

@ -1,539 +0,0 @@
//---
// gint:kprint - gint's printf(3)-like formatted printer
//
// Things to change when creating new formats:
// -> List of prototypes at the end of the definition section
// -> Formatted table just below the list of prototypes
// -> List of non-numerical specifiers in kformat_geometry()
//---
#include <gint/std/stdio.h>
#include <gint/std/string.h>
#include <gint/kprint.h>
#include <gint/defs/attributes.h>
#include <gint/defs/types.h>
#include <gint/defs/util.h>
#include <stdarg.h>
//---
// kprint() definitions
//---
#define KPRINT_BUFSIZE 64
/* Current position in the output buffer */
static char *kprint_ptr = NULL;
/* Limit of the output buffer */
static char *kprint_limit = NULL;
/* Total number of characters written for this call to kprint() */
static size_t kprint_count = 0;
/* Address of the current output buffer */
static char *kprint_buffer = NULL;
/* Internal buffer, used in many cases */
static char kprint_internal[KPRINT_BUFSIZE];
/* Output kind for this execution of kprint() */
static enum {
/* Output is user-provided string, then internal buffer for the rest */
KPrintOutputString = 0,
/* Output is a device, file descriptor, whatever */
// KprintOutputDevice = 1,
} kprint_type;
/* Default formatters */
static void kformat_char (KFORMAT_ARGS);
static void kformat_int (KFORMAT_ARGS);
static void kformat_uint (KFORMAT_ARGS);
static void kformat_ptr (KFORMAT_ARGS);
static void kformat_str (KFORMAT_ARGS);
static void kformat_fixed(KFORMAT_ARGS);
/* Formatter functions for a..z */
kprint_formatter_t kprint_formatters[26] = {
/* Standard formats plus the 'j' for fixed-point integers in base 10 */
NULL, NULL, kformat_char, kformat_int,
NULL, NULL, NULL, NULL,
kformat_int, kformat_fixed, NULL, NULL,
NULL, NULL, kformat_uint, kformat_ptr,
NULL, NULL, kformat_str, NULL,
kformat_uint, NULL, NULL, kformat_uint,
NULL, NULL,
};
/* kprint_register(): Register a formatter */
void kprint_register(int spec, kprint_formatter_t kformat)
{
/* Non-letters */
if(spec < 'a' || spec > 'z') return;
/* Size-specifying letters */
if(spec == 'h' || spec == 'l' || spec == 'L' || spec == 'z') return;
kprint_formatters[spec - 'a'] = kformat;
}
//---
// Output functions
//---
/* kprint_flush(): Flush the buffer when it's full */
static void kprint_flush(void)
{
/* Update the number of flushed characters */
kprint_count += kprint_ptr - kprint_buffer;
if(kprint_type != KPrintOutputString) return;
/* Make sure to write a NUL at the end of the string, even if
it means overriding one of the generated characters */
if(kprint_buffer != kprint_internal)
{
char *nul = min(kprint_ptr, kprint_limit - 1);
*nul = 0x00;
}
/* Switch to the internal buffer now that the output string has
been filled */
kprint_buffer = kprint_internal;
kprint_limit = kprint_internal + KPRINT_BUFSIZE;
kprint_ptr = kprint_buffer;
}
/* kprint_out(): Output a single character to the kprint buffer */
GINLINE void kprint_out(int byte)
{
if(kprint_ptr >= kprint_limit) kprint_flush();
*kprint_ptr++ = byte;
}
/* kprint_outn(): Output the same character <n> times */
GINLINE void kprint_outn(int byte, int n)
{
while(n-- > 0) kprint_out(byte);
}
/* kprint_outstr(): Output a string to the kprint buffer */
GINLINE void kprint_outstr(char const *str, int n)
{
for(int i = 0; i < n; i++) kprint_out(str[i]);
}
//---
// Parsing helpers
//---
/* kprint_opt(): Parse option strings */
kprint_options_t kprint_opt(char const **options_ptr)
{
/* No options enabled by default, set the size to int */
kprint_options_t opt = { .size = 2, .precision = -1 };
/* This function acts as a deterministic finite automaton */
enum {
basic, /* Reading option characters */
length, /* Reading length digits */
precision, /* Reading precision digits */
} state = basic;
char const *options = *options_ptr;
for(int c; (c = *options); options++)
{
int c_low = c | 0x20;
if(c_low >= 'a' && c_low <= 'z' && c != 'h' && c != 'l' &&
c != 'L') break;
if(c == '.')
{
state = precision;
opt.precision = 0;
continue;
}
else if(state == length && c >= '0' && c <= '9')
{
opt.length = opt.length * 10 + (c - '0');
continue;
}
else if(state == precision && c >= '0' && c <= '9')
{
opt.precision = opt.precision * 10 + (c - '0');
continue;
}
/* Remain in basic state mode */
state = basic;
if(c == '#') opt.alternative = 1;
if(c == ' ') opt.blank_sign = 1;
if(c == '+') opt.force_sign = 1;
/* Alignment options, including priority */
if((c == '-' || c == '0') && opt.alignment != '0')
{
opt.alignment = c;
}
/* Data size */
if(c == 'h') opt.size--;
if(c == 'l') opt.size++;
if(c == 'z') opt.size = 3;
if(c == 'L') {}
if(c >= '1' && c <= '9') state = length, options--;
}
*options_ptr = options;
return opt;
}
//---
// Base formatted printer
//---
/* kprint(): The kernel's formatted printer */
void kprint(char const *format, va_list *args)
{
int c, spec;
kprint_options_t opt;
while((c = *format++))
{
if(c != '%')
{
kprint_out(c);
continue;
}
if(!(c = *format)) break;
/* '%' character */
if(c == '%')
{
kprint_out('%');
format++;
continue;
}
opt = kprint_opt(&format);
spec = *format++;
int id = (spec | 0x20) - 'a';
if(id >= 0 && id < 26 && kprint_formatters[id])
kprint_formatters[id](spec, &opt, args);
}
kprint_flush();
}
/* kvsprint(): Formatted print to string */
size_t kvsprint(char *output, size_t length, char const *format, va_list *args)
{
kprint_buffer = output;
kprint_limit = output + length;
kprint_count = 0;
kprint_ptr = kprint_buffer;
kprint_type = KPrintOutputString;
kprint(format, args);
return kprint_count;
}
//---
// Formatter helpers
//---
/* kformat_geometry(): Calculate the geometry of a format */
void kformat_geometry(kprint_options_t *opt, kprint_geometry_t *g)
{
int integral = (g->style == KPRINT_INTEGER);
int numerical = (g->style == KPRINT_NUMERIC) || integral;
ssize_t padding;
/* Sign character (no discussion required for negative values) */
if(numerical && g->sign == '+')
{
g->sign = 0;
if(opt->blank_sign) g->sign = ' ';
if(opt->force_sign) g->sign = '+';
}
g->zeros = 0;
padding = opt->length - (g->sign != 0) - g->prefix
- max(g->content, opt->precision);
if(padding < 0) padding = 0;
/* In integral modes, precision forces zeros */
if(integral && opt->precision >= 0)
{
if(opt->alignment == '0') opt->alignment = 0;
ssize_t zeros = opt->precision - g->content;
if(zeros > 0) g->zeros = zeros;
}
if(opt->alignment == '0')
{
/* Zeros are only allowed in numerical modes */
if(numerical) g->zeros = padding;
else g->left_spaces = padding;
}
else if(opt->alignment == '-')
{
g->right_spaces = padding;
}
else
{
g->left_spaces = padding;
}
}
/* digits_10(): Generate digits in base 10
Fills up the provided digit string from least significant to most
significant digit, not adding zeros except if argument is zero. Returns the
number of digits. No NUL terminator is added. */
static int digits_10(char *str, uint64_t n)
{
int digits = 0;
while(n || !digits)
{
/* TODO: Use qdiv() in kprint's digits_10() */
str[digits++] = (n % 10) + '0';
n /= 10;
}
return digits;
}
/* digits_16(): Generate digits in base 16 */
static int digits_16(char *str, int uppercase, uint64_t n)
{
char *hex = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
int digits = 0;
while(n || !digits)
{
str[digits++] = hex[n & 0xf];
n >>= 4;
}
return digits;
}
/* digits_8(): Generate digits in base 8 */
static int digits_8(char *str, uint64_t n)
{
int digits = 0;
while(n || !digits)
{
str[digits++] = (n & 0x7) + '0';
n >>= 3;
}
return digits;
}
//---
// Loading helpers
//---
static int64_t load_i(int size, va_list *args)
{
/* All smaller types are promoted to int with sign extension, so we
don't need to care about them. */
if(size == 3) return va_arg(*args, long);
if(size == 4) return va_arg(*args, long long);
return va_arg(*args, int);
}
static uint64_t load_u(int size, va_list *args)
{
/* Again, no need to care about small types */
if(size == 3) return va_arg(*args, unsigned long);
if(size == 4) return va_arg(*args, unsigned long long);
return va_arg(*args, unsigned int);
}
//---
// Individual formatters
//---
/* kformat_char(): Character formatter (%c)
(-) Move spaces to the right
{len} Specifies numbers of (whitespace-padded) characters to print */
static void kformat_char(KFORMAT_ARGS)
{
int c = va_arg(*args, int);
kprint_geometry_t g = {
.prefix = 0, .sign = 0, .content = 1,
};
kformat_geometry(opt, &g);
kprint_outn(' ', g.left_spaces);
kprint_out(c);
kprint_outn(' ', g.right_spaces);
}
/* kformat_str(): String formatter (%s)
(-) Move spaces to the right
{len} Minimal numbers of characters to output
{pre} Maximal numbers of bytes to read from argument */
static void kformat_str(KFORMAT_ARGS)
{
char const *s = va_arg(*args, char const *);
/* Compute content length, which is the smallest of two sizes: the
length set as precision and the actual length of the string */
size_t len = 0;
uint32_t precision = opt->precision ? opt->precision : (-1);
while(s[len] && len < precision) len++;
kprint_geometry_t g = {
.prefix = 0, .sign = 0, .content = len,
};
kformat_geometry(opt, &g);
kprint_outn(' ', g.left_spaces);
for(size_t i = 0; i < len; i++) kprint_out(s[i]);
kprint_outn(' ', g.right_spaces);
}
/* kformat_int(): Integer formatter (%d, %i)
(0) Pad with zeros, rather than spaces, on the left
(-) Move spaces to the right (overrides '0', extends {pre})
( ) Force a blank sign before nonnegative numbers
(+) Force a sign before every number (overrides ' ')
{len} Minimal number of characters to print
{pre} Forces a minimal number of digits, creating 0s (overrides '0') */
static void kformat_int(KFORMAT_ARGS)
{
int64_t n = load_i(opt->size, args);
/* Compute the sign and the absolute value */
kprint_geometry_t g = {
.sign = (n < 0) ? '-' : '+',
.prefix = 0,
.style = KPRINT_INTEGER,
};
if(n < 0) n = -n;
/* Get the digit string */
char digits[32];
int pure, total;
pure = digits_10(digits, n);
if(opt->precision == 0 && !n) pure = 0;
total = max(pure, opt->precision);
g.content = total;
kformat_geometry(opt, &g);
/* Print the result */
kprint_outn(' ', g.left_spaces);
if(g.sign) kprint_out(g.sign);
kprint_outn('0', g.zeros);
kprint_outn('0', total - pure);
for(int i = pure - 1; i >= 0; i--) kprint_out(digits[i]);
kprint_outn(' ', g.right_spaces);
}
/* kformat_uint(): Unsigned integer formatter in various bases (%u, %o, %x)
(#) Enable base prefixes ("0" in octal, "0x" in hexadecimal)
(0) Pad with zeros, rather than spaces, on the left
(-) Move spaces to the right (overrides '0', extends {pre})
{len} Minimal number of characters to print
{pre} Forces a minimal number of digits, creating 0s (overrides '0') */
static void kformat_uint(KFORMAT_ARGS)
{
uint64_t n = load_u(opt->size, args);
char digits[48];
int pure = 0, total;
int specl = spec | 0x20;
if(specl == 'u') pure = digits_10(digits, n);
if(specl == 'o') pure = digits_8(digits, n);
if(specl == 'x') pure = digits_16(digits, spec == 'X', n);
if(opt->precision == 0 && !n) pure = 0;
total = max(pure, opt->precision);
/* Prefix length */
size_t prefix = 0;
if(opt->alternative) prefix = (specl != 'u') + (specl == 'x');
kprint_geometry_t g = {
.sign = 0, .prefix = prefix, .content = total,
.style = KPRINT_INTEGER,
};
kformat_geometry(opt, &g);
/* Output */
kprint_outn(' ', g.left_spaces);
if(opt->alternative)
{
if(specl != 'u') kprint_out('0');
if(specl == 'x') kprint_out(spec);
}
kprint_outn('0', g.zeros);
kprint_outn('0', total - pure);
for(int i = pure - 1; i >= 0; i--) kprint_out(digits[i]);
kprint_outn(' ', g.right_spaces);
}
/* kformat_ptr(): Pointer formatter */
static void kformat_ptr(KFORMAT_ARGS)
{
void *p = va_arg(*args, void *);
char digits[] = "00000000";
digits_16(digits, 0, (uint32_t)p);
kprint_out('0');
kprint_out('x');
for(int i = 7; i >= 0; i--) kprint_out(digits[i]);
}
/* kformat_fixed(): Fixed-point decimal formatter
(0) Pad with zeros, rather than spaces, on the left
(-) Move spaces to the right (overrides '0')
( ) Force a blank sign before nonnegative numbers
(+) Force a sign before every number (overrides ' ')
{len} Minimal number of characters to print
{pre} Number of digits after the decimal dot */
static void kformat_fixed(KFORMAT_ARGS)
{
int64_t n = load_i(opt->size, args);
/* Compute the sign and the absolute value */
kprint_geometry_t g = {
.sign = (n < 0) ? '-' : '+',
.prefix = 0,
.style = KPRINT_NUMERIC,
};
if(n < 0) n = -n;
/* Get the digit string */
char digits[32];
g.content = digits_10(digits, n) + 1;
kformat_geometry(opt, &g);
/* Print the result */
kprint_outn(' ', g.left_spaces);
if(g.sign) kprint_out(g.sign);
kprint_outn('0', g.zeros);
for(int i = g.content - 2; i >= 0; i--)
{
if(i == opt->precision - 1) kprint_out('.');
kprint_out(digits[i]);
}
kprint_outn(' ', g.right_spaces);
}

View File

@ -1,7 +1,8 @@
#include <gint/defs/types.h>
#include <gint/defs/attributes.h>
#include <gint/display.h>
#include <gint/std/string.h>
#include <string.h>
#include "../render/render.h"
#include "topti-asm.h"

View File

@ -25,6 +25,8 @@ struct command
uint32_t *masks;
/* Whether the first column is real (ie. x>=0) or not */
int real_start;
/* Whether the last column is written to VRAM */
int real_end;
/* Ignored elements between two rendered grid rows */
int vram_stride;
@ -103,7 +105,7 @@ void bopti_grid(void **layer, int rows, struct command *c)
offset++;
}
if(c->x) v1[offset] = pret.r;
if(c->real_end) v1[offset] = pret.r;
*layer += c->data_stride;
offset += c->vram_stride;
@ -137,7 +139,7 @@ void bopti_grid(void **layer, int rows, struct command *c)
offset++;
}
if(c->x)
if(c->real_end)
{
v1[offset] = qret.r1;
v2[offset] = qret.r2;
@ -201,6 +203,7 @@ void bopti_render(bopti_image_t const *img, struct rbox *rbox, uint32_t *v1,
.columns = rbox->columns,
.masks = masks + 2 * left_origin,
.real_start = (left_origin > 0),
.real_end = (rbox->x & 31) && (left_origin + img_columns < 5),
.vram_stride = 4 - rbox->columns,
.data_stride = ((img_columns - rbox->columns) << 2) * layers,
.gray = (v2 != NULL),

View File

@ -1,5 +1,5 @@
#include <gint/display.h>
#include <gint/std/stdio.h>
#include <stdio.h>
/* dprint(): Display a formatted string */
void dprint_opt(int x, int y, int fg, int bg, int halign, int valign,

View File

@ -1,38 +0,0 @@
//---
// gint:src:aprint - Allocating extensions to formatted printing
//---
#include <gint/std/stdio.h>
#include <gint/std/stdlib.h>
#include <gint/kprint.h>
#include <stdarg.h>
/* asprintf() */
GWEAK int asprintf(char **strp, char const *format, ...)
{
va_list args;
va_start(args, format);
int count = vasprintf(strp, format, args);
va_end(args);
return count;
}
/* vasprintf() */
GWEAK int vasprintf(char **strp, char const *format, va_list args1)
{
va_list args2;
va_copy(args2, args1);
int count = vsnprintf(NULL, 0, format, args1);
va_end(args1);
char *str = malloc(count + 1);
if(str) count = vsnprintf(str, count + 1, format, args2);
va_end(args2);
if(!str) return -1;
*strp = str;
return count;
}

View File

@ -1,36 +0,0 @@
//---
// gint:std:malloc - Standard memory allocation functions
//---
#include <gint/kmalloc.h>
#include <gint/std/string.h>
/* malloc(): Allocate dynamic memory */
void *malloc(size_t size)
{
return kmalloc(size, NULL);
}
/* free(): Free dynamic memory */
void free(void *ptr)
{
kfree(ptr);
}
/* calloc(): Allocate and initialize dynamic memory */
void *calloc(size_t nmemb, size_t size)
{
uint64_t total = (uint64_t)nmemb * (uint64_t)size;
if(total >= 1ull << 32) return NULL;
size = total;
void *ptr = malloc(size);
if(ptr) memset(ptr, 0, size);
return ptr;
}
/* realloc(): Reallocate dynamic memory */
void *realloc(void *ptr, size_t size)
{
return krealloc(ptr, size);
}

View File

@ -1,43 +0,0 @@
//---
// gint:src:print - Standard formatted printing functions
//---
#include <gint/std/stdio.h>
#include <gint/kprint.h>
#include <stdarg.h>
/* sprintf() */
GWEAK int sprintf(char *str, char const *format, ...)
{
va_list args;
va_start(args, format);
int count = kvsprint(str, 65536, format, &args);
va_end(args);
return count;
}
/* vsprintf() */
GWEAK int vsprintf(char *str, char const *format, va_list args)
{
return kvsprint(str, 65536, format, &args);
}
/* snprintf() */
GWEAK int snprintf(char *str, size_t n, char const *format, ...)
{
va_list args;
va_start(args, format);
int count = kvsprint(str, n, format, &args);
va_end(args);
return count;
}
/* vsprintf() */
GWEAK int vsnprintf(char *str, size_t n, char const *format, va_list args)
{
return kvsprint(str, n, format, &args);
}

View File

@ -1,7 +1,8 @@
#include <gint/usb.h>
#include <gint/usb-ff-bulk.h>
#include <gint/display.h>
#include <gint/std/string.h>
#include <string.h>
static usb_dc_interface_t dc_interface = {
.bLength = sizeof(usb_dc_interface_t),

View File

@ -3,7 +3,9 @@
#include <gint/clock.h>
#include <gint/dma.h>
#include <gint/defs/util.h>
#include <gint/std/string.h>
#include <string.h>
#include "usb_private.h"
#define USB SH7305_USB

View File

@ -1,8 +1,10 @@
#include <gint/usb.h>
#include <gint/mpu/usb.h>
#include <gint/std/endian.h>
#include "usb_private.h"
#include <stdarg.h>
#include <endian.h>
#include "usb_private.h"
#define USB SH7305_USB

View File

@ -3,8 +3,9 @@
//---
#include <gint/usb.h>
#include <gint/std/stdlib.h>
#include <gint/std/string.h>
#include <stdlib.h>
#include <string.h>
/* String descriptor array */
static usb_dc_string_t **array = NULL;