OSDN Git Service

PR tree-optimization/25737
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / gcc.dg / i386-cpuid.h
1 /* Helper file for i386 platform.  Runtime check for MMX/SSE/SSE2 support.
2    Used by 20020523-2.c and i386-sse-6.c, and possibly others.  */
3 /* Plagarized from 20020523-2.c.  */
4
5 /* %ecx */
6 #define bit_SSE3 (1 << 0)
7 #define bit_SSSE3 (1 << 9)
8 #define bit_SSE4_1 (1 << 19)
9 #define bit_SSE4_2 (1 << 20)
10 #define bit_POPCNT (1 << 23)
11
12 /* %edx */
13 #define bit_CMOV (1 << 15)
14 #define bit_MMX (1 << 23)
15 #define bit_SSE (1 << 25)
16 #define bit_SSE2 (1 << 26)
17
18 /* Extended Features */
19 /* %ecx */
20 #define bit_SSE4a (1 << 6)
21
22 #ifndef NOINLINE
23 #define NOINLINE __attribute__ ((noinline))
24 #endif
25
26 static inline unsigned int
27 i386_get_cpuid (unsigned int *ecx, unsigned int *edx)
28 {
29   int fl1;
30
31 #ifndef __x86_64__
32   int fl2;
33
34   /* See if we can use cpuid.  On AMD64 we always can.  */
35   __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
36            "pushl %0; popfl; pushfl; popl %0; popfl"
37            : "=&r" (fl1), "=&r" (fl2)
38            : "i" (0x00200000));
39   if (((fl1 ^ fl2) & 0x00200000) == 0)
40     return (0);
41 #endif
42
43   /* Host supports cpuid.  See if cpuid gives capabilities, try
44      CPUID(0).  Preserve %ebx and %ecx; cpuid insn clobbers these, we
45      don't need their CPUID values here, and %ebx may be the PIC
46      register.  */
47 #ifdef __x86_64__
48   __asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx"
49            : "=a" (fl1) : "0" (0) : "rdx", "cc");
50 #else
51   __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
52            : "=a" (fl1) : "0" (0) : "edx", "cc");
53 #endif
54   if (fl1 == 0)
55     return (0);
56
57   /* Invoke CPUID(1), return %ecx and %edx; caller can examine bits to
58      determine what's supported.  */
59 #ifdef __x86_64__
60   __asm__ ("pushq %%rbx; cpuid; popq %%rbx"
61            : "=c" (*ecx), "=d" (*edx), "=a" (fl1) : "2" (1) : "cc");
62 #else
63   __asm__ ("pushl %%ebx; cpuid; popl %%ebx"
64            : "=c" (*ecx), "=d" (*edx), "=a" (fl1) : "2" (1) : "cc");
65 #endif
66
67   return 1;
68 }
69
70 static inline unsigned int
71 i386_get_extended_cpuid (unsigned int *ecx, unsigned int *edx)
72 {
73   int fl1;
74   if (!(i386_get_cpuid (ecx, edx)))
75     return 0;
76
77   /* Invoke CPUID(0x80000000) to get the highest supported extended function
78      number */
79 #ifdef __x86_64__
80   __asm__ ("cpuid"
81            : "=a" (fl1) : "0" (0x80000000) : "edx", "ecx", "ebx");
82 #else
83   __asm__ ("pushl %%ebx; cpuid; popl %%ebx"
84            : "=a" (fl1) : "0" (0x80000000) : "edx", "ecx");
85 #endif
86   /* Check if highest supported extended function used below are supported */
87   if (fl1 < 0x80000001)
88     return 0;  
89
90   /* Invoke CPUID(0x80000001), return %ecx and %edx; caller can examine bits to
91      determine what's supported.  */
92 #ifdef __x86_64__
93   __asm__ ("cpuid"
94            : "=c" (*ecx), "=d" (*edx), "=a" (fl1) : "2" (0x80000001) : "ebx");
95 #else
96   __asm__ ("pushl %%ebx; cpuid; popl %%ebx"
97            : "=c" (*ecx), "=d" (*edx), "=a" (fl1) : "2" (0x80000001));
98 #endif
99   return 1;
100 }
101
102
103 unsigned int i386_cpuid_ecx (void) NOINLINE;
104 unsigned int i386_cpuid_edx (void) NOINLINE;
105 unsigned int i386_extended_cpuid_ecx (void) NOINLINE;
106 unsigned int i386_extended_cpuid_edx (void) NOINLINE;
107
108 unsigned int NOINLINE
109 i386_cpuid_ecx (void)
110 {
111   unsigned int ecx, edx;
112   if (i386_get_cpuid (&ecx, &edx))
113     return ecx;
114   else
115     return 0;
116 }
117
118 unsigned int NOINLINE
119 i386_cpuid_edx (void)
120 {
121   unsigned int ecx, edx;
122   if (i386_get_cpuid (&ecx, &edx))
123     return edx;
124   else
125     return 0;
126 }
127
128 unsigned int NOINLINE
129 i386_extended_cpuid_ecx (void)
130 {
131   unsigned int ecx, edx;
132   if (i386_get_extended_cpuid (&ecx, &edx))
133     return ecx;
134   else
135     return 0;
136 }
137
138 unsigned int NOINLINE
139 i386_extended_cpuid_edx (void)
140 {
141   unsigned int ecx, edx;
142   if (i386_get_extended_cpuid (&ecx, &edx))
143     return edx;
144   else
145     return 0;
146 }
147
148 static inline unsigned int
149 i386_cpuid (void)
150 {
151   return i386_cpuid_edx ();
152 }