1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifndef VPX_PORTS_X86_H_
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define VPX_PORTS_X86_H_
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx_config.h"
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef __cplusplus
18233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern "C" {
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan
21233d2500723e5594f3e7c70896ffeeef32b9c950ywantypedef enum {
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_UNKNOWN = -1,
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_AMD,
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_AMD_OLD,
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_CENTAUR,
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_CYRIX,
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_INTEL,
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_NEXGEN,
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_NSC,
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_RISE,
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_SIS,
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_TRANSMETA,
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_TRANSMETA_OLD,
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_UMC,
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_VIA,
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VPX_CPU_LAST
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  vpx_cpu_t;
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(__GNUC__) && __GNUC__ || defined(__ANDROID__)
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_X86_64
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, ax, bx, cx, dx)\
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm__ __volatile__ (\
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        "cpuid           \n\t" \
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        : "a" (func), "c" (func2));
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, ax, bx, cx, dx)\
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm__ __volatile__ (\
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        "mov %%ebx, %%edi   \n\t" \
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        "cpuid              \n\t" \
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        "xchg %%edi, %%ebx  \n\t" \
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan                        : "a" (func), "c" (func2));
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* end __GNUC__ or __ANDROID__*/
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_X86_64
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, ax, bx, cx, dx)\
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan  asm volatile (\
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "xchg %rsi, %rbx \n\t" \
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "cpuid           \n\t" \
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "movl %ebx, %edi \n\t" \
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "xchg %rsi, %rbx \n\t" \
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan                : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan                : "a" (func), "c" (func2));
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, ax, bx, cx, dx)\
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan  asm volatile (\
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "pushl %ebx       \n\t" \
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "cpuid            \n\t" \
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "movl %ebx, %edi  \n\t" \
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan                "popl %ebx        \n\t" \
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan                : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan                : "a" (func), "c" (func2));
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else /* end __SUNPRO__ */
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_X86_64
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(_MSC_VER) && _MSC_VER > 1500
79233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid __cpuidex(int CPUInfo[4], int info_type, int ecxvalue);
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan#pragma intrinsic(__cpuidex)
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, a, b, c, d) do {\
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int regs[4];\
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan    __cpuidex(regs, func, func2); \
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan    a = regs[0];  b = regs[1];  c = regs[2];  d = regs[3];\
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } while(0)
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
87233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid __cpuid(int CPUInfo[4], int info_type);
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan#pragma intrinsic(__cpuid)
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, a, b, c, d) do {\
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int regs[4];\
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan    __cpuid(regs, func); \
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan    a = regs[0];  b = regs[1];  c = regs[2];  d = regs[3];\
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } while (0)
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define cpuid(func, func2, a, b, c, d)\
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm mov eax, func\
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm mov ecx, func2\
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm cpuid\
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm mov a, eax\
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm mov b, ebx\
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm mov c, ecx\
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm mov d, edx
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif /* end others */
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_MMX     0x01
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_SSE     0x02
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_SSE2    0x04
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_SSE3    0x08
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_SSSE3   0x10
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_SSE4_1  0x20
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_AVX     0x40
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define HAS_AVX2    0x80
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifndef BIT
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define BIT(n) (1<<n)
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
120233d2500723e5594f3e7c70896ffeeef32b9c950ywanx86_simd_caps(void) {
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int flags = 0;
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int mask = ~0;
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char *env;
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan  (void)reg_ebx;
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* See if the CPU capabilities are being overridden by the environment */
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  env = getenv("VPX_SIMD_CAPS");
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (env && *env)
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return (int)strtol(env, NULL, 0);
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  env = getenv("VPX_SIMD_CAPS_MASK");
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (env && *env)
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mask = strtol(env, NULL, 0);
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Ensure that the CPUID instruction supports extended features */
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpuid(0, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_eax < 1)
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Get the standard feature flags */
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpuid(1, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_edx & BIT(23)) flags |= HAS_MMX;
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_ecx & BIT(0)) flags |= HAS_SSE3;
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_ecx & BIT(9)) flags |= HAS_SSSE3;
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_ecx & BIT(19)) flags |= HAS_SSE4_1;
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
159233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_ecx & BIT(28)) flags |= HAS_AVX;
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Get the leaf 7 feature flags. Needed to check for AVX2 support */
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan  reg_eax = 7;
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan  reg_ecx = 0;
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cpuid(7, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (reg_ebx & BIT(5)) flags |= HAS_AVX2;
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return flags & mask;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_X86_64 && defined(_MSC_VER)
172233d2500723e5594f3e7c70896ffeeef32b9c950ywanunsigned __int64 __rdtsc(void);
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan#pragma intrinsic(__rdtsc)
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
175233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int
176233d2500723e5594f3e7c70896ffeeef32b9c950ywanx86_readtsc(void) {
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(__GNUC__) && __GNUC__
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int tsc;
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm__ __volatile__("rdtsc\n\t":"=a"(tsc):);
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return tsc;
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int tsc;
183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  asm volatile("rdtsc\n\t":"=a"(tsc):);
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return tsc;
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_X86_64
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return (unsigned int)__rdtsc();
188233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm  rdtsc;
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
192233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(__GNUC__) && __GNUC__
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define x86_pause_hint()\
197233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm__ __volatile__ ("pause \n\t")
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define x86_pause_hint()\
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  asm volatile ("pause \n\t")
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if ARCH_X86_64
203233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define x86_pause_hint()\
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan  _mm_pause();
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define x86_pause_hint()\
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm pause
208233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan#if defined(__GNUC__) && __GNUC__
212233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
213233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_set_control_word(unsigned short mode) {
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm__ __volatile__("fldcw %0" : : "m"(*&mode));
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
216233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned short
217233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_get_control_word(void) {
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned short mode;
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm__ __volatile__("fstcw %0\n\t":"=m"(*&mode):);
220233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return mode;
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
223233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
224233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_set_control_word(unsigned short mode) {
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan  asm volatile("fldcw %0" : : "m"(*&mode));
226233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
227233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned short
228233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_get_control_word(void) {
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned short mode;
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan  asm volatile("fstcw %0\n\t":"=m"(*&mode):);
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return mode;
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif ARCH_X86_64
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* No fldcw intrinsics on Windows x64, punt to external asm */
235233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern void           vpx_winx64_fldcw(unsigned short mode);
236233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern unsigned short vpx_winx64_fstcw(void);
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define x87_set_control_word vpx_winx64_fldcw
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define x87_get_control_word vpx_winx64_fstcw
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else
240233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
241233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_set_control_word(unsigned short mode) {
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm { fldcw mode }
243233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
244233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned short
245233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_get_control_word(void) {
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned short mode;
247233d2500723e5594f3e7c70896ffeeef32b9c950ywan  __asm { fstcw mode }
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return mode;
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan
252233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned short
253233d2500723e5594f3e7c70896ffeeef32b9c950ywanx87_set_double_precision(void) {
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned short mode = x87_get_control_word();
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan  x87_set_control_word((mode&~0x300) | 0x200);
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return mode;
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
258233d2500723e5594f3e7c70896ffeeef32b9c950ywan
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan
260233d2500723e5594f3e7c70896ffeeef32b9c950ywanextern void vpx_reset_mmx_state(void);
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan
262233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef __cplusplus
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan}  // extern "C"
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif  // VPX_PORTS_X86_H_
267