From e476799ab7d0e26256ac9be25888e963dc0928a0 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Fri, 2 May 2025 22:50:18 -0400 Subject: Move coroutines into examples folder due to compatibility issues on some platforms/compilers --- examples/coroutines/acoyield.S | 208 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 examples/coroutines/acoyield.S (limited to 'examples/coroutines/acoyield.S') diff --git a/examples/coroutines/acoyield.S b/examples/coroutines/acoyield.S new file mode 100644 index 00000000..7bc87ff1 --- /dev/null +++ b/examples/coroutines/acoyield.S @@ -0,0 +1,208 @@ +.text +.globl aco_yield_asm +#if defined(__APPLE__) +#else +.type aco_yield_asm, @function +#endif +.intel_syntax noprefix +aco_yield_asm: +/* + extern void aco_yield_asm(aco_t* from_co, aco_t* to_co); + + struct aco_t { + void* reg[X]; + // ... + } + + reference: + https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI + + pitfall: + http://man7.org/linux/man-pages/man7/signal.7.html + http://man7.org/linux/man-pages/man2/sigaltstack.2.html + + > $ man 7 signal + > ... + > By default, the signal handler is invoked on the normal process + > stack. It is possible to arrange that the signal handler + > uses an alternate stack; see sigaltstack(2) for a discussion of + > how to do this and when it might be useful. + > ... + + This is a BUG example: + https://github.com/Tencent/libco/blob/v1.0/coctx_swap.S#L27 + + proof of correctness: + https://github.com/hnes/libaco + + mxcsr & fpu: + fnstcw * m2byte + Store FPU control word to m2byte without checking for + pending unmasked floating-point exceptions. + + fldcw m2byte + Load FPU control word from m2byte. + + stmxcsr m32 + Store contents of MXCSR register to m32 + + ldmxcsr m32 + Load MXCSR register from m32. +*/ +/* + 0x00 --> 0xff + eip esp ebp edi esi ebx fpucw16 mxcsr32 + 0 4 8 c 10 14 18 1c +*/ +#ifdef __i386__ + mov eax,DWORD PTR [esp+0x4] // from_co + mov edx,DWORD PTR [esp] // retaddr + lea ecx,[esp+0x4] // esp + mov DWORD PTR [eax+0x8],ebp //esp + mov ebp,DWORD PTR [ecx+0x8] //>ebp + mov eax,DWORD PTR [ecx+0x0] //>retaddr + mov edi,DWORD PTR [ecx+0xc] //>edi + mov esi,DWORD PTR [ecx+0x10] //>esi + mov ebx,DWORD PTR [ecx+0x14] //>ebx +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + fldcw WORD PTR [ecx+0x18] //>fpucw + ldmxcsr DWORD PTR [ecx+0x1c] //>mxcsr +#endif + xor ecx,ecx + mov esp,edx + mov edx,eax + + // Pass the user-provided argument as first argument: +#ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + mov eax,DWORD PTR [ecx+0x24] +#else + mov eax,DWORD PTR [ecx+0x28] +#endif + + jmp edx +#elif __x86_64__ +/* + 0x00 --> 0xff + r12 r13 r14 r15 rip rsp rbx rbp fpucw16 mxcsr32 + 0 8 10 18 20 28 30 38 40 44 +*/ + // rdi - from_co | rsi - to_co + mov rdx,QWORD PTR [rsp] // retaddr + lea rcx,[rsp+0x8] // rsp + mov QWORD PTR [rdi+0x0], r12 + mov QWORD PTR [rdi+0x8], r13 + mov QWORD PTR [rdi+0x10],r14 + mov QWORD PTR [rdi+0x18],r15 + mov QWORD PTR [rdi+0x20],rdx // retaddr + mov QWORD PTR [rdi+0x28],rcx // rsp + mov QWORD PTR [rdi+0x30],rbx + mov QWORD PTR [rdi+0x38],rbp +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + fnstcw WORD PTR [rdi+0x40] + stmxcsr DWORD PTR [rdi+0x44] +#endif + mov r12,QWORD PTR [rsi+0x0] + mov r13,QWORD PTR [rsi+0x8] + mov r14,QWORD PTR [rsi+0x10] + mov r15,QWORD PTR [rsi+0x18] + mov rax,QWORD PTR [rsi+0x20] // retaddr + mov rcx,QWORD PTR [rsi+0x28] // rsp + mov rbx,QWORD PTR [rsi+0x30] + mov rbp,QWORD PTR [rsi+0x38] +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + fldcw WORD PTR [rsi+0x40] + ldmxcsr DWORD PTR [rsi+0x44] +#endif + + // Pass the user-provided argument as first argument: +#ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + mov rdi,QWORD PTR [rsi+0x48] +#else + mov rdi,QWORD PTR [rsi+0x50] +#endif + + mov rsp,rcx + jmp rax +#else + #error "platform not supported" +#endif + +.globl aco_save_fpucw_mxcsr +#if defined(__APPLE__) +#else +.type aco_save_fpucw_mxcsr, @function +#endif +.intel_syntax noprefix +aco_save_fpucw_mxcsr: +#ifdef __i386__ + mov eax,DWORD PTR [esp+0x4] // ptr + fnstcw WORD PTR [eax] + stmxcsr DWORD PTR [eax+0x4] + ret +#elif __x86_64__ + fnstcw WORD PTR [rdi] + stmxcsr DWORD PTR [rdi+0x4] + ret +#else + #error "platform not supported" +#endif + +#if defined(__APPLE__) +.globl _abort +.globl _aco_funcp_protector +#else +.globl abort +.globl aco_funcp_protector +#endif + +.globl aco_funcp_protector_asm +#if defined(__APPLE__) +#else +.type aco_funcp_protector_asm, @function +#endif +.intel_syntax noprefix +aco_funcp_protector_asm: +#ifdef __i386__ + and esp,0xfffffff0 + #if defined(__APPLE__) + call _aco_funcp_protector + call _abort + #else + #if defined(__pic__) || defined(__PIC__) + call aco_funcp_protector@PLT + call abort@PLT + #else + call aco_funcp_protector + call abort + #endif + #endif + ret +#elif __x86_64__ + and rsp,0xfffffffffffffff0 + #if defined(__APPLE__) + call _aco_funcp_protector + call _abort + #else + #if defined(__pic__) || defined(__PIC__) + call aco_funcp_protector@PLT + call abort@PLT + #else + call aco_funcp_protector + call abort + #endif + #endif + ret +#else + #error "platform not supported" +#endif -- cgit v1.2.3