On Wed, Jan 04, 2006 at 09:14:18PM -0800, Dan Kegel wrote:
This would definitely be better handled in assembly...
Here is the first try. It leaves the old version for non-intel and non-gcc compilers.
Ciao, Marcus
Index: typelib.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v retrieving revision 1.200 diff -u -r1.200 typelib.c --- typelib.c 3 Jan 2006 12:42:34 -0000 1.200 +++ typelib.c 5 Jan 2006 09:07:25 -0000 @@ -4843,7 +4843,33 @@
switch (callconv) { case CC_STDCALL: +#if defined(__i386__) && defined(__GNUC__)
+ __asm__( + /* store all stuff into registers now, since we modify the stack */ + " mov %1, %%ecx\n" + " mov %2, %%edx\n" + " mov %3, %%esi\n" + " test %%ecx, %%ecx\n" + " jz 1f\n" /* no args, nothing to push */ + /* + * Arguments are pushed from right to left. + * We use intel memory move operations. + */ + " std\n" /* direction: backward */ + "2: lodsl\n" /* moves *esi -> eax, esi-= 4 */ + " pushl %%eax\n" + " dec %%ecx\n" + " jnz 2b\n" + "1: cld\n" /* direction: forward (default) */ + " call *%%edx\n" + " mov %%eax, %0\n" + : "=g" (res) + : "g" (nrargs), "g" (func), "g" (args + (nrargs-1)) + : "memory", "cc", "ax", "si", "cx", "dx" + ); + break; +#else switch (nrargs) { case 0: res = func(); @@ -4905,6 +4931,7 @@ break; } break; +#endif default: FIXME("unsupported calling convention %d\n",callconv); res = -1;