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