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:
parent
c36d9cc4a6
commit
11686876ac
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user