cross compile on UNIX with open watcom, and cleanup watdpmi
[dos_imgv] / src / util.h
1 #ifndef UTIL_H_
2 #define UTIL_H_
3
4
5 #ifdef NO_STDINT_H
6
7 #if __WATCOMC__ >= 1200
8 #include <sys/types.h>
9 #else
10 typedef char int8_t;
11 typedef unsigned char uint8_t;
12 typedef short int16_t;
13 typedef unsigned short uint16_t;
14 typedef int int32_t;
15 typedef unsigned int uint32_t;
16 typedef unsigned long uintptr_t;
17 #endif
18
19 #else
20 #include <stdint.h>
21 #endif
22
23 #ifdef __GNUC__
24 #define INLINE __inline
25 #define PACKED __attribute__((packed))
26
27 #elif defined(__WATCOMC__)
28 #define INLINE __inline
29 #define PACKED
30
31 #else
32 #define INLINE
33 #define PACKED
34 #endif
35
36 #define BSWAP16(x)      ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
37 #define BSWAP32(x)      \
38         ((((x) >> 24) & 0xff) | \
39          (((x) >> 8) & 0xff00) | \
40          (((x) << 8) & 0xff0000) | \
41          ((x) << 24))
42
43
44 extern short sinlut[];
45
46 #define SIN(x) (int)sinlut[(x) & 0x7ff]
47 #define COS(x) (int)sinlut[((x) + 512) & 0x7ff]
48
49 int mask_to_shift(unsigned int mask);
50
51 #if defined(__i386__) || defined(__x86_64__) || defined(__386__) || defined(MSDOS)
52 /* fast conversion of double -> 32bit int
53  * for details see:
54  *  - http://chrishecker.com/images/f/fb/Gdmfp.pdf
55  *  - http://stereopsis.com/FPU.html#convert
56  */
57 static INLINE int32_t cround64(double val)
58 {
59         val += 6755399441055744.0;
60         return *(int32_t*)&val;
61 }
62 #else
63 #define cround64(x)     ((int32_t)(x))
64 #endif
65
66 static INLINE float rsqrt(float x)
67 {
68         float xhalf = x * 0.5f;
69         int32_t i = *(int32_t*)&x;
70         i = 0x5f3759df - (i >> 1);
71         x = *(float*)&i;
72         x = x * (1.5f - xhalf * x * x);
73         return x;
74 }
75
76 extern uint32_t perf_start_count, perf_interval_count;
77
78 #ifdef __WATCOMC__
79 void memset16(void *dest, uint16_t val, int count);
80 #pragma aux memset16 = \
81         "cld" \
82         "test ecx, 1" \
83         "jz memset16_dwords" \
84         "rep stosw" \
85         "jmp memset16_done" \
86         "memset16_dwords:" \
87         "shr ecx, 1" \
88         "push ax" \
89         "shl eax, 16" \
90         "pop ax" \
91         "rep stosd" \
92         "memset16_done:" \
93         parm[edi][ax][ecx];
94
95 #ifdef USE_MMX
96 void memcpy64(void *dest, void *src, int count);
97 #pragma aux memcpy64 = \
98         "cploop:" \
99         "movq mm0, [edx]" \
100         "movq [ebx], mm0" \
101         "add edx, 8" \
102         "add ebx, 8" \
103         "dec ecx" \
104         "jnz cploop" \
105         "emms" \
106         parm[ebx][edx][ecx] \
107         modify[8087];
108 #else
109 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
110 #endif
111
112 void perf_start(void);
113 #pragma aux perf_start = \
114         "xor eax, eax" \
115         "cpuid" \
116         "rdtsc" \
117         "mov [perf_start_count], eax" \
118         modify[eax ebx ecx edx];
119
120 void perf_end(void);
121 #pragma aux perf_end = \
122         "xor eax, eax" \
123         "cpuid" \
124         "rdtsc" \
125         "sub eax, [perf_start_count]" \
126         "mov [perf_interval_count], eax" \
127         modify [eax ebx ecx edx];
128
129 void debug_break(void);
130 #pragma aux debug_break = "int 3";
131 #endif
132
133 #ifdef __GNUC__
134 #if defined(__i386__) || defined(__x86_64__)
135 #define memset16(dest, val, count) asm volatile ( \
136         "cld\n\t" \
137         "test $1, %2\n\t" \
138         "jz 0f\n\t" \
139         "rep stosw\n\t" \
140         "jmp 1f\n\t" \
141         "0:\n\t" \
142         "shr $1, %2\n\t" \
143         "push %%ax\n\t" \
144         "shl $16, %%eax\n\t" \
145         "pop %%ax\n\t" \
146         "rep stosl\n\t" \
147         "1:\n\t"\
148         :: "D"(dest), "a"((uint16_t)(val)), "c"(count) \
149         : "memory")
150 #else
151 static void INLINE memset16(void *dest, uint16_t val, int count)
152 {
153         uint16_t *ptr = dest;
154         while(count--) *ptr++ = val;
155 }
156 #endif
157
158 #ifdef USE_MMX
159 #define memcpy64(dest, src, count) asm volatile ( \
160         "0:\n\t" \
161         "movq (%1), %%mm0\n\t" \
162         "movq %%mm0, (%0)\n\t" \
163         "add $8, %1\n\t" \
164         "add $8, %0\n\t" \
165         "dec %2\n\t" \
166         "jnz 0b\n\t" \
167         "emms\n\t" \
168         :: "r"(dest), "r"(src), "r"(count) \
169         : "%mm0")
170 #else
171 #define memcpy64(dest, src, count)      memcpy(dest, src, (count) << 3)
172 #endif
173
174 #define perf_start()  asm volatile ( \
175         "xor %%eax, %%eax\n" \
176         "cpuid\n" \
177         "rdtsc\n" \
178         "mov %%eax, %0\n" \
179         : "=m"(perf_start_count) \
180         :: "%eax", "%ebx", "%ecx", "%edx")
181
182 #define perf_end() asm volatile ( \
183         "xor %%eax, %%eax\n" \
184         "cpuid\n" \
185         "rdtsc\n" \
186         "sub %1, %%eax\n" \
187         "mov %%eax, %0\n" \
188         : "=m"(perf_interval_count) \
189         : "m"(perf_start_count) \
190         : "%eax", "%ebx", "%ecx", "%edx")
191
192 #define debug_break() \
193         asm volatile ("int $3")
194 #endif
195
196 #ifdef _MSC_VER
197 void __inline memset16(void *dest, uint16_t val, int count)
198 {
199         __asm {
200                 cld
201                 mov ax, val
202                 mov edi, dest
203                 mov ecx, count
204                 test ecx, 1
205                 jz memset16_dwords
206                 rep stosw
207                 jmp memset16_done
208                 memset16_dwords:
209                 shr ecx, 1
210                 push ax
211                 shl eax, 16
212                 pop ax
213                 rep stosd
214                 memset16_done:
215         }
216 }
217
218 #define perf_start() \
219         do { \
220                 __asm { \
221                         xor eax, eax \
222                         cpuid \
223                         rdtsc \
224                         mov [perf_start_count], eax \
225                 } \
226         } while(0)
227
228 #define perf_end() \
229         do { \
230                 __asm { \
231                         xor eax, eax \
232                         cpuid \
233                         rdtsc \
234                         sub eax, [perf_start_count] \
235                         mov [perf_interval_count], eax \
236                 } \
237         } while(0)
238
239 #define debug_break() \
240         do { \
241                 __asm { int 3 } \
242         } while(0)
243 #endif
244
245 struct cpuid_info {
246         uint32_t maxidx;        /* 0: eax */
247         char vendor[12];        /* 0: ebx, edx, ecx */
248         uint32_t id;            /* 1: eax */
249         uint32_t rsvd0;         /* 1: ebx */
250         uint32_t feat;          /* 1: edx */
251         uint32_t feat2;         /* 1: ecx */
252 };
253
254 #define CPUID_STEPPING(id)      ((id) & 0xf)
255 #define CPUID_MODEL(id)         (((id) >> 4) & 0xf)
256 #define CPUID_FAMILY(id)        (((id) >> 8) & 0xf)
257
258 #define CPUID_FEAT_FPU                  0x00000001
259 #define CPUID_FEAT_VME                  0x00000002
260 #define CPUID_FEAT_DBGEXT               0x00000004
261 #define CPUID_FEAT_PSE                  0x00000008
262 #define CPUID_FEAT_TSC                  0x00000010
263 #define CPUID_FEAT_MSR                  0x00000020
264 #define CPUID_FEAT_PAE                  0x00000040
265 #define CPUID_FEAT_MCE                  0x00000080
266 #define CPUID_FEAT_CX8                  0x00000100
267 #define CPUID_FEAT_APIC                 0x00000200
268 #define CPUID_FEAT_SEP                  0x00000800
269 #define CPUID_FEAT_MTRR                 0x00001000
270 #define CPUID_FEAT_PGE                  0x00002000
271 #define CPUID_FEAT_MCA                  0x00004000
272 #define CPUID_FEAT_CMOV                 0x00008000
273 #define CPUID_FEAT_PAT                  0x00010000
274 #define CPUID_FEAT_PSE36                0x00020000
275 #define CPUID_FEAT_PSN                  0x00040000
276 #define CPUID_FEAT_CLF                  0x00080000
277 #define CPUID_FEAT_DTES                 0x00200000
278 #define CPUID_FEAT_ACPI                 0x00400000
279 #define CPUID_FEAT_MMX                  0x00800000
280 #define CPUID_FEAT_FXSR                 0x01000000
281 #define CPUID_FEAT_SSE                  0x02000000
282 #define CPUID_FEAT_SSE2                 0x04000000
283 #define CPUID_FEAT_SS                   0x08000000
284 #define CPUID_FEAT_HTT                  0x10000000
285 #define CPUID_FEAT_TM1                  0x20000000
286 #define CPUID_FEAT_IA64                 0x40000000
287 #define CPUID_FEAT_PBE                  0x80000000
288
289 #define CPUID_FEAT2_SSE3                0x00000001
290 #define CPUID_FEAT2_PCLMUL              0x00000002
291 #define CPUID_FEAT2_DTES64              0x00000004
292 #define CPUID_FEAT2_MONITOR             0x00000008
293 #define CPUID_FEAT2_DS_CPL              0x00000010
294 #define CPUID_FEAT2_VMX                 0x00000020
295 #define CPUID_FEAT2_SMX                 0x00000040
296 #define CPUID_FEAT2_EST                 0x00000080
297 #define CPUID_FEAT2_TM2                 0x00000100
298 #define CPUID_FEAT2_SSSE3               0x00000200
299 #define CPUID_FEAT2_CID                 0x00000400
300 #define CPUID_FEAT2_FMA                 0x00001000
301 #define CPUID_FEAT2_CX16                0x00002000
302 #define CPUID_FEAT2_ETPRD               0x00004000
303 #define CPUID_FEAT2_PDCM                0x00008000
304 #define CPUID_FEAT2_PCIDE               0x00020000
305 #define CPUID_FEAT2_DCA                 0x00040000
306 #define CPUID_FEAT2_SSE41               0x00080000
307 #define CPUID_FEAT2_SSE42               0x00100000
308 #define CPUID_FEAT2_X2APIC              0x00200000
309 #define CPUID_FEAT2_MOVBE               0x00400000
310 #define CPUID_FEAT2_POPCNT              0x00800000
311 #define CPUID_FEAT2_AES                 0x02000000
312 #define CPUID_FEAT2_XSAVE               0x04000000
313 #define CPUID_FEAT2_OSXSAVE             0x08000000
314 #define CPUID_FEAT2_AVX                 0x10000000
315
316 int read_cpuid(struct cpuid_info *info);
317
318 #endif  /* UTIL_H_ */