1 | #ifndef _OS_H
|
---|
2 | #define _OS_H
|
---|
3 | /********************************************************************
|
---|
4 | * *
|
---|
5 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
---|
6 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
---|
7 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
---|
8 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
---|
9 | * *
|
---|
10 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
|
---|
11 | * by the Xiph.Org Foundation https://xiph.org/ *
|
---|
12 | * *
|
---|
13 | ********************************************************************
|
---|
14 |
|
---|
15 | function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
---|
16 |
|
---|
17 | ********************************************************************/
|
---|
18 |
|
---|
19 | #ifdef HAVE_CONFIG_H
|
---|
20 | #include "config.h"
|
---|
21 | #endif
|
---|
22 |
|
---|
23 | #include <math.h>
|
---|
24 | #include <ogg/os_types.h>
|
---|
25 |
|
---|
26 | #include "misc.h"
|
---|
27 |
|
---|
28 | #ifndef _V_IFDEFJAIL_H_
|
---|
29 | # define _V_IFDEFJAIL_H_
|
---|
30 |
|
---|
31 | # ifdef __GNUC__
|
---|
32 | # define STIN static __inline__
|
---|
33 | # elif defined(_WIN32)
|
---|
34 | # define STIN static __inline
|
---|
35 | # else
|
---|
36 | # define STIN static
|
---|
37 | # endif
|
---|
38 |
|
---|
39 | #ifdef DJGPP
|
---|
40 | # define rint(x) (floor((x)+0.5f))
|
---|
41 | #endif
|
---|
42 |
|
---|
43 | #ifndef M_PI
|
---|
44 | # define M_PI (3.1415926536f)
|
---|
45 | #endif
|
---|
46 |
|
---|
47 | #if defined(_WIN32) && !defined(__SYMBIAN32__)
|
---|
48 | # include <malloc.h>
|
---|
49 | # define rint(x) (floor((x)+0.5f))
|
---|
50 | # define NO_FLOAT_MATH_LIB
|
---|
51 | # define FAST_HYPOT(a, b) sqrt((a)*(a) + (b)*(b))
|
---|
52 | #endif
|
---|
53 |
|
---|
54 | #if defined(__SYMBIAN32__) && defined(__WINS__)
|
---|
55 | void *_alloca(size_t size);
|
---|
56 | # define alloca _alloca
|
---|
57 | #endif
|
---|
58 |
|
---|
59 | #ifndef FAST_HYPOT
|
---|
60 | # define FAST_HYPOT hypot
|
---|
61 | #endif
|
---|
62 |
|
---|
63 | #endif /* _V_IFDEFJAIL_H_ */
|
---|
64 |
|
---|
65 | #ifdef HAVE_ALLOCA_H
|
---|
66 | # include <alloca.h>
|
---|
67 | #endif
|
---|
68 |
|
---|
69 | #ifdef USE_MEMORY_H
|
---|
70 | # include <memory.h>
|
---|
71 | #endif
|
---|
72 |
|
---|
73 | #ifndef min
|
---|
74 | # define min(x,y) ((x)>(y)?(y):(x))
|
---|
75 | #endif
|
---|
76 |
|
---|
77 | #ifndef max
|
---|
78 | # define max(x,y) ((x)<(y)?(y):(x))
|
---|
79 | #endif
|
---|
80 |
|
---|
81 |
|
---|
82 | /* Special i386 GCC implementation */
|
---|
83 | #if defined(__i386__) && defined(__GNUC__) && !defined(__BEOS__) && !defined(__SSE2_MATH__)
|
---|
84 | # define VORBIS_FPU_CONTROL
|
---|
85 | /* both GCC and MSVC are kinda stupid about rounding/casting to int.
|
---|
86 | Because of encapsulation constraints (GCC can't see inside the asm
|
---|
87 | block and so we end up doing stupid things like a store/load that
|
---|
88 | is collectively a noop), we do it this way */
|
---|
89 |
|
---|
90 | /* we must set up the fpu before this works!! */
|
---|
91 |
|
---|
92 | typedef ogg_int16_t vorbis_fpu_control;
|
---|
93 |
|
---|
94 | static inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
|
---|
95 | ogg_int16_t ret;
|
---|
96 | ogg_int16_t temp;
|
---|
97 | __asm__ __volatile__("fnstcw %0\n\t"
|
---|
98 | "movw %0,%%dx\n\t"
|
---|
99 | "andw $62463,%%dx\n\t"
|
---|
100 | "movw %%dx,%1\n\t"
|
---|
101 | "fldcw %1\n\t":"=m"(ret):"m"(temp): "dx");
|
---|
102 | *fpu=ret;
|
---|
103 | }
|
---|
104 |
|
---|
105 | static inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
|
---|
106 | __asm__ __volatile__("fldcw %0":: "m"(fpu));
|
---|
107 | }
|
---|
108 |
|
---|
109 | /* assumes the FPU is in round mode! */
|
---|
110 | static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise,
|
---|
111 | we get extra fst/fld to
|
---|
112 | truncate precision */
|
---|
113 | int i;
|
---|
114 | __asm__("fistl %0": "=m"(i) : "t"(f));
|
---|
115 | return(i);
|
---|
116 | }
|
---|
117 | #endif /* Special i386 GCC implementation */
|
---|
118 |
|
---|
119 |
|
---|
120 | /* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the
|
---|
121 | * 64 bit compiler and doesn't work on arm. */
|
---|
122 | #if defined(_MSC_VER) && defined(_M_IX86) && !defined(_WIN32_WCE)
|
---|
123 | # define VORBIS_FPU_CONTROL
|
---|
124 |
|
---|
125 | typedef ogg_int16_t vorbis_fpu_control;
|
---|
126 |
|
---|
127 | static __inline int vorbis_ftoi(double f){
|
---|
128 | int i;
|
---|
129 | __asm{
|
---|
130 | fld f
|
---|
131 | fistp i
|
---|
132 | }
|
---|
133 | return i;
|
---|
134 | }
|
---|
135 |
|
---|
136 | static __inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
|
---|
137 | (void)fpu;
|
---|
138 | }
|
---|
139 |
|
---|
140 | static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
|
---|
141 | (void)fpu;
|
---|
142 | }
|
---|
143 |
|
---|
144 | #endif /* Special MSVC 32 bit implementation */
|
---|
145 |
|
---|
146 |
|
---|
147 | /* Optimized code path for x86_64 builds. Uses SSE2 intrinsics. This can be
|
---|
148 | done safely because all x86_64 CPUs supports SSE2. */
|
---|
149 | #if (defined(_MSC_VER) && defined(_M_X64)) || (defined(__GNUC__) && defined (__SSE2_MATH__))
|
---|
150 | # define VORBIS_FPU_CONTROL
|
---|
151 |
|
---|
152 | typedef ogg_int16_t vorbis_fpu_control;
|
---|
153 |
|
---|
154 | #include <emmintrin.h>
|
---|
155 | static __inline int vorbis_ftoi(double f){
|
---|
156 | return _mm_cvtsd_si32(_mm_load_sd(&f));
|
---|
157 | }
|
---|
158 |
|
---|
159 | static __inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
|
---|
160 | (void)fpu;
|
---|
161 | }
|
---|
162 |
|
---|
163 | static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
|
---|
164 | (void)fpu;
|
---|
165 | }
|
---|
166 |
|
---|
167 | #endif /* Special MSVC x64 implementation */
|
---|
168 |
|
---|
169 |
|
---|
170 | /* If no special implementation was found for the current compiler / platform,
|
---|
171 | use the default implementation here: */
|
---|
172 | #ifndef VORBIS_FPU_CONTROL
|
---|
173 |
|
---|
174 | typedef int vorbis_fpu_control;
|
---|
175 |
|
---|
176 | STIN int vorbis_ftoi(double f){
|
---|
177 | /* Note: MSVC and GCC (at least on some systems) round towards zero, thus,
|
---|
178 | the floor() call is required to ensure correct roudning of
|
---|
179 | negative numbers */
|
---|
180 | return (int)floor(f+.5);
|
---|
181 | }
|
---|
182 |
|
---|
183 | /* We don't have special code for this compiler/arch, so do it the slow way */
|
---|
184 | # define vorbis_fpu_setround(vorbis_fpu_control) {}
|
---|
185 | # define vorbis_fpu_restore(vorbis_fpu_control) {}
|
---|
186 |
|
---|
187 | #endif /* default implementation */
|
---|
188 |
|
---|
189 | #endif /* _OS_H */
|
---|