]> granicus.if.org Git - libvpx/blob - vpx_ports/x86.h
vpx_ports/x86.h: de-dup #elif block
[libvpx] / vpx_ports / x86.h
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11
12 #ifndef VPX_PORTS_X86_H
13 #define VPX_PORTS_X86_H
14 #include <stdlib.h>
15 #include "vpx_config.h"
16
17 typedef enum {
18   VPX_CPU_UNKNOWN = -1,
19   VPX_CPU_AMD,
20   VPX_CPU_AMD_OLD,
21   VPX_CPU_CENTAUR,
22   VPX_CPU_CYRIX,
23   VPX_CPU_INTEL,
24   VPX_CPU_NEXGEN,
25   VPX_CPU_NSC,
26   VPX_CPU_RISE,
27   VPX_CPU_SIS,
28   VPX_CPU_TRANSMETA,
29   VPX_CPU_TRANSMETA_OLD,
30   VPX_CPU_UMC,
31   VPX_CPU_VIA,
32
33   VPX_CPU_LAST
34 }  vpx_cpu_t;
35
36 #if defined(__GNUC__) && __GNUC__ || defined(__ANDROID__)
37 #if ARCH_X86_64
38 #define cpuid(func,ax,bx,cx,dx)\
39   __asm__ __volatile__ (\
40                         "cpuid           \n\t" \
41                         : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
42                         : "a"  (func));
43 #else
44 #define cpuid(func,ax,bx,cx,dx)\
45   __asm__ __volatile__ (\
46                         "mov %%ebx, %%edi   \n\t" \
47                         "cpuid              \n\t" \
48                         "xchg %%edi, %%ebx  \n\t" \
49                         : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
50                         : "a" (func));
51 #endif
52 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* end __GNUC__ or __ANDROID__*/
53 #if ARCH_X86_64
54 #define cpuid(func,ax,bx,cx,dx)\
55   asm volatile (\
56                 "xchg %rsi, %rbx \n\t" \
57                 "cpuid           \n\t" \
58                 "movl %ebx, %edi \n\t" \
59                 "xchg %rsi, %rbx \n\t" \
60                 : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
61                 : "a"  (func));
62 #else
63 #define cpuid(func,ax,bx,cx,dx)\
64   asm volatile (\
65                 "pushl %ebx       \n\t" \
66                 "cpuid            \n\t" \
67                 "movl %ebx, %edi  \n\t" \
68                 "popl %ebx        \n\t" \
69                 : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
70                 : "a" (func));
71 #endif
72 #else /* end __SUNPRO__ */
73 #if ARCH_X86_64
74 void __cpuid(int CPUInfo[4], int info_type);
75 #pragma intrinsic(__cpuid)
76 #define cpuid(func,a,b,c,d) do{\
77     int regs[4];\
78     __cpuid(regs,func); a=regs[0];  b=regs[1];  c=regs[2];  d=regs[3];\
79   } while(0)
80 #else
81 #define cpuid(func,a,b,c,d)\
82   __asm mov eax, func\
83   __asm cpuid\
84   __asm mov a, eax\
85   __asm mov b, ebx\
86   __asm mov c, ecx\
87   __asm mov d, edx
88 #endif
89 #endif /* end others */
90
91 #define HAS_MMX   0x01
92 #define HAS_SSE   0x02
93 #define HAS_SSE2  0x04
94 #define HAS_SSE3  0x08
95 #define HAS_SSSE3 0x10
96 #define HAS_SSE4_1 0x20
97 #ifndef BIT
98 #define BIT(n) (1<<n)
99 #endif
100
101 static int
102 x86_simd_caps(void) {
103   unsigned int flags = 0;
104   unsigned int mask = ~0;
105   unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
106   char *env;
107   (void)reg_ebx;
108
109   /* See if the CPU capabilities are being overridden by the environment */
110   env = getenv("VPX_SIMD_CAPS");
111
112   if (env && *env)
113     return (int)strtol(env, NULL, 0);
114
115   env = getenv("VPX_SIMD_CAPS_MASK");
116
117   if (env && *env)
118     mask = strtol(env, NULL, 0);
119
120   /* Ensure that the CPUID instruction supports extended features */
121   cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
122
123   if (reg_eax < 1)
124     return 0;
125
126   /* Get the standard feature flags */
127   cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
128
129   if (reg_edx & BIT(23)) flags |= HAS_MMX;
130
131   if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
132
133   if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
134
135   if (reg_ecx & BIT(0))  flags |= HAS_SSE3;
136
137   if (reg_ecx & BIT(9))  flags |= HAS_SSSE3;
138
139   if (reg_ecx & BIT(19)) flags |= HAS_SSE4_1;
140
141   return flags & mask;
142 }
143
144 vpx_cpu_t vpx_x86_vendor(void);
145
146 #if ARCH_X86_64 && defined(_MSC_VER)
147 unsigned __int64 __rdtsc(void);
148 #pragma intrinsic(__rdtsc)
149 #endif
150 static unsigned int
151 x86_readtsc(void) {
152 #if defined(__GNUC__) && __GNUC__
153   unsigned int tsc;
154   __asm__ __volatile__("rdtsc\n\t":"=a"(tsc):);
155   return tsc;
156 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
157   unsigned int tsc;
158   asm volatile("rdtsc\n\t":"=a"(tsc):);
159   return tsc;
160 #else
161 #if ARCH_X86_64
162   return (unsigned int)__rdtsc();
163 #else
164   __asm  rdtsc;
165 #endif
166 #endif
167 }
168
169
170 #if defined(__GNUC__) && __GNUC__
171 #define x86_pause_hint()\
172   __asm__ __volatile__ ("pause \n\t")
173 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
174 #define x86_pause_hint()\
175   asm volatile ("pause \n\t")
176 #else
177 #if ARCH_X86_64
178 #define x86_pause_hint()\
179   _mm_pause();
180 #else
181 #define x86_pause_hint()\
182   __asm pause
183 #endif
184 #endif
185
186 #if defined(__GNUC__) && __GNUC__
187 static void
188 x87_set_control_word(unsigned short mode) {
189   __asm__ __volatile__("fldcw %0" : : "m"(*&mode));
190 }
191 static unsigned short
192 x87_get_control_word(void) {
193   unsigned short mode;
194   __asm__ __volatile__("fstcw %0\n\t":"=m"(*&mode):);
195     return mode;
196 }
197 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
198 static void
199 x87_set_control_word(unsigned short mode) {
200   asm volatile("fldcw %0" : : "m"(*&mode));
201 }
202 static unsigned short
203 x87_get_control_word(void) {
204   unsigned short mode;
205   asm volatile("fstcw %0\n\t":"=m"(*&mode):);
206   return mode;
207 }
208 #elif ARCH_X86_64
209 /* No fldcw intrinsics on Windows x64, punt to external asm */
210 extern void           vpx_winx64_fldcw(unsigned short mode);
211 extern unsigned short vpx_winx64_fstcw(void);
212 #define x87_set_control_word vpx_winx64_fldcw
213 #define x87_get_control_word vpx_winx64_fstcw
214 #else
215 static void
216 x87_set_control_word(unsigned short mode) {
217   __asm { fldcw mode }
218 }
219 static unsigned short
220 x87_get_control_word(void) {
221   unsigned short mode;
222   __asm { fstcw mode }
223   return mode;
224 }
225 #endif
226
227 static unsigned short
228 x87_set_double_precision(void) {
229   unsigned short mode = x87_get_control_word();
230   x87_set_control_word((mode&~0x300) | 0x200);
231   return mode;
232 }
233
234
235 extern void vpx_reset_mmx_state(void);
236 #endif
237