Alexandre Julliard : rpcrt4: Add support for float parameters in client calls on x86_64.

Alexandre Julliard julliard at winehq.org
Thu Jun 16 14:28:49 CDT 2011


Module: wine
Branch: master
Commit: ffb8f4bedf709dd63f6f9ec1569dc99873021a11
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ffb8f4bedf709dd63f6f9ec1569dc99873021a11

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun 13 13:39:21 2011 +0200

rpcrt4: Add support for float parameters in client calls on x86_64.

---

 dlls/rpcrt4/cproxy.c       |   12 ++++++---
 dlls/rpcrt4/ndr_stubless.c |   54 +++++++++++++++++++++++++++++++-------------
 dlls/rpcrt4/ndr_stubless.h |    2 +-
 3 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/dlls/rpcrt4/cproxy.c b/dlls/rpcrt4/cproxy.c
index b5be7ae..b1acbb0 100644
--- a/dlls/rpcrt4/cproxy.c
+++ b/dlls/rpcrt4/cproxy.c
@@ -131,11 +131,15 @@ __ASM_GLOBAL_FUNC(call_stubless_func,
                   "movzwq (%rdx,%r10,2),%rdx\n\t" /* FormatStringOffset[index] */
                   "addq 8(%rcx),%rdx\n\t"         /* info->ProcFormatString + offset */
                   "movq (%rcx),%rcx\n\t"          /* info->pStubDesc */
-                  "subq $0x28,%rsp\n\t"
-                  __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
+                  "subq $0x38,%rsp\n\t"
+                  __ASM_CFI(".cfi_adjust_cfa_offset 0x38\n\t")
+                  "movq %xmm1,0x20(%rsp)\n\t"
+                  "movq %xmm2,0x28(%rsp)\n\t"
+                  "movq %xmm3,0x30(%rsp)\n\t"
+                  "leaq 0x18(%rsp),%r9\n\t"       /* fpu_args */
                   "call " __ASM_NAME("ndr_client_call") "\n\t"
-                  "addq $0x28,%rsp\n\t"
-                  __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
+                  "addq $0x38,%rsp\n\t"
+                  __ASM_CFI(".cfi_adjust_cfa_offset -0x38\n\t")
                   "ret" );
 
 #include "pshpack1.h"
diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c
index 7fd7e6a..1f34b76 100644
--- a/dlls/rpcrt4/ndr_stubless.c
+++ b/dlls/rpcrt4/ndr_stubless.c
@@ -285,8 +285,8 @@ static void client_free_handle(
 }
 
 static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
-    int phase, unsigned char *args, unsigned short number_of_params,
-    unsigned char *pRetVal)
+                           int phase, unsigned char *args, void **fpu_args,
+                           unsigned short number_of_params, unsigned char *pRetVal)
 {
     /* current format string offset */
     int current_offset = 0;
@@ -314,6 +314,14 @@ static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
             const unsigned char * pTypeFormat =
                 &pParam->type_format_char;
 
+#ifdef __x86_64__  /* floats are passed as doubles through varargs functions */
+            float f;
+            if (*pTypeFormat == RPC_FC_FLOAT && !pParam->param_attributes.IsSimpleRef && !fpu_args)
+            {
+                f = *(double *)pArg;
+                pArg = (unsigned char *)&f;
+            }
+#endif
             if (pParam->param_attributes.IsSimpleRef)
             {
                 pArg = *(unsigned char **)pArg;
@@ -565,7 +573,8 @@ void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
     }
 }
 
-LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, void **stack_top )
+LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
+                                void **stack_top, void **fpu_stack )
 {
     /* pointer to start of stack where arguments start */
     RPC_MESSAGE rpcMsg;
@@ -652,16 +661,28 @@ LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
         number_of_params = pOIFHeader->number_of_params;
 
         pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
-    }
 
-    TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
+        TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
 
