diff --git a/src/osd/retro/libretro-common/include/libco.h b/src/osd/retro/libretro-common/include/libco.h index 851b29cc43..177721a3a8 100644 --- a/src/osd/retro/libretro-common/include/libco.h +++ b/src/osd/retro/libretro-common/include/libco.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2018 The RetroArch team +/* Copyright (C) 2010-2020 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (libco.h). diff --git a/src/osd/retro/libretro-common/libco/aarch64.c b/src/osd/retro/libretro-common/libco/aarch64.c new file mode 100644 index 0000000000..eef31a3f6e --- /dev/null +++ b/src/osd/retro/libretro-common/libco/aarch64.c @@ -0,0 +1,128 @@ +/* + libco.aarch64 (2017-06-26) + author: webgeek1234 + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" +#include +#include +#include +#include + +#ifndef __APPLE__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local uint64_t co_active_buffer[64]; +static thread_local cothread_t co_active_handle; + +asm ( + ".globl co_switch_aarch64\n" + ".globl _co_switch_aarch64\n" + "co_switch_aarch64:\n" + "_co_switch_aarch64:\n" + " stp x8, x9, [x1]\n" + " stp x10, x11, [x1, #16]\n" + " stp x12, x13, [x1, #32]\n" + " stp x14, x15, [x1, #48]\n" + " str x19, [x1, #72]\n" + " stp x20, x21, [x1, #80]\n" + " stp x22, x23, [x1, #96]\n" + " stp x24, x25, [x1, #112]\n" + " stp x26, x27, [x1, #128]\n" + " stp x28, x29, [x1, #144]\n" + " mov x16, sp\n" + " stp x16, x30, [x1, #160]\n" + + " ldp x8, x9, [x0]\n" + " ldp x10, x11, [x0, #16]\n" + " ldp x12, x13, [x0, #32]\n" + " ldp x14, x15, [x0, #48]\n" + " ldr x19, [x0, #72]\n" + " ldp x20, x21, [x0, #80]\n" + " ldp x22, x23, [x0, #96]\n" + " ldp x24, x25, [x0, #112]\n" + " ldp x26, x27, [x0, #128]\n" + " ldp x28, x29, [x0, #144]\n" + " ldp x16, x17, [x0, #160]\n" + " mov sp, x16\n" + " br x17\n" + ); + +/* ASM */ +void co_switch_aarch64(cothread_t handle, cothread_t current); + +static void crash(void) +{ + /* Called only if cothread_t entrypoint returns. */ + assert(0); +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) +{ + size = (size + 1023) & ~1023; + cothread_t handle = 0; +#if HAVE_POSIX_MEMALIGN >= 1 + if (posix_memalign(&handle, 1024, size + 512) < 0) + return 0; +#else + handle = memalign(1024, size + 512); +#endif + + if (!handle) + return handle; + + uint64_t *ptr = (uint64_t*)handle; + /* Non-volatiles. */ + ptr[0] = 0; /* x8 */ + ptr[1] = 0; /* x9 */ + ptr[2] = 0; /* x10 */ + ptr[3] = 0; /* x11 */ + ptr[4] = 0; /* x12 */ + ptr[5] = 0; /* x13 */ + ptr[6] = 0; /* x14 */ + ptr[7] = 0; /* x15 */ + ptr[8] = 0; /* padding */ + ptr[9] = 0; /* x19 */ + ptr[10] = 0; /* x20 */ + ptr[11] = 0; /* x21 */ + ptr[12] = 0; /* x22 */ + ptr[13] = 0; /* x23 */ + ptr[14] = 0; /* x24 */ + ptr[15] = 0; /* x25 */ + ptr[16] = 0; /* x26 */ + ptr[17] = 0; /* x27 */ + ptr[18] = 0; /* x28 */ + ptr[20] = (uintptr_t)ptr + size + 512 - 16; /* x30, stack pointer */ + ptr[19] = ptr[20]; /* x29, frame pointer */ + ptr[21] = (uintptr_t)entrypoint; /* PC (link register x31 gets saved here). */ + return handle; +} + +cothread_t co_active(void) +{ + if (!co_active_handle) + co_active_handle = co_active_buffer; + return co_active_handle; +} + +void co_delete(cothread_t handle) +{ + free(handle); +} + +void co_switch(cothread_t handle) +{ + cothread_t co_previous_handle = co_active(); + co_switch_aarch64(co_active_handle = handle, co_previous_handle); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/osd/retro/libretro-common/libco/amd64.c b/src/osd/retro/libretro-common/libco/amd64.c index cd38a65534..124c319761 100644 --- a/src/osd/retro/libretro-common/libco/amd64.c +++ b/src/osd/retro/libretro-common/libco/amd64.c @@ -25,51 +25,56 @@ static void (*co_swap)(cothread_t, cothread_t) = 0; #ifdef _WIN32 /* ABI: Win64 */ + /* On windows handle is allocated by malloc and there it's guaranteed to + have at least 16-byte alignment. Hence we don't need to align + it in order to use movaps. */ static unsigned char co_swap_function[] = { - 0x48, 0x89, 0x22, /* mov [rdx],rsp */ - 0x48, 0x8b, 0x21, /* mov rsp,[rcx] */ - 0x58, /* pop rax */ - 0x48, 0x89, 0x6a, 0x08, /* mov [rdx+0x8],rbp */ - 0x48, 0x89, 0x72, 0x10, /* mov [rdx+0x10],rsi */ - 0x48, 0x89, 0x7a, 0x18, /* mov [rdx+0x18],rdi */ - 0x48, 0x89, 0x5a, 0x20, /* mov [rdx+0x20],rbx */ - 0x4c, 0x89, 0x62, 0x28, /* mov [rdx+0x28],r12 */ - 0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+0x30],r13 */ - 0x4c, 0x89, 0x72, 0x38, /* mov [rdx+0x38],r14 */ - 0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+0x40],r15 */ - 0x48, 0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, /* add rdx,0x80 */ - 0x48, 0x83, 0xe2, 0xf0, /* and rdx,-0x10 */ - 0x0f, 0x29, 0x32, /* movaps [rdx],xmm6 */ - 0x0f, 0x29, 0x7a, 0x10, /* movaps [rdx+0x10],xmm7 */ - 0x44, 0x0f, 0x29, 0x42, 0x20, /* movaps [rdx+0x20],xmm8 */ - 0x44, 0x0f, 0x29, 0x4a, 0x30, /* movaps [rdx+0x30],xmm9 */ - 0x44, 0x0f, 0x29, 0x52, 0x40, /* movaps [rdx+0x40],xmm10 */ - 0x44, 0x0f, 0x29, 0x5a, 0x50, /* movaps [rdx+0x50],xmm11 */ - 0x44, 0x0f, 0x29, 0x62, 0x60, /* movaps [rdx+0x60],xmm12 */ - 0x44, 0x0f, 0x29, 0x6a, 0x70, /* movaps [rdx+0x70],xmm13 */ - 0x44, 0x0f, 0x29, 0xb2, 0x80, 0x00, 0x00, 0x00, /* movaps [rdx+0x80],xmm14 */ - 0x44, 0x0f, 0x29, 0xba, 0x90, 0x00, 0x00, 0x00, /* movaps [rdx+0x90],xmm15 */ - 0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+0x8] */ - 0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+0x10] */ - 0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+0x18] */ - 0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+0x20] */ - 0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+0x28] */ - 0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+0x30] */ - 0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+0x38] */ - 0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+0x40] */ - 0x48, 0x81, 0xc1, 0x80, 0x00, 0x00, 0x00, /* add rcx,0x80 */ - 0x48, 0x83, 0xe1, 0xf0, /* and rcx,-0x10 */ - 0x0f, 0x29, 0x31, /* movaps [rcx],xmm6 */ - 0x0f, 0x29, 0x79, 0x10, /* movaps [rcx+0x10],xmm7 */ - 0x44, 0x0f, 0x29, 0x41, 0x20, /* movaps [rcx+0x20],xmm8 */ - 0x44, 0x0f, 0x29, 0x49, 0x30, /* movaps [rcx+0x30],xmm9 */ - 0x44, 0x0f, 0x29, 0x51, 0x40, /* movaps [rcx+0x40],xmm10 */ - 0x44, 0x0f, 0x29, 0x59, 0x50, /* movaps [rcx+0x50],xmm11 */ - 0x44, 0x0f, 0x29, 0x61, 0x60, /* movaps [rcx+0x60],xmm12 */ - 0x44, 0x0f, 0x29, 0x69, 0x70, /* movaps [rcx+0x70],xmm13 */ - 0x44, 0x0f, 0x29, 0xb1, 0x80, 0x00, 0x00, 0x00, /* movaps [rcx+0x80],xmm14 */ - 0x44, 0x0f, 0x29, 0xb9, 0x90, 0x00, 0x00, 0x00, /* movaps [rcx+0x90],xmm15 */ - 0xff, 0xe0, /* jmp rax */ + 0x48, 0x89, 0x22, /* mov [rdx],rsp */ + 0x48, 0x8b, 0x21, /* mov rsp,[rcx] */ + 0x58, /* pop rax */ + 0x48, 0x89, 0x6a, 0x08, /* mov [rdx+ 8],rbp */ + 0x48, 0x89, 0x72, 0x10, /* mov [rdx+16],rsi */ + 0x48, 0x89, 0x7a, 0x18, /* mov [rdx+24],rdi */ + 0x48, 0x89, 0x5a, 0x20, /* mov [rdx+32],rbx */ + 0x4c, 0x89, 0x62, 0x28, /* mov [rdx+40],r12 */ + 0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+48],r13 */ + 0x4c, 0x89, 0x72, 0x38, /* mov [rdx+56],r14 */ + 0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+64],r15 */ + #if !defined(LIBCO_NO_SSE) + 0x0f, 0x29, 0x72, 0x50, /* movaps [rdx+ 80],xmm6 */ + 0x0f, 0x29, 0x7a, 0x60, /* movaps [rdx+ 96],xmm7 */ + 0x44, 0x0f, 0x29, 0x42, 0x70, /* movaps [rdx+112],xmm8 */ + 0x48, 0x83, 0xc2, 0x70, /* add rdx,112 */ + 0x44, 0x0f, 0x29, 0x4a, 0x10, /* movaps [rdx+ 16],xmm9 */ + 0x44, 0x0f, 0x29, 0x52, 0x20, /* movaps [rdx+ 32],xmm10 */ + 0x44, 0x0f, 0x29, 0x5a, 0x30, /* movaps [rdx+ 48],xmm11 */ + 0x44, 0x0f, 0x29, 0x62, 0x40, /* movaps [rdx+ 64],xmm12 */ + 0x44, 0x0f, 0x29, 0x6a, 0x50, /* movaps [rdx+ 80],xmm13 */ + 0x44, 0x0f, 0x29, 0x72, 0x60, /* movaps [rdx+ 96],xmm14 */ + 0x44, 0x0f, 0x29, 0x7a, 0x70, /* movaps [rdx+112],xmm15 */ + #endif + 0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+ 8] */ + 0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+16] */ + 0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+24] */ + 0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+32] */ + 0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+40] */ + 0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+48] */ + 0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+56] */ + 0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+64] */ + #if !defined(LIBCO_NO_SSE) + 0x0f, 0x28, 0x71, 0x50, /* movaps xmm6, [rcx+ 80] */ + 0x0f, 0x28, 0x79, 0x60, /* movaps xmm7, [rcx+ 96] */ + 0x44, 0x0f, 0x28, 0x41, 0x70, /* movaps xmm8, [rcx+112] */ + 0x48, 0x83, 0xc1, 0x70, /* add rcx,112 */ + 0x44, 0x0f, 0x28, 0x49, 0x10, /* movaps xmm9, [rcx+ 16] */ + 0x44, 0x0f, 0x28, 0x51, 0x20, /* movaps xmm10,[rcx+ 32] */ + 0x44, 0x0f, 0x28, 0x59, 0x30, /* movaps xmm11,[rcx+ 48] */ + 0x44, 0x0f, 0x28, 0x61, 0x40, /* movaps xmm12,[rcx+ 64] */ + 0x44, 0x0f, 0x28, 0x69, 0x50, /* movaps xmm13,[rcx+ 80] */ + 0x44, 0x0f, 0x28, 0x71, 0x60, /* movaps xmm14,[rcx+ 96] */ + 0x44, 0x0f, 0x28, 0x79, 0x70, /* movaps xmm15,[rcx+112] */ + #endif + 0xff, 0xe0, /* jmp rax */ }; #include @@ -146,6 +151,15 @@ cothread_t co_create(unsigned int size, void (*entrypoint)(void)) size += 512; /* allocate additional space for storage */ size &= ~15; /* align stack to 16-byte boundary */ +#ifdef __GENODE__ + if((handle = (cothread_t)genode_alloc_secondary_stack(size))) + { + long long *p = (long long*)((char*)handle); /* OS returns 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 */ + } +#else if((handle = (cothread_t)malloc(size))) { long long *p = (long long*)((char*)handle + size); /* seek to top of stack */ @@ -153,13 +167,18 @@ cothread_t co_create(unsigned int size, void (*entrypoint)(void)) *--p = (long long)entrypoint; /* start of function */ *(long long*)handle = (long long)p; /* stack pointer */ } +#endif return handle; } void co_delete(cothread_t handle) { +#ifdef __GENODE__ + genode_free_secondary_stack(handle); +#else free(handle); +#endif } #ifndef CO_USE_INLINE_ASM diff --git a/src/osd/retro/libretro-common/libco/armeabi.c b/src/osd/retro/libretro-common/libco/armeabi.c index f65aaa2e4b..f03a356794 100644 --- a/src/osd/retro/libretro-common/libco/armeabi.c +++ b/src/osd/retro/libretro-common/libco/armeabi.c @@ -104,4 +104,3 @@ void co_switch(cothread_t handle) #ifdef __cplusplus } #endif - diff --git a/src/osd/retro/libretro-common/libco/genode.cpp b/src/osd/retro/libretro-common/libco/genode.cpp new file mode 100644 index 0000000000..2f2bdac52a --- /dev/null +++ b/src/osd/retro/libretro-common/libco/genode.cpp @@ -0,0 +1,29 @@ +/* + libco.genode_secondary_stack (2018-09-15) + author: Emery Hemingway + license: public domain +*/ + +/* Genode include */ +#include + +/* Libco include */ +#include + +extern "C" +void *genode_alloc_secondary_stack(unsigned long stack_size) +{ + try { + return Genode::Thread::myself()->alloc_secondary_stack("libco", stack_size); } + catch (...) { + Genode::error("libco: failed to allocate ", stack_size, " byte secondary stack"); + return nullptr; + } + +} + +extern "C" +void genode_free_secondary_stack(void *stack) +{ + Genode::Thread::myself()->free_secondary_stack(stack); +} diff --git a/src/osd/retro/libretro-common/libco/libco.c b/src/osd/retro/libretro-common/libco/libco.c index 8d6f9343b9..44a65d528f 100644 --- a/src/osd/retro/libretro-common/libco/libco.c +++ b/src/osd/retro/libretro-common/libco/libco.c @@ -4,6 +4,11 @@ license: public domain */ +#ifdef __GENODE__ +void *genode_alloc_secondary_stack(unsigned long stack_size); +void genode_free_secondary_stack(void *stack); +#endif + #if defined _MSC_VER #include #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) @@ -24,6 +29,10 @@ #include "ppc.c" #elif defined(__aarch64__) #include "aarch64.c" + #elif defined(PS2) + #include "ps2.c" + #elif defined(PSP) + #include "psp1.c" #elif defined VITA #include "scefiber.c" #elif defined(__ARM_EABI__) || defined(__arm__) diff --git a/src/osd/retro/libretro-common/libco/ps2.c b/src/osd/retro/libretro-common/libco/ps2.c new file mode 100644 index 0000000000..65a9c09864 --- /dev/null +++ b/src/osd/retro/libretro-common/libco/ps2.c @@ -0,0 +1,66 @@ +#define LIBCO_C +#include "libco.h" + +#include +#include +#include + +/* Since cothread_t is a void pointer it must contain an address. We can't return a reference to a local variable + * because it would go out of scope, so we create a static variable instead so we can return a reference to it. + */ +static int32_t active_thread_id = -1; +extern void *_gp; + +cothread_t co_active() +{ + active_thread_id = GetThreadId(); + return &active_thread_id; +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) +{ + /* Similar scenario as with active_thread_id except there will only be one active_thread_id while there could be many + * new threads each with their own handle, so we create them on the heap instead and delete them manually when they're + * no longer needed in co_delete(). + */ + cothread_t handle = malloc(sizeof(cothread_t)); + ee_thread_t thread; + + // u8 threadStack[size/8] __attribute__ ((aligned(16))); + void *threadStack = (void *)malloc(size); + + if ( threadStack== NULL) + { + printf("libco: ERROR: creating threadStack\n"); + return(-1); + } + + thread.stack_size = size; + thread.gp_reg = &_gp; + thread.func = (void *)entrypoint; + thread.stack = threadStack; + thread.option = 0; + thread.initial_priority = 1; + + int32_t new_thread_id = CreateThread(&thread); + if (new_thread_id < 0) + printf("libco: ERROR: creating thread\n"); + + StartThread(new_thread_id, NULL); + *(uint32_t *)handle = new_thread_id; + return handle; +} + +void co_delete(cothread_t handle) +{ + TerminateThread(*(uint32_t *)handle); + DeleteThread(*(uint32_t *)handle); + free(handle); +} + +void co_switch(cothread_t handle) +{ + WakeupThread(*(uint32_t *)handle); + /* Sleep the currently active thread so the new thread can start */ + SleepThread(); +} diff --git a/src/osd/retro/libretro-common/libco/ps3.S b/src/osd/retro/libretro-common/libco/ps3.S new file mode 100644 index 0000000000..60a913466a --- /dev/null +++ b/src/osd/retro/libretro-common/libco/ps3.S @@ -0,0 +1,55 @@ +.globl .co_swap_asm +.globl co_swap_asm +.type .co_swap_asm, @function +.type co_swap_asm, @function +.co_swap_asm: +co_swap_asm: + mfcr 8 + std 1,40(4) + mflr 9 + std 14,72(4) + std 15,80(4) + std 16,88(4) + std 17,96(4) + std 18,104(4) + std 19,112(4) + std 20,120(4) + std 21,128(4) + std 22,136(4) + std 23,144(4) + std 24,152(4) + std 25,160(4) + std 26,168(4) + std 27,176(4) + std 28,184(4) + std 29,192(4) + std 30,200(4) + std 31,208(4) + std 9,32(4) + ld 7,32(3) + ld 1,40(3) + bl swap + trap +swap: stw 8,48(4) + lwz 6,48(3) + mtctr 7 + ld 14,72(3) + ld 15,80(3) + ld 16,88(3) + ld 17,96(3) + ld 18,104(3) + ld 19,112(3) + ld 20,120(3) + ld 21,128(3) + ld 22,136(3) + ld 23,144(3) + ld 24,152(3) + ld 25,160(3) + ld 26,168(3) + ld 27,176(3) + ld 28,184(3) + ld 29,192(3) + ld 30,200(3) + ld 31,208(3) + mtcr 6 + bctr diff --git a/src/osd/retro/libretro-common/libco/psp1.c b/src/osd/retro/libretro-common/libco/psp1.c new file mode 100644 index 0000000000..75a71c22e7 --- /dev/null +++ b/src/osd/retro/libretro-common/libco/psp1.c @@ -0,0 +1,41 @@ +#define LIBCO_C +#include "libco.h" + +#include +#include + +typedef void (*entrypoint_t)(void); + +cothread_t co_active() +{ + return (void *) sceKernelGetThreadId(); +} + +static int thread_wrap(unsigned int argc, void *argp) +{ + entrypoint_t entrypoint = *(entrypoint_t *) argp; + sceKernelSleepThread(); + entrypoint(); + return 0; +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) +{ + SceUID new_thread_id = sceKernelCreateThread("cothread", thread_wrap, 0x12, size, 0, NULL); + sceKernelStartThread(new_thread_id, sizeof (entrypoint), &entrypoint); + return (void *) new_thread_id; +} + +void co_delete(cothread_t handle) +{ + SceUID id = (SceUID) handle; + sceKernelTerminateDeleteThread(id); +} + +void co_switch(cothread_t handle) +{ + SceUID id = (SceUID) handle; + sceKernelWakeupThread(id); + /* Sleep the currently active thread so the new thread can start */ + sceKernelSleepThread(); +} diff --git a/src/osd/retro/libretro-common/libco/psp2.c b/src/osd/retro/libretro-common/libco/psp2.c new file mode 100644 index 0000000000..d45568992d --- /dev/null +++ b/src/osd/retro/libretro-common/libco/psp2.c @@ -0,0 +1,113 @@ +/* +libco.arm (2015-06-18) +license: public domain +*/ + +#define LIBCO_C +#include "libco.h" + +#include +#include +#include +#include +#include +#include + +#define FOUR_KB_ALIGN(x) align(x, 12) +#define MB_ALIGN(x) align(x, 20) + +#ifdef __cplusplus +extern "C" { +#endif + + static inline int align(int x, int n) + { + return (((x >> n) + 1) << n); + } + + 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; + static int block; + static uint32_t co_swap_function[] = { + 0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */ + 0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */ + 0xe12fff1e, /* bx lr */ + }; + + static void co_init(void) + { + int ret; + void *base; + + block = sceKernelAllocMemBlockForVM("libco", + MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); + if (block < 0) + return; + + /* get base address */ + ret = sceKernelGetMemBlockBase(block, &base); + if (ret < 0) + return; + + /* set domain to be writable by user */ + ret = sceKernelOpenVMDomain(); + if (ret < 0) + return; + + memcpy(base, co_swap_function, sizeof co_swap_function); + + /* set domain back to read-only */ + ret = sceKernelCloseVMDomain(); + if (ret < 0) + return; + + /* flush icache */ + ret = sceKernelSyncVMDomain(block, base, + MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); + if (ret < 0) + return; + + co_swap = (void(*)(cothread_t, cothread_t))base; + } + + cothread_t co_active(void) + { + 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(); + 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); + sceKernelFreeMemBlock(block); + } + + 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 diff --git a/src/osd/retro/libretro-common/libco/scefiber.c b/src/osd/retro/libretro-common/libco/scefiber.c new file mode 100644 index 0000000000..11f521d607 --- /dev/null +++ b/src/osd/retro/libretro-common/libco/scefiber.c @@ -0,0 +1,96 @@ +/* + libco.win (2016-09-06) + authors: frangarcj + license: public domain +*/ + +#define LIBCO_C +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local cothread_t co_active_ = 0; + +typedef struct SceFiber { + char reserved[128]; +} SceFiber __attribute__( ( aligned ( 8 ) ) ) ; + +int32_t _sceFiberInitializeImpl(SceFiber* fiber, char* name, void* entry, uint32_t argOnInitialize, void* addrContext, int32_t sizeContext, void* params); + +int32_t sceFiberFinalize(SceFiber* fiber); + +int32_t sceFiberRun(SceFiber* fiber, uint32_t argOnRunTo, uint32_t* argOnRun); + +int32_t sceFiberSwitch(SceFiber* fiber, uint32_t argOnRunTo, uint32_t* argOnRun); + +int32_t sceFiberReturnToThread(uint32_t argOnReturn, uint32_t* argOnRun); + +static void co_thunk(uint32_t argOnInitialize, uint32_t argOnRun) +{ + ((void (*)(void))argOnInitialize)(); +} + +cothread_t co_active(void) +{ + if(!co_active_) + { + sceSysmoduleLoadModule(SCE_SYSMODULE_FIBER); + co_active_ = (cothread_t)1; + } + return co_active_; +} + +cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) +{ + SceFiber* tailFiber = malloc(sizeof(SceFiber)); + char * m_contextBuffer = malloc(sizeof(char)*heapsize); + if(!co_active_) + { + sceSysmoduleLoadModule(SCE_SYSMODULE_FIBER); + co_active_ = (cothread_t)1; + } + + //_sceFiberInitializeImpl + int ret = _sceFiberInitializeImpl(tailFiber, "tailFiber", co_thunk, (uint32_t)coentry, (void*) m_contextBuffer, heapsize, NULL); + if(ret==0){ + return (cothread_t)tailFiber; + }else{ + return (cothread_t)ret; + } + +} + +void co_delete(cothread_t cothread) +{ + if(cothread == (cothread_t)1){ + return; + } + sceFiberFinalize((SceFiber*)cothread); +} + +void co_switch(cothread_t cothread) +{ + + uint32_t argOnReturn = 0; + if(cothread == (cothread_t)1){ + co_active_ = cothread; + sceFiberReturnToThread(0, NULL); + }else{ + SceFiber* theFiber = (SceFiber*)cothread; + if(co_active_ == (cothread_t)1){ + co_active_ = cothread; + sceFiberRun(theFiber, 0, &argOnReturn); + }else{ + co_active_ = cothread; + sceFiberSwitch(theFiber, 0, &argOnReturn); + } + } +} + +#ifdef __cplusplus +} +#endif