added perf_start/perf_end assembly macros
[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
9 #elif defined(__WATCOMC__)
10 #define INLINE __inline
11
12 #else
13 #define INLINE
14 #endif
15
16 /* fast conversion of double -> 32bit int
17  * for details see:
18  *  - http://chrishecker.com/images/f/fb/Gdmfp.pdf
19  *  - http://stereopsis.com/FPU.html#convert
20  */
21 static INLINE int32_t cround64(double val)
22 {
23         val += 6755399441055744.0;
24         return *(int32_t*)&val;
25 }
26
27 uint32_t perf_start_count, perf_interval_count;
28
29 #ifdef __WATCOMC__
30 void perf_start(void);
31 #pragma aux perf_start = \
32         "rdtsc" \
33         "mov [perf_start_count], eax" \
34         modify[eax edx];
35
36 void perf_end(void);
37 #pragma aux perf_end = \
38         "rdtsc" \
39         "sub eax, [perf_start_count]" \
40         "mov [perf_interval_count], eax" \
41         modify [eax edx];
42 #endif
43
44 #ifdef __GNUC__
45 #define perf_start()  asm volatile ( \
46         "rdtsc\n" \
47         "mov %%eax, %0\n" \
48         : "=m"(perf_start_count) :: "%eax", "%edx")
49
50 #define perf_end() asm volatile ( \
51         "rdtsc\n" \
52         "sub %1, %%eax\n" \
53         "mov %%eax, %0\n" \
54         : "=m"(perf_interval_count) \
55         : "m"(perf_start_count) \
56         : "%eax", "%edx")
57 #endif
58
59 #ifdef _MSC_VER
60 #define perf_start() \
61         do { \
62                 __asm { \
63                         rdtsc \
64                         mov [perf_start_count], eax \
65                 } \
66         } while(0)
67
68 #define perf_end() \
69         do { \
70                 __asm { \
71                         rdtsc \
72                         sub eax, [perf_start_count] \
73                         mov [perf_interval_count], eax \
74                 } \
75         } while(0)
76 #endif
77
78 #endif  /* UTIL_H_ */