-    if (Oif_flags.HasExtensions)
-    {
-        const NDR_PROC_HEADER_EXTS *pExtensions =
-            (const NDR_PROC_HEADER_EXTS *)pFormat;
-        ext_flags = pExtensions->Flags2;
-        pFormat += pExtensions->Size;
+        if (Oif_flags.HasExtensions)
+        {
+            const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
+            ext_flags = pExtensions->Flags2;
+            pFormat += pExtensions->Size;
+#ifdef __x86_64__
+            if (pExtensions->Size > sizeof(*pExtensions) && fpu_stack)
+            {
+                int i;
+                unsigned short fpu_mask = *(unsigned short *)(pExtensions + 1);
+                for (i = 0; i < 4; i++, fpu_mask >>= 2)
+                    switch (fpu_mask & 3)
+                    {
+                    case 1: *(float *)&stack_top[i] = *(float *)&fpu_stack[i]; break;
+                    case 2: *(double *)&stack_top[i] = *(double *)&fpu_stack[i]; break;
+                    }
+            }
+#endif
+        }
     }
 
     stubMsg.BufferLength = 0;
@@ -766,7 +787,7 @@ LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
                 case PROXY_MARSHAL:
                 case PROXY_UNMARSHAL:
                     if (bV2Format)
-                        client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop,
+                        client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop, fpu_stack,
                             number_of_params, (unsigned char *)&RetVal);
                     else
                         client_do_args_old_format(&stubMsg, pFormat, phase,
@@ -870,7 +891,7 @@ LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pForma
             case PROXY_MARSHAL:
             case PROXY_UNMARSHAL:
                 if (bV2Format)
-                    client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop,
+                    client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop, fpu_stack,
                         number_of_params, (unsigned char *)&RetVal);
                 else
                     client_do_args_old_format(&stubMsg, pFormat, phase,
@@ -919,6 +940,7 @@ __ASM_GLOBAL_FUNC( NdrClientCall2,
                    "movq %r8,0x18(%rsp)\n\t"
                    "movq %r9,0x20(%rsp)\n\t"
                    "leaq 0x18(%rsp),%r8\n\t"
+                   "xorq %r9,%r9\n\t"
                    "subq $0x28,%rsp\n\t"
                    __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
                    "call " __ASM_NAME("ndr_client_call") "\n\t"
@@ -937,7 +959,7 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING
     LONG_PTR ret;
 
     __ms_va_start( args, format );
-    ret = ndr_client_call( desc, format, va_arg( args, void ** ));
+    ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL );
     __ms_va_end( args );
     return *(CLIENT_CALL_RETURN *)&ret;
 }
@@ -1947,7 +1969,7 @@ CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall(PMIDL_STUB_DESC pStubDesc,
         case PROXY_CALCSIZE:
         case PROXY_MARSHAL:
             if (bV2Format)
-                client_do_args(pStubMsg, pFormat, phase, pStubMsg->StackTop,
+                client_do_args(pStubMsg, pFormat, phase, pStubMsg->StackTop, NULL,
                     async_call_data->number_of_params, NULL);
             else
                 client_do_args_old_format(pStubMsg, pFormat, phase,
@@ -2032,7 +2054,7 @@ RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
         case PROXY_UNMARSHAL:
             if (bV2Format)
                 client_do_args(pStubMsg, async_call_data->pParamFormat, phase, pStubMsg->StackTop,
-                    async_call_data->number_of_params, Reply);
+                               NULL, async_call_data->number_of_params, Reply);
             else
                 client_do_args_old_format(pStubMsg, async_call_data->pParamFormat, phase,
                     pStubMsg->StackTop, async_call_data->stack_size, Reply, FALSE, FALSE);
diff --git a/dlls/rpcrt4/ndr_stubless.h b/dlls/rpcrt4/ndr_stubless.h
index baa1f3e..3fa0922 100644
--- a/dlls/rpcrt4/ndr_stubless.h
+++ b/dlls/rpcrt4/ndr_stubless.h
@@ -237,7 +237,7 @@ typedef struct _NDR_EHD_CONTEXT
 #include "poppack.h"
 
 LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
-                                void **stack_top ) DECLSPEC_HIDDEN;
+                                void **stack_top, void **fpu_stack ) DECLSPEC_HIDDEN;
 void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
     PFORMAT_STRING pFormat, int phase, unsigned char *args,
     unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc,




More information about the wine-cvs mailing list