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 /*** Stack frame juggling ***/
73 #define _ReturnAddress() (__builtin_return_address(0))
74 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))
75 /* TODO: __getcallerseflags but how??? */
77 /* Maybe the same for x86? */
79 #define _alloca(s) __builtin_alloca(s)
82 /*** Memory barriers ***/
84 __INTRIN_INLINE
void _ReadWriteBarrier(void)
86 __asm__
__volatile__("" : : : "memory");
89 /* GCC only supports full barriers */
90 #define _ReadBarrier _ReadWriteBarrier
91 #define _WriteBarrier _ReadWriteBarrier
93 __INTRIN_INLINE
void _mm_mfence(void)
95 __asm__
__volatile__("mfence" : : : "memory");
98 __INTRIN_INLINE
void _mm_lfence(void)
101 __asm__
__volatile__("lfence");
105 __INTRIN_INLINE
void _mm_sfence(void)
108 __asm__
__volatile__("sfence");
113 __INTRIN_INLINE
void __faststorefence(void)
116 __asm__
__volatile__("lock; orl $0, %0;" : : "m"(local
));
121 /*** Atomic operations ***/
123 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
125 __INTRIN_INLINE
char _InterlockedCompareExchange8(volatile char * const Destination
, const char Exchange
, const char Comperand
)
127 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
130 __INTRIN_INLINE
short _InterlockedCompareExchange16(volatile short * const Destination
, const short Exchange
, const short Comperand
)
132 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
135 __INTRIN_INLINE
long _InterlockedCompareExchange(volatile long * const Destination
, const long Exchange
, const long Comperand
)
137 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
140 __INTRIN_INLINE
void * _InterlockedCompareExchangePointer(void * volatile * const Destination
, void * const Exchange
, void * const Comperand
)
142 return (void *)__sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
145 __INTRIN_INLINE
long _InterlockedExchange(volatile long * const Target
, const long Value
)
147 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
148 __sync_synchronize();
149 return __sync_lock_test_and_set(Target
, Value
);
152 #if defined(_M_AMD64)
153 __INTRIN_INLINE
long long _InterlockedExchange64(volatile long long * const Target
, const long long Value
)
155 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
156 __sync_synchronize();
157 return __sync_lock_test_and_set(Target
, Value
);
161 __INTRIN_INLINE
void * _InterlockedExchangePointer(void * volatile * const Target
, void * const Value
)
164 __sync_synchronize();
165 return (void *)__sync_lock_test_and_set(Target
, Value
);
168 __INTRIN_INLINE
long _InterlockedExchangeAdd16(volatile short * const Addend
, const short Value
)
170 return __sync_fetch_and_add(Addend
, Value
);
173 __INTRIN_INLINE
long _InterlockedExchangeAdd(volatile long * const Addend
, const long Value
)
175 return __sync_fetch_and_add(Addend
, Value
);
178 #if defined(_M_AMD64)
179 __INTRIN_INLINE
long long _InterlockedExchangeAdd64(volatile long long * const Addend
, const long long Value
)
181 return __sync_fetch_and_add(Addend
, Value
);
185 __INTRIN_INLINE
char _InterlockedAnd8(volatile char * const value
, const char mask
)
187 return __sync_fetch_and_and(value
, mask
);
190 __INTRIN_INLINE
short _InterlockedAnd16(volatile short * const value
, const short mask
)
192 return __sync_fetch_and_and(value
, mask
);
195 __INTRIN_INLINE
long _InterlockedAnd(volatile long * const value
, const long mask
)
197 return __sync_fetch_and_and(value
, mask
);
200 #if defined(_M_AMD64)
201 __INTRIN_INLINE
long long _InterlockedAnd64(volatile long long * const value
, const long long mask
)
203 return __sync_fetch_and_and(value
, mask
);
207 __INTRIN_INLINE
char _InterlockedOr8(volatile char * const value
, const char mask
)
209 return __sync_fetch_and_or(value
, mask
);
212 __INTRIN_INLINE
short _InterlockedOr16(volatile short * const value
, const short mask
)
214 return __sync_fetch_and_or(value
, mask
);
217 __INTRIN_INLINE
long _InterlockedOr(volatile long * const value
, const long mask
)
219 return __sync_fetch_and_or(value
, mask
);
222 #if defined(_M_AMD64)
223 __INTRIN_INLINE
long long _InterlockedOr64(volatile long long * const value
, const long long mask
)
225 return __sync_fetch_and_or(value
, mask
);
229 __INTRIN_INLINE
char _InterlockedXor8(volatile char * const value
, const char mask
)
231 return __sync_fetch_and_xor(value
, mask
);
234 __INTRIN_INLINE
short _InterlockedXor16(volatile short * const value
, const short mask
)
236 return __sync_fetch_and_xor(value
, mask
);
239 __INTRIN_INLINE
long _InterlockedXor(volatile long * const value
, const long mask
)
241 return __sync_fetch_and_xor(value
, mask
);
244 #if defined(_M_AMD64)
245 __INTRIN_INLINE
long long _InterlockedXor64(volatile long long * const value
, const long long mask
)
247 return __sync_fetch_and_xor(value
, mask
);
251 __INTRIN_INLINE
long _InterlockedDecrement(volatile long * const lpAddend
)
253 return __sync_sub_and_fetch(lpAddend
, 1);
256 __INTRIN_INLINE
long _InterlockedIncrement(volatile long * const lpAddend
)
258 return __sync_add_and_fetch(lpAddend
, 1);
261 __INTRIN_INLINE
short _InterlockedDecrement16(volatile short * const lpAddend
)
263 return __sync_sub_and_fetch(lpAddend
, 1);
266 __INTRIN_INLINE
short _InterlockedIncrement16(volatile short * const lpAddend
)
268 return __sync_add_and_fetch(lpAddend
, 1);
271 #if defined(_M_AMD64)
272 __INTRIN_INLINE
long long _InterlockedDecrement64(volatile long long * const lpAddend
)
274 return __sync_sub_and_fetch(lpAddend
, 1);
277 __INTRIN_INLINE
long long _InterlockedIncrement64(volatile long long * const lpAddend
)
279 return __sync_add_and_fetch(lpAddend
, 1);
285 __INTRIN_INLINE
char _InterlockedCompareExchange8(volatile char * const Destination
, const char Exchange
, const char Comperand
)
287 char retval
= Comperand
;
288 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval
] "+a" (retval
) : [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
) : "memory");
292 __INTRIN_INLINE
short _InterlockedCompareExchange16(volatile short * const Destination
, const short Exchange
, const short Comperand
)
294 short retval
= Comperand
;
295 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval
] "+a" (retval
) : [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
): "memory");
299 __INTRIN_INLINE
long _InterlockedCompareExchange(volatile long * const Destination
, const long Exchange
, const long Comperand
)
301 long retval
= Comperand
;
302 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval
] "+a" (retval
) : [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
): "memory");
306 __INTRIN_INLINE
void * _InterlockedCompareExchangePointer(void * volatile * const Destination
, void * const Exchange
, void * const Comperand
)
308 void * retval
= (void *)Comperand
;
309 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval
] "=a" (retval
) : "[retval]" (retval
), [Destination
] "m" (*Destination
), [Exchange
] "q" (Exchange
) : "memory");
313 __INTRIN_INLINE
long _InterlockedExchange(volatile long * const Target
, const long Value
)
316 __asm__("xchgl %[retval], %[Target]" : [retval
] "+r" (retval
) : [Target
] "m" (*Target
) : "memory");
320 __INTRIN_INLINE
void * _InterlockedExchangePointer(void * volatile * const Target
, void * const Value
)
322 void * retval
= Value
;
323 __asm__("xchgl %[retval], %[Target]" : [retval
] "+r" (retval
) : [Target
] "m" (*Target
) : "memory");
327 __INTRIN_INLINE
long _InterlockedExchangeAdd16(volatile short * const Addend
, const short Value
)
330 __asm__("lock; xaddw %[retval], %[Addend]" : [retval
] "+r" (retval
) : [Addend
] "m" (*Addend
) : "memory");
334 __INTRIN_INLINE
long _InterlockedExchangeAdd(volatile long * const Addend
, const long Value
)
337 __asm__("lock; xaddl %[retval], %[Addend]" : [retval
] "+r" (retval
) : [Addend
] "m" (*Addend
) : "memory");
341 __INTRIN_INLINE
char _InterlockedAnd8(volatile char * const value
, const char mask
)
351 y
= _InterlockedCompareExchange8(value
, x
& mask
, x
);
358 __INTRIN_INLINE
short _InterlockedAnd16(volatile short * const value
, const short mask
)
368 y
= _InterlockedCompareExchange16(value
, x
& mask
, x
);
375 __INTRIN_INLINE
long _InterlockedAnd(volatile long * const value
, const long mask
)
385 y
= _InterlockedCompareExchange(value
, x
& mask
, x
);
392 __INTRIN_INLINE
char _InterlockedOr8(volatile char * const value
, const char mask
)
402 y
= _InterlockedCompareExchange8(value
, x
| mask
, x
);
409 __INTRIN_INLINE
short _InterlockedOr16(volatile short * const value
, const short mask
)
419 y
= _InterlockedCompareExchange16(value
, x
| mask
, x
);
426 __INTRIN_INLINE
long _InterlockedOr(volatile long * const value
, const long mask
)
436 y
= _InterlockedCompareExchange(value
, x
| mask
, x
);
443 __INTRIN_INLINE
char _InterlockedXor8(volatile char * const value
, const char mask
)
453 y
= _InterlockedCompareExchange8(value
, x
^ mask
, x
);
460 __INTRIN_INLINE
short _InterlockedXor16(volatile short * const value
, const short mask
)
470 y
= _InterlockedCompareExchange16(value
, x
^ mask
, x
);
477 __INTRIN_INLINE
long _InterlockedXor(volatile long * const value
, const long mask
)
487 y
= _InterlockedCompareExchange(value
, x
^ mask
, x
);
494 __INTRIN_INLINE
long _InterlockedDecrement(volatile long * const lpAddend
)
496 return _InterlockedExchangeAdd(lpAddend
, -1) - 1;
499 __INTRIN_INLINE
long _InterlockedIncrement(volatile long * const lpAddend
)
501 return _InterlockedExchangeAdd(lpAddend
, 1) + 1;
504 __INTRIN_INLINE
short _InterlockedDecrement16(volatile short * const lpAddend
)
506 return _InterlockedExchangeAdd16(lpAddend
, -1) - 1;
509 __INTRIN_INLINE
short _InterlockedIncrement16(volatile short * const lpAddend
)
511 return _InterlockedExchangeAdd16(lpAddend
, 1) + 1;
514 #if defined(_M_AMD64)
515 __INTRIN_INLINE
long long _InterlockedDecrement64(volatile long long * const lpAddend
)
517 return _InterlockedExchangeAdd64(lpAddend
, -1) - 1;
520 __INTRIN_INLINE
long long _InterlockedIncrement64(volatile long long * const lpAddend
)
522 return _InterlockedExchangeAdd64(lpAddend
, 1) + 1;
528 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__)
530 __INTRIN_INLINE
long long _InterlockedCompareExchange64(volatile long long * const Destination
, const long long Exchange
, const long long Comperand
)
532 return __sync_val_compare_and_swap(Destination
, Comperand
, Exchange
);
537 __INTRIN_INLINE
long long _InterlockedCompareExchange64(volatile long long * const Destination
, const long long Exchange
, const long long Comperand
)
539 long long retval
= Comperand
;
543 "lock; cmpxchg8b %[Destination]" :
544 [retval
] "+A" (retval
) :
545 [Destination
] "m" (*Destination
),
546 "b" ((unsigned long)((Exchange
>> 0) & 0xFFFFFFFF)),
547 "c" ((unsigned long)((Exchange
>> 32) & 0xFFFFFFFF)) :
556 __INTRIN_INLINE
long _InterlockedAddLargeStatistic(volatile long long * const Addend
, const long Value
)
560 "lock; add %[Value], %[Lo32];"
562 "lock; adc $0, %[Hi32];"
564 [Lo32
] "+m" (*((volatile long *)(Addend
) + 0)), [Hi32
] "+m" (*((volatile long *)(Addend
) + 1)) :
565 [Value
] "ir" (Value
) :
572 __INTRIN_INLINE
unsigned char _interlockedbittestandreset(volatile long * a
, const long b
)
574 unsigned char retval
;
575 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
579 #if defined(_M_AMD64)
580 __INTRIN_INLINE
unsigned char _interlockedbittestandreset64(volatile long long * a
, const long long b
)
582 unsigned char retval
;
583 __asm__("lock; btrq %[b], %[a]; setb %b[retval]" : [retval
] "=r" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
588 __INTRIN_INLINE
unsigned char _interlockedbittestandset(volatile long * a
, const long b
)
590 unsigned char retval
;
591 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval
] "=q" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
595 #if defined(_M_AMD64)
596 __INTRIN_INLINE
unsigned char _interlockedbittestandset64(volatile long long * a
, const long long b
)
598 unsigned char retval
;
599 __asm__("lock; btsq %[b], %[a]; setc %b[retval]" : [retval
] "=r" (retval
), [a
] "+m" (*a
) : [b
] "Ir" (b
) : "memory");
604 /*** String operations ***/
605 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
606 __INTRIN_INLINE
void __stosb(unsigned char * Dest
, const unsigned char Data
, size_t Count
)
611 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
612 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
616 __INTRIN_INLINE
void __stosw(unsigned short * Dest
, const unsigned short Data
, size_t Count
)
621 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
622 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
626 __INTRIN_INLINE
void __stosd(unsigned long * Dest
, const unsigned long Data
, size_t Count
)
631 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
632 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
637 __INTRIN_INLINE
void __stosq(unsigned __int64
* Dest
, const unsigned __int64 Data
, size_t Count
)
642 [Dest
] "=D" (Dest
), [Count
] "=c" (Count
) :
643 "[Dest]" (Dest
), "a" (Data
), "[Count]" (Count
)
648 __INTRIN_INLINE
void __movsb(unsigned char * Destination
, const unsigned char * Source
, size_t Count
)
653 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
654 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
658 __INTRIN_INLINE
void __movsw(unsigned short * Destination
, const unsigned short * Source
, size_t Count
)
663 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
664 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
668 __INTRIN_INLINE
void __movsd(unsigned long * Destination
, const unsigned long * Source
, size_t Count
)
673 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
674 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
679 __INTRIN_INLINE
void __movsq(unsigned long * Destination
, const unsigned long * Source
, size_t Count
)
684 [Destination
] "=D" (Destination
), [Source
] "=S" (Source
), [Count
] "=c" (Count
) :
685 "[Destination]" (Destination
), "[Source]" (Source
), "[Count]" (Count
)
690 #if defined(_M_AMD64)
691 /*** GS segment addressing ***/
693 __INTRIN_INLINE
void __writegsbyte(const unsigned long Offset
, const unsigned char Data
)
695 __asm__
__volatile__("movb %b[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
698 __INTRIN_INLINE
void __writegsword(const unsigned long Offset
, const unsigned short Data
)
700 __asm__
__volatile__("movw %w[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
703 __INTRIN_INLINE
void __writegsdword(const unsigned long Offset
, const unsigned long Data
)
705 __asm__
__volatile__("movl %k[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
708 __INTRIN_INLINE
void __writegsqword(const unsigned long Offset
, const unsigned __int64 Data
)
710 __asm__
__volatile__("movq %q[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
713 __INTRIN_INLINE
unsigned char __readgsbyte(const unsigned long Offset
)
716 __asm__
__volatile__("movb %%gs:%a[Offset], %b[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
720 __INTRIN_INLINE
unsigned short __readgsword(const unsigned long Offset
)
722 unsigned short value
;
723 __asm__
__volatile__("movw %%gs:%a[Offset], %w[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
727 __INTRIN_INLINE
unsigned long __readgsdword(const unsigned long Offset
)
730 __asm__
__volatile__("movl %%gs:%a[Offset], %k[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
734 __INTRIN_INLINE
unsigned __int64
__readgsqword(const unsigned long Offset
)
736 unsigned __int64 value
;
737 __asm__
__volatile__("movq %%gs:%a[Offset], %q[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
741 __INTRIN_INLINE
void __incgsbyte(const unsigned long Offset
)
743 __asm__
__volatile__("incb %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
746 __INTRIN_INLINE
void __incgsword(const unsigned long Offset
)
748 __asm__
__volatile__("incw %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
751 __INTRIN_INLINE
void __incgsdword(const unsigned long Offset
)
753 __asm__
__volatile__("incl %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
756 __INTRIN_INLINE
void __addgsbyte(const unsigned long Offset
, const unsigned char Data
)
758 __asm__
__volatile__("addb %b[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
761 __INTRIN_INLINE
void __addgsword(const unsigned long Offset
, const unsigned short Data
)
763 __asm__
__volatile__("addw %w[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
766 __INTRIN_INLINE
void __addgsdword(const unsigned long Offset
, const unsigned int Data
)
768 __asm__
__volatile__("addl %k[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
771 __INTRIN_INLINE
void __addgsqword(const unsigned long Offset
, const unsigned __int64 Data
)
773 __asm__
__volatile__("addq %k[Data], %%gs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
777 /*** FS segment addressing ***/
778 __INTRIN_INLINE
void __writefsbyte(const unsigned long Offset
, const unsigned char Data
)
780 __asm__
__volatile__("movb %b[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
783 __INTRIN_INLINE
void __writefsword(const unsigned long Offset
, const unsigned short Data
)
785 __asm__
__volatile__("movw %w[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
788 __INTRIN_INLINE
void __writefsdword(const unsigned long Offset
, const unsigned long Data
)
790 __asm__
__volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
) : "memory");
793 __INTRIN_INLINE
unsigned char __readfsbyte(const unsigned long Offset
)
796 __asm__
__volatile__("movb %%fs:%a[Offset], %b[value]" : [value
] "=q" (value
) : [Offset
] "ir" (Offset
));
800 __INTRIN_INLINE
unsigned short __readfsword(const unsigned long Offset
)
802 unsigned short value
;
803 __asm__
__volatile__("movw %%fs:%a[Offset], %w[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
807 __INTRIN_INLINE
unsigned long __readfsdword(const unsigned long Offset
)
810 __asm__
__volatile__("movl %%fs:%a[Offset], %k[value]" : [value
] "=r" (value
) : [Offset
] "ir" (Offset
));
814 __INTRIN_INLINE
void __incfsbyte(const unsigned long Offset
)
816 __asm__
__volatile__("incb %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
819 __INTRIN_INLINE
void __incfsword(const unsigned long Offset
)
821 __asm__
__volatile__("incw %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
824 __INTRIN_INLINE
void __incfsdword(const unsigned long Offset
)
826 __asm__
__volatile__("incl %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
) : "memory");
829 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
830 __INTRIN_INLINE
void __addfsbyte(const unsigned long Offset
, const unsigned char Data
)
832 if(!__builtin_constant_p(Offset
))
833 __asm__
__volatile__("addb %b[Offset], %%fs:%a[Offset]" : : [Offset
] "r" (Offset
) : "memory");
835 __asm__
__volatile__("addb %b[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
838 __INTRIN_INLINE
void __addfsword(const unsigned long Offset
, const unsigned short Data
)
840 if(!__builtin_constant_p(Offset
))
841 __asm__
__volatile__("addw %w[Offset], %%fs:%a[Offset]" : : [Offset
] "r" (Offset
) : "memory");
843 __asm__
__volatile__("addw %w[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
846 __INTRIN_INLINE
void __addfsdword(const unsigned long Offset
, const unsigned int Data
)
848 if(!__builtin_constant_p(Offset
))
849 __asm__
__volatile__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset
] "r" (Offset
) : "memory");
851 __asm__
__volatile__("addl %k[Data], %%fs:%a[Offset]" : : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
) : "memory");
856 /*** Bit manipulation ***/
857 __INTRIN_INLINE
unsigned char _BitScanForward(unsigned long * const Index
, const unsigned long Mask
)
859 __asm__("bsfl %[Mask], %[Index]" : [Index
] "=r" (*Index
) : [Mask
] "mr" (Mask
));
863 __INTRIN_INLINE
unsigned char _BitScanReverse(unsigned long * const Index
, const unsigned long Mask
)
865 __asm__("bsrl %[Mask], %[Index]" : [Index
] "=r" (*Index
) : [Mask
] "mr" (Mask
));
869 /* NOTE: again, the bizarre implementation follows Visual C++ */
870 __INTRIN_INLINE
unsigned char _bittest(const long * const a
, const long b
)
872 unsigned char retval
;
874 if(__builtin_constant_p(b
))
875 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*(a
+ (b
/ 32))), [b
] "Ir" (b
% 32));
877 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*a
), [b
] "r" (b
));
883 __INTRIN_INLINE
unsigned char _bittest64(const __int64
* const a
, const __int64 b
)
885 unsigned char retval
;
887 if(__builtin_constant_p(b
))
888 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*(a
+ (b
/ 64))), [b
] "Ir" (b
% 64));
890 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval
] "=q" (retval
) : [a
] "mr" (*a
), [b
] "r" (b
));
896 __INTRIN_INLINE
unsigned char _bittestandcomplement(long * const a
, const long b
)
898 unsigned char retval
;
900 if(__builtin_constant_p(b
))
901 __asm__("btc %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*(a
+ (b
/ 32))), [retval
] "=q" (retval
) : [b
] "Ir" (b
% 32));
903 __asm__("btc %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*a
), [retval
] "=q" (retval
) : [b
] "r" (b
));
908 __INTRIN_INLINE
unsigned char _bittestandreset(long * const a
, const long b
)
910 unsigned char retval
;
912 if(__builtin_constant_p(b
))
913 __asm__("btr %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*(a
+ (b
/ 32))), [retval
] "=q" (retval
) : [b
] "Ir" (b
% 32));
915 __asm__("btr %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*a
), [retval
] "=q" (retval
) : [b
] "r" (b
));
920 __INTRIN_INLINE
unsigned char _bittestandset(long * const a
, const long b
)
922 unsigned char retval
;
924 if(__builtin_constant_p(b
))
925 __asm__("bts %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*(a
+ (b
/ 32))), [retval
] "=q" (retval
) : [b
] "Ir" (b
% 32));
927 __asm__("bts %[b], %[a]; setb %b[retval]" : [a
] "+mr" (*a
), [retval
] "=q" (retval
) : [b
] "r" (b
));
932 __INTRIN_INLINE
unsigned char _rotl8(unsigned char value
, unsigned char shift
)
934 unsigned char retval
;
935 __asm__("rolb %b[shift], %b[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
939 __INTRIN_INLINE
unsigned short _rotl16(unsigned short value
, unsigned char shift
)
941 unsigned short retval
;
942 __asm__("rolw %b[shift], %w[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
946 __INTRIN_INLINE
unsigned int _rotl(unsigned int value
, int shift
)
948 unsigned long retval
;
949 __asm__("roll %b[shift], %k[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
953 __INTRIN_INLINE
unsigned int _rotr(unsigned int value
, int shift
)
955 unsigned long retval
;
956 __asm__("rorl %b[shift], %k[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
960 __INTRIN_INLINE
unsigned char _rotr8(unsigned char value
, unsigned char shift
)
962 unsigned char retval
;
963 __asm__("rorb %b[shift], %b[retval]" : [retval
] "=qm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
967 __INTRIN_INLINE
unsigned short _rotr16(unsigned short value
, unsigned char shift
)
969 unsigned short retval
;
970 __asm__("rorw %b[shift], %w[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
), [shift
] "Nc" (shift
));
975 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
976 constraint (edx:eax) for the Mask argument, because it's the only way GCC
977 can pass 64-bit operands around - passing the two 32 bit parts separately
978 just confuses it. Also we declare Bit as an int and then truncate it to
979 match Visual C++ behavior
981 __INTRIN_INLINE
unsigned long long __ll_lshift(const unsigned long long Mask
, const int Bit
)
983 unsigned long long retval
= Mask
;
987 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
989 [Bit
] "Nc" ((unsigned char)((unsigned long)Bit
) & 0xFF)
995 __INTRIN_INLINE
long long __ll_rshift(const long long Mask
, const int Bit
)
997 unsigned long long retval
= Mask
;
1001 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
1003 [Bit
] "Nc" ((unsigned char)((unsigned long)Bit
) & 0xFF)
1009 __INTRIN_INLINE
unsigned long long __ull_rshift(const unsigned long long Mask
, int Bit
)
1011 unsigned long long retval
= Mask
;
1015 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
1017 [Bit
] "Nc" ((unsigned char)((unsigned long)Bit
) & 0xFF)
1023 __INTRIN_INLINE
unsigned short _byteswap_ushort(unsigned short value
)
1025 unsigned short retval
;
1026 __asm__("rorw $8, %w[retval]" : [retval
] "=rm" (retval
) : "[retval]" (value
));
1030 __INTRIN_INLINE
unsigned long _byteswap_ulong(unsigned long value
)
1032 unsigned long retval
;
1033 __asm__("bswapl %[retval]" : [retval
] "=r" (retval
) : "[retval]" (value
));
1038 __INTRIN_INLINE
unsigned __int64
_byteswap_uint64(unsigned __int64 value
)
1040 unsigned __int64 retval
;
1041 __asm__("bswapq %[retval]" : [retval
] "=r" (retval
) : "[retval]" (value
));
1045 __INTRIN_INLINE
unsigned __int64
_byteswap_uint64(unsigned __int64 value
)
1050 unsigned long lowpart
;
1051 unsigned long hipart
;
1054 retval
.int64part
= value
;
1055 __asm__("bswapl %[lowpart]\n"
1056 "bswapl %[hipart]\n"
1057 : [lowpart
] "=r" (retval
.hipart
), [hipart
] "=r" (retval
.lowpart
) : "[lowpart]" (retval
.lowpart
), "[hipart]" (retval
.hipart
) );
1058 return retval
.int64part
;
1062 /*** 64-bit math ***/
1063 __INTRIN_INLINE
long long __emul(const int a
, const int b
)
1066 __asm__("imull %[b]" : "=A" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1070 __INTRIN_INLINE
unsigned long long __emulu(const unsigned int a
, const unsigned int b
)
1072 unsigned long long retval
;
1073 __asm__("mull %[b]" : "=A" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1079 __INTRIN_INLINE __int64
__mulh(__int64 a
, __int64 b
)
1082 __asm__("imulq %[b]" : "=d" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1086 __INTRIN_INLINE
unsigned __int64
__umulh(unsigned __int64 a
, unsigned __int64 b
)
1088 unsigned __int64 retval
;
1089 __asm__("mulq %[b]" : "=d" (retval
) : [a
] "a" (a
), [b
] "rm" (b
));
1096 __INTRIN_INLINE
unsigned char __inbyte(const unsigned short Port
)
1099 __asm__
__volatile__("inb %w[Port], %b[byte]" : [byte
] "=a" (byte
) : [Port
] "Nd" (Port
));
1103 __INTRIN_INLINE
unsigned short __inword(const unsigned short Port
)
1105 unsigned short word
;
1106 __asm__
__volatile__("inw %w[Port], %w[word]" : [word
] "=a" (word
) : [Port
] "Nd" (Port
));
1110 __INTRIN_INLINE
unsigned long __indword(const unsigned short Port
)
1112 unsigned long dword
;
1113 __asm__
__volatile__("inl %w[Port], %k[dword]" : [dword
] "=a" (dword
) : [Port
] "Nd" (Port
));
1117 __INTRIN_INLINE
void __inbytestring(unsigned short Port
, unsigned char * Buffer
, unsigned long Count
)
1119 __asm__ __volatile__
1122 [Buffer
] "=D" (Buffer
), [Count
] "=c" (Count
) :
1123 "d" (Port
), "[Buffer]" (Buffer
), "[Count]" (Count
) :
1128 __INTRIN_INLINE
void __inwordstring(unsigned short Port
, unsigned short * Buffer
, unsigned long Count
)
1130 __asm__ __volatile__
1133 [Buffer
] "=D" (Buffer
), [Count
] "=c" (Count
) :
1134 "d" (Port
), "[Buffer]" (Buffer
), "[Count]" (Count
) :
1139 __INTRIN_INLINE
void __indwordstring(unsigned short Port
, unsigned long * Buffer
, unsigned long Count
)
1141 __asm__ __volatile__
1144 [Buffer
] "=D" (Buffer
), [Count
] "=c" (Count
) :
1145 "d" (Port
), "[Buffer]" (Buffer
), "[Count]" (Count
) :
1150 __INTRIN_INLINE
void __outbyte(unsigned short const Port
, const unsigned char Data
)
1152 __asm__
__volatile__("outb %b[Data], %w[Port]" : : [Port
] "Nd" (Port
), [Data
] "a" (Data
));
1155 __INTRIN_INLINE
void __outword(unsigned short const Port
, const unsigned short Data
)
1157 __asm__
__volatile__("outw %w[Data], %w[Port]" : : [Port
] "Nd" (Port
), [Data
] "a" (Data
));
1160 __INTRIN_INLINE
void __outdword(unsigned short const Port
, const unsigned long Data
)
1162 __asm__
__volatile__("outl %k[Data], %w[Port]" : : [Port
] "Nd" (Port
), [Data
] "a" (Data
));
1165 __INTRIN_INLINE
void __outbytestring(unsigned short const Port
, const unsigned char * const Buffer
, const unsigned long Count
)
1167 __asm__
__volatile__("rep; outsb" : : [Port
] "d" (Port
), [Buffer
] "S" (Buffer
), "c" (Count
));
1170 __INTRIN_INLINE
void __outwordstring(unsigned short const Port
, const unsigned short * const Buffer
, const unsigned long Count
)
1172 __asm__
__volatile__("rep; outsw" : : [Port
] "d" (Port
), [Buffer
] "S" (Buffer
), "c" (Count
));
1175 __INTRIN_INLINE
void __outdwordstring(unsigned short const Port
, const unsigned long * const Buffer
, const unsigned long Count
)
1177 __asm__
__volatile__("rep; outsl" : : [Port
] "d" (Port
), [Buffer
] "S" (Buffer
), "c" (Count
));
1180 __INTRIN_INLINE
int _inp(unsigned short Port
)
1182 return __inbyte(Port
);
1185 __INTRIN_INLINE
unsigned short _inpw(unsigned short Port
)
1187 return __inword(Port
);
1190 __INTRIN_INLINE
unsigned long _inpd(unsigned short Port
)
1192 return __indword(Port
);
1195 __INTRIN_INLINE
int _outp(unsigned short Port
, int databyte
)
1197 __outbyte(Port
, databyte
);
1201 __INTRIN_INLINE
unsigned short _outpw(unsigned short Port
, unsigned short dataword
)
1203 __outword(Port
, dataword
);
1207 __INTRIN_INLINE
unsigned long _outpd(unsigned short Port
, unsigned long dataword
)
1209 __outdword(Port
, dataword
);
1214 /*** System information ***/
1215 __INTRIN_INLINE
void __cpuid(int CPUInfo
[], const int InfoType
)
1217 __asm__
__volatile__("cpuid" : "=a" (CPUInfo
[0]), "=b" (CPUInfo
[1]), "=c" (CPUInfo
[2]), "=d" (CPUInfo
[3]) : "a" (InfoType
));
1220 __INTRIN_INLINE
unsigned long long __rdtsc(void)
1223 unsigned long long low
, high
;
1224 __asm__
__volatile__("rdtsc" : "=a"(low
), "=d"(high
));
1225 return low
| (high
<< 32);
1227 unsigned long long retval
;
1228 __asm__
__volatile__("rdtsc" : "=A"(retval
));
1233 __INTRIN_INLINE
void __writeeflags(uintptr_t Value
)
1235 __asm__
__volatile__("push %0\n popf" : : "rim"(Value
));
1238 __INTRIN_INLINE
uintptr_t __readeflags(void)
1241 __asm__
__volatile__("pushf\n pop %0" : "=rm"(retval
));
1245 /*** Interrupts ***/
1247 #define __debugbreak() __asm__("int $3")
1249 __INTRIN_INLINE
void __debugbreak(void)
1255 __INTRIN_INLINE
void __int2c(void)
1257 __asm__("int $0x2c");
1260 __INTRIN_INLINE
void _disable(void)
1262 __asm__("cli" : : : "memory");
1265 __INTRIN_INLINE
void _enable(void)
1267 __asm__("sti" : : : "memory");
1270 __INTRIN_INLINE
void __halt(void)
1272 __asm__("hlt\n\t" : : : "memory");
1275 /*** Protected memory management ***/
1278 __INTRIN_INLINE
void __writecr0(const unsigned __int64 Data
)
1280 __asm__("mov %[Data], %%cr0" : : [Data
] "r" (Data
) : "memory");
1283 __INTRIN_INLINE
void __writecr3(const unsigned __int64 Data
)
1285 __asm__("mov %[Data], %%cr3" : : [Data
] "r" (Data
) : "memory");
1288 __INTRIN_INLINE
void __writecr4(const unsigned __int64 Data
)
1290 __asm__("mov %[Data], %%cr4" : : [Data
] "r" (Data
) : "memory");
1293 __INTRIN_INLINE
void __writecr8(const unsigned __int64 Data
)
1295 __asm__("mov %[Data], %%cr8" : : [Data
] "r" (Data
) : "memory");
1298 __INTRIN_INLINE
unsigned __int64
__readcr0(void)
1300 unsigned __int64 value
;
1301 __asm__
__volatile__("mov %%cr0, %[value]" : [value
] "=r" (value
));
1305 __INTRIN_INLINE
unsigned __int64
__readcr2(void)
1307 unsigned __int64 value
;
1308 __asm__
__volatile__("mov %%cr2, %[value]" : [value
] "=r" (value
));
1312 __INTRIN_INLINE
unsigned __int64
__readcr3(void)
1314 unsigned __int64 value
;
1315 __asm__
__volatile__("mov %%cr3, %[value]" : [value
] "=r" (value
));
1319 __INTRIN_INLINE
unsigned __int64
__readcr4(void)
1321 unsigned __int64 value
;
1322 __asm__
__volatile__("mov %%cr4, %[value]" : [value
] "=r" (value
));
1326 __INTRIN_INLINE
unsigned __int64
__readcr8(void)
1328 unsigned __int64 value
;
1329 __asm__
__volatile__("movq %%cr8, %q[value]" : [value
] "=r" (value
));
1333 __INTRIN_INLINE
void __writecr0(const unsigned int Data
)
1335 __asm__("mov %[Data], %%cr0" : : [Data
] "r" (Data
) : "memory");
1338 __INTRIN_INLINE
void __writecr3(const unsigned int Data
)
1340 __asm__("mov %[Data], %%cr3" : : [Data
] "r" (Data
) : "memory");
1343 __INTRIN_INLINE
void __writecr4(const unsigned int Data
)
1345 __asm__("mov %[Data], %%cr4" : : [Data
] "r" (Data
) : "memory");
1348 __INTRIN_INLINE
unsigned long __readcr0(void)
1350 unsigned long value
;
1351 __asm__
__volatile__("mov %%cr0, %[value]" : [value
] "=r" (value
));
1355 __INTRIN_INLINE
unsigned long __readcr2(void)
1357 unsigned long value
;
1358 __asm__
__volatile__("mov %%cr2, %[value]" : [value
] "=r" (value
));
1362 __INTRIN_INLINE
unsigned long __readcr3(void)
1364 unsigned long value
;
1365 __asm__
__volatile__("mov %%cr3, %[value]" : [value
] "=r" (value
));
1369 __INTRIN_INLINE
unsigned long __readcr4(void)
1371 unsigned long value
;
1372 __asm__
__volatile__("mov %%cr4, %[value]" : [value
] "=r" (value
));
1378 __INTRIN_INLINE
unsigned __int64
__readdr(unsigned int reg
)
1380 unsigned __int64 value
;
1384 __asm__
__volatile__("movq %%dr0, %q[value]" : [value
] "=r" (value
));
1387 __asm__
__volatile__("movq %%dr1, %q[value]" : [value
] "=r" (value
));
1390 __asm__
__volatile__("movq %%dr2, %q[value]" : [value
] "=r" (value
));
1393 __asm__
__volatile__("movq %%dr3, %q[value]" : [value
] "=r" (value
));
1396 __asm__
__volatile__("movq %%dr4, %q[value]" : [value
] "=r" (value
));
1399 __asm__
__volatile__("movq %%dr5, %q[value]" : [value
] "=r" (value
));
1402 __asm__
__volatile__("movq %%dr6, %q[value]" : [value
] "=r" (value
));
1405 __asm__
__volatile__("movq %%dr7, %q[value]" : [value
] "=r" (value
));
1411 __INTRIN_INLINE
void __writedr(unsigned reg
, unsigned __int64 value
)
1416 __asm__("movq %q[value], %%dr0" : : [value
] "r" (value
) : "memory");
1419 __asm__("movq %q[value], %%dr1" : : [value
] "r" (value
) : "memory");
1422 __asm__("movq %q[value], %%dr2" : : [value
] "r" (value
) : "memory");
1425 __asm__("movq %q[value], %%dr3" : : [value
] "r" (value
) : "memory");
1428 __asm__("movq %q[value], %%dr4" : : [value
] "r" (value
) : "memory");
1431 __asm__("movq %q[value], %%dr5" : : [value
] "r" (value
) : "memory");
1434 __asm__("movq %q[value], %%dr6" : : [value
] "r" (value
) : "memory");
1437 __asm__("movq %q[value], %%dr7" : : [value
] "r" (value
) : "memory");
1442 __INTRIN_INLINE
unsigned int __readdr(unsigned int reg
)
1448 __asm__
__volatile__("mov %%dr0, %[value]" : [value
] "=r" (value
));
1451 __asm__
__volatile__("mov %%dr1, %[value]" : [value
] "=r" (value
));
1454 __asm__
__volatile__("mov %%dr2, %[value]" : [value
] "=r" (value
));
1457 __asm__
__volatile__("mov %%dr3, %[value]" : [value
] "=r" (value
));
1460 __asm__
__volatile__("mov %%dr4, %[value]" : [value
] "=r" (value
));
1463 __asm__
__volatile__("mov %%dr5, %[value]" : [value
] "=r" (value
));
1466 __asm__
__volatile__("mov %%dr6, %[value]" : [value
] "=r" (value
));
1469 __asm__
__volatile__("mov %%dr7, %[value]" : [value
] "=r" (value
));
1475 __INTRIN_INLINE
void __writedr(unsigned reg
, unsigned int value
)
1480 __asm__("mov %[value], %%dr0" : : [value
] "r" (value
) : "memory");
1483 __asm__("mov %[value], %%dr1" : : [value
] "r" (value
) : "memory");
1486 __asm__("mov %[value], %%dr2" : : [value
] "r" (value
) : "memory");
1489 __asm__("mov %[value], %%dr3" : : [value
] "r" (value
) : "memory");
1492 __asm__("mov %[value], %%dr4" : : [value
] "r" (value
) : "memory");
1495 __asm__("mov %[value], %%dr5" : : [value
] "r" (value
) : "memory");
1498 __asm__("mov %[value], %%dr6" : : [value
] "r" (value
) : "memory");
1501 __asm__("mov %[value], %%dr7" : : [value
] "r" (value
) : "memory");
1507 __INTRIN_INLINE
void __invlpg(void * const Address
)
1509 __asm__("invlpg %[Address]" : : [Address
] "m" (*((unsigned char *)(Address
))) : "memory");
1513 /*** System operations ***/
1514 __INTRIN_INLINE
unsigned long long __readmsr(const int reg
)
1517 unsigned long low
, high
;
1518 __asm__
__volatile__("rdmsr" : "=a" (low
), "=d" (high
) : "c" (reg
));
1519 return ((unsigned long long)high
<< 32) | low
;
1521 unsigned long long retval
;
1522 __asm__
__volatile__("rdmsr" : "=A" (retval
) : "c" (reg
));
1527 __INTRIN_INLINE
void __writemsr(const unsigned long Register
, const unsigned long long Value
)
1530 __asm__
__volatile__("wrmsr" : : "a" (Value
), "d" (Value
>> 32), "c" (Register
));
1532 __asm__
__volatile__("wrmsr" : : "A" (Value
), "c" (Register
));
1536 __INTRIN_INLINE
unsigned long long __readpmc(const int counter
)
1538 unsigned long long retval
;
1539 __asm__
__volatile__("rdpmc" : "=A" (retval
) : "c" (counter
));
1543 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
1544 __INTRIN_INLINE
unsigned long __segmentlimit(const unsigned long a
)
1546 unsigned long retval
;
1547 __asm__
__volatile__("lsl %[a], %[retval]" : [retval
] "=r" (retval
) : [a
] "rm" (a
));
1551 __INTRIN_INLINE
void __wbinvd(void)
1553 __asm__
__volatile__("wbinvd" : : : "memory");
1556 __INTRIN_INLINE
void __lidt(void *Source
)
1558 __asm__
__volatile__("lidt %0" : : "m"(*(short*)Source
));
1561 __INTRIN_INLINE
void __sidt(void *Destination
)
1563 __asm__
__volatile__("sidt %0" : : "m"(*(short*)Destination
) : "memory");
1566 /*** Misc operations ***/
1568 __INTRIN_INLINE
void _mm_pause(void)
1570 __asm__
__volatile__("pause" : : : "memory");
1573 __INTRIN_INLINE
void __nop(void)
1575 __asm__
__volatile__("nop");
1582 #endif /* KJK_INTRIN_X86_H_ */