rt: subsampling wip
[dosdemo] / src / util.h
1 #ifndef UTIL_H_
2 #define UTIL_H_
3
4 #include <stdlib.h>
5 #include "inttypes.h"
6
7 #ifdef __GNUC__
8 #define INLINE __inline
9 #define PACKED __attribute__((packed))
10
11 #elif defined(__WATCOMC__)
12 #define INLINE __inline
13 #define PACKED
14
15 #else
16 #define INLINE
17 #define PACKED
18 #endif
19
20 #define BSWAP16(x)      ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
21 #define BSWAP32(x)      \
22         ((((x) >> 24) & 0xff) | \
23          (((x) >> 8) & 0xff00) | \
24          (((x) << 8) & 0xff0000) | \
25          ((x) << 24))
26
27 #if defined(__i386__) || defined(__x86_64__) || defined(__386__) || defined(MSDOS)
28 /* fast conversion of double -> 32bit int
29  * for details see:
30  *  - http://chrishecker.com/images/f/fb/Gdmfp.pdf
31  *  - http://stereopsis.com/FPU.html#convert
32  */
33 static INLINE int32_t cround64(double val)
34 {
35         val += 6755399441055744.0;
36         return *(int32_t*)&val;
37 }
38 #else
39 #define cround64(x)     ((int32_t)(x))
40 #endif
41
42 static INLINE float rsqrt(float x)
43 {
44         float xhalf = x * 0.5f;
45         int32_t i = *(int32_t*)&x;
46         i = 0x5f3759df - (i >> 1);
47         x = *(float*)&i;
48         x = x * (1.5f - xhalf * x * x);
49         return x;
50 }
51
52 extern uint32_t perf_start_count, perf_interval_count;
53
54 #ifdef __WATCOMC__
55 void memset16(void *dest, uint16_t val, int count);
56 #pragma aux memset16 = \
57         "cld" \
58         "test ecx, 1" \
59         "jz memset16_dwords" \
60         "rep stosw" \
61         "jmp memset16_done" \
62         "memset16_dwords:" \
63         "shr ecx, 1" \
64         "push ax" \
65         "shl eax, 16" \
66         "pop ax" \
67         "rep stosd" \
68         "memset16_done:" \
69         parm[edi][ax][ecx];
70
71 #ifdef USE_MMX
72 void memcpy64(void *dest, void *src, int count);
73 #pragma aux memcpy64 = \
74         "cploop:" \
75         "movq mm0, [edx]" \
76         "movq [ebx], mm0" \
77         "add edx, 8" \
78         "add ebx, 8" \
79         "dec ecx" \
80         "jnz cploop" \
81         "emms" \
82         parm[ebx][edx][ecx] \
83         modify[8087];
84 #else
85 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
86 #endif
87
88 void perf_start(void);
89 #pragma aux perf_start = \
90         "xor eax, eax" \
91         "cpuid" \
92         "rdtsc" \
93         "mov [perf_start_count], eax" \
94         modify[eax ebx ecx edx];
95
96 void perf_end(void);
97 #pragma aux perf_end = \
98         "xor eax, eax" \
99         "cpuid" \
100         "rdtsc" \
101         "sub eax, [perf_start_count]" \
102         "mov [perf_interval_count], eax" \
103         modify [eax ebx ecx edx];
104
105 void debug_break(void);
106 #pragma aux debug_break = "int 3";
107
108 void halt(void);
109 #pragma aux halt = "hlt";
110 #endif
111
112 #ifdef __GNUC__
113 #if defined(__i386__) || defined(__x86_64__)
114 #define memset16(dest, val, count) asm volatile ( \
115         "cld\n\t" \
116         "test $1, %2\n\t" \
117         "jz 0f\n\t" \
118         "rep stosw\n\t" \
119         "jmp 1f\n\t" \
120         "0:\n\t" \
121         "shr $1, %2\n\t" \
122         "push %%ax\n\t" \
123         "shl $16, %%eax\n\t" \
124         "pop %%ax\n\t" \
125         "rep stosl\n\t" \
126         "1:\n\t"\
127         :: "D"(dest), "a"((uint16_t)(val)), "c"(count) \
128         : "memory")
129 #else
130 static void INLINE memset16(void *dest, uint16_t val, int count)
131 {
132         uint16_t *ptr = dest;
133         while(count--) *ptr++ = val;
134 }
135 #endif
136
137 #ifdef USE_MMX
138 #define memcpy64(dest, src, count) asm volatile ( \
139         "0:\n\t" \
140         "movq (%1), %%mm0\n\t" \
141         "movq %%mm0, (%0)\n\t" \
142         "add $8, %1\n\t" \
143         "add $8, %0\n\t" \
144         "dec %2\n\t" \
145         "jnz 0b\n\t" \
146         "emms\n\t" \
147         :: "r"(dest), "r"(src), "r"(count) \
148         : "%mm0")
149 #else
150 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
151 #endif
152
153 #define perf_start()  asm volatile ( \
154         "xor %%eax, %%eax\n" \
155         "cpuid\n" \
156         "rdtsc\n" \
157         "mov %%eax, %0\n" \
158         : "=m"(perf_start_count) \
159         :: "%eax", "%ebx", "%ecx", "%edx")
160
161 #define perf_end() asm volatile ( \
162         "xor %%eax, %%eax\n" \
163         "cpuid\n" \
164         "rdtsc\n" \
165         "sub %1, %%eax\n" \
166         "mov %%eax, %0\n" \
167         : "=m"(perf_interval_count) \
168         : "m"(perf_start_count) \
169         : "%eax", "%ebx", "%ecx", "%edx")
170
171 #define debug_break() \
172         asm volatile("int $3")
173
174 #define halt() \
175         asm volatile("hlt")
176 #endif
177
178 #ifdef _MSC_VER
179 static void __inline memset16(void *dest, uint16_t val, int count)
180 {
181         __asm {
182                 cld
183                 mov ax, val
184                 mov edi, dest
185                 mov ecx, count
186                 test ecx, 1
187                 jz memset16_dwords
188                 rep stosw
189                 jmp memset16_done
190                 memset16_dwords:
191                 shr ecx, 1
192                 push ax
193                 shl eax, 16
194                 pop ax
195                 rep stosd
196                 memset16_done:
197         }
198 }
199
200 #define perf_start() \
201         do { \
202                 __asm { \
203                         xor eax, eax \
204                         cpuid \
205                         rdtsc \
206                         mov [perf_start_count], eax \
207                 } \
208         } while(0)
209
210 #define perf_end() \
211         do { \
212                 __asm { \
213                         xor eax, eax \
214                         cpuid \
215                         rdtsc \
216                         sub eax, [perf_start_count] \
217                         mov [perf_interval_count], eax \
218                 } \
219         } while(0)
220
221 #define debug_break() \
222         do { \
223                 __asm { int 3 } \
224         } while(0)
225
226 static unsigned int __inline get_cs(void)
227 {
228         unsigned int res;
229         __asm {
230                 xor eax, eax
231                 mov ax, cs
232                 mov [res], ax
233         }
234         return res;
235 }
236 #endif
237
238 unsigned int get_cs(void);
239 #define get_cpl()       ((int)(get_cs() & 3))
240
241 void get_msr(uint32_t msr, uint32_t *low, uint32_t *high);
242 void set_msr(uint32_t msr, uint32_t low, uint32_t high);
243
244
245 /* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
246  * demo_abort on failure. Use the macros, don't call the *_impl functions.
247  */
248 #define malloc_nf(sz)   malloc_nf_impl(sz, __FILE__, __LINE__)
249 void *malloc_nf_impl(size_t sz, const char *file, int line);
250 #define calloc_nf(n, sz)        calloc_nf_impl(n, sz, __FILE__, __LINE__)
251 void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
252 #define realloc_nf(p, sz)       realloc_nf_impl(p, sz, __FILE__, __LINE__)
253 void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
254
255
256
257 #endif  /* UTIL_H_ */