mirror of https://github.com/bsnes-emu/bsnes.git
Update to v106r107 release.
[This WIP was made after byuu's forum closed, so byuu only gave a one-line description -Ed.] byuu says: This splits ColecoVision, SG-1000/SC-3000 away from Master System/Game Gear. Was getting too crowded in there.
This commit is contained in:
parent
40524fef8a
commit
80cc16d62d
18
amd64.c
18
amd64.c
|
@ -120,6 +120,24 @@ cothread_t co_active() {
|
|||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
cothread_t handle;
|
||||
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;
|
||||
|
||||
if(handle = (cothread_t)memory) {
|
||||
long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
|
||||
*--p = (long long)crash; /* crash if entrypoint returns */
|
||||
*--p = (long long)entrypoint; /* start of function */
|
||||
*(long long*)handle = (long long)p; /* stack pointer */
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
cothread_t handle;
|
||||
if(!co_swap) {
|
||||
|
|
19
arm.c
19
arm.c
|
@ -40,8 +40,25 @@ cothread_t co_active() {
|
|||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
unsigned long* handle;
|
||||
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;
|
||||
|
||||
if(handle = (unsigned long*)memory) {
|
||||
unsigned long* p = (unsigned long*)((unsigned char*)handle + size);
|
||||
handle[8] = (unsigned long)p;
|
||||
handle[9] = (unsigned long)entrypoint;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
unsigned long* handle = 0;
|
||||
unsigned long* handle;
|
||||
if(!co_swap) {
|
||||
co_init();
|
||||
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
|
||||
|
|
|
@ -62,6 +62,14 @@ Return handle to current cothread. Always returns a valid handle, even when
|
|||
called from the main program thread.
|
||||
<hr/>
|
||||
|
||||
<code>cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void));</code><br/><br/>
|
||||
Initializes new cothread.</br>
|
||||
This function is identical to co_create, only it attempts to use the provided
|
||||
memory instead of allocating new memory on the heap. Please note that certain
|
||||
implementations (currently only Windows Fibers) cannot be created using existing
|
||||
memory, and as such, this function will fail.
|
||||
<hr/>
|
||||
|
||||
<code>cothread_t co_create(unsigned int heapsize, void (*coentry)(void));</code><br/><br/>
|
||||
Create new cothread.<br/>
|
||||
Heapsize is the amount of memory allocated for the cothread stack, specified
|
||||
|
|
5
fiber.c
5
fiber.c
|
@ -24,6 +24,11 @@ cothread_t co_active() {
|
|||
return co_active_;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void)) {
|
||||
//Windows fibers do not allow users to supply their own memory
|
||||
return (cothread_t)0;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) {
|
||||
if(!co_active_) {
|
||||
ConvertThreadToFiber(0);
|
||||
|
|
3
libco.h
3
libco.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
libco v18.02 (2017-11-06)
|
||||
libco v19 (2019-02-18)
|
||||
author: byuu
|
||||
license: ISC
|
||||
*/
|
||||
|
@ -14,6 +14,7 @@ extern "C" {
|
|||
typedef void* cothread_t;
|
||||
|
||||
cothread_t co_active();
|
||||
cothread_t co_derive(void*, unsigned int, void (*)(void));
|
||||
cothread_t co_create(unsigned int, void (*)(void));
|
||||
void co_delete(cothread_t);
|
||||
void co_switch(cothread_t);
|
||||
|
|
64
ppc.c
64
ppc.c
|
@ -258,6 +258,70 @@ static const uint32_t libco_ppc_code[1024] = {
|
|||
#define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)libco_ppc_code)(x, y)
|
||||
#endif
|
||||
|
||||
static uint32_t* co_derive_(void* memory, unsigned size, uintptr_t entry) {
|
||||
(void)entry;
|
||||
|
||||
uint32_t* t = (uint32_t*)memory;
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
if(t) {
|
||||
memcpy(t, (void*)entry, sizeof(void*) * 3); /* copy entry's descriptor */
|
||||
*(const void**)t = libco_ppc_code; /* set function pointer to swap routine */
|
||||
}
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entry_)(void)) {
|
||||
uintptr_t entry = (uintptr_t)entry_;
|
||||
uint32_t* t = 0;
|
||||
|
||||
/* be sure main thread was successfully allocated */
|
||||
if(co_active()) {
|
||||
t = co_derive_(memory, size, entry);
|
||||
}
|
||||
|
||||
if(t) {
|
||||
uintptr_t sp;
|
||||
int shift;
|
||||
|
||||
/* save current registers into new thread, so that any special ones will have proper values when thread is begun */
|
||||
CO_SWAP_ASM(t, t);
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
entry = (uintptr_t)*(void**)entry; /* get real address */
|
||||
#endif
|
||||
|
||||
/* put stack near end of block, and align */
|
||||
sp = (uintptr_t)t + size - above_stack;
|
||||
sp -= sp % stack_align;
|
||||
|
||||
/* on PPC32, we save and restore GPRs as 32 bits. for PPC64, we
|
||||
save and restore them as 64 bits, regardless of the size the ABI
|
||||
uses. so, we manually write pointers at the proper size. we always
|
||||
save and restore at the same address, and since PPC is big-endian,
|
||||
we must put the low byte first on PPC32. */
|
||||
|
||||
/* if uintptr_t is 32 bits, >>32 is undefined behavior,
|
||||
so we do two shifts and don't have to care how many bits uintptr_t is. */
|
||||
#if LIBCO_PPC64
|
||||
shift = 16;
|
||||
#else
|
||||
shift = 0;
|
||||
#endif
|
||||
|
||||
/* set up so entry will be called on next swap */
|
||||
t[ 8] = (uint32_t)(entry >> shift >> shift);
|
||||
t[ 9] = (uint32_t)entry;
|
||||
|
||||
t[10] = (uint32_t)(sp >> shift >> shift);
|
||||
t[11] = (uint32_t)sp;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static uint32_t* co_create_(unsigned size, uintptr_t entry) {
|
||||
(void)entry;
|
||||
|
||||
|
|
44
sjlj.c
44
sjlj.c
|
@ -38,10 +38,52 @@ cothread_t co_active() {
|
|||
return (cothread_t)co_running;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
|
||||
cothread_struct* thread = (cothread_struct*)memory;
|
||||
memory = (unsigned char*)memory + sizeof(cothread_struct);
|
||||
size -= sizeof(cothread_struct);
|
||||
if(thread) {
|
||||
struct sigaction handler;
|
||||
struct sigaction old_handler;
|
||||
|
||||
stack_t stack;
|
||||
stack_t old_stack;
|
||||
|
||||
thread->coentry = thread->stack = 0;
|
||||
|
||||
stack.ss_flags = 0;
|
||||
stack.ss_size = size;
|
||||
thread->stack = stack.ss_sp = memory;
|
||||
if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) {
|
||||
handler.sa_handler = springboard;
|
||||
handler.sa_flags = SA_ONSTACK;
|
||||
sigemptyset(&handler.sa_mask);
|
||||
creating = thread;
|
||||
|
||||
if(!sigaction(SIGUSR1, &handler, &old_handler)) {
|
||||
if(!raise(SIGUSR1)) {
|
||||
thread->coentry = coentry;
|
||||
}
|
||||
sigaltstack(&old_stack, 0);
|
||||
sigaction(SIGUSR1, &old_handler, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(thread->coentry != coentry) {
|
||||
co_delete(thread);
|
||||
thread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
|
||||
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
cothread_struct* thread = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
if(thread) {
|
||||
struct sigaction handler;
|
||||
struct sigaction old_handler;
|
||||
|
|
17
ucontext.c
17
ucontext.c
|
@ -31,6 +31,23 @@ cothread_t co_active() {
|
|||
return (cothread_t)co_running;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
ucontext_t* thread = (ucontext_t*)memory;
|
||||
memory = (unsigned char*)memory + sizeof(ucontext_t);
|
||||
heapsize -= sizeof(ucontext_t);
|
||||
if(thread) {
|
||||
if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = memory)) {
|
||||
thread->uc_link = co_running;
|
||||
thread->uc_stack.ss_size = heapsize;
|
||||
makecontext(thread, coentry, 0);
|
||||
} else {
|
||||
thread = 0;
|
||||
}
|
||||
}
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
ucontext_t* thread = (ucontext_t*)malloc(sizeof(ucontext_t));
|
||||
|
|
18
x86.c
18
x86.c
|
@ -74,6 +74,24 @@ cothread_t co_active() {
|
|||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
cothread_t handle;
|
||||
if(!co_swap) {
|
||||
co_init();
|
||||
co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function;
|
||||
}
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
|
||||
if(handle = (cothread_t)memory) {
|
||||
long *p = (long*)((char*)handle + size); /* seek to top of stack */
|
||||
*--p = (long)crash; /* crash if entrypoint returns */
|
||||
*--p = (long)entrypoint; /* start of function */
|
||||
*(long*)handle = (long)p; /* stack pointer */
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
cothread_t handle;
|
||||
if(!co_swap) {
|
||||
|
|
Loading…
Reference in New Issue