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;


Reply via email to