Merge "More on "some XMM registers are non-volatile on windows x64 ABI""
[profile/ivi/libvpx.git] / vpx_ports / x86.h
1 /*
2  *  Copyright (c) 2010 The VP8 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