mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-23 14:42:33 +01:00
byuu says: Changelog: - added 30 new PAL games to icarus (courtesy of Mikerochip) - new version of libco no longer requires mprotect nor W|X permissions - nall: default C compiler to -std=c11 instead of -std=c99 - nall: use `-fno-strict-aliasing` during compilation - updated nall/certificates (hopefully for the last time) - updated nall/http to newer coding conventions - nall: improve handling of range() function I didn't really work on higan at all, this is mostly just a release because lots of other things have changed. The most interesting is `-fno-strict-aliasing` ... basically, it joins `-fwrapv` as being "stop the GCC developers from doing *really* evil shit that could lead to security vulnerabilities or instabilities." For the most part, it's a ~2% speed penalty for higan. Except for the Sega Genesis, where it's a ~10% speedup. I have no idea how that's possible, but clearly something's going very wrong with strict aliasing on the Genesis core. So ... it is what it is. If you need the performance for the non-Genesis cores, you can turn it off in your builds. But I'm getting quite sick of C++'s "surprises" and clever compiler developers, so I'm keeping it on in all of my software going forward.
80 lines
1.8 KiB
C
80 lines
1.8 KiB
C
/*
|
|
libco.arm (2016-09-14)
|
|
author: byuu
|
|
license: public domain
|
|
*/
|
|
|
|
#define LIBCO_C
|
|
#include "libco.h"
|
|
#include "settings.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
static thread_local unsigned long co_active_buffer[64];
|
|
static thread_local cothread_t co_active_handle = 0;
|
|
static void (*co_swap)(cothread_t, cothread_t) = 0;
|
|
|
|
#ifdef LIBCO_MPROTECT
|
|
alignas(4096)
|
|
#else
|
|
section(text)
|
|
#endif
|
|
static const unsigned long co_swap_function[1024] = {
|
|
0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */
|
|
0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */
|
|
0xe12fff1e, /* bx lr */
|
|
};
|
|
|
|
static void co_init() {
|
|
#ifdef LIBCO_MPROTECT
|
|
unsigned long addr = (unsigned long)co_swap_function;
|
|
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
|
|
unsigned long size = (addr - base) + sizeof co_swap_function;
|
|
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
|
|
#endif
|
|
}
|
|
|
|
cothread_t co_active() {
|
|
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
|
return co_active_handle;
|
|
}
|
|
|
|
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
|
unsigned long* handle = 0;
|
|
if(!co_swap) {
|
|
co_init();
|
|
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
|
|
}
|
|
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
|
size += 256;
|
|
size &= ~15;
|
|
|
|
if(handle = (unsigned long*)malloc(size)) {
|
|
unsigned long* p = (unsigned long*)((unsigned char*)handle + size);
|
|
handle[8] = (unsigned long)p;
|
|
handle[9] = (unsigned long)entrypoint;
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
void co_delete(cothread_t handle) {
|
|
free(handle);
|
|
}
|
|
|
|
void co_switch(cothread_t handle) {
|
|
cothread_t co_previous_handle = co_active_handle;
|
|
co_swap(co_active_handle = handle, co_previous_handle);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|