Hi,
Yes, the code is absolutely required as in: I do not know how you would achieve what you need to do there -calling a C function using the appropriate platform ABI- outside of assembler.
Cheers, - Andreas
----- Original Message ----- From: "Alejandro F. Reimondo" aleReimondo@smalltalking.net To: "The general-purpose Squeak developers list" squeak-dev@lists.squeakfoundation.org Cc: "Andreas Raab" raab@isgnw.cs.Uni-Magdeburg.DE Sent: Monday, October 25, 2004 5:44 AM Subject: is really "__asm" needed for current FFI support?
Hi Andreas, all, I have found the current implementation of FFI a little complex, but I think that it is related with some perfomance needs. Trying to make a build under WinCE I have found that currently a piece of assembler code must be implemented for each platform&processor... Please confirm me if it is really required, or if someone knows any standard C code to put for ffiCallAddress: implementation (or any higher level function). I think that it will be hard for me to port the asm code to my winCE host processor (ARM4). I can try to make the effort, but think that we will really need a 100% standard C level compatibility for FFI (as we have in very first versions). The current assembler code implemented for win32 platform follows this email. Thanks for your time! Ale.
/*************************************************************************** **/ /*************************************************************************** **/ int oldSP; int oldBP; int newSP; int newBP;
/* ffiCallAddress: Perform the actual function call. */ int ffiCallAddress(int fn) { #if 0 { FILE *f = fopen("ffi.log","at"); fprintf(f, "%x",fn); fflush(f); fclose(f); } #endif #ifdef _MSC_VER __asm { push ebx mov ebx, fn push ecx push edx push edi push esi push ebp /* mark the frame */ mov ebp, esp /* alloca() ffiStackIndex size bytes */ mov ecx, ffiArgIndex shl ecx, 2 sub esp, ecx /* copy stack */ mov edi, esp lea esi, ffiArgs shr ecx, 2 cld rep movsd /* go calling */ call ebx /* restore frame */ mov esp, ebp /* store the return values */ mov intReturnValue, eax mov intReturnValue2, edx fstp floatReturnValue /* restore register values */ pop ebp pop esi pop edi pop edx pop ecx pop ebx /* done */ } #endif #ifdef __GNUC__ asm(" movl %%ebp, _oldBP movl %%esp, _oldSP pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%edi; pushl %%esi; pushl %%ebp; /* mark the frame */ movl %%esp, %%ebp /* alloca() ffiStackIndex size bytes */ movl _ffiArgIndex, %%ecx; shll $2, %%ecx; subl %%ecx, %%esp /* copy stack */ movl %%esp, %%edi; leal _ffiArgs, %%esi; shrl $2, %%ecx; cld; rep movsl; /* go calling */ call *%%ebx /* restore frame */ movl %%ebp, %%esp /* store the return values */ movl %%eax, _intReturnValue movl %%edx, _intReturnValue2 fstpl _floatReturnValue /* restore register values */ popl %%ebp popl %%esi popl %%edi popl %%edx popl %%ecx popl %%ebx movl %%ebp, _newBP movl %%esp, _newSP ": /* no outputs */ : "ebx" (fn) : "eax" /* clobbered registers */); /* done */ #endif #if 0 { FILE *f = fopen("ffi.log","at"); fprintf(f, "...ok\n"); if(oldBP != newBP || oldSP != newSP) { fprintf(f,"oldSP=%x, oldBP=%x\nnewSP=%x, newBP=%x\n",oldSP, oldBP,newSP,newBP); } fprintf(f,"SP=%x, BP=%x\n",newSP,newBP); fflush(f); fclose(f); } #endif return intReturnValue; }
int ffiCallAddressOfWithPointerReturn(int fn, int callType) { return ffiCallAddress(fn); } int ffiCallAddressOfWithStructReturn(int fn, int callType, int* structSpec, int specSize) { return ffiCallAddress(fn); }
int ffiCallAddressOfWithReturnType(int fn, int callType, int typeSpec) { return ffiCallAddress(fn); }