Use "C" interface for intrinsic functions to avoid problems with C++. Fix _rotr and...
[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
78 /*** Atomic operations ***/
79
80 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
81 #define _ReadWriteBarrier() __sync_synchronize()
82 #else
83 static void __inline__ __attribute__((always_inline)) _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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd16(volatile short * const Addend, const short Value)
140 {
141 return __sync_fetch_and_add(Addend, Value);
142 }
143
144 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)
157 {
158 return __sync_fetch_and_and(value, mask);
159 }
160
161 static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)
162 {
163 return __sync_fetch_and_and(value, mask);
164 }
165
166 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)
179 {
180 return __sync_fetch_and_or(value, mask);
181 }
182
183 static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)
184 {
185 return __sync_fetch_and_or(value, mask);
186 }
187
188 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)
201 {
202 return __sync_fetch_and_xor(value, mask);
203 }
204
205 static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)
206 {
207 return __sync_fetch_and_xor(value, mask);
208 }
209
210 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_inline)) long _InterlockedDecrement(volatile long * const lpAddend)
473 {
474 return _InterlockedExchangeAdd(lpAddend, -1) - 1;
475 }
476
477 static __inline__ __attribute__((always_inline)) long _InterlockedIncrement(volatile long * const lpAddend)
478 {
479 return _InterlockedExchangeAdd(lpAddend, 1) + 1;
480 }
481
482 static __inline__ __attribute__((always_inline)) long _InterlockedDecrement16(volatile short * const lpAddend)
483 {
484 return _InterlockedExchangeAdd16(lpAddend, -1) - 1;
485 }
486
487 static __inline__ __attribute__((always_inline)) long _InterlockedIncrement16(volatile short * const lpAddend)
488 {
489 return _InterlockedExchangeAdd16(lpAddend, 1) + 1;
490 }
491
492 #if defined(_M_AMD64)
493 static __inline__ __attribute__((always_inline)) long long _InterlockedDecrement64(volatile long long * const lpAddend)
494 {
495 return _InterlockedExchangeAdd64(lpAddend, -1) - 1;
496 }
497
498 static __inline__ __attribute__((always_inline)) long long _InterlockedIncrement64(volatile long long * const lpAddend)
499 {
500 return _InterlockedExchangeAdd64(lpAddend, 1) + 1;
501 }
502 #endif
503
504 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
604 }
605
606 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
609 }
610
611 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
614 }
615
616 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
619 }
620
621 static __inline__ __attribute__((always_inline)) unsigned char __readgsbyte(const unsigned long Offset)
622 {
623 unsigned char value;
624 __asm__ __volatile__("movb %%gs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
625 return value;
626 }
627
628 static __inline__ __attribute__((always_inline)) unsigned short __readgsword(const unsigned long Offset)
629 {
630 unsigned short value;
631 __asm__ __volatile__("movw %%gs:%a[Offset], %w[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
632 return value;
633 }
634
635 static __inline__ __attribute__((always_inline)) unsigned long __readgsdword(const unsigned long Offset)
636 {
637 unsigned long value;
638 __asm__ __volatile__("movl %%gs:%a[Offset], %k[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
639 return value;
640 }
641
642 static __inline__ __attribute__((always_inline)) unsigned __int64 __readgsqword(const unsigned long Offset)
643 {
644 unsigned __int64 value;
645 __asm__ __volatile__("movq %%gs:%a[Offset], %q[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
646 return value;
647 }
648
649 static __inline__ __attribute__((always_inline)) void __incgsbyte(const unsigned long Offset)
650 {
651 __asm__ __volatile__("incb %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
652 }
653
654 static __inline__ __attribute__((always_inline)) void __incgsword(const unsigned long Offset)
655 {
656 __asm__ __volatile__("incw %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
657 }
658
659 static __inline__ __attribute__((always_inline)) void __incgsdword(const unsigned long Offset)
660 {
661 __asm__ __volatile__("incl %%gs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
662 }
663
664 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
667 }
668
669 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
672 }
673
674 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
677 }
678
679 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
682 }
683
684 #else
685 /*** FS segment addressing ***/
686 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
694 }
695
696 static __inline__ __attribute__((always_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] "iq" (Data) : "memory");
699 }
700
701 static __inline__ __attribute__((always_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] "irm" (Offset) : "memory");
705 return value;
706 }
707
708 static __inline__ __attribute__((always_inline)) unsigned short __readfsword(const unsigned long Offset)
709 {
710 unsigned short value;
711 __asm__ __volatile__("movw %%fs:%a[Offset], %w[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
712 return value;
713 }
714
715 static __inline__ __attribute__((always_inline)) unsigned long __readfsdword(const unsigned long Offset)
716 {
717 unsigned long value;
718 __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
719 return value;
720 }
721
722 static __inline__ __attribute__((always_inline)) void __incfsbyte(const unsigned long Offset)
723 {
724 __asm__ __volatile__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
725 }
726
727 static __inline__ __attribute__((always_inline)) void __incfsword(const unsigned long Offset)
728 {
729 __asm__ __volatile__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset) : "memory");
730 }
731
732 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_inline)) void __addfsbyte(const unsigned long Offset, const unsigned char Data)
739 {
740 if(!__builtin_constant_p(Offset))
741 __asm__ __volatile__("addb %k[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 static __inline__ __attribute__((always_inline)) void __addfsword(const unsigned long Offset, const unsigned short Data)
747 {
748 if(!__builtin_constant_p(Offset))
749 __asm__ __volatile__("addw %k[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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 static __inline__ __attribute__((always_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 #ifndef __MSVCRT__
841 static __inline__ __attribute__((always_inline)) unsigned int _rotl(unsigned int value, int shift)
842 {
843 unsigned long retval;
844 __asm__("roll %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
845 return retval;
846 }
847
848 static __inline__ __attribute__((always_inline)) unsigned int _rotr(unsigned int value, int shift)
849 {
850 unsigned long retval;
851 __asm__("rorl %b[shift], %k[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
852 return retval;
853 }
854 #endif
855
856 static __inline__ __attribute__((always_inline)) unsigned char _rotr8(unsigned char value, unsigned char shift)
857 {
858 unsigned char retval;
859 __asm__("rorb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
860 return retval;
861 }
862
863 static __inline__ __attribute__((always_inline)) unsigned short _rotr16(unsigned short value, unsigned char shift)
864 {
865 unsigned short retval;
866 __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
867 return retval;
868 }
869
870 /*
871 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
872 constraint (edx:eax) for the Mask argument, because it's the only way GCC
873 can pass 64-bit operands around - passing the two 32 bit parts separately
874 just confuses it. Also we declare Bit as an int and then truncate it to
875 match Visual C++ behavior
876 */
877 static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, const int Bit)
878 {
879 unsigned long long retval = Mask;
880
881 __asm__
882 (
883 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
884 "+A" (retval) :
885 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
886 );
887
888 return retval;
889 }
890
891 static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit)
892 {
893 unsigned long long retval = Mask;
894
895 __asm__
896 (
897 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
898 "+A" (retval) :
899 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
900 );
901
902 return retval;
903 }
904
905 static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)
906 {
907 unsigned long long retval = Mask;
908
909 __asm__
910 (
911 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
912 "+A" (retval) :
913 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
914 );
915
916 return retval;
917 }
918
919 static __inline__ __attribute__((always_inline)) unsigned short _byteswap_ushort(unsigned short value)
920 {
921 unsigned short retval;
922 __asm__("rorw $8, %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
923 return retval;
924 }
925
926 static __inline__ __attribute__((always_inline)) unsigned long _byteswap_ulong(unsigned long value)
927 {
928 unsigned long retval;
929 __asm__("bswapl %[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
930 return retval;
931 }
932
933 #ifdef _M_AMD64
934 static __inline__ __attribute__((always_inline)) unsigned __int64 _byteswap_uint64(unsigned __int64 value)
935 {
936 unsigned __int64 retval;
937 __asm__("bswapq %[retval]" : [retval] "=rm" (retval) : "[retval]" (value));
938 return retval;
939 }
940 #else
941 static __inline__ __attribute__((always_inline)) unsigned __int64 _byteswap_uint64(unsigned __int64 value)
942 {
943 union {
944 __int64 int64part;
945 struct {
946 unsigned long lowpart;
947 unsigned long hipart;
948 };
949 } retval;
950 retval.int64part = value;
951 __asm__("bswapl %[lowpart]\n"
952 "bswapl %[hipart]\n"
953 : [lowpart] "=rm" (retval.hipart), [hipart] "=rm" (retval.lowpart) : "[lowpart]" (retval.lowpart), "[hipart]" (retval.hipart) );
954 return retval.int64part;
955 }
956 #endif
957
958 /*** 64-bit math ***/
959 static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b)
960 {
961 long long retval;
962 __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
963 return retval;
964 }
965
966 static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b)
967 {
968 unsigned long long retval;
969 __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
970 return retval;
971 }
972
973
974 /*** Port I/O ***/
975 static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port)
976 {
977 unsigned char byte;
978 __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port));
979 return byte;
980 }
981
982 static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port)
983 {
984 unsigned short word;
985 __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port));
986 return word;
987 }
988
989 static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port)
990 {
991 unsigned long dword;
992 __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port));
993 return dword;
994 }
995
996 static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)
997 {
998 __asm__ __volatile__
999 (
1000 "rep; insb" :
1001 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1002 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1003 "memory"
1004 );
1005 }
1006
1007 static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)
1008 {
1009 __asm__ __volatile__
1010 (
1011 "rep; insw" :
1012 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1013 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1014 "memory"
1015 );
1016 }
1017
1018 static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)
1019 {
1020 __asm__ __volatile__
1021 (
1022 "rep; insl" :
1023 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
1024 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
1025 "memory"
1026 );
1027 }
1028
1029 static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data)
1030 {
1031 __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1032 }
1033
1034 static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data)
1035 {
1036 __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1037 }
1038
1039 static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data)
1040 {
1041 __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
1042 }
1043
1044 static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)
1045 {
1046 __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1047 }
1048
1049 static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)
1050 {
1051 __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1052 }
1053
1054 static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)
1055 {
1056 __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
1057 }
1058
1059
1060 /*** System information ***/
1061 static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)
1062 {
1063 __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType));
1064 }
1065
1066 static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void)
1067 {
1068 #ifdef _M_AMD64
1069 unsigned long long low, high;
1070 __asm__ __volatile__("rdtsc" : "=a"(low), "=d"(high));
1071 return low | (high << 32);
1072 #else
1073 unsigned long long retval;
1074 __asm__ __volatile__("rdtsc" : "=A"(retval));
1075 return retval;
1076 #endif
1077 }
1078
1079 static __inline__ __attribute__((always_inline)) void __writeeflags(uintptr_t Value)
1080 {
1081 __asm__ __volatile__("push %0\n popf" : : "rim"(Value));
1082 }
1083
1084 static __inline__ __attribute__((always_inline)) uintptr_t __readeflags(void)
1085 {
1086 uintptr_t retval;
1087 __asm__ __volatile__("pushf\n pop %0" : "=rm"(retval));
1088 return retval;
1089 }
1090
1091 /*** Interrupts ***/
1092 static __inline__ __attribute__((always_inline)) void __debugbreak(void)
1093 {
1094 __asm__("int $3");
1095 }
1096
1097 static __inline__ __attribute__((always_inline)) void __int2c(void)
1098 {
1099 __asm__("int $0x2c");
1100 }
1101
1102 static __inline__ __attribute__((always_inline)) void _disable(void)
1103 {
1104 __asm__("cli");
1105 }
1106
1107 static __inline__ __attribute__((always_inline)) void _enable(void)
1108 {
1109 __asm__("sti");
1110 }
1111
1112
1113 /*** Protected memory management ***/
1114
1115 static __inline__ __attribute__((always_inline)) void __writecr0(const unsigned __int64 Data)
1116 {
1117 __asm__("mov %[Data], %%cr0" : : [Data] "q" (Data) : "memory");
1118 }
1119
1120 static __inline__ __attribute__((always_inline)) void __writecr3(const unsigned __int64 Data)
1121 {
1122 __asm__("mov %[Data], %%cr3" : : [Data] "q" (Data) : "memory");
1123 }
1124
1125 static __inline__ __attribute__((always_inline)) void __writecr4(const unsigned __int64 Data)
1126 {
1127 __asm__("mov %[Data], %%cr4" : : [Data] "q" (Data) : "memory");
1128 }
1129
1130 #ifdef _M_AMD64
1131 static __inline__ __attribute__((always_inline)) void __writecr8(const unsigned __int64 Data)
1132 {
1133 __asm__("mov %[Data], %%cr8" : : [Data] "q" (Data) : "memory");
1134 }
1135 #endif
1136
1137 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr0(void)
1138 {
1139 unsigned __int64 value;
1140 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=q" (value));
1141 return value;
1142 }
1143
1144 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr2(void)
1145 {
1146 unsigned __int64 value;
1147 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=q" (value));
1148 return value;
1149 }
1150
1151 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr3(void)
1152 {
1153 unsigned __int64 value;
1154 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=q" (value));
1155 return value;
1156 }
1157
1158 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr4(void)
1159 {
1160 unsigned __int64 value;
1161 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=q" (value));
1162 return value;
1163 }
1164
1165 #ifdef _M_AMD64
1166 static __inline__ __attribute__((always_inline)) unsigned __int64 __readcr8(void)
1167 {
1168 unsigned __int64 value;
1169 __asm__ __volatile__("movq %%cr8, %q[value]" : [value] "=q" (value));
1170 return value;
1171 }
1172 #endif
1173
1174 #ifdef _M_AMD64
1175 static __inline__ __attribute__((always_inline)) unsigned __int64 __readdr(unsigned int reg)
1176 {
1177 unsigned __int64 value;
1178 switch (reg)
1179 {
1180 case 0:
1181 __asm__ __volatile__("movq %%dr0, %q[value]" : [value] "=q" (value));
1182 break;
1183 case 1:
1184 __asm__ __volatile__("movq %%dr1, %q[value]" : [value] "=q" (value));
1185 break;
1186 case 2:
1187 __asm__ __volatile__("movq %%dr2, %q[value]" : [value] "=q" (value));
1188 break;
1189 case 3:
1190 __asm__ __volatile__("movq %%dr3, %q[value]" : [value] "=q" (value));
1191 break;
1192 case 4:
1193 __asm__ __volatile__("movq %%dr4, %q[value]" : [value] "=q" (value));
1194 break;
1195 case 5:
1196 __asm__ __volatile__("movq %%dr5, %q[value]" : [value] "=q" (value));
1197 break;
1198 case 6:
1199 __asm__ __volatile__("movq %%dr6, %q[value]" : [value] "=q" (value));
1200 break;
1201 case 7:
1202 __asm__ __volatile__("movq %%dr7, %q[value]" : [value] "=q" (value));
1203 break;
1204 }
1205 return value;
1206 }
1207
1208 static __inline__ __attribute__((always_inline)) void __writedr(unsigned reg, unsigned __int64 value)
1209 {
1210 switch (reg)
1211 {
1212 case 0:
1213 __asm__("movq %q[value], %%dr0" : : [value] "q" (value) : "memory");
1214 break;
1215 case 1:
1216 __asm__("movq %q[value], %%dr1" : : [value] "q" (value) : "memory");
1217 break;
1218 case 2:
1219 __asm__("movq %q[value], %%dr2" : : [value] "q" (value) : "memory");
1220 break;
1221 case 3:
1222 __asm__("movq %q[value], %%dr3" : : [value] "q" (value) : "memory");
1223 break;
1224 case 4:
1225 __asm__("movq %q[value], %%dr4" : : [value] "q" (value) : "memory");
1226 break;
1227 case 5:
1228 __asm__("movq %q[value], %%dr5" : : [value] "q" (value) : "memory");
1229 break;
1230 case 6:
1231 __asm__("movq %q[value], %%dr6" : : [value] "q" (value) : "memory");
1232 break;
1233 case 7:
1234 __asm__("movq %q[value], %%dr7" : : [value] "q" (value) : "memory");
1235 break;
1236 }
1237 }
1238 #endif
1239
1240 static __inline__ __attribute__((always_inline)) void __invlpg(void * const Address)
1241 {
1242 __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))));
1243 }
1244
1245
1246 /*** System operations ***/
1247 static __inline__ __attribute__((always_inline)) unsigned long long __readmsr(const int reg)
1248 {
1249 #ifdef _M_AMD64
1250 unsigned long low, high;
1251 __asm__ __volatile__("rdmsr" : "=a" (low), "=d" (high) : "c" (reg));
1252 return ((unsigned long long)high << 32) | low;
1253 #else
1254 unsigned long long retval;
1255 __asm__ __volatile__("rdmsr" : "=A" (retval) : "c" (reg));
1256 return retval;
1257 #endif
1258 }
1259
1260 static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Register, const unsigned long long Value)
1261 {
1262 #ifdef _M_AMD64
1263 __asm__ __volatile__("wrmsr" : : "a" (Value), "d" (Value >> 32), "c" (Register));
1264 #else
1265 __asm__ __volatile__("wrmsr" : : "A" (Value), "c" (Register));
1266 #endif
1267 }
1268
1269 static __inline__ __attribute__((always_inline)) unsigned long long __readpmc(const int counter)
1270 {
1271 unsigned long long retval;
1272 __asm__ __volatile__("rdpmc" : "=A" (retval) : "c" (counter));
1273 return retval;
1274 }
1275
1276 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
1277 static __inline__ __attribute__((always_inline)) unsigned long __segmentlimit(const unsigned long a)
1278 {
1279 unsigned long retval;
1280 __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a));
1281 return retval;
1282 }
1283
1284 static __inline__ __attribute__((always_inline)) void __wbinvd(void)
1285 {
1286 __asm__ __volatile__("wbinvd");
1287 }
1288
1289 static __inline__ __attribute__((always_inline)) void __lidt(void *Source)
1290 {
1291 __asm__ __volatile__("lidt %0" : : "m"(*(short*)Source));
1292 }
1293
1294 static __inline__ __attribute__((always_inline)) void __sidt(void *Destination)
1295 {
1296 __asm__ __volatile__("sidt %0" : : "m"(*(short*)Destination) : "memory");
1297 }
1298
1299 #ifdef __cplusplus
1300 }
1301 #endif
1302
1303 #endif /* KJK_INTRIN_X86_H_ */
1304
1305 /* EOF */