Piotr Caban : msvcrt: Call cdecl functions with empty FPU stack in _CI* functions.

Alexandre Julliard julliard at winehq.org
Tue Nov 28 15:11:04 CST 2017


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Mon Nov 27 20:29:44 2017 +0100

msvcrt: Call cdecl functions with empty FPU stack in _CI* functions.

The FPU stack should be empty on cdecl function call. Failing to do so
breaks GCC 6.4.0 -O2 optimized code.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/math.c | 269 ++++++++++++++++++++++-------------------------------
 1 file changed, 111 insertions(+), 158 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index b7288cf..0627bfa 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -593,164 +593,117 @@ double CDECL MSVCRT_tanh( double x )
 
 #if defined(__GNUC__) && defined(__i386__)
 
-#define FPU_DOUBLE(var) double var; \
-  __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
-#define FPU_DOUBLES(var1,var2) double var1,var2; \
-  __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
-  __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
-
-/*********************************************************************
- *		_CIacos (MSVCRT.@)
- */
-double CDECL _CIacos(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_acos(x);
-}
-
-/*********************************************************************
- *		_CIasin (MSVCRT.@)
- */
-double CDECL _CIasin(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_asin(x);
-}
-
-/*********************************************************************
- *		_CIatan (MSVCRT.@)
- */
-double CDECL _CIatan(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_atan(x);
-}
-
-/*********************************************************************
- *		_CIatan2 (MSVCRT.@)
- */
-double CDECL _CIatan2(void)
-{
-  FPU_DOUBLES(x,y);
-  return MSVCRT_atan2(x,y);
-}
-
-/*********************************************************************
- *		_CIcos (MSVCRT.@)
- */
-double CDECL _CIcos(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_cos(x);
-}
-
-/*********************************************************************
- *		_CIcosh (MSVCRT.@)
- */
-double CDECL _CIcosh(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_cosh(x);
-}
-
-/*********************************************************************
- *		_CIexp (MSVCRT.@)
- */
-double CDECL _CIexp(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_exp(x);
-}
-
-/*********************************************************************
- *		_CIfmod (MSVCRT.@)
- */
-double CDECL _CIfmod(void)
-{
-  FPU_DOUBLES(x,y);
-  return MSVCRT_fmod(x,y);
-}
-
-/*********************************************************************
- *		_CIlog (MSVCRT.@)
- */
-double CDECL _CIlog(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_log(x);
-}
-
-/*********************************************************************
- *		_CIlog10 (MSVCRT.@)
- */
-double CDECL _CIlog10(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_log10(x);
-}
-
-/*********************************************************************
- *		_CIpow (MSVCRT.@)
- */
-double CDECL _CIpow(void)
-{
-  FPU_DOUBLES(x,y);
-  return MSVCRT_pow(x,y);
-}
-
-/*********************************************************************
- *		_CIsin (MSVCRT.@)
- */
-double CDECL _CIsin(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_sin(x);
-}
-
-/*********************************************************************
- *		_CIsinh (MSVCRT.@)
- */
-double CDECL _CIsinh(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_sinh(x);
-}
-
-/*********************************************************************
- *		_CIsqrt (MSVCRT.@)
- */
-double CDECL _CIsqrt(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_sqrt(x);
-}
-
-/*********************************************************************
- *		_CItan (MSVCRT.@)
- */
-double CDECL _CItan(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_tan(x);
-}
-
-/*********************************************************************
- *		_CItanh (MSVCRT.@)
- */
-double CDECL _CItanh(void)
-{
-  FPU_DOUBLE(x);
-  return MSVCRT_tanh(x);
-}
-
-/*********************************************************************
- *                  _ftol   (MSVCRT.@)
- */
-LONGLONG CDECL MSVCRT__ftol(void)
-{
-    FPU_DOUBLE(x);
-    return (LONGLONG)x;
-}
+#define CREATE_FPU_FUNC1(name, call) \
+    __ASM_GLOBAL_FUNC(name, \
+            "pushl   %ebp\n\t" \
+            __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
+            __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
+            "movl    %esp, %ebp\n\t" \
+            __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
+            "subl    $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
+            "fstpl   (%esp)\n\t"    /* store function argument */ \
+            "fwait\n\t" \
+            "movl    $1, %ecx\n\t"  /* empty FPU stack */ \
+            "1:\n\t" \
+            "fxam\n\t" \
+            "fstsw   %ax\n\t" \
+            "and     $0x4500, %ax\n\t" \
+            "cmp     $0x4100, %ax\n\t" \
+            "je      2f\n\t" \
+            "fstpl    (%esp,%ecx,8)\n\t" \
+            "fwait\n\t" \
+            "incl    %ecx\n\t" \
+            "jmp     1b\n\t" \
+            "2:\n\t" \
+            "movl    %ecx, -4(%ebp)\n\t" \
+            "call    " __ASM_NAME( #call ) "\n\t" \
+            "movl    -4(%ebp), %ecx\n\t" \
+            "fstpl   (%esp)\n\t"    /* save result */ \
+            "3:\n\t"                /* restore FPU stack */ \
+            "decl    %ecx\n\t" \
+            "fldl    (%esp,%ecx,8)\n\t" \
+            "cmpl    $0, %ecx\n\t" \
+            "jne     3b\n\t" \
+            "leave\n\t" \
+            __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
+            __ASM_CFI(".cfi_same_value %ebp\n\t") \
+            "ret")
+
+#define CREATE_FPU_FUNC2(name, call) \
+    __ASM_GLOBAL_FUNC(name, \
+            "pushl   %ebp\n\t" \
+            __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
+            __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
+            "movl    %esp, %ebp\n\t" \
+            __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
+            "subl    $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
+            "fstpl   8(%esp)\n\t"   /* store function argument */ \
+            "fwait\n\t" \
+            "fstpl   (%esp)\n\t" \
+            "fwait\n\t" \
+            "movl    $2, %ecx\n\t"  /* empty FPU stack */ \
+            "1:\n\t" \
+            "fxam\n\t" \
+            "fstsw   %ax\n\t" \
+            "and     $0x4500, %ax\n\t" \
+            "cmp     $0x4100, %ax\n\t" \
+            "je      2f\n\t" \
+            "fstpl    (%esp,%ecx,8)\n\t" \
+            "fwait\n\t" \
+            "incl    %ecx\n\t" \
+            "jmp     1b\n\t" \
+            "2:\n\t" \
+            "movl    %ecx, -4(%ebp)\n\t" \
+            "call    " __ASM_NAME( #call ) "\n\t" \
+            "movl    -4(%ebp), %ecx\n\t" \
+            "fstpl   8(%esp)\n\t"   /* save result */ \
+            "3:\n\t"                /* restore FPU stack */ \
+            "decl    %ecx\n\t" \
+            "fldl    (%esp,%ecx,8)\n\t" \
+            "cmpl    $1, %ecx\n\t" \
+            "jne     3b\n\t" \
+            "leave\n\t" \
+            __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
+            __ASM_CFI(".cfi_same_value %ebp\n\t") \
+            "ret")
+
+CREATE_FPU_FUNC1(_CIacos, MSVCRT_acos)
+CREATE_FPU_FUNC1(_CIasin, MSVCRT_asin)
+CREATE_FPU_FUNC1(_CIatan, MSVCRT_atan)
+CREATE_FPU_FUNC2(_CIatan2, MSVCRT_atan2)
+CREATE_FPU_FUNC1(_CIcos, MSVCRT_cos)
+CREATE_FPU_FUNC1(_CIcosh, MSVCRT_cosh)
+CREATE_FPU_FUNC1(_CIexp, MSVCRT_exp)
+CREATE_FPU_FUNC2(_CIfmod, MSVCRT_fmod)
+CREATE_FPU_FUNC1(_CIlog, MSVCRT_log)
+CREATE_FPU_FUNC1(_CIlog10, MSVCRT_log10)
+CREATE_FPU_FUNC2(_CIpow, MSVCRT_pow)
+CREATE_FPU_FUNC1(_CIsin, MSVCRT_sin)
+CREATE_FPU_FUNC1(_CIsinh, MSVCRT_sinh)
+CREATE_FPU_FUNC1(_CIsqrt, MSVCRT_sqrt)
+CREATE_FPU_FUNC1(_CItan, MSVCRT_tan)
+CREATE_FPU_FUNC1(_CItanh, MSVCRT_tanh)
+
+__ASM_GLOBAL_FUNC(MSVCRT__ftol,
+        "pushl   %ebp\n\t"
+        __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+        __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+        "movl    %esp, %ebp\n\t"
+        __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+        "subl    $12, %esp\n\t"     /* sizeof(LONGLONG) + 2*sizeof(WORD) */
+        "fnstcw  (%esp)\n\t"
+        "mov     (%esp), %ax\n\t"
+        "or      $0xc, %ax\n\t"
+        "mov     %ax, 2(%esp)\n\t"
+        "fldcw   2(%esp)\n\t"
+        "fistpq  4(%esp)\n\t"
+        "fldcw   (%esp)\n\t"
+        "movl    4(%esp), %eax\n\t"
+        "movl    8(%esp), %edx\n\t"
+        "leave\n\t"
+        __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+        __ASM_CFI(".cfi_same_value %ebp\n\t")
+        "ret")
 
 #endif /* defined(__GNUC__) && defined(__i386__) */
 




More information about the wine-cvs mailing list