Sync with trunk r43000
[reactos.git] / reactos / include / crt / mingw32 / intrin_x86.h
1 /*
2 Compatibility <intrin_x86.h> header for GCC -- GCC equivalents of intrinsic
3 Microsoft Visual C++ functions. Originally developed for the ReactOS
4 (<http://www.reactos.org/>) and TinyKrnl (<http://www.tinykrnl.org/>)
5 projects.
6
7 Copyright (c) 2006 KJK::Hyperion <hackbunny@reactos.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 */
27
28 #ifndef KJK_INTRIN_X86_H_
29 #define KJK_INTRIN_X86_H_
30
31 /*
32 FIXME: review all "memory" clobbers, add/remove to match Visual C++
33 behavior: some "obvious" memory barriers are not present in the Visual C++
34 implementation - e.g. __stosX; on the other hand, some memory barriers that
35 *are* present could have been missed
36 */
37
38 /*
39 NOTE: this is a *compatibility* header. Some functions may look wrong at
40 first, but they're only "as wrong" as they would be on Visual C++. Our
41 priority is compatibility
42
43 NOTE: unlike most people who write inline asm for GCC, I didn't pull the
44 constraints and the uses of __volatile__ out of my... hat. Do not touch
45 them. I hate cargo cult programming
46
47 NOTE: be very careful with declaring "memory" clobbers. Some "obvious"
48 barriers aren't there in Visual C++ (e.g. __stosX)
49
50 NOTE: review all intrinsics with a return value, add/remove __volatile__
51 where necessary. If an intrinsic whose value is ignored generates a no-op
52 under Visual C++, __volatile__ must be omitted; if it always generates code
53 (for example, if it has side effects), __volatile__ must be specified. GCC
54 will only optimize out non-volatile asm blocks with outputs, so input-only
55 blocks are safe. Oddities such as the non-volatile 'rdmsr' are intentional
56 and follow Visual C++ behavior
57
58 NOTE: on GCC 4.1.0, please use the __sync_* built-ins for barriers and
59 atomic operations. Test the version like this:
60
61 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
62 ...
63
64 Pay attention to the type of barrier. Make it match with what Visual C++
65 would use in the same case
66 */
67
68 #ifdef __cplusplus
69 extern "C" {
70 #endif
71
72 /*** Stack frame juggling ***/
73 #define _ReturnAddress() (__builtin_return_address(0))
74 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))
75 /* TODO: __getcallerseflags but how??? */
76
77 /* Maybe the same for x86? */
78 #ifdef _x86_64
79 #define _alloca(s) __builtin_alloca(s)
80 #endif
81
82 /*** Atomic operations ***/
83
84 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
85 #define _ReadWriteBarrier() __sync_synchronize()
86 #else
87 __INTRIN_INLINE void _MemoryBarrier(void)
88 {
89 __asm__ __volatile__("" : : : "memory");
90 }
91 #define _ReadWriteBarrier() _MemoryBarrier()
92 #endif
93
94 /* BUGBUG: GCC only supports full barriers */
95 #define _ReadBarrier _ReadWriteBarrier
96 #define _WriteBarrier _ReadWriteBarrier
97
98 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
99
100 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * Destination, const char Exchange, const char Comperand)
101 {
102 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
103 }
104
105 __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * Destination, const short Exchange, const short Comperand)
106 {
107 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
108 }
109
110 __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * Destination, const long Exchange, const long Comperand)
111 {
112 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
113 }
114
115 __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * Destination, void * const Exchange, void * const Comperand)
116 {
117 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
118 }
119
120 __INTRIN_INLINE long _InterlockedExchange(volatile long * Target, const long Value)
121 {
122 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
123 __sync_synchronize();
124 return __sync_lock_test_and_set(Target, Value);
125 }
126
127 #if defined(_M_AMD64)
128 __INTRIN_INLINE long long _InterlockedExchange64(volatile long long * Target, const long long Value)
129 {
130 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
131 __sync_synchronize();
132 return __sync_lock_test_and_set(Target, Value);
133 }
134 #endif
135
136 __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * Target, void * const Value)
137 {
138 /* NOTE: ditto */
139 __sync_synchronize();
140 return __sync_lock_test_and_set(Target, Value);
141 }
142
143 __INTRIN_INLINE long _InterlockedExchangeAdd16(volatile short * Addend, const short Value)
144 {
145 return __sync_fetch_and_add(Addend, Value);
146 }
147
148 __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * Addend, const long Value)
149 {
150 return __sync_fetch_and_add(Addend, Value);
151 }
152
153 #if defined(_M_AMD64)
154 __INTRIN_INLINE long long _InterlockedExchangeAdd64(volatile long long * Addend, const long long Value)
155 {
156 return __sync_fetch_and_add(Addend, Value);
157 }
158 #endif
159
160 __INTRIN_INLINE char _InterlockedAnd8(volatile char * value, const char mask)
161 {
162 return __sync_fetch_and_and(value, mask);
163 }
164
165 __INTRIN_INLINE short _InterlockedAnd16(volatile short * value, const short mask)
166 {
167 return __sync_fetch_and_and(value, mask);
168 }
169
170 __INTRIN_INLINE long _InterlockedAnd(volatile long * value, const long mask)
171 {
172 return __sync_fetch_and_and(value, mask);
173 }
174
175 #if defined(_M_AMD64)
176 __INTRIN_INLINE long _InterlockedAnd64(volatile long long * value, const long long mask)
177 {
178 return __sync_fetch_and_and(value, mask);
179 }
180 #endif
181
182 __INTRIN_INLINE char _InterlockedOr8(volatile char * value, const char mask)
183 {
184 return __sync_fetch_and_or(value, mask);
185 }
186
187 __INTRIN_INLINE short _InterlockedOr16(volatile short * value, const short mask)
188 {
189 return __sync_fetch_and_or(value, mask);
190 }
191
192 __INTRIN_INLINE long _InterlockedOr(volatile long * value, const long mask)
193 {
194 return __sync_fetch_and_or(value, mask);
195 }
196
197 #if defined(_M_AMD64)
198 __INTRIN_INLINE long _InterlockedOr64(volatile long long * value, const long long mask)
199 {
200 return __sync_fetch_and_or(value, mask);
201 }
202 #endif
203
204 __INTRIN_INLINE char _InterlockedXor8(volatile char * value, const char mask)
205 {
206 return __sync_fetch_and_xor(value, mask);
207 }
208
209 __INTRIN_INLINE short _InterlockedXor16(volatile short * value, const short mask)
210 {
211 return __sync_fetch_and_xor(value, mask);
212 }
213
214 __INTRIN_INLINE long _InterlockedXor(volatile long * value, const long mask)
215 {
216 return __sync_fetch_and_xor(value, mask);
217 }
218
219 #else
220
221 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * Destination, const char Exchange, const char Comperand)
222 {
223 char retval = Comperand;
224 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
225 return retval;
226 }
227
228 __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * Destination, const short Exchange, const short Comperand)
229 {
230 short retval = Comperand;
231 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
232 return retval;
233 }
234
235 __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * Destination, const long Exchange, const long Comperand)
236 {
237 long retval = Comperand;
238 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
239 return retval;
240 }
241
242 __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * Destination, void * const Exchange, void * const Comperand)
243 {
244 void * retval = (void *)Comperand;
245 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
246 return retval;
247 }
248
249 __INTRIN_INLINE long _InterlockedExchange(volatile long * Target, const long Value)
250 {
251 long retval = Value;
252 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
253 return retval;
254 }
255
256 __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * Target, void * const Value)
257 {
258 void * retval = Value;
259 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
260 return retval;
261 }
262
263 __INTRIN_INLINE long _InterlockedExchangeAdd16(volatile short * Addend, const short Value)
264 {
265 long retval = Value;
266 __asm__("lock; xaddw %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
267 return retval;
268 }
269
270 __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * Addend, const long Value)
271 {
272 long retval = Value;
273 __asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
274 return retval;
275 }
276
277 __INTRIN_INLINE char _InterlockedAnd8(volatile char * value, const char mask)
278 {
279 char x;
280 char y;
281
282 y = *value;
283
284 do
285 {
286 x = y;
287 y = _InterlockedCompareExchange8(value, x & mask, x);
288 }
289 while(y != x);
290
291 return y;
292 }
293
294 __INTRIN_INLINE short _InterlockedAnd16(volatile short * value, const short mask)
295 {
296 short x;
297 short y;
298
299 y = *value;
300
301 do
302 {
303 x = y;
304 y = _InterlockedCompareExchange16(value, x & mask, x);
305 }
306 while(y != x);
307
308 return y;
309 }
310
311 __INTRIN_INLINE long _InterlockedAnd(volatile long * value, const long mask)
312 {
313 long x;
314 long y;
315
316 y = *value;
317
318 do
319 {
320 x = y;
321 y = _InterlockedCompareExchange(value, x & mask, x);
322 }
323 while(y != x);
324
325 return y;
326 }
327
328 __INTRIN_INLINE char _InterlockedOr8(volatile char * value, const char mask)
329 {
330 char x;
331 char y;
332
333 y = *value;
334
335 do
336 {
337 x = y;
338 y = _InterlockedCompareExchange8(value, x | mask, x);
339 }
340 while(y != x);
341
342 return y;
343 }
344
345 __INTRIN_INLINE short _InterlockedOr16(volatile short * value, const short mask)
346 {
347 short x;
348 short y;
349
350 y = *value;
351
352 do
353 {
354 x = y;
355 y = _InterlockedCompareExchange16(value, x | mask, x);
356 }
357 while(y != x);
358
359 return y;
360 }
361
362 __INTRIN_INLINE long _InterlockedOr(volatile long * value, const long mask)
363 {
364 long x;
365 long y;
366
367 y = *value;
368
369 do
370 {
371 x = y;
372 y = _InterlockedCompareExchange(value, x | mask, x);
373 }
374 while(y != x);
375
376 return y;
377 }
378
379 __INTRIN_INLINE char _InterlockedXor8(volatile char * value, const char mask)
380 {
381 char x;
382 char y;
383
384 y = *value;
385
386 do
387 {
388 x = y;
389 y = _InterlockedCompareExchange8(value, x ^ mask, x);
390 }
391 while(y != x);
392
393 return y;
394 }
395
396 __INTRIN_INLINE short _InterlockedXor16(volatile short * value, const short mask)
397 {
398 short x;
399 short y;
400
401 y = *value;
402
403 do
404 {
405 x = y;
406 y = _InterlockedCompareExchange16(value, x ^ mask, x);
407 }
408 while(y != x);
409
410 return y;
411 }
412
413 __INTRIN_INLINE long _InterlockedXor(volatile long * value, const long mask)
414 {
415 long x;
416 long y;
417
418 y = *value;
419
420 do
421 {
422 x = y;
423 y = _InterlockedCompareExchange(value, x ^ mask, x);
424 }
425 while(y != x);
426
427 return y;
428 }
429
430 #endif
431
432 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__)
433
434 __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * Destination, const long long Exchange, const long long Comperand)
435 {
436 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
437 }
438
439 #else
440
441 __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * Destination, const long long Exchange, const long long Comperand)
442 {
443 long long retval = Comperand;
444
445 __asm__
446 (
447 "lock; cmpxchg8b %[Destination]" :
448 [retval] "+A" (retval) :
449 [Destination] "m" (*Destination),
450 "b" ((unsigned long)((Exchange >> 0) & 0xFFFFFFFF)),
451 "c" ((unsigned long)((Exchange >> 32) & 0xFFFFFFFF)) :
452 "memory"
453 );
454
455 return retval;
456 }
457
458 #endif
459
460 __INTRIN_INLINE long _InterlockedAddLargeStatistic(volatile long long * Addend, const long Value)
461 {
462 __asm__
463 (
464 "lock; add %[Value], %[Lo32];"
465 "jae LABEL%=;"
466 "lock; adc $0, %[Hi32];"
467 "LABEL%=:;" :
468 [Lo32] "+m" (*((volatile long *)(Addend) + 0)), [Hi32] "+m" (*((volatile long *)(Addend) + 1)) :
469 [Value] "ir" (Value) :
470 "memory"
471 );
472
473 return Value;
474 }
475
476 __INTRIN_INLINE long _InterlockedDecrement(volatile long * lpAddend)
477 {
478 return _InterlockedExchangeAdd(lpAddend, -1) - 1;
479 }
480
481 __INTRIN_INLINE long _InterlockedIncrement(volatile long * lpAddend)
482 {
483 return _InterlockedExchangeAdd(lpAddend, 1) + 1;
484 }
485
486 __INTRIN_INLINE short _InterlockedDecrement16(volatile short * lpAddend)
487 {
488 return _InterlockedExchangeAdd16(lpAddend, -1) - 1;
489 }
490
491 __INTRIN_INLINE short _InterlockedIncrement16(volatile short * lpAddend)
492 {
493 return _InterlockedExchangeAdd16(lpAddend, 1) + 1;
494 }
495
496 #if defined(_M_AMD64)
497 __INTRIN_INLINE long long _InterlockedDecrement64(volatile long long * lpAddend)
498 {
499 return _InterlockedExchangeAdd64(lpAddend, -1) - 1;
500 }
501
502 __INTRIN_INLINE long long _InterlockedIncrement64(volatile long long * lpAddend)
503 {
504 return _InterlockedExchangeAdd64(lpAddend, 1) + 1;
505 }
506 #endif
507
508 __INTRIN_INLINE unsigned char _interlockedbittestandreset(volatile long * a, const long b)
509 {
510 unsigned char retval;
511 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
512 return retval;
513 }
514
515 #if defined(_M_AMD64)
516 __INTRIN_INLINE unsigned char _interlockedbittestandreset64(volatile long long * a, const long long b)
517 {
518 unsigned char retval;
519 __asm__("lock; btrq %[b], %[a]; setb %b[retval]" : [retval] "=r" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
520 return retval;
521 }
522 #endif
523
524 __INTRIN_INLINE unsigned char _interlockedbittestandset(volatile long * a, const long b)
525 {
526 unsigned char retval;
527 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
528 return retval;
529 }
530
531 #if defined(_M_AMD64)
532 __INTRIN_INLINE unsigned char _interlockedbittestandset64(volatile long long * a, const long long b)
533 {
534 unsigned char retval;
535 __asm__("lock; btsq %[b], %[a]; setc %b[retval]" : [retval] "=r" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
536 return retval;
537 }
538 #endif
539
540 /*** String operations ***/
541 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
542 __INTRIN_INLINE void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)
543 {
544 __asm__ __volatile__
545 (
546 "rep; stosb" :
547 [Dest] "=D" (Dest), [Count] "=c" (Count) :
548 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
549 );
550 }
551
552 __INTRIN_INLINE void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)
553 {
554 __asm__ __volatile__
555 (
556 "rep; stosw" :
557 [Dest] "=D" (Dest), [Count] "=c" (Count) :
558 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
559 );
560 }
561
562 __INTRIN_INLINE void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)
563 {
564 __asm__ __volatile__
565 (
566 "rep; stosl" :
567 [Dest] "=D" (Dest), [Count] "=c" (Count) :
568 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
569 );
570 }
571
572 __INTRIN_INLINE void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)
573 {
574 __asm__ __volatile__
575 (
576 "rep; movsb" :
577 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
578 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
579 );
580 }
581
582 __INTRIN_INLINE void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)
583 {
584 __asm__ __volatile__
585 (
586 "rep; movsw" :
587 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
588 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
589 );
590 }
591
592 __INTRIN_INLINE void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)
593 {
594 __asm__ __volatile__
595 (
596 "rep; movsd" :
597 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
598 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
599 );
600 }
601
602 #if defined(_M_AMD64)
603 /*** GS segment addressing ***/
604
605 __INTRIN_INLINE void __writegsbyte(const unsigned long Offset, const unsigned char Data)
606 {
607 __asm__ __volatile__("movb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
608 }
609
610 __INTRIN_INLINE void __writegsword(const unsigned long Offset, const unsigned short Data)
611 {
612 __asm__ __volatile__("movw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
613 }
614
615 __INTRIN_INLINE void __writegsdword(const unsigned long Offset, const unsigned long Data)
616 {
617 __asm__ __volatile__("movl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
618 }
619
620 __INTRIN_INLINE void __writegsqword(const unsigned long Offset, const unsigned __int64 Data)
621 {
622 __asm__ __volatile__("movq %q[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
623 }
624
625 __INTRIN_INLINE unsigned char __readgsbyte(const unsigned long Offset)
626 {
627 unsigned char value;
628 __asm__ __volatile__("movb %%gs:%a[Offset], %b[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
629 return value;
630 }
631
632 __INTRIN_INLINE unsigned short __readgsword(const unsigned long Offset)
633 {
634 unsigned short value;
635 __asm__ __volatile__("movw %%gs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
636 return value;
637 }
638
639 __INTRIN_INLINE unsigned long __readgsdword(const unsigned long Offset)
640 {
641 unsigned long value;
642 __asm__ __volatile__("movl %%gs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
643 return value;
644 }
645
646 __INTRIN_INLINE unsigned __int64 __readgsqword(const unsigned long Offset)
647 {
648 unsigned __int64 value;
649 __asm__ __volatile__("movq %%gs:%a[Offset], %q[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
650 return value;
651 }
652
653 __INTRIN_INLINE void __incgsbyte(const unsigned long Offset)
654 {
655 __asm__ __volatile__("incb %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
656 }
657
658 __INTRIN_INLINE void __incgsword(const unsigned long Offset)
659 {
660 __asm__ __volatile__("incw %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
661 }
662
663 __INTRIN_INLINE void __incgsdword(const unsigned long Offset)
664 {
665 __asm__ __volatile__("incl %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
666 }
667
668 __INTRIN_INLINE void __addgsbyte(const unsigned long Offset, const unsigned char Data)
669 {
670 __asm__ __volatile__("addb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
671 }
672
673 __INTRIN_INLINE void __addgsword(const unsigned long Offset, const unsigned short Data)
674 {
675 __asm__ __volatile__("addw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
676 }
677
678 __INTRIN_INLINE void __addgsdword(const unsigned long Offset, const unsigned int Data)
679 {
680 __asm__ __volatile__("addl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
681 }
682
683 __INTRIN_INLINE void __addgsqword(const unsigned long Offset, const unsigned __int64 Data)
684 {
685 __asm__ __volatile__("addq %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
686 }
687
688 #else
689 /*** FS segment addressing ***/
690 __INTRIN_INLINE void __writefsbyte(const unsigned long Offset, const unsigned char Data)
691 {
692 __asm__ __volatile__("movb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
693 }
694
695 __INTRIN_INLINE void __writefsword(const unsigned long Offset, const unsigned short Data)
696 {
697 __asm__ __volatile__("movw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
698 }
699
700 __INTRIN_INLINE void __writefsdword(const unsigned long Offset, const unsigned long Data)
701 {
702 __asm__ __volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
703 }
704
705 __INTRIN_INLINE unsigned char __readfsbyte(const unsigned long Offset)
706 {
707 unsigned char value;
708 __asm__ __volatile__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "ir" (Offset));
709 return value;
710 }
711
712 __INTRIN_INLINE unsigned short __readfsword(const unsigned long Offset)
713 {
714 unsigned short value;
715 __asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
716 return value;
717 }
718
719 __INTRIN_INLINE unsigned long __readfsdword(const unsigned long Offset)
720 {
721 unsigned long value;
722 __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
723 return value;
724 }
725
726 __INTRIN_INLINE void __incfsbyte(const unsigned long Offset)
727 {
728 __asm__ __volatile__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
729 }
730
731 __INTRIN_INLINE void __incfsword(const unsigned long Offset)
732 {
733 __asm__ __volatile__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
734 }
735
736 __INTRIN_INLINE void __incfsdword(const unsigned long Offset)
737 {
738 __asm__ __volatile__("incl %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
739 }
740
741 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
742 __INTRIN_INLINE void __addfsbyte(const unsigned long Offset, const unsigned char Data)
743 {
744 if(!__builtin_constant_p(Offset))
745 __asm__ __volatile__("addb %b[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
746 else
747 __asm__ __volatile__("addb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
748 }
749
750 __INTRIN_INLINE void __addfsword(const unsigned long Offset, const unsigned short Data)
751 {
752 if(!__builtin_constant_p(Offset))
753 __asm__ __volatile__("addw %w[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
754 else
755 __asm__ __volatile__("addw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
756 }
757
758 __INTRIN_INLINE void __addfsdword(const unsigned long Offset, const unsigned int Data)
759 {
760 if(!__builtin_constant_p(Offset))
761 __asm__ __volatile__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
762 else
763 __asm__ __volatile__("addl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
764 }
765 #endif
766
767
768 /*** Bit manipulation ***/
769 __INTRIN_INLINE unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)
770 {
771 __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
772 return Mask ? 1 : 0;
773 }
774
775 __INTRIN_INLINE unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)
776 {
777 __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
778 return Mask ? 1 : 0;
779 }
780
781 /* NOTE: again, the bizarre implementation follows Visual C++ */
782 __INTRIN_INLINE unsigned char _bittest(const long * const a, const long b)
783 {
784 unsigned char retval;
785
786 if(__builtin_constant_p(b))
787 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
788 else
789 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
790
791 return retval;
792 }
793
794 __INTRIN_INLINE unsigned char _bittestandcomplement(long * const a, const long b)
795 {
796 unsigned char retval;
797
798 if(__builtin_constant_p(b))
799 __asm__("btc %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32));
800 else
801 __asm__("btc %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b));
802
803 return retval;
804 }
805
806 __INTRIN_INLINE unsigned char _bittestandreset(long * const a, const long b)
807 {
808 unsigned char retval;
809
810 if(__builtin_constant_p(b))
811 __asm__("btr %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32));
812 else
813 __asm__("btr %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b));
814
815 return retval;
816 }
817
818 __INTRIN_INLINE unsigned char _bittestandset(long * const a, const long b)
819 {
820 unsigned char retval;
821
822 if(__builtin_constant_p(b))
823 __asm__("bts %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32));
824 else
825 __asm__("bts %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b));
826
827 return retval;
828 }
829
830 __INTRIN_INLINE unsigned char _rotl8(unsigned char value, unsigned char shift)
831 {
832 unsigned char retval;
833 __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
834 return retval;
835 }
836
837 __INTRIN_INLINE unsigned short _rotl16(unsigned short value, unsigned char shift)
838 {
839 unsigned short retval;
840 __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
841 return retval;
842 }
843
844 __INTRIN_INLINE unsigned int _rotl(unsigned int value, int shift)
845 {
846 unsigned long retval;
847 __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
848 return retval;
849 }
850
851 __INTRIN_INLINE unsigned int _rotr(unsigned int value, int shift)
852 {
853 unsigned long retval;
854 __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
855 return retval;
856 }
857
858 __INTRIN_INLINE unsigned char _rotr8(unsigned char value, unsigned char shift)
859 {
860 unsigned char retval;
861 __asm__("rorb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
862 return retval;
863 }
864
865 __INTRIN_INLINE unsigned short _rotr16(unsigned short value, unsigned char shift)
866 {
867 unsigned short retval;
868 __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
869 return retval;
870 }
871
872 /*
873 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
874 constraint (edx:eax) for the Mask argument, because it's the only way GCC
875 can pass 64-bit operands around - passing the two 32 bit parts separately
876 just confuses it. Also we declare Bit as an int and then truncate it to
877 match Visual C++ behavior
878 */
879 __INTRIN_INLINE unsigned long long __ll_lshift(const unsigned long long Mask, const int Bit)
880 {
881 unsigned long long retval = Mask;
882
883 __asm__
884 (
885 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
886 "+A" (retval) :
887 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
888 );
889
890 return retval;
891 }
892
893 __INTRIN_INLINE long long __ll_rshift(const long long Mask, const int Bit)
894 {
895 unsigned long long retval = Mask;
896
897 __asm__
898 (
899 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
900 "+A" (retval) :
901 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
902 );
903
904 return retval;
905 }
906
907 __INTRIN_INLINE unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)
908 {
909 unsigned long long retval = Mask;
910
911 __asm__
912 (
913 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
914 "+A" (retval) :
915 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
916 );
917
918 return retval;
919 }
920
921 __INTRIN_INLINE unsigned short _byteswap_ushort(unsigned short value)
922 {
923 unsigned short retval;
924 __asm__("rorw $8, %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
925 return retval;
926 }
927
928 __INTRIN_INLINE unsigned long _byteswap_ulong(unsigned long value)
929 {
930 unsigned long retval;
931 __asm__("bswapl %[retval]" : [retval] "=r" (retval) : "[retval]" (value));
932 return retval;
933 }
934
935 #ifdef _M_AMD64
936 __INTRIN_INLINE unsigned __int64 _byteswap_uint64(unsigned __int64 value)
937 {
938 unsigned __int64 retval;
939 __asm__("bswapq %[retval]" : [retval] "=r" (retval) : "[retval]" (value));
940 return retval;
941 }
942 #else
943 __INTRIN_INLINE unsigned __int64 _byteswap_uint64(unsigned __int64 value)
944 {
945 union {
946 __int64 int64part;
947 struct {
948 unsigned long lowpart;
949 unsigned long hipart;
950 };
951 } retval;
952 retval.int64part = value;
953 __asm__("bswapl %[lowpart]\n"
954 "bswapl %[hipart]\n"
955 : [lowpart] "=r" (retval.hipart), [hipart] "=r" (retval.lowpart) : "[lowpart]" (retval.lowpart), "[hipart]" (retval.hipart) );
956 return retval.int64part;
957 }
958 #endif
959
960 /*** 64-bit math ***/
961 __INTRIN_INLINE long long __emul(const int a, const int b)
962 {
963 long long retval;
964 __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
965 return retval;
966 }
967
968 __INTRIN_INLINE unsigned long long __emulu(const unsigned int a, const unsigned int b)
969 {
970 unsigned long long retval;
971 __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
972 return retval;
973 }
974
975 #ifdef _M_AMD64
976
977 static __inline__ __attribute__((always_inline)) __int64 __mulh(__int64 a, __int64 b)
978 {
979 __int64 retval;
980 __asm__("imulq %[b]" : "=d" (retval) : [a] "a" (a), [b] "rm" (b));
981 return retval;
982 }
983
984 static __inline__ __attribute__((always_inline)) unsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b)
985 {
986 unsigned __int64 retval;
987 __asm__("mulq %[b]" : "=d" (retval) : [a] "a" (a), [b] "rm" (b));
988 return retval;
989 }
990
991 #endif
992
993 /*** Port I/O ***/
994 __INTRIN_INLINE unsigned char __inbyte(const unsigned short Port)
995 {
996 unsigned char byte;
997 __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port));
998 return byte;
999 }
1000
1001 __INTRIN_INLINE unsigned short __inword(const unsigned short Port)
1002 {
1003 unsigned short word;
1004 __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port));
1005 return word;
1006 }
1007
1008 __INTRIN_INLINE unsigned long __indword(const unsigned short Port)
1009 {
1010 unsigned long dword;
1011 __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port));
1012 return dword;
1013 }
1014
1015 __INTRIN_INLINE void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)
1016 {
1017 __asm__ __volatile__
1018 (
1019 "rep; insb" :
1020 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1021 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1022 "memory"
1023 );
1024 }
1025
1026 __INTRIN_INLINE void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)
1027 {
1028 __asm__ __volatile__
1029 (
1030 "rep; insw" :
1031 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1032 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1033 "memory"
1034 );
1035 }
1036
1037 __INTRIN_INLINE void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)
1038 {
1039 __asm__ __volatile__
1040 (
1041 "rep; insl" :
1042 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1043 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1044 "memory"
1045 );
1046 }
1047
1048 __INTRIN_INLINE void __outbyte(unsigned short const Port, const unsigned char Data)
1049 {
1050 __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1051 }
1052
1053 __INTRIN_INLINE void __outword(unsigned short const Port, const unsigned short Data)
1054 {
1055 __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1056 }
1057
1058 __INTRIN_INLINE void __outdword(unsigned short const Port, const unsigned long Data)
1059 {
1060 __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1061 }
1062
1063 __INTRIN_INLINE void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)
1064 {
1065 __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1066 }
1067
1068 __INTRIN_INLINE void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)
1069 {
1070 __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1071 }
1072
1073 __INTRIN_INLINE void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)
1074 {
1075 __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1076 }
1077
1078
1079 /*** System information ***/
1080 __INTRIN_INLINE void __cpuid(int CPUInfo[], const int InfoType)
1081 {
1082 __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType));
1083 }
1084
1085 __INTRIN_INLINE unsigned long long __rdtsc(void)
1086 {
1087 #ifdef _M_AMD64
1088 unsigned long long low, high;
1089 __asm__ __volatile__("rdtsc" : "=a"(low), "=d"(high));
1090 return low | (high << 32);
1091 #else
1092 unsigned long long retval;
1093 __asm__ __volatile__("rdtsc" : "=A"(retval));
1094 return retval;
1095 #endif
1096 }
1097
1098 __INTRIN_INLINE void __writeeflags(uintptr_t Value)
1099 {
1100 __asm__ __volatile__("push %0\n popf" : : "rim"(Value));
1101 }
1102
1103 __INTRIN_INLINE uintptr_t __readeflags(void)
1104 {
1105 uintptr_t retval;
1106 __asm__ __volatile__("pushf\n pop %0" : "=rm"(retval));
1107 return retval;
1108 }
1109
1110 /*** Interrupts ***/
1111 __INTRIN_INLINE void __debugbreak(void)
1112 {
1113 __asm__("int $3");
1114 }
1115
1116 __INTRIN_INLINE void __int2c(void)
1117 {
1118 __asm__("int $0x2c");
1119 }
1120
1121 __INTRIN_INLINE void _disable(void)
1122 {
1123 __asm__("cli");
1124 }
1125
1126 __INTRIN_INLINE void _enable(void)
1127 {
1128 __asm__("sti");
1129 }
1130
1131
1132 /*** Protected memory management ***/
1133
1134 __INTRIN_INLINE void __writecr0(const unsigned __int64 Data)
1135 {
1136 __asm__("mov %[Data], %%cr0" : : [Data] "r" (Data) : "memory");
1137 }
1138
1139 __INTRIN_INLINE void __writecr3(const unsigned __int64 Data)
1140 {
1141 __asm__("mov %[Data], %%cr3" : : [Data] "r" (Data) : "memory");
1142 }
1143
1144 __INTRIN_INLINE void __writecr4(const unsigned __int64 Data)
1145 {
1146 __asm__("mov %[Data], %%cr4" : : [Data] "r" (Data) : "memory");
1147 }
1148
1149 #ifdef _M_AMD64
1150 __INTRIN_INLINE void __writecr8(const unsigned __int64 Data)
1151 {
1152 __asm__("mov %[Data], %%cr8" : : [Data] "r" (Data) : "memory");
1153 }
1154
1155 __INTRIN_INLINE unsigned __int64 __readcr0(void)
1156 {
1157 unsigned __int64 value;
1158 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=r" (value));
1159 return value;
1160 }
1161
1162 __INTRIN_INLINE unsigned __int64 __readcr2(void)
1163 {
1164 unsigned __int64 value;
1165 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=r" (value));
1166 return value;
1167 }
1168
1169 __INTRIN_INLINE unsigned __int64 __readcr3(void)
1170 {
1171 unsigned __int64 value;
1172 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=r" (value));
1173 return value;
1174 }
1175
1176 __INTRIN_INLINE unsigned __int64 __readcr4(void)
1177 {
1178 unsigned __int64 value;
1179 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=r" (value));
1180 return value;
1181 }
1182
1183 __INTRIN_INLINE unsigned __int64 __readcr8(void)
1184 {
1185 unsigned __int64 value;
1186 __asm__ __volatile__("movq %%cr8, %q[value]" : [value] "=r" (value));
1187 return value;
1188 }
1189 #else
1190 __INTRIN_INLINE unsigned long __readcr0(void)
1191 {
1192 unsigned long value;
1193 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=r" (value));
1194 return value;
1195 }
1196
1197 __INTRIN_INLINE unsigned long __readcr2(void)
1198 {
1199 unsigned long value;
1200 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=r" (value));
1201 return value;
1202 }
1203
1204 __INTRIN_INLINE unsigned long __readcr3(void)
1205 {
1206 unsigned long value;
1207 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=r" (value));
1208 return value;
1209 }
1210
1211 __INTRIN_INLINE unsigned long __readcr4(void)
1212 {
1213 unsigned long value;
1214 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=r" (value));
1215 return value;
1216 }
1217 #endif
1218
1219 #ifdef _M_AMD64
1220 __INTRIN_INLINE unsigned __int64 __readdr(unsigned int reg)
1221 {
1222 unsigned __int64 value;
1223 switch (reg)
1224 {
1225 case 0:
1226 __asm__ __volatile__("movq %%dr0, %q[value]" : [value] "=r" (value));
1227 break;
1228 case 1:
1229 __asm__ __volatile__("movq %%dr1, %q[value]" : [value] "=r" (value));
1230 break;
1231 case 2:
1232 __asm__ __volatile__("movq %%dr2, %q[value]" : [value] "=r" (value));
1233 break;
1234 case 3:
1235 __asm__ __volatile__("movq %%dr3, %q[value]" : [value] "=r" (value));
1236 break;
1237 case 4:
1238 __asm__ __volatile__("movq %%dr4, %q[value]" : [value] "=r" (value));
1239 break;
1240 case 5:
1241 __asm__ __volatile__("movq %%dr5, %q[value]" : [value] "=r" (value));
1242 break;
1243 case 6:
1244 __asm__ __volatile__("movq %%dr6, %q[value]" : [value] "=r" (value));
1245 break;
1246 case 7:
1247 __asm__ __volatile__("movq %%dr7, %q[value]" : [value] "=r" (value));
1248 break;
1249 }
1250 return value;
1251 }
1252
1253 __INTRIN_INLINE void __writedr(unsigned reg, unsigned __int64 value)
1254 {
1255 switch (reg)
1256 {
1257 case 0:
1258 __asm__("movq %q[value], %%dr0" : : [value] "r" (value) : "memory");
1259 break;
1260 case 1:
1261 __asm__("movq %q[value], %%dr1" : : [value] "r" (value) : "memory");
1262 break;
1263 case 2:
1264 __asm__("movq %q[value], %%dr2" : : [value] "r" (value) : "memory");
1265 break;
1266 case 3:
1267 __asm__("movq %q[value], %%dr3" : : [value] "r" (value) : "memory");
1268 break;
1269 case 4:
1270 __asm__("movq %q[value], %%dr4" : : [value] "r" (value) : "memory");
1271 break;
1272 case 5:
1273 __asm__("movq %q[value], %%dr5" : : [value] "r" (value) : "memory");
1274 break;
1275 case 6:
1276 __asm__("movq %q[value], %%dr6" : : [value] "r" (value) : "memory");
1277 break;
1278 case 7:
1279 __asm__("movq %q[value], %%dr7" : : [value] "r" (value) : "memory");
1280 break;
1281 }
1282 }
1283 #else
1284 __INTRIN_INLINE unsigned int __readdr(unsigned int reg)
1285 {
1286 unsigned int value;
1287 switch (reg)
1288 {
1289 case 0:
1290 __asm__ __volatile__("mov %%dr0, %[value]" : [value] "=r" (value));
1291 break;
1292 case 1:
1293 __asm__ __volatile__("mov %%dr1, %[value]" : [value] "=r" (value));
1294 break;
1295 case 2:
1296 __asm__ __volatile__("mov %%dr2, %[value]" : [value] "=r" (value));
1297 break;
1298 case 3:
1299 __asm__ __volatile__("mov %%dr3, %[value]" : [value] "=r" (value));
1300 break;
1301 case 4:
1302 __asm__ __volatile__("mov %%dr4, %[value]" : [value] "=r" (value));
1303 break;
1304 case 5:
1305 __asm__ __volatile__("mov %%dr5, %[value]" : [value] "=r" (value));
1306 break;
1307 case 6:
1308 __asm__ __volatile__("mov %%dr6, %[value]" : [value] "=r" (value));
1309 break;
1310 case 7:
1311 __asm__ __volatile__("mov %%dr7, %[value]" : [value] "=r" (value));
1312 break;
1313 }
1314 return value;
1315 }
1316
1317 __INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
1318 {
1319 switch (reg)
1320 {
1321 case 0:
1322 __asm__("mov %[value], %%dr0" : : [value] "r" (value) : "memory");
1323 break;
1324 case 1:
1325 __asm__("mov %[value], %%dr1" : : [value] "r" (value) : "memory");
1326 break;
1327 case 2:
1328 __asm__("mov %[value], %%dr2" : : [value] "r" (value) : "memory");
1329 break;
1330 case 3:
1331 __asm__("mov %[value], %%dr3" : : [value] "r" (value) : "memory");
1332 break;
1333 case 4:
1334 __asm__("mov %[value], %%dr4" : : [value] "r" (value) : "memory");
1335 break;
1336 case 5:
1337 __asm__("mov %[value], %%dr5" : : [value] "r" (value) : "memory");
1338 break;
1339 case 6:
1340 __asm__("mov %[value], %%dr6" : : [value] "r" (value) : "memory");
1341 break;
1342 case 7:
1343 __asm__("mov %[value], %%dr7" : : [value] "r" (value) : "memory");
1344 break;
1345 }
1346 }
1347 #endif
1348
1349 __INTRIN_INLINE void __invlpg(void * const Address)
1350 {
1351 __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))));
1352 }
1353
1354
1355 /*** System operations ***/
1356 __INTRIN_INLINE unsigned long long __readmsr(const int reg)
1357 {
1358 #ifdef _M_AMD64
1359 unsigned long low, high;
1360 __asm__ __volatile__("rdmsr" : "=a" (low), "=d" (high) : "c" (reg));
1361 return ((unsigned long long)high << 32) | low;
1362 #else
1363 unsigned long long retval;
1364 __asm__ __volatile__("rdmsr" : "=A" (retval) : "c" (reg));
1365 return retval;
1366 #endif
1367 }
1368
1369 __INTRIN_INLINE void __writemsr(const unsigned long Register, const unsigned long long Value)
1370 {
1371 #ifdef _M_AMD64
1372 __asm__ __volatile__("wrmsr" : : "a" (Value), "d" (Value >> 32), "c" (Register));
1373 #else
1374 __asm__ __volatile__("wrmsr" : : "A" (Value), "c" (Register));
1375 #endif
1376 }
1377
1378 __INTRIN_INLINE unsigned long long __readpmc(const int counter)
1379 {
1380 unsigned long long retval;
1381 __asm__ __volatile__("rdpmc" : "=A" (retval) : "c" (counter));
1382 return retval;
1383 }
1384
1385 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
1386 __INTRIN_INLINE unsigned long __segmentlimit(const unsigned long a)
1387 {
1388 unsigned long retval;
1389 __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a));
1390 return retval;
1391 }
1392
1393 __INTRIN_INLINE void __wbinvd(void)
1394 {
1395 __asm__ __volatile__("wbinvd");
1396 }
1397
1398 __INTRIN_INLINE void __lidt(void *Source)
1399 {
1400 __asm__ __volatile__("lidt %0" : : "m"(*(short*)Source));
1401 }
1402
1403 __INTRIN_INLINE void __sidt(void *Destination)
1404 {
1405 __asm__ __volatile__("sidt %0" : : "m"(*(short*)Destination) : "memory");
1406 }
1407
1408 __INTRIN_INLINE void _mm_pause(void)
1409 {
1410 __asm__ __volatile__("pause");
1411 }
1412
1413 #ifdef __cplusplus
1414 }
1415 #endif
1416
1417 #endif /* KJK_INTRIN_X86_H_ */
1418
1419 /* EOF */