diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2009-06-16 21:17:31 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2009-06-16 14:17:31 -0700 |
commit | 7c45393e40d63f23b2691285d5ed450ce4fb5389 (patch) | |
tree | 45ac6794a48bd3484b3e2a6c77c35d5300994e10 /gcc/config/i386/i386.md | |
parent | cd3b0fafaaebab56b17ec9f4fceff4c0f8e26aec (diff) | |
download | gcc-7c45393e40d63f23b2691285d5ed450ce4fb5389.tar.gz |
config.gcc (extra_headers): Add ia32intrin.h for x86.
2009-06-16 H.J. Lu <hongjiu.lu@intel.com>
* config.gcc (extra_headers): Add ia32intrin.h for x86.
* config/i386/i386.c (ix86_builtins): Add IX86_BUILTIN_BSRSI,
IX86_BUILTIN_BSRDI. IX86_BUILTIN_RDPMC, IX86_BUILTIN_RDTSC.
IX86_BUILTIN_RDTSCP. IX86_BUILTIN_ROLQI, IX86_BUILTIN_ROLHI,
IX86_BUILTIN_RORQI and IX86_BUILTIN_RORHI.
(ix86_special_builtin_type): Add UINT64_FTYPE_VOID,
UINT64_FTYPE_PINT, INT_FTYPE_INT, UINT64_FTYPE_INT,
INT64_FTYPE_INT64, UINT16_FTYPE_UINT16_INT and
UINT8_FTYPE_UINT8_INT
(bdesc_special_args): Add __builtin_ia32_rdtsc and
__builtin_ia32_rdtscp.
(bdesc_args): Add __builtin_ia32_bsrsi, __builtin_ia32_bsrdi,
__builtin_ia32_rolqi, __builtin_ia32_rolhi, __builtin_ia32_rorqi
and __builtin_ia32_rorhi,
(ix86_init_mmx_sse_builtins): Handle UINT64_FTYPE_VOID,
UINT64_FTYPE_PINT, INT_FTYPE_INT, UINT64_FTYPE_INT,
INT64_FTYPE_INT64, UINT16_FTYPE_UINT16_INT and
UINT8_FTYPE_UINT8_INT.
(ix86_expand_args_builtin): Likewise.
(ix86_expand_special_args_builtin): Likewise.
* config/i386/i386.md (UNSPECV_RDTSCP): New.
(UNSPECV_RDTSC): Likewise.
(UNSPECV_RDPMC): Likewise.
(*bsr): Removed to ...
(bsr): This
(*bsr_rex64): Removed to ...
(bsr_rex64): This.
(rdpmc): New.
(*rdpmc): Likewise.
(*rdpmc_rex64): Likewise.
(rdtsc): Likewise.
(*rdtsc): Likewise.
(*rdtsc_rex64): Likewise.
(rdtscp): Likewise.
(*rdtscp): Likewise.
(*rdtscp_rex64): Likewise.
* config/i386/ia32intrin.h: New.
* config/i386/x86intrin.h: Include <ia32intrin.h>.
From-SVN: r148554
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 170 |
1 files changed, 168 insertions, 2 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c21aa9c679e..59d9e829ed0 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -244,6 +244,9 @@ (UNSPECV_CLD 15) (UNSPECV_VZEROALL 16) (UNSPECV_VZEROUPPER 17) + (UNSPECV_RDTSC 18) + (UNSPECV_RDTSCP 19) + (UNSPECV_RDPMC 20) ]) ;; Constants to represent pcomtrue/pcomfalse variants @@ -16153,7 +16156,7 @@ (set_attr "type" "bitmanip") (set_attr "mode" "SI")]) -(define_insn "*bsr" +(define_insn "bsr" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (const_int 31) (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))) @@ -16338,7 +16341,7 @@ (set_attr "type" "bitmanip") (set_attr "mode" "DI")]) -(define_insn "*bsr_rex64" +(define_insn "bsr_rex64" [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (const_int 63) (clz:DI (match_operand:DI 1 "nonimmediate_operand" "rm")))) @@ -22670,6 +22673,169 @@ (set_attr "prefix_extra" "1") (set_attr "mode" "DI")]) +(define_expand "rdpmc" + [(match_operand:DI 0 "register_operand" "") + (match_operand:SI 1 "register_operand" "")] + "" +{ + rtx reg = gen_reg_rtx (DImode); + rtx si; + + /* Force operand 1 into ECX. */ + rtx ecx = gen_rtx_REG (SImode, CX_REG); + emit_insn (gen_rtx_SET (VOIDmode, ecx, operands[1])); + si = gen_rtx_UNSPEC_VOLATILE (DImode, gen_rtvec (1, ecx), + UNSPECV_RDPMC); + + if (TARGET_64BIT) + { + rtvec vec = rtvec_alloc (2); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + rtx upper = gen_reg_rtx (DImode); + rtx di = gen_rtx_UNSPEC_VOLATILE (DImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDPMC); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, si); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, di); + emit_insn (load); + upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + reg = expand_simple_binop (DImode, IOR, reg, upper, reg, 1, + OPTAB_DIRECT); + } + else + emit_insn (gen_rtx_SET (VOIDmode, reg, si)); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], reg)); + DONE; +}) + +(define_insn "*rdpmc" + [(set (match_operand:DI 0 "register_operand" "=A") + (unspec_volatile:DI [(match_operand:SI 1 "register_operand" "c")] + UNSPECV_RDPMC))] + "!TARGET_64BIT" + "rdpmc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_insn "*rdpmc_rex64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(match_operand:SI 2 "register_operand" "c")] + UNSPECV_RDPMC)) + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDPMC))] + "TARGET_64BIT" + "rdpmc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_expand "rdtsc" + [(set (match_operand:DI 0 "register_operand" "") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] + "" +{ + if (TARGET_64BIT) + { + rtvec vec = rtvec_alloc (2); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + rtx upper = gen_reg_rtx (DImode); + rtx lower = gen_reg_rtx (DImode); + rtx src = gen_rtx_UNSPEC_VOLATILE (DImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDTSC); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, lower, src); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, src); + emit_insn (load); + upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + lower = expand_simple_binop (DImode, IOR, lower, upper, lower, 1, + OPTAB_DIRECT); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], lower)); + DONE; + } +}) + +(define_insn "*rdtsc" + [(set (match_operand:DI 0 "register_operand" "=A") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] + "!TARGET_64BIT" + "rdtsc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_insn "*rdtsc_rex64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC)) + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSC))] + "TARGET_64BIT" + "rdtsc" + [(set_attr "type" "other") + (set_attr "length" "2")]) + +(define_expand "rdtscp" + [(match_operand:DI 0 "register_operand" "") + (match_operand:SI 1 "memory_operand" "")] + "" +{ + rtx di = gen_rtx_UNSPEC_VOLATILE (DImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDTSCP); + rtx si = gen_rtx_UNSPEC_VOLATILE (SImode, + gen_rtvec (1, const0_rtx), + UNSPECV_RDTSCP); + rtx reg = gen_reg_rtx (DImode); + rtx tmp = gen_reg_rtx (SImode); + + if (TARGET_64BIT) + { + rtvec vec = rtvec_alloc (3); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + rtx upper = gen_reg_rtx (DImode); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, di); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, upper, di); + RTVEC_ELT (vec, 2) = gen_rtx_SET (VOIDmode, tmp, si); + emit_insn (load); + upper = expand_simple_binop (DImode, ASHIFT, upper, GEN_INT (32), + NULL, 1, OPTAB_DIRECT); + reg = expand_simple_binop (DImode, IOR, reg, upper, reg, 1, + OPTAB_DIRECT); + } + else + { + rtvec vec = rtvec_alloc (2); + rtx load = gen_rtx_PARALLEL (VOIDmode, vec); + RTVEC_ELT (vec, 0) = gen_rtx_SET (VOIDmode, reg, di); + RTVEC_ELT (vec, 1) = gen_rtx_SET (VOIDmode, tmp, si); + emit_insn (load); + } + emit_insn (gen_rtx_SET (VOIDmode, operands[0], reg)); + emit_insn (gen_rtx_SET (VOIDmode, operands[1], tmp)); + DONE; +}) + +(define_insn "*rdtscp" + [(set (match_operand:DI 0 "register_operand" "=A") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (set (match_operand:SI 1 "register_operand" "=c") + (unspec_volatile:SI [(const_int 0)] UNSPECV_RDTSCP))] + "!TARGET_64BIT" + "rdtscp" + [(set_attr "type" "other") + (set_attr "length" "3")]) + +(define_insn "*rdtscp_rex64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (set (match_operand:DI 1 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_RDTSCP)) + (set (match_operand:SI 2 "register_operand" "=c") + (unspec_volatile:SI [(const_int 0)] UNSPECV_RDTSCP))] + "TARGET_64BIT" + "rdtscp" + [(set_attr "type" "other") + (set_attr "length" "3")]) + (include "mmx.md") (include "sse.md") (include "sync.md") |