blob: feffc3e69b7000efd083a653cf8953bc8a1088ee [file] [log] [blame]
John Koleszar0ea50ce2010-05-18 11:58:33 -04001/*
John Koleszarc2140b82010-09-09 08:16:39 -04002 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar0ea50ce2010-05-18 11:58:33 -04003 *
John Koleszar94c52e42010-06-18 12:39:21 -04004 * Use of this source code is governed by a BSD-style license
John Koleszar09202d82010-06-04 16:19:40 -04005 * 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
John Koleszar94c52e42010-06-18 12:39:21 -04007 * in the file PATENTS. All contributing project authors may
John Koleszar09202d82010-06-04 16:19:40 -04008 * be found in the AUTHORS file in the root of the source tree.
John Koleszar0ea50ce2010-05-18 11:58:33 -04009 */
10
11
12#ifndef VPX_PORTS_X86_H
13#define VPX_PORTS_X86_H
14#include <stdlib.h>
15#include "config.h"
16
Fritz Koenig0f5c63e2010-10-12 14:55:31 -070017typedef enum
18{
19 VPX_CPU_UNKNOWN = -1,
20 VPX_CPU_AMD,
21 VPX_CPU_AMD_OLD,
22 VPX_CPU_CENTAUR,
23 VPX_CPU_CYRIX,
24 VPX_CPU_INTEL,
25 VPX_CPU_NEXGEN,
26 VPX_CPU_NSC,
27 VPX_CPU_RISE,
28 VPX_CPU_SIS,
29 VPX_CPU_TRANSMETA,
30 VPX_CPU_TRANSMETA_OLD,
31 VPX_CPU_UMC,
32 VPX_CPU_VIA,
33
34 VPX_CPU_LAST
35} vpx_cpu_t;
36
John Koleszar0ea50ce2010-05-18 11:58:33 -040037#if defined(__GNUC__) && __GNUC__
38#if ARCH_X86_64
39#define cpuid(func,ax,bx,cx,dx)\
40 __asm__ __volatile__ (\
41 "cpuid \n\t" \
42 : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
43 : "a" (func));
44#else
45#define cpuid(func,ax,bx,cx,dx)\
46 __asm__ __volatile__ (\
Fritz Koenige50f5d42010-10-12 09:42:03 -070047 "mov %%ebx, %%edi \n\t" \
48 "cpuid \n\t" \
49 "xchg %%edi, %%ebx \n\t" \
50 : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
51 : "a" (func));
John Koleszar0ea50ce2010-05-18 11:58:33 -040052#endif
53#else
54#if ARCH_X86_64
55void __cpuid(int CPUInfo[4], int info_type);
56#pragma intrinsic(__cpuid)
57#define cpuid(func,a,b,c,d) do{\
58 int regs[4];\
59 __cpuid(regs,func); a=regs[0]; b=regs[1]; c=regs[2]; d=regs[3];\
60 } while(0)
61#else
62#define cpuid(func,a,b,c,d)\
63 __asm mov eax, func\
64 __asm cpuid\
65 __asm mov a, eax\
66 __asm mov b, ebx\
67 __asm mov c, ecx\
68 __asm mov d, edx
69#endif
70#endif
71
72#define HAS_MMX 0x01
73#define HAS_SSE 0x02
74#define HAS_SSE2 0x04
75#define HAS_SSE3 0x08
76#define HAS_SSSE3 0x10
77#ifndef BIT
78#define BIT(n) (1<<n)
79#endif
80
81static int
82x86_simd_caps(void)
83{
84 unsigned int flags = 0;
85 unsigned int mask = ~0;
86 unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
87 char *env;
88 (void)reg_ebx;
89
90 /* See if the CPU capabilities are being overridden by the environment */
91 env = getenv("VPX_SIMD_CAPS");
92
93 if (env && *env)
94 return (int)strtol(env, NULL, 0);
95
96 env = getenv("VPX_SIMD_CAPS_MASK");
97
98 if (env && *env)
99 mask = strtol(env, NULL, 0);
100
101 /* Ensure that the CPUID instruction supports extended features */
102 cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
103
104 if (reg_eax < 1)
105 return 0;
106
107 /* Get the standard feature flags */
108 cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
109
110 if (reg_edx & BIT(23)) flags |= HAS_MMX;
111
112 if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
113
114 if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
115
116 if (reg_ecx & BIT(0)) flags |= HAS_SSE3;
117
118 if (reg_ecx & BIT(9)) flags |= HAS_SSSE3;
119
120 return flags & mask;
121}
122
Fritz Koenig0f5c63e2010-10-12 14:55:31 -0700123vpx_cpu_t vpx_x86_vendor(void);
John Koleszar0ea50ce2010-05-18 11:58:33 -0400124
125#if ARCH_X86_64 && defined(_MSC_VER)
126unsigned __int64 __rdtsc(void);
127#pragma intrinsic(__rdtsc)
128#endif
129static unsigned int
130x86_readtsc(void)
131{
132#if defined(__GNUC__) && __GNUC__
133 unsigned int tsc;
134 __asm__ __volatile__("rdtsc\n\t":"=a"(tsc):);
135 return tsc;
136#else
137#if ARCH_X86_64
138 return __rdtsc();
139#else
140 __asm rdtsc;
141#endif
142#endif
143}
144
145
146#if defined(__GNUC__) && __GNUC__
147#define x86_pause_hint()\
148 __asm__ __volatile__ ("pause \n\t")
149#else
150#if ARCH_X86_64
151/* No pause intrinsic for windows x64 */
152#define x86_pause_hint()
153#else
154#define x86_pause_hint()\
155 __asm pause
156#endif
157#endif
158
159#if defined(__GNUC__) && __GNUC__
160static void
161x87_set_control_word(unsigned short mode)
162{
163 __asm__ __volatile__("fldcw %0" : : "m"(*&mode));
164}
165static unsigned short
166x87_get_control_word(void)
167{
168 unsigned short mode;
169 __asm__ __volatile__("fstcw %0\n\t":"=m"(*&mode):);
170 return mode;
171}
172#elif ARCH_X86_64
173/* No fldcw intrinsics on Windows x64, punt to external asm */
174extern void vpx_winx64_fldcw(unsigned short mode);
175extern unsigned short vpx_winx64_fstcw(void);
176#define x87_set_control_word vpx_winx64_fldcw
177#define x87_get_control_word vpx_winx64_fstcw
178#else
179static void
180x87_set_control_word(unsigned short mode)
181{
182 __asm { fldcw mode }
183}
184static unsigned short
185x87_get_control_word(void)
186{
187 unsigned short mode;
188 __asm { fstcw mode }
189 return mode;
190}
191#endif
192
193static unsigned short
194x87_set_double_precision(void)
195{
196 unsigned short mode = x87_get_control_word();
197 x87_set_control_word((mode&~0x300) | 0x200);
198 return mode;
199}
200
201
202extern void vpx_reset_mmx_state(void);
203#endif
204