diff options
Diffstat (limited to 'gcc/config/i386')
-rw-r--r-- | gcc/config/i386/cpuid.h | 3 | ||||
-rw-r--r-- | gcc/config/i386/driver-i386.c | 19 | ||||
-rw-r--r-- | gcc/config/i386/fxsrintrin.h | 61 | ||||
-rw-r--r-- | gcc/config/i386/i386-builtin-types.def | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386-c.c | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 210 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 3 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 146 | ||||
-rw-r--r-- | gcc/config/i386/i386.opt | 12 | ||||
-rw-r--r-- | gcc/config/i386/x86intrin.h | 12 | ||||
-rw-r--r-- | gcc/config/i386/xsaveintrin.h | 61 | ||||
-rw-r--r-- | gcc/config/i386/xsaveoptintrin.h | 47 |
12 files changed, 555 insertions, 26 deletions
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h index 5cd1eb1c736..1f76d3a5077 100644 --- a/gcc/config/i386/cpuid.h +++ b/gcc/config/i386/cpuid.h @@ -75,6 +75,9 @@ #define bit_RDSEED (1 << 18) #define bit_ADX (1 << 19) +/* Extended State Enumeration Sub-leaf (%eax == 13, %ecx == 1) */ +#define bit_XSAVEOPT (1 << 0) + /* Signatures for different CPU implementations as returned in uses of cpuid with level 0. */ #define signature_AMD_ebx 0x68747541 diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c index 36d80b1e621..940060a97f3 100644 --- a/gcc/config/i386/driver-i386.c +++ b/gcc/config/i386/driver-i386.c @@ -390,7 +390,7 @@ const char *host_detect_local_cpu (int argc, const char **argv) unsigned int has_hle = 0, has_rtm = 0; unsigned int has_rdrnd = 0, has_f16c = 0, has_fsgsbase = 0; unsigned int has_rdseed = 0, has_prfchw = 0, has_adx = 0; - unsigned int has_osxsave = 0; + unsigned int has_osxsave = 0, has_fxsr = 0, has_xsave = 0, has_xsaveopt = 0; bool arch; @@ -441,10 +441,12 @@ const char *host_detect_local_cpu (int argc, const char **argv) has_fma = ecx & bit_FMA; has_f16c = ecx & bit_F16C; has_rdrnd = ecx & bit_RDRND; + has_xsave = ecx & bit_XSAVE; has_cmpxchg8b = edx & bit_CMPXCHG8B; has_cmov = edx & bit_CMOV; has_mmx = edx & bit_MMX; + has_fxsr = edx & bit_FXSAVE; has_sse = edx & bit_SSE; has_sse2 = edx & bit_SSE2; @@ -462,6 +464,13 @@ const char *host_detect_local_cpu (int argc, const char **argv) has_adx = ebx & bit_ADX; } + if (max_level >= 13) + { + __cpuid_count (13, 1, eax, ebx, ecx, edx); + + has_xsaveopt = eax & bit_XSAVEOPT; + } + /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */ #define XCR_XFEATURE_ENABLED_MASK 0x0 #define XSTATE_FP 0x1 @@ -481,6 +490,8 @@ const char *host_detect_local_cpu (int argc, const char **argv) has_fma = 0; has_fma4 = 0; has_xop = 0; + has_xsave = 0; + has_xsaveopt = 0; } /* Check cpuid level of extended features. */ @@ -763,11 +774,15 @@ const char *host_detect_local_cpu (int argc, const char **argv) const char *rdseed = has_rdseed ? " -mrdseed" : " -mno-rdseed"; const char *prfchw = has_prfchw ? " -mprfchw" : " -mno-prfchw"; const char *adx = has_adx ? " -madx" : " -mno-adx"; + const char *fxsr = has_fxsr ? " -mfxsr" : " -mno-fxsr"; + const char *xsave = has_xsave ? " -mxsave" : " -mno-xsave"; + const char *xsaveopt = has_xsaveopt ? " -mxsaveopt" : " -mno-xsaveopt"; options = concat (options, cx16, sahf, movbe, ase, pclmul, popcnt, abm, lwp, fma, fma4, xop, bmi, bmi2, tbm, avx, avx2, sse4_2, sse4_1, lzcnt, rtm, - hle, rdrnd, f16c, fsgsbase, rdseed, prfchw, adx, NULL); + hle, rdrnd, f16c, fsgsbase, rdseed, prfchw, adx, + fxsr, xsave, xsaveopt, NULL); } done: diff --git a/gcc/config/i386/fxsrintrin.h b/gcc/config/i386/fxsrintrin.h new file mode 100644 index 00000000000..9f5e411ac32 --- /dev/null +++ b/gcc/config/i386/fxsrintrin.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2012 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* #if !defined _X86INTRIN_H_INCLUDED && !defined _IMMINTRIN_H_INCLUDED */ +/* # error "Never use <fxsrintrin.h> directly; include <x86intrin.h> instead." */ +/* #endif */ + +#ifndef _FXSRINTRIN_H_INCLUDED +#define _FXSRINTRIN_H_INCLUDED + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxsave (void *__P) +{ + return __builtin_ia32_fxsave (__P); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxrstor (void *__P) +{ + return __builtin_ia32_fxrstor (__P); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxsave64 (void *__P) +{ + return __builtin_ia32_fxsave64 (__P); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_fxrstor64 (void *__P) +{ + return __builtin_ia32_fxrstor64 (__P); +} +#endif + +#endif /* _FXSRINTRIN_H_INCLUDED */ diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 8a199c0a7f8..314f3e888d8 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -356,6 +356,7 @@ DEF_FUNCTION_TYPE (V4DI, V4DI, V2DI) DEF_FUNCTION_TYPE (V4DI, PCV4DI, V4DI) DEF_FUNCTION_TYPE (V4DI, V4DI, INT) DEF_FUNCTION_TYPE (V2DI, V4DI, INT) +DEF_FUNCTION_TYPE (VOID, PVOID, INT64) DEF_FUNCTION_TYPE (VOID, PCHAR, V16QI) DEF_FUNCTION_TYPE (VOID, PCHAR, V32QI) DEF_FUNCTION_TYPE (VOID, PDOUBLE, V2DF) diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index edd64ff7ae3..bd02fbb1bfa 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -302,6 +302,12 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag, def_or_undef (parse_in, "__PRFCHW__"); if (isa_flag & OPTION_MASK_ISA_ADX) def_or_undef (parse_in, "__ADX__"); + if (isa_flag & OPTION_MASK_ISA_FXSR) + def_or_undef (parse_in, "__FXSR__"); + if (isa_flag & OPTION_MASK_ISA_XSAVE) + def_or_undef (parse_in, "__XSAVE__"); + if (isa_flag & OPTION_MASK_ISA_XSAVEOPT) + def_or_undef (parse_in, "__XSAVEOPT__"); if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE)) def_or_undef (parse_in, "__SSE_MATH__"); if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2)) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index c98c6b7a52f..2a9db18b173 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2752,7 +2752,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, preceding options while match those first. */ static struct ix86_target_opts isa_opts[] = { - { "-mfma4", OPTION_MASK_ISA_FMA4 }, + { "-mfma4", OPTION_MASK_ISA_FMA4 }, { "-mfma", OPTION_MASK_ISA_FMA }, { "-mxop", OPTION_MASK_ISA_XOP }, { "-mlwp", OPTION_MASK_ISA_LWP }, @@ -2760,17 +2760,18 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, { "-msse4.2", OPTION_MASK_ISA_SSE4_2 }, { "-msse4.1", OPTION_MASK_ISA_SSE4_1 }, { "-mssse3", OPTION_MASK_ISA_SSSE3 }, - { "-msse3", OPTION_MASK_ISA_SSE3 }, - { "-msse2", OPTION_MASK_ISA_SSE2 }, + { "-msse3", OPTION_MASK_ISA_SSE3 }, + { "-msse2", OPTION_MASK_ISA_SSE2 }, { "-msse", OPTION_MASK_ISA_SSE }, { "-m3dnow", OPTION_MASK_ISA_3DNOW }, { "-m3dnowa", OPTION_MASK_ISA_3DNOW_A }, { "-mmmx", OPTION_MASK_ISA_MMX }, { "-mabm", OPTION_MASK_ISA_ABM }, { "-mbmi", OPTION_MASK_ISA_BMI }, - { "-mbmi2", OPTION_MASK_ISA_BMI2 }, + { "-mbmi2", OPTION_MASK_ISA_BMI2 }, { "-mlzcnt", OPTION_MASK_ISA_LZCNT }, { "-mhle", OPTION_MASK_ISA_HLE }, + { "-mfxsr", OPTION_MASK_ISA_FXSR }, { "-mrdseed", OPTION_MASK_ISA_RDSEED }, { "-mprfchw", OPTION_MASK_ISA_PRFCHW }, { "-madx", OPTION_MASK_ISA_ADX }, @@ -2782,8 +2783,10 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, { "-mpclmul", OPTION_MASK_ISA_PCLMUL }, { "-mfsgsbase", OPTION_MASK_ISA_FSGSBASE }, { "-mrdrnd", OPTION_MASK_ISA_RDRND }, - { "-mf16c", OPTION_MASK_ISA_F16C }, + { "-mf16c", OPTION_MASK_ISA_F16C }, { "-mrtm", OPTION_MASK_ISA_RTM }, + { "-mxsave", OPTION_MASK_ISA_XSAVE }, + { "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT }, }; /* Flag options. */ @@ -3054,6 +3057,10 @@ ix86_option_override_internal (bool main_args_p) #define PTA_PRFCHW (HOST_WIDE_INT_1 << 34) #define PTA_RDSEED (HOST_WIDE_INT_1 << 35) #define PTA_ADX (HOST_WIDE_INT_1 << 36) +#define PTA_FXSR (HOST_WIDE_INT_1 << 37) +#define PTA_XSAVE (HOST_WIDE_INT_1 << 38) +#define PTA_XSAVEOPT (HOST_WIDE_INT_1 << 39) + /* if this reaches 64, need to widen struct pta flags below */ static struct pta @@ -3076,46 +3083,48 @@ ix86_option_override_internal (bool main_args_p) {"c3-2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX | PTA_SSE}, {"i686", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0}, {"pentiumpro", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, 0}, - {"pentium2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX}, + {"pentium2", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, PTA_MMX | PTA_FXSR}, {"pentium3", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, - PTA_MMX | PTA_SSE}, + PTA_MMX | PTA_SSE | PTA_FXSR}, {"pentium3m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, - PTA_MMX | PTA_SSE}, + PTA_MMX | PTA_SSE | PTA_FXSR}, {"pentium-m", PROCESSOR_PENTIUMPRO, CPU_PENTIUMPRO, - PTA_MMX | PTA_SSE | PTA_SSE2}, + PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_FXSR}, {"pentium4", PROCESSOR_PENTIUM4, CPU_NONE, - PTA_MMX |PTA_SSE | PTA_SSE2}, + PTA_MMX |PTA_SSE | PTA_SSE2 | PTA_FXSR}, {"pentium4m", PROCESSOR_PENTIUM4, CPU_NONE, - PTA_MMX | PTA_SSE | PTA_SSE2}, + PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_FXSR}, {"prescott", PROCESSOR_NOCONA, CPU_NONE, - PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3}, + PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_FXSR}, {"nocona", PROCESSOR_NOCONA, CPU_NONE, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_CX16 | PTA_NO_SAHF}, + | PTA_CX16 | PTA_NO_SAHF | PTA_FXSR}, {"core2", PROCESSOR_CORE2_64, CPU_CORE2, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSSE3 | PTA_CX16}, + | PTA_SSSE3 | PTA_CX16 | PTA_FXSR}, {"corei7", PROCESSOR_COREI7_64, CPU_COREI7, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16}, + | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16 | PTA_FXSR}, {"corei7-avx", PROCESSOR_COREI7_64, CPU_COREI7, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AVX - | PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL}, + | PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL + | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT}, {"core-avx-i", PROCESSOR_COREI7_64, CPU_COREI7, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AVX | PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL | PTA_FSGSBASE - | PTA_RDRND | PTA_F16C}, + | PTA_RDRND | PTA_F16C | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT}, {"core-avx2", PROCESSOR_COREI7_64, CPU_COREI7, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AVX | PTA_AVX2 | PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL | PTA_FSGSBASE | PTA_RDRND | PTA_F16C | PTA_BMI | PTA_BMI2 | PTA_LZCNT - | PTA_FMA | PTA_MOVBE | PTA_RTM | PTA_HLE}, + | PTA_FMA | PTA_MOVBE | PTA_RTM | PTA_HLE | PTA_FXSR | PTA_XSAVE + | PTA_XSAVEOPT}, {"atom", PROCESSOR_ATOM, CPU_ATOM, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE}, + | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE | PTA_FXSR}, {"geode", PROCESSOR_GEODE, CPU_GEODE, PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE}, {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX}, @@ -3156,7 +3165,7 @@ ix86_option_override_internal (bool main_args_p) | PTA_SSE2 | PTA_NO_SAHF}, {"amdfam10", PROCESSOR_AMDFAM10, CPU_AMDFAM10, PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE - | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM}, + | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM}, {"barcelona", PROCESSOR_AMDFAM10, CPU_AMDFAM10, PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM}, @@ -3164,21 +3173,24 @@ ix86_option_override_internal (bool main_args_p) PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4 - | PTA_XOP | PTA_LWP | PTA_PRFCHW}, + | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE + | PTA_XSAVEOPT}, {"bdver2", PROCESSOR_BDVER2, CPU_BDVER2, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C - | PTA_FMA | PTA_PRFCHW}, + | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT}, {"btver1", PROCESSOR_BTVER1, CPU_GENERIC64, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 - | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_PRFCHW}, + | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_PRFCHW + | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT}, {"btver2", PROCESSOR_BTVER2, CPU_GENERIC64, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX - | PTA_BMI | PTA_F16C | PTA_MOVBE | PTA_PRFCHW}, + | PTA_BMI | PTA_F16C | PTA_MOVBE | PTA_PRFCHW + | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT}, {"generic32", PROCESSOR_GENERIC32, CPU_PENTIUMPRO, PTA_HLE /* flags are only used for -march switch. */ }, @@ -3549,6 +3561,15 @@ ix86_option_override_internal (bool main_args_p) if (processor_alias_table[i].flags & PTA_ADX && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ADX)) ix86_isa_flags |= OPTION_MASK_ISA_ADX; + if (processor_alias_table[i].flags & PTA_FXSR + && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FXSR)) + ix86_isa_flags |= OPTION_MASK_ISA_FXSR; + if (processor_alias_table[i].flags & PTA_XSAVE + && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVE)) + ix86_isa_flags |= OPTION_MASK_ISA_XSAVE; + if (processor_alias_table[i].flags & PTA_XSAVEOPT + && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVEOPT)) + ix86_isa_flags |= OPTION_MASK_ISA_XSAVEOPT; if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE)) x86_prefetch_sse = true; @@ -4368,6 +4389,9 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[], IX86_ATTR_ISA ("prfchw", OPT_mprfchw), IX86_ATTR_ISA ("rdseed", OPT_mrdseed), IX86_ATTR_ISA ("adx", OPT_madx), + IX86_ATTR_ISA ("fxsr", OPT_mfxsr), + IX86_ATTR_ISA ("xsave", OPT_mxsave), + IX86_ATTR_ISA ("xsaveopt", OPT_mxsaveopt), /* enum options */ IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_), @@ -25570,6 +25594,19 @@ enum ix86_builtins IX86_BUILTIN_STMXCSR, IX86_BUILTIN_SFENCE, + IX86_BUILTIN_FXSAVE, + IX86_BUILTIN_FXRSTOR, + IX86_BUILTIN_FXSAVE64, + IX86_BUILTIN_FXRSTOR64, + + IX86_BUILTIN_XSAVE, + IX86_BUILTIN_XRSTOR, + IX86_BUILTIN_XSAVE64, + IX86_BUILTIN_XRSTOR64, + + IX86_BUILTIN_XSAVEOPT, + IX86_BUILTIN_XSAVEOPT64, + /* 3DNow! Original */ IX86_BUILTIN_FEMMS, IX86_BUILTIN_PAVGUSB, @@ -26776,6 +26813,19 @@ static const struct builtin_description bdesc_special_args[] = /* 3DNow! */ { OPTION_MASK_ISA_3DNOW, CODE_FOR_mmx_femms, "__builtin_ia32_femms", IX86_BUILTIN_FEMMS, UNKNOWN, (int) VOID_FTYPE_VOID }, + /* FXSR, XSAVE and XSAVEOPT */ + { OPTION_MASK_ISA_FXSR, CODE_FOR_nothing, "__builtin_ia32_fxsave", IX86_BUILTIN_FXSAVE, UNKNOWN, (int) VOID_FTYPE_PVOID }, + { OPTION_MASK_ISA_FXSR, CODE_FOR_nothing, "__builtin_ia32_fxrstor", IX86_BUILTIN_FXRSTOR, UNKNOWN, (int) VOID_FTYPE_PVOID }, + { OPTION_MASK_ISA_XSAVE, CODE_FOR_nothing, "__builtin_ia32_xsave", IX86_BUILTIN_XSAVE, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 }, + { OPTION_MASK_ISA_XSAVE, CODE_FOR_nothing, "__builtin_ia32_xrstor", IX86_BUILTIN_XRSTOR, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 }, + { OPTION_MASK_ISA_XSAVEOPT, CODE_FOR_nothing, "__builtin_ia32_xsaveopt", IX86_BUILTIN_XSAVEOPT, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 }, + + { OPTION_MASK_ISA_FXSR | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_fxsave64", IX86_BUILTIN_FXSAVE64, UNKNOWN, (int) VOID_FTYPE_PVOID }, + { OPTION_MASK_ISA_FXSR | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_fxrstor64", IX86_BUILTIN_FXRSTOR64, UNKNOWN, (int) VOID_FTYPE_PVOID }, + { OPTION_MASK_ISA_XSAVE | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xsave64", IX86_BUILTIN_XSAVE64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 }, + { OPTION_MASK_ISA_XSAVE | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xrstor64", IX86_BUILTIN_XRSTOR64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 }, + { OPTION_MASK_ISA_XSAVEOPT | OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_xsaveopt64", IX86_BUILTIN_XSAVEOPT64, UNKNOWN, (int) VOID_FTYPE_PVOID_INT64 }, + /* SSE */ { OPTION_MASK_ISA_SSE, CODE_FOR_sse_storeups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF }, { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movntv4sf, "__builtin_ia32_movntps", IX86_BUILTIN_MOVNTPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF }, @@ -30690,6 +30740,118 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, emit_move_insn (target, op0); return target; + case IX86_BUILTIN_FXSAVE: + case IX86_BUILTIN_FXRSTOR: + case IX86_BUILTIN_FXSAVE64: + case IX86_BUILTIN_FXRSTOR64: + switch (fcode) + { + case IX86_BUILTIN_FXSAVE: + icode = CODE_FOR_fxsave; + break; + case IX86_BUILTIN_FXRSTOR: + icode = CODE_FOR_fxrstor; + break; + case IX86_BUILTIN_FXSAVE64: + icode = CODE_FOR_fxsave64; + break; + case IX86_BUILTIN_FXRSTOR64: + icode = CODE_FOR_fxrstor64; + break; + default: + gcc_unreachable (); + } + + arg0 = CALL_EXPR_ARG (exp, 0); + op0 = expand_normal (arg0); + + if (!address_operand (op0, VOIDmode)) + { + op0 = convert_memory_address (Pmode, op0); + op0 = copy_addr_to_reg (op0); + } + op0 = gen_rtx_MEM (BLKmode, op0); + + pat = GEN_FCN (icode) (op0); + if (pat) + emit_insn (pat); + return 0; + + case IX86_BUILTIN_XSAVE: + case IX86_BUILTIN_XRSTOR: + case IX86_BUILTIN_XSAVE64: + case IX86_BUILTIN_XRSTOR64: + case IX86_BUILTIN_XSAVEOPT: + case IX86_BUILTIN_XSAVEOPT64: + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + op0 = expand_normal (arg0); + op1 = expand_normal (arg1); + + if (!address_operand (op0, VOIDmode)) + { + op0 = convert_memory_address (Pmode, op0); + op0 = copy_addr_to_reg (op0); + } + op0 = gen_rtx_MEM (BLKmode, op0); + + op1 = force_reg (DImode, op1); + + if (TARGET_64BIT) + { + op2 = expand_simple_binop (DImode, LSHIFTRT, op1, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + switch (fcode) + { + case IX86_BUILTIN_XSAVE: + icode = CODE_FOR_xsave_rex64; + break; + case IX86_BUILTIN_XRSTOR: + icode = CODE_FOR_xrstor_rex64; + break; + case IX86_BUILTIN_XSAVE64: + icode = CODE_FOR_xsave64; + break; + case IX86_BUILTIN_XRSTOR64: + icode = CODE_FOR_xrstor64; + break; + case IX86_BUILTIN_XSAVEOPT: + icode = CODE_FOR_xsaveopt_rex64; + break; + case IX86_BUILTIN_XSAVEOPT64: + icode = CODE_FOR_xsaveopt64; + break; + default: + gcc_unreachable (); + } + + op2 = gen_lowpart (SImode, op2); + op1 = gen_lowpart (SImode, op1); + pat = GEN_FCN (icode) (op0, op1, op2); + } + else + { + switch (fcode) + { + case IX86_BUILTIN_XSAVE: + icode = CODE_FOR_xsave; + break; + case IX86_BUILTIN_XRSTOR: + icode = CODE_FOR_xrstor; + break; + case IX86_BUILTIN_XSAVEOPT: + icode = CODE_FOR_xsaveopt; + break; + default: + gcc_unreachable (); + } + pat = GEN_FCN (icode) (op0, op1); + } + + if (pat) + emit_insn (pat); + return 0; + case IX86_BUILTIN_LLWPCB: arg0 = CALL_EXPR_ARG (exp, 0); op0 = expand_normal (arg0); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f923a973b64..712d00a5ed8 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -79,6 +79,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_RDSEED TARGET_ISA_RDSEED #define TARGET_PRFCHW TARGET_ISA_PRFCHW #define TARGET_ADX TARGET_ISA_ADX +#define TARGET_FXSR TARGET_ISA_FXSR +#define TARGET_XSAVE TARGET_ISA_XSAVE +#define TARGET_XSAVEOPT TARGET_ISA_XSAVEOPT #define TARGET_LP64 TARGET_ABI_64 #define TARGET_X32 TARGET_ABI_X32 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 049d53494f9..63d64acf23d 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -202,6 +202,16 @@ UNSPECV_RDGSBASE UNSPECV_WRFSBASE UNSPECV_WRGSBASE + UNSPECV_FXSAVE + UNSPECV_FXRSTOR + UNSPECV_FXSAVE64 + UNSPECV_FXRSTOR64 + UNSPECV_XSAVE + UNSPECV_XRSTOR + UNSPECV_XSAVE64 + UNSPECV_XRSTOR64 + UNSPECV_XSAVEOPT + UNSPECV_XSAVEOPT64 ;; For RDRAND support UNSPECV_RDRAND @@ -18031,6 +18041,142 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; +;; FXSR, XSAVE and XSAVEOPT instructions +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define_insn "fxsave" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec_volatile:BLK [(const_int 0)] UNSPECV_FXSAVE))] + "TARGET_FXSR" + "fxsave\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 3"))]) + +(define_insn "fxsave64" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec_volatile:BLK [(const_int 0)] UNSPECV_FXSAVE64))] + "TARGET_64BIT && TARGET_FXSR" + "fxsave64\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 4"))]) + +(define_insn "fxrstor" + [(unspec_volatile [(match_operand:BLK 0 "memory_operand" "m")] + UNSPECV_FXRSTOR)] + "TARGET_FXSR" + "fxrstor\t%0" + [(set_attr "type" "other") + (set_attr "memory" "load") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 3"))]) + +(define_insn "fxrstor64" + [(unspec_volatile [(match_operand:BLK 0 "memory_operand" "m")] + UNSPECV_FXRSTOR64)] + "TARGET_64BIT && TARGET_FXSR" + "fxrstor64\t%0" + [(set_attr "type" "other") + (set_attr "memory" "load") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 4"))]) + +(define_int_iterator ANY_XSAVE + [UNSPECV_XSAVE + (UNSPECV_XSAVEOPT "TARGET_XSAVEOPT")]) + +(define_int_iterator ANY_XSAVE64 + [UNSPECV_XSAVE64 + (UNSPECV_XSAVEOPT64 "TARGET_XSAVEOPT")]) + +(define_int_attr xsave + [(UNSPECV_XSAVE "xsave") + (UNSPECV_XSAVE64 "xsave64") + (UNSPECV_XSAVEOPT "xsaveopt") + (UNSPECV_XSAVEOPT64 "xsaveopt64")]) + +(define_insn "<xsave>" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec_volatile:BLK + [(match_operand:DI 1 "register_operand" "A")] + ANY_XSAVE))] + "!TARGET_64BIT && TARGET_XSAVE" + "<xsave>\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 3"))]) + +(define_insn "<xsave>_rex64" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec_volatile:BLK + [(match_operand:SI 1 "register_operand" "a") + (match_operand:SI 2 "register_operand" "d")] + ANY_XSAVE))] + "TARGET_64BIT && TARGET_XSAVE" + "<xsave>\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 3"))]) + +(define_insn "<xsave>" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec_volatile:BLK + [(match_operand:SI 1 "register_operand" "a") + (match_operand:SI 2 "register_operand" "d")] + ANY_XSAVE64))] + "TARGET_64BIT && TARGET_XSAVE" + "<xsave>\t%0" + [(set_attr "type" "other") + (set_attr "memory" "store") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 4"))]) + +(define_insn "xrstor" + [(unspec_volatile:BLK + [(match_operand:BLK 0 "memory_operand" "m") + (match_operand:DI 1 "register_operand" "A")] + UNSPECV_XRSTOR)] + "!TARGET_64BIT && TARGET_XSAVE" + "xrstor\t%0" + [(set_attr "type" "other") + (set_attr "memory" "load") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 3"))]) + +(define_insn "xrstor_rex64" + [(unspec_volatile:BLK + [(match_operand:BLK 0 "memory_operand" "m") + (match_operand:SI 1 "register_operand" "a") + (match_operand:SI 2 "register_operand" "d")] + UNSPECV_XRSTOR)] + "TARGET_64BIT && TARGET_XSAVE" + "xrstor\t%0" + [(set_attr "type" "other") + (set_attr "memory" "load") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 3"))]) + +(define_insn "xrstor64" + [(unspec_volatile:BLK + [(match_operand:BLK 0 "memory_operand" "m") + (match_operand:SI 1 "register_operand" "a") + (match_operand:SI 2 "register_operand" "d")] + UNSPECV_XRSTOR64)] + "TARGET_64BIT && TARGET_XSAVE" + "xrstor64\t%0" + [(set_attr "type" "other") + (set_attr "memory" "load") + (set (attr "length") + (symbol_ref "ix86_attr_length_address_default (insn) + 4"))]) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; LWP instructions ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 6a389947d90..dc59c479fe8 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -552,6 +552,18 @@ madx Target Report Mask(ISA_ADX) Var(ix86_isa_flags) Save Support flag-preserving add-carry instructions +mfxsr +Target Report Mask(ISA_FXSR) Var(ix86_isa_flags) Save +Support FXSAVE and FXRSTOR instructions + +mxsave +Target Report Mask(ISA_XSAVE) Var(ix86_isa_flags) Save +Support XSAVE and XRSTOR instructions + +mxsaveopt +Target Report Mask(ISA_XSAVEOPT) Var(ix86_isa_flags) Save +Support XSAVEOPT instruction + mtbm Target Report Mask(ISA_TBM) Var(ix86_isa_flags) Save Support TBM built-in functions and code generation diff --git a/gcc/config/i386/x86intrin.h b/gcc/config/i386/x86intrin.h index fae6491c49f..8b6df7a0fd7 100644 --- a/gcc/config/i386/x86intrin.h +++ b/gcc/config/i386/x86intrin.h @@ -105,6 +105,18 @@ #include <prfchwintrin.h> #endif +#ifdef __FXSR__ +#include <fxsrintrin.h> +#endif + +#ifdef __XSAVE__ +#include <xsaveintrin.h> +#endif + +#ifdef __XSAVEOPT__ +#include <xsaveoptintrin.h> +#endif + #include <adxintrin.h> #endif /* _X86INTRIN_H_INCLUDED */ diff --git a/gcc/config/i386/xsaveintrin.h b/gcc/config/i386/xsaveintrin.h new file mode 100644 index 00000000000..0acae2720b1 --- /dev/null +++ b/gcc/config/i386/xsaveintrin.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2012 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* #if !defined _X86INTRIN_H_INCLUDED && !defined _IMMINTRIN_H_INCLUDED */ +/* # error "Never use <xsaveintrin.h> directly; include <x86intrin.h> instead." */ +/* #endif */ + +#ifndef _XSAVEINTRIN_H_INCLUDED +#define _XSAVEINTRIN_H_INCLUDED + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsave (void *__P, long long __M) +{ + return __builtin_ia32_xsave (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xrstor (void *__P, long long __M) +{ + return __builtin_ia32_xrstor (__P, __M); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsave64 (void *__P, long long __M) +{ + return __builtin_ia32_xsave64 (__P, __M); +} + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xrstor64 (void *__P, long long __M) +{ + return __builtin_ia32_xrstor64 (__P, __M); +} +#endif + +#endif /* _XSAVEINTRIN_H_INCLUDED */ diff --git a/gcc/config/i386/xsaveoptintrin.h b/gcc/config/i386/xsaveoptintrin.h new file mode 100644 index 00000000000..cc962a16966 --- /dev/null +++ b/gcc/config/i386/xsaveoptintrin.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2012 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* #if !defined _X86INTRIN_H_INCLUDED && !defined _IMMINTRIN_H_INCLUDED */ +/* # error "Never use <xsaveoptintrin.h> directly; include <x86intrin.h> instead." */ +/* #endif */ + +#ifndef _XSAVEOPTINTRIN_H_INCLUDED +#define _XSAVEOPTINTRIN_H_INCLUDED + +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsaveopt (void *__P, long long __M) +{ + return __builtin_ia32_xsaveopt (__P, __M); +} + +#ifdef __x86_64__ +extern __inline void +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_xsaveopt64 (void *__P, long long __M) +{ + return __builtin_ia32_xsaveopt64 (__P, __M); +} +#endif + +#endif /* _XSAVEOPTINTRIN_H_INCLUDED */ |