diff --git a/libctru/source/internal.h b/libctru/source/internal.h index e4d47cb..4328e35 100644 --- a/libctru/source/internal.h +++ b/libctru/source/internal.h @@ -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); diff --git a/libctru/source/system/syscalls.c b/libctru/source/system/syscalls.c index 1308326..c65a154 100644 --- a/libctru/source/system/syscalls.c +++ b/libctru/source/system/syscalls.c @@ -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); diff --git a/libctru/source/thread.c b/libctru/source/thread.c index 988def2..688900f 100644 --- a/libctru/source/thread.c +++ b/libctru/source/thread.c @@ -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); }