[ROSTESTS]
[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 /*** Memory barriers ***/
83
84 __INTRIN_INLINE void _ReadWriteBarrier(void)
85 {
86 __asm__ __volatile__("" : : : "memory");
87 }
88
89 /* GCC only supports full barriers */
90 #define _ReadBarrier _ReadWriteBarrier
91 #define _WriteBarrier _ReadWriteBarrier
92
93 __INTRIN_INLINE void _mm_mfence(void)
94 {
95 __asm__ __volatile__("mfence" : : : "memory");
96 }
97
98 __INTRIN_INLINE void _mm_lfence(void)
99 {
100 _ReadBarrier();
101 __asm__ __volatile__("lfence");
102 _ReadBarrier();
103 }
104
105 __INTRIN_INLINE void _mm_sfence(void)
106 {
107 _WriteBarrier();
108 __asm__ __volatile__("sfence");
109 _WriteBarrier();
110 }
111
112 #ifdef _x86_64
113 __INTRIN_INLINE void __faststorefence(void)
114 {
115 long local;
116 __asm__ __volatile__("lock; orl $0, %0;" : : "m"(local));
117 }
118 #endif
119
120
121 /*** Atomic operations ***/
122
123 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
124
125 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
126 {
127 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
128 }
129
130 __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
131 {
132 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
133 }
134
135 __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
136 {
137 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
138 }
139
140 __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
141 {
142 return (void *)__sync_val_compare_and_swap(Destination, Comperand, Exchange);
143 }
144
145 __INTRIN_INLINE long _InterlockedExchange(volatile long * const Target, const long Value)
146 {
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);
150 }
151
152 #if defined(_M_AMD64)
153 __INTRIN_INLINE long long _InterlockedExchange64(volatile long long * const Target, const long long Value)
154 {
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);
158 }
159 #endif
160
161 __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
162 {
163 /* NOTE: ditto */
164 __sync_synchronize();
165 return (void *)__sync_lock_test_and_set(Target, Value);
166 }
167
168 __INTRIN_INLINE long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value)
169 {
170 return __sync_fetch_and_add(Addend, Value);
171 }
172
173 __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
174 {
175 return __sync_fetch_and_add(Addend, Value);
176 }
177
178 #if defined(_M_AMD64)
179 __INTRIN_INLINE long long _InterlockedExchangeAdd64(volatile long long * const Addend, const long long Value)
180 {
181 return __sync_fetch_and_add(Addend, Value);
182 }
183 #endif
184
185 __INTRIN_INLINE char _InterlockedAnd8(volatile char * const value, const char mask)
186 {
187 return __sync_fetch_and_and(value, mask);
188 }
189
190 __INTRIN_INLINE short _InterlockedAnd16(volatile short * const value, const short mask)
191 {
192 return __sync_fetch_and_and(value, mask);
193 }
194
195 __INTRIN_INLINE long _InterlockedAnd(volatile long * const value, const long mask)
196 {
197 return __sync_fetch_and_and(value, mask);
198 }
199
200 #if defined(_M_AMD64)
201 __INTRIN_INLINE long _InterlockedAnd64(volatile long long * const value, const long long mask)
202 {
203 return __sync_fetch_and_and(value, mask);
204 }
205 #endif
206
207 __INTRIN_INLINE char _InterlockedOr8(volatile char * const value, const char mask)
208 {
209 return __sync_fetch_and_or(value, mask);
210 }
211
212 __INTRIN_INLINE short _InterlockedOr16(volatile short * const value, const short mask)
213 {
214 return __sync_fetch_and_or(value, mask);
215 }
216
217 __INTRIN_INLINE long _InterlockedOr(volatile long * const value, const long mask)
218 {
219 return __sync_fetch_and_or(value, mask);
220 }
221
222 #if defined(_M_AMD64)
223 __INTRIN_INLINE long _InterlockedOr64(volatile long long * const value, const long long mask)
224 {
225 return __sync_fetch_and_or(value, mask);
226 }
227 #endif
228
229 __INTRIN_INLINE char _InterlockedXor8(volatile char * const value, const char mask)
230 {
231 return __sync_fetch_and_xor(value, mask);
232 }
233
234 __INTRIN_INLINE short _InterlockedXor16(volatile short * const value, const short mask)
235 {
236 return __sync_fetch_and_xor(value, mask);
237 }
238
239 __INTRIN_INLINE long _InterlockedXor(volatile long * const value, const long mask)
240 {
241 return __sync_fetch_and_xor(value, mask);
242 }
243
244 #else
245
246 __INTRIN_INLINE char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
247 {
248 char retval = Comperand;
249 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
250 return retval;
251 }
252
253 __INTRIN_INLINE short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
254 {
255 short retval = Comperand;
256 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
257 return retval;
258 }
259
260 __INTRIN_INLINE long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
261 {
262 long retval = Comperand;
263 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
264 return retval;
265 }
266
267 __INTRIN_INLINE void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
268 {
269 void * retval = (void *)Comperand;
270 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
271 return retval;
272 }
273
274 __INTRIN_INLINE long _InterlockedExchange(volatile long * const Target, const long Value)
275 {
276 long retval = Value;
277 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
278 return retval;
279 }
280
281 __INTRIN_INLINE void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
282 {
283 void * retval = Value;
284 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
285 return retval;
286 }
287
288 __INTRIN_INLINE long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value)
289 {
290 long retval = Value;
291 __asm__("lock; xaddw %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
292 return retval;
293 }
294
295 __INTRIN_INLINE long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
296 {
297 long retval = Value;
298 __asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
299 return retval;
300 }
301
302 __INTRIN_INLINE char _InterlockedAnd8(volatile char * const value, const char mask)
303 {
304 char x;
305 char y;
306
307 y = *value;
308
309 do
310 {
311 x = y;
312 y = _InterlockedCompareExchange8(value, x & mask, x);
313 }
314 while(y != x);
315
316 return y;
317 }
318
319 __INTRIN_INLINE short _InterlockedAnd16(volatile short * const value, const short mask)
320 {
321 short x;
322 short y;
323
324 y = *value;
325
326 do
327 {
328 x = y;
329 y = _InterlockedCompareExchange16(value, x & mask, x);
330 }
331 while(y != x);
332
333 return y;
334 }
335
336 __INTRIN_INLINE long _InterlockedAnd(volatile long * const value, const long mask)
337 {
338 long x;
339 long y;
340
341 y = *value;
342
343 do
344 {
345 x = y;
346 y = _InterlockedCompareExchange(value, x & mask, x);
347 }
348 while(y != x);
349
350 return y;
351 }
352
353 __INTRIN_INLINE char _InterlockedOr8(volatile char * const value, const char mask)
354 {
355 char x;
356 char y;
357
358 y = *value;
359
360 do
361 {
362 x = y;
363 y = _InterlockedCompareExchange8(value, x | mask, x);
364 }
365 while(y != x);
366
367 return y;
368 }
369
370 __INTRIN_INLINE short _InterlockedOr16(volatile short * const value, const short mask)
371 {
372 short x;
373 short y;
374
375 y = *value;
376
377 do
378 {
379 x = y;
380 y = _InterlockedCompareExchange16(value, x | mask, x);
381 }
382 while(y != x);
383
384 return y;
385 }
386
387 __INTRIN_INLINE long _InterlockedOr(volatile long * const value, const long mask)
388 {
389 long x;
390 long y;
391
392 y = *value;
393
394 do
395 {
396 x = y;
397 y = _InterlockedCompareExchange(value, x | mask, x);
398 }
399 while(y != x);
400
401 return y;
402 }
403
404 __INTRIN_INLINE char _InterlockedXor8(volatile char * const value, const char mask)
405 {
406 char x;
407 char y;
408
409 y = *value;
410
411 do
412 {
413 x = y;
414 y = _InterlockedCompareExchange8(value, x ^ mask, x);
415 }
416 while(y != x);
417
418 return y;
419 }
420
421 __INTRIN_INLINE short _InterlockedXor16(volatile short * const value, const short mask)
422 {
423 short x;
424 short y;
425
426 y = *value;
427
428 do
429 {
430 x = y;
431 y = _InterlockedCompareExchange16(value, x ^ mask, x);
432 }
433 while(y != x);
434
435 return y;
436 }
437
438 __INTRIN_INLINE long _InterlockedXor(volatile long * const value, const long mask)
439 {
440 long x;
441 long y;
442
443 y = *value;
444
445 do
446 {
447 x = y;
448 y = _InterlockedCompareExchange(value, x ^ mask, x);
449 }
450 while(y != x);
451
452 return y;
453 }
454
455 #endif
456
457 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 && defined(__x86_64__)
458
459 __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
460 {
461 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
462 }
463
464 #else
465
466 __INTRIN_INLINE long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
467 {
468 long long retval = Comperand;
469
470 __asm__
471 (
472 "lock; cmpxchg8b %[Destination]" :
473 [retval] "+A" (retval) :
474 [Destination] "m" (*Destination),
475 "b" ((unsigned long)((Exchange >> 0) & 0xFFFFFFFF)),
476 "c" ((unsigned long)((Exchange >> 32) & 0xFFFFFFFF)) :
477 "memory"
478 );
479
480 return retval;
481 }
482
483 #endif
484
485 __INTRIN_INLINE long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)
486 {
487 __asm__
488 (
489 "lock; add %[Value], %[Lo32];"
490 "jae LABEL%=;"
491 "lock; adc $0, %[Hi32];"
492 "LABEL%=:;" :
493 [Lo32] "+m" (*((volatile long *)(Addend) + 0)), [Hi32] "+m" (*((volatile long *)(Addend) + 1)) :
494 [Value] "ir" (Value) :
495 "memory"
496 );
497
498 return Value;
499 }
500
501 __INTRIN_INLINE long _InterlockedDecrement(volatile long * const lpAddend)
502 {
503 return _InterlockedExchangeAdd(lpAddend, -1) - 1;
504 }
505
506 __INTRIN_INLINE long _InterlockedIncrement(volatile long * const lpAddend)
507 {
508 return _InterlockedExchangeAdd(lpAddend, 1) + 1;
509 }
510
511 __INTRIN_INLINE short _InterlockedDecrement16(volatile short * const lpAddend)
512 {
513 return _InterlockedExchangeAdd16(lpAddend, -1) - 1;
514 }
515
516 __INTRIN_INLINE short _InterlockedIncrement16(volatile short * const lpAddend)
517 {
518 return _InterlockedExchangeAdd16(lpAddend, 1) + 1;
519 }
520
521 #if defined(_M_AMD64)
522 __INTRIN_INLINE long long _InterlockedDecrement64(volatile long long * const lpAddend)
523 {
524 return _InterlockedExchangeAdd64(lpAddend, -1) - 1;
525 }
526
527 __INTRIN_INLINE long long _InterlockedIncrement64(volatile long long * const lpAddend)
528 {
529 return _InterlockedExchangeAdd64(lpAddend, 1) + 1;
530 }
531 #endif
532
533 __INTRIN_INLINE unsigned char _interlockedbittestandreset(volatile long * a, const long b)
534 {
535 unsigned char retval;
536 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
537 return retval;
538 }
539
540 #if defined(_M_AMD64)
541 __INTRIN_INLINE unsigned char _interlockedbittestandreset64(volatile long long * a, const long long b)
542 {
543 unsigned char retval;
544 __asm__("lock; btrq %[b], %[a]; setb %b[retval]" : [retval] "=r" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
545 return retval;
546 }
547 #endif
548
549 __INTRIN_INLINE unsigned char _interlockedbittestandset(volatile long * a, const long b)
550 {
551 unsigned char retval;
552 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
553 return retval;
554 }
555
556 #if defined(_M_AMD64)
557 __INTRIN_INLINE unsigned char _interlockedbittestandset64(volatile long long * a, const long long b)
558 {
559 unsigned char retval;
560 __asm__("lock; btsq %[b], %[a]; setc %b[retval]" : [retval] "=r" (retval), [a] "+m" (*a) : [b] "Ir" (b) : "memory");
561 return retval;
562 }
563 #endif
564
565 /*** String operations ***/
566 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
567 __INTRIN_INLINE void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)
568 {
569 __asm__ __volatile__
570 (
571 "rep; stosb" :
572 [Dest] "=D" (Dest), [Count] "=c" (Count) :
573 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
574 );
575 }
576
577 __INTRIN_INLINE void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)
578 {
579 __asm__ __volatile__
580 (
581 "rep; stosw" :
582 [Dest] "=D" (Dest), [Count] "=c" (Count) :
583 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
584 );
585 }
586
587 __INTRIN_INLINE void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)
588 {
589 __asm__ __volatile__
590 (
591 "rep; stosl" :
592 [Dest] "=D" (Dest), [Count] "=c" (Count) :
593 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
594 );
595 }
596
597 #ifdef _M_AMD64
598 __INTRIN_INLINE void __stosq(unsigned __int64 * Dest, const unsigned __int64 Data, size_t Count)
599 {
600 __asm__ __volatile__
601 (
602 "rep; stosq" :
603 [Dest] "=D" (Dest), [Count] "=c" (Count) :
604 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
605 );
606 }
607 #endif
608
609 __INTRIN_INLINE void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)
610 {
611 __asm__ __volatile__
612 (
613 "rep; movsb" :
614 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
615 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
616 );
617 }
618
619 __INTRIN_INLINE void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)
620 {
621 __asm__ __volatile__
622 (
623 "rep; movsw" :
624 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
625 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
626 );
627 }
628
629 __INTRIN_INLINE void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)
630 {
631 __asm__ __volatile__
632 (
633 "rep; movsd" :
634 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
635 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
636 );
637 }
638
639 #ifdef _M_AMD64
640 __INTRIN_INLINE void __movsq(unsigned long * Destination, const unsigned long * Source, size_t Count)
641 {
642 __asm__ __volatile__
643 (
644 "rep; movsq" :
645 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
646 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
647 );
648 }
649 #endif
650
651 #if defined(_M_AMD64)
652 /*** GS segment addressing ***/
653
654 __INTRIN_INLINE void __writegsbyte(const unsigned long Offset, const unsigned char Data)
655 {
656 __asm__ __volatile__("movb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
657 }
658
659 __INTRIN_INLINE void __writegsword(const unsigned long Offset, const unsigned short Data)
660 {
661 __asm__ __volatile__("movw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
662 }
663
664 __INTRIN_INLINE void __writegsdword(const unsigned long Offset, const unsigned long Data)
665 {
666 __asm__ __volatile__("movl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
667 }
668
669 __INTRIN_INLINE void __writegsqword(const unsigned long Offset, const unsigned __int64 Data)
670 {
671 __asm__ __volatile__("movq %q[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
672 }
673
674 __INTRIN_INLINE unsigned char __readgsbyte(const unsigned long Offset)
675 {
676 unsigned char value;
677 __asm__ __volatile__("movb %%gs:%a[Offset], %b[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
678 return value;
679 }
680
681 __INTRIN_INLINE unsigned short __readgsword(const unsigned long Offset)
682 {
683 unsigned short value;
684 __asm__ __volatile__("movw %%gs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
685 return value;
686 }
687
688 __INTRIN_INLINE unsigned long __readgsdword(const unsigned long Offset)
689 {
690 unsigned long value;
691 __asm__ __volatile__("movl %%gs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
692 return value;
693 }
694
695 __INTRIN_INLINE unsigned __int64 __readgsqword(const unsigned long Offset)
696 {
697 unsigned __int64 value;
698 __asm__ __volatile__("movq %%gs:%a[Offset], %q[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
699 return value;
700 }
701
702 __INTRIN_INLINE void __incgsbyte(const unsigned long Offset)
703 {
704 __asm__ __volatile__("incb %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
705 }
706
707 __INTRIN_INLINE void __incgsword(const unsigned long Offset)
708 {
709 __asm__ __volatile__("incw %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
710 }
711
712 __INTRIN_INLINE void __incgsdword(const unsigned long Offset)
713 {
714 __asm__ __volatile__("incl %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
715 }
716
717 __INTRIN_INLINE void __addgsbyte(const unsigned long Offset, const unsigned char Data)
718 {
719 __asm__ __volatile__("addb %b[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
720 }
721
722 __INTRIN_INLINE void __addgsword(const unsigned long Offset, const unsigned short Data)
723 {
724 __asm__ __volatile__("addw %w[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
725 }
726
727 __INTRIN_INLINE void __addgsdword(const unsigned long Offset, const unsigned int Data)
728 {
729 __asm__ __volatile__("addl %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
730 }
731
732 __INTRIN_INLINE void __addgsqword(const unsigned long Offset, const unsigned __int64 Data)
733 {
734 __asm__ __volatile__("addq %k[Data], %%gs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
735 }
736
737 #else
738 /*** FS segment addressing ***/
739 __INTRIN_INLINE void __writefsbyte(const unsigned long Offset, const unsigned char Data)
740 {
741 __asm__ __volatile__("movb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
742 }
743
744 __INTRIN_INLINE void __writefsword(const unsigned long Offset, const unsigned short Data)
745 {
746 __asm__ __volatile__("movw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
747 }
748
749 __INTRIN_INLINE void __writefsdword(const unsigned long Offset, const unsigned long Data)
750 {
751 __asm__ __volatile__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "ir" (Data) : "memory");
752 }
753
754 __INTRIN_INLINE unsigned char __readfsbyte(const unsigned long Offset)
755 {
756 unsigned char value;
757 __asm__ __volatile__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "ir" (Offset));
758 return value;
759 }
760
761 __INTRIN_INLINE unsigned short __readfsword(const unsigned long Offset)
762 {
763 unsigned short value;
764 __asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
765 return value;
766 }
767
768 __INTRIN_INLINE unsigned long __readfsdword(const unsigned long Offset)
769 {
770 unsigned long value;
771 __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
772 return value;
773 }
774
775 __INTRIN_INLINE void __incfsbyte(const unsigned long Offset)
776 {
777 __asm__ __volatile__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
778 }
779
780 __INTRIN_INLINE void __incfsword(const unsigned long Offset)
781 {
782 __asm__ __volatile__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
783 }
784
785 __INTRIN_INLINE void __incfsdword(const unsigned long Offset)
786 {
787 __asm__ __volatile__("incl %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
788 }
789
790 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
791 __INTRIN_INLINE void __addfsbyte(const unsigned long Offset, const unsigned char Data)
792 {
793 if(!__builtin_constant_p(Offset))
794 __asm__ __volatile__("addb %b[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
795 else
796 __asm__ __volatile__("addb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
797 }
798
799 __INTRIN_INLINE void __addfsword(const unsigned long Offset, const unsigned short Data)
800 {
801 if(!__builtin_constant_p(Offset))
802 __asm__ __volatile__("addw %w[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
803 else
804 __asm__ __volatile__("addw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
805 }
806
807 __INTRIN_INLINE void __addfsdword(const unsigned long Offset, const unsigned int Data)
808 {
809 if(!__builtin_constant_p(Offset))
810 __asm__ __volatile__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset) : "memory");
811 else
812 __asm__ __volatile__("addl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data) : "memory");
813 }
814 #endif
815
816
817 /*** Bit manipulation ***/
818 __INTRIN_INLINE unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)
819 {
820 __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
821 return Mask ? 1 : 0;
822 }
823
824 __INTRIN_INLINE unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)
825 {
826 __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
827 return Mask ? 1 : 0;
828 }
829
830 /* NOTE: again, the bizarre implementation follows Visual C++ */
831 __INTRIN_INLINE unsigned char _bittest(const long * const a, const long b)
832 {
833 unsigned char retval;
834
835 if(__builtin_constant_p(b))
836 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
837 else
838 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
839
840 return retval;
841 }
842
843 #ifdef _M_AMD64
844 __INTRIN_INLINE unsigned char _bittest64(const __int64 * const a, const __int64 b)
845 {
846 unsigned char retval;
847
848 if(__builtin_constant_p(b))
849 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 64))), [b] "Ir" (b % 64));
850 else
851 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
852
853 return retval;
854 }
855 #endif
856
857 __INTRIN_INLINE unsigned char _bittestandcomplement(long * const a, const long b)
858 {
859 unsigned char retval;
860
861 if(__builtin_constant_p(b))
862 __asm__("btc %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32));
863 else
864 __asm__("btc %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b));
865
866 return retval;
867 }
868
869 __INTRIN_INLINE unsigned char _bittestandreset(long * const a, const long b)
870 {
871 unsigned char retval;
872
873 if(__builtin_constant_p(b))
874 __asm__("btr %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32));
875 else
876 __asm__("btr %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b));
877
878 return retval;
879 }
880
881 __INTRIN_INLINE unsigned char _bittestandset(long * const a, const long b)
882 {
883 unsigned char retval;
884
885 if(__builtin_constant_p(b))
886 __asm__("bts %[b], %[a]; setb %b[retval]" : [a] "+mr" (*(a + (b / 32))), [retval] "=q" (retval) : [b] "Ir" (b % 32));
887 else
888 __asm__("bts %[b], %[a]; setb %b[retval]" : [a] "+mr" (*a), [retval] "=q" (retval) : [b] "r" (b));
889
890 return retval;
891 }
892
893 __INTRIN_INLINE unsigned char _rotl8(unsigned char value, unsigned char shift)
894 {
895 unsigned char retval;
896 __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
897 return retval;
898 }
899
900 __INTRIN_INLINE unsigned short _rotl16(unsigned short value, unsigned char shift)
901 {
902 unsigned short retval;
903 __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
904 return retval;
905 }
906
907 __INTRIN_INLINE unsigned int _rotl(unsigned int value, int shift)
908 {
909 unsigned long retval;
910 __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
911 return retval;
912 }
913
914 __INTRIN_INLINE unsigned int _rotr(unsigned int value, int shift)
915 {
916 unsigned long retval;
917 __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
918 return retval;
919 }
920
921 __INTRIN_INLINE unsigned char _rotr8(unsigned char value, unsigned char shift)
922 {
923 unsigned char retval;
924 __asm__("rorb %b[shift], %b[retval]" : [retval] "=qm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
925 return retval;
926 }
927
928 __INTRIN_INLINE unsigned short _rotr16(unsigned short value, unsigned char shift)
929 {
930 unsigned short retval;
931 __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
932 return retval;
933 }
934
935 /*
936 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
937 constraint (edx:eax) for the Mask argument, because it's the only way GCC
938 can pass 64-bit operands around - passing the two 32 bit parts separately
939 just confuses it. Also we declare Bit as an int and then truncate it to
940 match Visual C++ behavior
941 */
942 __INTRIN_INLINE unsigned long long __ll_lshift(const unsigned long long Mask, const int Bit)
943 {
944 unsigned long long retval = Mask;
945
946 __asm__
947 (
948 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
949 "+A" (retval) :
950 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
951 );
952
953 return retval;
954 }
955
956 __INTRIN_INLINE long long __ll_rshift(const long long Mask, const int Bit)
957 {
958 unsigned long long retval = Mask;
959
960 __asm__
961 (
962 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
963 "+A" (retval) :
964 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
965 );
966
967 return retval;
968 }
969
970 __INTRIN_INLINE unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)
971 {
972 unsigned long long retval = Mask;
973
974 __asm__
975 (
976 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
977 "+A" (retval) :
978 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
979 );
980
981 return retval;
982 }
983
984 __INTRIN_INLINE unsigned short _byteswap_ushort(unsigned short value)
985 {
986 unsigned short retval;
987 __asm__("rorw $8, %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
988 return retval;
989 }
990
991 __INTRIN_INLINE unsigned long _byteswap_ulong(unsigned long value)
992 {
993 unsigned long retval;
994 __asm__("bswapl %[retval]" : [retval] "=r" (retval) : "[retval]" (value));
995 return retval;
996 }
997
998 #ifdef _M_AMD64
999 __INTRIN_INLINE unsigned __int64 _byteswap_uint64(unsigned __int64 value)
1000 {
1001 unsigned __int64 retval;
1002 __asm__("bswapq %[retval]" : [retval] "=r" (retval) : "[retval]" (value));
1003 return retval;
1004 }
1005 #else
1006 __INTRIN_INLINE unsigned __int64 _byteswap_uint64(unsigned __int64 value)
1007 {
1008 union {
1009 __int64 int64part;
1010 struct {
1011 unsigned long lowpart;
1012 unsigned long hipart;
1013 };
1014 } retval;
1015 retval.int64part = value;
1016 __asm__("bswapl %[lowpart]\n"
1017 "bswapl %[hipart]\n"
1018 : [lowpart] "=r" (retval.hipart), [hipart] "=r" (retval.lowpart) : "[lowpart]" (retval.lowpart), "[hipart]" (retval.hipart) );
1019 return retval.int64part;
1020 }
1021 #endif
1022
1023 /*** 64-bit math ***/
1024 __INTRIN_INLINE long long __emul(const int a, const int b)
1025 {
1026 long long retval;
1027 __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
1028 return retval;
1029 }
1030
1031 __INTRIN_INLINE unsigned long long __emulu(const unsigned int a, const unsigned int b)
1032 {
1033 unsigned long long retval;
1034 __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
1035 return retval;
1036 }
1037
1038 #ifdef _M_AMD64
1039
1040 __INTRIN_INLINE __int64 __mulh(__int64 a, __int64 b)
1041 {
1042 __int64 retval;
1043 __asm__("imulq %[b]" : "=d" (retval) : [a] "a" (a), [b] "rm" (b));
1044 return retval;
1045 }
1046
1047 __INTRIN_INLINE unsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b)
1048 {
1049 unsigned __int64 retval;
1050 __asm__("mulq %[b]" : "=d" (retval) : [a] "a" (a), [b] "rm" (b));
1051 return retval;
1052 }
1053
1054 #endif
1055
1056 /*** Port I/O ***/
1057 __INTRIN_INLINE unsigned char __inbyte(const unsigned short Port)
1058 {
1059 unsigned char byte;
1060 __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port));
1061 return byte;
1062 }
1063
1064 __INTRIN_INLINE unsigned short __inword(const unsigned short Port)
1065 {
1066 unsigned short word;
1067 __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port));
1068 return word;
1069 }
1070
1071 __INTRIN_INLINE unsigned long __indword(const unsigned short Port)
1072 {
1073 unsigned long dword;
1074 __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port));
1075 return dword;
1076 }
1077
1078 __INTRIN_INLINE void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)
1079 {
1080 __asm__ __volatile__
1081 (
1082 "rep; insb" :
1083 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1084 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1085 "memory"
1086 );
1087 }
1088
1089 __INTRIN_INLINE void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)
1090 {
1091 __asm__ __volatile__
1092 (
1093 "rep; insw" :
1094 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1095 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1096 "memory"
1097 );
1098 }
1099
1100 __INTRIN_INLINE void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)
1101 {
1102 __asm__ __volatile__
1103 (
1104 "rep; insl" :
1105 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1106 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1107 "memory"
1108 );
1109 }
1110
1111 __INTRIN_INLINE void __outbyte(unsigned short const Port, const unsigned char Data)
1112 {
1113 __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1114 }
1115
1116 __INTRIN_INLINE void __outword(unsigned short const Port, const unsigned short Data)
1117 {
1118 __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1119 }
1120
1121 __INTRIN_INLINE void __outdword(unsigned short const Port, const unsigned long Data)
1122 {
1123 __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1124 }
1125
1126 __INTRIN_INLINE void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)
1127 {
1128 __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1129 }
1130
1131 __INTRIN_INLINE void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)
1132 {
1133 __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1134 }
1135
1136 __INTRIN_INLINE void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)
1137 {
1138 __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1139 }
1140
1141 __INTRIN_INLINE int _inp(unsigned short Port)
1142 {
1143 return __inbyte(Port);
1144 }
1145
1146 __INTRIN_INLINE unsigned short _inpw(unsigned short Port)
1147 {
1148 return __inword(Port);
1149 }
1150
1151 __INTRIN_INLINE unsigned long _inpd(unsigned short Port)
1152 {
1153 return __indword(Port);
1154 }
1155
1156 __INTRIN_INLINE int _outp(unsigned short Port, int databyte)
1157 {
1158 __outbyte(Port, databyte);
1159 return databyte;
1160 }
1161
1162 __INTRIN_INLINE unsigned short _outpw(unsigned short Port, unsigned short dataword)
1163 {
1164 __outword(Port, dataword);
1165 return dataword;
1166 }
1167
1168 __INTRIN_INLINE unsigned long _outpd(unsigned short Port, unsigned long dataword)
1169 {
1170 __outdword(Port, dataword);
1171 return dataword;
1172 }
1173
1174
1175 /*** System information ***/
1176 __INTRIN_INLINE void __cpuid(int CPUInfo[], const int InfoType)
1177 {
1178 __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType));
1179 }
1180
1181 __INTRIN_INLINE unsigned long long __rdtsc(void)
1182 {
1183 #ifdef _M_AMD64
1184 unsigned long long low, high;
1185 __asm__ __volatile__("rdtsc" : "=a"(low), "=d"(high));
1186 return low | (high << 32);
1187 #else
1188 unsigned long long retval;
1189 __asm__ __volatile__("rdtsc" : "=A"(retval));
1190 return retval;
1191 #endif
1192 }
1193
1194 __INTRIN_INLINE void __writeeflags(uintptr_t Value)
1195 {
1196 __asm__ __volatile__("push %0\n popf" : : "rim"(Value));
1197 }
1198
1199 __INTRIN_INLINE uintptr_t __readeflags(void)
1200 {
1201 uintptr_t retval;
1202 __asm__ __volatile__("pushf\n pop %0" : "=rm"(retval));
1203 return retval;
1204 }
1205
1206 /*** Interrupts ***/
1207 __INTRIN_INLINE void __debugbreak(void)
1208 {
1209 __asm__("int $3");
1210 }
1211
1212 __INTRIN_INLINE void __int2c(void)
1213 {
1214 __asm__("int $0x2c");
1215 }
1216
1217 __INTRIN_INLINE void _disable(void)
1218 {
1219 __asm__("cli" : : : "memory");
1220 }
1221
1222 __INTRIN_INLINE void _enable(void)
1223 {
1224 __asm__("sti" : : : "memory");
1225 }
1226
1227 __INTRIN_INLINE void __halt(void)
1228 {
1229 __asm__("hlt\n\t" : : : "memory");
1230 }
1231
1232 /*** Protected memory management ***/
1233
1234 __INTRIN_INLINE void __writecr0(const unsigned __int64 Data)
1235 {
1236 __asm__("mov %[Data], %%cr0" : : [Data] "r" (Data) : "memory");
1237 }
1238
1239 __INTRIN_INLINE void __writecr3(const unsigned __int64 Data)
1240 {
1241 __asm__("mov %[Data], %%cr3" : : [Data] "r" (Data) : "memory");
1242 }
1243
1244 __INTRIN_INLINE void __writecr4(const unsigned __int64 Data)
1245 {
1246 __asm__("mov %[Data], %%cr4" : : [Data] "r" (Data) : "memory");
1247 }
1248
1249 #ifdef _M_AMD64
1250 __INTRIN_INLINE void __writecr8(const unsigned __int64 Data)
1251 {
1252 __asm__("mov %[Data], %%cr8" : : [Data] "r" (Data) : "memory");
1253 }
1254
1255 __INTRIN_INLINE unsigned __int64 __readcr0(void)
1256 {
1257 unsigned __int64 value;
1258 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=r" (value));
1259 return value;
1260 }
1261
1262 __INTRIN_INLINE unsigned __int64 __readcr2(void)
1263 {
1264 unsigned __int64 value;
1265 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=r" (value));
1266 return value;
1267 }
1268
1269 __INTRIN_INLINE unsigned __int64 __readcr3(void)
1270 {
1271 unsigned __int64 value;
1272 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=r" (value));
1273 return value;
1274 }
1275
1276 __INTRIN_INLINE unsigned __int64 __readcr4(void)
1277 {
1278 unsigned __int64 value;
1279 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=r" (value));
1280 return value;
1281 }
1282
1283 __INTRIN_INLINE unsigned __int64 __readcr8(void)
1284 {
1285 unsigned __int64 value;
1286 __asm__ __volatile__("movq %%cr8, %q[value]" : [value] "=r" (value));
1287 return value;
1288 }
1289 #else
1290 __INTRIN_INLINE unsigned long __readcr0(void)
1291 {
1292 unsigned long value;
1293 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=r" (value));
1294 return value;
1295 }
1296
1297 __INTRIN_INLINE unsigned long __readcr2(void)
1298 {
1299 unsigned long value;
1300 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=r" (value));
1301 return value;
1302 }
1303
1304 __INTRIN_INLINE unsigned long __readcr3(void)
1305 {
1306 unsigned long value;
1307 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=r" (value));
1308 return value;
1309 }
1310
1311 __INTRIN_INLINE unsigned long __readcr4(void)
1312 {
1313 unsigned long value;
1314 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=r" (value));
1315 return value;
1316 }
1317 #endif
1318
1319 #ifdef _M_AMD64
1320 __INTRIN_INLINE unsigned __int64 __readdr(unsigned int reg)
1321 {
1322 unsigned __int64 value;
1323 switch (reg)
1324 {
1325 case 0:
1326 __asm__ __volatile__("movq %%dr0, %q[value]" : [value] "=r" (value));
1327 break;
1328 case 1:
1329 __asm__ __volatile__("movq %%dr1, %q[value]" : [value] "=r" (value));
1330 break;
1331 case 2:
1332 __asm__ __volatile__("movq %%dr2, %q[value]" : [value] "=r" (value));
1333 break;
1334 case 3:
1335 __asm__ __volatile__("movq %%dr3, %q[value]" : [value] "=r" (value));
1336 break;
1337 case 4:
1338 __asm__ __volatile__("movq %%dr4, %q[value]" : [value] "=r" (value));
1339 break;
1340 case 5:
1341 __asm__ __volatile__("movq %%dr5, %q[value]" : [value] "=r" (value));
1342 break;
1343 case 6:
1344 __asm__ __volatile__("movq %%dr6, %q[value]" : [value] "=r" (value));
1345 break;
1346 case 7:
1347 __asm__ __volatile__("movq %%dr7, %q[value]" : [value] "=r" (value));
1348 break;
1349 }
1350 return value;
1351 }
1352
1353 __INTRIN_INLINE void __writedr(unsigned reg, unsigned __int64 value)
1354 {
1355 switch (reg)
1356 {
1357 case 0:
1358 __asm__("movq %q[value], %%dr0" : : [value] "r" (value) : "memory");
1359 break;
1360 case 1:
1361 __asm__("movq %q[value], %%dr1" : : [value] "r" (value) : "memory");
1362 break;
1363 case 2:
1364 __asm__("movq %q[value], %%dr2" : : [value] "r" (value) : "memory");
1365 break;
1366 case 3:
1367 __asm__("movq %q[value], %%dr3" : : [value] "r" (value) : "memory");
1368 break;
1369 case 4:
1370 __asm__("movq %q[value], %%dr4" : : [value] "r" (value) : "memory");
1371 break;
1372 case 5:
1373 __asm__("movq %q[value], %%dr5" : : [value] "r" (value) : "memory");
1374 break;
1375 case 6:
1376 __asm__("movq %q[value], %%dr6" : : [value] "r" (value) : "memory");
1377 break;
1378 case 7:
1379 __asm__("movq %q[value], %%dr7" : : [value] "r" (value) : "memory");
1380 break;
1381 }
1382 }
1383 #else
1384 __INTRIN_INLINE unsigned int __readdr(unsigned int reg)
1385 {
1386 unsigned int value;
1387 switch (reg)
1388 {
1389 case 0:
1390 __asm__ __volatile__("mov %%dr0, %[value]" : [value] "=r" (value));
1391 break;
1392 case 1:
1393 __asm__ __volatile__("mov %%dr1, %[value]" : [value] "=r" (value));
1394 break;
1395 case 2:
1396 __asm__ __volatile__("mov %%dr2, %[value]" : [value] "=r" (value));
1397 break;
1398 case 3:
1399 __asm__ __volatile__("mov %%dr3, %[value]" : [value] "=r" (value));
1400 break;
1401 case 4:
1402 __asm__ __volatile__("mov %%dr4, %[value]" : [value] "=r" (value));
1403 break;
1404 case 5:
1405 __asm__ __volatile__("mov %%dr5, %[value]" : [value] "=r" (value));
1406 break;
1407 case 6:
1408 __asm__ __volatile__("mov %%dr6, %[value]" : [value] "=r" (value));
1409 break;
1410 case 7:
1411 __asm__ __volatile__("mov %%dr7, %[value]" : [value] "=r" (value));
1412 break;
1413 }
1414 return value;
1415 }
1416
1417 __INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
1418 {
1419 switch (reg)
1420 {
1421 case 0:
1422 __asm__("mov %[value], %%dr0" : : [value] "r" (value) : "memory");
1423 break;
1424 case 1:
1425 __asm__("mov %[value], %%dr1" : : [value] "r" (value) : "memory");
1426 break;
1427 case 2:
1428 __asm__("mov %[value], %%dr2" : : [value] "r" (value) : "memory");
1429 break;
1430 case 3:
1431 __asm__("mov %[value], %%dr3" : : [value] "r" (value) : "memory");
1432 break;
1433 case 4:
1434 __asm__("mov %[value], %%dr4" : : [value] "r" (value) : "memory");
1435 break;
1436 case 5:
1437 __asm__("mov %[value], %%dr5" : : [value] "r" (value) : "memory");
1438 break;
1439 case 6:
1440 __asm__("mov %[value], %%dr6" : : [value] "r" (value) : "memory");
1441 break;
1442 case 7:
1443 __asm__("mov %[value], %%dr7" : : [value] "r" (value) : "memory");
1444 break;
1445 }
1446 }
1447 #endif
1448
1449 __INTRIN_INLINE void __invlpg(void * const Address)
1450 {
1451 __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))) : "memory");
1452 }
1453
1454
1455 /*** System operations ***/
1456 __INTRIN_INLINE unsigned long long __readmsr(const int reg)
1457 {
1458 #ifdef _M_AMD64
1459 unsigned long low, high;
1460 __asm__ __volatile__("rdmsr" : "=a" (low), "=d" (high) : "c" (reg));
1461 return ((unsigned long long)high << 32) | low;
1462 #else
1463 unsigned long long retval;
1464 __asm__ __volatile__("rdmsr" : "=A" (retval) : "c" (reg));
1465 return retval;
1466 #endif
1467 }
1468
1469 __INTRIN_INLINE void __writemsr(const unsigned long Register, const unsigned long long Value)
1470 {
1471 #ifdef _M_AMD64
1472 __asm__ __volatile__("wrmsr" : : "a" (Value), "d" (Value >> 32), "c" (Register));
1473 #else
1474 __asm__ __volatile__("wrmsr" : : "A" (Value), "c" (Register));
1475 #endif
1476 }
1477
1478 __INTRIN_INLINE unsigned long long __readpmc(const int counter)
1479 {
1480 unsigned long long retval;
1481 __asm__ __volatile__("rdpmc" : "=A" (retval) : "c" (counter));
1482 return retval;
1483 }
1484
1485 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
1486 __INTRIN_INLINE unsigned long __segmentlimit(const unsigned long a)
1487 {
1488 unsigned long retval;
1489 __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a));
1490 return retval;
1491 }
1492
1493 __INTRIN_INLINE void __wbinvd(void)
1494 {
1495 __asm__ __volatile__("wbinvd" : : : "memory");
1496 }
1497
1498 __INTRIN_INLINE void __lidt(void *Source)
1499 {
1500 __asm__ __volatile__("lidt %0" : : "m"(*(short*)Source));
1501 }
1502
1503 __INTRIN_INLINE void __sidt(void *Destination)
1504 {
1505 __asm__ __volatile__("sidt %0" : : "m"(*(short*)Destination) : "memory");
1506 }
1507
1508 /*** Misc operations ***/
1509
1510 __INTRIN_INLINE void _mm_pause(void)
1511 {
1512 __asm__ __volatile__("pause" : : : "memory");
1513 }
1514
1515 __INTRIN_INLINE void __nop(void)
1516 {
1517 __asm__ __volatile__("nop");
1518 }
1519
1520 #ifdef __cplusplus
1521 }
1522 #endif
1523
1524 #endif /* KJK_INTRIN_X86_H_ */
1525
1526 /* EOF */