Mercurial > pub > dyncall > dyncall
diff dyncall/dyncall_call_x86.S @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | 572aff021627 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dyncall/dyncall_call_x86.S Thu Mar 19 22:24:28 2015 +0100 @@ -0,0 +1,239 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_call_x86.S + Description: All - except Plan9 - x86 abi call kernel implementation + License: + + Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>, + Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + + +#include "../portasm/portasm-x86.S" +BEGIN_ASM +/* ============================================================================ + DynCall Call Kernels for X86 Architecture + ---------------------------------------------------------------------------- + C Interface: + dcCall_x86_XXX(void* target, void* args, size_t size); + ddCall_x86_sys_XXX(int_ptr target, void* args, size_t size); + + Where XXX is one of calling-conventions, + cdecl, win32_msthis, win32_std, win32_fastcall. + + Parameter Stack layout: + size := EBP + 16 + args := EBP + 12 + target := EBP + 8 + + NOTES: + - epilog restore ESP serves callee cleanup + - 16 byte alignment (to be compatible with darwin). +*/ + + +/*--- default / cdecl -------------------------------------------------------- + + Details: + - caller clean-up + +*/ + +GLOBAL(dcCall_x86_cdecl) +BEGIN_PROC(dcCall_x86_cdecl) + PUSH(EBP) /* prolog. */ + MOVL(ESP,EBP) + PUSH(ESI) /* save preserved registers. */ + PUSH(EDI) + MOVL(DWORD(EBP,12),ESI) /* ESI = arg buffer ptr */ + MOVL(DWORD(EBP,16),ECX) /* ECX = arg buffer size */ + ADDL(LIT(15),ECX) /* ECX = align(ECX,16) */ + ANDL(LIT(-16),ECX) + MOVL(ECX,DWORD(EBP,16)) /* save ECX. */ + SUBL(ECX,ESP) /* allocate stack size */ + MOVL(ESP,EDI) /* EDI = stack ptr */ + + /* + work around for rep movsd (not supported by SunPro) + + SHRL(LIT(2),ECX) + REP(MOVSD) + + */ + + REP(MOVSB) + CALL_DWORD(EBP,8) + ADDL(DWORD(EBP,16),ESP) + POP(EDI) + POP(ESI) + MOVL(EBP,ESP) + POP(EBP) + RET() +END_PROC(dcCall_x86_cdecl) +/* ---- C++ this calls (microsoft) ------------------------------------------ + + Details: + - this pointer is in ECX + +*/ + +GLOBAL(dcCall_x86_win32_msthis) +BEGIN_PROC(dcCall_x86_win32_msthis) + PUSH(EBP) /* prolog. */ + MOVL(ESP,EBP) + PUSH(ESI) /* save preserved. */ + PUSH(EDI) + MOVL(DWORD(EBP,12),ESI) /* ESI = pointer on args. */ + MOVL(DWORD(EBP,16),ECX) /* ECX = size. */ + MOVL(DWORD(ESI,0),EAX) /* EAX = this pointer. */ + ADDL(LIT(4),ESI) /* increment args pointer by thisptr. */ + SUBL(LIT(4),ECX) /* decrement size by sizeof(thisptr). */ + SUBL(ECX,ESP) /* allocate argument-block on stack. */ + MOVL(ESP,EDI) /* EDI = stack args. */ + REP(MOVSB) /* copy arguments. */ + MOVL(EAX,ECX) /* ECX = this pointer. */ + CALL_DWORD(EBP,8) /* call function. */ + POP(EDI) /* restore preserved. */ + POP(ESI) + MOVL(EBP,ESP) /* epilog. */ + POP(EBP) + RET() +END_PROC(dcCall_x86_win32_msthis) + +/*---- win32 stdcall --------------------------------------------------------- + + Details: + - callee cleans up stack + +*/ + +GLOBAL(dcCall_x86_win32_std) +BEGIN_PROC(dcCall_x86_win32_std) + PUSH(EBP) /* prolog. */ + MOVL(ESP,EBP) + PUSH(ESI) /* save ESI, EDI. */ + PUSH(EDI) + MOVL(DWORD(EBP,12),ESI) /* ESI = args. */ + MOVL(DWORD(EBP,16),ECX) /* ECX = size. */ + SUBL(ECX,ESP) /* allocate size bytes on stack. */ + MOVL(ESP,EDI) /* EDI = copy destination stack. */ + REP(MOVSB) /* copy BYTEs. */ + CALL_DWORD(EBP,8) /* call target. */ + POP(EDI) /* restore EDI, ESI. */ + POP(ESI) + MOVL(EBP,ESP) /* epilog. */ + POP(EBP) + RET() +END_PROC(dcCall_x86_win32_std) + +/*---- win32 fastcall (GNU/Microsoft) ---------------------------------------- + + Details: + - callee cleans up stack + - first two integer (up to 32bits) are passed in ECX and EDX + +*/ + +GLOBAL(dcCall_x86_win32_fast) +BEGIN_PROC(dcCall_x86_win32_fast) + PUSH(EBP) /* prolog. */ + MOVL(ESP,EBP) + PUSH(ESI) /* save preserved. */ + PUSH(EDI) + MOVL(DWORD(EBP,12),ESI) /* ESI = copy source args. */ + MOVL(DWORD(EBP,16),ECX) /* ECX = size. */ + MOVL(DWORD(ESI,0),EAX) /* EAX = first argument. */ + MOVL(DWORD(ESI,4),EDX) /* EDX = second argument. */ + ADDL(LIT(8),ESI) /* skip registers. */ + SUBL(LIT(8),ECX) + MOVL(ECX,DWORD(EBP,16)) /* save stack alloc size. */ + SUBL(ECX,ESP) /* allocate stack. */ + MOVL(ESP,EDI) /* EDI = stack args. */ + REP(MOVSB) /* copy BYTEs. */ + MOVL(EAX,ECX) /* ECX = first argument. */ + CALL_DWORD(EBP,8) /* call target. */ + POP(EDI) /* restore preserved. */ + POP(ESI) + MOVL(EBP,ESP) /* epilog. */ + POP(EBP) + RET() +END_PROC(dcCall_x86_win32_fast) + +/*--- syscall int80 linux --------------------------------------------------- + + Details: + - all arguments are passed via registers + +*/ + +GLOBAL(dcCall_x86_sys_int80h_linux) +BEGIN_PROC(dcCall_x86_sys_int80h_linux) + PUSH(EBP) /* prolog. */ + MOVL(ESP,EBP) + PUSH(EBX) /* save preserved. */ + PUSH(ESI) + PUSH(EDI) + MOVL(DWORD(EBP,12),EAX) /* EAX = argument buffer. */ + MOVL(DWORD(EAX,0),EBX) /* move first five arguments. */ + MOVL(DWORD(EAX,4),ECX) + MOVL(DWORD(EAX,8),EDX) + MOVL(DWORD(EAX,12),ESI) + MOVL(DWORD(EAX,16),EDI) + MOVL(DWORD(EBP,8),EAX) /* EAX = syscall id. */ + INT(LIT(HEX(80))) + POP(EDI) /* restore preserved. */ + POP(ESI) + POP(EBX) + MOVL(EBP,ESP) /* epilog. */ + POP(EBP) + RET() +END_PROC(dcCall_x86_sys_int80h_linux) + +/*--- syscall int80 bsd ----------------------------------------------------- + + Details: + - all arguments are passed via stack + +*/ + +GLOBAL(dcCall_x86_sys_int80h_bsd) +BEGIN_PROC(dcCall_x86_sys_int80h_bsd) + PUSH(EBP) /* prolog. */ + MOVL(ESP,EBP) + PUSH(ESI) /* save preserved. */ + PUSH(EDI) + MOVL(DWORD(EBP,12),ESI) /* ESI = pointer on args. */ + MOVL(DWORD(EBP,16),ECX) /* ECX = size. */ + SUBL(ECX,ESP) /* allocate stack space. */ + MOVL(ESP,EDI) /* EDI = stack args. */ + REP(MOVSB) + MOVL(DWORD(EBP,8),EAX) /* load system call id. */ + CALL(_do_int) + POP(EDI) /* restore preserved. */ + POP(ESI) + MOVL(EBP,ESP) /* epilog. */ + POP(EBP) + RET() +_do_int: + INT(LIT(HEX(80))) + RET() +END_PROC(dcCall_x86_sys_int80h_bsd) + +END_ASM +