190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/*
2f71323e297a928af368937089d3ed71239786f86Andreas Huber *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber *
4f71323e297a928af368937089d3ed71239786f86Andreas Huber *  Use of this source code is governed by a BSD-style license
5f71323e297a928af368937089d3ed71239786f86Andreas Huber *  that can be found in the LICENSE file in the root of the source
6f71323e297a928af368937089d3ed71239786f86Andreas Huber *  tree. An additional intellectual property rights grant can be found
7f71323e297a928af368937089d3ed71239786f86Andreas Huber *  in the file PATENTS.  All contributing project authors may
8f71323e297a928af368937089d3ed71239786f86Andreas Huber *  be found in the AUTHORS file in the root of the source tree.
990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber */
1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
1290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifndef VPX_PORTS_X86_H
1390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define VPX_PORTS_X86_H
1490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdlib.h>
151b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx_config.h"
1690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubertypedef enum
18538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
19538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_UNKNOWN = -1,
20538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_AMD,
21538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_AMD_OLD,
22538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_CENTAUR,
23538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_CYRIX,
24538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_INTEL,
25538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_NEXGEN,
26538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_NSC,
27538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_RISE,
28538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_SIS,
29538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_TRANSMETA,
30538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_TRANSMETA_OLD,
31538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_UMC,
32538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_VIA,
33538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
34538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    VPX_CPU_LAST
35538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}  vpx_cpu_t;
36538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
3790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if defined(__GNUC__) && __GNUC__
3890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if ARCH_X86_64
3990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define cpuid(func,ax,bx,cx,dx)\
4090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm__ __volatile__ (\
4190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          "cpuid           \n\t" \
4290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
4390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber                          : "a"  (func));
4490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
4590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define cpuid(func,ax,bx,cx,dx)\
4690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm__ __volatile__ (\
47538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                          "mov %%ebx, %%edi   \n\t" \
48538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                          "cpuid              \n\t" \
49538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                          "xchg %%edi, %%ebx  \n\t" \
50538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                          : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
51538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                          : "a" (func));
5290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
531b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
541b362b15af34006e6a11974088a46d42b903418eJohann#if ARCH_X86_64
551b362b15af34006e6a11974088a46d42b903418eJohann#define cpuid(func,ax,bx,cx,dx)\
561b362b15af34006e6a11974088a46d42b903418eJohann    asm volatile (\
571b362b15af34006e6a11974088a46d42b903418eJohann                  "xchg %rsi, %rbx \n\t" \
581b362b15af34006e6a11974088a46d42b903418eJohann                  "cpuid           \n\t" \
591b362b15af34006e6a11974088a46d42b903418eJohann                  "movl %ebx, %edi \n\t" \
601b362b15af34006e6a11974088a46d42b903418eJohann                  "xchg %rsi, %rbx \n\t" \
611b362b15af34006e6a11974088a46d42b903418eJohann                  : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
621b362b15af34006e6a11974088a46d42b903418eJohann                  : "a"  (func));
631b362b15af34006e6a11974088a46d42b903418eJohann#else
641b362b15af34006e6a11974088a46d42b903418eJohann#define cpuid(func,ax,bx,cx,dx)\
651b362b15af34006e6a11974088a46d42b903418eJohann    asm volatile (\
661b362b15af34006e6a11974088a46d42b903418eJohann                  "pushl %ebx       \n\t" \
671b362b15af34006e6a11974088a46d42b903418eJohann                  "cpuid            \n\t" \
681b362b15af34006e6a11974088a46d42b903418eJohann                  "movl %ebx, %edi  \n\t" \
691b362b15af34006e6a11974088a46d42b903418eJohann                  "popl %ebx        \n\t" \
701b362b15af34006e6a11974088a46d42b903418eJohann                  : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
711b362b15af34006e6a11974088a46d42b903418eJohann                  : "a" (func));
721b362b15af34006e6a11974088a46d42b903418eJohann#endif
7390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
7490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if ARCH_X86_64
7590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervoid __cpuid(int CPUInfo[4], int info_type);
7690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#pragma intrinsic(__cpuid)
7790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define cpuid(func,a,b,c,d) do{\
7890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        int regs[4];\
7990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        __cpuid(regs,func); a=regs[0];  b=regs[1];  c=regs[2];  d=regs[3];\
8090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    } while(0)
8190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
8290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define cpuid(func,a,b,c,d)\
8390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm mov eax, func\
8490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm cpuid\
8590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm mov a, eax\
8690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm mov b, ebx\
8790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm mov c, ecx\
8890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm mov d, edx
8990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
9090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
9190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
9290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define HAS_MMX   0x01
9390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define HAS_SSE   0x02
9490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define HAS_SSE2  0x04
9590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define HAS_SSE3  0x08
9690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define HAS_SSSE3 0x10
97538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define HAS_SSE4_1 0x20
9890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifndef BIT
9990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define BIT(n) (1<<n)
10090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
10190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
10290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic int
10390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx86_simd_caps(void)
10490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
10590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned int flags = 0;
10690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned int mask = ~0;
10790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
10890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    char *env;
10990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    (void)reg_ebx;
11090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    /* See if the CPU capabilities are being overridden by the environment */
11290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    env = getenv("VPX_SIMD_CAPS");
11390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (env && *env)
11590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return (int)strtol(env, NULL, 0);
11690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    env = getenv("VPX_SIMD_CAPS_MASK");
11890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
11990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (env && *env)
12090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        mask = strtol(env, NULL, 0);
12190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
12290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    /* Ensure that the CPUID instruction supports extended features */
12390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
12490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
12590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (reg_eax < 1)
12690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber        return 0;
12790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
12890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    /* Get the standard feature flags */
12990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
13090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
13190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (reg_edx & BIT(23)) flags |= HAS_MMX;
13290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
13390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
13490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
13590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
13690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
13790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (reg_ecx & BIT(0))  flags |= HAS_SSE3;
13890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
13990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    if (reg_ecx & BIT(9))  flags |= HAS_SSSE3;
14090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (reg_ecx & BIT(19)) flags |= HAS_SSE4_1;
142538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
14390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return flags & mask;
14490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
14590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervpx_cpu_t vpx_x86_vendor(void);
14790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
14890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if ARCH_X86_64 && defined(_MSC_VER)
14990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberunsigned __int64 __rdtsc(void);
15090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#pragma intrinsic(__rdtsc)
15190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
15290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic unsigned int
15390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx86_readtsc(void)
15490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
15590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if defined(__GNUC__) && __GNUC__
15690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned int tsc;
15790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm__ __volatile__("rdtsc\n\t":"=a"(tsc):);
15890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return tsc;
1591b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
1601b362b15af34006e6a11974088a46d42b903418eJohann    unsigned int tsc;
1611b362b15af34006e6a11974088a46d42b903418eJohann    asm volatile("rdtsc\n\t":"=a"(tsc):);
1621b362b15af34006e6a11974088a46d42b903418eJohann    return tsc;
16390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
16490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if ARCH_X86_64
1651b362b15af34006e6a11974088a46d42b903418eJohann    return (unsigned int)__rdtsc();
16690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
16790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm  rdtsc;
16890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
16990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
17090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
17190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
17390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if defined(__GNUC__) && __GNUC__
17490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define x86_pause_hint()\
17590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm__ __volatile__ ("pause \n\t")
1761b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
1771b362b15af34006e6a11974088a46d42b903418eJohann#define x86_pause_hint()\
1781b362b15af34006e6a11974088a46d42b903418eJohann    asm volatile ("pause \n\t")
17990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
18090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if ARCH_X86_64
1811b362b15af34006e6a11974088a46d42b903418eJohann#define x86_pause_hint()\
1821b362b15af34006e6a11974088a46d42b903418eJohann    _mm_pause();
18390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
18490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define x86_pause_hint()\
18590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm pause
18690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
18790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
18890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
18990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#if defined(__GNUC__) && __GNUC__
19090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void
19190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx87_set_control_word(unsigned short mode)
19290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
19390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm__ __volatile__("fldcw %0" : : "m"(*&mode));
19490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
19590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic unsigned short
19690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx87_get_control_word(void)
19790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
19890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned short mode;
19990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm__ __volatile__("fstcw %0\n\t":"=m"(*&mode):);
20090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return mode;
20190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
2021b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
2031b362b15af34006e6a11974088a46d42b903418eJohannstatic void
2041b362b15af34006e6a11974088a46d42b903418eJohannx87_set_control_word(unsigned short mode)
2051b362b15af34006e6a11974088a46d42b903418eJohann{
2061b362b15af34006e6a11974088a46d42b903418eJohann    asm volatile("fldcw %0" : : "m"(*&mode));
2071b362b15af34006e6a11974088a46d42b903418eJohann}
2081b362b15af34006e6a11974088a46d42b903418eJohannstatic unsigned short
2091b362b15af34006e6a11974088a46d42b903418eJohannx87_get_control_word(void)
2101b362b15af34006e6a11974088a46d42b903418eJohann{
2111b362b15af34006e6a11974088a46d42b903418eJohann    unsigned short mode;
2121b362b15af34006e6a11974088a46d42b903418eJohann    asm volatile("fstcw %0\n\t":"=m"(*&mode):);
2131b362b15af34006e6a11974088a46d42b903418eJohann    return mode;
2141b362b15af34006e6a11974088a46d42b903418eJohann}
21590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#elif ARCH_X86_64
21690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/* No fldcw intrinsics on Windows x64, punt to external asm */
21790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberextern void           vpx_winx64_fldcw(unsigned short mode);
21890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberextern unsigned short vpx_winx64_fstcw(void);
21990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define x87_set_control_word vpx_winx64_fldcw
22090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define x87_get_control_word vpx_winx64_fstcw
22190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else
22290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic void
22390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx87_set_control_word(unsigned short mode)
22490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
22590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm { fldcw mode }
22690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
22790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic unsigned short
22890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx87_get_control_word(void)
22990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
23090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned short mode;
23190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    __asm { fstcw mode }
23290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return mode;
23390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
23490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
23590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
23690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberstatic unsigned short
23790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberx87_set_double_precision(void)
23890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{
23990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    unsigned short mode = x87_get_control_word();
24090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    x87_set_control_word((mode&~0x300) | 0x200);
24190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber    return mode;
24290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber}
24390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
24490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
24590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberextern void vpx_reset_mmx_state(void);
24690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif
24790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber
248