rename to molten metal
[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 /*
52 #define memset32(dest, val, count) \
53         asm volatile ( \
54                 "cld\n\t" \
55                 "rep stosl\n\t" \
56                 :: "a"(val), "c"(count), "D"(dest) \
57                 : "flags", "memory")
58 */
59 #define memset32(dest, val, count) \
60         do { \
61                 int i; \
62                 uint32_t *ptr = (uint32_t*)dest; \
63                 for(i=0; i<count; i++) { \
64                         ptr[i] = val; \
65                 } \
66         } while(0)
67
68
69 #ifdef USE_MMX
70 #define memcpy64(dest, src, count) asm volatile ( \
71         "0:\n\t" \
72         "movq (%1), %%mm0\n\t" \
73         "movq %%mm0, (%0)\n\t" \
74         "add $8, %1\n\t" \
75         "add $8, %0\n\t" \
76         "dec %2\n\t" \
77         "jnz 0b\n\t" \
78         "emms\n\t" \
79         :: "r"(dest), "r"(src), "r"(count) \
80         : "%mm0")
81 #else
82 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
83 #endif
84
85 #ifndef NO_PENTIUM
86 #define perf_start()  asm volatile ( \
87         "xor %%eax, %%eax\n" \
88         "cpuid\n" \
89         "rdtsc\n" \
90         "mov %%eax, %0\n" \
91         : "=m"(perf_start_count) \
92         :: "%eax", "%ebx", "%ecx", "%edx")
93
94 #define perf_end() asm volatile ( \
95         "xor %%eax, %%eax\n" \
96         "cpuid\n" \
97         "rdtsc\n" \
98         "sub %1, %%eax\n" \
99         "mov %%eax, %0\n" \
100         : "=m"(perf_interval_count) \
101         : "m"(perf_start_count) \
102         : "%eax", "%ebx", "%ecx", "%edx")
103 #endif  /* !def NO_PENTIUM */
104
105 #define debug_break() \
106         asm volatile("int $3")
107
108 #define halt() \
109         asm volatile("hlt")
110
111 unsigned int get_cs(void);
112 #define get_cpl()       ((int)(get_cs() & 3))
113
114 void get_msr(uint32_t msr, uint32_t *low, uint32_t *high);
115 void set_msr(uint32_t msr, uint32_t low, uint32_t high);
116
117
118 /* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
119  * demo_abort on failure. Use the macros, don't call the *_impl functions.
120  */
121 #define malloc_nf(sz)   malloc_nf_impl(sz, __FILE__, __LINE__)
122 void *malloc_nf_impl(size_t sz, const char *file, int line);
123 #define calloc_nf(n, sz)        calloc_nf_impl(n, sz, __FILE__, __LINE__)
124 void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
125 #define realloc_nf(p, sz)       realloc_nf_impl(p, sz, __FILE__, __LINE__)
126 void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
127 #define strdup_nf(s)    strdup_nf_impl(s, __FILE__, __LINE__)
128 char *strdup_nf_impl(const char *s, const char *file, int line);
129
130 #endif  /* UTIL_H_ */