OSDN Git Service

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