Add support for native Solaris compiler on x86.
[profile/ivi/libvpx.git] / vpx_ports / x86.h
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 "vpx_config.h"
16
17 typedef 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
37 #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__ (\
47                           "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));
52 #endif
53 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
54 #if ARCH_X86_64
55 #define cpuid(func,ax,bx,cx,dx)\
56     asm volatile (\
57                   "xchg %rsi, %rbx \n\t" \
58                   "cpuid           \n\t" \
59                   "movl %ebx, %edi \n\t" \
60                   "xchg %rsi, %rbx \n\t" \
61                   : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
62                   : "a"  (func));
63 #else
64 #define cpuid(func,ax,bx,cx,dx)\
65     asm volatile (\
66                   "pushl %ebx       \n\t" \
67                   "cpuid            \n\t" \
68                   "movl %ebx, %edi  \n\t" \
69                   "popl %ebx        \n\t" \
70                   : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
71                   : "a" (func));
72 #endif
73 #else
74 #if ARCH_X86_64
75 void __cpuid(int CPUInfo[4], int info_type);
76 #pragma intrinsic(__cpuid)
77 #define cpuid(func,a,b,c,d) do{\
78         int regs[4];\
79         __cpuid(regs,func); a=regs[0];  b=regs[1];  c=regs[2];  d=regs[3];\
80     } while(0)
81 #else
82 #define cpuid(func,a,b,c,d)\
83     __asm mov eax, func\
84     __asm cpuid\
85     __asm mov a, eax\
86     __asm mov b, ebx\
87     __asm mov c, ecx\
88     __asm mov d, edx
89 #endif
90 #endif
91
92 #define HAS_MMX   0x01
93 #define HAS_SSE   0x02
94 #define HAS_SSE2  0x04
95 #define HAS_SSE3  0x08
96 #define HAS_SSSE3 0x10
97 #define HAS_SSE4_1 0x20
98 #ifndef BIT
99 #define BIT(n) (1<<n)
100 #endif
101
102 static int
103 x86_simd_caps(void)
104 {
105     unsigned int flags = 0;
106     unsigned int mask = ~0;
107     unsigned int reg_eax, reg_ebx, reg_ecx, reg_edx;
108     char *env;
109     (void)reg_ebx;
110
111     /* See if the CPU capabilities are being overridden by the environment */
112     env = getenv("VPX_SIMD_CAPS");
113
114     if (env && *env)
115         return (int)strtol(env, NULL, 0);
116
117     env = getenv("VPX_SIMD_CAPS_MASK");
118
119     if (env && *env)
120         mask = strtol(env, NULL, 0);
121
122     /* Ensure that the CPUID instruction supports extended features */
123     cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
124
125     if (reg_eax < 1)
126         return 0;
127
128     /* Get the standard feature flags */
129     cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
130
131     if (reg_edx & BIT(23)) flags |= HAS_MMX;
132
133     if (reg_edx & BIT(25)) flags |= HAS_SSE; /* aka xmm */
134
135     if (reg_edx & BIT(26)) flags |= HAS_SSE2; /* aka wmt */
136
137     if (reg_ecx & BIT(0))  flags |= HAS_SSE3;
138
139     if (reg_ecx & BIT(9))  flags |= HAS_SSSE3;
140
141     if (reg_ecx & BIT(19)) flags |= HAS_SSE4_1;
142
143     return flags & mask;
144 }
145
146 vpx_cpu_t vpx_x86_vendor(void);
147
148 #if ARCH_X86_64 && defined(_MSC_VER)
149 unsigned __int64 __rdtsc(void);
150 #pragma intrinsic(__rdtsc)
151 #endif
152 static unsigned int
153 x86_readtsc(void)
154 {
155 #if defined(__GNUC__) && __GNUC__
156     unsigned int tsc;
157     __asm__ __volatile__("rdtsc\n\t":"=a"(tsc):);
158     return tsc;
159 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
160     unsigned int tsc;
161     asm volatile("rdtsc\n\t":"=a"(tsc):);
162     return tsc;
163 #else
164 #if ARCH_X86_64
165     return __rdtsc();
166 #else
167     __asm  rdtsc;
168 #endif
169 #endif
170 }
171
172
173 #if defined(__GNUC__) && __GNUC__
174 #define x86_pause_hint()\
175     __asm__ __volatile__ ("pause \n\t")
176 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
177 #define x86_pause_hint()\
178     asm volatile ("pause \n\t")
179 #else
180 #if ARCH_X86_64
181 #define x86_pause_hint()\
182     _mm_pause();
183 #else
184 #define x86_pause_hint()\
185     __asm pause
186 #endif
187 #endif
188
189 #if defined(__GNUC__) && __GNUC__
190 static void
191 x87_set_control_word(unsigned short mode)
192 {
193     __asm__ __volatile__("fldcw %0" : : "m"(*&mode));
194 }
195 static unsigned short
196 x87_get_control_word(void)
197 {
198     unsigned short mode;
199     __asm__ __volatile__("fstcw %0\n\t":"=m"(*&mode):);
200     return mode;
201 }
202 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
203 static void
204 x87_set_control_word(unsigned short mode)
205 {
206     asm volatile("fldcw %0" : : "m"(*&mode));
207 }
208 static unsigned short
209 x87_get_control_word(void)
210 {
211     unsigned short mode;
212     asm volatile("fstcw %0\n\t":"=m"(*&mode):);
213     return mode;
214 }
215 #elif ARCH_X86_64
216 /* No fldcw intrinsics on Windows x64, punt to external asm */
217 extern void           vpx_winx64_fldcw(unsigned short mode);
218 extern unsigned short vpx_winx64_fstcw(void);
219 #define x87_set_control_word vpx_winx64_fldcw
220 #define x87_get_control_word vpx_winx64_fstcw
221 #else
222 static void
223 x87_set_control_word(unsigned short mode)
224 {
225     __asm { fldcw mode }
226 }
227 static unsigned short
228 x87_get_control_word(void)
229 {
230     unsigned short mode;
231     __asm { fstcw mode }
232     return mode;
233 }
234 #endif
235
236 static unsigned short
237 x87_set_double_precision(void)
238 {
239     unsigned short mode = x87_get_control_word();
240     x87_set_control_word((mode&~0x300) | 0x200);
241     return mode;
242 }
243
244
245 extern void vpx_reset_mmx_state(void);
246 #endif
247