]> granicus.if.org Git - libvpx/blob - vpx_ports/x86.h
Merge "silent a lot of MSVC compiler warnings" into experimental
[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 "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__
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 #else
53 #if ARCH_X86_64
54 void __cpuid(int CPUInfo[4], int info_type);
55 #pragma intrinsic(__cpuid)
56 #define cpuid(func,a,b,c,d) do{\
57     int regs[4];\
58     __cpuid(regs,func); a=regs[0];  b=regs[1];  c=regs[2];  d=regs[3];\
59   } while(0)
60 #else
61 #define cpuid(func,a,b,c,d)\
62   __asm mov eax, func\
63   __asm cpuid\
64   __asm mov a, eax\
65   __asm mov b, ebx\
66   __asm mov c, ecx\
67   __asm mov d, edx
68 #endif
69 #endif
70
71 #define HAS_MMX   0x01
72 #define HAS_SSE   0x02
73 #define HAS_SSE2  0x04
74 #define HAS_SSE3  0x08
75 #define HAS_SSSE3 0x10
76 #define HAS_SSE4_1 0x20
77 #ifndef BIT
78 #define BIT(n) (1<<n)
79 #endif
80
81 static int
82 x86_simd_caps(void) {
83   unsigned int flags = 0;
84   unsigned int mask = ~0;
85   unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
86   char *env;
87   (void)reg_ebx;
88
89   /* See if the CPU capabilities are being overridden by the environment */
90   env = getenv("VPX_SIMD_CAPS");
91
92   if (env && *env)
93     return (int)strtol(env, NULL, 0);
94
95   env = getenv("VPX_SIMD_CAPS_MASK");
96
97   if (env && *env)
98     mask = strtol(env, NULL, 0);
99
100   /* Ensure that the CPUID instruction supports extended features */
101   cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
102
103   if (reg_eax < 1)
104     return 0;
105
106   /* Get the standard feature flags */
107   cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
108
109   if (reg_edx & BIT(23)) flags |= HAS_MMX;
110
111   if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
112
113   if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
114
115   if (reg_ecx & BIT(0))  flags |= HAS_SSE3;
116
117   if (reg_ecx & BIT(9))  flags |= HAS_SSSE3;
118
119   if (reg_ecx & BIT(19)) flags |= HAS_SSE4_1;
120
121   return flags & mask;
122 }
123
124 vpx_cpu_t vpx_x86_vendor(void);
125
126 #if ARCH_X86_64 && defined(_MSC_VER)
127 unsigned __int64 __rdtsc(void);
128 #pragma intrinsic(__rdtsc)
129 #endif
130
131
132 #if defined(__GNUC__) && __GNUC__
133 #define x86_pause_hint()\
134   __asm__ __volatile__ ("pause \n\t")
135 #else
136 #if ARCH_X86_64
137 #define x86_pause_hint()\
138   _mm_pause();
139 #else
140 #define x86_pause_hint()\
141   __asm pause
142 #endif
143 #endif
144
145 #if defined(__GNUC__) && __GNUC__
146 static void
147 x87_set_control_word(unsigned short mode) {
148   __asm__ __volatile__("fldcw %0" : : "m"( *&mode));
149 }
150 static unsigned short
151 x87_get_control_word(void) {
152   unsigned short mode;
153   __asm__ __volatile__("fstcw %0\n\t":"=m"( *&mode):);
154   return mode;
155 }
156 #elif ARCH_X86_64
157 /* No fldcw intrinsics on Windows x64, punt to external asm */
158 extern void           vpx_winx64_fldcw(unsigned short mode);
159 extern unsigned short vpx_winx64_fstcw(void);
160 #define x87_set_control_word vpx_winx64_fldcw
161 #define x87_get_control_word vpx_winx64_fstcw
162 #else
163 static void
164 x87_set_control_word(unsigned short mode) {
165   __asm { fldcw mode }
166 }
167 static unsigned short
168 x87_get_control_word(void) {
169   unsigned short mode;
170   __asm { fstcw mode }
171   return mode;
172 }
173 #endif
174
175 static unsigned short
176 x87_set_double_precision(void) {
177   unsigned short mode = x87_get_control_word();
178   x87_set_control_word((mode&~0x300) | 0x200);
179   return mode;
180 }
181
182
183 extern void vpx_reset_mmx_state(void);
184 #endif
185