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:
Tim Allen 2019-02-27 23:02:30 +11:00
parent 40524fef8a
commit 80cc16d62d
9 changed files with 193 additions and 3 deletions

18
amd64.c
View File

@ -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
View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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
View File

@ -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
View File

@ -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;

View File

@ -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
View File

@ -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) {