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