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;