crt: Provide a common __mingw_has_sse()

This commit moves `__mingw_has_sse()` to a separate file, and makes its
result cacheable.

SSE is required for x86-64, and can be enabled for x86-32 by passing `-msse`
to GCC. On ARM and ARM64 it's always absent. A macro is defined if it would
be known to return a constant.

Co-authored-by: Morilli <molli.bender@gmail.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
This commit is contained in:
LIU Hao 2024-10-22 23:16:04 +08:00
parent e9a763950a
commit 7a9b6e1616
10 changed files with 68 additions and 63 deletions

View File

@ -1044,7 +1044,7 @@ src_libmingwex=\
misc/feclearexcept.c misc/fegetenv.c misc/fegetexceptflag.c misc/fegetround.c misc/feholdexcept.c \
misc/feraiseexcept.c misc/fesetenv.c misc/fesetexceptflag.c misc/fesetround.c misc/fetestexcept.c \
misc/feupdateenv.c misc/ftruncate.c misc/fwide.c misc/getlogin.c misc/getopt.c \
misc/gettimeofday.c \
misc/gettimeofday.c misc/__mingw_has_sse.c \
misc/mempcpy.c misc/mingw-aligned-malloc.c \
misc/mingw_matherr.c misc/mingw_mbwc_convert.c misc/mingw_usleep.c misc/mingw_wcstod.c misc/mingw_wcstof.c \
misc/mingw_wcstold.c \

View File

@ -146,6 +146,14 @@ extern "C" {
PIMAGE_SECTION_HEADER __cdecl _FindPESection (PBYTE pImageBase, DWORD_PTR rva);
BOOL __cdecl _IsNonwritableInCurrentImage (PBYTE pTarget);
#if defined(__SSE__)
# define __mingw_has_sse() 1
#elif defined(__i386__)
int __mingw_has_sse(void);
#else
# define __mingw_has_sse() 0
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,37 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#if defined(__i386__)
int __mingw_has_sse (void);
static int __has_sse = -1;
int __mingw_has_sse(void)
{
int cpuInfo[4], infoType = 1;
int o_flag, n_flag;
if (__has_sse != -1)
return __has_sse;
__asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (o_flag));
n_flag = o_flag ^ 0x200000;
__asm__ volatile ("pushl %0\n\tpopfl" : : "g" (n_flag));
__asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (n_flag));
if (n_flag == o_flag)
{
__has_sse = 0;
return 0;
}
__asm__ __volatile__ (
"cpuid"
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]),
"=d" (cpuInfo[3])
: "a" (infoType));
__has_sse = (cpuInfo[3] & 0x2000000);
return __has_sse;
}
#endif /* __i386__ */

View File

@ -3,36 +3,9 @@
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
int __mingw_has_sse (void);
int __mingw_has_sse(void)
{
int cpuInfo[4],infoType = 1;
#ifndef _WIN64
int o_flag, n_flag;
__asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (o_flag));
n_flag = o_flag ^ 0x200000;
__asm__ volatile ("pushl %0\n\tpopfl" : : "g" (n_flag));
__asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (n_flag));
if (n_flag == o_flag)
return 0;
#endif
__asm__ __volatile__ (
"cpuid"
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]),
"=d" (cpuInfo[3])
: "a" (infoType));
if (cpuInfo[3] & 0x2000000)
return 1;
return 0;
}
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
#include <internal.h>
/* 7.6.2.1
The feclearexcept function clears the supported exceptions

View File

@ -3,11 +3,9 @@
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
int __mingw_has_sse (void);
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
#include <fenv.h>
#include <internal.h>
/* 7.6.4.1
The fegetenv function stores the current floating-point environment

View File

@ -3,13 +3,11 @@
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#include <internal.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
extern int __mingw_has_sse (void);
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
/* 7.6.2.2
/* 7.6.2.2
The fegetexceptflag function stores an implementation-defined
representation of the exception flags indicated by the argument
excepts in the object pointed to by the argument flagp. */
@ -32,7 +30,7 @@ int fegetexceptflag (fexcept_t * flagp, int excepts)
_mxcsr = 0;
if (__mingw_has_sse ())
__asm__ volatile ("stmxcsr %0" : "=m" (_mxcsr));
*flagp = (_mxcsr | _status) & excepts & FE_ALL_EXCEPT;
#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */
return 0;

View File

@ -3,13 +3,11 @@
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <_mingw.h>
#include <fenv.h>
#include <float.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
extern int __mingw_has_sse (void);
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
#include <internal.h>
/* 7.6.4.3
The fesetenv function establishes the floating-point environment
@ -28,7 +26,7 @@ int fesetenv (const fenv_t * envp)
{
#if defined(_ARM_) || defined(__arm__)
if (envp == FE_DFL_ENV)
/* Use the choice made at app startup */
/* Use the choice made at app startup */
_fpreset();
else
__asm__ volatile ("fmxr FPSCR, %0" : : "r" (*envp));
@ -59,7 +57,7 @@ int fesetenv (const fenv_t * envp)
(* __MINGW_IMP_SYMBOL(_fpreset))();
else if (envp == FE_DFL_ENV)
/* Use the choice made at app startup */
/* Use the choice made at app startup */
_fpreset();
else

View File

@ -3,11 +3,9 @@
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
extern int __mingw_has_sse (void);
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
#include <fenv.h>
#include <internal.h>
/* 7.6.2.4
The fesetexceptflag function sets the complete status for those
@ -16,9 +14,9 @@ extern int __mingw_has_sse (void);
*flagp shall have been set by a previous call to fegetexceptflag
whose second argument represented at least those exceptions
represented by the argument excepts. This function does not raise
exceptions, but only sets the state of the flags. */
exceptions, but only sets the state of the flags. */
int fesetexceptflag (const fexcept_t * flagp, int excepts)
int fesetexceptflag (const fexcept_t * flagp, int excepts)
{
fenv_t _env;

View File

@ -3,11 +3,9 @@
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
int __mingw_has_sse (void);
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
#include <fenv.h>
#include <internal.h>
/* 7.6.3.2
The fesetround function establishes the rounding direction
@ -42,7 +40,7 @@ int fesetround (int mode)
_cw &= ~0xc00;
_cw |= mode;
__asm__ volatile ("fldcw %0;" : : "m" (*&_cw));
if (__mingw_has_sse ())
{
int mxcsr;

View File

@ -4,13 +4,10 @@
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <fenv.h>
#include <fenv.h>
#include <internal.h>
#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__))
extern int __mingw_has_sse (void);
#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */
/* 7.6.2.5
/* 7.6.2.5
The fetestexcept function determines which of a specified subset of
the exception flags are currently set. The excepts argument
specifies the exception flags to be queried.