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/>)
7 Copyright (c) 2006 KJK::Hyperion <hackbunny@reactos.com>
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:
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
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.
28 #ifndef KJK_INTRIN_X86_H_
29 #define KJK_INTRIN_X86_H_
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
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
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
47 NOTE: be very careful with declaring "memory" clobbers. Some "obvious"
48 barriers aren't there in Visual C++ (e.g. __stosX)
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
58 NOTE: on GCC 4.1.0, please use the __sync_* built-ins for barriers and
59 atomic operations. Test the version like this:
61 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
64 Pay attention to the type of barrier. Make it match with what Visual C++
65 would use in the same case
72 /*** memcopy must be memmove ***/
73 __INTRIN_INLINE
void* memcpy(void* dest
, const void* source
, size_t num
)
75 return memmove(dest
, source
, num
);
79 /*** Stack frame juggling ***/
80 #define _ReturnAddress() (__builtin_return_address(0))
81 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))
82 /* TODO: __getcallerseflags but how??? */
84 /* Maybe the same for x86? */
86 #define _alloca(s) __builtin_alloca(s)
89 /*** Memory barriers ***/
91 __INTRIN_INLINE
void _ReadWriteBarrier(void)
93 __asm__
__volatile__("" : : : "memory");
96 /* GCC only supports full barriers */
97 #define _ReadBarrier _ReadWriteBarrier
98 #define _WriteBarrier _ReadWriteBarrier
100 __INTRIN_INLINE
void _mm_mfence(void)
102 __asm__
__volatile__("mfence" : : : "memory");
105 __INTRIN_INLINE
void _mm_lfence(void)
108 __asm__
__volatile__("lfence");
112 __INTRIN_INLINE
void _mm_sfence(void)
115 __asm__
__volatile__("sfence");
120 __INTRIN_INLINE
void __faststorefence(void)
123 __asm__
__volatile__("lock; orl $0, %0;" : : "m"(local
));
128 /*** Atomic operations ***/
130 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
132 __INTRIN_INLINE
char _InterlockedCompareExchange8(volatile char * const Destination
, const char Exchange
, const char Comperand
)
134 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
137 __INTRIN_INLINE
short _InterlockedCompareExchange16(volatile short * const Destination
, const short Exchange
, const short Comperand
)
139 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
142 __INTRIN_INLINE
long _InterlockedCompareExchange(volatile long * const Destination
, const long Exchange
, const long Comperand
)
144 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
147 __INTRIN_INLINE
void * _InterlockedCompareExchangePointer(void * volatile * const Destination
, void * const Exchange
, void * const Comperand
)
149 return (void *)__sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
152 __INTRIN_INLINE
long _InterlockedExchange(volatile long * const Target
, const long Value
)
154 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
155 __sync_synchronize();
156 return __sync_lock_test_and_set(Target
, Value
);
159 #if defined(_M_AMD64)
160 __INTRIN_INLINE
long long _InterlockedExchange64(volatile long long * const Target
, const long long Value
)
162 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
163 __sync_synchronize();
164 return __sync_lock_test_and_set(Target
, Value
);
168 __INTRIN_INLINE
void * _InterlockedExchangePointer(void * volatile * const Target
, void * const Value
)
171 __sync_synchronize();
172 return (void *)__sync_lock_test_and_set(Target
, Value
);
175 __INTRIN_INLINE
long _InterlockedExchangeAdd16(volatile short * const Addend
, const short Value
)
177 return __sync_fetch_and_add(Addend
, Value
);
180 __INTRIN_INLINE
long _InterlockedExchangeAdd(volatile long * const Addend
, const long Value
)
182 return __sync_fetch_and_add(Addend
, Value
);
185 #if defined(_M_AMD64)
186 __INTRIN_INLINE
long long _InterlockedExchangeAdd64(volatile long long * const Addend
, const long long Value
)
188 return __sync_fetch_and_add(Addend
, Value
);
192 __INTRIN_INLINE
char _InterlockedAnd8(volatile char * const value
, const char mask
)
194 return __sync_fetch_and_and(value
, mask
);
197 __INTRIN_INLINE
short _InterlockedAnd16(volatile short * const value
, const short mask
)
199 return __sync_fetch_and_and(value
, mask
);
202 __INTRIN_INLINE
long _InterlockedAnd(volatile long * const value
, const long mask
)
204 return __sync_fetch_and_and(value
, mask
);
207 #if defined(_M_AMD64)
208 __INTRIN_INLINE
long long _InterlockedAnd64(volatile long long * const value
, const long long mask
)
210 return __sync_fetch_and_and(value
, mask
);
214 __INTRIN_INLINE
char _InterlockedOr8(volatile char * const value
, const char mask
)
216 return __sync_fetch_and_or(value
, mask
);
219 __INTRIN_INLINE
short _InterlockedOr16(volatile short * const value
, const short mask
)
221 return __sync_fetch_and_or(value
, mask
);
224 __INTRIN_INLINE
long _InterlockedOr(volatile long * const value
, const long mask
)
226 return __sync_fetch_and_or(value
, mask
);
229 #if defined(_M_AMD64)
230 __INTRIN_INLINE
long long _InterlockedOr64(volatile long long * const value
, const long long mask
)
232 return __sync_fetch_and_or(value
, mask
);
236 __INTRIN_INLINE
char _InterlockedXor8(volatile char * const value
, const char mask
)
238 return __sync_fetch_and_xor(value
, mask
);
241 __INTRIN_INLINE
short _InterlockedXor16(volatile short * const value
, const short mask
)
243 return __sync_fetch_and_xor(value
, mask
);
246 __INTRIN_INLINE
long _InterlockedXor(volatile long * const value
, const long mask
)
248 return __sync_fetch_and_xor(value
, mask
);
251 #if defined(_M_AMD64)
252 __INTRIN_INLINE
long long _InterlockedXor64(volatile long long * const value
, const long long mask
)
254 return __sync_fetch_and_xor(value
, mask
);
258 __INTRIN_INLINE
long _InterlockedDecrement(volatile long * const lpAddend
)
260 return __sync_sub_and_fetch(lpAddend
, 1);
263 __INTRIN_INLINE
long _InterlockedIncrement(volatile long * const lpAddend
)
265 return __sync_add_and_fetch(lpAddend
, 1);
268 __INTRIN_INLINE
short _InterlockedDecrement16(volatile short * const lpAddend
)
270 return __sync_sub_and_fetch(lpAddend
, 1);
273 __INTRIN_INLINE
short _InterlockedIncrement16(volatile short * const lpAddend
)
275 return __sync_add_and_fetch(lpAddend
, 1);
278 #if defined(_M_AMD64)
279 __INTRIN_INLINE
long long _InterlockedDecrement64(volatile long long * const lpAddend
)
281 return __sync_sub_and_fetch(lpAddend
, 1);
284 __INTRIN_INLINE
long long _InterlockedIncrement64(volatile long long * const lpAddend
)
286 return __sync_add_and_fetch(lpAddend
, 1);
292 __INTRIN_INLINE
char _InterlockedCompareExchange8(volatile char * const Destination
, const char Exchange
, const char Comperand
)
294 char retval
= Comperand
;
295 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval
] "+a" (retval
) : [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
) : "memory");
299 __INTRIN_INLINE
short _InterlockedCompareExchange16(volatile short * const Destination
, const short Exchange
, const short Comperand
)
301 short retval
= Comperand
;
302 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval
] "+a" (retval
) : [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
): "memory");
306 __INTRIN_INLINE
long _InterlockedCompareExchange(volatile long * const Destination
, const long Exchange
, const long Comperand
)
308 long retval
= Comperand
;
309 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval
] "+a" (retval
) : [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
): "memory");
313 __INTRIN_INLINE
void * _InterlockedCompareExchangePointer(void * volatile * const Destination
, void * const Exchange
, void * const Comperand
)
315 void * retval
= (void *)Comperand
;
316 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval
] "=a" (retval
) : "[retval]" (retval
), [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
) : "memory");
320 __INTRIN_INLINE
long _InterlockedExchange(volatile long * const Target
, const long Value
)
323 __asm__("xchgl %[retval], %[Target]" : [retval
] "+r" (retval
) : [Target
] "m" (*Target
) : "memory");
327 __INTRIN_INLINE
void * _InterlockedExchangePointer(void * volatile * const Target
, void * const Value
)
329 void * retval
= Value
;
330 __asm__("xchgl %[retval], %[Target]" : [retval
] "+r" (retval
) : [Target
] "m" (*Target
) : "memory");
334 __INTRIN_INLINE
long _InterlockedExchangeAdd16(volatile short * const Addend
, const short Value
)
337 __asm__("lock; xaddw %[retval], %[Addend]" : [retval
] "+r" (retval
) : [Addend
] "m" (*Addend
) : "memory");
341 __INTRIN_INLINE
long _InterlockedExchangeAdd(volatile long * const Addend
, const long Value
)
344 __asm__("lock; xaddl %[retval], %[Addend]" : [retval
] "+r" (retval
) : [Addend
] "m" (*Addend
) : "memory");
348 __INTRIN_INLINE
char _InterlockedAnd8(volatile char * const value
, const char mask
)
358 y
= _InterlockedCompareExchange8(value
, x
& mask
, x
);
365 __INTRIN_INLINE
short _InterlockedAnd16(volatile short * const value
, const short mask
)
375 y
= _InterlockedCompareExchange16(value
, x
& mask
, x
);
382 __INTRIN_INLINE
long _InterlockedAnd(volatile long * const value
, const long mask
)
392 y
= _InterlockedCompareExchange(value
, x
& mask
, x
);
399 __INTRIN_INLINE
char _InterlockedOr8(volatile char * const value
, const char mask
)
409 y
= _InterlockedCompareExchange8(value
, x
| mask
, x
);
416 __INTRIN_INLINE
short _InterlockedOr16(volatile short * const value
, const short mask
)
426 y
= _InterlockedCompareExchange16(value
, x
| mask
, x
);
433 __INTRIN_INLINE
long _InterlockedOr(volatile long * const value
, const long mask
)
443 y
= _InterlockedCompareExchange(value
, x
| mask
, x
);
450 __INTRIN_INLINE
char _InterlockedXor8(volatile char * const value
, const char mask
)
460 y
= _InterlockedCompareExchange8(value
, x
^ mask
, x
);
467 __INTRIN_INLINE
short _InterlockedXor16(volatile short * const value
, const short mask
)
477 y
= _InterlockedCompareExchange16(value
, x
^ mask
, x
);
484 __INTRIN_INLINE
long _InterlockedXor(volatile long * const value
, const long mask
)
494 y
= _InterlockedCompareExchange(value
, x
^ mask
, x
);
501 __INTRIN_INLINE
long _InterlockedDecrement(volatile long * const lpAddend
)
503 return _InterlockedExchangeAdd(lpAddend
, -1) - 1;
506 __INTRIN_INLINE
long _InterlockedIncrement(volatile long * const lpAddend
)
508 return _InterlockedExchangeAdd(lpAddend
, 1) + 1;
511 __INTRIN_INLINE
short _InterlockedDecrement16(volatile short * const lpAddend
)
513 return _InterlockedExchangeAdd16(lpAddend
, -1) - 1;
516 __INTRIN_INLINE
short _InterlockedIncrement16(volatile short * const lpAddend
)
518 return _InterlockedExchangeAdd16(lpAddend
, 1) + 1;
521 #if defined(_M_AMD64)
522 __INTRIN_INLINE
long long _InterlockedDecrement64(volatile long long * const lpAddend
)
524 return _InterlockedExchangeAdd64(lpAddend
, -1) - 1;
527 __INTRIN_INLINE
long long _InterlockedIncrement64(volatile long long * const lpAddend
)
529 return _InterlockedExchangeAdd64(lpAddend
, 1) + 1;
535 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__)
537 __INTRIN_INLINE
long long _InterlockedCompareExchange64(volatile long long * const Destination
, const long long Exchange
, const long long Comperand
)
539 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
544 __INTRIN_INLINE
long long _InterlockedCompareExchange64(volatile long long * const Destination
, const long long Exchange
, const long long Comperand
)
546 long long retval
= Comperand
;
550 "lock; cmpxchg8b %[Destination]" :
551 [retval
] "+A" (retval
) :
552 [Destination
] "m" (*Destination
),
553 "b" ((unsigned long)((Exchange
>> 0) & 0xFFFFFFFF)),
554 "c" ((unsigned long)((Exchange
>> 32) & 0xFFFFFFFF)) :
563 __INTRIN_INLINE
long _InterlockedAddLargeStatistic(volatile long long * const Addend
, const long Value
)
567 "lock; add %[Value], %[Lo32];"
569 "lock; adc $0, %[Hi32];"
571 [Lo32
] "+m" (*((volatile long *)(Addend
) + 0)), [Hi32
] "+m" (*((volatile long *)(Addend
) + 1)) :
572 [Value
] "ir" (Value
) :
579 __INTRIN_INLINE
unsigned char _interlockedbittestandreset(volatile long * a
, const long b
)
581 unsigned char retval
;
582 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
586 #if defined(_M_AMD64)
587 __INTRIN_INLINE
unsigned char _interlockedbittestandreset64(volatile long long * a
, const long long b
)
589 unsigned char retval
;
590 __asm__("lock; btrq %[b], %[a]; setb %b[retval]" : [retval
] "=r" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
595 __INTRIN_INLINE
unsigned char _interlockedbittestandset(volatile long * a
, const long b
)
597 unsigned char retval
;
598 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval
] "=q" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
602 #if defined(_M_AMD64)
603 __INTRIN_INLINE
unsigned char _interlockedbittestandset64(volatile long long * a
, const long long b
)
605 unsigned char retval
;
606 __asm__("lock; btsq %[b], %[a]; setc %b[retval]" : [retval
] "=r" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
611 /*** String operations ***/
612 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
613 __INTRIN_INLINE
void __stosb(unsigned char * Dest
, const unsigned char Data
, size_t Count
)
618 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
619 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
623 __INTRIN_INLINE
void __stosw(unsigned short * Dest
, const unsigned short Data
, size_t Count
)
628 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
629 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
633 __INTRIN_INLINE
void __stosd(unsigned long * Dest
, const unsigned long Data
, size_t Count
)
638 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
639 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
644 __INTRIN_INLINE
void __stosq(unsigned __int64
* Dest
, const unsigned __int64 Data
, size_t Count
)
649 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
650 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
655 __INTRIN_INLINE
void __movsb(unsigned char * Destination
, const unsigned char * Source
, size_t Count
)
660 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
661 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
665 __INTRIN_INLINE
void __movsw(unsigned short * Destination
, const unsigned short * Source
, size_t Count
)
670 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
671 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
675 __INTRIN_INLINE
void __movsd(unsigned long * Destination
, const unsigned long * Source
, size_t Count
)
680 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
681 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
686 __INTRIN_INLINE
void __movsq(unsigned long * Destination
, const unsigned long * Source
, size_t Count
)
691 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
692 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
697 #if defined(_M_AMD64)
698 /*** GS segment addressing ***/
700 __INTRIN_INLINE
void __writegsbyte(const unsigned long Offset
, const unsigned char Data
)
702 __asm__
__volatile__("movb %b[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
705 __INTRIN_INLINE
void __writegsword(const unsigned long Offset
, const unsigned short Data
)
707 __asm__
__volatile__("movw %w[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
710 __INTRIN_INLINE
void __writegsdword(const unsigned long Offset
, const unsigned long Data
)
712 __asm__
__volatile__("movl %k[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
715 __INTRIN_INLINE
void __writegsqword(const unsigned long Offset
, const unsigned __int64 Data
)
717 __asm__
__volatile__("movq %q[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
720 __INTRIN_INLINE
unsigned char __readgsbyte(const unsigned long Offset
)
723 __asm__
__volatile__("movb %%gs:%a[Offset], %b[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
727 __INTRIN_INLINE
unsigned short __readgsword(const unsigned long Offset
)
729 unsigned short value
;
730 __asm__
__volatile__("movw %%gs:%a[Offset], %w[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
734 __INTRIN_INLINE
unsigned long __readgsdword(const unsigned long Offset
)
737 __asm__
__volatile__("movl %%gs:%a[Offset], %k[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
741 __INTRIN_INLINE
unsigned __int64
__readgsqword(const unsigned long Offset
)
743 unsigned __int64 value
;
744 __asm__
__volatile__("movq %%gs:%a[Offset], %q[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
748 __INTRIN_INLINE
void __incgsbyte(const unsigned long Offset
)
750 __asm__
__volatile__("incb %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
753 __INTRIN_INLINE
void __incgsword(const unsigned long Offset
)
755 __asm__
__volatile__("incw %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
758 __INTRIN_INLINE
void __incgsdword(const unsigned long Offset
)
760 __asm__
__volatile__("incl %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
763 __INTRIN_INLINE
void __addgsbyte(const unsigned long Offset
, const unsigned char Data
)
765 __asm__
__volatile__("addb %b[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
768 __INTRIN_INLINE
void __addgsword(const unsigned long Offset
, const unsigned short Data
)
770 __asm__
__volatile__("addw %w[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
773 __INTRIN_INLINE
void __addgsdword(const unsigned long Offset
, const unsigned int Data
)
775 __asm__
__volatile__("addl %k[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
778 __INTRIN_INLINE
void __addgsqword(const unsigned long Offset
, const unsigned __int64 Data
)
780 __asm__
__volatile__("addq %k[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
784 /*** FS segment addressing ***/
785 __INTRIN_INLINE
void __writefsbyte(const unsigned long Offset
, const unsigned char Data
)
787 __asm__
__volatile__("movb %b[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
790 __INTRIN_INLINE
void __writefsword(const unsigned long Offset
, const unsigned short Data
)
792 __asm__
__volatile__("movw %w[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
795 __INTRIN_INLINE
void __writefsdword(const unsigned long Offset
, const unsigned long Data
)
797 __asm__
__volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
800 __INTRIN_INLINE
unsigned char __readfsbyte(const unsigned long Offset
)
803 __asm__
__volatile__("movb %%fs:%a[Offset], %b[value]" : [value
] "=q" (value
) : [Offset
] "ir" (Offset
));
807 __INTRIN_INLINE
unsigned short __readfsword(const unsigned long Offset
)
809 unsigned short value
;
810 __asm__
__volatile__("movw %%fs:%a[Offset], %w[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
814 __INTRIN_INLINE
unsigned long __readfsdword(const unsigned long Offset
)
817 __asm__
__volatile__("movl %%fs:%a[Offset], %k[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
821 __INTRIN_INLINE
void __incfsbyte(const unsigned long Offset
)
823 __asm__
__volatile__("incb %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
826 __INTRIN_INLINE
void __incfsword(const unsigned long Offset
)
828 __asm__
__volatile__("incw %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
831 __INTRIN_INLINE
void __incfsdword(const unsigned long Offset
)
833 __asm__
__volatile__("incl %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
836 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
837 __INTRIN_INLINE
void __addfsbyte(const unsigned long Offset
, const unsigned char Data
)
839 if(!__builtin_constant_p(Offset
))
840 __asm__
__volatile__("addb %b[Offset], %%fs:%a[Offset]" : : [Offset
] "r" (Offset
) : "memory");
842 __asm__
__volatile__("addb %b[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
845 __INTRIN_INLINE
void __addfsword(const unsigned long Offset
, const unsigned short Data
)
847 if(!__builtin_constant_p(Offset
))
848 __asm__
__volatile__("addw %w[Offset], %%fs:%a[Offset]" : : [Offset
] "r" (Offset
) : "memory");
850 __asm__
__volatile__("addw %w[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
853 __INTRIN_INLINE
void __addfsdword(const unsigned long Offset
, const unsigned int Data
)
855 if(!__builtin_constant_p(Offset
))
856 __asm__
__volatile__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset
] "r" (Offset
) : "memory");
858 __asm__
__volatile__("addl %k[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
863 /*** Bit manipulation ***/
864 __INTRIN_INLINE
unsigned char _BitScanForward(unsigned long * const Index
, const unsigned long Mask
)
866 __asm__("bsfl %[Mask], %[Index]" : [Index
] "=r" (*Index
) : [Mask
] "mr" (Mask
));
870 __INTRIN_INLINE
unsigned char _BitScanReverse(unsigned long * const Index
, const unsigned long Mask
)
872 __asm__("bsrl %[Mask], %[Index]" : [Index
] "=r" (*Index
) : [Mask
] "mr" (Mask
));
876 /* NOTE: again, the bizarre implementation follows Visual C++ */
877 __INTRIN_INLINE
unsigned char _bittest(const long * const a
, const long b
)
879 unsigned char retval
;
881 if(__builtin_constant_p(b
))
882 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*(a
+ (b
/ 32))), [b
] "Ir" (b
% 32));
884 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*a
), [b
] "r" (b
));
890 __INTRIN_INLINE
unsigned char _bittest64(const __int64
* const a
, const __int64 b
)
892 unsigned char retval
;
894 if(__builtin_constant_p(b
))
895 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*(a
+ (b
/ 64))), [b
] "Ir" (b
% 64));
897 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*a
), [b
] "r" (b
));
903 __INTRIN_INLINE
unsigned char _bittestandcomplement(long * const a
, const long b
)
905 unsigned char retval
;
907 if(__builtin_constant_p(b
))
908 __asm__("btc %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*(a
+ (b
/ 32))), [retval
] "=q" (retval
) : [b
] "Ir" (b
% 32));
910 __asm__("btc %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*a
), [retval
] "=q" (retval
) : [b
] "r" (b
));
915 __INTRIN_INLINE
unsigned char _bittestandreset(long * const a
, const long b
)
917 unsigned char retval
;
919 if(__builtin_constant_p(b
))
920 __asm__("btr %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*(a
+ (b
/ 32))), [retval
] "=q" (retval
) : [b
] "Ir" (b
% 32));
922 __asm__("btr %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*a
), [retval
] "=q" (retval
) : [b
] "r" (b
));
927 __INTRIN_INLINE
unsigned char _bittestandset(long * const a
, const long b
)
929 unsigned char retval
;
931 if(__builtin_constant_p(b
))
932 __asm__("bts %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*(a
+ (b
/ 32))), [retval
] "=q" (retval
) : [b
] "Ir" (b
% 32));
934 __asm__("bts %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*a
), [retval
] "=q" (retval
) : [b
] "r" (b
));
939 __INTRIN_INLINE
unsigned char _rotl8(unsigned char value
, unsigned char shift
)
941 unsigned char retval
;
942 __asm__("rolb %b[shift], %b[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
946 __INTRIN_INLINE
unsigned short _rotl16(unsigned short value
, unsigned char shift
)
948 unsigned short retval
;
949 __asm__("rolw %b[shift], %w[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
953 __INTRIN_INLINE
unsigned int _rotl(unsigned int value
, int shift
)
955 unsigned long retval
;
956 __asm__("roll %b[shift], %k[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
960 __INTRIN_INLINE
unsigned int _rotr(unsigned int value
, int shift
)
962 unsigned long retval
;
963 __asm__("rorl %b[shift], %k[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
967 __INTRIN_INLINE
unsigned char _rotr8(unsigned char value
, unsigned char shift
)
969 unsigned char retval
;
970 __asm__("rorb %b[shift], %b[retval]" : [retval
] "=qm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
974 __INTRIN_INLINE
unsigned short _rotr16(unsigned short value
, unsigned char shift
)
976 unsigned short retval
;
977 __asm__("rorw %b[shift], %w[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
982 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
983 constraint (edx:eax) for the Mask argument, because it's the only way GCC
984 can pass 64-bit operands around - passing the two 32 bit parts separately
985 just confuses it. Also we declare Bit as an int and then truncate it to
986 match Visual C++ behavior
988 __INTRIN_INLINE
unsigned long long __ll_lshift(const unsigned long long Mask
, const int Bit
)
990 unsigned long long retval
= Mask
;
994 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
996 [Bit
] "Nc" ((unsigned char)((unsigned long)Bit
) & 0xFF)
1002 __INTRIN_INLINE
long long __ll_rshift(const long long Mask
, const int Bit
)
1004 unsigned long long retval
= Mask
;
1008 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
1010 [Bit
] "Nc" ((unsigned char)((unsigned long)Bit
) & 0xFF)
1016 __INTRIN_INLINE
unsigned long long __ull_rshift(const unsigned long long Mask
, int Bit
)
1018 unsigned long long retval
= Mask
;
1022 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
1024 [Bit
] "Nc" ((unsigned char)((unsigned long)Bit
) & 0xFF)
1030 __INTRIN_INLINE
unsigned short _byteswap_ushort(unsigned short value
)
1032 unsigned short retval
;
1033 __asm__("rorw $8, %w[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
));
1037 __INTRIN_INLINE
unsigned long _byteswap_ulong(unsigned long value
)
1039 unsigned long retval
;
1040 __asm__("bswapl %[retval]" : [retval
] "=r" (retval
) : "[retval]" (value
));
1045 __INTRIN_INLINE
unsigned __int64
_byteswap_uint64(unsigned __int64 value
)
1047 unsigned __int64 retval
;
1048 __asm__("bswapq %[retval]" : [retval
] "=r" (retval
) : "[retval]" (value
));
1052 __INTRIN_INLINE
unsigned __int64
_byteswap_uint64(unsigned __int64 value
)
1057 unsigned long lowpart
;
1058 unsigned long hipart
;
1061 retval
.int64part
= value
;
1062 __asm__("bswapl %[lowpart]\n"
1063 "bswapl %[hipart]\n"
1064 : [lowpart
] "=r" (retval
.hipart
), [hipart
] "=r" (retval
.lowpart
) : "[lowpart]" (retval
.lowpart
), "[hipart]" (retval
.hipart
) );
1065 return retval
.int64part
;
1069 /*** 64-bit math ***/
1070 __INTRIN_INLINE
long long __emul(const int a
, const int b
)
1073 __asm__("imull %[b]" : "=A" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1077 __INTRIN_INLINE
unsigned long long __emulu(const unsigned int a
, const unsigned int b
)
1079 unsigned long long retval
;
1080 __asm__("mull %[b]" : "=A" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1086 __INTRIN_INLINE __int64
__mulh(__int64 a
, __int64 b
)
1089 __asm__("imulq %[b]" : "=d" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1093 __INTRIN_INLINE
unsigned __int64
__umulh(unsigned __int64 a
, unsigned __int64 b
)
1095 unsigned __int64 retval
;
1096 __asm__("mulq %[b]" : "=d" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1103 __INTRIN_INLINE
unsigned char __inbyte(const unsigned short Port
)
1106 __asm__
__volatile__("inb %w[Port], %b[byte]" : [byte
] "=a" (byte
) : [Port
] "Nd" (Port
));
1110 __INTRIN_INLINE
unsigned short __inword(const unsigned short Port
)
1112 unsigned short word
;
1113 __asm__
__volatile__("inw %w[Port], %w[word]" : [word
] "=a" (word
) : [Port
] "Nd" (Port
));
1117 __INTRIN_INLINE
unsigned long __indword(const unsigned short Port
)
1119 unsigned long dword
;
1120 __asm__
__volatile__("inl %w[Port], %k[dword]" : [dword
] "=a" (dword
) : [Port
] "Nd" (Port
));
1124 __INTRIN_INLINE
void __inbytestring(unsigned short Port
, unsigned char * Buffer
, unsigned long Count
)
1126 __asm__ __volatile__
1129 [Buffer
] "=D" (Buffer
), [Count
] "=c" (Count
) :
1130 "d" (Port
), "[Buffer]" (Buffer
), "[Count]" (Count
) :
1135 __INTRIN_INLINE
void __inwordstring(unsigned short Port
, unsigned short * Buffer
, unsigned long Count
)
1137 __asm__ __volatile__
1140 [Buffer
] "=D" (Buffer
), [Count
] "=c" (Count
) :
1141 "d" (Port
), "[Buffer]" (Buffer
), "[Count]" (Count
) :
1146 __INTRIN_INLINE
void __indwordstring(unsigned short Port
, unsigned long * Buffer
, unsigned long Count
)
1148 __asm__ __volatile__
1151 [Buffer
] "=D" (Buffer
), [Count
] "=c" (Count
) :
1152 "d" (Port
), "[Buffer]" (Buffer
), "[Count]" (Count
) :
1157 __INTRIN_INLINE
void __outbyte(unsigned short const Port
, const unsigned char Data
)
1159 __asm__
__volatile__("outb %b[Data], %w[Port]" : : [Port
] "Nd" (Port
), [Data
] "a" (Data
));
1162 __INTRIN_INLINE
void __outword(unsigned short const Port
, const unsigned short Data
)
1164 __asm__
__volatile__("outw %w[Data], %w[Port]" : : [Port
] "Nd" (Port
), [Data
] "a" (Data
));
1167 __INTRIN_INLINE
void __outdword(unsigned short const Port
, const unsigned long Data
)
1169 __asm__
__volatile__("outl %k[Data], %w[Port]" : : [Port
] "Nd" (Port
), [Data
] "a" (Data
));
1172 __INTRIN_INLINE
void __outbytestring(unsigned short const Port
, const unsigned char * const Buffer
, const unsigned long Count
)
1174 __asm__
__volatile__("rep; outsb" : : [Port
] "d" (Port
), [Buffer
] "S" (Buffer
), "c" (Count
));
1177 __INTRIN_INLINE
void __outwordstring(unsigned short const Port
, const unsigned short * const Buffer
, const unsigned long Count
)
1179 __asm__
__volatile__("rep; outsw" : : [Port
] "d" (Port
), [Buffer
] "S" (Buffer
), "c" (Count
));
1182 __INTRIN_INLINE
void __outdwordstring(unsigned short const Port
, const unsigned long * const Buffer
, const unsigned long Count
)
1184 __asm__
__volatile__("rep; outsl" : : [Port
] "d" (Port
), [Buffer
] "S" (Buffer
), "c" (Count
));
1187 __INTRIN_INLINE
int _inp(unsigned short Port
)
1189 return __inbyte(Port
);
1192 __INTRIN_INLINE
unsigned short _inpw(unsigned short Port
)
1194 return __inword(Port
);
1197 __INTRIN_INLINE
unsigned long _inpd(unsigned short Port
)
1199 return __indword(Port
);
1202 __INTRIN_INLINE
int _outp(unsigned short Port
, int databyte
)
1204 __outbyte(Port
, databyte
);
1208 __INTRIN_INLINE
unsigned short _outpw(unsigned short Port
, unsigned short dataword
)
1210 __outword(Port
, dataword
);
1214 __INTRIN_INLINE
unsigned long _outpd(unsigned short Port
, unsigned long dataword
)
1216 __outdword(Port
, dataword
);
1221 /*** System information ***/
1222 __INTRIN_INLINE
void __cpuid(int CPUInfo
[], const int InfoType
)
1224 __asm__
__volatile__("cpuid" : "=a" (CPUInfo
[0]), "=b" (CPUInfo
[1]), "=c" (CPUInfo
[2]), "=d" (CPUInfo
[3]) : "a" (InfoType
));
1227 __INTRIN_INLINE
unsigned long long __rdtsc(void)
1230 unsigned long long low
, high
;
1231 __asm__
__volatile__("rdtsc" : "=a"(low
), "=d"(high
));
1232 return low
| (high
<< 32);
1234 unsigned long long retval
;
1235 __asm__
__volatile__("rdtsc" : "=A"(retval
));
1240 __INTRIN_INLINE
void __writeeflags(uintptr_t Value
)
1242 __asm__
__volatile__("push %0\n popf" : : "rim"(Value
));
1245 __INTRIN_INLINE
uintptr_t __readeflags(void)
1248 __asm__
__volatile__("pushf\n pop %0" : "=rm"(retval
));
1252 /*** Interrupts ***/
1254 #define __debugbreak() __asm__("int $3")
1256 __INTRIN_INLINE
void __debugbreak(void)
1262 __INTRIN_INLINE
void __int2c(void)
1264 __asm__("int $0x2c");
1267 __INTRIN_INLINE
void _disable(void)
1269 __asm__("cli" : : : "memory");
1272 __INTRIN_INLINE
void _enable(void)
1274 __asm__("sti" : : : "memory");
1277 __INTRIN_INLINE
void __halt(void)
1279 __asm__("hlt\n\t" : : : "memory");
1282 /*** Protected memory management ***/
1285 __INTRIN_INLINE
void __writecr0(const unsigned __int64 Data
)
1287 __asm__("mov %[Data], %%cr0" : : [Data
] "r" (Data
) : "memory");
1290 __INTRIN_INLINE
void __writecr3(const unsigned __int64 Data
)
1292 __asm__("mov %[Data], %%cr3" : : [Data
] "r" (Data
) : "memory");
1295 __INTRIN_INLINE
void __writecr4(const unsigned __int64 Data
)
1297 __asm__("mov %[Data], %%cr4" : : [Data
] "r" (Data
) : "memory");
1300 __INTRIN_INLINE
void __writecr8(const unsigned __int64 Data
)
1302 __asm__("mov %[Data], %%cr8" : : [Data
] "r" (Data
) : "memory");
1305 __INTRIN_INLINE
unsigned __int64
__readcr0(void)
1307 unsigned __int64 value
;
1308 __asm__
__volatile__("mov %%cr0, %[value]" : [value
] "=r" (value
));
1312 __INTRIN_INLINE
unsigned __int64
__readcr2(void)
1314 unsigned __int64 value
;
1315 __asm__
__volatile__("mov %%cr2, %[value]" : [value
] "=r" (value
));
1319 __INTRIN_INLINE
unsigned __int64
__readcr3(void)
1321 unsigned __int64 value
;
1322 __asm__
__volatile__("mov %%cr3, %[value]" : [value
] "=r" (value
));
1326 __INTRIN_INLINE
unsigned __int64
__readcr4(void)
1328 unsigned __int64 value
;
1329 __asm__
__volatile__("mov %%cr4, %[value]" : [value
] "=r" (value
));
1333 __INTRIN_INLINE
unsigned __int64
__readcr8(void)
1335 unsigned __int64 value
;
1336 __asm__
__volatile__("movq %%cr8, %q[value]" : [value
] "=r" (value
));
1340 __INTRIN_INLINE
void __writecr0(const unsigned int Data
)
1342 __asm__("mov %[Data], %%cr0" : : [Data
] "r" (Data
) : "memory");
1345 __INTRIN_INLINE
void __writecr3(const unsigned int Data
)
1347 __asm__("mov %[Data], %%cr3" : : [Data
] "r" (Data
) : "memory");
1350 __INTRIN_INLINE
void __writecr4(const unsigned int Data
)
1352 __asm__("mov %[Data], %%cr4" : : [Data
] "r" (Data
) : "memory");
1355 __INTRIN_INLINE
unsigned long __readcr0(void)
1357 unsigned long value
;
1358 __asm__
__volatile__("mov %%cr0, %[value]" : [value
] "=r" (value
));
1362 __INTRIN_INLINE
unsigned long __readcr2(void)
1364 unsigned long value
;
1365 __asm__
__volatile__("mov %%cr2, %[value]" : [value
] "=r" (value
));
1369 __INTRIN_INLINE
unsigned long __readcr3(void)
1371 unsigned long value
;
1372 __asm__
__volatile__("mov %%cr3, %[value]" : [value
] "=r" (value
));
1376 __INTRIN_INLINE
unsigned long __readcr4(void)
1378 unsigned long value
;
1379 __asm__
__volatile__("mov %%cr4, %[value]" : [value
] "=r" (value
));
1385 __INTRIN_INLINE
unsigned __int64
__readdr(unsigned int reg
)
1387 unsigned __int64 value
;
1391 __asm__
__volatile__("movq %%dr0, %q[value]" : [value
] "=r" (value
));
1394 __asm__
__volatile__("movq %%dr1, %q[value]" : [value
] "=r" (value
));
1397 __asm__
__volatile__("movq %%dr2, %q[value]" : [value
] "=r" (value
));
1400 __asm__
__volatile__("movq %%dr3, %q[value]" : [value
] "=r" (value
));
1403 __asm__
__volatile__("movq %%dr4, %q[value]" : [value
] "=r" (value
));
1406 __asm__
__volatile__("movq %%dr5, %q[value]" : [value
] "=r" (value
));
1409 __asm__
__volatile__("movq %%dr6, %q[value]" : [value
] "=r" (value
));
1412 __asm__
__volatile__("movq %%dr7, %q[value]" : [value
] "=r" (value
));
1418 __INTRIN_INLINE
void __writedr(unsigned reg
, unsigned __int64 value
)
1423 __asm__("movq %q[value], %%dr0" : : [value
] "r" (value
) : "memory");
1426 __asm__("movq %q[value], %%dr1" : : [value
] "r" (value
) : "memory");
1429 __asm__("movq %q[value], %%dr2" : : [value
] "r" (value
) : "memory");
1432 __asm__("movq %q[value], %%dr3" : : [value
] "r" (value
) : "memory");
1435 __asm__("movq %q[value], %%dr4" : : [value
] "r" (value
) : "memory");
1438 __asm__("movq %q[value], %%dr5" : : [value
] "r" (value
) : "memory");
1441 __asm__("movq %q[value], %%dr6" : : [value
] "r" (value
) : "memory");
1444 __asm__("movq %q[value], %%dr7" : : [value
] "r" (value
) : "memory");
1449 __INTRIN_INLINE
unsigned int __readdr(unsigned int reg
)
1455 __asm__
__volatile__("mov %%dr0, %[value]" : [value
] "=r" (value
));
1458 __asm__
__volatile__("mov %%dr1, %[value]" : [value
] "=r" (value
));
1461 __asm__
__volatile__("mov %%dr2, %[value]" : [value
] "=r" (value
));
1464 __asm__
__volatile__("mov %%dr3, %[value]" : [value
] "=r" (value
));
1467 __asm__
__volatile__("mov %%dr4, %[value]" : [value
] "=r" (value
));
1470 __asm__
__volatile__("mov %%dr5, %[value]" : [value
] "=r" (value
));
1473 __asm__
__volatile__("mov %%dr6, %[value]" : [value
] "=r" (value
));
1476 __asm__
__volatile__("mov %%dr7, %[value]" : [value
] "=r" (value
));
1482 __INTRIN_INLINE
void __writedr(unsigned reg
, unsigned int value
)
1487 __asm__("mov %[value], %%dr0" : : [value
] "r" (value
) : "memory");
1490 __asm__("mov %[value], %%dr1" : : [value
] "r" (value
) : "memory");
1493 __asm__("mov %[value], %%dr2" : : [value
] "r" (value
) : "memory");
1496 __asm__("mov %[value], %%dr3" : : [value
] "r" (value
) : "memory");
1499 __asm__("mov %[value], %%dr4" : : [value
] "r" (value
) : "memory");
1502 __asm__("mov %[value], %%dr5" : : [value
] "r" (value
) : "memory");
1505 __asm__("mov %[value], %%dr6" : : [value
] "r" (value
) : "memory");
1508 __asm__("mov %[value], %%dr7" : : [value
] "r" (value
) : "memory");
1514 __INTRIN_INLINE
void __invlpg(void * const Address
)
1516 __asm__("invlpg %[Address]" : : [Address
] "m" (*((unsigned char *)(Address
))) : "memory");
1520 /*** System operations ***/
1521 __INTRIN_INLINE
unsigned long long __readmsr(const int reg
)
1524 unsigned long low
, high
;
1525 __asm__
__volatile__("rdmsr" : "=a" (low
), "=d" (high
) : "c" (reg
));
1526 return ((unsigned long long)high
<< 32) | low
;
1528 unsigned long long retval
;
1529 __asm__
__volatile__("rdmsr" : "=A" (retval
) : "c" (reg
));
1534 __INTRIN_INLINE
void __writemsr(const unsigned long Register
, const unsigned long long Value
)
1537 __asm__
__volatile__("wrmsr" : : "a" (Value
), "d" (Value
>> 32), "c" (Register
));
1539 __asm__
__volatile__("wrmsr" : : "A" (Value
), "c" (Register
));
1543 __INTRIN_INLINE
unsigned long long __readpmc(const int counter
)
1545 unsigned long long retval
;
1546 __asm__
__volatile__("rdpmc" : "=A" (retval
) : "c" (counter
));
1550 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
1551 __INTRIN_INLINE
unsigned long __segmentlimit(const unsigned long a
)
1553 unsigned long retval
;
1554 __asm__
__volatile__("lsl %[a], %[retval]" : [retval
] "=r" (retval
) : [a
] "rm" (a
));
1558 __INTRIN_INLINE
void __wbinvd(void)
1560 __asm__
__volatile__("wbinvd" : : : "memory");
1563 __INTRIN_INLINE
void __lidt(void *Source
)
1565 __asm__
__volatile__("lidt %0" : : "m"(*(short*)Source
));
1568 __INTRIN_INLINE
void __sidt(void *Destination
)
1570 __asm__
__volatile__("sidt %0" : : "m"(*(short*)Destination
) : "memory");
1573 /*** Misc operations ***/
1575 __INTRIN_INLINE
void _mm_pause(void)
1577 __asm__
__volatile__("pause" : : : "memory");
1580 __INTRIN_INLINE
void __nop(void)
1582 __asm__
__volatile__("nop");
1589 #endif /* KJK_INTRIN_X86_H_ */