@@ -35,6 +35,8 @@
#define bit_XSAVE (1 << 26)
#define bit_OSXSAVE (1 << 27)
#define bit_AVX (1 << 28)
+#define bit_F16C (1 << 29)
+#define bit_RDRND (1 << 30)
/* %edx */
#define bit_CMPXCHG8B (1 << 8)
@@ -58,6 +60,8 @@
#define bit_3DNOWP (1 << 30)
#define bit_3DNOW (1 << 31)
+/* Extended Features (%eax == 7) */
+#define bit_FSGSBASE (1 << 0)
#if defined(__i386__) && defined(__PIC__)
/* %ebx may be the PIC register. */
@@ -128,6 +128,7 @@ DEF_POINTER_TYPE (PCV8SF, V8SF, CONST)
DEF_FUNCTION_TYPE (FLOAT128)
DEF_FUNCTION_TYPE (UINT64)
DEF_FUNCTION_TYPE (UNSIGNED)
+DEF_FUNCTION_TYPE (UINT16)
DEF_FUNCTION_TYPE (VOID)
DEF_FUNCTION_TYPE (PVOID)
@@ -179,6 +180,7 @@ DEF_FUNCTION_TYPE (V4SF, V4DF)
DEF_FUNCTION_TYPE (V4SF, V4SF)
DEF_FUNCTION_TYPE (V4SF, V4SI)
DEF_FUNCTION_TYPE (V4SF, V8SF)
+DEF_FUNCTION_TYPE (V4SF, V8HI)
DEF_FUNCTION_TYPE (V4SI, V16QI)
DEF_FUNCTION_TYPE (V4SI, V2DF)
DEF_FUNCTION_TYPE (V4SI, V4DF)
@@ -194,10 +196,12 @@ DEF_FUNCTION_TYPE (V8SF, PCV4SF)
DEF_FUNCTION_TYPE (V8SF, V4SF)
DEF_FUNCTION_TYPE (V8SF, V8SF)
DEF_FUNCTION_TYPE (V8SF, V8SI)
+DEF_FUNCTION_TYPE (V8SF, V8HI)
DEF_FUNCTION_TYPE (V8SI, V4SI)
DEF_FUNCTION_TYPE (V8SI, V8SF)
DEF_FUNCTION_TYPE (VOID, PCVOID)
DEF_FUNCTION_TYPE (VOID, PVOID)
+DEF_FUNCTION_TYPE (VOID, UINT64)
DEF_FUNCTION_TYPE (VOID, UNSIGNED)
DEF_FUNCTION_TYPE (DI, V2DI, INT)
@@ -282,6 +286,8 @@ DEF_FUNCTION_TYPE (V8HI, V4SI, V4SI)
DEF_FUNCTION_TYPE (V8HI, V8HI, INT)
DEF_FUNCTION_TYPE (V8HI, V8HI, SI)
DEF_FUNCTION_TYPE (V8HI, V8HI, V8HI)
+DEF_FUNCTION_TYPE (V8HI, V8SF, INT)
+DEF_FUNCTION_TYPE (V8HI, V4SF, INT)
DEF_FUNCTION_TYPE (V8QI, V4HI, V4HI)
DEF_FUNCTION_TYPE (V8QI, V8QI, V8QI)
DEF_FUNCTION_TYPE (V8SF, PCV8SF, V8SF)
@@ -246,6 +246,12 @@ ix86_target_macros_internal (int isa_flag,
def_or_undef (parse_in, "__ABM__");
if (isa_flag & OPTION_MASK_ISA_POPCNT)
def_or_undef (parse_in, "__POPCNT__");
+ if (isa_flag & OPTION_MASK_ISA_FSGSBASE)
+ def_or_undef (parse_in, "__FSGSBASE__");
+ if (isa_flag & OPTION_MASK_ISA_RDRND)
+ def_or_undef (parse_in, "__RDRND__");
+ if (isa_flag & OPTION_MASK_ISA_F16C)
+ def_or_undef (parse_in, "__F16C__");
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))
@@ -2080,6 +2080,11 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_MOVBE_SET OPTION_MASK_ISA_MOVBE
#define OPTION_MASK_ISA_CRC32_SET OPTION_MASK_ISA_CRC32
+#define OPTION_MASK_ISA_FSGSBASE_SET OPTION_MASK_ISA_FSGSBASE
+#define OPTION_MASK_ISA_RDRND_SET OPTION_MASK_ISA_RDRND
+#define OPTION_MASK_ISA_F16C_SET \
+ (OPTION_MASK_ISA_F16C | OPTION_MASK_ISA_AVX_SET)
+
/* Define a set of ISAs which aren't available when a given ISA is
disabled. MMX and SSE ISAs are handled separately. */
@@ -2105,7 +2110,7 @@ static int ix86_isa_flags_explicit;
(OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_AVX_UNSET )
#define OPTION_MASK_ISA_AVX_UNSET \
(OPTION_MASK_ISA_AVX | OPTION_MASK_ISA_FMA_UNSET \
- | OPTION_MASK_ISA_FMA4_UNSET)
+ | OPTION_MASK_ISA_FMA4_UNSET | OPTION_MASK_ISA_F16C_UNSET)
#define OPTION_MASK_ISA_FMA_UNSET OPTION_MASK_ISA_FMA
/* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same
@@ -2129,6 +2134,10 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_MOVBE_UNSET OPTION_MASK_ISA_MOVBE
#define OPTION_MASK_ISA_CRC32_UNSET OPTION_MASK_ISA_CRC32
+#define OPTION_MASK_ISA_FSGSBASE_UNSET OPTION_MASK_ISA_FSGSBASE
+#define OPTION_MASK_ISA_RDRND_UNSET OPTION_MASK_ISA_RDRND
+#define OPTION_MASK_ISA_F16C_UNSET OPTION_MASK_ISA_F16C
+
/* Vectorization library interface and handlers. */
tree (*ix86_veclib_handler)(enum built_in_function, tree, tree) = NULL;
static tree ix86_veclibabi_svml (enum built_in_function, tree, tree);
@@ -2498,6 +2507,45 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
}
return true;
+ case OPT_mfsgsbase:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_FSGSBASE_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_FSGSBASE_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_FSGSBASE_UNSET;
+ }
+ return true;
+
+ case OPT_mrdrnd:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_RDRND_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_RDRND_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_RDRND_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_RDRND_UNSET;
+ }
+ return true;
+
+ case OPT_mf16c:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_F16C_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_F16C_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_F16C_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_F16C_UNSET;
+ }
+ return true;
+
default:
return true;
}
@@ -2541,6 +2589,9 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
{ "-mcrc32", OPTION_MASK_ISA_CRC32 },
{ "-maes", OPTION_MASK_ISA_AES },
{ "-mpclmul", OPTION_MASK_ISA_PCLMUL },
+ { "-mfsgsbase", OPTION_MASK_ISA_FSGSBASE },
+ { "-mrdrnd", OPTION_MASK_ISA_RDRND },
+ { "-mf16c", OPTION_MASK_ISA_F16C },
};
/* Flag options. */
@@ -2778,7 +2829,10 @@ override_options (bool main_args_p)
PTA_MOVBE = 1 << 20,
PTA_FMA4 = 1 << 21,
PTA_XOP = 1 << 22,
- PTA_LWP = 1 << 23
+ PTA_LWP = 1 << 23,
+ PTA_FSGSBASE = 1 << 24,
+ PTA_RDRND = 1 << 25,
+ PTA_F16C = 1 << 26
};
static struct pta
@@ -3154,6 +3208,15 @@ override_options (bool main_args_p)
if (processor_alias_table[i].flags & PTA_PCLMUL
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_PCLMUL))
ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL;
+ if (processor_alias_table[i].flags & PTA_FSGSBASE
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FSGSBASE))
+ ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE;
+ if (processor_alias_table[i].flags & PTA_RDRND
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RDRND))
+ ix86_isa_flags |= OPTION_MASK_ISA_RDRND;
+ if (processor_alias_table[i].flags & PTA_F16C
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_F16C))
+ ix86_isa_flags |= OPTION_MASK_ISA_F16C;
if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE))
x86_prefetch_sse = true;
@@ -21629,6 +21692,27 @@ enum ix86_builtins
IX86_BUILTIN_CLZS,
+ /* FSGSBASE instructions. */
+ IX86_BUILTIN_RDFSBASE32,
+ IX86_BUILTIN_RDFSBASE64,
+ IX86_BUILTIN_RDGSBASE32,
+ IX86_BUILTIN_RDGSBASE64,
+ IX86_BUILTIN_WRFSBASE32,
+ IX86_BUILTIN_WRFSBASE64,
+ IX86_BUILTIN_WRGSBASE32,
+ IX86_BUILTIN_WRGSBASE64,
+
+ /* RDRND instructions. */
+ IX86_BUILTIN_RDRND16,
+ IX86_BUILTIN_RDRND32,
+ IX86_BUILTIN_RDRND64,
+
+ /* F16C instructions. */
+ IX86_BUILTIN_CVTPH2PS,
+ IX86_BUILTIN_CVTPH2PS256,
+ IX86_BUILTIN_CVTPS2PH,
+ IX86_BUILTIN_CVTPS2PH256,
+
IX86_BUILTIN_MAX
};
@@ -21903,6 +21987,20 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_LWP, CODE_FOR_lwp_lwpinssi3, "__builtin_ia32_lwpins32", IX86_BUILTIN_LWPINS32, UNKNOWN, (int) UCHAR_FTYPE_UINT_UINT_UINT },
{ OPTION_MASK_ISA_LWP, CODE_FOR_lwp_lwpinsdi3, "__builtin_ia32_lwpins64", IX86_BUILTIN_LWPINS64, UNKNOWN, (int) UCHAR_FTYPE_UINT64_UINT_UINT },
+ /* FSGSBASE */
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_rdfsbasesi, "__builtin_ia32_rdfsbase32", IX86_BUILTIN_RDFSBASE32, UNKNOWN, (int) UNSIGNED_FTYPE_VOID },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_rdfsbasedi, "__builtin_ia32_rdfsbase64", IX86_BUILTIN_RDFSBASE64, UNKNOWN, (int) UINT64_FTYPE_VOID },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_rdgsbasesi, "__builtin_ia32_rdgsbase32", IX86_BUILTIN_RDGSBASE32, UNKNOWN, (int) UNSIGNED_FTYPE_VOID },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_rdgsbasedi, "__builtin_ia32_rdgsbase64", IX86_BUILTIN_RDGSBASE64, UNKNOWN, (int) UINT64_FTYPE_VOID },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrfsbasesi, "__builtin_ia32_wrfsbase32", IX86_BUILTIN_WRFSBASE32, UNKNOWN, (int) VOID_FTYPE_UNSIGNED },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrfsbasedi, "__builtin_ia32_wrfsbase64", IX86_BUILTIN_WRFSBASE64, UNKNOWN, (int) VOID_FTYPE_UINT64 },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrgsbasesi, "__builtin_ia32_wrgsbase32", IX86_BUILTIN_WRGSBASE32, UNKNOWN, (int) VOID_FTYPE_UNSIGNED },
+ { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrgsbasedi, "__builtin_ia32_wrgsbase64", IX86_BUILTIN_WRGSBASE64, UNKNOWN, (int) VOID_FTYPE_UINT64 },
+
+ /* RDRND */
+ { OPTION_MASK_ISA_RDRND, CODE_FOR_rdrndhi, "__builtin_ia32_rdrnd16", IX86_BUILTIN_RDRND16, UNKNOWN, (int) UINT16_FTYPE_VOID },
+ { OPTION_MASK_ISA_RDRND, CODE_FOR_rdrndsi, "__builtin_ia32_rdrnd32", IX86_BUILTIN_RDRND32, UNKNOWN, (int) UNSIGNED_FTYPE_VOID },
+ { OPTION_MASK_ISA_RDRND | OPTION_MASK_ISA_64BIT, CODE_FOR_rdrnddi, "__builtin_ia32_rdrnd64", IX86_BUILTIN_RDRND64, UNKNOWN, (int) UINT64_FTYPE_VOID },
};
/* Builtins with variable number of arguments. */
@@ -22529,6 +22627,12 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_movmskps256, "__builtin_ia32_movmskps256", IX86_BUILTIN_MOVMSKPS256, UNKNOWN, (int) INT_FTYPE_V8SF },
{ OPTION_MASK_ISA_ABM, CODE_FOR_clzhi2_abm, "__builtin_clzs", IX86_BUILTIN_CLZS, UNKNOWN, (int) UINT16_FTYPE_UINT16 },
+
+ /* F16C */
+ { OPTION_MASK_ISA_F16C, CODE_FOR_vcvtph2ps, "__builtin_ia32_vcvtph2ps", IX86_BUILTIN_CVTPH2PS, UNKNOWN, (int) V4SF_FTYPE_V8HI },
+ { OPTION_MASK_ISA_F16C, CODE_FOR_vcvtph2ps256, "__builtin_ia32_vcvtph2ps256", IX86_BUILTIN_CVTPH2PS256, UNKNOWN, (int) V8SF_FTYPE_V8HI },
+ { OPTION_MASK_ISA_F16C, CODE_FOR_vcvtps2ph, "__builtin_ia32_vcvtps2ph", IX86_BUILTIN_CVTPS2PH, UNKNOWN, (int) V8HI_FTYPE_V4SF_INT },
+ { OPTION_MASK_ISA_F16C, CODE_FOR_vcvtps2ph256, "__builtin_ia32_vcvtps2ph256", IX86_BUILTIN_CVTPS2PH256, UNKNOWN, (int) V8HI_FTYPE_V8SF_INT },
};
/* FMA4 and XOP. */
@@ -23769,6 +23873,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V8SF_FTYPE_V8SF:
case V8SF_FTYPE_V8SI:
case V8SF_FTYPE_V4SF:
+ case V8SF_FTYPE_V8HI:
case V4SI_FTYPE_V4SI:
case V4SI_FTYPE_V16QI:
case V4SI_FTYPE_V4SF:
@@ -23785,6 +23890,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V4SF_FTYPE_V4SI:
case V4SF_FTYPE_V8SF:
case V4SF_FTYPE_V4DF:
+ case V4SF_FTYPE_V8HI:
case V4SF_FTYPE_V2DF:
case V2DI_FTYPE_V2DI:
case V2DI_FTYPE_V16QI:
@@ -23887,6 +23993,8 @@ ix86_expand_args_builtin (const struct builtin_description *d,
nargs_constant = 1;
break;
case V8HI_FTYPE_V8HI_INT:
+ case V8HI_FTYPE_V8SF_INT:
+ case V8HI_FTYPE_V4SF_INT:
case V8SF_FTYPE_V8SF_INT:
case V4SI_FTYPE_V4SI_INT:
case V4SI_FTYPE_V8SI_INT:
@@ -24134,7 +24242,16 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
case VOID_FTYPE_VOID:
emit_insn (GEN_FCN (icode) (target));
return 0;
+ case VOID_FTYPE_UINT64:
+ case VOID_FTYPE_UNSIGNED:
+ nargs = 0;
+ klass = store;
+ memory = 0;
+ break;
+ break;
case UINT64_FTYPE_VOID:
+ case UNSIGNED_FTYPE_VOID:
+ case UINT16_FTYPE_VOID:
nargs = 0;
klass = load;
memory = 0;
@@ -24213,7 +24330,10 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
arg = CALL_EXPR_ARG (exp, 0);
op = expand_normal (arg);
gcc_assert (target == 0);
- target = gen_rtx_MEM (tmode, copy_to_mode_reg (Pmode, op));
+ if (memory)
+ target = gen_rtx_MEM (tmode, copy_to_mode_reg (Pmode, op));
+ else
+ target = force_reg (tmode, op);
arg_adjust = 1;
}
else
@@ -66,6 +66,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_AES OPTION_ISA_AES
#define TARGET_PCLMUL OPTION_ISA_PCLMUL
#define TARGET_CMPXCHG16B OPTION_ISA_CX16
+#define TARGET_FSGSBASE OPTION_ISA_FSGSBASE
+#define TARGET_RDRND OPTION_ISA_RDRND
+#define TARGET_F16C OPTION_ISA_F16C
/* SSE4.1 defines round instructions */
@@ -226,6 +226,8 @@
UNSPEC_MASKSTORE
UNSPEC_CAST
UNSPEC_VTESTP
+ UNSPEC_VCVTPH2PS
+ UNSPEC_VCVTPS2PH
])
(define_c_enum "unspecv" [
@@ -254,6 +256,11 @@
UNSPECV_SLWP_INTRINSIC
UNSPECV_LWPVAL_INTRINSIC
UNSPECV_LWPINS_INTRINSIC
+ UNSPECV_RDFSBASE
+ UNSPECV_RDGSBASE
+ UNSPECV_WRFSBASE
+ UNSPECV_WRGSBASE
+ UNSPECV_RDRND
])
;; Constants to represent pcomtrue/pcomfalse variants
@@ -18446,6 +18453,46 @@
(set (attr "length")
(symbol_ref "ix86_attr_length_address_default (insn) + 9"))])
+(define_insn "rdfsbase<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec_volatile:SWI48 [(const_int 0)] UNSPECV_RDFSBASE))]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "rdfsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "rdgsbase<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (unspec_volatile:SWI48 [(const_int 0)] UNSPECV_RDGSBASE))]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "rdgsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "wrfsbase<mode>"
+ [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
+ UNSPECV_WRFSBASE)]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "wrfsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "wrgsbase<mode>"
+ [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
+ UNSPECV_WRGSBASE)]
+ "TARGET_64BIT && TARGET_FSGSBASE"
+ "wrgsbase %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "2")])
+
+(define_insn "rdrnd<mode>"
+ [(set (match_operand:SWI248 0 "register_operand" "=r")
+ (unspec_volatile:SWI248 [(const_int 0)] UNSPECV_RDRND))]
+ "TARGET_RDRND"
+ "rdrnd %0"
+ [(set_attr "type" "other")
+ (set_attr "prefix_extra" "1")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
@@ -363,3 +363,15 @@ Support PCLMUL built-in functions and code generation
msse2avx
Target Report Var(ix86_sse2avx)
Encode SSE instructions with VEX prefix
+
+mfsgsbase
+Target Report Mask(ISA_FSGSBASE) Var(ix86_isa_flags) VarExists Save
+Support FSGSBASE built-in functions and code generation
+
+mrdrnd
+Target Report Mask(ISA_RDRND) Var(ix86_isa_flags) VarExists Save
+Support RDRND built-in functions and code generation
+
+mf16c
+Target Report Mask(ISA_F16C) Var(ix86_isa_flags) VarExists Save
+Support F16C built-in functions and code generation
@@ -56,4 +56,159 @@
#include <avxintrin.h>
#endif
+#ifdef __RDRND__
+/* 16bit rdrnd */
+extern __inline unsigned short
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdrnd_u16 (void)
+{
+ return __builtin_ia32_rdrnd16 ();
+}
+
+/* 32bit rdrnd */
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdrnd_u32 (void)
+{
+ return __builtin_ia32_rdrnd32 ();
+}
+#endif /* __RDRND__ */
+
+#ifdef __x86_64__
+#ifdef __FSGSBASE__
+/* 32bit rdfsbase */
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_readfsbase_u32 (void)
+{
+ return __builtin_ia32_rdfsbase32 ();
+}
+
+/* 64bit rdfsbase */
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_readfsbase_u64 (void)
+{
+ return __builtin_ia32_rdfsbase64 ();
+}
+
+/* 32bit rdgsbase */
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_readgsbase_u32 (void)
+{
+ return __builtin_ia32_rdgsbase32 ();
+}
+
+/* 64bit rdgsbase */
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_readgsbase_u64 (void)
+{
+ return __builtin_ia32_rdgsbase64 ();
+}
+
+/* 32bit wrfsbase */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_writefsbase_u32 (unsigned int __B)
+{
+ __builtin_ia32_wrfsbase32 (__B);
+}
+
+/* 64bit wrfsbase */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_writefsbase_u64 (unsigned long long __B)
+{
+ __builtin_ia32_wrfsbase64 (__B);
+}
+
+/* 32bit wrgsbase */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_writegsbase_u32 (unsigned int __B)
+{
+ __builtin_ia32_wrgsbase32 (__B);
+}
+
+/* 64bit wrgsbase */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_writegsbase_u64 (unsigned long long __B)
+{
+ __builtin_ia32_wrgsbase64 (__B);
+}
+#endif /* __FSGSBASE__ */
+
+#ifdef __RDRND__
+/* 64bit rdrnd */
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdrnd_u64 (void)
+{
+ return __builtin_ia32_rdrnd64 ();
+}
+#endif /* __RDRND__ */
+#endif /* __x86_64__ */
+
+#ifdef __F16C__
+extern __inline float __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_cvtsh_ss (unsigned short __S)
+{
+ __v8hi __H = __extension__ (__v8hi){ __S, 0, 0, 0, 0, 0, 0, 0 };
+ __v4sf __A = __builtin_ia32_vcvtph2ps (__H);
+ return __builtin_ia32_vec_ext_v4sf (__A, 0);
+}
+
+extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtph_ps (__m128i __A)
+{
+ return (__m128) __builtin_ia32_vcvtph2ps ((__v8hi) __A);
+}
+
+extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtph_ps (__m128i __A)
+{
+ return (__m256) __builtin_ia32_vcvtph2ps256 ((__v8hi) __A);
+}
+
+#ifdef __OPTIMIZE__
+extern __inline unsigned short __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_cvtss_sh (float __F, const int __I)
+{
+ __v4sf __A = __extension__ (__v4sf){ __F, 0, 0, 0 };
+ __v8hi __H = __builtin_ia32_vcvtps2ph (__A, __I);
+ return (unsigned short) __builtin_ia32_vec_ext_v8hi (__H, 0);
+}
+
+extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_cvtps_ph (__m128 __A, const int __I)
+{
+ return (__m128i) __builtin_ia32_vcvtps2ph ((__v4sf) __A, __I);
+}
+
+extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_cvtps_ph (__m256 __A, const int __I)
+{
+ return (__m128i) __builtin_ia32_vcvtps2ph256 ((__v8sf) __A, __I);
+}
+#else
+#define _cvtss_sh(__F, __I) \
+ (__extension__ \
+ ({ \
+ __v4sf __A = __extension__ (__v4sf){ __F, 0, 0, 0 }; \
+ __v8hi __H = __builtin_ia32_vcvtps2ph (__A, __I); \
+ (unsigned short) __builtin_ia32_vec_ext_v8hi (__H, 0); \
+ }))
+
+#define _mm_cvtps_ph(A, I) \
+ ((__m128i) __builtin_ia32_vcvtps2ph ((__v4sf)(__m128) A, (int) (I)))
+
+#define _mm256_cvtps_ph(A, I) \
+ ((__m128i) __builtin_ia32_vcvtps2ph256 ((__v8sf)(__m256) A, (int) (I)))
+#endif
+
+#endif /* __F16C__ */
+
#endif /* _IMMINTRIN_H_INCLUDED */
@@ -12322,3 +12322,81 @@
(set_attr "length_immediate" "1,*")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxvecmode>")])
+
+(define_insn "vcvtph2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_select:V4SF
+ (unspec:V8SF [(match_operand:V8HI 1 "register_operand" "x")]
+ UNSPEC_VCVTPH2PS)
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 1) (const_int 2)])))]
+ "TARGET_F16C"
+ "vcvtph2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*vcvtph2ps_load"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (unspec:V4SF [(match_operand:V4HI 1 "memory_operand" "m")]
+ UNSPEC_VCVTPH2PS))]
+ "TARGET_F16C"
+ "vcvtph2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+(define_insn "vcvtph2ps256"
+ [(set (match_operand:V8SF 0 "register_operand" "=x")
+ (unspec:V8SF [(match_operand:V8HI 1 "nonimmediate_operand" "xm")]
+ UNSPEC_VCVTPH2PS))]
+ "TARGET_F16C"
+ "vcvtph2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+(define_expand "vcvtps2ph"
+ [(set (match_operand:V8HI 0 "register_operand" "")
+ (vec_concat:V8HI
+ (unspec:V4HI [(match_operand:V4SF 1 "register_operand" "")
+ (match_operand:SI 2 "immediate_operand" "")]
+ UNSPEC_VCVTPS2PH)
+ (match_dup 3)))]
+ "TARGET_F16C"
+ "operands[3] = CONST0_RTX (V4HImode);")
+
+(define_insn "*vcvtps2ph"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_concat:V8HI
+ (unspec:V4HI [(match_operand:V4SF 1 "register_operand" "x")
+ (match_operand:SI 2 "immediate_operand" "N")]
+ UNSPEC_VCVTPS2PH)
+ (match_operand:V4HI 3 "const0_operand" "")))]
+ "TARGET_F16C"
+ "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*vcvtps2ph_store"
+ [(set (match_operand:V4HI 0 "memory_operand" "=m")
+ (unspec:V4HI [(match_operand:V4SF 1 "register_operand" "x")
+ (match_operand:SI 2 "immediate_operand" "N")]
+ UNSPEC_VCVTPS2PH))]
+ "TARGET_F16C"
+ "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "vcvtps2ph256"
+ [(set (match_operand:V8HI 0 "nonimmediate_operand" "=xm")
+ (unspec:V8HI [(match_operand:V8SF 1 "register_operand" "x")
+ (match_operand:SI 2 "immediate_operand" "N")]
+ UNSPEC_VCVTPS2PH))]
+ "TARGET_F16C"
+ "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
@@ -8958,6 +8958,31 @@ used.
Generates the @code{pclmulqdq} machine instruction.
@end table
+The following built-in function is available when @option{-mfsgsbase} is
+used. All of them generate the machine instruction that is part of the
+name.
+
+@smallexample
+unsigned int __builtin_ia32_rdfsbase32 (void)
+unsigned long long __builtin_ia32_rdfsbase64 (void)
+unsigned int __builtin_ia32_rdgsbase32 (void)
+unsigned long long __builtin_ia32_rdgsbase64 (void)
+void _writefsbase_u32 (unsigned int)
+void _writefsbase_u64 (unsigned long long)
+void _writegsbase_u32 (unsigned int)
+void _writegsbase_u64 (unsigned long long)
+@end smallexample
+
+The following built-in function is available when @option{-mrdrnd} is
+used. All of them generate the machine instruction that is part of the
+name.
+
+@smallexample
+unsigned short __builtin_ia32_rdrnd16 (void)
+unsigned int __builtin_ia32_rdrnd32 (void)
+unsigned long long __builtin_ia32_rdrnd64 (void)
+@end smallexample
+
The following built-in functions are available when @option{-msse4a} is used.
All of them generate the machine instruction that is part of the name.
@@ -591,7 +591,7 @@ Objective-C and Objective-C++ Dialects}.
-mincoming-stack-boundary=@var{num}
-mcld -mcx16 -msahf -mmovbe -mcrc32 -mrecip @gol
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
--maes -mpclmul -mfused-madd @gol
+-maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfused-madd @gol
-msse4a -m3dnow -mpopcnt -mabm -mfma4 -mxop -mlwp @gol
-mthreads -mno-align-stringops -minline-all-stringops @gol
-minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
@@ -12216,6 +12216,12 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mno-aes
@itemx -mpclmul
@itemx -mno-pclmul
+@itemx -mfsgsbase
+@itemx -mno-fsgsbase
+@itemx -mrdrnd
+@itemx -mno-rdrnd
+@itemx -mf16c
+@itemx -mno-f16c
@itemx -msse4a
@itemx -mno-sse4a
@itemx -mfma4
@@ -12237,8 +12243,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@opindex m3dnow
@opindex mno-3dnow
These switches enable or disable the use of instructions in the MMX,
-SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AES, PCLMUL, SSE4A, FMA4, XOP,
-LWP, ABM or 3DNow!@: extended instruction sets.
+SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AES, PCLMUL, FSGSBASE, RDRND,
+F16C, SSE4A, FMA4, XOP, LWP, ABM or 3DNow!@: extended instruction sets.
These extensions are also available as built-in functions: see
@ref{X86 Built-in Functions}, for details of the functions enabled and
disabled by these switches.
new file mode 100644
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "cpuid.h"
+#include "m256-check.h"
+
+static void f16c_test (void);
+
+int
+main ()
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return 0;
+
+ /* Run F16C test only if host has F16C support. */
+ if (ecx & bit_F16C)
+ {
+ f16c_test ();
+#ifdef DEBUG
+ printf ("PASSED\n");
+#endif
+ }
+#ifdef DEBUG
+ else
+ printf ("SKIPPED\n");
+#endif
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "rdfsbase\[ \t]+(%|)eax" } } */
+
+#include <immintrin.h>
+
+unsigned int
+read_fs_base32 (void)
+{
+ return _readfsbase_u32 ();
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "rdfsbase\[ \t]+(%|)rax" } } */
+
+#include <immintrin.h>
+
+unsigned long long
+read_fs_base64 (void)
+{
+ return _readfsbase_u64 ();
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "rdgsbase\[ \t]+(%|)eax" } } */
+
+#include <immintrin.h>
+
+unsigned int
+read_gs_base32 (void)
+{
+ return _readgsbase_u32 ();
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "rdgsbase\[ \t]+(%|)rax" } } */
+
+#include <immintrin.h>
+
+unsigned long long
+read_gs_base64 (void)
+{
+ return _readgsbase_u64 ();
+}
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mrdrnd " } */
+/* { dg-final { scan-assembler "rdrnd\[ \t]+(%|)ax" } } */
+
+#include <immintrin.h>
+
+unsigned short
+read_rdrnd16 (void)
+{
+ return _rdrnd_u16 ();
+}
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mrdrnd " } */
+/* { dg-final { scan-assembler "rdrnd\[ \t]+(%|)eax" } } */
+
+#include <immintrin.h>
+
+unsigned int
+read_rdrnd32 (void)
+{
+ return _rdrnd_u32 ();
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mrdrnd " } */
+/* { dg-final { scan-assembler "rdrnd\[ \t]+(%|)rax" } } */
+
+#include <immintrin.h>
+
+unsigned long long
+read_rdrnd64 (void)
+{
+ return _rdrnd_u64 ();
+}
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-require-effective-target f16c } */
+/* { dg-options "-O2 -mf16c" } */
+
+#include "f16c-check.h"
+
+static void
+f16c_test (void)
+{
+ union128i_w val;
+ union128 res;
+ float exp[4];
+
+ exp[0] = 1;
+ exp[1] = -2;
+ exp[2] = -1;
+ exp[3] = 2;
+
+ val.a[0] = 0x3c00;
+ val.a[1] = 0xc000;
+ val.a[2] = 0xbc00;
+ val.a[3] = 0x4000;
+
+ res.x = _mm_cvtph_ps (val.x);
+
+ if (check_union128 (res, exp))
+ abort ();
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-require-effective-target f16c } */
+/* { dg-options "-O2 -mf16c" } */
+
+#include "f16c-check.h"
+
+static void
+f16c_test (void)
+{
+ union256 res;
+ union128i_w val;
+ float exp[8];
+
+ exp[0] = 1;
+ exp[1] = 2;
+ exp[2] = 4;
+ exp[3] = 8;
+ exp[4] = -1;
+ exp[5] = -2;
+ exp[6] = -4;
+ exp[7] = -8;
+
+ val.a[0] = 0x3c00;
+ val.a[1] = 0x4000;
+ val.a[2] = 0x4400;
+ val.a[3] = 0x4800;
+ val.a[4] = 0xbc00;
+ val.a[5] = 0xc000;
+ val.a[6] = 0xc400;
+ val.a[7] = 0xc800;
+
+ res.x = _mm256_cvtph_ps (val.x);
+
+ if (check_union256 (res, exp))
+ abort ();
+}
new file mode 100644
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-require-effective-target f16c } */
+/* { dg-options "-O2 -mf16c" } */
+
+#include "f16c-check.h"
+
+static void
+f16c_test (void)
+{
+ unsigned short val = 0xc000;
+ float exp = -2;
+ float res;
+
+ res = _cvtsh_ss (val);
+
+ if (res != exp)
+ abort ();
+}
new file mode 100644
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-require-effective-target f16c } */
+/* { dg-options "-O2 -mf16c" } */
+
+#include "f16c-check.h"
+
+static void
+f16c_test (void)
+{
+ union128 val;
+ union128i_w res;
+ short exp[8];
+
+ val.a[0] = 1;
+ val.a[1] = -2;
+ val.a[2] = -1;
+ val.a[3] = 2;
+
+ exp[0] = 0x3c00;
+ exp[1] = 0xc000;
+ exp[2] = 0xbc00;
+ exp[3] = 0x4000;
+ exp[4] = 0;
+ exp[5] = 0;
+ exp[6] = 0;
+ exp[7] = 0;
+
+ res.x = _mm_cvtps_ph (val.x, 0);
+
+ if (check_union128i_w (res, exp))
+ abort ();
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-require-effective-target f16c } */
+/* { dg-options "-O2 -mf16c" } */
+
+#include "f16c-check.h"
+
+static void
+f16c_test (void)
+{
+ union256 val;
+ union128i_w res;
+ short exp[8];
+
+ val.a[0] = 1;
+ val.a[1] = 2;
+ val.a[2] = 4;
+ val.a[3] = 8;
+ val.a[4] = -1;
+ val.a[5] = -2;
+ val.a[6] = -4;
+ val.a[7] = -8;
+
+ exp[0] = 0x3c00;
+ exp[1] = 0x4000;
+ exp[2] = 0x4400;
+ exp[3] = 0x4800;
+ exp[4] = 0xbc00;
+ exp[5] = 0xc000;
+ exp[6] = 0xc400;
+ exp[7] = 0xc800;
+
+ res.x = _mm256_cvtps_ph (val.x, 0);
+
+ if (check_union128i_w (res, exp))
+ abort ();
+}
new file mode 100644
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-require-effective-target f16c } */
+/* { dg-options "-O2 -mf16c" } */
+
+#include "f16c-check.h"
+
+static void
+f16c_test (void)
+{
+ float val = -2;
+ unsigned short exp = 0xc000;
+ unsigned short res;
+
+ res = _cvtss_sh (val, 0);
+
+ if (res != exp)
+ abort ();
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "wrfsbase\[ \t]+(%|)edi" } } */
+
+#include <immintrin.h>
+
+void
+write_fs_base32 (unsigned int base)
+{
+ _writefsbase_u32 (base);
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "wrfsbase\[ \t]+(%|)rdi" } } */
+
+#include <immintrin.h>
+
+void
+write_fs_base64 (unsigned long long base)
+{
+ _writefsbase_u64 (base);
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "wrgsbase\[ \t]+(%|)edi" } } */
+
+#include <immintrin.h>
+
+void
+write_gs_base32 (unsigned int base)
+{
+ _writegsbase_u32 (base);
+}
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -mfsgsbase" } */
+/* { dg-final { scan-assembler "wrgsbase\[ \t]+(%|)rdi" } } */
+
+#include <immintrin.h>
+
+void
+write_gs_base64 (unsigned long long base)
+{
+ _writegsbase_u64 (base);
+}
@@ -3273,6 +3273,19 @@ proc check_effective_target_sse2 { } {
} "-O2 -msse2" ]
}
+# Return 1 if F16C instructions can be compiled.
+
+proc check_effective_target_f16c { } {
+ return [check_no_compiler_messages f16c object {
+ #include "immintrin.h"
+ float
+ foo (unsigned short val)
+ {
+ return _cvtsh_ss (val);
+ }
+ } "-O2 -mf16c" ]
+}
+
# Return 1 if C wchar_t type is compatible with char16_t.
proc check_effective_target_wchar_t_char16_t_compatible { } {