removed clang-format and clang_complete files from the repo
[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) \
115         do { \
116                 uint32_t dummy1, dummy2; \
117                 asm volatile ( \
118                         "cld\n\t" \
119                         "test $1, %%ecx\n\t" \
120                         "jz 0f\n\t" \
121                         "rep stosw\n\t" \
122                         "jmp 1f\n\t" \
123                         "0:\n\t" \
124                         "shr $1, %%ecx\n\t" \
125                         "push %%ax\n\t" \
126                         "shl $16, %%eax\n\t" \
127                         "pop %%ax\n\t" \
128                         "rep stosl\n\t" \
129                         "1:\n\t"\
130                         : "=D"(dummy1), "=c"(dummy2) \
131                         : "0"(dest), "a"((uint16_t)(val)), "1"(count) \
132                         : "flags", "memory"); \
133         } while(0)
134 #else
135 static void INLINE memset16(void *dest, uint16_t val, int count)
136 {
137         uint16_t *ptr = dest;
138         while(count--) *ptr++ = val;
139 }
140 #endif
141
142 #ifdef USE_MMX
143 #define memcpy64(dest, src, count) asm volatile ( \
144         "0:\n\t" \
145         "movq (%1), %%mm0\n\t" \
146         "movq %%mm0, (%0)\n\t" \
147         "add $8, %1\n\t" \
148         "add $8, %0\n\t" \
149         "dec %2\n\t" \
150         "jnz 0b\n\t" \
151         "emms\n\t" \
152         :: "r"(dest), "r"(src), "r"(count) \
153         : "%mm0")
154 #else
155 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
156 #endif
157
158 #define perf_start()  asm volatile ( \
159         "xor %%eax, %%eax\n" \
160         "cpuid\n" \
161         "rdtsc\n" \
162         "mov %%eax, %0\n" \
163         : "=m"(perf_start_count) \
164         :: "%eax", "%ebx", "%ecx", "%edx")
165
166 #define perf_end() asm volatile ( \
167         "xor %%eax, %%eax\n" \
168         "cpuid\n" \
169         "rdtsc\n" \
170         "sub %1, %%eax\n" \
171         "mov %%eax, %0\n" \
172         : "=m"(perf_interval_count) \
173         : "m"(perf_start_count) \
174         : "%eax", "%ebx", "%ecx", "%edx")
175
176 #define debug_break() \
177         asm volatile("int $3")
178
179 #define halt() \
180         asm volatile("hlt")
181 #endif
182
183 #ifdef _MSC_VER
184 static void __inline memset16(void *dest, uint16_t val, int count)
185 {
186         __asm {
187                 cld
188                 mov ax, val
189                 mov edi, dest
190                 mov ecx, count
191                 test ecx, 1
192                 jz memset16_dwords
193                 rep stosw
194                 jmp memset16_done
195                 memset16_dwords:
196                 shr ecx, 1
197                 push ax
198                 shl eax, 16
199                 pop ax
200                 rep stosd
201                 memset16_done:
202         }
203 }
204
205 #define perf_start() \
206         do { \
207                 __asm { \
208                         xor eax, eax \
209                         cpuid \
210                         rdtsc \
211                         mov [perf_start_count], eax \
212                 } \
213         } while(0)
214
215 #define perf_end() \
216         do { \
217                 __asm { \
218                         xor eax, eax \
219                         cpuid \
220                         rdtsc \
221                         sub eax, [perf_start_count] \
222                         mov [perf_interval_count], eax \
223                 } \
224         } while(0)
225
226 #define debug_break() \
227         do { \
228                 __asm { int 3 } \
229         } while(0)
230
231 static unsigned int __inline get_cs(void)
232 {
233         unsigned int res;
234         __asm {
235                 xor eax, eax
236                 mov ax, cs
237                 mov [res], ax
238         }
239         return res;
240 }
241 #endif
242
243 unsigned int get_cs(void);
244 #define get_cpl()       ((int)(get_cs() & 3))
245
246 void get_msr(uint32_t msr, uint32_t *low, uint32_t *high);
247 void set_msr(uint32_t msr, uint32_t low, uint32_t high);
248
249
250 /* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
251  * demo_abort on failure. Use the macros, don't call the *_impl functions.
252  */
253 #define malloc_nf(sz)   malloc_nf_impl(sz, __FILE__, __LINE__)
254 void *malloc_nf_impl(size_t sz, const char *file, int line);
255 #define calloc_nf(n, sz)        calloc_nf_impl(n, sz, __FILE__, __LINE__)
256 void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
257 #define realloc_nf(p, sz)       realloc_nf_impl(p, sz, __FILE__, __LINE__)
258 void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
259
260
261
262 #endif  /* UTIL_H_ */