3dgfx code, untested
[metatoy] / src / util.h
1 #ifndef UTIL_H_
2 #define UTIL_H_
3
4 #include <stdlib.h>
5 #include "inttypes.h"
6
7 /* fast conversion of double -> 32bit int
8  * for details see:
9  *  - http://chrishecker.com/images/f/fb/Gdmfp.pdf
10  *  - http://stereopsis.com/FPU.html#convert
11  */
12 static inline int32_t cround64(double val)
13 {
14         val += 6755399441055744.0;
15         return *(int32_t*)&val;
16 }
17
18 static inline float rsqrt(float x)
19 {
20         float xhalf = x * 0.5f;
21         int32_t i = *(int32_t*)&x;
22         i = 0x5f3759df - (i >> 1);
23         x = *(float*)&i;
24         x = x * (1.5f - xhalf * x * x);
25         return x;
26 }
27
28 extern uint32_t perf_start_count, perf_interval_count;
29
30 #define memset16(dest, val, count) \
31         do { \
32                 uint32_t dummy1, dummy2; \
33                 asm volatile ( \
34                         "cld\n\t" \
35                         "test $1, %%ecx\n\t" \
36                         "jz 0f\n\t" \
37                         "rep stosw\n\t" \
38                         "jmp 1f\n\t" \
39                         "0:\n\t" \
40                         "shr $1, %%ecx\n\t" \
41                         "push %%ax\n\t" \
42                         "shl $16, %%eax\n\t" \
43                         "pop %%ax\n\t" \
44                         "rep stosl\n\t" \
45                         "1:\n\t"\
46                         : "=D"(dummy1), "=c"(dummy2) \
47                         : "0"(dest), "a"((uint16_t)(val)), "1"(count) \
48                         : "flags", "memory"); \
49         } while(0)
50
51 #ifdef USE_MMX
52 #define memcpy64(dest, src, count) asm volatile ( \
53         "0:\n\t" \
54         "movq (%1), %%mm0\n\t" \
55         "movq %%mm0, (%0)\n\t" \
56         "add $8, %1\n\t" \
57         "add $8, %0\n\t" \
58         "dec %2\n\t" \
59         "jnz 0b\n\t" \
60         "emms\n\t" \
61         :: "r"(dest), "r"(src), "r"(count) \
62         : "%mm0")
63 #else
64 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
65 #endif
66
67 #ifndef NO_PENTIUM
68 #define perf_start()  asm volatile ( \
69         "xor %%eax, %%eax\n" \
70         "cpuid\n" \
71         "rdtsc\n" \
72         "mov %%eax, %0\n" \
73         : "=m"(perf_start_count) \
74         :: "%eax", "%ebx", "%ecx", "%edx")
75
76 #define perf_end() asm volatile ( \
77         "xor %%eax, %%eax\n" \
78         "cpuid\n" \
79         "rdtsc\n" \
80         "sub %1, %%eax\n" \
81         "mov %%eax, %0\n" \
82         : "=m"(perf_interval_count) \
83         : "m"(perf_start_count) \
84         : "%eax", "%ebx", "%ecx", "%edx")
85 #endif  /* !def NO_PENTIUM */
86
87 #define debug_break() \
88         asm volatile("int $3")
89
90 #define halt() \
91         asm volatile("hlt")
92
93 unsigned int get_cs(void);
94 #define get_cpl()       ((int)(get_cs() & 3))
95
96 void get_msr(uint32_t msr, uint32_t *low, uint32_t *high);
97 void set_msr(uint32_t msr, uint32_t low, uint32_t high);
98
99
100 /* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
101  * demo_abort on failure. Use the macros, don't call the *_impl functions.
102  */
103 #define malloc_nf(sz)   malloc_nf_impl(sz, __FILE__, __LINE__)
104 void *malloc_nf_impl(size_t sz, const char *file, int line);
105 #define calloc_nf(n, sz)        calloc_nf_impl(n, sz, __FILE__, __LINE__)
106 void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
107 #define realloc_nf(p, sz)       realloc_nf_impl(p, sz, __FILE__, __LINE__)
108 void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
109 #define strdup_nf(s)    strdup_nf_impl(s, __FILE__, __LINE__)
110 char *strdup_nf_impl(const char *s, const char *file, int line);
111
112 #endif  /* UTIL_H_ */