bsnes/libco.x86.asm

156 lines
3.4 KiB
NASM
Raw Normal View History

;*****
;libco.x86 (2007-12-11)
;author: byuu
;license: public domain
;
;cross-platform x86 implementation of libco
;thanks to Aaron Giles and Joel Yliluoma for various optimizations
;thanks to Lucas Newman and Vas Crabb for assistance with OS X support
;
;[ABI compatibility]
;- visual c++; windows; x86
;- mingw; windows; x86
;- gcc; mac os x; x86
;- gcc; linux; x86
;- gcc; freebsd; x86
;
;[nonvolatile registers]
;- esp, ebp, edi, esi, ebx
;
;[volatile registers]
;- eax, ecx, edx
;- st0 - st7
;- xmm0 - xmm15
;*****
;*****
;linker-specific name decorations
;*****
%ifdef WIN
%define malloc _malloc
%define free _free
%define co_active @co_active@0
%define co_create @co_create@8
%define co_delete @co_delete@4
%define co_switch @co_switch@4
%endif
%ifdef OSX
%define malloc _malloc
%define free _free
%define co_active _co_active
%define co_create _co_create
%define co_delete _co_delete
%define co_switch _co_switch
%endif
bits 32
section .bss
align 4
co_primary_buffer resb 512
section .data
align 4
co_active_context dd co_primary_buffer
section .text
extern malloc
extern free
global co_active
global co_create
global co_delete
global co_switch
;*****
;extern "C" cothread_t fastcall co_active();
;return = eax
;*****
align 16
co_active:
mov eax,[co_active_context]
ret
;*****
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
;ecx = heapsize
;edx = coentry
;return = eax
;*****
align 16
co_create:
;create heap space (stack + context)
add ecx,512 ;allocate extra memory for contextual info
push ecx ;backup volatile registers before malloc call
push edx
push ecx
call malloc ;eax = malloc(ecx)
add esp,4
pop edx ;restore volatile registers
pop ecx
add ecx,eax ;set edx to point to top of stack heap
and ecx,-16 ;force 16-byte alignment of stack heap
;store thread entry point + registers, so that first call to co_switch will execute coentry
mov dword[ecx-4],0 ;crash if entry point returns
mov dword[ecx-8],edx ;entry point
mov dword[ecx-12],0 ;ebp
mov dword[ecx-16],0 ;esi
mov dword[ecx-20],0 ;edi
mov dword[ecx-24],0 ;ebx
sub ecx,24
;initialize context memory heap and return
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
ret ;return allocated memory block as thread handle
;*****
;extern "C" void fastcall co_delete(cothread_t cothread);
;ecx = cothread
;*****
align 16
co_delete:
sub esp,8 ;SSE 16-byte stack alignment
push ecx
call free ;free(ecx)
add esp,4+8
ret
;*****
;extern "C" void fastcall co_switch(cothread_t cothread);
;ecx = cothread
;*****
align 16
co_switch:
mov eax,[co_active_context] ;backup current context
mov [co_active_context],ecx ;set new active context
push ebp
push esi
push edi
push ebx
mov [eax],esp
mov esp,[ecx]
pop ebx
pop edi
pop esi
pop ebp
ret