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