summaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.md
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2009-06-16 21:17:31 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2009-06-16 14:17:31 -0700
commit7c45393e40d63f23b2691285d5ed450ce4fb5389 (patch)
tree45ac6794a48bd3484b3e2a6c77c35d5300994e10 /gcc/config/i386/i386.md
parentcd3b0fafaaebab56b17ec9f4fceff4c0f8e26aec (diff)
downloadgcc-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.md170
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")