Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > b5e52bbfb4bb11a6cbed452927fba979 > files > 116

gcc-4.1.2-50.el5.src.rpm

2007-11-12  Dwarakanath Rajagopal  <dwarak.rajagopal@amd.com>
            Michael Meissner  <michael.meissner@amd.com>

	* config/i386/i386.md (sse5_setcc<mode>): Use <ssemodefsuffix> to
	get the appropriate suffix for the coms* instruction.

	* config/i386/sse.md (sse5_pcmov_<mode>): Correct the operand
	constraints to follow the mnemonics for the pcmov instruction

2007-10-27  Uros Bizjak  <ubizjak@gmail.com>

	* g++.dg/other/i386-2a.C: New test.
	* gcc.target/i386/sse-13.c: Also include mm3dnow.h.  Add
	"-march=k8 -m3dnow" to check 3dnow and 3dnowA intrinsics.
	* gcc.target/i386/sse-14.c: Ditto.

2007-09-22  Uros Bizjak  <ubizjak@gmail.com>

	* gcc.target/i386/sse5-hadduX.c: Remove target selector.
	* gcc.target/i386/sse5-haddX.c: Ditto.
	* gcc.target/i386/sse5-hsubX.c: Ditto.
	* gcc.target/i386/sse5-maccXX.c: Ditto.
	* gcc.target/i386/sse5-msubXX.c: Ditto.
	* gcc.target/i386/sse5-nmaccXX.c: Ditto.
	* gcc.target/i386/sse5-nmsubXX.c: Ditto.
	* gcc.target/i386/sse5-permpX.c: Ditto.
	* gcc.target/i386/sse5-fma.c: Remove target selector. Require lp64
	effective target.
	* gcc.target/i386/sse5-fma-vector.c: Ditto.
	* gcc.target/i386/sse5-ima-vector.c: Ditto.
	* gcc.target/i386/sse5-pcmov.c: Ditto.
	* gcc.target/i386/sse5-pcmov2.c: Ditto.

2007-09-12  Michael Meissner  <michael.meissner@amd.com>
	    Dwarakanath Rajagopal  <dwarak.rajagopal@amd.com>
	    Tony Linthicum  <tony.linthicum@amd.com>

	* config/i386/i386.h (TARGET_ROUND): New macro for the round/ptest
	instructions which are shared between SSE4.1 and SSE5.
	(TARGET_FUSED_MADD): New macro for -mfused-madd swtich.
	(TARGET_CPU_CPP_BUILTINS): Add SSE5 support.

	* config/i386/i386.opt (-msse5): New switch for SSE5 support.
	(-mfused-madd): New switch to give users control over whether the
	compiler optimizes to use the multiply/add SSE5 instructions.

	* config/i386/i386.c (ix86_handle_option): Turn off -msse5 if
	-mno-sse, -mno-sse2, -mno-sse3 or -mno-sse4a.
	(override_options): Add SSE5 support.
	(print_operand): %Y prints comparison codes for SSE5 com/pcom
	instructions.
	(ix86_expand_sse_movcc): Add SSE5 support.
	(IX86_BUILTIN_ROUNDPD): New for SSE4.1/SSE5 intrinsic.
	(IX86_BUILTIN_ROUNDPS): Likewise.
	(IX86_BUILTIN_ROUNDSD): Likewise.
	(IX86_BUILTIN_ROUNDSS): Likewise.
	(IX86_BUILTIN_PTESTZ): Likewise.
	(IX86_BUILTIN_PTESTC): Likewise.
	(IX86_BUILTIN_PTESTNZC): Likewise.
	(IX86_BUILTIN_FMADDSS): New for SSE5 intrinsic.
	(IX86_BUILTIN_FMADDSD): Ditto.
	(IX86_BUILTIN_FMADDPS): Ditto.
	(IX86_BUILTIN_FMADDPD): Ditto.
	(IX86_BUILTIN_FMSUBSS): Ditto.
	(IX86_BUILTIN_FMSUBSD): Ditto.
	(IX86_BUILTIN_FMSUBPS): Ditto.
	(IX86_BUILTIN_FMSUBPD): Ditto.
	(IX86_BUILTIN_FNMADDSS): Ditto.
	(IX86_BUILTIN_FNMADDSD): Ditto.
	(IX86_BUILTIN_FNMADDPS): Ditto.
	(IX86_BUILTIN_FNMADDPD): Ditto.
	(IX86_BUILTIN_FNMSUBSS): Ditto.
	(IX86_BUILTIN_FNMSUBSD): Ditto.
	(IX86_BUILTIN_FNMSUBPS): Ditto.
	(IX86_BUILTIN_FNMSUBPD): Ditto.
	(IX86_BUILTIN_PCMOV_V2DI): Ditto.
	(IX86_BUILTIN_PCMOV_V4SI): Ditto.
	(IX86_BUILTIN_PCMOV_V8HI): Ditto.
	(IX86_BUILTIN_PCMOV_V16QI): Ditto.
	(IX86_BUILTIN_PCMOV_V4SF): Ditto.
	(IX86_BUILTIN_PCMOV_V2DF): Ditto.
	(IX86_BUILTIN_PPERM): Ditto.
	(IX86_BUILTIN_PERMPS): Ditto.
	(IX86_BUILTIN_PERMPD): Ditto.
	(IX86_BUILTIN_PMACSSWW): Ditto.
	(IX86_BUILTIN_PMACSWW): Ditto.
	(IX86_BUILTIN_PMACSSWD): Ditto.
	(IX86_BUILTIN_PMACSWD): Ditto.
	(IX86_BUILTIN_PMACSSDD): Ditto.
	(IX86_BUILTIN_PMACSDD): Ditto.
	(IX86_BUILTIN_PMACSSDQL): Ditto.
	(IX86_BUILTIN_PMACSSDQH): Ditto.
	(IX86_BUILTIN_PMACSDQL): Ditto.
	(IX86_BUILTIN_PMACSDQH): Ditto.
	(IX86_BUILTIN_PMADCSSWD): Ditto.
	(IX86_BUILTIN_PMADCSWD): Ditto.
	(IX86_BUILTIN_PHADDBW): Ditto.
	(IX86_BUILTIN_PHADDBD): Ditto.
	(IX86_BUILTIN_PHADDBQ): Ditto.
	(IX86_BUILTIN_PHADDWD): Ditto.
	(IX86_BUILTIN_PHADDWQ): Ditto.
	(IX86_BUILTIN_PHADDDQ): Ditto.
	(IX86_BUILTIN_PHADDUBW): Ditto.
	(IX86_BUILTIN_PHADDUBD): Ditto.
	(IX86_BUILTIN_PHADDUBQ): Ditto.
	(IX86_BUILTIN_PHADDUWD): Ditto.
	(IX86_BUILTIN_PHADDUWQ): Ditto.
	(IX86_BUILTIN_PHADDUDQ): Ditto.
	(IX86_BUILTIN_PHSUBBW): Ditto.
	(IX86_BUILTIN_PHSUBWD): Ditto.
	(IX86_BUILTIN_PHSUBDQ): Ditto.
	(IX86_BUILTIN_PROTB): Ditto.
	(IX86_BUILTIN_PROTW): Ditto.
	(IX86_BUILTIN_PROTD): Ditto.
	(IX86_BUILTIN_PROTQ): Ditto.
	(IX86_BUILTIN_PROTB_IMM): Ditto.
	(IX86_BUILTIN_PROTW_IMM): Ditto.
	(IX86_BUILTIN_PROTD_IMM): Ditto.
	(IX86_BUILTIN_PROTQ_IMM): Ditto.
	(IX86_BUILTIN_PSHLB): Ditto.
	(IX86_BUILTIN_PSHLW): Ditto.
	(IX86_BUILTIN_PSHLD): Ditto.
	(IX86_BUILTIN_PSHLQ): Ditto.
	(IX86_BUILTIN_PSHAB): Ditto.
	(IX86_BUILTIN_PSHAW): Ditto.
	(IX86_BUILTIN_PSHAD): Ditto.
	(IX86_BUILTIN_PSHAQ): Ditto.
	(IX86_BUILTIN_FRCZSS): Ditto.
	(IX86_BUILTIN_FRCZSD): Ditto.
	(IX86_BUILTIN_FRCZPS): Ditto.
	(IX86_BUILTIN_FRCZPD): Ditto.
	(IX86_BUILTIN_CVTPH2PS): Ditto.
	(IX86_BUILTIN_CVTPS2PH): Ditto.
	(IX86_BUILTIN_COMEQSS): Ditto.
	(IX86_BUILTIN_COMNESS): Ditto.
	(IX86_BUILTIN_COMLTSS): Ditto.
	(IX86_BUILTIN_COMLESS): Ditto.
	(IX86_BUILTIN_COMGTSS): Ditto.
	(IX86_BUILTIN_COMGESS): Ditto.
	(IX86_BUILTIN_COMUEQSS): Ditto.
	(IX86_BUILTIN_COMUNESS): Ditto.
	(IX86_BUILTIN_COMULTSS): Ditto.
	(IX86_BUILTIN_COMULESS): Ditto.
	(IX86_BUILTIN_COMUGTSS): Ditto.
	(IX86_BUILTIN_COMUGESS): Ditto.
	(IX86_BUILTIN_COMORDSS): Ditto.
	(IX86_BUILTIN_COMUNORDSS): Ditto.
	(IX86_BUILTIN_COMFALSESS): Ditto.
	(IX86_BUILTIN_COMTRUESS): Ditto.
	(IX86_BUILTIN_COMEQSD): Ditto.
	(IX86_BUILTIN_COMNESD): Ditto.
	(IX86_BUILTIN_COMLTSD): Ditto.
	(IX86_BUILTIN_COMLESD): Ditto.
	(IX86_BUILTIN_COMGTSD): Ditto.
	(IX86_BUILTIN_COMGESD): Ditto.
	(IX86_BUILTIN_COMUEQSD): Ditto.
	(IX86_BUILTIN_COMUNESD): Ditto.
	(IX86_BUILTIN_COMULTSD): Ditto.
	(IX86_BUILTIN_COMULESD): Ditto.
	(IX86_BUILTIN_COMUGTSD): Ditto.
	(IX86_BUILTIN_COMUGESD): Ditto.
	(IX86_BUILTIN_COMORDSD): Ditto.
	(IX86_BUILTIN_COMUNORDSD): Ditto.
	(IX86_BUILTIN_COMFALSESD): Ditto.
	(IX86_BUILTIN_COMTRUESD): Ditto.
	(IX86_BUILTIN_COMEQPS): Ditto.
	(IX86_BUILTIN_COMNEPS): Ditto.
	(IX86_BUILTIN_COMLTPS): Ditto.
	(IX86_BUILTIN_COMLEPS): Ditto.
	(IX86_BUILTIN_COMGTPS): Ditto.
	(IX86_BUILTIN_COMGEPS): Ditto.
	(IX86_BUILTIN_COMUEQPS): Ditto.
	(IX86_BUILTIN_COMUNEPS): Ditto.
	(IX86_BUILTIN_COMULTPS): Ditto.
	(IX86_BUILTIN_COMULEPS): Ditto.
	(IX86_BUILTIN_COMUGTPS): Ditto.
	(IX86_BUILTIN_COMUGEPS): Ditto.
	(IX86_BUILTIN_COMORDPS): Ditto.
	(IX86_BUILTIN_COMUNORDPS): Ditto.
	(IX86_BUILTIN_COMFALSEPS): Ditto.
	(IX86_BUILTIN_COMTRUEPS): Ditto.
	(IX86_BUILTIN_COMEQPD): Ditto.
	(IX86_BUILTIN_COMNEPD): Ditto.
	(IX86_BUILTIN_COMLTPD): Ditto.
	(IX86_BUILTIN_COMLEPD): Ditto.
	(IX86_BUILTIN_COMGTPD): Ditto.
	(IX86_BUILTIN_COMGEPD): Ditto.
	(IX86_BUILTIN_COMUEQPD): Ditto.
	(IX86_BUILTIN_COMUNEPD): Ditto.
	(IX86_BUILTIN_COMULTPD): Ditto.
	(IX86_BUILTIN_COMULEPD): Ditto.
	(IX86_BUILTIN_COMUGTPD): Ditto.
	(IX86_BUILTIN_COMUGEPD): Ditto.
	(IX86_BUILTIN_COMORDPD): Ditto.
	(IX86_BUILTIN_COMUNORDPD): Ditto.
	(IX86_BUILTIN_COMFALSEPD): Ditto.
	(IX86_BUILTIN_COMTRUEPD): Ditto.
	(IX86_BUILTIN_PCOMEQUB): Ditto.
	(IX86_BUILTIN_PCOMNEUB): Ditto.
	(IX86_BUILTIN_PCOMLTUB): Ditto.
	(IX86_BUILTIN_PCOMLEUB): Ditto.
	(IX86_BUILTIN_PCOMGTUB): Ditto.
	(IX86_BUILTIN_PCOMGEUB): Ditto.
	(IX86_BUILTIN_PCOMFALSEUB): Ditto.
	(IX86_BUILTIN_PCOMTRUEUB): Ditto.
	(IX86_BUILTIN_PCOMEQUW): Ditto.
	(IX86_BUILTIN_PCOMNEUW): Ditto.
	(IX86_BUILTIN_PCOMLTUW): Ditto.
	(IX86_BUILTIN_PCOMLEUW): Ditto.
	(IX86_BUILTIN_PCOMGTUW): Ditto.
	(IX86_BUILTIN_PCOMGEUW): Ditto.
	(IX86_BUILTIN_PCOMFALSEUW): Ditto.
	(IX86_BUILTIN_PCOMTRUEUW): Ditto.
	(IX86_BUILTIN_PCOMEQUD): Ditto.
	(IX86_BUILTIN_PCOMNEUD): Ditto.
	(IX86_BUILTIN_PCOMLTUD): Ditto.
	(IX86_BUILTIN_PCOMLEUD): Ditto.
	(IX86_BUILTIN_PCOMGTUD): Ditto.
	(IX86_BUILTIN_PCOMGEUD): Ditto.
	(IX86_BUILTIN_PCOMFALSEUD): Ditto.
	(IX86_BUILTIN_PCOMTRUEUD): Ditto.
	(IX86_BUILTIN_PCOMEQUQ): Ditto.
	(IX86_BUILTIN_PCOMNEUQ): Ditto.
	(IX86_BUILTIN_PCOMLTUQ): Ditto.
	(IX86_BUILTIN_PCOMLEUQ): Ditto.
	(IX86_BUILTIN_PCOMGTUQ): Ditto.
	(IX86_BUILTIN_PCOMGEUQ): Ditto.
	(IX86_BUILTIN_PCOMFALSEUQ): Ditto.
	(IX86_BUILTIN_PCOMTRUEUQ): Ditto.
	(IX86_BUILTIN_PCOMEQB): Ditto.
	(IX86_BUILTIN_PCOMNEB): Ditto.
	(IX86_BUILTIN_PCOMLTB): Ditto.
	(IX86_BUILTIN_PCOMLEB): Ditto.
	(IX86_BUILTIN_PCOMGTB): Ditto.
	(IX86_BUILTIN_PCOMGEB): Ditto.
	(IX86_BUILTIN_PCOMFALSEB): Ditto.
	(IX86_BUILTIN_PCOMTRUEB): Ditto.
	(IX86_BUILTIN_PCOMEQW): Ditto.
	(IX86_BUILTIN_PCOMNEW): Ditto.
	(IX86_BUILTIN_PCOMLTW): Ditto.
	(IX86_BUILTIN_PCOMLEW): Ditto.
	(IX86_BUILTIN_PCOMGTW): Ditto.
	(IX86_BUILTIN_PCOMGEW): Ditto.
	(IX86_BUILTIN_PCOMFALSEW): Ditto.
	(IX86_BUILTIN_PCOMTRUEW): Ditto.
	(IX86_BUILTIN_PCOMEQD): Ditto.
	(IX86_BUILTIN_PCOMNED): Ditto.
	(IX86_BUILTIN_PCOMLTD): Ditto.
	(IX86_BUILTIN_PCOMLED): Ditto.
	(IX86_BUILTIN_PCOMGTD): Ditto.
	(IX86_BUILTIN_PCOMGED): Ditto.
	(IX86_BUILTIN_PCOMFALSED): Ditto.
	(IX86_BUILTIN_PCOMTRUED): Ditto.
	(IX86_BUILTIN_PCOMEQQ): Ditto.
	(IX86_BUILTIN_PCOMNEQ): Ditto.
	(IX86_BUILTIN_PCOMLTQ): Ditto.
	(IX86_BUILTIN_PCOMLEQ): Ditto.
	(IX86_BUILTIN_PCOMGTQ): Ditto.
	(IX86_BUILTIN_PCOMGEQ): Ditto.
	(IX86_BUILTIN_PCOMFALSEQ): Ditto.
	(IX86_BUILTIN_PCOMTRUEQ): Ditto.
	(bdesc_ptest): New table for SSE4.1/SSE5 intrinsic support.
	(bdesc_sse_3arg): Likewise.
	(bdesc_1arg): Add roundpd/roundps.
	(enum multi_arg_type): New enum for describing the various SSE5
	intrinsic argument types.
	(bdesc_multi_arg): New table for SSE5 intrinsics.
	(ix86_init_mmx_sse_builtins): Add SSE5 intrinsic support.
	(ix86_expand_sse_4_operands_builtin, ix86_expand_sse_ptest): Add
	SSE4.1/SSE5 intrinsic support.
	(ix86_expand_multi_arg_builtin): New function for creating SSE5
	intrinsics.
	(ix86_expand_unop_builtin): Handle CODE_FOR_sse4_1_roundpd and
	CODE_FOR_sse4_1_roundps.
	(ix86_expand_builtin): Add SSE5 intrinsic support.
	(ix86_sse5_valid_op_p): New function to validate SSE5 3 and 4
	operand instructions.
	(ix86_expand_sse5_multiple_memory): New function to split the
	second memory reference from SSE5 instructions.
	(type_has_variadic_args_p): Delete in favor of stdarg_p.

	* config/i386/i386-protos.h (ix86_sse5_valid_op_p): Add declaration.
	(ix86_expand_sse5_multiple_memory): Ditto.

	* config/i386/i386.md (UNSPEC_PTEST, UNSPEC_ROUND): Add new UNSPEC
	constants for SSE4.1/SSE5 support.
	(UNSPEC_SSE5_INTRINSIC): Add new UNSPEC constant for SSE5 support.
	(UNSPEC_SSE5_UNSIGNED_CMP): Ditto.
	(UNSPEC_SSE5_TRUEFALSE): Ditto.
	(UNSPEC_SSE5_PERMUTE): Ditto.
	(UNSPEC_SSE5_ASHIFT): Ditto.
	(UNSPEC_SSE5_LSHIFT): Ditto.
	(UNSPEC_FRCZ): Ditto.
	(UNSPEC_CVTPH2PS): Ditto.
	(UNSPEC_CVTPS2PH): Ditto.
	(PCOM_FALSE): Add new constant for true/false SSE5 comparisons.
	(PCOM_TRUE): Ditto.
	(COM_FALSE_S): Ditto.
	(COM_FALSE_P): Ditto.
	(COM_TRUE_S): Ditto.
	(COM_TRUE_P): Ditto.
	(type attribute): Add ssemuladd, sseiadd1, ssecvt1, sse4arg types.
	(unit attribute): Add support for ssemuladd, ssecvt1, sseiadd1 sse4arg
	types.
	(memory attribute): Ditto.
	(MODEF): New mode macro.
	(ssemodefsuffix): New mode attr.
	(sse4_1_round<mode>2): New.
	(sse_setccsf): Disable if SSE5.
	(sse_setccdf): Ditto.
	(sse5_setcc<mode>): New support for SSE5 conditional move.
	(sse5_pcmov_<mode>): Ditto.

	* config/i386/sse.md (SSEMODE1248): New mode iterator for SSE5.
	(SSEMODEF4): Ditto.
	(SSEMODEF2P): Ditto.
	(ssemodesuffixf4): New mode attribute for SSE5.
	(ssemodesuffixf2s): Ditto.
	(ssemodesuffixf2c): Ditto.
	(sserotatemax): Ditto.
	(ssescalarmode): Ditto.
	(sse5_fmadd<mode>4): Add SSE5 floating point multiply/add
	instructions.
	(sse5_vmfmadd<mode>4): Ditto.
	(sse5_fmsub<mode>4): Ditto.
	(sse5_vmfmsub<mode>4): Ditto.
	(sse5_fnmadd<mode>4): Ditto.
	(sse5_vmfnmadd<mode>4): Ditto.
	(sse5_fnmsub<mode>4): Ditto.
	(sse5_vmfnmsub<mode>4): Ditto.
	(sse5i_fmadd<mode>4): Ditto.
	(sse5i_fmsub<mode>4): Ditto.
	(sse5i_fnmadd<mode>4): Ditto.
	(sse5i_fnmsub<mode>4): Ditto.
	(sse5i_vmfmadd<mode>4): Ditto.
	(sse5i_vmfmsub<mode>4): Ditto.
	(sse5i_vmfnmadd<mode>4): Ditto.
	(sse5i_vmfnmsub<mode>4): Ditto.
	(mulv4si3): Add SSE5 support.
	(sse5_mulv4si3): New insn for 32-bit multiply support on SSE5.
	(sse4_1_ptest): New.
	(sse4_1_roundpd): Ditto.
	(sse4_1_roundps): Ditto.
	(sse4_1_roundsd): Ditto.
	(sse4_1_roundss): Ditto.
	(sse_maskcmpv4sf3): Disable if SSE5 so the SSE5 instruction will
	be generated.
	(sse_vmmaskcmpv4sf3): Ditto.
	(sse2_maskcmpv2df3): Ditto.
	(sse2_vmmaskcmpv2df3): Ditto.
	(sse2_eq<mode>3): Ditto.
	(sse2_gt<mode>3): Ditto.
	(sse5_pcmov_<mode>): Add SSE5 support.
	(vec_unpacku_hi_v16qi): Ditto.
	(vec_unpacks_hi_v16qi): Ditto.
	(vec_unpacku_lo_v16qi): Ditto.
	(vec_unpacks_lo_v16qi): Ditto.
	(vec_unpacku_hi_v8hi): Ditto.
	(vec_unpacks_hi_v8hi): Ditto.
	(vec_unpacku_lo_v8hi): Ditto.
	(vec_unpacks_lo_v8hi): Ditto.
	(vec_unpacku_hi_v4si): Ditto.
	(vec_unpacks_hi_v4si): Ditto.
	(vec_unpacku_lo_v4si): Ditto.
	(vec_unpacks_lo_v4si): Ditto.
	(sse5_pmacsww): New SSE5 intrinsic insn.
	(sse5_pmacssww): Ditto.
	(sse5_pmacsdd): Ditto.
	(sse5_pmacssdd): Ditto.
	(sse5_pmacssdql): Ditto.
	(sse5_pmacssdqh): Ditto.
	(sse5_pmacsdqh): Ditto.
	(sse5_pmacsswd): Ditto.
	(sse5_pmacswd): Ditto.
	(sse5_pmadcsswd): Ditto.
	(sse5_pmadcswd): Ditto.
	(sse5_pcmov_<move>): Conditional move support on SSE5.
	(sse5_phaddbw): New SSE5 intrinsic insn.
	(sse5_phaddbd): Ditto.
	(sse5_phaddbq): Ditto.
	(sse5_phaddwd): Ditto.
	(sse5_phaddwq): Ditto.
	(sse5_phadddq): Ditto.
	(sse5_phaddubw): Ditto.
	(sse5_phaddubd): Ditto.
	(sse5_phaddubq): Ditto.
	(sse5_phadduwd): Ditto.
	(sse5_phadduwq): Ditto.
	(sse5_phaddudq): Ditto.
	(sse5_phsubbw): Ditto.
	(sse5_phsubwd): Ditto.
	(sse5_phsubdq): Ditto.
	(sse5_pperm): Ditto.
	(sse5_pperm_sign_v16qi_v8hi): New insns for pack/unpack with SSE5.
	(sse5_pperm_zero_v16qi_v8hi): Ditto.
	(sse5_pperm_sign_v8hi_v4si): Ditto.
	(sse5_pperm_zero_v8hi_v4si): Ditto.
	(sse5_pperm_sign_v4si_v2di): Ditto.
	(sse5_pperm_sign_v4si_v2di): Ditto.
	(sse5_pperm_pack_v2di_v4si): Ditto.
	(sse5_pperm_pack_v4si_v8hi): Ditto.
	(sse5_pperm_pack_v8hi_v16qi): Ditto.
	(sse5_perm<mode>): New SSE5 intrinsic insn.
	(rotl<mode>3): Ditto.
	(sse5_rotl<mode>3): Ditto.
	(sse5_ashl<mode>3): Ditto.
	(sse5_lshl<mode>3): Ditto.
	(sse5_frcz<mode>2): Ditto.
	(sse5s_frcz<mode>2): Ditto.
	(sse5_cvtph2ps): Ditto.
	(sse5_cvtps2ph): Ditto.
	(sse5_vmmaskcmp<mode>3): Ditto.
	(sse5_com_tf<mode>3): Ditto.
	(sse5_maskcmp<mode>3): Ditto.
	(sse5_maskcmp_uns<mode>3): Ditto.
	(sse5_maskcmp_uns2<mode>3): Ditto.
	(sse5_pcom_tf<mode>3): Ditto.
	
	* config/i386/predicates.md (const_0_to_31_operand): New predicate
	to match 0..31.
	(sse5_comparison_float_operator): New predicate to match the
	comparison operators supported by the SSE5 com instruction.
	(ix86_comparison_int_operator): New predicate to match just the
	signed int comparisons.
	(ix86_comparison_uns_operator): New predicate to match just the
	unsigned int comparisons.

	* doc/invoke.texi (-msse5): Add documentation.
	(-mfused-madd): Ditto.

	* doc/extend.texi (x86 intrinsics): Document new SSE5 intrinsics.

	* config.gcc (i[34567]86-*-*): Include bmmintrin.h and
	mmintrin-common.h.
	(x86_64-*-*): Ditto.

	* config/i386/bmmintrin.h: New file, provide common x86 compiler
	intrinisics for SSE5.

	* config/i386/mmintrin-common.h: New file, to contain common
	instructions between SSE4.1 and SSE5.

	* gcc.dg/i386-cpuid.h (bit_SSE5): Define SSE5 bit.

	* gcc.target/i386/sse5-hadduX.c: Add support for SSE5 tests.
	* gcc.target/i386/sse5-hsubX.c: Ditto.
	* gcc.target/i386/sse5-permpX.c: Ditto.
	* gcc.target/i386/sse5-haddX.c: Ditto.
	* gcc.target/i386/sse5-maccXX.c: Ditto.
	* gcc.target/i386/sse5-msubXX.c: Ditto.
	* gcc.target/i386/sse5-nmaccXX.c: Ditto.
	* gcc.target/i386/sse5-nmsubXX.c: Ditto.

	* gcc.target/i386/sse5-pcmov.c: New file to make sure the compiler
	optimizes floating point conditional moves into the pcmov
	instruction on SSE5.
	* gcc.target/i386/sse5-pcmov2.c: Ditto.

	* gcc.target/i386/sse5-ima-vector.c: New file to make sure the
	compiler optimizes vector 32-bit int (a*b)+c into pmacsdd on
	SSE5.

	* gcc.target/i386/sse5-fma-vector.c: New file to make sure the
	compiler optimizes vector (a*b)+c into fmadd on SSE5.

	* gcc.target/i386/sse5-fma.c: New file to make sure the compiler
	optimizes (a*b)+c into fmadd on SSE5.

	* gcc.target/i386/i386.exp (check_effective_target_sse5): Check
	whether the SSE5 instructions can be generated.

	* gcc.target/i386/sse5-check.h: New. Add support for 
	SSE5 tests.

	* gcc.target/i386/sse-12a.c: New test.
	* gcc.target/i386/sse-13a.c: New test.
	* gcc.target/i386/sse-14a.c: New test.

2007-05-22  H.J. Lu  <hongjiu.lu@intel.com>
	    Richard Henderson  <rth@redhat.com>

	* config/i386/i386-modes.def (V2QI): New.

2007-05-20  Uros Bizjak  <ubizjak@gmail.com>

	* config/386/mm3dnow.h (_m_from_float): Use C++ compatible
	assignment.
	(_m_to_float): Use C89 compatible assignment.

2006-05-23  Kazu Hirata  <kazu@codesourcery.com>

	PR target/27696
	* config/i386/i386.c (ix86_expand_builtin): Use
	gen_sse3_monitor64 for TARGET_64BIT.

--- gcc/config.gcc.jj	2007-12-28 15:43:25.000000000 +0100
+++ gcc/config.gcc	2007-12-28 20:04:35.000000000 +0100
@@ -264,12 +264,14 @@ xscale-*-*)
 i[34567]86-*-*)
 	cpu_type=i386
 	extra_headers="mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h
-		       pmmintrin.h tmmintrin.h ammintrin.h"
+		       pmmintrin.h tmmintrin.h ammintrin.h bmmintrin.h
+		       mmintrin-common.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
 	extra_headers="mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h
-		       pmmintrin.h tmmintrin.h ammintrin.h"
+		       pmmintrin.h tmmintrin.h ammintrin.h bmmintrin.h
+		       mmintrin-common.h"
 	need_64bit_hwint=yes
 	;;
 ia64-*-*)
