summaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/cpuid.h3
-rw-r--r--gcc/config/i386/driver-i386.c19
-rw-r--r--gcc/config/i386/fxsrintrin.h61
-rw-r--r--gcc/config/i386/i386-builtin-types.def1
-rw-r--r--gcc/config/i386/i386-c.c6
-rw-r--r--gcc/config/i386/i386.c210
-rw-r--r--gcc/config/i386/i386.h3
-rw-r--r--gcc/config/i386/i386.md146
-rw-r--r--gcc/config/i386/i386.opt12
-rw-r--r--gcc/config/i386/x86intrin.h12
-rw-r--r--gcc/config/i386/xsaveintrin.h61
-rw-r--r--gcc/config/i386/xsaveoptintrin.h47
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 */