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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2017-11-27 20:29:44 +01:00 committed by Alexandre Julliard
parent a7ba456587
commit ee33d38c50

View file

@ -593,164 +593,117 @@ double CDECL MSVCRT_tanh( double x )
#if defined(__GNUC__) && defined(__i386__) #if defined(__GNUC__) && defined(__i386__)
#define FPU_DOUBLE(var) double var; \ #define CREATE_FPU_FUNC1(name, call) \
__asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : ) __ASM_GLOBAL_FUNC(name, \
#define FPU_DOUBLES(var1,var2) double var1,var2; \ "pushl %ebp\n\t" \
__asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
__asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : ) __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) \
* _CIacos (MSVCRT.@) __ASM_GLOBAL_FUNC(name, \
*/ "pushl %ebp\n\t" \
double CDECL _CIacos(void) __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
{ __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
FPU_DOUBLE(x); "movl %esp, %ebp\n\t" \
return MSVCRT_acos(x); __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)
* _CIasin (MSVCRT.@) CREATE_FPU_FUNC1(_CIasin, MSVCRT_asin)
*/ CREATE_FPU_FUNC1(_CIatan, MSVCRT_atan)
double CDECL _CIasin(void) CREATE_FPU_FUNC2(_CIatan2, MSVCRT_atan2)
{ CREATE_FPU_FUNC1(_CIcos, MSVCRT_cos)
FPU_DOUBLE(x); CREATE_FPU_FUNC1(_CIcosh, MSVCRT_cosh)
return MSVCRT_asin(x); 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,
* _CIatan (MSVCRT.@) "pushl %ebp\n\t"
*/ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
double CDECL _CIatan(void) __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
{ "movl %esp, %ebp\n\t"
FPU_DOUBLE(x); __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
return MSVCRT_atan(x); "subl $12, %esp\n\t" /* sizeof(LONGLONG) + 2*sizeof(WORD) */
} "fnstcw (%esp)\n\t"
"mov (%esp), %ax\n\t"
/********************************************************************* "or $0xc, %ax\n\t"
* _CIatan2 (MSVCRT.@) "mov %ax, 2(%esp)\n\t"
*/ "fldcw 2(%esp)\n\t"
double CDECL _CIatan2(void) "fistpq 4(%esp)\n\t"
{ "fldcw (%esp)\n\t"
FPU_DOUBLES(x,y); "movl 4(%esp), %eax\n\t"
return MSVCRT_atan2(x,y); "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")
* _CIcos (MSVCRT.@) "ret")
*/
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;
}
#endif /* defined(__GNUC__) && defined(__i386__) */ #endif /* defined(__GNUC__) && defined(__i386__) */