--- gcc/config/i386/bmmintrin.h	2007-12-28 20:04:35.000000000 +0100
+++ gcc/config/i386/bmmintrin.h	2007-12-31 10:19:52.000000000 +0100
@@ -0,0 +1,1260 @@
+/* Copyright (C) 2007 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 2, 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.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, if you include this header file into source
+   files compiled by GCC, this header file does not by itself cause
+   the resulting executable to be covered by the GNU General Public
+   License.  This exception does not however invalidate any other
+   reasons why the executable file might be covered by the GNU General
+   Public License.  */
+
+#ifndef _BMMINTRIN_H_INCLUDED
+#define _BMMINTRIN_H_INCLUDED
+
+#ifndef __SSE5__
+# error "SSE5 instruction set not enabled"
+#else
+
+/* We need definitions from the SSE4A, SSE3, SSE2 and SSE header files.  */
+#include <ammintrin.h>
+#include <mmintrin-common.h>
+
+/* Floating point multiply/add type instructions */
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_macc_ps(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fmaddps ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_macc_pd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fmaddpd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_macc_ss(__m128 __A, __m128 __B, __m128 __C)
+{
+  return  (__m128) __builtin_ia32_fmaddss ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_macc_sd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fmaddsd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_msub_ps(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fmsubps ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_msub_pd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fmsubpd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_msub_ss(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fmsubss ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_msub_sd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fmsubsd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_nmacc_ps(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fnmaddps ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_nmacc_pd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fnmaddpd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_nmacc_ss(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fnmaddss ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_nmacc_sd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fnmaddsd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_nmsub_ps(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fnmsubps ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_nmsub_pd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fnmsubpd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_nmsub_ss(__m128 __A, __m128 __B, __m128 __C)
+{
+  return (__m128) __builtin_ia32_fnmsubss ((__v4sf)__A, (__v4sf)__B, (__v4sf)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_nmsub_sd(__m128d __A, __m128d __B, __m128d __C)
+{
+  return (__m128d) __builtin_ia32_fnmsubsd ((__v2df)__A, (__v2df)__B, (__v2df)__C);
+}
+
+/* Integer multiply/add intructions. */
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C)
+{
+  return (__m128i) __builtin_ia32_pmacssww ((__v8hi)__A,(__v8hi)__B, (__v8hi)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_macc_epi16(__m128i __A, __m128i __B, __m128i __C)
+{
+  return (__m128i) __builtin_ia32_pmacsww ((__v8hi)__A, (__v8hi)__B, (__v8hi)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maccsd_epi16(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacsswd ((__v8hi)__A, (__v8hi)__B, (__v4si)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maccd_epi16(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacswd ((__v8hi)__A, (__v8hi)__B, (__v4si)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maccs_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacssdd ((__v4si)__A, (__v4si)__B, (__v4si)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_macc_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacsdd ((__v4si)__A, (__v4si)__B, (__v4si)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maccslo_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacssdql ((__v4si)__A, (__v4si)__B, (__v2di)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_macclo_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacsdql ((__v4si)__A, (__v4si)__B, (__v2di)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maccshi_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacssdqh ((__v4si)__A, (__v4si)__B, (__v2di)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_macchi_epi32(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmacsdqh ((__v4si)__A, (__v4si)__B, (__v2di)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maddsd_epi16(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmadcsswd ((__v8hi)__A,(__v8hi)__B,(__v4si)__C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_maddd_epi16(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pmadcswd ((__v8hi)__A,(__v8hi)__B,(__v4si)__C);
+}
+
+/* Packed Integer Horizontal Add and Subtract */
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddw_epi8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddbw ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddd_epi8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddbd ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddq_epi8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddbq ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddd_epi16(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddwd ((__v8hi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddq_epi16(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddwq ((__v8hi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddq_epi32(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phadddq ((__v4si)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddw_epu8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddubw ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddd_epu8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddubd ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddq_epu8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddubq ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddd_epu16(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phadduwd ((__v8hi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddq_epu16(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phadduwq ((__v8hi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_haddq_epu32(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phaddudq ((__v4si)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_hsubw_epi8(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phsubbw ((__v16qi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_hsubd_epi16(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phsubwd ((__v8hi)__A);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_hsubq_epi32(__m128i __A)
+{
+  return  (__m128i) __builtin_ia32_phsubdq ((__v4si)__A);
+}
+
+/* Vector conditional move and permute */
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_cmov_si128(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pcmov (__A, __B, __C);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_perm_epi8(__m128i __A, __m128i __B, __m128i __C)
+{
+  return  (__m128i) __builtin_ia32_pperm ((__v16qi)__A, (__v16qi)__B, (__v16qi)__C);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_perm_ps(__m128 __A, __m128 __B, __m128i __C)
+{
+  return  (__m128) __builtin_ia32_permps ((__m128)__A, (__m128)__B, (__v16qi)__C);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_perm_pd(__m128d __A, __m128d __B, __m128i __C)
+{
+  return  (__m128d) __builtin_ia32_permpd ((__m128d)__A, (__m128d)__B, (__v16qi)__C);
+}
+
+/* Packed Integer Rotates and Shifts */
+
+/* Rotates - Non-Immediate form */
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_rot_epi8(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_protb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_rot_epi16(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_protw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_rot_epi32(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_protd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_rot_epi64(__m128i __A,  __m128i __B)
+{
+  return (__m128i)  __builtin_ia32_protq ((__v2di)__A, (__v2di)__B);
+}
+
+
+/* Rotates - Immediate form */
+#ifdef __OPTIMIZE__
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_roti_epi8(__m128i __A,  int __B)
+{
+  return  (__m128i) __builtin_ia32_protbi ((__v16qi)__A, __B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_roti_epi16(__m128i __A, int __B)
+{
+  return  (__m128i) __builtin_ia32_protwi ((__v8hi)__A, __B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_roti_epi32(__m128i __A, int __B)
+{
+  return  (__m128i) __builtin_ia32_protdi ((__v4si)__A, __B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_roti_epi64(__m128i __A, int __B)
+{
+  return  (__m128i) __builtin_ia32_protqi ((__v2di)__A, __B);
+}
+#else
+#define _mm_roti_epi8(A, B) ((__m128i) __builtin_ia32_protbi ((__v16qi)(A), B))
+#define _mm_roti_epi16(A, B) ((__m128i) __builtin_ia32_protwi ((__v8hi)(A), B))
+#define _mm_roti_epi32(A, B) ((__m128i) __builtin_ia32_protdi ((__v4si)(A), B))
+#define _mm_roti_epi64(A, B) ((__m128i) __builtin_ia32_protqi ((__v2di)(A), B))
+#endif
+
+/* pshl */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_shl_epi8(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshlb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_shl_epi16(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshlw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_shl_epi32(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshld ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_shl_epi64(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshlq ((__v2di)__A, (__v2di)__B);
+}
+
+/* psha */
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_sha_epi8(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshab ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_sha_epi16(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshaw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_sha_epi32(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshad ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_sha_epi64(__m128i __A,  __m128i __B)
+{
+  return  (__m128i) __builtin_ia32_pshaq ((__v2di)__A, (__v2di)__B);
+}
+
+/* Compare and Predicate Generation */
+
+/* com (floating point, packed single) */
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comeq_ps(__m128 __A, __m128 __B)
+{
+  return  (__m128) __builtin_ia32_comeqps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comlt_ps(__m128 __A, __m128 __B)
+{
+  return  (__m128) __builtin_ia32_comltps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comle_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comleps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comunord_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comunordps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comneq_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comuneqps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comnlt_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comunltps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comnle_ps(__m128 __A, __m128 __B)
+{
+  return (__m128)  __builtin_ia32_comunleps ((__v4sf)__A, (__v4sf)__B);
+}
+
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comord_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comordps ((__v4sf)__A, (__v4sf)__B);
+}
+
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comueq_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comueqps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comnge_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comungeps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comngt_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comungtps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comfalseps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comoneq_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comneqps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comge_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comgeps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comgt_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comgtps ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_ps(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comtrueps ((__v4sf)__A, (__v4sf)__B);
+}
+
+/* com (floating point, packed double) */
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comeq_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comeqpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comlt_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comltpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comle_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comlepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comunord_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comunordpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comneq_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comuneqpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comnlt_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comunltpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comnle_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comunlepd ((__v2df)__A, (__v2df)__B);
+}
+
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comord_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comordpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comueq_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comueqpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comnge_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comungepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comngt_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comungtpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comfalsepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comoneq_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comneqpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comge_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comgepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comgt_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comgtpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_pd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comtruepd ((__v2df)__A, (__v2df)__B);
+}
+
+/* com (floating point, scalar single) */
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comeq_ss(__m128 __A, __m128 __B)
+{
+  return (__m128)  __builtin_ia32_comeqss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comlt_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comltss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comle_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comless ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comunord_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comunordss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comneq_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comuneqss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comnlt_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comunltss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comnle_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comunless ((__v4sf)__A, (__v4sf)__B);
+}
+
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comord_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comordss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comueq_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comueqss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comnge_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comungess ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comngt_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comungtss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comfalsess ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comoneq_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comneqss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comge_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comgess ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comgt_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comgtss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_ss(__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_comtruess ((__v4sf)__A, (__v4sf)__B);
+}
+
+/* com (floating point, scalar double) */
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comeq_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comeqsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comlt_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comltsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comle_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comlesd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comunord_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comunordsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comneq_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comuneqsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comnlt_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comunltsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comnle_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comunlesd ((__v2df)__A, (__v2df)__B);
+}
+
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comord_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comordsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comueq_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comueqsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comnge_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comungesd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comngt_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comungtsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comfalsesd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comoneq_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comneqsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comge_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comgesd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comgt_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comgtsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_sd(__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_comtruesd ((__v2df)__A, (__v2df)__B);
+}
+
+
+/*pcom (integer, unsinged bytes) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltub ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomleub ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtub ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgeub ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomequb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomnequb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalseub ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epu8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrueub ((__v16qi)__A, (__v16qi)__B);
+}
+
+/*pcom (integer, unsinged words) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltuw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomleuw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtuw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgeuw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomequw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomnequw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalseuw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epu16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrueuw ((__v8hi)__A, (__v8hi)__B);
+}
+
+/*pcom (integer, unsinged double words) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltud ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomleud ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtud ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgeud ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomequd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomnequd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalseud ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epu32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrueud ((__v4si)__A, (__v4si)__B);
+}
+
+/*pcom (integer, unsinged quad words) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltuq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomleuq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtuq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgeuq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomequq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomnequq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalseuq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epu64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrueuq ((__v2di)__A, (__v2di)__B);
+}
+
+/*pcom (integer, signed bytes) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomleb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgeb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomeqb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomneqb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalseb ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epi8(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrueb ((__v16qi)__A, (__v16qi)__B);
+}
+
+/*pcom (integer, signed words) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomlew ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgew ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomeqw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomneqw ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalsew ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epi16(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtruew ((__v8hi)__A, (__v8hi)__B);
+}
+
+/*pcom (integer, signed double words) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomled ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomged ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomeqd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomneqd ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalsed ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epi32(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrued ((__v4si)__A, (__v4si)__B);
+}
+
+/*pcom (integer, signed quad words) */
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comlt_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomltq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comle_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomleq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comgt_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgtq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comge_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomgeq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comeq_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomeqq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comneq_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomneqq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comfalse_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomfalseq ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __artificial__))
+_mm_comtrue_epi64(__m128i __A, __m128i __B)
+{
+  return (__m128i) __builtin_ia32_pcomtrueq ((__v2di)__A, (__v2di)__B);
+}
+
+/* FRCZ */
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_frcz_ps (__m128 __A)
+{
+  return (__m128) __builtin_ia32_frczps ((__v4sf)__A);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_frcz_pd (__m128d __A)
+{
+  return (__m128d) __builtin_ia32_frczpd ((__v2df)__A);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_frcz_ss (__m128 __A, __m128 __B)
+{
+  return (__m128) __builtin_ia32_frczss ((__v4sf)__A, (__v4sf)__B);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_frcz_sd (__m128d __A, __m128d __B)
+{
+  return (__m128d) __builtin_ia32_frczsd ((__v2df)__A, (__v2df)__B);
+}
+
+#endif /* __SSE5__ */
+
+#endif /* _BMMINTRIN_H_INCLUDED */
--- gcc/config/i386/i386-modes.def.jj	2007-02-20 22:38:59.000000000 +0100
+++ gcc/config/i386/i386-modes.def	2007-12-28 20:04:35.000000000 +0100
@@ -68,6 +68,7 @@ VECTOR_MODES (INT, 8);        /*       V
 VECTOR_MODES (INT, 16);       /* V16QI V8HI V4SI V2DI */
 VECTOR_MODES (FLOAT, 8);      /*            V4HF V2SF */
 VECTOR_MODES (FLOAT, 16);     /*       V8HF V4SF V2DF */
+VECTOR_MODE (INT, QI, 2);     /*                 V2QI */
 VECTOR_MODE (INT, DI, 4);     /*                 V4DI */
 VECTOR_MODE (INT, SI, 8);     /*                 V8SI */
 VECTOR_MODE (INT, HI, 16);    /*                V16HI */
--- gcc/config/i386/i386-protos.h.jj	2007-02-20 22:38:59.000000000 +0100
+++ gcc/config/i386/i386-protos.h	2007-12-28 20:04:35.000000000 +0100
@@ -48,6 +48,10 @@ extern bool x86_extended_QIreg_mentioned
 extern bool x86_extended_reg_mentioned_p (rtx);
 extern enum machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
 
+extern bool ix86_sse5_valid_op_p (rtx [], rtx, int, bool, int);
+extern void ix86_expand_sse5_multiple_memory (rtx [], int,
+					      enum machine_mode mode);
+
 extern int ix86_expand_movmem (rtx, rtx, rtx, rtx);
 extern int ix86_expand_clrmem (rtx, rtx, rtx);
 extern int ix86_expand_strlen (rtx, rtx, rtx, rtx);
--- gcc/config/i386/i386.c	2007-12-28 22:12:02.000000000 +0100
+++ gcc/config/i386/i386.c	2007-12-31 10:09:34.000000000 +0100
@@ -1636,24 +1636,32 @@ ix86_handle_option (size_t code, const c
     case OPT_msse:
       if (!value)
 	{
-	  target_flags &= ~(MASK_SSE2 | MASK_SSE3 | MASK_SSE4A);
-	  target_flags_explicit |= MASK_SSE2 | MASK_SSE3 | MASK_SSE4A;
+	  target_flags &= ~(MASK_SSE2 | MASK_SSE3 | MASK_SSE4A | MASK_SSE5);
+	  target_flags_explicit |= MASK_SSE2 | MASK_SSE3 | MASK_SSE4A | MASK_SSE5;
 	}
       return true;
 
     case OPT_msse2:
       if (!value)
 	{
-	  target_flags &= ~(MASK_SSE3 | MASK_SSE4A);
-	  target_flags_explicit |= MASK_SSE3 | MASK_SSE4A;
+	  target_flags &= ~(MASK_SSE3 | MASK_SSE4A | MASK_SSE5);
+	  target_flags_explicit |= MASK_SSE3 | MASK_SSE4A | MASK_SSE5;
 	}
       return true;
 
     case OPT_msse3:
       if (!value)
 	{
-	  target_flags &= ~MASK_SSE4A;
-	  target_flags_explicit |= MASK_SSE4A;
+	  target_flags &= ~(MASK_SSE4A | MASK_SSE5);
+	  target_flags_explicit |= MASK_SSE4A | MASK_SSE5;
+	}
+      return true;
+
+    case OPT_msse4a:
+      if (!value)
+	{
+	  target_flags &= ~MASK_SSE5;
+	  target_flags_explicit |= MASK_SSE5;
 	}
       return true;
 
@@ -1728,7 +1736,8 @@ override_options (void)
 	  PTA_CX16 = 512,
 	  PTA_POPCNT = 1024,
 	  PTA_ABM = 2048,
- 	  PTA_SSE4A = 4096
+ 	  PTA_SSE4A = 4096,
+	  PTA_SSE5 = 8192
 	} flags;
     }
   const processor_alias_table[] =
@@ -1948,6 +1957,9 @@ override_options (void)
 	if (processor_alias_table[i].flags & PTA_SSE4A
 	    && !(target_flags_explicit & MASK_SSE4A))
 	  target_flags |= MASK_SSE4A;
+	if (processor_alias_table[i].flags & PTA_SSE5
+	    && !(target_flags_explicit & MASK_SSE5))
+	  target_flags |= MASK_SSE5;
 	if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT))
 	  error ("CPU you selected does not support x86-64 "
 		 "instruction set");
@@ -2139,6 +2151,10 @@ override_options (void)
   if (TARGET_SSSE3)
     target_flags |= MASK_SSE3;
 
+  /* Turn on SSE4A builtins for -msse5.  */
+  if (TARGET_SSE5)
+    target_flags |= MASK_SSE4A;
+
   /* Turn on SSE3 builtins for -msse4a.  */
   if (TARGET_SSE4A)
     target_flags |= MASK_SSE3;
@@ -2476,6 +2492,171 @@ optimization_options (int level, int siz
 #endif
 }
 
+/* Validate whether a SSE5 instruction is valid or not.
+   OPERANDS is the array of operands.
+   NUM is the number of operands.
+   USES_OC0 is true if the instruction uses OC0 and provides 4 variants.
+   NUM_MEMORY is the maximum number of memory operands to accept.  */
+bool
+ix86_sse5_valid_op_p (rtx operands[], rtx insn ATTRIBUTE_UNUSED, int num, bool uses_oc0, int num_memory)
+{
+  int mem_mask;
+  int mem_count;
+  int i;
+
+  /* Count the number of memory arguments */
+  mem_mask = 0;
+  mem_count = 0;
+  for (i = 0; i < num; i++)
+    {
+      enum machine_mode mode = GET_MODE (operands[i]);
+      if (register_operand (operands[i], mode))
+	;
+
+      else if (memory_operand (operands[i], mode))
+	{
+	  mem_mask |= (1 << i);
+	  mem_count++;
+	}
+
+      else
+	return false;
+    }
+
+  /* If there were no memory operations, allow the insn */
+  if (mem_mask == 0)
+    return true;
+
+  /* Do not allow the destination register to be a memory operand.  */
+  else if (mem_mask & (1 << 0))
+    return false;
+
+  /* If there are too many memory operations, disallow the instruction.  While
+     the hardware only allows 1 memory reference, before register allocation
+     for some insns, we allow two memory operations sometimes in order to allow
+     code like the following to be optimized:
+
+	float fmadd (float *a, float *b, float *c) { return (*a * *b) + *c; }
+
+    or similar cases that are vectorized into using the fmaddss
+    instruction.  */
+  else if (mem_count > num_memory)
+    return false;
+
+  /* Don't allow more than one memory operation if not optimizing.  */
+  else if (mem_count > 1 && !optimize)
+    return false;
+
+  else if (num == 4 && mem_count == 1)
+    {
+      /* formats (destination is the first argument), example fmaddss:
+	 xmm1, xmm1, xmm2, xmm3/mem
+	 xmm1, xmm1, xmm2/mem, xmm3
+	 xmm1, xmm2, xmm3/mem, xmm1
+	 xmm1, xmm2/mem, xmm3, xmm1 */
+      if (uses_oc0)
+	return ((mem_mask == (1 << 1))
+		|| (mem_mask == (1 << 2))
+		|| (mem_mask == (1 << 3)));
+
+      /* format, example pmacsdd:
+	 xmm1, xmm2, xmm3/mem, xmm1 */
+      else
+	return (mem_mask == (1 << 2));
+    }
+
+  else if (num == 4 && num_memory == 2)
+    {
+      /* If there are two memory operations, we can load one of the memory ops
+	 into the destination register.  This is for optimizing the
+	 multiply/add ops, which the combiner has optimized both the multiply
+	 and the add insns to have a memory operation.  We have to be careful
+	 that the destination doesn't overlap with the inputs.  */
+      rtx op0 = operands[0];
+
+      if (reg_mentioned_p (op0, operands[1])
+	  || reg_mentioned_p (op0, operands[2])
+	  || reg_mentioned_p (op0, operands[3]))
+	return false;
+
+      /* formats (destination is the first argument), example fmaddss:
+	 xmm1, xmm1, xmm2, xmm3/mem
+	 xmm1, xmm1, xmm2/mem, xmm3
+	 xmm1, xmm2, xmm3/mem, xmm1
+	 xmm1, xmm2/mem, xmm3, xmm1
+
+         For the oc0 case, we will load either operands[1] or operands[3] into
+         operands[0], so any combination of 2 memory operands is ok.  */
+      if (uses_oc0)
+	return true;
+
+      /* format, example pmacsdd:
+	 xmm1, xmm2, xmm3/mem, xmm1
+
+         For the integer multiply/add instructions be more restrictive and
+         require operands[2] and operands[3] to be the memory operands.  */
+      else
+	return (mem_mask == ((1 << 2) | (1 << 3)));
+    }
+
+  else if (num == 3 && num_memory == 1)
+    {
+      /* formats, example protb:
+	 xmm1, xmm2, xmm3/mem
+	 xmm1, xmm2/mem, xmm3 */
+      if (uses_oc0)
+	return ((mem_mask == (1 << 1)) || (mem_mask == (1 << 2)));
+
+      /* format, example comeq:
+	 xmm1, xmm2, xmm3/mem */
+      else
+	return (mem_mask == (1 << 2));
+    }
+
+  else
+    gcc_unreachable ();
+
+  return false;
+}
+
+
+/* Fixup an SSE5 instruction that has 2 memory input references into a form the
+   hardware will allow by using the destination register to load one of the
+   memory operations.  Presently this is used by the multiply/add routines to
+   allow 2 memory references.  */
+
+void
+ix86_expand_sse5_multiple_memory (rtx operands[],
+				  int num,
+				  enum machine_mode mode)
+{
+  rtx op0 = operands[0];
+  if (num != 4
+      || memory_operand (op0, mode)
+      || reg_mentioned_p (op0, operands[1])
+      || reg_mentioned_p (op0, operands[2])
+      || reg_mentioned_p (op0, operands[3]))
+    gcc_unreachable ();
+
+  /* For 2 memory operands, pick either operands[1] or operands[3] to move into
+     the destination register.  */
+  if (memory_operand (operands[1], mode))
+    {
+      emit_move_insn (op0, operands[1]);
+      operands[1] = op0;
+    }
+  else if (memory_operand (operands[3], mode))
+    {
+      emit_move_insn (op0, operands[3]);
+      operands[3] = op0;
+    }
+  else
+    gcc_unreachable ();
+
+  return;
+}
+
+
 /* Table of valid machine attributes.  */
 const struct attribute_spec ix86_attribute_table[] =
 {
@@ -7679,6 +7860,7 @@ get_some_local_dynamic_name_1 (rtx *px, 
    X -- don't print any sort of PIC '@' suffix for a symbol.
    & -- print some in-use local-dynamic symbol name.
    H -- print a memory address offset by 8; used for sse high-parts
+   Y -- print condition for SSE5 com* instruction.
  */
 
 void
@@ -7950,6 +8132,61 @@ print_operand (FILE *file, rtx x, int co
 	      }
 	    return;
 	  }
+
+	case 'Y':
+	  switch (GET_CODE (x))
+	    {
+	    case NE:
+	      fputs ("neq", file);
+	      break;
+	    case EQ:
+	      fputs ("eq", file);
+	      break;
+	    case GE:
+	    case GEU:
+	      fputs (INTEGRAL_MODE_P (GET_MODE (x)) ? "ge" : "unlt", file);
+	      break;
+	    case GT:
+	    case GTU:
+	      fputs (INTEGRAL_MODE_P (GET_MODE (x)) ? "gt" : "unle", file);
+	      break;
+	    case LE:
+	    case LEU:
+	      fputs ("le", file);
+	      break;
+	    case LT:
+	    case LTU:
+	      fputs ("lt", file);
+	      break;
+	    case UNORDERED:
+	      fputs ("unord", file);
+	      break;
+	    case ORDERED:
+	      fputs ("ord", file);
+	      break;
+	    case UNEQ:
+	      fputs ("ueq", file);
+	      break;
+	    case UNGE:
+	      fputs ("nlt", file);
+	      break;
+	    case UNGT:
+	      fputs ("nle", file);
+	      break;
+	    case UNLE:
+	      fputs ("ule", file);
+	      break;
+	    case UNLT:
+	      fputs ("ult", file);
+	      break;
+	    case LTGT:
+	      fputs ("une", file);
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
+	  return;
+
 	default:
 	    output_operand_lossage ("invalid operand code '%c'", code);
 	}
@@ -11510,6 +11747,14 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp
       x = gen_rtx_AND (mode, x, op_false);
       emit_insn (gen_rtx_SET (VOIDmode, dest, x));
     }
+  else if (TARGET_SSE5)
+    {
+      rtx pcmov = gen_rtx_SET (mode, dest,
+			       gen_rtx_IF_THEN_ELSE (mode, cmp,
+						     op_true,
+						     op_false));
+      emit_insn (pcmov);
+    }
   else
     {
       op_true = force_reg (mode, op_true);
@@ -14608,6 +14853,226 @@ enum ix86_builtins
   IX86_BUILTIN_VEC_SET_V8HI,
   IX86_BUILTIN_VEC_SET_V4HI,
 
+  /* SSE4.1/SSE5 Common instructions */
+  IX86_BUILTIN_ROUNDPD,
+  IX86_BUILTIN_ROUNDPS,
+  IX86_BUILTIN_ROUNDSD,
+  IX86_BUILTIN_ROUNDSS,
+
+  IX86_BUILTIN_PTESTZ,
+  IX86_BUILTIN_PTESTC,
+  IX86_BUILTIN_PTESTNZC,
+
+  /* SSE5 instructions */
+  IX86_BUILTIN_FMADDSS,
+  IX86_BUILTIN_FMADDSD,
+  IX86_BUILTIN_FMADDPS,
+  IX86_BUILTIN_FMADDPD,
+  IX86_BUILTIN_FMSUBSS,
+  IX86_BUILTIN_FMSUBSD,
+  IX86_BUILTIN_FMSUBPS,
+  IX86_BUILTIN_FMSUBPD,
+  IX86_BUILTIN_FNMADDSS,
+  IX86_BUILTIN_FNMADDSD,
+  IX86_BUILTIN_FNMADDPS,
+  IX86_BUILTIN_FNMADDPD,
+  IX86_BUILTIN_FNMSUBSS,
+  IX86_BUILTIN_FNMSUBSD,
+  IX86_BUILTIN_FNMSUBPS,
+  IX86_BUILTIN_FNMSUBPD,
+  IX86_BUILTIN_PCMOV_V2DI,
+  IX86_BUILTIN_PCMOV_V4SI,
+  IX86_BUILTIN_PCMOV_V8HI,
+  IX86_BUILTIN_PCMOV_V16QI,
+  IX86_BUILTIN_PCMOV_V4SF,
+  IX86_BUILTIN_PCMOV_V2DF,
+  IX86_BUILTIN_PPERM,
+  IX86_BUILTIN_PERMPS,
+  IX86_BUILTIN_PERMPD,
+  IX86_BUILTIN_PMACSSWW,
+  IX86_BUILTIN_PMACSWW,
+  IX86_BUILTIN_PMACSSWD,
+  IX86_BUILTIN_PMACSWD,
+  IX86_BUILTIN_PMACSSDD,
+  IX86_BUILTIN_PMACSDD,
+  IX86_BUILTIN_PMACSSDQL,
+  IX86_BUILTIN_PMACSSDQH,
+  IX86_BUILTIN_PMACSDQL,
+  IX86_BUILTIN_PMACSDQH,
+  IX86_BUILTIN_PMADCSSWD,
+  IX86_BUILTIN_PMADCSWD,
+  IX86_BUILTIN_PHADDBW,
+  IX86_BUILTIN_PHADDBD,
+  IX86_BUILTIN_PHADDBQ,
+  IX86_BUILTIN_PHADDWD,
+  IX86_BUILTIN_PHADDWQ,
+  IX86_BUILTIN_PHADDDQ,
+  IX86_BUILTIN_PHADDUBW,
+  IX86_BUILTIN_PHADDUBD,
+  IX86_BUILTIN_PHADDUBQ,
+  IX86_BUILTIN_PHADDUWD,
+  IX86_BUILTIN_PHADDUWQ,
+  IX86_BUILTIN_PHADDUDQ,
+  IX86_BUILTIN_PHSUBBW,
+  IX86_BUILTIN_PHSUBWD,
+  IX86_BUILTIN_PHSUBDQ,
+  IX86_BUILTIN_PROTB,
+  IX86_BUILTIN_PROTW,
+  IX86_BUILTIN_PROTD,
+  IX86_BUILTIN_PROTQ,
+  IX86_BUILTIN_PROTB_IMM,
+  IX86_BUILTIN_PROTW_IMM,
+  IX86_BUILTIN_PROTD_IMM,
+  IX86_BUILTIN_PROTQ_IMM,
+  IX86_BUILTIN_PSHLB,
+  IX86_BUILTIN_PSHLW,
+  IX86_BUILTIN_PSHLD,
+  IX86_BUILTIN_PSHLQ,
+  IX86_BUILTIN_PSHAB,
+  IX86_BUILTIN_PSHAW,
+  IX86_BUILTIN_PSHAD,
+  IX86_BUILTIN_PSHAQ,
+  IX86_BUILTIN_FRCZSS,
+  IX86_BUILTIN_FRCZSD,
+  IX86_BUILTIN_FRCZPS,
+  IX86_BUILTIN_FRCZPD,
+  IX86_BUILTIN_CVTPH2PS,
+  IX86_BUILTIN_CVTPS2PH,
+
+  IX86_BUILTIN_COMEQSS,
+  IX86_BUILTIN_COMNESS,
+  IX86_BUILTIN_COMLTSS,
+  IX86_BUILTIN_COMLESS,
+  IX86_BUILTIN_COMGTSS,
+  IX86_BUILTIN_COMGESS,
+  IX86_BUILTIN_COMUEQSS,
+  IX86_BUILTIN_COMUNESS,
+  IX86_BUILTIN_COMULTSS,
+  IX86_BUILTIN_COMULESS,
+  IX86_BUILTIN_COMUGTSS,
+  IX86_BUILTIN_COMUGESS,
+  IX86_BUILTIN_COMORDSS,
+  IX86_BUILTIN_COMUNORDSS,
+  IX86_BUILTIN_COMFALSESS,
+  IX86_BUILTIN_COMTRUESS,
+
+  IX86_BUILTIN_COMEQSD,
+  IX86_BUILTIN_COMNESD,
+  IX86_BUILTIN_COMLTSD,
+  IX86_BUILTIN_COMLESD,
+  IX86_BUILTIN_COMGTSD,
+  IX86_BUILTIN_COMGESD,
+  IX86_BUILTIN_COMUEQSD,
+  IX86_BUILTIN_COMUNESD,
+  IX86_BUILTIN_COMULTSD,
+  IX86_BUILTIN_COMULESD,
+  IX86_BUILTIN_COMUGTSD,
+  IX86_BUILTIN_COMUGESD,
+  IX86_BUILTIN_COMORDSD,
+  IX86_BUILTIN_COMUNORDSD,
+  IX86_BUILTIN_COMFALSESD,
+  IX86_BUILTIN_COMTRUESD,
+
+  IX86_BUILTIN_COMEQPS,
+  IX86_BUILTIN_COMNEPS,
+  IX86_BUILTIN_COMLTPS,
+  IX86_BUILTIN_COMLEPS,
+  IX86_BUILTIN_COMGTPS,
+  IX86_BUILTIN_COMGEPS,
+  IX86_BUILTIN_COMUEQPS,
+  IX86_BUILTIN_COMUNEPS,
+  IX86_BUILTIN_COMULTPS,
+  IX86_BUILTIN_COMULEPS,
+  IX86_BUILTIN_COMUGTPS,
+  IX86_BUILTIN_COMUGEPS,
+  IX86_BUILTIN_COMORDPS,
+  IX86_BUILTIN_COMUNORDPS,
+  IX86_BUILTIN_COMFALSEPS,
+  IX86_BUILTIN_COMTRUEPS,
+
+  IX86_BUILTIN_COMEQPD,
+  IX86_BUILTIN_COMNEPD,
+  IX86_BUILTIN_COMLTPD,
+  IX86_BUILTIN_COMLEPD,
+  IX86_BUILTIN_COMGTPD,
+  IX86_BUILTIN_COMGEPD,
+  IX86_BUILTIN_COMUEQPD,
+  IX86_BUILTIN_COMUNEPD,
+  IX86_BUILTIN_COMULTPD,
+  IX86_BUILTIN_COMULEPD,
+  IX86_BUILTIN_COMUGTPD,
+  IX86_BUILTIN_COMUGEPD,
+  IX86_BUILTIN_COMORDPD,
+  IX86_BUILTIN_COMUNORDPD,
+  IX86_BUILTIN_COMFALSEPD,
+  IX86_BUILTIN_COMTRUEPD,
+
+  IX86_BUILTIN_PCOMEQUB,
+  IX86_BUILTIN_PCOMNEUB,
+  IX86_BUILTIN_PCOMLTUB,
+  IX86_BUILTIN_PCOMLEUB,
+  IX86_BUILTIN_PCOMGTUB,
+  IX86_BUILTIN_PCOMGEUB,
+  IX86_BUILTIN_PCOMFALSEUB,
+  IX86_BUILTIN_PCOMTRUEUB,
+  IX86_BUILTIN_PCOMEQUW,
+  IX86_BUILTIN_PCOMNEUW,
+  IX86_BUILTIN_PCOMLTUW,
+  IX86_BUILTIN_PCOMLEUW,
+  IX86_BUILTIN_PCOMGTUW,
+  IX86_BUILTIN_PCOMGEUW,
+  IX86_BUILTIN_PCOMFALSEUW,
+  IX86_BUILTIN_PCOMTRUEUW,
+  IX86_BUILTIN_PCOMEQUD,
+  IX86_BUILTIN_PCOMNEUD,
+  IX86_BUILTIN_PCOMLTUD,
+  IX86_BUILTIN_PCOMLEUD,
+  IX86_BUILTIN_PCOMGTUD,
+  IX86_BUILTIN_PCOMGEUD,
+  IX86_BUILTIN_PCOMFALSEUD,
+  IX86_BUILTIN_PCOMTRUEUD,
+  IX86_BUILTIN_PCOMEQUQ,
+  IX86_BUILTIN_PCOMNEUQ,
+  IX86_BUILTIN_PCOMLTUQ,
+  IX86_BUILTIN_PCOMLEUQ,
+  IX86_BUILTIN_PCOMGTUQ,
+  IX86_BUILTIN_PCOMGEUQ,
+  IX86_BUILTIN_PCOMFALSEUQ,
+  IX86_BUILTIN_PCOMTRUEUQ,
+
+  IX86_BUILTIN_PCOMEQB,
+  IX86_BUILTIN_PCOMNEB,
+  IX86_BUILTIN_PCOMLTB,
+  IX86_BUILTIN_PCOMLEB,
+  IX86_BUILTIN_PCOMGTB,
+  IX86_BUILTIN_PCOMGEB,
+  IX86_BUILTIN_PCOMFALSEB,
+  IX86_BUILTIN_PCOMTRUEB,
+  IX86_BUILTIN_PCOMEQW,
+  IX86_BUILTIN_PCOMNEW,
+  IX86_BUILTIN_PCOMLTW,
+  IX86_BUILTIN_PCOMLEW,
+  IX86_BUILTIN_PCOMGTW,
+  IX86_BUILTIN_PCOMGEW,
+  IX86_BUILTIN_PCOMFALSEW,
+  IX86_BUILTIN_PCOMTRUEW,
+  IX86_BUILTIN_PCOMEQD,
+  IX86_BUILTIN_PCOMNED,
+  IX86_BUILTIN_PCOMLTD,
+  IX86_BUILTIN_PCOMLED,
+  IX86_BUILTIN_PCOMGTD,
+  IX86_BUILTIN_PCOMGED,
+  IX86_BUILTIN_PCOMFALSED,
+  IX86_BUILTIN_PCOMTRUED,
+  IX86_BUILTIN_PCOMEQQ,
+  IX86_BUILTIN_PCOMNEQ,
+  IX86_BUILTIN_PCOMLTQ,
+  IX86_BUILTIN_PCOMLEQ,
+  IX86_BUILTIN_PCOMGTQ,
+  IX86_BUILTIN_PCOMGEQ,
+  IX86_BUILTIN_PCOMFALSEQ,
+  IX86_BUILTIN_PCOMTRUEQ,
+
   IX86_BUILTIN_MAX
 };
 
@@ -14663,6 +15128,22 @@ static const struct builtin_description 
   { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdneq", IX86_BUILTIN_UCOMINEQSD, LTGT, 0 },
 };
 
+static const struct builtin_description bdesc_ptest[] =
+{
+  /* SSE4.1/SSE5 */
+  { MASK_SSE5, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestz128", IX86_BUILTIN_PTESTZ, EQ, 0 },
+  { MASK_SSE5, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestc128", IX86_BUILTIN_PTESTC, LTU, 0 },
+  { MASK_SSE5, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestnzc128", IX86_BUILTIN_PTESTNZC, GTU, 0 },
+};
+
+/* SSE builtins with 3 arguments and the last argument must be an immediate or xmm0.  */
+static const struct builtin_description bdesc_sse_3arg[] =
+{
+  /* SSE4.1/SSE5 */
+  { MASK_SSE5, CODE_FOR_sse4_1_roundsd, 0, IX86_BUILTIN_ROUNDSD, UNKNOWN, 0 },
+  { MASK_SSE5, CODE_FOR_sse4_1_roundss, 0, IX86_BUILTIN_ROUNDSS, UNKNOWN, 0 },
+};
+
 static const struct builtin_description bdesc_2arg[] =
 {
   /* SSE */
@@ -15015,7 +15496,300 @@ static const struct builtin_description 
   { MASK_SSSE3, CODE_FOR_ssse3_pabsv8hi2, "__builtin_ia32_pabsw128", IX86_BUILTIN_PABSW128, 0, 0 },
   { MASK_SSSE3, CODE_FOR_ssse3_pabsv4hi2, "__builtin_ia32_pabsw", IX86_BUILTIN_PABSW, 0, 0 },
   { MASK_SSSE3, CODE_FOR_ssse3_pabsv4si2, "__builtin_ia32_pabsd128", IX86_BUILTIN_PABSD128, 0, 0 },
-  { MASK_SSSE3, CODE_FOR_ssse3_pabsv2si2, "__builtin_ia32_pabsd", IX86_BUILTIN_PABSD, 0, 0 }
+  { MASK_SSSE3, CODE_FOR_ssse3_pabsv2si2, "__builtin_ia32_pabsd", IX86_BUILTIN_PABSD, 0, 0 },
+
+  /* Fake 1 arg builtins with a constant smaller than 8 bits as the 2nd arg.  */
+  { MASK_SSE5, CODE_FOR_sse4_1_roundpd, 0, IX86_BUILTIN_ROUNDPD, 0, 0 },
+  { MASK_SSE5, CODE_FOR_sse4_1_roundps, 0, IX86_BUILTIN_ROUNDPS, 0, 0 }
+};
+
+/* SSE5 */
+enum multi_arg_type {
+  MULTI_ARG_UNKNOWN,
+  MULTI_ARG_3_SF,
+  MULTI_ARG_3_DF,
+  MULTI_ARG_3_DI,
+  MULTI_ARG_3_SI,
+  MULTI_ARG_3_SI_DI,
+  MULTI_ARG_3_HI,
+  MULTI_ARG_3_HI_SI,
+  MULTI_ARG_3_QI,
+  MULTI_ARG_3_PERMPS,
+  MULTI_ARG_3_PERMPD,
+  MULTI_ARG_2_SF,
+  MULTI_ARG_2_DF,
+  MULTI_ARG_2_DI,
+  MULTI_ARG_2_SI,
+  MULTI_ARG_2_HI,
+  MULTI_ARG_2_QI,
+  MULTI_ARG_2_DI_IMM,
+  MULTI_ARG_2_SI_IMM,
+  MULTI_ARG_2_HI_IMM,
+  MULTI_ARG_2_QI_IMM,
+  MULTI_ARG_2_SF_CMP,
+  MULTI_ARG_2_DF_CMP,
+  MULTI_ARG_2_DI_CMP,
+  MULTI_ARG_2_SI_CMP,
+  MULTI_ARG_2_HI_CMP,
+  MULTI_ARG_2_QI_CMP,
+  MULTI_ARG_2_DI_TF,
+  MULTI_ARG_2_SI_TF,
+  MULTI_ARG_2_HI_TF,
+  MULTI_ARG_2_QI_TF,
+  MULTI_ARG_2_SF_TF,
+  MULTI_ARG_2_DF_TF,
+  MULTI_ARG_1_SF,
+  MULTI_ARG_1_DF,
+  MULTI_ARG_1_DI,
+  MULTI_ARG_1_SI,
+  MULTI_ARG_1_HI,
+  MULTI_ARG_1_QI,
+  MULTI_ARG_1_SI_DI,
+  MULTI_ARG_1_HI_DI,
+  MULTI_ARG_1_HI_SI,
+  MULTI_ARG_1_QI_DI,
+  MULTI_ARG_1_QI_SI,
+  MULTI_ARG_1_QI_HI,
+  MULTI_ARG_1_PH2PS,
+  MULTI_ARG_1_PS2PH
+};
+
+static const struct builtin_description bdesc_multi_arg[] =
+{
+  { MASK_SSE5, CODE_FOR_sse5i_vmfmaddv4sf4,     "__builtin_ia32_fmaddss",    IX86_BUILTIN_FMADDSS,    0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfmaddv2df4,     "__builtin_ia32_fmaddsd",    IX86_BUILTIN_FMADDSD,    0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_fmaddv4sf4,       "__builtin_ia32_fmaddps",    IX86_BUILTIN_FMADDPS,    0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_fmaddv2df4,       "__builtin_ia32_fmaddpd",    IX86_BUILTIN_FMADDPD,    0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfmsubv4sf4,     "__builtin_ia32_fmsubss",    IX86_BUILTIN_FMSUBSS,    0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfmsubv2df4,     "__builtin_ia32_fmsubsd",    IX86_BUILTIN_FMSUBSD,    0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_fmsubv4sf4,       "__builtin_ia32_fmsubps",    IX86_BUILTIN_FMSUBPS,    0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_fmsubv2df4,       "__builtin_ia32_fmsubpd",    IX86_BUILTIN_FMSUBPD,    0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfnmaddv4sf4,    "__builtin_ia32_fnmaddss",   IX86_BUILTIN_FNMADDSS,   0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfnmaddv2df4,    "__builtin_ia32_fnmaddsd",   IX86_BUILTIN_FNMADDSD,   0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_fnmaddv4sf4,      "__builtin_ia32_fnmaddps",   IX86_BUILTIN_FNMADDPS,   0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_fnmaddv2df4,      "__builtin_ia32_fnmaddpd",   IX86_BUILTIN_FNMADDPD,   0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfnmsubv4sf4,    "__builtin_ia32_fnmsubss",   IX86_BUILTIN_FNMSUBSS,   0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_vmfnmsubv2df4,    "__builtin_ia32_fnmsubsd",   IX86_BUILTIN_FNMSUBSD,   0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5i_fnmsubv4sf4,      "__builtin_ia32_fnmsubps",   IX86_BUILTIN_FNMSUBPS,   0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5i_fnmsubv2df4,      "__builtin_ia32_fnmsubpd",   IX86_BUILTIN_FNMSUBPD,   0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v2di,        "__builtin_ia32_pcmov",      IX86_BUILTIN_PCMOV_V2DI, 0,            (int)MULTI_ARG_3_DI },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v2di,        "__builtin_ia32_pcmov_v2di", IX86_BUILTIN_PCMOV_V2DI, 0,            (int)MULTI_ARG_3_DI },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v4si,        "__builtin_ia32_pcmov_v4si", IX86_BUILTIN_PCMOV_V4SI, 0,            (int)MULTI_ARG_3_SI },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v8hi,        "__builtin_ia32_pcmov_v8hi", IX86_BUILTIN_PCMOV_V8HI, 0,            (int)MULTI_ARG_3_HI },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v16qi,       "__builtin_ia32_pcmov_v16qi",IX86_BUILTIN_PCMOV_V16QI,0,            (int)MULTI_ARG_3_QI },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v2df,        "__builtin_ia32_pcmov_v2df", IX86_BUILTIN_PCMOV_V2DF, 0,            (int)MULTI_ARG_3_DF },
+  { MASK_SSE5, CODE_FOR_sse5_pcmov_v4sf,        "__builtin_ia32_pcmov_v4sf", IX86_BUILTIN_PCMOV_V4SF, 0,            (int)MULTI_ARG_3_SF },
+  { MASK_SSE5, CODE_FOR_sse5_pperm,             "__builtin_ia32_pperm",      IX86_BUILTIN_PPERM,      0,            (int)MULTI_ARG_3_QI },
+  { MASK_SSE5, CODE_FOR_sse5_permv4sf,          "__builtin_ia32_permps",     IX86_BUILTIN_PERMPS,     0,            (int)MULTI_ARG_3_PERMPS },
+  { MASK_SSE5, CODE_FOR_sse5_permv2df,          "__builtin_ia32_permpd",     IX86_BUILTIN_PERMPD,     0,            (int)MULTI_ARG_3_PERMPD },
+  { MASK_SSE5, CODE_FOR_sse5_pmacssww,          "__builtin_ia32_pmacssww",   IX86_BUILTIN_PMACSSWW,   0,            (int)MULTI_ARG_3_HI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacsww,           "__builtin_ia32_pmacsww",    IX86_BUILTIN_PMACSWW,    0,            (int)MULTI_ARG_3_HI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacsswd,          "__builtin_ia32_pmacsswd",   IX86_BUILTIN_PMACSSWD,   0,            (int)MULTI_ARG_3_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacswd,           "__builtin_ia32_pmacswd",    IX86_BUILTIN_PMACSWD,    0,            (int)MULTI_ARG_3_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacssdd,          "__builtin_ia32_pmacssdd",   IX86_BUILTIN_PMACSSDD,   0,            (int)MULTI_ARG_3_SI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacsdd,           "__builtin_ia32_pmacsdd",    IX86_BUILTIN_PMACSDD,    0,            (int)MULTI_ARG_3_SI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacssdql,         "__builtin_ia32_pmacssdql",  IX86_BUILTIN_PMACSSDQL,  0,            (int)MULTI_ARG_3_SI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacssdqh,         "__builtin_ia32_pmacssdqh",  IX86_BUILTIN_PMACSSDQH,  0,            (int)MULTI_ARG_3_SI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacsdql,          "__builtin_ia32_pmacsdql",   IX86_BUILTIN_PMACSDQL,   0,            (int)MULTI_ARG_3_SI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_pmacsdqh,          "__builtin_ia32_pmacsdqh",   IX86_BUILTIN_PMACSDQH,   0,            (int)MULTI_ARG_3_SI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_pmadcsswd,         "__builtin_ia32_pmadcsswd",  IX86_BUILTIN_PMADCSSWD,  0,            (int)MULTI_ARG_3_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_pmadcswd,          "__builtin_ia32_pmadcswd",   IX86_BUILTIN_PMADCSWD,   0,            (int)MULTI_ARG_3_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_rotlv2di3,         "__builtin_ia32_protq",      IX86_BUILTIN_PROTQ,      0,            (int)MULTI_ARG_2_DI },
+  { MASK_SSE5, CODE_FOR_sse5_rotlv4si3,         "__builtin_ia32_protd",      IX86_BUILTIN_PROTD,      0,            (int)MULTI_ARG_2_SI },
+  { MASK_SSE5, CODE_FOR_sse5_rotlv8hi3,         "__builtin_ia32_protw",      IX86_BUILTIN_PROTW,      0,            (int)MULTI_ARG_2_HI },
+  { MASK_SSE5, CODE_FOR_sse5_rotlv16qi3,        "__builtin_ia32_protb",      IX86_BUILTIN_PROTB,      0,            (int)MULTI_ARG_2_QI },
+  { MASK_SSE5, CODE_FOR_rotlv2di3,              "__builtin_ia32_protqi",     IX86_BUILTIN_PROTQ_IMM,  0,            (int)MULTI_ARG_2_DI_IMM },
+  { MASK_SSE5, CODE_FOR_rotlv4si3,              "__builtin_ia32_protdi",     IX86_BUILTIN_PROTD_IMM,  0,            (int)MULTI_ARG_2_SI_IMM },
+  { MASK_SSE5, CODE_FOR_rotlv8hi3,              "__builtin_ia32_protwi",     IX86_BUILTIN_PROTW_IMM,  0,            (int)MULTI_ARG_2_HI_IMM },
+  { MASK_SSE5, CODE_FOR_rotlv16qi3,             "__builtin_ia32_protbi",     IX86_BUILTIN_PROTB_IMM,  0,            (int)MULTI_ARG_2_QI_IMM },
+  { MASK_SSE5, CODE_FOR_sse5_ashlv2di3,         "__builtin_ia32_pshaq",      IX86_BUILTIN_PSHAQ,      0,            (int)MULTI_ARG_2_DI },
+  { MASK_SSE5, CODE_FOR_sse5_ashlv4si3,         "__builtin_ia32_pshad",      IX86_BUILTIN_PSHAD,      0,            (int)MULTI_ARG_2_SI },
+  { MASK_SSE5, CODE_FOR_sse5_ashlv8hi3,         "__builtin_ia32_pshaw",      IX86_BUILTIN_PSHAW,      0,            (int)MULTI_ARG_2_HI },
+  { MASK_SSE5, CODE_FOR_sse5_ashlv16qi3,        "__builtin_ia32_pshab",      IX86_BUILTIN_PSHAB,      0,            (int)MULTI_ARG_2_QI },
+  { MASK_SSE5, CODE_FOR_sse5_lshlv2di3,         "__builtin_ia32_pshlq",      IX86_BUILTIN_PSHLQ,      0,            (int)MULTI_ARG_2_DI },
+  { MASK_SSE5, CODE_FOR_sse5_lshlv4si3,         "__builtin_ia32_pshld",      IX86_BUILTIN_PSHLD,      0,            (int)MULTI_ARG_2_SI },
+  { MASK_SSE5, CODE_FOR_sse5_lshlv8hi3,         "__builtin_ia32_pshlw",      IX86_BUILTIN_PSHLW,      0,            (int)MULTI_ARG_2_HI },
+  { MASK_SSE5, CODE_FOR_sse5_lshlv16qi3,        "__builtin_ia32_pshlb",      IX86_BUILTIN_PSHLB,      0,            (int)MULTI_ARG_2_QI },
+  { MASK_SSE5, CODE_FOR_sse5_vmfrczv4sf2,       "__builtin_ia32_frczss",     IX86_BUILTIN_FRCZSS,     0,            (int)MULTI_ARG_2_SF },
+  { MASK_SSE5, CODE_FOR_sse5_vmfrczv2df2,       "__builtin_ia32_frczsd",     IX86_BUILTIN_FRCZSD,     0,            (int)MULTI_ARG_2_DF },
+  { MASK_SSE5, CODE_FOR_sse5_frczv4sf2,         "__builtin_ia32_frczps",     IX86_BUILTIN_FRCZPS,     0,            (int)MULTI_ARG_1_SF },
+  { MASK_SSE5, CODE_FOR_sse5_frczv2df2,         "__builtin_ia32_frczpd",     IX86_BUILTIN_FRCZPD,     0,            (int)MULTI_ARG_1_DF },
+  { MASK_SSE5, CODE_FOR_sse5_cvtph2ps,          "__builtin_ia32_cvtph2ps",   IX86_BUILTIN_CVTPH2PS,   0,            (int)MULTI_ARG_1_PH2PS },
+  { MASK_SSE5, CODE_FOR_sse5_cvtps2ph,          "__builtin_ia32_cvtps2ph",   IX86_BUILTIN_CVTPS2PH,   0,            (int)MULTI_ARG_1_PS2PH },
+  { MASK_SSE5, CODE_FOR_sse5_phaddbw,           "__builtin_ia32_phaddbw",    IX86_BUILTIN_PHADDBW,    0,            (int)MULTI_ARG_1_QI_HI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddbd,           "__builtin_ia32_phaddbd",    IX86_BUILTIN_PHADDBD,    0,            (int)MULTI_ARG_1_QI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddbq,           "__builtin_ia32_phaddbq",    IX86_BUILTIN_PHADDBQ,    0,            (int)MULTI_ARG_1_QI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddwd,           "__builtin_ia32_phaddwd",    IX86_BUILTIN_PHADDWD,    0,            (int)MULTI_ARG_1_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddwq,           "__builtin_ia32_phaddwq",    IX86_BUILTIN_PHADDWQ,    0,            (int)MULTI_ARG_1_HI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_phadddq,           "__builtin_ia32_phadddq",    IX86_BUILTIN_PHADDDQ,    0,            (int)MULTI_ARG_1_SI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddubw,          "__builtin_ia32_phaddubw",   IX86_BUILTIN_PHADDUBW,   0,            (int)MULTI_ARG_1_QI_HI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddubd,          "__builtin_ia32_phaddubd",   IX86_BUILTIN_PHADDUBD,   0,            (int)MULTI_ARG_1_QI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddubq,          "__builtin_ia32_phaddubq",   IX86_BUILTIN_PHADDUBQ,   0,            (int)MULTI_ARG_1_QI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_phadduwd,          "__builtin_ia32_phadduwd",   IX86_BUILTIN_PHADDUWD,   0,            (int)MULTI_ARG_1_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_phadduwq,          "__builtin_ia32_phadduwq",   IX86_BUILTIN_PHADDUWQ,   0,            (int)MULTI_ARG_1_HI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_phaddudq,          "__builtin_ia32_phaddudq",   IX86_BUILTIN_PHADDUDQ,   0,            (int)MULTI_ARG_1_SI_DI },
+  { MASK_SSE5, CODE_FOR_sse5_phsubbw,           "__builtin_ia32_phsubbw",    IX86_BUILTIN_PHSUBBW,    0,            (int)MULTI_ARG_1_QI_HI },
+  { MASK_SSE5, CODE_FOR_sse5_phsubwd,           "__builtin_ia32_phsubwd",    IX86_BUILTIN_PHSUBWD,    0,            (int)MULTI_ARG_1_HI_SI },
+  { MASK_SSE5, CODE_FOR_sse5_phsubdq,           "__builtin_ia32_phsubdq",    IX86_BUILTIN_PHSUBDQ,    0,            (int)MULTI_ARG_1_SI_DI },
+
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comeqss",    IX86_BUILTIN_COMEQSS,    EQ,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comness",    IX86_BUILTIN_COMNESS,    NE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comneqss",   IX86_BUILTIN_COMNESS,    NE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comltss",    IX86_BUILTIN_COMLTSS,    LT,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comless",    IX86_BUILTIN_COMLESS,    LE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comgtss",    IX86_BUILTIN_COMGTSS,    GT,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comgess",    IX86_BUILTIN_COMGESS,    GE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comueqss",   IX86_BUILTIN_COMUEQSS,   UNEQ,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comuness",   IX86_BUILTIN_COMUNESS,   LTGT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comuneqss",  IX86_BUILTIN_COMUNESS,   LTGT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comunltss",  IX86_BUILTIN_COMULTSS,   UNLT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comunless",  IX86_BUILTIN_COMULESS,   UNLE,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comungtss",  IX86_BUILTIN_COMUGTSS,   UNGT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comungess",  IX86_BUILTIN_COMUGESS,   UNGE,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comordss",   IX86_BUILTIN_COMORDSS,   ORDERED,      (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv4sf3,    "__builtin_ia32_comunordss", IX86_BUILTIN_COMUNORDSS, UNORDERED,    (int)MULTI_ARG_2_SF_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comeqsd",    IX86_BUILTIN_COMEQSD,    EQ,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comnesd",    IX86_BUILTIN_COMNESD,    NE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comneqsd",   IX86_BUILTIN_COMNESD,    NE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comltsd",    IX86_BUILTIN_COMLTSD,    LT,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comlesd",    IX86_BUILTIN_COMLESD,    LE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comgtsd",    IX86_BUILTIN_COMGTSD,    GT,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comgesd",    IX86_BUILTIN_COMGESD,    GE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comueqsd",   IX86_BUILTIN_COMUEQSD,   UNEQ,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comunesd",   IX86_BUILTIN_COMUNESD,   LTGT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comuneqsd",  IX86_BUILTIN_COMUNESD,   LTGT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comunltsd",  IX86_BUILTIN_COMULTSD,   UNLT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comunlesd",  IX86_BUILTIN_COMULESD,   UNLE,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comungtsd",  IX86_BUILTIN_COMUGTSD,   UNGT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comungesd",  IX86_BUILTIN_COMUGESD,   UNGE,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comordsd",   IX86_BUILTIN_COMORDSD,   ORDERED,      (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_vmmaskcmpv2df3,    "__builtin_ia32_comunordsd", IX86_BUILTIN_COMUNORDSD, UNORDERED,    (int)MULTI_ARG_2_DF_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comeqps",    IX86_BUILTIN_COMEQPS,    EQ,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comneps",    IX86_BUILTIN_COMNEPS,    NE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comneqps",   IX86_BUILTIN_COMNEPS,    NE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comltps",    IX86_BUILTIN_COMLTPS,    LT,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comleps",    IX86_BUILTIN_COMLEPS,    LE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comgtps",    IX86_BUILTIN_COMGTPS,    GT,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comgeps",    IX86_BUILTIN_COMGEPS,    GE,           (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comueqps",   IX86_BUILTIN_COMUEQPS,   UNEQ,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comuneps",   IX86_BUILTIN_COMUNEPS,   LTGT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comuneqps",  IX86_BUILTIN_COMUNEPS,   LTGT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comunltps",  IX86_BUILTIN_COMULTPS,   UNLT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comunleps",  IX86_BUILTIN_COMULEPS,   UNLE,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comungtps",  IX86_BUILTIN_COMUGTPS,   UNGT,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comungeps",  IX86_BUILTIN_COMUGEPS,   UNGE,         (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comordps",   IX86_BUILTIN_COMORDPS,   ORDERED,      (int)MULTI_ARG_2_SF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4sf3,      "__builtin_ia32_comunordps", IX86_BUILTIN_COMUNORDPS, UNORDERED,    (int)MULTI_ARG_2_SF_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comeqpd",    IX86_BUILTIN_COMEQPD,    EQ,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comnepd",    IX86_BUILTIN_COMNEPD,    NE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comneqpd",   IX86_BUILTIN_COMNEPD,    NE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comltpd",    IX86_BUILTIN_COMLTPD,    LT,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comlepd",    IX86_BUILTIN_COMLEPD,    LE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comgtpd",    IX86_BUILTIN_COMGTPD,    GT,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comgepd",    IX86_BUILTIN_COMGEPD,    GE,           (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comueqpd",   IX86_BUILTIN_COMUEQPD,   UNEQ,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comunepd",   IX86_BUILTIN_COMUNEPD,   LTGT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comuneqpd",  IX86_BUILTIN_COMUNEPD,   LTGT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comunltpd",  IX86_BUILTIN_COMULTPD,   UNLT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comunlepd",  IX86_BUILTIN_COMULEPD,   UNLE,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comungtpd",  IX86_BUILTIN_COMUGTPD,   UNGT,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comungepd",  IX86_BUILTIN_COMUGEPD,   UNGE,         (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comordpd",   IX86_BUILTIN_COMORDPD,   ORDERED,      (int)MULTI_ARG_2_DF_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2df3,      "__builtin_ia32_comunordpd", IX86_BUILTIN_COMUNORDPD, UNORDERED,    (int)MULTI_ARG_2_DF_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomeqb",    IX86_BUILTIN_PCOMEQB,    EQ,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomneb",    IX86_BUILTIN_PCOMNEB,    NE,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomneqb",   IX86_BUILTIN_PCOMNEB,    NE,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomltb",    IX86_BUILTIN_PCOMLTB,    LT,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomleb",    IX86_BUILTIN_PCOMLEB,    LE,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomgtb",    IX86_BUILTIN_PCOMGTB,    GT,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv16qi3,     "__builtin_ia32_pcomgeb",    IX86_BUILTIN_PCOMGEB,    GE,           (int)MULTI_ARG_2_QI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomeqw",    IX86_BUILTIN_PCOMEQW,    EQ,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomnew",    IX86_BUILTIN_PCOMNEW,    NE,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomneqw",   IX86_BUILTIN_PCOMNEW,    NE,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomltw",    IX86_BUILTIN_PCOMLTW,    LT,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomlew",    IX86_BUILTIN_PCOMLEW,    LE,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomgtw",    IX86_BUILTIN_PCOMGTW,    GT,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv8hi3,      "__builtin_ia32_pcomgew",    IX86_BUILTIN_PCOMGEW,    GE,           (int)MULTI_ARG_2_HI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomeqd",    IX86_BUILTIN_PCOMEQD,    EQ,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomned",    IX86_BUILTIN_PCOMNED,    NE,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomneqd",   IX86_BUILTIN_PCOMNED,    NE,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomltd",    IX86_BUILTIN_PCOMLTD,    LT,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomled",    IX86_BUILTIN_PCOMLED,    LE,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomgtd",    IX86_BUILTIN_PCOMGTD,    GT,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv4si3,      "__builtin_ia32_pcomged",    IX86_BUILTIN_PCOMGED,    GE,           (int)MULTI_ARG_2_SI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomeqq",    IX86_BUILTIN_PCOMEQQ,    EQ,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomneq",    IX86_BUILTIN_PCOMNEQ,    NE,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomneqq",   IX86_BUILTIN_PCOMNEQ,    NE,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomltq",    IX86_BUILTIN_PCOMLTQ,    LT,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomleq",    IX86_BUILTIN_PCOMLEQ,    LE,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomgtq",    IX86_BUILTIN_PCOMGTQ,    GT,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmpv2di3,      "__builtin_ia32_pcomgeq",    IX86_BUILTIN_PCOMGEQ,    GE,           (int)MULTI_ARG_2_DI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v16qi3,"__builtin_ia32_pcomequb",   IX86_BUILTIN_PCOMEQUB,   EQ,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v16qi3,"__builtin_ia32_pcomneub",   IX86_BUILTIN_PCOMNEUB,   NE,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v16qi3,"__builtin_ia32_pcomnequb",  IX86_BUILTIN_PCOMNEUB,   NE,           (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv16qi3, "__builtin_ia32_pcomltub",   IX86_BUILTIN_PCOMLTUB,   LTU,          (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv16qi3, "__builtin_ia32_pcomleub",   IX86_BUILTIN_PCOMLEUB,   LEU,          (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv16qi3, "__builtin_ia32_pcomgtub",   IX86_BUILTIN_PCOMGTUB,   GTU,          (int)MULTI_ARG_2_QI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv16qi3, "__builtin_ia32_pcomgeub",   IX86_BUILTIN_PCOMGEUB,   GEU,          (int)MULTI_ARG_2_QI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v8hi3, "__builtin_ia32_pcomequw",   IX86_BUILTIN_PCOMEQUW,   EQ,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v8hi3, "__builtin_ia32_pcomneuw",   IX86_BUILTIN_PCOMNEUW,   NE,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v8hi3, "__builtin_ia32_pcomnequw",  IX86_BUILTIN_PCOMNEUW,   NE,           (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv8hi3,  "__builtin_ia32_pcomltuw",   IX86_BUILTIN_PCOMLTUW,   LTU,          (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv8hi3,  "__builtin_ia32_pcomleuw",   IX86_BUILTIN_PCOMLEUW,   LEU,          (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv8hi3,  "__builtin_ia32_pcomgtuw",   IX86_BUILTIN_PCOMGTUW,   GTU,          (int)MULTI_ARG_2_HI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv8hi3,  "__builtin_ia32_pcomgeuw",   IX86_BUILTIN_PCOMGEUW,   GEU,          (int)MULTI_ARG_2_HI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v4si3, "__builtin_ia32_pcomequd",   IX86_BUILTIN_PCOMEQUD,   EQ,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v4si3, "__builtin_ia32_pcomneud",   IX86_BUILTIN_PCOMNEUD,   NE,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v4si3, "__builtin_ia32_pcomnequd",  IX86_BUILTIN_PCOMNEUD,   NE,           (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv4si3,  "__builtin_ia32_pcomltud",   IX86_BUILTIN_PCOMLTUD,   LTU,          (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv4si3,  "__builtin_ia32_pcomleud",   IX86_BUILTIN_PCOMLEUD,   LEU,          (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv4si3,  "__builtin_ia32_pcomgtud",   IX86_BUILTIN_PCOMGTUD,   GTU,          (int)MULTI_ARG_2_SI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv4si3,  "__builtin_ia32_pcomgeud",   IX86_BUILTIN_PCOMGEUD,   GEU,          (int)MULTI_ARG_2_SI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v2di3, "__builtin_ia32_pcomequq",   IX86_BUILTIN_PCOMEQUQ,   EQ,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v2di3, "__builtin_ia32_pcomneuq",   IX86_BUILTIN_PCOMNEUQ,   NE,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_uns2v2di3, "__builtin_ia32_pcomnequq",  IX86_BUILTIN_PCOMNEUQ,   NE,           (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv2di3,  "__builtin_ia32_pcomltuq",   IX86_BUILTIN_PCOMLTUQ,   LTU,          (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv2di3,  "__builtin_ia32_pcomleuq",   IX86_BUILTIN_PCOMLEUQ,   LEU,          (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv2di3,  "__builtin_ia32_pcomgtuq",   IX86_BUILTIN_PCOMGTUQ,   GTU,          (int)MULTI_ARG_2_DI_CMP },
+  { MASK_SSE5, CODE_FOR_sse5_maskcmp_unsv2di3,  "__builtin_ia32_pcomgeuq",   IX86_BUILTIN_PCOMGEUQ,   GEU,          (int)MULTI_ARG_2_DI_CMP },
+
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv4sf3,       "__builtin_ia32_comfalsess", IX86_BUILTIN_COMFALSESS, COM_FALSE_S,  (int)MULTI_ARG_2_SF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv4sf3,       "__builtin_ia32_comtruess",  IX86_BUILTIN_COMTRUESS,  COM_TRUE_S,   (int)MULTI_ARG_2_SF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv4sf3,       "__builtin_ia32_comfalseps", IX86_BUILTIN_COMFALSEPS, COM_FALSE_P,  (int)MULTI_ARG_2_SF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv4sf3,       "__builtin_ia32_comtrueps",  IX86_BUILTIN_COMTRUEPS,  COM_TRUE_P,   (int)MULTI_ARG_2_SF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv2df3,       "__builtin_ia32_comfalsesd", IX86_BUILTIN_COMFALSESD, COM_FALSE_S,  (int)MULTI_ARG_2_DF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv2df3,       "__builtin_ia32_comtruesd",  IX86_BUILTIN_COMTRUESD,  COM_TRUE_S,   (int)MULTI_ARG_2_DF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv2df3,       "__builtin_ia32_comfalsepd", IX86_BUILTIN_COMFALSEPD, COM_FALSE_P,  (int)MULTI_ARG_2_DF_TF },
+  { MASK_SSE5, CODE_FOR_sse5_com_tfv2df3,       "__builtin_ia32_comtruepd",  IX86_BUILTIN_COMTRUEPD,  COM_TRUE_P,   (int)MULTI_ARG_2_DF_TF },
+
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv16qi3,     "__builtin_ia32_pcomfalseb", IX86_BUILTIN_PCOMFALSEB, PCOM_FALSE,   (int)MULTI_ARG_2_QI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv8hi3,      "__builtin_ia32_pcomfalsew", IX86_BUILTIN_PCOMFALSEW, PCOM_FALSE,   (int)MULTI_ARG_2_HI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv4si3,      "__builtin_ia32_pcomfalsed", IX86_BUILTIN_PCOMFALSED, PCOM_FALSE,   (int)MULTI_ARG_2_SI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv2di3,      "__builtin_ia32_pcomfalseq", IX86_BUILTIN_PCOMFALSEQ, PCOM_FALSE,   (int)MULTI_ARG_2_DI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv16qi3,     "__builtin_ia32_pcomfalseub",IX86_BUILTIN_PCOMFALSEUB,PCOM_FALSE,   (int)MULTI_ARG_2_QI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv8hi3,      "__builtin_ia32_pcomfalseuw",IX86_BUILTIN_PCOMFALSEUW,PCOM_FALSE,   (int)MULTI_ARG_2_HI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv4si3,      "__builtin_ia32_pcomfalseud",IX86_BUILTIN_PCOMFALSEUD,PCOM_FALSE,   (int)MULTI_ARG_2_SI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv2di3,      "__builtin_ia32_pcomfalseuq",IX86_BUILTIN_PCOMFALSEUQ,PCOM_FALSE,   (int)MULTI_ARG_2_DI_TF },
+
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv16qi3,     "__builtin_ia32_pcomtrueb",  IX86_BUILTIN_PCOMTRUEB,  PCOM_TRUE,    (int)MULTI_ARG_2_QI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv8hi3,      "__builtin_ia32_pcomtruew",  IX86_BUILTIN_PCOMTRUEW,  PCOM_TRUE,    (int)MULTI_ARG_2_HI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv4si3,      "__builtin_ia32_pcomtrued",  IX86_BUILTIN_PCOMTRUED,  PCOM_TRUE,    (int)MULTI_ARG_2_SI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv2di3,      "__builtin_ia32_pcomtrueq",  IX86_BUILTIN_PCOMTRUEQ,  PCOM_TRUE,    (int)MULTI_ARG_2_DI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv16qi3,     "__builtin_ia32_pcomtrueub", IX86_BUILTIN_PCOMTRUEUB, PCOM_TRUE,    (int)MULTI_ARG_2_QI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv8hi3,      "__builtin_ia32_pcomtrueuw", IX86_BUILTIN_PCOMTRUEUW, PCOM_TRUE,    (int)MULTI_ARG_2_HI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv4si3,      "__builtin_ia32_pcomtrueud", IX86_BUILTIN_PCOMTRUEUD, PCOM_TRUE,    (int)MULTI_ARG_2_SI_TF },
+  { MASK_SSE5, CODE_FOR_sse5_pcom_tfv2di3,      "__builtin_ia32_pcomtrueuq", IX86_BUILTIN_PCOMTRUEUQ, PCOM_TRUE,    (int)MULTI_ARG_2_DI_TF },
 };
 
 static void
@@ -15332,6 +16106,137 @@ ix86_init_mmx_sse_builtins (void)
   tree v2di_ftype_v2di_v16qi
     = build_function_type_list (V2DI_type_node, V2DI_type_node, V16QI_type_node,
                                 NULL_TREE);
+  tree v2df_ftype_v2df_v2df_v2df
+    = build_function_type_list (V2DF_type_node,
+				V2DF_type_node, V2DF_type_node,
+				V2DF_type_node, NULL_TREE);
+  tree v4sf_ftype_v4sf_v4sf_v4sf
+    = build_function_type_list (V4SF_type_node,
+				V4SF_type_node, V4SF_type_node,
+				V4SF_type_node, NULL_TREE);
+  tree v8hi_ftype_v16qi
+    = build_function_type_list (V8HI_type_node, V16QI_type_node,
+				NULL_TREE);
+  tree v4si_ftype_v16qi
+    = build_function_type_list (V4SI_type_node, V16QI_type_node,
+				NULL_TREE);
+  tree v2di_ftype_v16qi
+    = build_function_type_list (V2DI_type_node, V16QI_type_node,
+				NULL_TREE);
+  tree v4si_ftype_v8hi
+    = build_function_type_list (V4SI_type_node, V8HI_type_node,
+				NULL_TREE);
+  tree v2di_ftype_v8hi
+    = build_function_type_list (V2DI_type_node, V8HI_type_node,
+				NULL_TREE);
+  tree v2di_ftype_v4si
+    = build_function_type_list (V2DI_type_node, V4SI_type_node,
+				NULL_TREE);
+  tree v16qi_ftype_v16qi_v16qi_int
+    = build_function_type_list (V16QI_type_node, V16QI_type_node,
+				V16QI_type_node, integer_type_node,
+				NULL_TREE);
+  tree v8hi_ftype_v8hi_v8hi_int
+    = build_function_type_list (V8HI_type_node, V8HI_type_node,
+				V8HI_type_node, integer_type_node,
+				NULL_TREE);
+  tree v4si_ftype_v4si_v4si_int
+    = build_function_type_list (V4SI_type_node, V4SI_type_node,
+				V4SI_type_node, integer_type_node,
+				NULL_TREE);
+  tree int_ftype_v2di_v2di
+    = build_function_type_list (integer_type_node,
+				V2DI_type_node, V2DI_type_node,
+				NULL_TREE);
+  tree v16qi_ftype_v16qi_v16qi_v16qi
+    = build_function_type_list (V16QI_type_node, V16QI_type_node,
+				V16QI_type_node, V16QI_type_node,
+				NULL_TREE);
+  /* SSE5 instructions */
+  tree v2di_ftype_v2di_v2di_v2di
+    = build_function_type_list (V2DI_type_node,
+				V2DI_type_node,
+				V2DI_type_node,
+				V2DI_type_node,
+				NULL_TREE);
+
+  tree v4si_ftype_v4si_v4si_v4si
+    = build_function_type_list (V4SI_type_node,
+				V4SI_type_node,
+				V4SI_type_node,
+				V4SI_type_node,
+				NULL_TREE);
+
+  tree v4si_ftype_v4si_v4si_v2di
+    = build_function_type_list (V4SI_type_node,
+				V4SI_type_node,
+				V4SI_type_node,
+				V2DI_type_node,
+				NULL_TREE);
+
+  tree v8hi_ftype_v8hi_v8hi_v8hi
+    = build_function_type_list (V8HI_type_node,
+				V8HI_type_node,
+				V8HI_type_node,
+				V8HI_type_node,
+				NULL_TREE);
+
+  tree v8hi_ftype_v8hi_v8hi_v4si
+    = build_function_type_list (V8HI_type_node,
+				V8HI_type_node,
+				V8HI_type_node,
+				V4SI_type_node,
+				NULL_TREE);
+
+  tree v2df_ftype_v2df_v2df_v16qi
+    = build_function_type_list (V2DF_type_node,
+				V2DF_type_node,
+				V2DF_type_node,
+				V16QI_type_node,
+				NULL_TREE);
+
+  tree v4sf_ftype_v4sf_v4sf_v16qi
+    = build_function_type_list (V4SF_type_node,
+				V4SF_type_node,
+				V4SF_type_node,
+				V16QI_type_node,
+				NULL_TREE);
+
+  tree v2di_ftype_v2di_si
+    = build_function_type_list (V2DI_type_node,
+				V2DI_type_node,
+				integer_type_node,
+				NULL_TREE);
+
+  tree v4si_ftype_v4si_si
+    = build_function_type_list (V4SI_type_node,
+				V4SI_type_node,
+				integer_type_node,
+				NULL_TREE);
+
+  tree v8hi_ftype_v8hi_si
+    = build_function_type_list (V8HI_type_node,
+				V8HI_type_node,
+				integer_type_node,
+				NULL_TREE);
+
+  tree v16qi_ftype_v16qi_si
+    = build_function_type_list (V16QI_type_node,
+				V16QI_type_node,
+				integer_type_node,
+				NULL_TREE);
+  tree v4sf_ftype_v4hi
+    = build_function_type_list (V4SF_type_node,
+				V4HI_type_node,
+				NULL_TREE);
+
+  tree v4hi_ftype_v4sf
+    = build_function_type_list (V4HI_type_node,
+				V4SF_type_node,
+				NULL_TREE);
+
+  tree v2di_ftype_v2di
+    = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE);
 
   tree float80_type;
   tree float128_type;
@@ -15358,6 +16263,48 @@ ix86_init_mmx_sse_builtins (void)
       (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
     }
 
+  /* Add all SSE builtins that are more or less simple operations on
+     three operands.  */
+  for (i = 0, d = bdesc_sse_3arg;
+       i < ARRAY_SIZE (bdesc_sse_3arg);
+       i++, d++)
+    {
+      /* Use one of the operands; the target can have a different mode for
+	 mask-generating compares.  */
+      enum machine_mode mode;
+      tree type;
+
+      if (d->name == 0)
+	continue;
+      mode = insn_data[d->icode].operand[1].mode;
+
+      switch (mode)
+	{
+	case V16QImode:
+	  type = v16qi_ftype_v16qi_v16qi_int;
+	  break;
+	case V8HImode:
+	  type = v8hi_ftype_v8hi_v8hi_int;
+	  break;
+	case V4SImode:
+	  type = v4si_ftype_v4si_v4si_int;
+	  break;
+	case V2DImode:
+	  type = v2di_ftype_v2di_v2di_int;
+	  break;
+	case V2DFmode:
+	  type = v2df_ftype_v2df_v2df_int;
+	  break;
+	case V4SFmode:
+	  type = v4sf_ftype_v4sf_v4sf_int;
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+
+      def_builtin (d->mask, d->name, type, d->code);
+    }
+
   /* Add all builtins that are more or less simple operations on two
      operands.  */
   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
@@ -15483,6 +16430,10 @@ ix86_init_mmx_sse_builtins (void)
   def_builtin (MASK_MMX, "__builtin_ia32_pshufw", v4hi_ftype_v4hi_int, IX86_BUILTIN_PSHUFW);
   def_builtin (MASK_MMX, "__builtin_ia32_pmaddwd", v2si_ftype_v4hi_v4hi, IX86_BUILTIN_PMADDWD);
 
+  /* ptest insns.  */
+  for (i = 0, d = bdesc_ptest; i < ARRAY_SIZE (bdesc_ptest); i++, d++)
+    def_builtin (d->mask, d->name, int_ftype_v2di_v2di, d->code);
+
   /* comi/ucomi insns.  */
   for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
     if (d->mask == MASK_SSE2)
@@ -15680,6 +16631,12 @@ ix86_init_mmx_sse_builtins (void)
   def_builtin (MASK_SSE4A, "__builtin_ia32_insertq",
                v2di_ftype_v2di_v2di, IX86_BUILTIN_INSERTQ);
 
+  /* SSE4.1 and SSE5 */
+  def_builtin (MASK_SSE5, "__builtin_ia32_roundpd", v2df_ftype_v2df_int, IX86_BUILTIN_ROUNDPD);
+  def_builtin (MASK_SSE5, "__builtin_ia32_roundps", v4sf_ftype_v4sf_int, IX86_BUILTIN_ROUNDPS);
+  def_builtin (MASK_SSE5, "__builtin_ia32_roundsd", v2df_ftype_v2df_v2df_int, IX86_BUILTIN_ROUNDSD);
+  def_builtin (MASK_SSE5, "__builtin_ia32_roundss", v4sf_ftype_v4sf_v4sf_int, IX86_BUILTIN_ROUNDSS);
+
   /* Access to the vec_init patterns.  */
   ftype = build_function_type_list (V2SI_type_node, integer_type_node,
 				    integer_type_node, NULL_TREE);
@@ -15750,6 +16707,72 @@ ix86_init_mmx_sse_builtins (void)
 				    integer_type_node, NULL_TREE);
   def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_vec_set_v4hi",
 	       ftype, IX86_BUILTIN_VEC_SET_V4HI);
+
+
+  /* Add SSE5 multi-arg argument instructions */
+  for (i = 0, d = bdesc_multi_arg; i < ARRAY_SIZE (bdesc_multi_arg); i++, d++)
+    {
+      tree mtype = NULL_TREE;
+
+      if (d->name == 0)
+	continue;
+
+      switch ((enum multi_arg_type)d->flag)
+	{
+	case MULTI_ARG_3_SF:     mtype = v4sf_ftype_v4sf_v4sf_v4sf; 	break;
+	case MULTI_ARG_3_DF:     mtype = v2df_ftype_v2df_v2df_v2df; 	break;
+	case MULTI_ARG_3_DI:     mtype = v2di_ftype_v2di_v2di_v2di; 	break;
+	case MULTI_ARG_3_SI:     mtype = v4si_ftype_v4si_v4si_v4si; 	break;
+	case MULTI_ARG_3_SI_DI:  mtype = v4si_ftype_v4si_v4si_v2di; 	break;
+	case MULTI_ARG_3_HI:     mtype = v8hi_ftype_v8hi_v8hi_v8hi; 	break;
+	case MULTI_ARG_3_HI_SI:  mtype = v8hi_ftype_v8hi_v8hi_v4si; 	break;
+	case MULTI_ARG_3_QI:     mtype = v16qi_ftype_v16qi_v16qi_v16qi; break;
+	case MULTI_ARG_3_PERMPS: mtype = v4sf_ftype_v4sf_v4sf_v16qi; 	break;
+	case MULTI_ARG_3_PERMPD: mtype = v2df_ftype_v2df_v2df_v16qi; 	break;
+	case MULTI_ARG_2_SF:     mtype = v4sf_ftype_v4sf_v4sf;      	break;
+	case MULTI_ARG_2_DF:     mtype = v2df_ftype_v2df_v2df;      	break;
+	case MULTI_ARG_2_DI:     mtype = v2di_ftype_v2di_v2di;      	break;
+	case MULTI_ARG_2_SI:     mtype = v4si_ftype_v4si_v4si;      	break;
+	case MULTI_ARG_2_HI:     mtype = v8hi_ftype_v8hi_v8hi;      	break;
+	case MULTI_ARG_2_QI:     mtype = v16qi_ftype_v16qi_v16qi;      	break;
+	case MULTI_ARG_2_DI_IMM: mtype = v2di_ftype_v2di_si;        	break;
+	case MULTI_ARG_2_SI_IMM: mtype = v4si_ftype_v4si_si;        	break;
+	case MULTI_ARG_2_HI_IMM: mtype = v8hi_ftype_v8hi_si;        	break;
+	case MULTI_ARG_2_QI_IMM: mtype = v16qi_ftype_v16qi_si;        	break;
+	case MULTI_ARG_2_SF_CMP: mtype = v4sf_ftype_v4sf_v4sf;      	break;
+	case MULTI_ARG_2_DF_CMP: mtype = v2df_ftype_v2df_v2df;      	break;
+	case MULTI_ARG_2_DI_CMP: mtype = v2di_ftype_v2di_v2di;      	break;
+	case MULTI_ARG_2_SI_CMP: mtype = v4si_ftype_v4si_v4si;      	break;
+	case MULTI_ARG_2_HI_CMP: mtype = v8hi_ftype_v8hi_v8hi;      	break;
+	case MULTI_ARG_2_QI_CMP: mtype = v16qi_ftype_v16qi_v16qi;      	break;
+	case MULTI_ARG_2_SF_TF:  mtype = v4sf_ftype_v4sf_v4sf;      	break;
+	case MULTI_ARG_2_DF_TF:  mtype = v2df_ftype_v2df_v2df;      	break;
+	case MULTI_ARG_2_DI_TF:  mtype = v2di_ftype_v2di_v2di;      	break;
+	case MULTI_ARG_2_SI_TF:  mtype = v4si_ftype_v4si_v4si;      	break;
+	case MULTI_ARG_2_HI_TF:  mtype = v8hi_ftype_v8hi_v8hi;      	break;
+	case MULTI_ARG_2_QI_TF:  mtype = v16qi_ftype_v16qi_v16qi;      	break;
+	case MULTI_ARG_1_SF:     mtype = v4sf_ftype_v4sf;           	break;
+	case MULTI_ARG_1_DF:     mtype = v2df_ftype_v2df;           	break;
+	case MULTI_ARG_1_DI:     mtype = v2di_ftype_v2di;           	break;
+	case MULTI_ARG_1_SI:     mtype = v4si_ftype_v4si;           	break;
+	case MULTI_ARG_1_HI:     mtype = v8hi_ftype_v8hi;           	break;
+	case MULTI_ARG_1_QI:     mtype = v16qi_ftype_v16qi;           	break;
+	case MULTI_ARG_1_SI_DI:  mtype = v2di_ftype_v4si;           	break;
+	case MULTI_ARG_1_HI_DI:  mtype = v2di_ftype_v8hi;           	break;
+	case MULTI_ARG_1_HI_SI:  mtype = v4si_ftype_v8hi;           	break;
+	case MULTI_ARG_1_QI_DI:  mtype = v2di_ftype_v16qi;           	break;
+	case MULTI_ARG_1_QI_SI:  mtype = v4si_ftype_v16qi;           	break;
+	case MULTI_ARG_1_QI_HI:  mtype = v8hi_ftype_v16qi;           	break;
+	case MULTI_ARG_1_PH2PS:  mtype = v4sf_ftype_v4hi;		break;
+	case MULTI_ARG_1_PS2PH:  mtype = v4hi_ftype_v4sf;		break;
+	case MULTI_ARG_UNKNOWN:
+	default:
+	  gcc_unreachable ();
+	}
+
+      if (mtype)
+	def_builtin (d->mask, d->name, mtype, d->code);
+    }
 }
 
 /* Errors in the source file can cause expand_expr to return const0_rtx
@@ -15763,6 +16786,65 @@ safe_vector_operand (rtx x, enum machine
   return x;
 }
 
+/* Subroutine of ix86_expand_builtin to take care of SSE insns with
+   4 operands. The third argument must be a constant smaller than 8
+   bits or xmm0.  */
+
+static rtx
+ix86_expand_sse_4_operands_builtin (enum insn_code icode, tree arglist,
+				    rtx target)
+{
+  rtx pat;
+  tree arg0 = TREE_VALUE (arglist);
+  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+  rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+  rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
+  enum machine_mode mode1 = insn_data[icode].operand[1].mode;
+  enum machine_mode mode2 = insn_data[icode].operand[2].mode;
+  enum machine_mode mode3 = insn_data[icode].operand[3].mode;
+
+  if (VECTOR_MODE_P (mode1))
+    op0 = safe_vector_operand (op0, mode1);
+  if (VECTOR_MODE_P (mode2))
+    op1 = safe_vector_operand (op1, mode2);
+  if (VECTOR_MODE_P (mode3))
+    op2 = safe_vector_operand (op2, mode3);
+
+  if (optimize
+      || target == 0
+      || GET_MODE (target) != tmode
+      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+    target = gen_reg_rtx (tmode);
+
+  if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
+    op0 = copy_to_mode_reg (mode1, op0);
+  if ((optimize && !register_operand (op1, mode2))
+      || !(*insn_data[icode].operand[2].predicate) (op1, mode2))
+    op1 = copy_to_mode_reg (mode2, op1);
+
+  if (! (*insn_data[icode].operand[3].predicate) (op2, mode3))
+    switch (icode)
+      {
+      case CODE_FOR_sse4_1_roundsd:
+      case CODE_FOR_sse4_1_roundss:
+	error ("the third argument must be a 4-bit immediate");
+	return const0_rtx;
+
+      default:
+	error ("the third argument must be an 8-bit immediate");
+	return const0_rtx;
+      }
+
+  pat = GEN_FCN (icode) (target, op0, op1, op2);
+  if (! pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
 /* Subroutine of ix86_expand_builtin to take care of binop insns.  */
 
 static rtx
@@ -15831,6 +16913,189 @@ ix86_expand_binop_builtin (enum insn_cod
   return target;
 }
 
+/* Subroutine of ix86_expand_builtin to take care of 2-4 argument insns.  */
+
+static rtx
+ix86_expand_multi_arg_builtin (enum insn_code icode, tree arglist, rtx target,
+			       enum multi_arg_type m_type,
+			       enum insn_code sub_code)
+{
+  rtx pat;
+  int i;
+  int nargs;
+  bool comparison_p = false;
+  bool tf_p = false;
+  bool last_arg_constant = false;
+  int num_memory = 0;
+  struct {
+    rtx op;
+    enum machine_mode mode;
+  } args[4];
+
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
+
+  switch (m_type)
+    {
+    case MULTI_ARG_3_SF:
+    case MULTI_ARG_3_DF:
+    case MULTI_ARG_3_DI:
+    case MULTI_ARG_3_SI:
+    case MULTI_ARG_3_SI_DI:
+    case MULTI_ARG_3_HI:
+    case MULTI_ARG_3_HI_SI:
+    case MULTI_ARG_3_QI:
+    case MULTI_ARG_3_PERMPS:
+    case MULTI_ARG_3_PERMPD:
+      nargs = 3;
+      break;
+
+    case MULTI_ARG_2_SF:
+    case MULTI_ARG_2_DF:
+    case MULTI_ARG_2_DI:
+    case MULTI_ARG_2_SI:
+    case MULTI_ARG_2_HI:
+    case MULTI_ARG_2_QI:
+      nargs = 2;
+      break;
+
+    case MULTI_ARG_2_DI_IMM:
+    case MULTI_ARG_2_SI_IMM:
+    case MULTI_ARG_2_HI_IMM:
+    case MULTI_ARG_2_QI_IMM:
+      nargs = 2;
+      last_arg_constant = true;
+      break;
+
+    case MULTI_ARG_1_SF:
+    case MULTI_ARG_1_DF:
+    case MULTI_ARG_1_DI:
+    case MULTI_ARG_1_SI:
+    case MULTI_ARG_1_HI:
+    case MULTI_ARG_1_QI:
+    case MULTI_ARG_1_SI_DI:
+    case MULTI_ARG_1_HI_DI:
+    case MULTI_ARG_1_HI_SI:
+    case MULTI_ARG_1_QI_DI:
+    case MULTI_ARG_1_QI_SI:
+    case MULTI_ARG_1_QI_HI:
+    case MULTI_ARG_1_PH2PS:
+    case MULTI_ARG_1_PS2PH:
+      nargs = 1;
+      break;
+
+    case MULTI_ARG_2_SF_CMP:
+    case MULTI_ARG_2_DF_CMP:
+    case MULTI_ARG_2_DI_CMP:
+    case MULTI_ARG_2_SI_CMP:
+    case MULTI_ARG_2_HI_CMP:
+    case MULTI_ARG_2_QI_CMP:
+      nargs = 2;
+      comparison_p = true;
+      break;
+
+    case MULTI_ARG_2_SF_TF:
+    case MULTI_ARG_2_DF_TF:
+    case MULTI_ARG_2_DI_TF:
+    case MULTI_ARG_2_SI_TF:
+    case MULTI_ARG_2_HI_TF:
+    case MULTI_ARG_2_QI_TF:
+      nargs = 2;
+      tf_p = true;
+      break;
+
+    case MULTI_ARG_UNKNOWN:
+    default:
+      gcc_unreachable ();
+    }
+
+  if (optimize || !target
+      || GET_MODE (target) != tmode
+      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+    target = gen_reg_rtx (tmode);
+
+  gcc_assert (nargs <= 4);
+
+  for (i = 0; i < nargs; i++)
+    {
+      int adjust = (comparison_p) ? 1 : 0;
+      enum machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
+      tree arg;
+      rtx op;
+
+      gcc_assert (arglist != NULL);
+      arg = TREE_VALUE (arglist);
+
+      gcc_assert (arg != NULL);
+      op = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+
+      if (last_arg_constant && i == nargs-1)
+	{
+	  if (GET_CODE (op) != CONST_INT)
+	    {
+	      error ("last argument must be an immediate");
+	      return gen_reg_rtx (tmode);
+	    }
+	}
+      else
+	{
+	  if (VECTOR_MODE_P (mode))
+	    op = safe_vector_operand (op, mode);
+
+	  /* If we aren't optimizing, only allow one memory operand to be
+	     generated.  */
+	  if (memory_operand (op, mode))
+	    num_memory++;
+
+	  gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode);
+
+	  if (optimize
+	      || ! (*insn_data[icode].operand[i+adjust+1].predicate) (op, mode)
+	      || num_memory > 1)
+	    op = force_reg (mode, op);
+	}
+
+      args[i].op = op;
+      args[i].mode = mode;
+      arglist = TREE_CHAIN (arglist);
+    }
+
+  switch (nargs)
+    {
+    case 1:
+      pat = GEN_FCN (icode) (target, args[0].op);
+      break;
+
+    case 2:
+      if (tf_p)
+	pat = GEN_FCN (icode) (target, args[0].op, args[1].op,
+			       GEN_INT ((int)sub_code));
+      else if (! comparison_p)
+	pat = GEN_FCN (icode) (target, args[0].op, args[1].op);
+      else
+	{
+	  rtx cmp_op = gen_rtx_fmt_ee (sub_code, GET_MODE (target),
+				       args[0].op,
+				       args[1].op);
+
+	  pat = GEN_FCN (icode) (target, cmp_op, args[0].op, args[1].op);
+	}
+      break;
+
+    case 3:
+      pat = GEN_FCN (icode) (target, args[0].op, args[1].op, args[2].op);
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  if (! pat)
+    return 0;
+
+  emit_insn (pat);
+  return target;
+}
+
 /* Subroutine of ix86_expand_builtin to take care of stores.  */
 
 static rtx
@@ -15884,7 +17149,28 @@ ix86_expand_unop_builtin (enum insn_code
 	op0 = copy_to_mode_reg (mode0, op0);
     }
 
-  pat = GEN_FCN (icode) (target, op0);
+  switch (icode)
+    {
+    case CODE_FOR_sse4_1_roundpd:
+    case CODE_FOR_sse4_1_roundps:
+	{
+	  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+	  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+	  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+
+	  if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+	    {
+	      error ("the second argument must be a 4-bit immediate");
+	      return const0_rtx;
+	    }
+	  pat = GEN_FCN (icode) (target, op0, op1);
+	}
+      break;
+    default:
+      pat = GEN_FCN (icode) (target, op0);
+      break;
+    }
+
   if (! pat)
     return 0;
   emit_insn (pat);
@@ -16033,6 +17319,52 @@ ix86_expand_sse_comi (const struct built
   return SUBREG_REG (target);
 }
 
+/* Subroutine of ix86_expand_builtin to take care of ptest insns.  */
+
+static rtx
+ix86_expand_sse_ptest (const struct builtin_description *d, tree arglist,
+		       rtx target)
+{
+  rtx pat;
+  tree arg0 = TREE_VALUE (arglist);
+  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+  enum machine_mode mode0 = insn_data[d->icode].operand[0].mode;
+  enum machine_mode mode1 = insn_data[d->icode].operand[1].mode;
+  enum rtx_code comparison = d->comparison;
+
+  if (VECTOR_MODE_P (mode0))
+    op0 = safe_vector_operand (op0, mode0);
+  if (VECTOR_MODE_P (mode1))
+    op1 = safe_vector_operand (op1, mode1);
+
+  target = gen_reg_rtx (SImode);
+  emit_move_insn (target, const0_rtx);
+  target = gen_rtx_SUBREG (QImode, target, 0);
+
+  if ((optimize && !register_operand (op0, mode0))
+      || !(*insn_data[d->icode].operand[0].predicate) (op0, mode0))
+    op0 = copy_to_mode_reg (mode0, op0);
+  if ((optimize && !register_operand (op1, mode1))
+      || !(*insn_data[d->icode].operand[1].predicate) (op1, mode1))
+    op1 = copy_to_mode_reg (mode1, op1);
+
+  pat = GEN_FCN (d->icode) (op0, op1);
+  if (! pat)
+    return 0;
+  emit_insn (pat);
+  emit_insn (gen_rtx_SET (VOIDmode,
+			  gen_rtx_STRICT_LOW_PART (VOIDmode, target),
+			  gen_rtx_fmt_ee (comparison, QImode,
+					  SET_DEST (pat),
+					  const0_rtx)));
+
+  return SUBREG_REG (target);
+}
+
+
+
 /* Return the integer constant in ARG.  Constrain it to be in the range
    of the subparts of VEC_TYPE; issue an error if not.  */
 
@@ -16617,12 +17949,15 @@ ix86_expand_builtin (tree exp, rtx targe
       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
       op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
       if (!REG_P (op0))
-	op0 = copy_to_mode_reg (SImode, op0);
+	op0 = copy_to_mode_reg (Pmode, op0);
       if (!REG_P (op1))
 	op1 = copy_to_mode_reg (SImode, op1);
       if (!REG_P (op2))
 	op2 = copy_to_mode_reg (SImode, op2);
-      emit_insn (gen_sse3_monitor (op0, op1, op2));
+      if (!TARGET_64BIT)
+	emit_insn (gen_sse3_monitor (op0, op1, op2));
+      else
+	emit_insn (gen_sse3_monitor64 (op0, op1, op2));
       return 0;
 
     case IX86_BUILTIN_MWAIT:
@@ -16817,6 +18152,10 @@ ix86_expand_builtin (tree exp, rtx targe
       break;
     }
 
+  for (i = 0, d = bdesc_sse_3arg; i < ARRAY_SIZE (bdesc_sse_3arg); i++, d++)
+    if (d->code == fcode)
+      return ix86_expand_sse_4_operands_builtin (d->icode, arglist, target);
+
   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
     if (d->code == fcode)
       {
@@ -16838,6 +18177,16 @@ ix86_expand_builtin (tree exp, rtx targe
     if (d->code == fcode)
       return ix86_expand_sse_comi (d, arglist, target);
 
+  for (i = 0, d = bdesc_ptest; i < ARRAY_SIZE (bdesc_ptest); i++, d++)
+    if (d->code == fcode)
+      return ix86_expand_sse_ptest (d, arglist, target);
+
+  for (i = 0, d = bdesc_multi_arg; i < ARRAY_SIZE (bdesc_multi_arg); i++, d++)
+    if (d->code == fcode)
+      return ix86_expand_multi_arg_builtin (d->icode, arglist, target,
+					    (enum multi_arg_type)d->flag,
+					    d->comparison);
+
   gcc_unreachable ();
 }
 
--- gcc/config/i386/i386.h.jj	2007-06-26 13:38:46.000000000 +0200
+++ gcc/config/i386/i386.h	2007-12-28 20:08:53.000000000 +0100
@@ -143,6 +143,8 @@ extern const struct processor_costs *ix8
 #define TARGET_GENERIC (TARGET_GENERIC32 || TARGET_GENERIC64)
 #define TARGET_AMDFAM10 (ix86_tune == PROCESSOR_AMDFAM10)
 
+#define TARGET_ROUND TARGET_SSE5
+
 #define TUNEMASK (1 << ix86_tune)
 extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
 extern const int x86_use_bit_test, x86_cmove, x86_fisttp, x86_deep_branch;
@@ -228,6 +230,7 @@ extern int x86_prefetch_sse, x86_cmpxchg
 #define TARGET_USE_BT (x86_use_bt & TUNEMASK)
 #define TARGET_USE_INCDEC (x86_use_incdec & TUNEMASK)
 #define TARGET_PAD_RETURNS (x86_pad_returns & TUNEMASK)
+#define TARGET_FUSED_MADD x86_fused_muladd
 
 #define ASSEMBLER_DIALECT (ix86_asm_dialect)
 
@@ -408,6 +411,8 @@ extern int x86_prefetch_sse, x86_cmpxchg
 	}							\
       if (TARGET_SSE4A)						\
 	builtin_define ("__SSE4A__");		                \
+      if (TARGET_SSE5)						\
+	builtin_define ("__SSE5__");				\
       if (TARGET_SSE_MATH && TARGET_SSE)			\
 	builtin_define ("__SSE_MATH__");			\
       if (TARGET_SSE_MATH && TARGET_SSE2)			\
--- gcc/config/i386/i386.md.jj	2007-06-26 13:38:46.000000000 +0200
+++ gcc/config/i386/i386.md	2007-12-28 20:12:10.000000000 +0100
@@ -157,6 +157,21 @@
    (UNSPEC_EXTRQ                131)   
    (UNSPEC_INSERTQI             132)
    (UNSPEC_INSERTQ              133)
+
+   ; For SSE4.1/SSE5 support
+   (UNSPEC_PTEST		145)
+   (UNSPEC_ROUND		146)
+
+   ;; For SSE5
+   (UNSPEC_SSE5_INTRINSIC	150)
+   (UNSPEC_SSE5_UNSIGNED_CMP	151)
+   (UNSPEC_SSE5_TRUEFALSE	152)
+   (UNSPEC_SSE5_PERMUTE		153)
+   (UNSPEC_SSE5_ASHIFT		154)
+   (UNSPEC_SSE5_LSHIFT		155)
+   (UNSPEC_FRCZ			156)
+   (UNSPEC_CVTPH2PS		157)
+   (UNSPEC_CVTPS2PH		158)
   ])
 
 (define_constants
@@ -176,6 +191,16 @@
    (UNSPECV_LOCK		13)
   ])
 
+;; Constants to represent pcomtrue/pcomfalse variants
+(define_constants
+  [(PCOM_FALSE			0)
+   (PCOM_TRUE			1)
+   (COM_FALSE_S			2)
+   (COM_FALSE_P			3)
+   (COM_TRUE_S			4)
+   (COM_TRUE_P			5)
+  ])
+
 ;; Registers by name.
 (define_constants
   [(BP_REG			 6)
@@ -210,8 +235,9 @@
    push,pop,call,callv,leave,
    str,bitmanip,cld,
    fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
-   sselog,sselog1,sseiadd,sseishft,sseimul,
-   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins,
+   sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,ssediv,sseins,
+   ssemuladd,sse4arg,
    mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
   (const_string "other"))
 
@@ -224,8 +250,9 @@
 (define_attr "unit" "integer,i387,sse,mmx,unknown"
   (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
 	   (const_string "i387")
-	 (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
-			  sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins")
+	 (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+			  sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,
+			  ssediv,sseins,ssemuladd,sse4arg")
 	   (const_string "sse")
 	 (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
 	   (const_string "mmx")
@@ -417,12 +444,12 @@
 		 "!alu1,negnot,ishift1,
 		   imov,imovx,icmp,test,bitmanip,
 		   fmov,fcmp,fsgn,
-		   sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
-		   mmx,mmxmov,mmxcmp,mmxcvt")
+		   sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,sselog1,
+		   sseiadd1,mmx,mmxmov,mmxcmp,mmxcvt")
 	      (match_operand 2 "memory_operand" ""))
 	   (const_string "load")
-	 (and (eq_attr "type" "icmov")
-	      (match_operand 3 "memory_operand" ""))
+ 	 (and (eq_attr "type" "icmov,ssemuladd,sse4arg")
+  	      (match_operand 3 "memory_operand" ""))
 	   (const_string "load")
 	]
 	(const_string "none")))
@@ -469,10 +496,14 @@
 
 ;; All SSE floating point modes
 (define_mode_macro SSEMODEF [SF DF])
+(define_mode_macro MODEF [SF DF])
  
 ;; All integer modes handled by SSE cvtts?2si* operators.
 (define_mode_macro SSEMODEI24 [SI DI])
 
+;; SSE asm suffix for floating point modes
+(define_mode_attr ssemodefsuffix [(SF "s") (DF "d")])
+
 
 ;; Scheduling descriptions
 
@@ -7417,6 +7448,9 @@
 		 (match_operand:SF 2 "nonimmediate_operand" "")))]
   "TARGET_80387 || TARGET_SSE_MATH"
   "")
+
+;; SSE5 scalar multiply/add instructions are defined in sse.md.
+
 
 ;; Divide instructions
 
@@ -13429,7 +13463,7 @@
 	(match_operator:SF 1 "sse_comparison_operator"
 	  [(match_operand:SF 2 "register_operand" "0")
 	   (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
-  "TARGET_SSE"
+  "TARGET_SSE && !TARGET_SSE5"
   "cmp%D1ss\t{%3, %0|%0, %3}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "SF")])
@@ -13439,10 +13473,21 @@
 	(match_operator:DF 1 "sse_comparison_operator"
 	  [(match_operand:DF 2 "register_operand" "0")
 	   (match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
-  "TARGET_SSE2"
+  "TARGET_SSE2 && !TARGET_SSE5"
   "cmp%D1sd\t{%3, %0|%0, %3}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "DF")])
+
+(define_insn "*sse5_setcc<mode>"
+  [(set (match_operand:MODEF 0 "register_operand" "=x")
+	(match_operator:MODEF 1 "sse5_comparison_float_operator"
+	  [(match_operand:MODEF 2 "register_operand" "x")
+	   (match_operand:MODEF 3 "nonimmediate_operand" "xm")]))]
+  "TARGET_SSE5"
+  "com%Y1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "<MODE>")])
+
 
 ;; Basic conditional jump instructions.
 ;; We ignore the overflow flag for signed branch instructions.
@@ -17208,6 +17253,15 @@
     operands[i] = gen_reg_rtx (XFmode);
 })
 
+(define_insn "sse4_1_round<mode>2"
+  [(set (match_operand:MODEF 0 "register_operand" "=x")
+	(unspec:MODEF [(match_operand:MODEF 1 "register_operand" "x")
+		       (match_operand:SI 2 "const_0_to_15_operand" "n")]
+		      UNSPEC_ROUND))]
+  "TARGET_ROUND"
+  "rounds<ssemodefsuffix>\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "<MODE>")])
 
 (define_insn "frndintxf2"
   [(set (match_operand:XF 0 "register_operand" "=f")
@@ -19180,6 +19234,20 @@
   [(set_attr "type" "fcmov")
    (set_attr "mode" "XF")])
 
+;; All moves in SSE5 pcmov instructions are 128 bits and hence we restrict
+;; the scalar versions to have only XMM registers as operands.
+
+;; SSE5 conditional move
+(define_insn "*sse5_pcmov_<mode>"
+  [(set (match_operand:MODEF 0 "register_operand" "=x,x")
+	(if_then_else:MODEF
+	  (match_operand:MODEF 1 "register_operand" "x,0")
+	  (match_operand:MODEF 2 "register_operand" "0,x")
+	  (match_operand:MODEF 3 "register_operand" "x,x")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "pcmov\t{%1, %3, %2, %0|%0, %2, %3, %1}"
+  [(set_attr "type" "sse4arg")])
+
 ;; These versions of the min/max patterns are intentionally ignorant of
 ;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
 ;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
--- gcc/config/i386/i386.opt.jj	2007-06-26 13:38:46.000000000 +0200
+++ gcc/config/i386/i386.opt	2007-12-28 21:59:55.000000000 +0100
@@ -209,6 +209,10 @@ msse4a
 Target Report Mask(SSE4A)
 Support MMX, SSE, SSE2, SSE3 and SSE4A built-in functions and code generation
 
+msse5
+Target Report Mask(SSE5)
+Support SSE5 built-in functions and code generation
+
 mpopcnt
 Target Report Mask(POPCNT)
 Support code generation of popcount instruction for popcount built-ins 
@@ -247,3 +251,9 @@ Schedule code for given CPU
 
 ;; Support Athlon 3Dnow builtins
 Mask(3DNOW_A)
+
+mfused-madd
+Target Report Var(x86_fused_muladd) Init(1)
+Enable automatic generation of fused floating point multiply-add instructions
+if the ISA supports such instructions.  The -mfused-madd option is on by
+default.
--- gcc/config/i386/mm3dnow.h.jj	2007-12-28 15:43:26.000000000 +0100
+++ gcc/config/i386/mm3dnow.h	2007-12-30 22:13:34.000000000 +0100
@@ -172,13 +172,17 @@ _m_prefetchw (void *__P)
 static __inline __m64
 _m_from_float (float __A)
 {
-  return (__m64)(__v2sf){ __A, 0 };
+  union { __v2sf v; float a[2]; } __tmp;
+  __tmp.a[0] = __A;
+  __tmp.a[1] = 0;
+  return (__m64)__tmp.v;
 }
 
 static __inline float
 _m_to_float (__m64 __A)
 {
-  union { __v2sf v; float a[2]; } __tmp = { (__v2sf)__A };
+  union { __v2sf v; float a[2]; } __tmp;
+  __tmp.v = (__v2sf)__A;
   return __tmp.a[0];
 }
 
--- gcc/config/i386/mmintrin-common.h.jj	2007-12-28 20:04:35.000000000 +0100
+++ gcc/config/i386/mmintrin-common.h	2007-12-28 20:04:35.000000000 +0100
@@ -0,0 +1,156 @@
+/* Copyright (C) 2007 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 2, 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.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, if you include this header file into source
+   files compiled by GCC, this header file does not by itself cause
+   the resulting executable to be covered by the GNU General Public
+   License.  This exception does not however invalidate any other
+   reasons why the executable file might be covered by the GNU General
+   Public License.  */
+
+/* Common definition of the ROUND and PTEST intrinsics that are shared
+   between SSE4.1 and SSE5.  */
+
+#ifndef _MMINTRIN_COMMON_H_INCLUDED
+#define _MMINTRIN_COMMON_H_INCLUDED
+
+#if !defined(__SSE5__) && !defined(__SSE4_1__)
+# error "SSE5 or SSE4.1 instruction set not enabled"
+#else
+
+/* Rounding mode macros. */
+#define _MM_FROUND_TO_NEAREST_INT	0x00
+#define _MM_FROUND_TO_NEG_INF		0x01
+#define _MM_FROUND_TO_POS_INF		0x02
+#define _MM_FROUND_TO_ZERO		0x03
+#define _MM_FROUND_CUR_DIRECTION	0x04
+
+#define _MM_FROUND_RAISE_EXC		0x00
+#define _MM_FROUND_NO_EXC		0x08
+
+#define _MM_FROUND_NINT		\
+  (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_RAISE_EXC)
+#define _MM_FROUND_FLOOR	\
+  (_MM_FROUND_TO_NEG_INF | _MM_FROUND_RAISE_EXC)
+#define _MM_FROUND_CEIL		\
+  (_MM_FROUND_TO_POS_INF | _MM_FROUND_RAISE_EXC)
+#define _MM_FROUND_TRUNC	\
+  (_MM_FROUND_TO_ZERO | _MM_FROUND_RAISE_EXC)
+#define _MM_FROUND_RINT		\
+  (_MM_FROUND_CUR_DIRECTION | _MM_FROUND_RAISE_EXC)
+#define _MM_FROUND_NEARBYINT	\
+  (_MM_FROUND_CUR_DIRECTION | _MM_FROUND_NO_EXC)
+
+/* Test Instruction */
+/* Packed integer 128-bit bitwise comparison. Return 1 if
+   (__V & __M) == 0.  */
+static __inline int __attribute__((__always_inline__, __artificial__))
+_mm_testz_si128 (__m128i __M, __m128i __V)
+{
+  return __builtin_ia32_ptestz128 ((__v2di)__M, (__v2di)__V);
+}
+
+/* Packed integer 128-bit bitwise comparison. Return 1 if
+   (__V & ~__M) == 0.  */
+static __inline int __attribute__((__always_inline__, __artificial__))
+_mm_testc_si128 (__m128i __M, __m128i __V)
+{
+  return __builtin_ia32_ptestc128 ((__v2di)__M, (__v2di)__V);
+}
+
+/* Packed integer 128-bit bitwise comparison. Return 1 if
+   (__V & __M) != 0 && (__V & ~__M) != 0.  */
+static __inline int __attribute__((__always_inline__, __artificial__))
+_mm_testnzc_si128 (__m128i __M, __m128i __V)
+{
+  return __builtin_ia32_ptestnzc128 ((__v2di)__M, (__v2di)__V);
+}
+
+/* Macros for packed integer 128-bit comparison intrinsics.  */
+#define _mm_test_all_zeros(M, V) _mm_testz_si128 ((M), (V))
+
+#define _mm_test_all_ones(V) \
+  _mm_testc_si128 ((V), _mm_cmpeq_epi32 ((V), (V)))
+
+#define _mm_test_mix_ones_zeros(M, V) _mm_testnzc_si128 ((M), (V))
+
+/* Packed/scalar double precision floating point rounding.  */
+
+#ifdef __OPTIMIZE__
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_round_pd (__m128d __V, const int __M)
+{
+  return (__m128d) __builtin_ia32_roundpd ((__v2df)__V, __M);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __artificial__))
+_mm_round_sd(__m128d __D, __m128d __V, const int __M)
+{
+  return (__m128d) __builtin_ia32_roundsd ((__v2df)__D,
+					   (__v2df)__V,
+					   __M);
+}
+#else
+#define _mm_round_pd(V, M) \
+  ((__m128d) __builtin_ia32_roundpd ((__v2df)(V), (M)))
+
+#define _mm_round_sd(D, V, M) \
+  ((__m128d) __builtin_ia32_roundsd ((__v2df)(D), (__v2df)(V), (M)))
+#endif
+
+/* Packed/scalar single precision floating point rounding.  */
+
+#ifdef __OPTIMIZE__
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_round_ps (__m128 __V, const int __M)
+{
+  return (__m128) __builtin_ia32_roundps ((__v4sf)__V, __M);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __artificial__))
+_mm_round_ss (__m128 __D, __m128 __V, const int __M)
+{
+  return (__m128) __builtin_ia32_roundss ((__v4sf)__D,
+					  (__v4sf)__V,
+					  __M);
+}
+#else
+#define _mm_round_ps(V, M) \
+  ((__m128) __builtin_ia32_roundps ((__v4sf)(V), (M)))
+
+#define _mm_round_ss(D, V, M) \
+  ((__m128) __builtin_ia32_roundss ((__v4sf)(D), (__v4sf)(V), (M)))
+#endif
+
+/* Macros for ceil/floor intrinsics.  */
+#define _mm_ceil_pd(V)	   _mm_round_pd ((V), _MM_FROUND_CEIL)
+#define _mm_ceil_sd(D, V)  _mm_round_sd ((D), (V), _MM_FROUND_CEIL)
+
+#define _mm_floor_pd(V)	   _mm_round_pd((V), _MM_FROUND_FLOOR)
+#define _mm_floor_sd(D, V) _mm_round_sd ((D), (V), _MM_FROUND_FLOOR)
+
+#define _mm_ceil_ps(V)	   _mm_round_ps ((V), _MM_FROUND_CEIL)
+#define _mm_ceil_ss(D, V)  _mm_round_ss ((D), (V), _MM_FROUND_CEIL)
+
+#define _mm_floor_ps(V)	   _mm_round_ps ((V), _MM_FROUND_FLOOR)
+#define _mm_floor_ss(D, V) _mm_round_ss ((D), (V), _MM_FROUND_FLOOR)
+
+#endif /* __SSE5__/__SSE4_1__ */
+
+#endif /* _MMINTRIN_COMMON_H_INCLUDED */
--- gcc/config/i386/predicates.md.jj	2007-02-20 22:38:59.000000000 +0100
+++ gcc/config/i386/predicates.md	2007-12-28 20:04:35.000000000 +0100
@@ -566,6 +566,11 @@
   (and (match_code "const_int")
        (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 15")))
 
+;; Match 0 to 31.
+(define_predicate "const_0_to_31_operand"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
+
 ;; Match 0 to 63.
 (define_predicate "const_0_to_63_operand"
   (and (match_code "const_int")
@@ -806,6 +811,18 @@
 (define_special_predicate "sse_comparison_operator"
   (match_code "eq,lt,le,unordered,ne,unge,ungt,ordered"))
 
+;; Return 1 if OP is a comparison operator that can be issued by sse predicate
+;; generation instructions
+(define_predicate "sse5_comparison_float_operator"
+  (and (match_test "TARGET_SSE5")
+       (match_code "ne,eq,ge,gt,le,lt,unordered,ordered,uneq,unge,ungt,unle,unlt,ltgt")))
+
+(define_predicate "ix86_comparison_int_operator"
+  (match_code "ne,eq,ge,gt,le,lt"))
+
+(define_predicate "ix86_comparison_uns_operator"
+  (match_code "ne,eq,geu,gtu,leu,ltu"))
+
 ;; Return 1 if OP is a valid comparison operator in valid mode.
 (define_predicate "ix86_comparison_operator"
   (match_operand 0 "comparison_operator")
--- gcc/config/i386/sse.md.jj	2007-07-23 12:11:56.000000000 +0200
+++ gcc/config/i386/sse.md	2007-12-30 21:39:00.000000000 +0100
@@ -33,10 +33,24 @@
 (define_mode_macro SSEMODE14 [V16QI V4SI])
 (define_mode_macro SSEMODE124 [V16QI V8HI V4SI])
 (define_mode_macro SSEMODE248 [V8HI V4SI V2DI])
+(define_mode_macro SSEMODE1248 [V16QI V8HI V4SI V2DI])
+(define_mode_macro SSEMODEF4 [SF DF V4SF V2DF])
+(define_mode_macro SSEMODEF2P [V4SF V2DF])
 
 ;; Mapping from integer vector mode to mnemonic suffix
 (define_mode_attr ssevecsize [(V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")])
 
+;; Mapping of the sse5 suffix
+(define_mode_attr ssemodesuffixf4 [(SF "ss") (DF "sd") (V4SF "ps") (V2DF "pd")])
+(define_mode_attr ssemodesuffixf2s [(SF "ss") (DF "sd") (V4SF "ss") (V2DF "sd")])
+(define_mode_attr ssemodesuffixf2c [(V4SF "s") (V2DF "d")])
+
+;; Mapping of the max integer size for sse5 rotate immediate constraint
+(define_mode_attr sserotatemax [(V16QI "7") (V8HI "15") (V4SI "31") (V2DI "63")])
+
+;; Mapping of vector modes back to the scalar modes
+(define_mode_attr ssescalarmode [(V4SF "SF") (V2DF "DF")])
+
 ;; Patterns whose name begins with "sse{,2,3}_" are invoked by intrinsics.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -745,7 +759,7 @@
 	(match_operator:V4SF 3 "sse_comparison_operator"
 		[(match_operand:V4SF 1 "register_operand" "0")
 		 (match_operand:V4SF 2 "nonimmediate_operand" "xm")]))]
-  "TARGET_SSE"
+  "TARGET_SSE && !TARGET_SSE5"
   "cmp%D3ps\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "V4SF")])
@@ -758,7 +772,7 @@
 		 (match_operand:V4SF 2 "register_operand" "x")])
 	 (match_dup 1)
 	 (const_int 1)))]
-  "TARGET_SSE"
+  "TARGET_SSE && !TARGET_SSE5"
   "cmp%D3ss\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "SF")])
@@ -1386,6 +1400,563 @@
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
+;; SSE5 floating point multiply/accumulate instructions This includes the
+;; scalar version of the instructions as well as the vector
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; In order to match (*a * *b) + *c, particularly when vectorizing, allow
+;; combine to generate a multiply/add with two memory references.  We then
+;; split this insn, into loading up the destination register with one of the
+;; memory operations.  If we don't manage to split the insn, reload will
+;; generate the appropriate moves.  The reason this is needed, is that combine
+;; has already folded one of the memory references into both the multiply and
+;; add insns, and it can't generate a new pseudo.  I.e.:
+;;	(set (reg1) (mem (addr1)))
+;;	(set (reg2) (mult (reg1) (mem (addr2))))
+;;	(set (reg3) (plus (reg2) (mem (addr3))))
+
+(define_insn "sse5_fmadd<mode>4"
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
+	(plus:SSEMODEF4
+	 (mult:SSEMODEF4
+	  (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
+  "fmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Split fmadd with two memory operands into a load and the fmadd.
+(define_split
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "")
+	(plus:SSEMODEF4
+	 (mult:SSEMODEF4
+	  (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
+  "TARGET_SSE5
+   && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
+   && !reg_mentioned_p (operands[0], operands[1])
+   && !reg_mentioned_p (operands[0], operands[2])
+   && !reg_mentioned_p (operands[0], operands[3])"
+  [(const_int 0)]
+{
+  ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
+  emit_insn (gen_sse5_fmadd<mode>4 (operands[0], operands[1],
+				    operands[2], operands[3]));
+  DONE;
+})
+
+;; For the scalar operations, use operand1 for the upper words that aren't
+;; modified, so restrict the forms that are generated.
+;; Scalar version of fmadd
+(define_insn "sse5_vmfmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(vec_merge:SSEMODEF2P
+	 (plus:SSEMODEF2P
+	  (mult:SSEMODEF2P
+	   (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
+	   (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
+	  (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
+	 (match_dup 1)
+	 (const_int 1)))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Floating multiply and subtract
+;; Allow two memory operands the same as fmadd
+(define_insn "sse5_fmsub<mode>4"
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
+	(minus:SSEMODEF4
+	 (mult:SSEMODEF4
+	  (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
+  "fmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Split fmsub with two memory operands into a load and the fmsub.
+(define_split
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "")
+	(minus:SSEMODEF4
+	 (mult:SSEMODEF4
+	  (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
+  "TARGET_SSE5
+   && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
+   && !reg_mentioned_p (operands[0], operands[1])
+   && !reg_mentioned_p (operands[0], operands[2])
+   && !reg_mentioned_p (operands[0], operands[3])"
+  [(const_int 0)]
+{
+  ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
+  emit_insn (gen_sse5_fmsub<mode>4 (operands[0], operands[1],
+				    operands[2], operands[3]));
+  DONE;
+})
+
+;; For the scalar operations, use operand1 for the upper words that aren't
+;; modified, so restrict the forms that are generated.
+;; Scalar version of fmsub
+(define_insn "sse5_vmfmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(vec_merge:SSEMODEF2P
+	 (minus:SSEMODEF2P
+	  (mult:SSEMODEF2P
+	   (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
+	   (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
+	  (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
+	 (match_dup 1)
+	 (const_int 1)))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Floating point negative multiply and add
+;; Rewrite (- (a * b) + c) into the canonical form: c - (a * b)
+;; Note operands are out of order to simplify call to ix86_sse5_valid_p
+;; Allow two memory operands to help in optimizing.
+(define_insn "sse5_fnmadd<mode>4"
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
+	(minus:SSEMODEF4
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")
+	 (mult:SSEMODEF4
+	  (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
+  "fnmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Split fnmadd with two memory operands into a load and the fnmadd.
+(define_split
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "")
+	(minus:SSEMODEF4
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")
+	 (mult:SSEMODEF4
+	  (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))))]
+  "TARGET_SSE5
+   && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
+   && !reg_mentioned_p (operands[0], operands[1])
+   && !reg_mentioned_p (operands[0], operands[2])
+   && !reg_mentioned_p (operands[0], operands[3])"
+  [(const_int 0)]
+{
+  ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
+  emit_insn (gen_sse5_fnmadd<mode>4 (operands[0], operands[1],
+				     operands[2], operands[3]));
+  DONE;
+})
+
+;; For the scalar operations, use operand1 for the upper words that aren't
+;; modified, so restrict the forms that are generated.
+;; Scalar version of fnmadd
+(define_insn "sse5_vmfnmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(vec_merge:SSEMODEF2P
+	 (minus:SSEMODEF2P
+	  (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x")
+	  (mult:SSEMODEF2P
+	   (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
+	   (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm")))
+	 (match_dup 1)
+	 (const_int 1)))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fnmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Floating point negative multiply and subtract
+;; Rewrite (- (a * b) - c) into the canonical form: ((-a) * b) - c
+;; Allow 2 memory operands to help with optimization
+(define_insn "sse5_fnmsub<mode>4"
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x")
+	(minus:SSEMODEF4
+	 (mult:SSEMODEF4
+	  (neg:SSEMODEF4
+	   (match_operand:SSEMODEF4 1 "nonimmediate_operand" "0,0"))
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm"))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x")))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
+  "fnmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Split fnmsub with two memory operands into a load and the fmsub.
+(define_split
+  [(set (match_operand:SSEMODEF4 0 "register_operand" "")
+	(minus:SSEMODEF4
+	 (mult:SSEMODEF4
+	  (neg:SSEMODEF4
+	   (match_operand:SSEMODEF4 1 "nonimmediate_operand" ""))
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
+  "TARGET_SSE5
+   && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
+   && !reg_mentioned_p (operands[0], operands[1])
+   && !reg_mentioned_p (operands[0], operands[2])
+   && !reg_mentioned_p (operands[0], operands[3])"
+  [(const_int 0)]
+{
+  ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
+  emit_insn (gen_sse5_fnmsub<mode>4 (operands[0], operands[1],
+				     operands[2], operands[3]));
+  DONE;
+})
+
+;; For the scalar operations, use operand1 for the upper words that aren't
+;; modified, so restrict the forms that are generated.
+;; Scalar version of fnmsub
+(define_insn "sse5_vmfnmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(vec_merge:SSEMODEF2P
+	 (minus:SSEMODEF2P
+	  (mult:SSEMODEF2P
+	   (neg:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0"))
+	   (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
+	  (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
+	 (match_dup 1)
+	 (const_int 1)))]
+  "TARGET_SSE5 && TARGET_FUSED_MADD
+   && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
+  "fnmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; The same instructions using an UNSPEC to allow the intrinsic to be used
+;; even if the user used -mno-fused-madd
+;; Parallel instructions.  During instruction generation, just default
+;; to registers, and let combine later build the appropriate instruction.
+(define_expand "sse5i_fmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(plus:SSEMODEF2P
+	   (mult:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "register_operand" "")
+	    (match_operand:SSEMODEF2P 2 "register_operand" ""))
+	   (match_operand:SSEMODEF2P 3 "register_operand" ""))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_fmadd<mode>4 (operands[0], operands[1],
+					operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_fmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
+	(unspec:SSEMODEF2P
+	 [(plus:SSEMODEF2P
+	   (mult:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0,0,x,xm")
+	    (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x"))
+	   (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0"))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+(define_expand "sse5i_fmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(minus:SSEMODEF2P
+	   (mult:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "register_operand" "")
+	    (match_operand:SSEMODEF2P 2 "register_operand" ""))
+	   (match_operand:SSEMODEF2P 3 "register_operand" ""))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_fmsub<mode>4 (operands[0], operands[1],
+					operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_fmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
+	(unspec:SSEMODEF2P
+	 [(minus:SSEMODEF2P
+	   (mult:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "register_operand" "%0,0,x,xm")
+	    (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x"))
+	   (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0"))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Rewrite (- (a * b) + c) into the canonical form: c - (a * b)
+;; Note operands are out of order to simplify call to ix86_sse5_valid_p
+(define_expand "sse5i_fnmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(minus:SSEMODEF2P
+	   (match_operand:SSEMODEF2P 3 "register_operand" "")
+	   (mult:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "register_operand" "")
+	    (match_operand:SSEMODEF2P 2 "register_operand" "")))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_fnmadd<mode>4 (operands[0], operands[1],
+					 operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_fnmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
+	(unspec:SSEMODEF2P
+	 [(minus:SSEMODEF2P
+	   (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0")
+	   (mult:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0,0,x,xm")
+	    (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x")))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fnmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Rewrite (- (a * b) - c) into the canonical form: ((-a) * b) - c
+(define_expand "sse5i_fnmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(minus:SSEMODEF2P
+	   (mult:SSEMODEF2P
+	    (neg:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "register_operand" ""))
+	    (match_operand:SSEMODEF2P 2 "register_operand" ""))
+	   (match_operand:SSEMODEF2P 3 "register_operand" ""))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_fnmsub<mode>4 (operands[0], operands[1],
+					 operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_fnmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
+	(unspec:SSEMODEF2P
+	 [(minus:SSEMODEF2P
+	   (mult:SSEMODEF2P
+	    (neg:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "%0,0,x,xm"))
+	    (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,xm,x"))
+	   (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x,0,0"))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fnmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<MODE>")])
+
+;; Scalar instructions
+(define_expand "sse5i_vmfmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (plus:SSEMODEF2P
+	    (mult:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "register_operand" "")
+	     (match_operand:SSEMODEF2P 2 "register_operand" ""))
+	    (match_operand:SSEMODEF2P 3 "register_operand" ""))
+	   (match_dup 1)
+	   (const_int 0))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_vmfmadd<mode>4 (operands[0], operands[1],
+					  operands[2], operands[3]));
+      DONE;
+    }
+})
+
+;; For the scalar operations, use operand1 for the upper words that aren't
+;; modified, so restrict the forms that are accepted.
+(define_insn "*sse5i_vmfmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (plus:SSEMODEF2P
+	    (mult:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "register_operand" "0,0")
+	     (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
+	    (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
+	   (match_dup 0)
+	   (const_int 0))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<ssescalarmode>")])
+
+(define_expand "sse5i_vmfmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (minus:SSEMODEF2P
+	    (mult:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "register_operand" "")
+	     (match_operand:SSEMODEF2P 2 "register_operand" ""))
+	    (match_operand:SSEMODEF2P 3 "register_operand" ""))
+	   (match_dup 0)
+	   (const_int 1))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_vmfmsub<mode>4 (operands[0], operands[1],
+					  operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_vmfmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (minus:SSEMODEF2P
+	    (mult:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
+	     (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
+	    (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
+	   (match_dup 1)
+	   (const_int 1))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<ssescalarmode>")])
+
+;; Note operands are out of order to simplify call to ix86_sse5_valid_p
+(define_expand "sse5i_vmfnmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (minus:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 3 "register_operand" "")
+	    (mult:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "register_operand" "")
+	     (match_operand:SSEMODEF2P 2 "register_operand" "")))
+	   (match_dup 1)
+	   (const_int 1))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_vmfnmadd<mode>4 (operands[0], operands[1],
+					   operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_vmfnmadd<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (minus:SSEMODEF2P
+	    (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x")
+	    (mult:SSEMODEF2P
+	     (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
+	     (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm")))
+	   (match_dup 1)
+	   (const_int 1))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fnmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<ssescalarmode>")])
+
+(define_expand "sse5i_vmfnmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (minus:SSEMODEF2P
+	    (mult:SSEMODEF2P
+	     (neg:SSEMODEF2P
+	      (match_operand:SSEMODEF2P 1 "register_operand" ""))
+	     (match_operand:SSEMODEF2P 2 "register_operand" ""))
+	    (match_operand:SSEMODEF2P 3 "register_operand" ""))
+	   (match_dup 1)
+	   (const_int 1))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5"
+{
+  /* If we have -mfused-madd, emit the normal insn rather than the UNSPEC */
+  if (TARGET_FUSED_MADD)
+    {
+      emit_insn (gen_sse5_vmfnmsub<mode>4 (operands[0], operands[1],
+					   operands[2], operands[3]));
+      DONE;
+    }
+})
+
+(define_insn "*sse5i_vmfnmsub<mode>4"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
+	(unspec:SSEMODEF2P
+	 [(vec_merge:SSEMODEF2P
+	   (minus:SSEMODEF2P
+	    (mult:SSEMODEF2P
+	     (neg:SSEMODEF2P
+	      (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0"))
+	     (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
+	    (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
+	   (match_dup 1)
+	   (const_int 1))]
+	 UNSPEC_SSE5_INTRINSIC))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "fnmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "<ssescalarmode>")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
 ;; Parallel double-precision floating point arithmetic
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1716,7 +2287,7 @@
 	(match_operator:V2DF 3 "sse_comparison_operator"
 		[(match_operand:V2DF 1 "register_operand" "0")
 		 (match_operand:V2DF 2 "nonimmediate_operand" "xm")]))]
-  "TARGET_SSE2"
+  "TARGET_SSE2 && !TARGET_SSE5"
   "cmp%D3pd\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "V2DF")])
@@ -1729,7 +2300,7 @@
 		 (match_operand:V2DF 2 "nonimmediate_operand" "xm")])
 	  (match_dup 1)
 	  (const_int 1)))]
-  "TARGET_SSE2"
+  "TARGET_SSE2 && !TARGET_SSE5"
   "cmp%D3sd\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "DF")])
@@ -2677,6 +3248,31 @@
   [(set_attr "type" "sseiadd")
    (set_attr "mode" "TI")])
 
+;; We don't have a straight 32-bit parallel multiply on SSE5, so fake it with a
+;; multiply/add.  In general, we expect the define_split to occur before
+;; register allocation, so we have to handle the corner case where the target
+;; is used as the base or index register in operands 1/2.
+(define_insn_and_split "sse5_mulv4si3"
+  [(set (match_operand:V4SI 0 "register_operand" "=&x")
+	(mult:V4SI (match_operand:V4SI 1 "register_operand" "%x")
+		   (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
+  "TARGET_SSE5"
+  "#"
+  "&& (reload_completed
+       || (!reg_mentioned_p (operands[0], operands[1])
+	   && !reg_mentioned_p (operands[0], operands[2])))"
+  [(set (match_dup 0)
+	(match_dup 3))
+   (set (match_dup 0)
+	(plus:V4SI (mult:V4SI (match_dup 1)
+			      (match_dup 2))
+		   (match_dup 0)))]
+{
+  operands[3] = CONST0_RTX (V4SImode);
+}
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
 (define_expand "mulv4si3"
   [(set (match_operand:V4SI 0 "register_operand" "")
 	(mult:V4SI (match_operand:V4SI 1 "register_operand" "")
@@ -2686,6 +3282,13 @@
   rtx t1, t2, t3, t4, t5, t6, thirtytwo;
   rtx op0, op1, op2;
 
+  if (TARGET_SSE5)
+    {
+      ix86_fixup_binary_operands_no_copy (MULT, V4SImode, operands);
+      emit_insn (gen_sse5_mulv4si3 (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+
   op0 = operands[0];
   op1 = operands[1];
   op2 = operands[2];
@@ -3013,7 +3616,8 @@
 	(eq:SSEMODE124
 	  (match_operand:SSEMODE124 1 "nonimmediate_operand" "%0")
 	  (match_operand:SSEMODE124 2 "nonimmediate_operand" "xm")))]
-  "TARGET_SSE2 && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
+  "TARGET_SSE2 && !TARGET_SSE5
+   && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
   "pcmpeq<ssevecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "TI")])
@@ -3023,7 +3627,7 @@
 	(gt:SSEMODE124
 	  (match_operand:SSEMODE124 1 "register_operand" "0")
 	  (match_operand:SSEMODE124 2 "nonimmediate_operand" "xm")))]
-  "TARGET_SSE2"
+  "TARGET_SSE2 && !TARGET_SSE5"
   "pcmpgt<ssevecsize>\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "TI")])
@@ -4658,3 +5262,1245 @@
   "insertq\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseins")
    (set_attr "mode" "TI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Common SSE4.1/SSE5 instructions
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ptest is very similar to comiss and ucomiss when setting FLAGS_REG.
+;; But it is not a really compare instruction.
+(define_insn "sse4_1_ptest"
+  [(set (reg:CC FLAGS_REG)
+	(unspec:CC [(match_operand:V2DI 0 "register_operand" "x")
+		    (match_operand:V2DI 1 "nonimmediate_operand" "xm")]
+		   UNSPEC_PTEST))]
+  "TARGET_ROUND"
+  "ptest\t{%1, %0|%0, %1}"
+  [(set_attr "type" "ssecomi")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse4_1_roundpd"
+  [(set (match_operand:V2DF 0 "register_operand" "=x")
+	(unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm")
+		      (match_operand:SI 2 "const_0_to_15_operand" "n")]
+		     UNSPEC_ROUND))]
+  "TARGET_ROUND"
+  "roundpd\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "V2DF")])
+
+(define_insn "sse4_1_roundps"
+  [(set (match_operand:V4SF 0 "register_operand" "=x")
+	(unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")
+		      (match_operand:SI 2 "const_0_to_15_operand" "n")]
+		     UNSPEC_ROUND))]
+  "TARGET_ROUND"
+  "roundps\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "V4SF")])
+
+(define_insn "sse4_1_roundsd"
+  [(set (match_operand:V2DF 0 "register_operand" "=x")
+	(vec_merge:V2DF
+	  (unspec:V2DF [(match_operand:V2DF 2 "register_operand" "x")
+			(match_operand:SI 3 "const_0_to_15_operand" "n")]
+		       UNSPEC_ROUND)
+	  (match_operand:V2DF 1 "register_operand" "0")
+	  (const_int 1)))]
+  "TARGET_ROUND"
+  "roundsd\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "V2DF")])
+
+(define_insn "sse4_1_roundss"
+  [(set (match_operand:V4SF 0 "register_operand" "=x")
+	(vec_merge:V4SF
+	  (unspec:V4SF [(match_operand:V4SF 2 "register_operand" "x")
+			(match_operand:SI 3 "const_0_to_15_operand" "n")]
+		       UNSPEC_ROUND)
+	  (match_operand:V4SF 1 "register_operand" "0")
+	  (const_int 1)))]
+  "TARGET_ROUND"
+  "roundss\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "V4SF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; SSE5 instructions
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; SSE5 parallel integer multiply/add instructions.
+;; Note the instruction does not allow the value being added to be a memory
+;; operation.  However by pretending via the nonimmediate_operand predicate
+;; that it does and splitting it later allows the following to be recognized:
+;;	a[i] = b[i] * c[i] + d[i];
+(define_insn "sse5_pmacsww"
+  [(set (match_operand:V8HI 0 "register_operand" "=x,x,x")
+        (plus:V8HI
+	 (mult:V8HI
+	  (match_operand:V8HI 1 "nonimmediate_operand" "%x,x,m")
+	  (match_operand:V8HI 2 "nonimmediate_operand" "x,m,x"))
+	 (match_operand:V8HI 3 "nonimmediate_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 2)"
+  "@
+   pmacsww\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsww\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsww\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+;; Split pmacsww with two memory operands into a load and the pmacsww.
+(define_split
+  [(set (match_operand:V8HI 0 "register_operand" "")
+	(plus:V8HI
+	 (mult:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "")
+		    (match_operand:V8HI 2 "nonimmediate_operand" ""))
+	 (match_operand:V8HI 3 "nonimmediate_operand" "")))]
+  "TARGET_SSE5
+   && !ix86_sse5_valid_op_p (operands, insn, 4, false, 1)
+   && ix86_sse5_valid_op_p (operands, insn, 4, false, 2)
+   && !reg_mentioned_p (operands[0], operands[1])
+   && !reg_mentioned_p (operands[0], operands[2])
+   && !reg_mentioned_p (operands[0], operands[3])"
+  [(const_int 0)]
+{
+  ix86_expand_sse5_multiple_memory (operands, 4, V8HImode);
+  emit_insn (gen_sse5_pmacsww (operands[0], operands[1], operands[2],
+			       operands[3]));
+  DONE;
+})
+
+(define_insn "sse5_pmacssww"
+  [(set (match_operand:V8HI 0 "register_operand" "=x,x,x")
+        (ss_plus:V8HI
+	 (mult:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "%x,x,m")
+		    (match_operand:V8HI 2 "nonimmediate_operand" "x,m,x"))
+	 (match_operand:V8HI 3 "nonimmediate_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacssww\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssww\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssww\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+;; Note the instruction does not allow the value being added to be a memory
+;; operation.  However by pretending via the nonimmediate_operand predicate
+;; that it does and splitting it later allows the following to be recognized:
+;;	a[i] = b[i] * c[i] + d[i];
+(define_insn "sse5_pmacsdd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
+        (plus:V4SI
+	 (mult:V4SI
+	  (match_operand:V4SI 1 "nonimmediate_operand" "%x,x,m")
+	  (match_operand:V4SI 2 "nonimmediate_operand" "x,m,x"))
+	 (match_operand:V4SI 3 "nonimmediate_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 2)"
+  "@
+   pmacsdd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsdd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsdd\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+;; Split pmacsdd with two memory operands into a load and the pmacsdd.
+(define_split
+  [(set (match_operand:V4SI 0 "register_operand" "")
+	(plus:V4SI
+	 (mult:V4SI (match_operand:V4SI 1 "nonimmediate_operand" "")
+		    (match_operand:V4SI 2 "nonimmediate_operand" ""))
+	 (match_operand:V4SI 3 "nonimmediate_operand" "")))]
+  "TARGET_SSE5
+   && !ix86_sse5_valid_op_p (operands, insn, 4, false, 1)
+   && ix86_sse5_valid_op_p (operands, insn, 4, false, 2)
+   && !reg_mentioned_p (operands[0], operands[1])
+   && !reg_mentioned_p (operands[0], operands[2])
+   && !reg_mentioned_p (operands[0], operands[3])"
+  [(const_int 0)]
+{
+  ix86_expand_sse5_multiple_memory (operands, 4, V4SImode);
+  emit_insn (gen_sse5_pmacsdd (operands[0], operands[1], operands[2],
+			       operands[3]));
+  DONE;
+})
+
+(define_insn "sse5_pmacssdd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
+        (ss_plus:V4SI
+	 (mult:V4SI (match_operand:V4SI 1 "nonimmediate_operand" "%x,x,m")
+		    (match_operand:V4SI 2 "nonimmediate_operand" "x,m,x"))
+	 (match_operand:V4SI 3 "nonimmediate_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacssdd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssdd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssdd\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmacssdql"
+  [(set (match_operand:V2DI 0 "register_operand" "=x,x,x")
+	(ss_plus:V2DI
+	 (mult:V2DI
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 1 "nonimmediate_operand" "x,x,m")
+	    (parallel [(const_int 1)
+		       (const_int 3)])))
+	   (vec_select:V2SI
+	    (match_operand:V4SI 2 "nonimmediate_operand" "x,m,x")
+	    (parallel [(const_int 1)
+		       (const_int 3)])))
+	 (match_operand:V2DI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacssdql\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssdql\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssdql\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmacssdqh"
+  [(set (match_operand:V2DI 0 "register_operand" "=x,x,x")
+	(ss_plus:V2DI
+	 (mult:V2DI
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 1 "nonimmediate_operand" "x,x,m")
+	    (parallel [(const_int 0)
+		       (const_int 2)])))
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 2 "nonimmediate_operand" "x,m,x")
+	    (parallel [(const_int 0)
+		       (const_int 2)]))))
+	 (match_operand:V2DI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacssdqh\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssdqh\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacssdqh\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmacsdql"
+  [(set (match_operand:V2DI 0 "register_operand" "=x,x,x")
+	(plus:V2DI
+	 (mult:V2DI
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 1 "nonimmediate_operand" "x,x,m")
+	    (parallel [(const_int 1)
+		       (const_int 3)])))
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 2 "nonimmediate_operand" "x,m,x")
+	    (parallel [(const_int 1)
+		       (const_int 3)]))))
+	 (match_operand:V2DI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacsdql\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsdql\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsdql\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmacsdqh"
+  [(set (match_operand:V2DI 0 "register_operand" "=x,x,x")
+	(plus:V2DI
+	 (mult:V2DI
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 1 "nonimmediate_operand" "x,x,m")
+	    (parallel [(const_int 0)
+		       (const_int 2)])))
+	  (sign_extend:V2DI
+	   (vec_select:V2SI
+	    (match_operand:V4SI 2 "nonimmediate_operand" "x,m,x")
+	    (parallel [(const_int 0)
+		       (const_int 2)]))))
+	 (match_operand:V2DI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacsdqh\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsdqh\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsdqh\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+;; SSE5 parallel integer multiply/add instructions for the intrinisics
+(define_insn "sse5_pmacsswd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
+	(ss_plus:V4SI
+	 (mult:V4SI
+	  (sign_extend:V4SI
+	   (vec_select:V4HI
+	    (match_operand:V8HI 1 "nonimmediate_operand" "x,x,m")
+	    (parallel [(const_int 1)
+		       (const_int 3)
+		       (const_int 5)
+		       (const_int 7)])))
+	  (sign_extend:V4SI
+	   (vec_select:V4HI
+	    (match_operand:V8HI 2 "nonimmediate_operand" "x,m,x")
+	    (parallel [(const_int 1)
+		       (const_int 3)
+		       (const_int 5)
+		       (const_int 7)]))))
+	 (match_operand:V4SI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacsswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacsswd\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmacswd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
+	(plus:V4SI
+	 (mult:V4SI
+	  (sign_extend:V4SI
+	   (vec_select:V4HI
+	    (match_operand:V8HI 1 "nonimmediate_operand" "x,x,m")
+	    (parallel [(const_int 1)
+		       (const_int 3)
+		       (const_int 5)
+		       (const_int 7)])))
+	  (sign_extend:V4SI
+	   (vec_select:V4HI
+	    (match_operand:V8HI 2 "nonimmediate_operand" "x,m,x")
+	    (parallel [(const_int 1)
+		       (const_int 3)
+		       (const_int 5)
+		       (const_int 7)]))))
+	 (match_operand:V4SI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmacswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmacswd\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmadcsswd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
+	(ss_plus:V4SI
+	 (plus:V4SI
+	  (mult:V4SI
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_operand:V8HI 1 "nonimmediate_operand" "x,x,m")
+	     (parallel [(const_int 0)
+			(const_int 2)
+			(const_int 4)
+			(const_int 6)])))
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_operand:V8HI 2 "nonimmediate_operand" "x,m,x")
+	     (parallel [(const_int 0)
+			(const_int 2)
+			(const_int 4)
+			(const_int 6)]))))
+	  (mult:V4SI
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_dup 1)
+	     (parallel [(const_int 1)
+			(const_int 3)
+			(const_int 5)
+			(const_int 7)])))
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_dup 2)
+	     (parallel [(const_int 1)
+			(const_int 3)
+			(const_int 5)
+			(const_int 7)])))))
+	 (match_operand:V4SI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmadcsswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmadcsswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmadcsswd\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pmadcswd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
+	(plus:V4SI
+	 (plus:V4SI
+	  (mult:V4SI
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_operand:V8HI 1 "nonimmediate_operand" "x,x,m")
+	     (parallel [(const_int 0)
+			(const_int 2)
+			(const_int 4)
+			(const_int 6)])))
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_operand:V8HI 2 "nonimmediate_operand" "x,m,x")
+	     (parallel [(const_int 0)
+			(const_int 2)
+			(const_int 4)
+			(const_int 6)]))))
+	  (mult:V4SI
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_dup 1)
+	     (parallel [(const_int 1)
+			(const_int 3)
+			(const_int 5)
+			(const_int 7)])))
+	   (sign_extend:V4SI
+	    (vec_select:V4HI
+	     (match_dup 2)
+	     (parallel [(const_int 1)
+			(const_int 3)
+			(const_int 5)
+			(const_int 7)])))))
+	 (match_operand:V4SI 3 "register_operand" "0,0,0")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, false, 1)"
+  "@
+   pmadcswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmadcswd\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pmadcswd\t{%3, %1, %2, %0|%0, %2, %1, %3}"
+  [(set_attr "type" "ssemuladd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pcmov_<mode>"
+  [(set (match_operand:SSEMODE 0 "register_operand" "=x,x,x,x")
+	(if_then_else:SSEMODE
+	  (match_operand:SSEMODE 3 "nonimmediate_operand" "0,0,xm,x")
+	  (match_operand:SSEMODE 1 "nonimmediate_operand" "x,xm,0,0")
+	  (match_operand:SSEMODE 2 "nonimmediate_operand" "xm,x,x,xm")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "@
+   pcmov\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pcmov\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pcmov\t{%3, %2, %1, %0|%0, %1, %2, %3}
+   pcmov\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "sse4arg")])
+
+;; SSE5 horizontal add/subtract instructions
+(define_insn "sse5_phaddbw"
+  [(set (match_operand:V8HI 0 "register_operand" "=x")
+	(plus:V8HI
+	 (sign_extend:V8HI
+	  (vec_select:V8QI
+	   (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)
+		      (const_int 4)
+		      (const_int 6)
+		      (const_int 8)
+		      (const_int 10)
+		      (const_int 12)
+		      (const_int 14)])))
+	 (sign_extend:V8HI
+	  (vec_select:V8QI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)
+		      (const_int 5)
+		      (const_int 7)
+		      (const_int 9)
+		      (const_int 11)
+		      (const_int 13)
+		      (const_int 15)])))))]
+  "TARGET_SSE5"
+  "phaddbw\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddbd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x")
+	(plus:V4SI
+	 (plus:V4SI
+	  (sign_extend:V4SI
+	   (vec_select:V4QI
+	    (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	    (parallel [(const_int 0)
+		       (const_int 4)
+		       (const_int 8)
+		       (const_int 12)])))
+	  (sign_extend:V4SI
+	   (vec_select:V4QI
+	    (match_dup 1)
+	    (parallel [(const_int 1)
+		       (const_int 5)
+		       (const_int 9)
+		       (const_int 13)]))))
+	 (plus:V4SI
+	  (sign_extend:V4SI
+	   (vec_select:V4QI
+	    (match_dup 1)
+	    (parallel [(const_int 2)
+		       (const_int 6)
+		       (const_int 10)
+		       (const_int 14)])))
+	  (sign_extend:V4SI
+	   (vec_select:V4QI
+	    (match_dup 1)
+	    (parallel [(const_int 3)
+		       (const_int 7)
+		       (const_int 11)
+		       (const_int 15)]))))))]
+  "TARGET_SSE5"
+  "phaddbd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddbq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(plus:V2DI
+	 (plus:V2DI
+	  (plus:V2DI
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	     (parallel [(const_int 0)
+			(const_int 4)])))
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 1)
+			(const_int 5)]))))
+	  (plus:V2DI
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 2)
+			(const_int 6)])))
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 3)
+			(const_int 7)])))))
+	 (plus:V2DI
+	  (plus:V2DI
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 8)
+			(const_int 12)])))
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 9)
+			(const_int 13)]))))
+	  (plus:V2DI
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 10)
+			(const_int 14)])))
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 11)
+			(const_int 15)])))))))]
+  "TARGET_SSE5"
+  "phaddbq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddwd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x")
+	(plus:V4SI
+	 (sign_extend:V4SI
+	  (vec_select:V4HI
+	   (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)
+		      (const_int 4)
+		      (const_int 6)])))
+	 (sign_extend:V4SI
+	  (vec_select:V4HI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)
+		      (const_int 5)
+		      (const_int 7)])))))]
+  "TARGET_SSE5"
+  "phaddwd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddwq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(plus:V2DI
+	 (plus:V2DI
+	  (sign_extend:V2DI
+	   (vec_select:V2HI
+	    (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+	    (parallel [(const_int 0)
+		       (const_int 4)])))
+	  (sign_extend:V2DI
+	   (vec_select:V2HI
+	    (match_dup 1)
+	    (parallel [(const_int 1)
+		       (const_int 5)]))))
+	 (plus:V2DI
+	  (sign_extend:V2DI
+	   (vec_select:V2HI
+	    (match_dup 1)
+	    (parallel [(const_int 2)
+		       (const_int 6)])))
+	  (sign_extend:V2DI
+	   (vec_select:V2HI
+	    (match_dup 1)
+	    (parallel [(const_int 3)
+		       (const_int 7)]))))))]
+  "TARGET_SSE5"
+  "phaddwq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phadddq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(plus:V2DI
+	 (sign_extend:V2DI
+	  (vec_select:V2SI
+	   (match_operand:V4SI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)])))
+	 (sign_extend:V2DI
+	  (vec_select:V2SI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)])))))]
+  "TARGET_SSE5"
+  "phadddq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddubw"
+  [(set (match_operand:V8HI 0 "register_operand" "=x")
+	(plus:V8HI
+	 (zero_extend:V8HI
+	  (vec_select:V8QI
+	   (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)
+		      (const_int 4)
+		      (const_int 6)
+		      (const_int 8)
+		      (const_int 10)
+		      (const_int 12)
+		      (const_int 14)])))
+	 (zero_extend:V8HI
+	  (vec_select:V8QI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)
+		      (const_int 5)
+		      (const_int 7)
+		      (const_int 9)
+		      (const_int 11)
+		      (const_int 13)
+		      (const_int 15)])))))]
+  "TARGET_SSE5"
+  "phaddubw\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddubd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x")
+	(plus:V4SI
+	 (plus:V4SI
+	  (zero_extend:V4SI
+	   (vec_select:V4QI
+	    (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	    (parallel [(const_int 0)
+		       (const_int 4)
+		       (const_int 8)
+		       (const_int 12)])))
+	  (zero_extend:V4SI
+	   (vec_select:V4QI
+	    (match_dup 1)
+	    (parallel [(const_int 1)
+		       (const_int 5)
+		       (const_int 9)
+		       (const_int 13)]))))
+	 (plus:V4SI
+	  (zero_extend:V4SI
+	   (vec_select:V4QI
+	    (match_dup 1)
+	    (parallel [(const_int 2)
+		       (const_int 6)
+		       (const_int 10)
+		       (const_int 14)])))
+	  (zero_extend:V4SI
+	   (vec_select:V4QI
+	    (match_dup 1)
+	    (parallel [(const_int 3)
+		       (const_int 7)
+		       (const_int 11)
+		       (const_int 15)]))))))]
+  "TARGET_SSE5"
+  "phaddubd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddubq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(plus:V2DI
+	 (plus:V2DI
+	  (plus:V2DI
+	   (zero_extend:V2DI
+	    (vec_select:V2QI
+	     (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	     (parallel [(const_int 0)
+			(const_int 4)])))
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 1)
+			(const_int 5)]))))
+	  (plus:V2DI
+	   (zero_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 2)
+			(const_int 6)])))
+	   (zero_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 3)
+			(const_int 7)])))))
+	 (plus:V2DI
+	  (plus:V2DI
+	   (zero_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 8)
+			(const_int 12)])))
+	   (sign_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 9)
+			(const_int 13)]))))
+	  (plus:V2DI
+	   (zero_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 10)
+			(const_int 14)])))
+	   (zero_extend:V2DI
+	    (vec_select:V2QI
+	     (match_dup 1)
+	     (parallel [(const_int 11)
+			(const_int 15)])))))))]
+  "TARGET_SSE5"
+  "phaddubq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phadduwd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x")
+	(plus:V4SI
+	 (zero_extend:V4SI
+	  (vec_select:V4HI
+	   (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)
+		      (const_int 4)
+		      (const_int 6)])))
+	 (zero_extend:V4SI
+	  (vec_select:V4HI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)
+		      (const_int 5)
+		      (const_int 7)])))))]
+  "TARGET_SSE5"
+  "phadduwd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phadduwq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(plus:V2DI
+	 (plus:V2DI
+	  (zero_extend:V2DI
+	   (vec_select:V2HI
+	    (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+	    (parallel [(const_int 0)
+		       (const_int 4)])))
+	  (zero_extend:V2DI
+	   (vec_select:V2HI
+	    (match_dup 1)
+	    (parallel [(const_int 1)
+		       (const_int 5)]))))
+	 (plus:V2DI
+	  (zero_extend:V2DI
+	   (vec_select:V2HI
+	    (match_dup 1)
+	    (parallel [(const_int 2)
+		       (const_int 6)])))
+	  (zero_extend:V2DI
+	   (vec_select:V2HI
+	    (match_dup 1)
+	    (parallel [(const_int 3)
+		       (const_int 7)]))))))]
+  "TARGET_SSE5"
+  "phadduwq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phaddudq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(plus:V2DI
+	 (zero_extend:V2DI
+	  (vec_select:V2SI
+	   (match_operand:V4SI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)])))
+	 (zero_extend:V2DI
+	  (vec_select:V2SI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)])))))]
+  "TARGET_SSE5"
+  "phaddudq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phsubbw"
+  [(set (match_operand:V8HI 0 "register_operand" "=x")
+	(minus:V8HI
+	 (sign_extend:V8HI
+	  (vec_select:V8QI
+	   (match_operand:V16QI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)
+		      (const_int 4)
+		      (const_int 6)
+		      (const_int 8)
+		      (const_int 10)
+		      (const_int 12)
+		      (const_int 14)])))
+	 (sign_extend:V8HI
+	  (vec_select:V8QI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)
+		      (const_int 5)
+		      (const_int 7)
+		      (const_int 9)
+		      (const_int 11)
+		      (const_int 13)
+		      (const_int 15)])))))]
+  "TARGET_SSE5"
+  "phsubbw\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phsubwd"
+  [(set (match_operand:V4SI 0 "register_operand" "=x")
+	(minus:V4SI
+	 (sign_extend:V4SI
+	  (vec_select:V4HI
+	   (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)
+		      (const_int 4)
+		      (const_int 6)])))
+	 (sign_extend:V4SI
+	  (vec_select:V4HI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)
+		      (const_int 5)
+		      (const_int 7)])))))]
+  "TARGET_SSE5"
+  "phsubwd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+(define_insn "sse5_phsubdq"
+  [(set (match_operand:V2DI 0 "register_operand" "=x")
+	(minus:V2DI
+	 (sign_extend:V2DI
+	  (vec_select:V2SI
+	   (match_operand:V4SI 1 "nonimmediate_operand" "xm")
+	   (parallel [(const_int 0)
+		      (const_int 2)])))
+	 (sign_extend:V2DI
+	  (vec_select:V2SI
+	   (match_dup 1)
+	   (parallel [(const_int 1)
+		      (const_int 3)])))))]
+  "TARGET_SSE5"
+  "phsubdq\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseiadd1")])
+
+;; SSE5 permute instructions
+(define_insn "sse5_pperm"
+  [(set (match_operand:V16QI 0 "register_operand" "=x,x,x,x")
+	(unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "0,0,xm,xm")
+		       (match_operand:V16QI 2 "nonimmediate_operand" "x,xm,0,x")
+		       (match_operand:V16QI 3 "nonimmediate_operand" "xm,x,x,0")]
+		     UNSPEC_SSE5_PERMUTE))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "pperm\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "TI")])
+
+;; The following are for the various unpack insns which doesn't need the first
+;; source operand, so we can just use the output operand for the first operand.
+;; This allows either of the other two operands to be a memory operand.  We
+;; can't just use the first operand as an argument to the normal pperm because
+;; then an output only argument, suddenly becomes an input operand.
+(define_insn "sse5_pperm_zero_v16qi_v8hi"
+  [(set (match_operand:V8HI 0 "register_operand" "=x,x")
+	(zero_extend:V8HI
+	 (vec_select:V8QI
+	  (match_operand:V16QI 1 "nonimmediate_operand" "xm,x")
+	  (match_operand 2 "" ""))))	;; parallel with const_int's
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "x,xm"))]
+  "TARGET_SSE5
+   && (register_operand (operands[1], V16QImode)
+       || register_operand (operands[2], V16QImode))"
+  "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+  [(set_attr "type" "sseadd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_sign_v16qi_v8hi"
+  [(set (match_operand:V8HI 0 "register_operand" "=x,x")
+	(sign_extend:V8HI
+	 (vec_select:V8QI
+	  (match_operand:V16QI 1 "nonimmediate_operand" "xm,x")
+	  (match_operand 2 "" ""))))	;; parallel with const_int's
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "x,xm"))]
+  "TARGET_SSE5
+   && (register_operand (operands[1], V16QImode)
+       || register_operand (operands[2], V16QImode))"
+  "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+  [(set_attr "type" "sseadd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_zero_v8hi_v4si"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x")
+	(zero_extend:V4SI
+	 (vec_select:V4HI
+	  (match_operand:V8HI 1 "nonimmediate_operand" "xm,x")
+	  (match_operand 2 "" ""))))	;; parallel with const_int's
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "x,xm"))]
+  "TARGET_SSE5
+   && (register_operand (operands[1], V8HImode)
+       || register_operand (operands[2], V16QImode))"
+  "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+  [(set_attr "type" "sseadd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_sign_v8hi_v4si"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x")
+	(sign_extend:V4SI
+	 (vec_select:V4HI
+	  (match_operand:V8HI 1 "nonimmediate_operand" "xm,x")
+	  (match_operand 2 "" ""))))	;; parallel with const_int's
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "x,xm"))]
+  "TARGET_SSE5
+   && (register_operand (operands[1], V8HImode)
+       || register_operand (operands[2], V16QImode))"
+  "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+  [(set_attr "type" "sseadd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_zero_v4si_v2di"
+  [(set (match_operand:V2DI 0 "register_operand" "=x,x")
+	(zero_extend:V2DI
+	 (vec_select:V2SI
+	  (match_operand:V4SI 1 "nonimmediate_operand" "xm,x")
+	  (match_operand 2 "" ""))))	;; parallel with const_int's
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "x,xm"))]
+  "TARGET_SSE5
+   && (register_operand (operands[1], V4SImode)
+       || register_operand (operands[2], V16QImode))"
+  "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+  [(set_attr "type" "sseadd")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_sign_v4si_v2di"
+  [(set (match_operand:V2DI 0 "register_operand" "=x,x")
+	(sign_extend:V2DI
+	 (vec_select:V2SI
+	  (match_operand:V4SI 1 "nonimmediate_operand" "xm,x")
+	  (match_operand 2 "" ""))))	;; parallel with const_int's
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "x,xm"))]
+  "TARGET_SSE5
+   && (register_operand (operands[1], V4SImode)
+       || register_operand (operands[2], V16QImode))"
+  "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+  [(set_attr "type" "sseadd")
+   (set_attr "mode" "TI")])
+
+;; SSE5 pack instructions that combine two vectors into a smaller vector
+(define_insn "sse5_pperm_pack_v2di_v4si"
+  [(set (match_operand:V4SI 0 "register_operand" "=x,x,x,x")
+	(vec_concat:V4SI
+	 (truncate:V2SI
+	  (match_operand:V2DI 1 "nonimmediate_operand" "0,0,xm,xm"))
+	 (truncate:V2SI
+	  (match_operand:V2DI 2 "nonimmediate_operand" "x,xm,0,x"))))
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "xm,x,x,0"))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "pperm\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_pack_v4si_v8hi"
+  [(set (match_operand:V8HI 0 "register_operand" "=x,x,x,x")
+	(vec_concat:V8HI
+	 (truncate:V4HI
+	  (match_operand:V4SI 1 "nonimmediate_operand" "0,0,xm,xm"))
+	 (truncate:V4HI
+	  (match_operand:V4SI 2 "nonimmediate_operand" "x,xm,0,x"))))
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "xm,x,x,0"))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "pperm\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_pperm_pack_v8hi_v16qi"
+  [(set (match_operand:V16QI 0 "register_operand" "=x,x,x,x")
+	(vec_concat:V16QI
+	 (truncate:V8QI
+	  (match_operand:V8HI 1 "nonimmediate_operand" "0,0,xm,xm"))
+	 (truncate:V8QI
+	  (match_operand:V8HI 2 "nonimmediate_operand" "x,xm,0,x"))))
+   (use (match_operand:V16QI 3 "nonimmediate_operand" "xm,x,x,0"))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "pperm\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "TI")])
+
+;; Floating point permutation (permps, permpd)
+(define_insn "sse5_perm<mode>"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x,x,x")
+	(unspec:SSEMODEF2P
+	 [(match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0,xm,xm")
+	  (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm,0,x")
+	  (match_operand:V16QI 3 "nonimmediate_operand" "xm,x,x,0")]
+	 UNSPEC_SSE5_PERMUTE))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "perm<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "<MODE>")])
+
+;; SSE5 packed rotate instructions
+(define_insn "rotl<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x")
+	(rotate:SSEMODE1248
+	 (match_operand:SSEMODE1248 1 "nonimmediate_operand" "xm")
+	 (match_operand:SI 2 "const_0_to_<sserotatemax>_operand" "n")))]
+  "TARGET_SSE5"
+  "prot<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "sseishft")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_rotl<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x,x")
+	(rotate:SSEMODE1248
+	 (match_operand:SSEMODE1248 1 "nonimmediate_operand" "x,xm")
+	 (match_operand:SSEMODE1248 2 "nonimmediate_operand" "xm,x")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1)"
+  "prot<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "sseishft")
+   (set_attr "mode" "TI")])
+
+;; SSE5 packed shift instructions.  Note negative values for the shift amount
+;; convert this into a right shift instead of left shift.  For now, model this
+;; with an UNSPEC instead of using ashift/lshift since the rest of the x86 does
+;; not have the concept of negating the shift amount.  Also, there is no LSHIFT
+(define_insn "sse5_ashl<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x,x")
+	(unspec:SSEMODE1248
+	 [(match_operand:SSEMODE1248 1 "nonimmediate_operand" "x,xm")
+	  (match_operand:SSEMODE1248 2 "nonimmediate_operand" "xm,x")]
+	 UNSPEC_SSE5_ASHIFT))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1)"
+  "psha<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "sseishft")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_lshl<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x,x")
+	(unspec:SSEMODE1248
+	 [(match_operand:SSEMODE1248 1 "nonimmediate_operand" "x,xm")
+	  (match_operand:SSEMODE1248 2 "nonimmediate_operand" "xm,x")]
+	 UNSPEC_SSE5_LSHIFT))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1)"
+  "pshl<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "sseishft")
+   (set_attr "mode" "TI")])
+
+;; SSE5 FRCZ support
+;; parallel insns
+(define_insn "sse5_frcz<mode>2"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
+	(unspec:SSEMODEF2P
+	 [(match_operand:SSEMODEF2P 1 "nonimmediate_operand" "xm")]
+	 UNSPEC_FRCZ))]
+  "TARGET_SSE5"
+  "frcz<ssesuffixf4>\t{%1, %0|%0, %1}"
+  [(set_attr "type" "ssecvt1")
+   (set_attr "mode" "<MODE>")])
+
+;; scalar insns
+(define_insn "sse5_vmfrcz<mode>2"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
+	(vec_merge:SSEMODEF2P
+	  (unspec:SSEMODEF2P
+	   [(match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")]
+	   UNSPEC_FRCZ)
+	  (match_operand:SSEMODEF2P 1 "register_operand" "0")
+	  (const_int 1)))]
+  "TARGET_ROUND"
+  "frcz<ssesuffixf2s>\t{%2, %0|%0, %2}"
+  [(set_attr "type" "ssecvt1")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "sse5_cvtph2ps"
+  [(set (match_operand:V4SF 0 "register_operand" "=x")
+	(unspec:V4SF [(match_operand:V4HI 1 "nonimmediate_operand" "xm")]
+		     UNSPEC_CVTPH2PS))]
+  "TARGET_SSE5"
+  "cvtph2ps\t{%1, %0|%0, %1}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "V4SF")])
+
+(define_insn "sse5_cvtps2ph"
+  [(set (match_operand:V4HI 0 "nonimmediate_operand" "=xm")
+	(unspec:V4HI [(match_operand:V4SF 1 "register_operand" "x")]
+		     UNSPEC_CVTPS2PH))]
+  "TARGET_SSE5"
+  "cvtps2ph\t{%1, %0|%0, %1}"
+  [(set_attr "type" "ssecvt")
+   (set_attr "mode" "V4SF")])
+
+;; Scalar versions of the com instructions that use vector types that are
+;; called from the intrinsics.  Unlike the the other s{s,d} instructions, the
+;; com instructions fill in 0's in the upper bits instead of leaving them
+;; unmodified, so we use const_vector of 0 instead of match_dup.
+(define_expand "sse5_vmmaskcmp<mode>3"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "")
+	(vec_merge:SSEMODEF2P
+	 (match_operator:SSEMODEF2P 1 "sse5_comparison_float_operator"
+	  [(match_operand:SSEMODEF2P 2 "register_operand" "")
+	   (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "")])
+	 (match_dup 4)
+	 (const_int 1)))]
+  "TARGET_SSE5"
+{
+  operands[4] = CONST0_RTX (<MODE>mode);
+})
+
+(define_insn "*sse5_vmmaskcmp<mode>3"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
+	(vec_merge:SSEMODEF2P
+	 (match_operator:SSEMODEF2P 1 "sse5_comparison_float_operator"
+	  [(match_operand:SSEMODEF2P 2 "register_operand" "x")
+	   (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm")])
+	  (match_operand:SSEMODEF2P 4 "")
+	  (const_int 1)))]
+  "TARGET_SSE5"
+  "com%Y1<ssemodesuffixf2s>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "<ssescalarmode>")])
+
+;; We don't have a comparison operator that always returns true/false, so
+;; handle comfalse and comtrue specially.
+(define_insn "sse5_com_tf<mode>3"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
+	(unspec:SSEMODEF2P
+	 [(match_operand:SSEMODEF2P 1 "register_operand" "x")
+	  (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "xm")
+	  (match_operand:SI 3 "const_int_operand" "n")]
+	 UNSPEC_SSE5_TRUEFALSE))]
+  "TARGET_SSE5"
+{
+  const char *ret = NULL;
+
+  switch (INTVAL (operands[3]))
+    {
+    case COM_FALSE_S:
+      ret = \"comfalses<ssemodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}\";
+      break;
+
+    case COM_FALSE_P:
+      ret = \"comfalsep<ssemodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}\";
+      break;
+
+    case COM_TRUE_S:
+      ret = \"comfalses<ssemodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}\";
+      break;
+
+    case COM_TRUE_P:
+      ret = \"comfalsep<ssemodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}\";
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return ret;
+}
+  [(set_attr "type" "ssecmp")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "sse5_maskcmp<mode>3"
+  [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x")
+	(match_operator:SSEMODEF2P 1 "sse5_comparison_float_operator"
+	 [(match_operand:SSEMODEF2P 2 "register_operand" "x")
+	  (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm")]))]
+  "TARGET_SSE5"
+  "com%Y1<ssemodesuffixf4>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "ssecmp")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "sse5_maskcmp<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x")
+	(match_operator:SSEMODE1248 1 "ix86_comparison_int_operator"
+	 [(match_operand:SSEMODE1248 2 "register_operand" "x")
+	  (match_operand:SSEMODE1248 3 "nonimmediate_operand" "xm")]))]
+  "TARGET_SSE5"
+  "pcom%Y1<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "TI")])
+
+(define_insn "sse5_maskcmp_uns<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x")
+	(match_operator:SSEMODE1248 1 "ix86_comparison_uns_operator"
+	 [(match_operand:SSEMODE1248 2 "register_operand" "x")
+	  (match_operand:SSEMODE1248 3 "nonimmediate_operand" "xm")]))]
+  "TARGET_SSE5"
+  "pcom%Y1u<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "ssecmp")
+   (set_attr "mode" "TI")])
+
+;; Version of pcom*u* that is called from the intrinsics that allows pcomequ*
+;; and pcomneu* not to be converted to the signed ones in case somebody needs
+;; the exact instruction generated for the intrinsic.
+(define_insn "sse5_maskcmp_uns2<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x")
+	(unspec:SSEMODE1248
+	 [(match_operator:SSEMODE1248 1 "ix86_comparison_uns_operator"
+	  [(match_operand:SSEMODE1248 2 "register_operand" "x")
+	   (match_operand:SSEMODE1248 3 "nonimmediate_operand" "xm")])]
+	 UNSPEC_SSE5_UNSIGNED_CMP))]
+  "TARGET_SSE5"
+  "pcom%Y1u<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "ssecmp")
+   (set_attr "mode" "TI")])
+
+;; Pcomtrue and pcomfalse support.  These are useless instructions, but are
+;; being added here to be complete.
+(define_insn "sse5_pcom_tf<mode>3"
+  [(set (match_operand:SSEMODE1248 0 "register_operand" "=x")
+	(unspec:SSEMODE1248 [(match_operand:SSEMODE1248 1 "register_operand" "x")
+			     (match_operand:SSEMODE1248 2 "nonimmediate_operand" "xm")
+			     (match_operand:SI 3 "const_int_operand" "n")]
+			    UNSPEC_SSE5_TRUEFALSE))]
+  "TARGET_SSE5"
+{
+  return ((INTVAL (operands[3]) != 0)
+	  ? "pcomtrue<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+	  : "pcomfalse<ssevecsize>\t{%2, %1, %0|%0, %1, %2}");
+}
+  [(set_attr "type" "ssecmp")
+   (set_attr "mode" "TI")])
--- gcc/doc/extend.texi.jj	2007-12-28 15:43:26.000000000 +0100
+++ gcc/doc/extend.texi	2007-12-28 20:04:35.000000000 +0100
@@ -5970,6 +5970,222 @@ Similar to @code{__builtin_powi}, except
 are @code{long double}.
 @end deftypefn
 
+The following built-in functions are available when @option{-msse5} is used.
+All of them generate the machine instruction that is part of the name
+with MMX registers.
+
+@smallexample
+v2df __builtin_ia32_comeqpd (v2df, v2df)
+v2df __builtin_ia32_comeqps (v2df, v2df)
+v4sf __builtin_ia32_comeqsd (v4sf, v4sf)
+v4sf __builtin_ia32_comeqss (v4sf, v4sf)
+v2df __builtin_ia32_comfalsepd (v2df, v2df)
+v2df __builtin_ia32_comfalseps (v2df, v2df)
+v4sf __builtin_ia32_comfalsesd (v4sf, v4sf)
+v4sf __builtin_ia32_comfalsess (v4sf, v4sf)
+v2df __builtin_ia32_comgepd (v2df, v2df)
+v2df __builtin_ia32_comgeps (v2df, v2df)
+v4sf __builtin_ia32_comgesd (v4sf, v4sf)
+v4sf __builtin_ia32_comgess (v4sf, v4sf)
+v2df __builtin_ia32_comgtpd (v2df, v2df)
+v2df __builtin_ia32_comgtps (v2df, v2df)
+v4sf __builtin_ia32_comgtsd (v4sf, v4sf)
+v4sf __builtin_ia32_comgtss (v4sf, v4sf)
+v2df __builtin_ia32_comlepd (v2df, v2df)
+v2df __builtin_ia32_comleps (v2df, v2df)
+v4sf __builtin_ia32_comlesd (v4sf, v4sf)
+v4sf __builtin_ia32_comless (v4sf, v4sf)
+v2df __builtin_ia32_comltpd (v2df, v2df)
+v2df __builtin_ia32_comltps (v2df, v2df)
+v4sf __builtin_ia32_comltsd (v4sf, v4sf)
+v4sf __builtin_ia32_comltss (v4sf, v4sf)
+v2df __builtin_ia32_comnepd (v2df, v2df)
+v2df __builtin_ia32_comneps (v2df, v2df)
+v4sf __builtin_ia32_comnesd (v4sf, v4sf)
+v4sf __builtin_ia32_comness (v4sf, v4sf)
+v2df __builtin_ia32_comordpd (v2df, v2df)
+v2df __builtin_ia32_comordps (v2df, v2df)
+v4sf __builtin_ia32_comordsd (v4sf, v4sf)
+v4sf __builtin_ia32_comordss (v4sf, v4sf)
+v2df __builtin_ia32_comtruepd (v2df, v2df)
+v2df __builtin_ia32_comtrueps (v2df, v2df)
+v4sf __builtin_ia32_comtruesd (v4sf, v4sf)
+v4sf __builtin_ia32_comtruess (v4sf, v4sf)
+v2df __builtin_ia32_comueqpd (v2df, v2df)
+v2df __builtin_ia32_comueqps (v2df, v2df)
+v4sf __builtin_ia32_comueqsd (v4sf, v4sf)
+v4sf __builtin_ia32_comueqss (v4sf, v4sf)
+v2df __builtin_ia32_comugepd (v2df, v2df)
+v2df __builtin_ia32_comugeps (v2df, v2df)
+v4sf __builtin_ia32_comugesd (v4sf, v4sf)
+v4sf __builtin_ia32_comugess (v4sf, v4sf)
+v2df __builtin_ia32_comugtpd (v2df, v2df)
+v2df __builtin_ia32_comugtps (v2df, v2df)
+v4sf __builtin_ia32_comugtsd (v4sf, v4sf)
+v4sf __builtin_ia32_comugtss (v4sf, v4sf)
+v2df __builtin_ia32_comulepd (v2df, v2df)
+v2df __builtin_ia32_comuleps (v2df, v2df)
+v4sf __builtin_ia32_comulesd (v4sf, v4sf)
+v4sf __builtin_ia32_comuless (v4sf, v4sf)
+v2df __builtin_ia32_comultpd (v2df, v2df)
+v2df __builtin_ia32_comultps (v2df, v2df)
+v4sf __builtin_ia32_comultsd (v4sf, v4sf)
+v4sf __builtin_ia32_comultss (v4sf, v4sf)
+v2df __builtin_ia32_comunepd (v2df, v2df)
+v2df __builtin_ia32_comuneps (v2df, v2df)
+v4sf __builtin_ia32_comunesd (v4sf, v4sf)
+v4sf __builtin_ia32_comuness (v4sf, v4sf)
+v2df __builtin_ia32_comunordpd (v2df, v2df)
+v2df __builtin_ia32_comunordps (v2df, v2df)
+v4sf __builtin_ia32_comunordsd (v4sf, v4sf)
+v4sf __builtin_ia32_comunordss (v4sf, v4sf)
+v2df __builtin_ia32_fmaddpd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fmaddps (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fmaddsd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fmaddss (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fmsubpd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fmsubps (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fmsubsd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fmsubss (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fnmaddpd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fnmaddps (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fnmaddsd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fnmaddss (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fnmsubpd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fnmsubps (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_fnmsubsd (v2df, v2df, v2df)
+v4sf __builtin_ia32_fnmsubss (v4sf, v4sf, v4sf)
+v2df __builtin_ia32_frczpd (v2df)
+v4sf __builtin_ia32_frczps (v4sf)
+v2df __builtin_ia32_frczsd (v2df, v2df)
+v4sf __builtin_ia32_frczss (v4sf, v4sf)
+v2di __builtin_ia32_pcmov (v2di, v2di, v2di)
+v2di __builtin_ia32_pcmov_v2di (v2di, v2di, v2di)
+v4si __builtin_ia32_pcmov_v4si (v4si, v4si, v4si)
+v8hi __builtin_ia32_pcmov_v8hi (v8hi, v8hi, v8hi)
+v16qi __builtin_ia32_pcmov_v16qi (v16qi, v16qi, v16qi)
+v2df __builtin_ia32_pcmov_v2df (v2df, v2df, v2df)
+v4sf __builtin_ia32_pcmov_v4sf (v4sf, v4sf, v4sf)
+v16qi __builtin_ia32_pcomeqb (v16qi, v16qi)
+v8hi __builtin_ia32_pcomeqw (v8hi, v8hi)
+v4si __builtin_ia32_pcomeqd (v4si, v4si)
+v2di __builtin_ia32_pcomeqq (v2di, v2di)
+v16qi __builtin_ia32_pcomequb (v16qi, v16qi)
+v4si __builtin_ia32_pcomequd (v4si, v4si)
+v2di __builtin_ia32_pcomequq (v2di, v2di)
+v8hi __builtin_ia32_pcomequw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomeqw (v8hi, v8hi)
+v16qi __builtin_ia32_pcomfalseb (v16qi, v16qi)
+v4si __builtin_ia32_pcomfalsed (v4si, v4si)
+v2di __builtin_ia32_pcomfalseq (v2di, v2di)
+v16qi __builtin_ia32_pcomfalseub (v16qi, v16qi)
+v4si __builtin_ia32_pcomfalseud (v4si, v4si)
+v2di __builtin_ia32_pcomfalseuq (v2di, v2di)
+v8hi __builtin_ia32_pcomfalseuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomfalsew (v8hi, v8hi)
+v16qi __builtin_ia32_pcomgeb (v16qi, v16qi)
+v4si __builtin_ia32_pcomged (v4si, v4si)
+v2di __builtin_ia32_pcomgeq (v2di, v2di)
+v16qi __builtin_ia32_pcomgeub (v16qi, v16qi)
+v4si __builtin_ia32_pcomgeud (v4si, v4si)
+v2di __builtin_ia32_pcomgeuq (v2di, v2di)
+v8hi __builtin_ia32_pcomgeuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomgew (v8hi, v8hi)
+v16qi __builtin_ia32_pcomgtb (v16qi, v16qi)
+v4si __builtin_ia32_pcomgtd (v4si, v4si)
+v2di __builtin_ia32_pcomgtq (v2di, v2di)
+v16qi __builtin_ia32_pcomgtub (v16qi, v16qi)
+v4si __builtin_ia32_pcomgtud (v4si, v4si)
+v2di __builtin_ia32_pcomgtuq (v2di, v2di)
+v8hi __builtin_ia32_pcomgtuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomgtw (v8hi, v8hi)
+v16qi __builtin_ia32_pcomleb (v16qi, v16qi)
+v4si __builtin_ia32_pcomled (v4si, v4si)
+v2di __builtin_ia32_pcomleq (v2di, v2di)
+v16qi __builtin_ia32_pcomleub (v16qi, v16qi)
+v4si __builtin_ia32_pcomleud (v4si, v4si)
+v2di __builtin_ia32_pcomleuq (v2di, v2di)
+v8hi __builtin_ia32_pcomleuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomlew (v8hi, v8hi)
+v16qi __builtin_ia32_pcomltb (v16qi, v16qi)
+v4si __builtin_ia32_pcomltd (v4si, v4si)
+v2di __builtin_ia32_pcomltq (v2di, v2di)
+v16qi __builtin_ia32_pcomltub (v16qi, v16qi)
+v4si __builtin_ia32_pcomltud (v4si, v4si)
+v2di __builtin_ia32_pcomltuq (v2di, v2di)
+v8hi __builtin_ia32_pcomltuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomltw (v8hi, v8hi)
+v16qi __builtin_ia32_pcomneb (v16qi, v16qi)
+v4si __builtin_ia32_pcomned (v4si, v4si)
+v2di __builtin_ia32_pcomneq (v2di, v2di)
+v16qi __builtin_ia32_pcomneub (v16qi, v16qi)
+v4si __builtin_ia32_pcomneud (v4si, v4si)
+v2di __builtin_ia32_pcomneuq (v2di, v2di)
+v8hi __builtin_ia32_pcomneuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomnew (v8hi, v8hi)
+v16qi __builtin_ia32_pcomtrueb (v16qi, v16qi)
+v4si __builtin_ia32_pcomtrued (v4si, v4si)
+v2di __builtin_ia32_pcomtrueq (v2di, v2di)
+v16qi __builtin_ia32_pcomtrueub (v16qi, v16qi)
+v4si __builtin_ia32_pcomtrueud (v4si, v4si)
+v2di __builtin_ia32_pcomtrueuq (v2di, v2di)
+v8hi __builtin_ia32_pcomtrueuw (v8hi, v8hi)
+v8hi __builtin_ia32_pcomtruew (v8hi, v8hi)
+v4df __builtin_ia32_permpd (v2df, v2df, v16qi)
+v4sf __builtin_ia32_permps (v4sf, v4sf, v16qi)
+v4si __builtin_ia32_phaddbd (v16qi)
+v2di __builtin_ia32_phaddbq (v16qi)
+v8hi __builtin_ia32_phaddbw (v16qi)
+v2di __builtin_ia32_phadddq (v4si)
+v4si __builtin_ia32_phaddubd (v16qi)
+v2di __builtin_ia32_phaddubq (v16qi)
+v8hi __builtin_ia32_phaddubw (v16qi)
+v2di __builtin_ia32_phaddudq (v4si)
+v4si __builtin_ia32_phadduwd (v8hi)
+v2di __builtin_ia32_phadduwq (v8hi)
+v4si __builtin_ia32_phaddwd (v8hi)
+v2di __builtin_ia32_phaddwq (v8hi)
+v8hi __builtin_ia32_phsubbw (v16qi)
+v2di __builtin_ia32_phsubdq (v4si)
+v4si __builtin_ia32_phsubwd (v8hi)
+v4si __builtin_ia32_pmacsdd (v4si, v4si, v4si)
+v2di __builtin_ia32_pmacsdqh (v4si, v4si, v2di)
+v2di __builtin_ia32_pmacsdql (v4si, v4si, v2di)
+v4si __builtin_ia32_pmacssdd (v4si, v4si, v4si)
+v2di __builtin_ia32_pmacssdqh (v4si, v4si, v2di)
+v2di __builtin_ia32_pmacssdql (v4si, v4si, v2di)
+v4si __builtin_ia32_pmacsswd (v8hi, v8hi, v4si)
+v8hi __builtin_ia32_pmacssww (v8hi, v8hi, v8hi)
+v4si __builtin_ia32_pmacswd (v8hi, v8hi, v4si)
+v8hi __builtin_ia32_pmacsww (v8hi, v8hi, v8hi)
+v4si __builtin_ia32_pmadcsswd (v8hi, v8hi, v4si)
+v4si __builtin_ia32_pmadcswd (v8hi, v8hi, v4si)
+v16qi __builtin_ia32_pperm (v16qi, v16qi, v16qi)
+v16qi __builtin_ia32_protb (v16qi, v16qi)
+v4si __builtin_ia32_protd (v4si, v4si)
+v2di __builtin_ia32_protq (v2di, v2di)
+v8hi __builtin_ia32_protw (v8hi, v8hi)
+v16qi __builtin_ia32_pshab (v16qi, v16qi)
+v4si __builtin_ia32_pshad (v4si, v4si)
+v2di __builtin_ia32_pshaq (v2di, v2di)
+v8hi __builtin_ia32_pshaw (v8hi, v8hi)
+v16qi __builtin_ia32_pshlb (v16qi, v16qi)
+v4si __builtin_ia32_pshld (v4si, v4si)
+v2di __builtin_ia32_pshlq (v2di, v2di)
+v8hi __builtin_ia32_pshlw (v8hi, v8hi)
+@end smallexample
+
+The following builtin-in functions are available when @option{-msse5}
+is used.  The second argument must be an integer constant and generate
+the machine instruction that is part of the name with the @samp{_imm}
+suffix removed.
+
+@smallexample
+v16qi __builtin_ia32_protb_imm (v16qi, int)
+v4si __builtin_ia32_protd_imm (v4si, int)
+v2di __builtin_ia32_protq_imm (v2di, int)
+v8hi __builtin_ia32_protw_imm (v8hi, int)
+@end smallexample
 
 @node Target Builtins
 @section Built-in Functions Specific to Particular Target Machines
--- gcc/doc/invoke.texi.jj	2007-11-24 21:47:34.000000000 +0100
+++ gcc/doc/invoke.texi	2007-12-28 20:06:54.000000000 +0100
@@ -525,13 +525,14 @@ Objective-C and Objective-C++ Dialects}.
 -mno-fp-ret-in-387  -msoft-float  -msvr3-shlib @gol
 -mno-wide-multiply  -mrtd  -malign-double @gol
 -mpreferred-stack-boundary=@var{num} @gol
--mmmx  -msse  -msse2 -msse3 -mssse3 -msse4a -m3dnow -mpopcnt -mabm @gol
+-mmmx  -msse  -msse2 -msse3 -mssse3 -msse4a -msse5 -m3dnow -mpopcnt -mabm @gol
 -mthreads  -mno-align-stringops  -minline-all-stringops @gol
 -mpush-args  -maccumulate-outgoing-args  -m128bit-long-double @gol
 -m96bit-long-double  -mregparm=@var{num}  -msseregparm @gol
 -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
 -mcmodel=@var{code-model} @gol
--m32  -m64 -mlarge-data-threshold=@var{num}}
+-m32  -m64 -mlarge-data-threshold=@var{num}
+-mfused-madd -mno-fused-madd}
 
 @emph{IA-64 Options}
 @gccoptlist{-mbig-endian  -mlittle-endian  -mgnu-as  -mgnu-ld  -mno-pic @gol
@@ -9122,7 +9123,7 @@ AMD K8 core based CPUs with x86-64 instr
 MMX, SSE, SSE2, 3dNOW!, enhanced 3dNOW! and 64-bit instruction set extensions.)
 @item amdfam10
 AMD Family 10 core based CPUs with x86-64 instruction set support.  (This
-supersets MMX, SSE, SSE2, SSE3, SSE4A, 3dNOW!, enhanced 3dNOW!, ABM and 64-bit
+supersets MMX, SSE, SSE2, SSE3, SSE4A, SSE5, 3dNOW!, enhanced 3dNOW!, ABM and 64-bit
 instruction set extensions.)
 @item winchip-c6
 IDT Winchip C6 CPU, dealt in same way as i486 with additional MMX instruction
@@ -9403,6 +9404,8 @@ preferred alignment to @option{-mpreferr
 @itemx -mno-ssse3
 @item -msse4a
 @item -mno-sse4a
+@item -msse5
+@item -mno-sse5
 @item -m3dnow
 @itemx -mno-3dnow
 @item -mpopcnt
@@ -9535,6 +9538,13 @@ building of shared libraries are not sup
 Generate code for the large model: This model makes no assumptions
 about addresses and sizes of sections.  Currently GCC does not implement
 this model.
+
+@item -mfused-madd
+@itemx -mno-fused-madd
+@opindex mfused-madd
+Enable automatic generation of fused floating point multiply-add instructions
+if the ISA supports such instructions.  The -mfused-madd option is on by
+default.
 @end table
 
 @node IA-64 Options
--- gcc/testsuite/g++.dg/other/i386-2a.C.jj	2007-12-30 21:57:01.000000000 +0100
+++ gcc/testsuite/g++.dg/other/i386-2a.C	2007-12-30 22:02:14.000000000 +0100
@@ -0,0 +1,10 @@
+/* Test that {,x,e,p,t,a,b}mmintrin.h, mm3dnow.h and mm_malloc.h are
+   usable with -O -pedantic-errors.  */
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O -pedantic-errors -march=k8 -m3dnow -mssse3 -msse5" } */
+
+#include <bmmintrin.h>
+#include <tmmintrin.h>
+#include <mm3dnow.h>
+
+int dummy;
--- gcc/testsuite/gcc.dg/i386-cpuid.h.jj	2007-06-26 13:38:46.000000000 +0200
+++ gcc/testsuite/gcc.dg/i386-cpuid.h	2007-12-29 18:35:01.000000000 +0100
@@ -15,6 +15,7 @@
 /* Extended Features */
 /* %ecx */
 #define bit_SSE4a (1 << 6)
+#define bit_SSE5 (1 << 11)
 
 #ifndef NOINLINE
 #define NOINLINE __attribute__ ((noinline))
--- gcc/testsuite/gcc.target/i386/i386.exp.jj	2007-02-20 22:35:34.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/i386.exp	2007-12-30 21:39:35.000000000 +0100
@@ -24,6 +24,21 @@ if { ![istarget i?86*-*-*] && ![istarget
 # Load support procs.
 load_lib gcc-dg.exp
 
+# Return 1 if sse5 instructions can be compiled.
+proc check_effective_target_sse5 { } {
+    return [check_no_compiler_messages sse5 object {
+	typedef long long __m128i __attribute__ ((__vector_size__ (16)));
+	typedef long long __v2di __attribute__ ((__vector_size__ (16)));
+
+	__m128i _mm_maccs_epi16(__m128i __A, __m128i __B, __m128i __C)
+	{
+	    return (__m128i) __builtin_ia32_pmacssww ((__v2di)__A,
+						      (__v2di)__B,
+						      (__v2di)__C);
+	}
+    } "-O2 -msse5" ]
+}
+
 # If a testcase doesn't have special options, use these.
 global DEFAULT_CFLAGS
 if ![info exists DEFAULT_CFLAGS] then {
--- gcc/testsuite/gcc.target/i386/sse-12a.c.jj	2007-12-30 22:01:34.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse-12a.c	2007-12-30 22:02:40.000000000 +0100
@@ -0,0 +1,10 @@
+/* Test that {,x,e,p,t,a,b}mmintrin.h, mm3dnow.h and mm_malloc.h are
+   usable with -O -std=c89 -pedantic-errors.  */
+/* { dg-do compile } */
+/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -m3dnow -mssse3 -msse5" } */
+
+#include <bmmintrin.h>
+#include <tmmintrin.h>
+#include <mm3dnow.h>
+
+int dummy;
--- gcc/testsuite/gcc.target/i386/sse-13a.c.jj	2007-12-30 22:01:37.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse-13a.c	2007-12-31 09:57:36.000000000 +0100
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=k8 -m3dnow -mssse3 -msse5" } */
+
+/* Test that the intrinsics compile with optimization.  All of them are
+   defined as inline functions in {,x,e,p,t,s,a,b}mmintrin.h and mm3dnow.h
+   that reference the proper builtin functions.  Defining away "static" and
+   "__inline" results in all of them being compiled as proper functions.  */
+
+#define static
+#define __inline
+
+/* Following intrinsics require immediate arguments. */
+
+/* ammintrin.h */
+#define __builtin_ia32_extrqi(X, I, L)  __builtin_ia32_extrqi(X, 1, 1)
+#define __builtin_ia32_insertqi(X, Y, I, L) __builtin_ia32_insertqi(X, Y, 1, 1)
+
+/* mmintrin-common.h */
+#define __builtin_ia32_roundpd(V, M) __builtin_ia32_roundpd(V, 1)
+#define __builtin_ia32_roundsd(D, V, M) __builtin_ia32_roundsd(D, V, 1)
+#define __builtin_ia32_roundps(V, M) __builtin_ia32_roundps(V, 1)
+#define __builtin_ia32_roundss(D, V, M) __builtin_ia32_roundss(D, V, 1)
+
+/* tmmintrin.h */
+#define __builtin_ia32_palignr128(X, Y, N) __builtin_ia32_palignr128(X, Y, 8)
+#define __builtin_ia32_palignr(X, Y, N) __builtin_ia32_palignr(X, Y, 8)
+
+/* emmintrin.h */
+#define __builtin_ia32_psrldqi128(A, B) __builtin_ia32_psrldqi128(A, 8)
+#define __builtin_ia32_pslldqi128(A, B) __builtin_ia32_pslldqi128(A, 8)
+#define __builtin_ia32_pshufhw(A, N) __builtin_ia32_pshufhw(A, 0)
+#define __builtin_ia32_pshuflw(A, N) __builtin_ia32_pshuflw(A, 0)
+#define __builtin_ia32_pshufd(A, N) __builtin_ia32_pshufd(A, 0)
+#define __builtin_ia32_vec_set_v8hi(A, D, N) \
+  __builtin_ia32_vec_set_v8hi(A, D, 0)
+#define __builtin_ia32_vec_ext_v8hi(A, N) __builtin_ia32_vec_ext_v8hi(A, 0)
+#define __builtin_ia32_shufpd(A, B, N) __builtin_ia32_shufpd(A, B, 0)
+
+/* xmmintrin.h */
+#define __builtin_prefetch(P, A, I) __builtin_prefetch(P, A, _MM_HINT_NTA)
+#define __builtin_ia32_pshufw(A, N) __builtin_ia32_pshufw(A, 0)
+#define __builtin_ia32_vec_set_v4hi(A, D, N) \
+  __builtin_ia32_vec_set_v4hi(A, D, 0)
+#define __builtin_ia32_vec_ext_v4hi(A, N) __builtin_ia32_vec_ext_v4hi(A, 0)
+#define __builtin_ia32_shufps(A, B, N) __builtin_ia32_shufps(A, B, 0)
+
+/* bmmintrin.h */
+#define __builtin_ia32_protbi(A, B) __builtin_ia32_protbi(A,1)
+#define __builtin_ia32_protwi(A, B) __builtin_ia32_protwi(A,1)
+#define __builtin_ia32_protdi(A, B) __builtin_ia32_protdi(A,1)
+#define __builtin_ia32_protqi(A, B) __builtin_ia32_protqi(A,1)
+
+#include <bmmintrin.h>
+#include <tmmintrin.h>
+#include <mm3dnow.h>
--- gcc/testsuite/gcc.target/i386/sse-14a.c.jj	2007-12-30 22:01:40.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse-14a.c	2007-12-30 22:04:01.000000000 +0100
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -march=k8 -m3dnow -mssse3 -msse5" } */
+
+/* Test that the intrinsics compile without optimization.  All of them are
+   defined as inline functions in {,x,e,p,t,a,b}mmintrin.h  and mm3dnow.h
+   that reference the proper builtin functions.  Defining away "static" and
+   "__inline" results in all of them being compiled as proper functions.  */
+
+#define static
+#define __inline
+
+#include <bmmintrin.h>
+#include <tmmintrin.h>
+#include <mm3dnow.h>
+
+#define _CONCAT(x,y) x ## y
+
+#define test_1(func, type, op1_type, imm)				\
+  type _CONCAT(_,func) (op1_type A, int const I)			\
+  { return func (A, imm); }
+
+#define test_1x(func, type, op1_type, imm1, imm2)			\
+  type _CONCAT(_,func) (op1_type A, int const I, int const L)		\
+  { return func (A, imm1, imm2); }
+
+#define test_2(func, type, op1_type, op2_type, imm)			\
+  type _CONCAT(_,func) (op1_type A, op2_type B, int const I)		\
+  { return func (A, B, imm); }
+
+#define test_2x(func, type, op1_type, op2_type, imm1, imm2)		\
+  type _CONCAT(_,func) (op1_type A, op2_type B, int const I, int const L) \
+  { return func (A, B, imm1, imm2); }
+
+#define test_4(func, type, op1_type, op2_type, op3_type, op4_type, imm)	\
+  type _CONCAT(_,func) (op1_type A, op2_type B,				\
+			op3_type C, op4_type D, int const I)		\
+  { return func (A, B, C, D, imm); }
+
+
+/* Following intrinsics require immediate arguments.  They
+   are defined as macros for non-optimized compilations. */
+
+/* ammintrin.h */
+test_1x (_mm_extracti_si64, __m128i, __m128i, 1, 1)
+test_2x (_mm_inserti_si64, __m128i, __m128i, __m128i, 1, 1)
+
+/* tmmintrin.h */
+test_2 (_mm_alignr_epi8, __m128i, __m128i, __m128i, 1)
+test_2 (_mm_alignr_pi8, __m64, __m64, __m64, 1)
+
+/* emmintrin.h */
+test_2 (_mm_shuffle_pd, __m128d, __m128d, __m128d, 1)
+test_1 (_mm_srli_si128, __m128i, __m128i, 1)
+test_1 (_mm_slli_si128, __m128i, __m128i, 1)
+test_1 (_mm_extract_epi16, int, __m128i, 1)
+test_2 (_mm_insert_epi16, __m128i, __m128i, int, 1)
+test_1 (_mm_shufflehi_epi16, __m128i, __m128i, 1)
+test_1 (_mm_shufflelo_epi16, __m128i, __m128i, 1)
+test_1 (_mm_shuffle_epi32, __m128i, __m128i, 1)
+
+/* xmmintrin.h */
+test_2 (_mm_shuffle_ps, __m128, __m128, __m128, 1)
+test_1 (_mm_extract_pi16, int, __m64, 1)
+test_1 (_m_pextrw, int, __m64, 1)
+test_2 (_mm_insert_pi16, __m64, __m64, int, 1)
+test_2 (_m_pinsrw, __m64, __m64, int, 1)
+test_1 (_mm_shuffle_pi16, __m64, __m64, 1)
+test_1 (_m_pshufw, __m64, __m64, 1)
+test_1 (_mm_prefetch, void, void *, _MM_HINT_NTA)
+
+/* bmmintrin.h */
+test_1 (_mm_roti_epi8, __m128i, __m128i, 1)
+test_1 (_mm_roti_epi16, __m128i, __m128i, 1)
+test_1 (_mm_roti_epi32, __m128i, __m128i, 1)
+test_1 (_mm_roti_epi64, __m128i, __m128i, 1)
--- gcc/testsuite/gcc.target/i386/sse5-check.h.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-check.h	2007-12-29 18:36:02.000000000 +0100
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+#include "../../gcc.dg/i386-cpuid.h"
+
+static void sse5_test (void);
+
+int
+main ()
+{
+  unsigned long cpu_facilities = i386_extended_cpuid_ecx ();
+    
+  /* Run SSE5 test only if host has SSE5 support.  */
+  if (cpu_facilities & bit_SSE5)
+    sse5_test ();
+
+  exit (0);
+}
--- gcc/testsuite/gcc.target/i386/sse5-fma-vector.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-fma-vector.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,93 @@
+/* Test that the compiler properly optimizes floating point multiply and add
+   instructions vector into fmaddps on SSE5 systems.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -msse5 -mfused-madd -ftree-vectorize" } */
+
+extern void exit (int);
+
+typedef float     __m128  __attribute__ ((__vector_size__ (16), __may_alias__));
+typedef double    __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
+
+#define SIZE 10240
+
+union {
+  __m128 f_align;
+  __m128d d_align;
+  float f[SIZE];
+  double d[SIZE];
+} a, b, c, d;
+
+void
+flt_mul_add (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.f[i] = (b.f[i] * c.f[i]) + d.f[i];
+}
+
+void
+dbl_mul_add (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.d[i] = (b.d[i] * c.d[i]) + d.d[i];
+}
+
+void
+flt_mul_sub (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.f[i] = (b.f[i] * c.f[i]) - d.f[i];
+}
+
+void
+dbl_mul_sub (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.d[i] = (b.d[i] * c.d[i]) - d.d[i];
+}
+
+void
+flt_neg_mul_add (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.f[i] = (-(b.f[i] * c.f[i])) + d.f[i];
+}
+
+void
+dbl_neg_mul_add (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.d[i] = (-(b.d[i] * c.d[i])) + d.d[i];
+}
+
+int main ()
+{
+  flt_mul_add ();
+  flt_mul_sub ();
+  flt_neg_mul_add ();
+
+  dbl_mul_add ();
+  dbl_mul_sub ();
+  dbl_neg_mul_add ();
+  exit (0);
+}
+
+/* { dg-final { scan-assembler "fmaddps" } } */
+/* { dg-final { scan-assembler "fmaddpd" } } */
+/* { dg-final { scan-assembler "fmsubps" } } */
+/* { dg-final { scan-assembler "fmsubpd" } } */
+/* { dg-final { scan-assembler "fnmaddps" } } */
+/* { dg-final { scan-assembler "fnmaddpd" } } */
--- gcc/testsuite/gcc.target/i386/sse5-fma.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-fma.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,82 @@
+/* Test that the compiler properly optimizes floating point multiply and add
+   instructions into fmaddss, fmsubss, fnmaddss, fnmsubss on SSE5 systems.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -msse5 -mfused-madd" } */
+
+extern void exit (int);
+
+float
+flt_mul_add (float a, float b, float c)
+{
+  return (a * b) + c;
+}
+
+double
+dbl_mul_add (double a, double b, double c)
+{
+  return (a * b) + c;
+}
+
+float
+flt_mul_sub (float a, float b, float c)
+{
+  return (a * b) - c;
+}
+
+double
+dbl_mul_sub (double a, double b, double c)
+{
+  return (a * b) - c;
+}
+
+float
+flt_neg_mul_add (float a, float b, float c)
+{
+  return (-(a * b)) + c;
+}
+
+double
+dbl_neg_mul_add (double a, double b, double c)
+{
+  return (-(a * b)) + c;
+}
+
+float
+flt_neg_mul_sub (float a, float b, float c)
+{
+  return (-(a * b)) - c;
+}
+
+double
+dbl_neg_mul_sub (double a, double b, double c)
+{
+  return (-(a * b)) - c;
+}
+
+float  f[10] = { 2, 3, 4 };
+double d[10] = { 2, 3, 4 };
+
+int main ()
+{
+  f[3] = flt_mul_add (f[0], f[1], f[2]);
+  f[4] = flt_mul_sub (f[0], f[1], f[2]);
+  f[5] = flt_neg_mul_add (f[0], f[1], f[2]);
+  f[6] = flt_neg_mul_sub (f[0], f[1], f[2]);
+
+  d[3] = dbl_mul_add (d[0], d[1], d[2]);
+  d[4] = dbl_mul_sub (d[0], d[1], d[2]);
+  d[5] = dbl_neg_mul_add (d[0], d[1], d[2]);
+  d[6] = dbl_neg_mul_sub (d[0], d[1], d[2]);
+  exit (0);
+}
+
+/* { dg-final { scan-assembler "fmaddss" } } */
+/* { dg-final { scan-assembler "fmaddsd" } } */
+/* { dg-final { scan-assembler "fmsubss" } } */
+/* { dg-final { scan-assembler "fmsubsd" } } */
+/* { dg-final { scan-assembler "fnmaddss" } } */
+/* { dg-final { scan-assembler "fnmaddsd" } } */
+/* { dg-final { scan-assembler "fnmsubss" } } */
+/* { dg-final { scan-assembler "fnmsubsd" } } */
--- gcc/testsuite/gcc.target/i386/sse5-haddX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-haddX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,208 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 10
+
+union
+{
+  __m128i x[NUM];
+  int8_t ssi[NUM * 16];
+  int16_t si[NUM * 8];
+  int32_t li[NUM * 4];
+  int64_t lli[NUM * 2];
+} dst, res, src1;
+
+static void
+init_sbyte ()
+{
+  int i;
+  for (i=0; i < NUM * 16; i++)
+    src1.ssi[i] = i;
+}
+
+static void
+init_sword ()
+{
+  int i;
+  for (i=0; i < NUM * 8; i++)
+    src1.si[i] = i;
+}
+
+
+static void
+init_sdword ()
+{
+  int i;
+  for (i=0; i < NUM * 4; i++)
+    src1.li[i] = i;
+}
+
+static int 
+check_sbyte2word ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 8; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.si[s] = src1.ssi[t] + src1.ssi[t + 1] ;
+	  if (res.si[s] != dst.si[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static int 
+check_sbyte2dword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 4; j++)
+	{
+	  t = i + (4 * j);
+	  s = (i / 4) + j;
+	  res.li[s] = (src1.ssi[t] + src1.ssi[t + 1]) + (src1.ssi[t + 2]
+	              + src1.ssi[t + 3]); 
+	  if (res.li[s] != dst.li[s]) 
+	    check_fails++;
+	}
+    }
+  return check_fails++;
+}
+
+static int
+check_sbyte2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (8 * j);
+	  s = (i / 8) + j;
+	  res.lli[s] = ((src1.ssi[t] + src1.ssi[t + 1]) + (src1.ssi[t + 2] 
+		       + src1.ssi[t + 3])) + ((src1.ssi[t + 4] + src1.ssi[t +5])
+	               + (src1.ssi[t + 6] + src1.ssi[t + 7])); 
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;
+	}
+    }
+  return check_fails++;
+}
+
+static int
+check_sword2dword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < (NUM * 8); i = i + 8)
+    {
+      for (j = 0; j < 4; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.li[s] = src1.si[t] + src1.si[t + 1] ;
+	  if (res.li[s] != dst.li[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static int 
+check_sword2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 8; i = i + 8)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (4 * j);
+	  s = (i / 4) + j;
+	  res.lli[s] = (src1.si[t] + src1.si[t + 1]) + (src1.si[t + 2]
+	               + src1.si[t + 3]); 
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;
+	}
+    }
+  return check_fails++;
+}
+
+static int
+check_dword2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < (NUM * 4); i = i + 4)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.lli[s] = src1.li[t] + src1.li[t + 1] ;
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check haddbw */
+  init_sbyte ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddw_epi8 (src1.x[i]);
+  
+  if (check_sbyte2word())
+  abort ();
+  
+  /* Check haddbd */
+  for (i = 0; i < (NUM ); i++)
+    dst.x[i] = _mm_haddd_epi8 (src1.x[i]);
+  
+  if (check_sbyte2dword())
+    abort (); 
+  
+  /* Check haddbq */
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddq_epi8 (src1.x[i]);
+  
+  if (check_sbyte2qword())
+    abort ();
+
+  /* Check haddwd */
+  init_sword ();
+
+  for (i = 0; i < (NUM ); i++)
+    dst.x[i] = _mm_haddd_epi16 (src1.x[i]);
+  
+  if (check_sword2dword())
+    abort (); 
+   
+  /* Check haddbwq */
+ 
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddq_epi16 (src1.x[i]);
+  
+  if (check_sword2qword())
+    abort ();
+ 
+  /* Check haddq */
+  init_sdword ();
+
+    for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddq_epi32 (src1.x[i]);
+  
+  if (check_dword2qword())
+    abort ();
+}
--- gcc/testsuite/gcc.target/i386/sse5-hadduX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-hadduX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,207 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 10
+
+union
+{
+  __m128i x[NUM];
+  unsigned char  ssi[NUM * 16];
+  unsigned short si[NUM * 8];
+  unsigned int li[NUM * 4];
+  unsigned long long  lli[NUM * 2];
+} dst, res, src1;
+
+static void
+init_byte ()
+{
+  int i;
+  for (i=0; i < NUM * 16; i++)
+    src1.ssi[i] = i;
+}
+
+static void
+init_word ()
+{
+  int i;
+  for (i=0; i < NUM * 8; i++)
+    src1.si[i] = i;
+}
+
+
+static void
+init_dword ()
+{
+  int i;
+  for (i=0; i < NUM * 4; i++)
+    src1.li[i] = i;
+}
+
+static int 
+check_byte2word ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 8; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.si[s] = src1.ssi[t] + src1.ssi[t + 1] ;
+	  if (res.si[s] != dst.si[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static int 
+check_byte2dword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 4; j++)
+	{
+	  t = i + (4 * j);
+	  s = (i / 4) + j;
+	  res.li[s] = (src1.ssi[t] + src1.ssi[t + 1]) + (src1.ssi[t + 2]
+	              + src1.ssi[t + 3]); 
+	  if (res.li[s] != dst.li[s]) 
+	    check_fails++;
+	}
+    }
+  return check_fails++;
+}
+
+static int
+check_byte2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (8 * j);
+	  s = (i / 8) + j;
+	  res.lli[s] = ((src1.ssi[t] + src1.ssi[t + 1]) + (src1.ssi[t + 2] 
+		       + src1.ssi[t + 3])) + ((src1.ssi[t + 4] + src1.ssi[t +5])
+	               + (src1.ssi[t + 6] + src1.ssi[t + 7])); 
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;
+	}
+    }
+  return check_fails++;
+}
+
+static int
+check_word2dword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < (NUM * 8); i = i + 8)
+    {
+      for (j = 0; j < 4; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.li[s] = src1.si[t] + src1.si[t + 1] ;
+	  if (res.li[s] != dst.li[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static int 
+check_word2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 8; i = i + 8)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (4 * j);
+	  s = (i / 4) + j;
+	  res.lli[s] = (src1.si[t] + src1.si[t + 1]) + (src1.si[t + 2]
+	               + src1.si[t + 3]); 
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;
+	}
+    }
+  return check_fails++;
+}
+
+static int
+check_dword2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < (NUM * 4); i = i + 4)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.lli[s] = src1.li[t] + src1.li[t + 1] ;
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check haddubw */
+  init_byte ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddw_epu8 (src1.x[i]);
+  
+  if (check_byte2word())
+  abort ();
+  
+  /* Check haddubd */
+  for (i = 0; i < (NUM ); i++)
+    dst.x[i] = _mm_haddd_epu8 (src1.x[i]);
+  
+  if (check_byte2dword())
+    abort (); 
+  
+  /* Check haddubq */
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddq_epu8 (src1.x[i]);
+  
+  if (check_byte2qword())
+    abort ();
+
+  /* Check hadduwd */
+  init_word ();
+
+  for (i = 0; i < (NUM ); i++)
+    dst.x[i] = _mm_haddd_epu16 (src1.x[i]);
+  
+  if (check_word2dword())
+    abort (); 
+   
+  /* Check haddbuwq */
+ 
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddq_epu16 (src1.x[i]);
+  
+  if (check_word2qword())
+    abort ();
+ 
+  /* Check hadudq */
+  init_dword ();
+    for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_haddq_epu32 (src1.x[i]);
+  
+  if (check_dword2qword())
+    abort ();
+}
--- gcc/testsuite/gcc.target/i386/sse5-hsubX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-hsubX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,128 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 10
+
+union
+{
+  __m128i x[NUM];
+  int8_t ssi[NUM * 16];
+  int16_t si[NUM * 8];
+  int32_t li[NUM * 4];
+  int64_t lli[NUM * 2];
+} dst, res, src1;
+
+static void
+init_sbyte ()
+{
+  int i;
+  for (i=0; i < NUM * 16; i++)
+    src1.ssi[i] = i;
+}
+
+static void
+init_sword ()
+{
+  int i;
+  for (i=0; i < NUM * 8; i++)
+    src1.si[i] = i;
+}
+
+
+static void
+init_sdword ()
+{
+  int i;
+  for (i=0; i < NUM * 4; i++)
+    src1.li[i] = i;
+}
+
+static int 
+check_sbyte2word ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < NUM * 16; i = i + 16)
+    {
+      for (j = 0; j < 8; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.si[s] = src1.ssi[t] - src1.ssi[t + 1] ;
+	  if (res.si[s] != dst.si[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static int
+check_sword2dword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < (NUM * 8); i = i + 8)
+    {
+      for (j = 0; j < 4; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.li[s] = src1.si[t] - src1.si[t + 1] ;
+	  if (res.li[s] != dst.li[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static int
+check_dword2qword ()
+{
+  int i, j, s, t, check_fails = 0;
+  for (i = 0; i < (NUM * 4); i = i + 4)
+    {
+      for (j = 0; j < 2; j++)
+	{
+	  t = i + (2 * j);
+	  s = (i / 2) + j;
+	  res.lli[s] = src1.li[t] - src1.li[t + 1] ;
+	  if (res.lli[s] != dst.lli[s]) 
+	    check_fails++;	
+	}
+    }
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check hsubbw */
+  init_sbyte ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_hsubw_epi8 (src1.x[i]);
+  
+  if (check_sbyte2word())
+  abort ();
+  
+
+  /* Check hsubwd */
+  init_sword ();
+
+  for (i = 0; i < (NUM ); i++)
+    dst.x[i] = _mm_hsubd_epi16 (src1.x[i]);
+  
+  if (check_sword2dword())
+    abort (); 
+   
+   /* Check hsubdq */
+  init_sdword ();
+    for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_hsubq_epi32 (src1.x[i]);
+  
+  if (check_dword2qword())
+    abort ();
+}
--- gcc/testsuite/gcc.target/i386/sse5-ima-vector.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-ima-vector.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,34 @@
+/* Test that the compiler properly optimizes vector 32-bit integer point
+   multiply and add instructions vector into pmacsdd on SSE5 systems.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -msse5 -ftree-vectorize" } */
+
+extern void exit (int);
+
+typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__));
+
+#define SIZE 10240
+
+union {
+  __m128i align;
+  int i[SIZE];
+} a, b, c, d;
+
+void
+int_mul_add (void)
+{
+  int i;
+
+  for (i = 0; i < SIZE; i++)
+    a.i[i] = (b.i[i] * c.i[i]) + d.i[i];
+}
+
+int main ()
+{
+  int_mul_add ();
+  exit (0);
+}
+
+/* { dg-final { scan-assembler "pmacsdd" } } */
--- gcc/testsuite/gcc.target/i386/sse5-maccXX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-maccXX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,140 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 20
+
+union
+{
+  __m128 x[NUM];
+  float f[NUM * 4];
+  __m128d y[NUM];
+  double d[NUM * 2];
+} dst, res, src1, src2, src3;
+
+
+/* Note that in macc*,msub*,mnmacc* and mnsub* instructions, the intermdediate 
+   product is not rounded, only the addition is rounded. */
+
+static void
+init_maccps ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.f[i] = i;
+      src2.f[i] = i + 10;
+      src3.f[i] = i + 20;
+    }
+}
+
+static void
+init_maccpd ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.d[i] = i;
+      src2.d[i] = i + 10;
+      src3.d[i] = i + 20;
+    }
+}
+
+static int
+check_maccps ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    for (j = 0; j < 4; j++)
+      {
+	res.f[i + j] = (src1.f[i + j] * src2.f[i + j]) + src3.f[i + j];
+	if (dst.f[i + j] != res.f[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+static int
+check_maccpd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    for (j = 0; j < 2; j++)
+      {
+	res.d[i + j] = (src1.d[i + j] * src2.d[i + j]) + src3.d[i + j];
+	if (dst.d[i + j] != res.d[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+
+static int
+check_maccss ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i= i + 4)
+    {
+      res.f[i] = (src1.f[i] * src2.f[i]) + src3.f[i];
+      if (dst.f[i] != res.f[i]) 
+	check_fails++;
+    }	
+  return check_fails++;
+}
+
+static int
+check_maccsd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    {
+      res.d[i] = (src1.d[i] * src2.d[i]) + src3.d[i];
+      if (dst.d[i] != res.d[i]) 
+	check_fails++;
+    }
+  return check_fails++;
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check maccps */
+  init_maccps ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_macc_ps (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_maccps ()) 
+    abort ();
+  
+  /* check maccss */
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_macc_ss (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_maccss ()) 
+    abort ();
+  
+  /* Check maccpd */
+  init_maccpd ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_macc_pd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_maccpd ()) 
+    abort ();
+  
+  /* Check maccps */
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_macc_sd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_maccsd ()) 
+    abort ();
+  
+}
--- gcc/testsuite/gcc.target/i386/sse5-msubXX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-msubXX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,139 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 20
+
+union
+{
+  __m128 x[NUM];
+  float f[NUM * 4];
+  __m128d y[NUM];
+  double d[NUM * 2];
+} dst, res, src1, src2, src3;
+
+/* Note that in macc*,msub*,mnmacc* and mnsub* instructions, the intermdediate 
+   product is not rounded, only the addition is rounded. */
+
+static void
+init_msubps ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.f[i] = i;
+      src2.f[i] = i + 10;
+      src3.f[i] = i + 20;
+    }
+}
+
+static void
+init_msubpd ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.d[i] = i;
+      src2.d[i] = i + 10;
+      src3.d[i] = i + 20;
+    }
+}
+
+static int
+check_msubps ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    for (j = 0; j < 4; j++)
+      {
+	res.f[i + j] = (src1.f[i + j] * src2.f[i + j]) - src3.f[i + j];
+	if (dst.f[i + j] != res.f[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+static int
+check_msubpd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    for (j = 0; j < 2; j++)
+      {
+	res.d[i + j] = (src1.d[i + j] * src2.d[i + j]) - src3.d[i + j];
+	if (dst.d[i + j] != res.d[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+
+static int
+check_msubss ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    {
+      res.f[i] = (src1.f[i] * src2.f[i]) - src3.f[i];
+      if (dst.f[i] != res.f[i]) 
+	check_fails++;
+    }	
+  return check_fails++;
+}
+
+static int
+check_msubsd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    {
+      res.d[i] = (src1.d[i] * src2.d[i]) - src3.d[i];
+      if (dst.d[i] != res.d[i]) 
+	check_fails++;
+    }
+  return check_fails++;
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check msubps */
+  init_msubps ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_msub_ps (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_msubps ()) 
+    abort ();
+  
+  /* check msubss */
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_msub_ss (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_msubss ()) 
+    abort ();
+  
+  /* Check msubpd */
+  init_msubpd ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_msub_pd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_msubpd ()) 
+    abort ();
+  
+  /* Check msubps */
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_msub_sd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_msubsd ()) 
+    abort ();
+  
+}
--- gcc/testsuite/gcc.target/i386/sse5-nmaccXX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-nmaccXX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,139 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 20
+
+union
+{
+  __m128 x[NUM];
+  float f[NUM * 4];
+  __m128d y[NUM];
+  double d[NUM * 2];
+} dst, res, src1, src2, src3;
+
+/* Note that in macc*,msub*,mnmacc* and mnsub* instructions, the intermdediate 
+   product is not rounded, only the addition is rounded. */
+
+static void
+init_nmaccps ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.f[i] = i;
+      src2.f[i] = i + 10;
+      src3.f[i] = i + 20;
+    }
+}
+
+static void
+init_nmaccpd ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.d[i] = i;
+      src2.d[i] = i + 10;
+      src3.d[i] = i + 20;
+    }
+}
+
+static int
+check_nmaccps ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    for (j = 0; j < 4; j++)
+      {
+	res.f[i + j] = - (src1.f[i + j] * src2.f[i + j]) + src3.f[i + j];
+	if (dst.f[i + j] != res.f[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+static int
+check_nmaccpd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    for (j = 0; j < 2; j++)
+      {
+	res.d[i + j] = - (src1.d[i + j] * src2.d[i + j]) + src3.d[i + j];
+	if (dst.d[i + j] != res.d[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+
+static int
+check_nmaccss ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    {
+      res.f[i] = - (src1.f[i] * src2.f[i]) + src3.f[i];
+      if (dst.f[i] != res.f[i]) 
+	check_fails++;
+    }	
+  return check_fails++;
+}
+
+static int
+check_nmaccsd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    {
+      res.d[i] = - (src1.d[i] * src2.d[i]) + src3.d[i];
+      if (dst.d[i] != res.d[i]) 
+	check_fails++;
+    }
+  return check_fails++;
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check nmaccps */
+  init_nmaccps ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_nmacc_ps (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_nmaccps ()) 
+    abort ();
+  
+  /* check nmaccss */
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_nmacc_ss (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_nmaccss ()) 
+    abort ();
+  
+  /* Check nmaccpd */
+  init_nmaccpd ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_nmacc_pd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_nmaccpd ()) 
+    abort ();
+  
+  /* Check nmaccps */
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_nmacc_sd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_nmaccsd ()) 
+    abort ();
+  
+}
--- gcc/testsuite/gcc.target/i386/sse5-nmsubXX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-nmsubXX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,139 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+#define NUM 20
+
+union
+{
+  __m128 x[NUM];
+  float f[NUM * 4];
+  __m128d y[NUM];
+  double d[NUM * 2];
+} dst, res, src1, src2, src3;
+
+/* Note that in macc*,msub*,mnmacc* and mnsub* instructions, the intermdediate 
+   product is not rounded, only the addition is rounded. */
+
+static void
+init_nmsubps ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.f[i] = i;
+      src2.f[i] = i + 10;
+      src3.f[i] = i + 20;
+    }
+}
+
+static void
+init_nmsubpd ()
+{
+  int i;
+  for (i = 0; i < NUM * 4; i++)
+    {
+      src1.d[i] = i;
+      src2.d[i] = i + 10;
+      src3.d[i] = i + 20;
+    }
+}
+
+static int
+check_nmsubps ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    for (j = 0; j < 4; j++)
+      {
+	res.f[i + j] = - (src1.f[i + j] * src2.f[i + j]) - src3.f[i + j];
+	if (dst.f[i + j] != res.f[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+static int
+check_nmsubpd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    for (j = 0; j < 2; j++)
+      {
+	res.d[i + j] = - (src1.d[i + j] * src2.d[i + j]) - src3.d[i + j];
+	if (dst.d[i + j] != res.d[i + j]) 
+	  check_fails++;
+      }
+  return check_fails++;
+}
+
+
+static int
+check_nmsubss ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 4; i = i + 4)
+    {
+      res.f[i] = - (src1.f[i] * src2.f[i]) - src3.f[i];
+      if (dst.f[i] != res.f[i]) 
+	check_fails++;
+    }	
+  return check_fails++;
+}
+
+static int
+check_nmsubsd ()
+{
+  int i, j, check_fails = 0;
+  for (i = 0; i < NUM * 2; i = i + 2)
+    {
+      res.d[i] = - (src1.d[i] * src2.d[i]) - src3.d[i];
+      if (dst.d[i] != res.d[i]) 
+	check_fails++;
+    }
+  return check_fails++;
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  
+  /* Check nmsubps */
+  init_nmsubps ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_nmsub_ps (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_nmsubps (&dst.x[i], &src1.f[i * 4], &src2.f[i * 4], &src3.f[i * 4])) 
+    abort ();
+  
+  /* check nmsubss */
+  for (i = 0; i < NUM; i++)
+    dst.x[i] = _mm_nmsub_ss (src1.x[i], src2.x[i], src3.x[i]);
+  
+  if (check_nmsubss (&dst.x[i], &src1.f[i * 4], &src2.f[i * 4], &src3.f[i * 4])) 
+    abort ();
+  
+  /* Check nmsubpd */
+  init_nmsubpd ();
+  
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_nmsub_pd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_nmsubpd (&dst.y[i], &src1.d[i * 2], &src2.d[i * 2], &src3.d[i * 2])) 
+    abort ();
+  
+  /* Check nmsubps */
+  for (i = 0; i < NUM; i++)
+    dst.y[i] = _mm_nmsub_sd (src1.y[i], src2.y[i], src3.y[i]);
+  
+  if (check_nmsubsd (&dst.y[i], &src1.d[i * 2], &src2.d[i * 2], &src3.d[i * 2])) 
+    abort ();
+  
+}
--- gcc/testsuite/gcc.target/i386/sse5-pcmov.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-pcmov.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,23 @@
+/* Test that the compiler properly optimizes conditional floating point moves
+   into the pcmov instruction on SSE5 systems.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -msse5" } */
+
+extern void exit (int);
+
+double dbl_test (double a, double b, double c, double d)
+{
+  return (a > b) ? c : d;
+}
+
+double dbl_a = 1, dbl_b = 2, dbl_c = 3, dbl_d = 4, dbl_e;
+
+int main()
+{
+  dbl_e = dbl_test (dbl_a, dbl_b, dbl_c, dbl_d);
+  exit (0);
+}
+
+/* { dg-final { scan-assembler "pcmov" } } */
--- gcc/testsuite/gcc.target/i386/sse5-pcmov2.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-pcmov2.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,23 @@
+/* Test that the compiler properly optimizes conditional floating point moves
+   into the pcmov instruction on SSE5 systems.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -msse5" } */
+
+extern void exit (int);
+
+float flt_test (float a, float b, float c, float d)
+{
+  return (a > b) ? c : d;
+}
+
+float flt_a = 1, flt_b = 2, flt_c = 3, flt_d = 4, flt_e;
+
+int main()
+{
+  flt_e = flt_test (flt_a, flt_b, flt_c, flt_d);
+  exit (0);
+}
+
+/* { dg-final { scan-assembler "pcmov" } } */
--- gcc/testsuite/gcc.target/i386/sse5-permpX.c.jj	2007-12-29 18:27:58.000000000 +0100
+++ gcc/testsuite/gcc.target/i386/sse5-permpX.c	2007-09-22 23:16:19.000000000 +0200
@@ -0,0 +1,120 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse5 } */
+/* { dg-options "-O2 -msse5" } */
+
+#include "sse5-check.h"
+
+#include <bmmintrin.h>
+#include <string.h>
+
+union
+{
+  __m128 x[2];
+  __m128d y[2];
+  __m128i z[2];
+  float f[8];
+  double d[4];
+  int i[8];
+  long li[4];
+} dst, res, src1, src2, src3;
+
+
+static void
+init_ddata ()
+{
+  int i;
+  for (i = 0; i < 4; i++)
+    {
+      src1.d[i] = i;
+      src2.d[i] = i + 2;
+    }
+ 
+  src3.li[0] = 3;
+  src3.li[1] = 0;
+  src3.li[2] = 1;
+  src3.li[3] = 2;
+
+  res.d[0] = 3.0;
+  res.d[1] = 0.0;
+  res.d[2] = 3.0;
+  res.d[3] = 4.0;
+}
+
+
+static void 
+init_fdata ()
+{
+  int i;
+  for (i = 0; i < 8; i++)
+    {
+      src1.f[i] = i;
+      src2.f[i] = i + 2;
+    }
+
+  src3.i[0] = 7;
+  src3.i[1] = 5;
+  src3.i[2] = 1;
+  src3.i[3] = 2;
+  src3.i[4] = 0;
+  src3.i[5] = 4;
+  src3.i[6] = 3;
+  src3.i[7] = 6; 
+
+  res.f[0] = 5.0;
+  res.f[1] = 3.0;
+  res.f[2] = 1.0;
+  res.f[3] = 2.0;
+  res.f[4] = 4.0;
+  res.f[5] = 6.0;
+  res.f[6] = 7.0;
+  res.f[7] = 8.0;
+}
+
+static int
+check_permpd ()
+{
+  int i, check_fails = 0;
+
+  for (i = 0; i < 4; i++)
+    {
+      if (res.d[i] != dst.d[i])
+	check_fails++;
+    }
+  return check_fails++;
+}
+
+static int
+check_permps ()
+{
+  int i, check_fails = 0;
+
+  for (i = 0; i < 8; i++)
+    {
+      if (res.f[i] != dst.f[i])
+	check_fails++;
+    }
+  return check_fails++;
+}
+
+static void
+sse5_test (void)
+{
+  int i;
+  init_ddata();
+
+  for (i = 0; i < 2; i++)
+    dst.y[i] = _mm_perm_pd (src1.y[i], src2.y[i], src3.z[i]);
+  
+  if (check_permpd ())
+    abort ();
+  
+  init_fdata();
+  
+  for (i = 0; i < 2; i++)
+    dst.x[i] = _mm_perm_ps (src1.x[i], src2.x[i], src3.z[i]);
+   
+  if (check_permps ())
+    abort (); 
+}
+
+