Make sure FPSCR is properly initialized

This is a potentially breaking change as the register was left with an unpredictable/unspecified value.

Config: default NaN mode enabled, flush-to-zero enabled, and round to nearest.
This commit is contained in:
TuxSH 2022-04-12 22:22:56 +01:00
parent c36d9cc4a6
commit 11686876ac
3 changed files with 31 additions and 25 deletions

View File

@ -31,7 +31,20 @@ typedef struct
bool srv_blocking_policy;
} ThreadVars;
struct Thread_tag
{
Handle handle;
ThreadFunc ep;
void* arg;
int rc;
bool detached, finished;
struct _reent reent;
void* stacktop;
};
static inline ThreadVars* getThreadVars(void)
{
return (ThreadVars*)getThreadLocalStorage();
}
void initThreadVars(struct Thread_tag *thread);

View File

@ -99,18 +99,27 @@ void __SYSCALL(exit)(int rc) {
__ctru_exit(rc);
}
void initThreadVars(struct Thread_tag *thread)
{
ThreadVars* tv = getThreadVars();
tv->magic = THREADVARS_MAGIC;
tv->reent = thread != NULL ? &thread->reent : _impure_ptr;
tv->thread_ptr = thread;
tv->tls_tp = (thread != NULL ? (u8*)thread->stacktop : __tls_start) - 8; // Arm ELF TLS ABI mandates an 8-byte header
tv->srv_blocking_policy = false;
// Kernel does not initialize fpscr at all, so we must do it ourselves
// https://developer.arm.com/documentation/ddi0360/f/vfp-programmers-model/vfp11-system-registers/floating-point-status-and-control-register--fpscr
// All flags clear, all interrupts disabled, all instruction scalar.
// As for the 3 below fields: default NaN mode, flush-to-zero both enabled & round to nearest.
__builtin_arm_set_fpscr(BIT(25) | BIT(24) | (0u << 22));
}
void __system_initSyscalls(void)
{
// Initialize thread vars for the main thread
ThreadVars* tv = getThreadVars();
tv->magic = THREADVARS_MAGIC;
tv->reent = _impure_ptr;
tv->thread_ptr = NULL;
tv->tls_tp = __tls_start-8; // ARM ELF TLS ABI mandates an 8-byte header
tv->srv_blocking_policy = false;
initThreadVars(NULL);
u32 tls_size = __tdata_lma_end - __tdata_lma;
if (tls_size)
memcpy(__tls_start, __tdata_lma, tls_size);

View File

@ -8,17 +8,6 @@ extern const u8 __tdata_lma_end[];
extern u8 __tls_start[];
extern u8 __tls_end[];
struct Thread_tag
{
Handle handle;
ThreadFunc ep;
void* arg;
int rc;
bool detached, finished;
struct _reent reent;
void* stacktop;
};
static void __panic(void)
{
svcBreak(USERBREAK_PANIC);
@ -28,12 +17,7 @@ static void __panic(void)
static void _thread_begin(void* arg)
{
Thread t = (Thread)arg;
ThreadVars* tv = getThreadVars();
tv->magic = THREADVARS_MAGIC;
tv->reent = &t->reent;
tv->thread_ptr = t;
tv->tls_tp = (u8*)t->stacktop-8; // ARM ELF TLS ABI mandates an 8-byte header
tv->srv_blocking_policy = false;
initThreadVars(t);
t->ep(t->arg);
threadExit(0);
}