/[pcsx2_0.9.7]/trunk/common/include/intrin_x86.h
ViewVC logotype

Contents of /trunk/common/include/intrin_x86.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 10 months ago) by william
File MIME type: text/plain
File size: 31124 byte(s)
exported r3113 from ./upstream/trunk
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
69 #ifndef __SIZE_T
70 #define __SIZE_T
71 typedef unsigned int size_t;
72 #endif
73
74 /*** Stack frame juggling ***/
75 #define _ReturnAddress() (__builtin_return_address(0))
76 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))
77 /* TODO: __getcallerseflags but how??? */
78
79
80 /*** Atomic operations ***/
81
82 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
83 #define _ReadWriteBarrier() __sync_synchronize()
84 #else
85 static void __inline__ __attribute__((always_inline)) _MemoryBarrier(void)
86 {
87 __asm__ __volatile__("" : : : "memory");
88 }
89 #define _ReadWriteBarrier() _MemoryBarrier()
90 #endif
91
92 /* BUGBUG: GCC only supports full barriers */
93 #define _ReadBarrier _ReadWriteBarrier
94 #define _WriteBarrier _ReadWriteBarrier
95
96 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
97
98 static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
99 {
100 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
101 }
102
103 static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
104 {
105 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
106 }
107
108 static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
109 {
110 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
111 }
112
113 static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
114 {
115 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
116 }
117
118 static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
119 {
120 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
121 }
122
123 static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)
124 {
125 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
126 __sync_synchronize();
127 return __sync_lock_test_and_set(Target, Value);
128 }
129
130 static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
131 {
132 /* NOTE: ditto */
133 __sync_synchronize();
134 return __sync_lock_test_and_set(Target, Value);
135 }
136
137 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
138 {
139 return __sync_fetch_and_add(Addend, Value);
140 }
141
142 static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)
143 {
144 return __sync_fetch_and_and(value, mask);
145 }
146
147 static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)
148 {
149 return __sync_fetch_and_and(value, mask);
150 }
151
152 static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)
153 {
154 return __sync_fetch_and_and(value, mask);
155 }
156
157 static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)
158 {
159 return __sync_fetch_and_or(value, mask);
160 }
161
162 static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)
163 {
164 return __sync_fetch_and_or(value, mask);
165 }
166
167 static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)
168 {
169 return __sync_fetch_and_or(value, mask);
170 }
171
172 static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)
173 {
174 return __sync_fetch_and_xor(value, mask);
175 }
176
177 static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)
178 {
179 return __sync_fetch_and_xor(value, mask);
180 }
181
182 static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)
183 {
184 return __sync_fetch_and_xor(value, mask);
185 }
186
187 #else
188
189 static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
190 {
191 char retval = Comperand;
192 __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
193 return retval;
194 }
195
196 static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
197 {
198 short retval = Comperand;
199 __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
200 return retval;
201 }
202
203 static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
204 {
205 long retval = Comperand;
206 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "+a" (retval) : [Destination] "m" (*Destination), [Exchange] "q" (Exchange): "memory");
207 return retval;
208 }
209
210 static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
211 {
212 long long retval = Comperand;
213
214 __asm__
215 (
216 "cmpxchg8b %[Destination]" :
217 [retval] "+A" (retval) :
218 [Destination] "m" (*Destination),
219 "b" ((unsigned long)((Exchange >> 0) & 0xFFFFFFFF)),
220 "c" ((unsigned long)((Exchange >> 32) & 0xFFFFFFFF)) :
221 "memory"
222 );
223
224 return retval;
225 }
226
227 static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
228 {
229 void * retval = (void *)Comperand;
230 __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : [retval] "=a" (retval) : "[retval]" (retval), [Destination] "m" (*Destination), [Exchange] "q" (Exchange) : "memory");
231 return retval;
232 }
233
234 static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)
235 {
236 long retval = Value;
237 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
238 return retval;
239 }
240
241 static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
242 {
243 void * retval = Value;
244 __asm__("xchgl %[retval], %[Target]" : [retval] "+r" (retval) : [Target] "m" (*Target) : "memory");
245 return retval;
246 }
247
248 static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
249 {
250 long retval = Value;
251 __asm__("lock; xaddl %[retval], %[Addend]" : [retval] "+r" (retval) : [Addend] "m" (*Addend) : "memory");
252 return retval;
253 }
254
255 static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)
256 {
257 char x;
258 char y;
259
260 y = *value;
261
262 do
263 {
264 x = y;
265 y = _InterlockedCompareExchange8(value, x & mask, x);
266 }
267 while(y != x);
268
269 return y;
270 }
271
272 static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)
273 {
274 short x;
275 short y;
276
277 y = *value;
278
279 do
280 {
281 x = y;
282 y = _InterlockedCompareExchange16(value, x & mask, x);
283 }
284 while(y != x);
285
286 return y;
287 }
288
289 static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)
290 {
291 long x;
292 long y;
293
294 y = *value;
295
296 do
297 {
298 x = y;
299 y = _InterlockedCompareExchange(value, x & mask, x);
300 }
301 while(y != x);
302
303 return y;
304 }
305
306 static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)
307 {
308 char x;
309 char y;
310
311 y = *value;
312
313 do
314 {
315 x = y;
316 y = _InterlockedCompareExchange8(value, x | mask, x);
317 }
318 while(y != x);
319
320 return y;
321 }
322
323 static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)
324 {
325 short x;
326 short y;
327
328 y = *value;
329
330 do
331 {
332 x = y;
333 y = _InterlockedCompareExchange16(value, x | mask, x);
334 }
335 while(y != x);
336
337 return y;
338 }
339
340 static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)
341 {
342 long x;
343 long y;
344
345 y = *value;
346
347 do
348 {
349 x = y;
350 y = _InterlockedCompareExchange(value, x | mask, x);
351 }
352 while(y != x);
353
354 return y;
355 }
356
357 static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)
358 {
359 char x;
360 char y;
361
362 y = *value;
363
364 do
365 {
366 x = y;
367 y = _InterlockedCompareExchange8(value, x ^ mask, x);
368 }
369 while(y != x);
370
371 return y;
372 }
373
374 static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)
375 {
376 short x;
377 short y;
378
379 y = *value;
380
381 do
382 {
383 x = y;
384 y = _InterlockedCompareExchange16(value, x ^ mask, x);
385 }
386 while(y != x);
387
388 return y;
389 }
390
391 static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)
392 {
393 long x;
394 long y;
395
396 y = *value;
397
398 do
399 {
400 x = y;
401 y = _InterlockedCompareExchange(value, x ^ mask, x);
402 }
403 while(y != x);
404
405 return y;
406 }
407
408 #endif
409
410 static __inline__ __attribute__((always_inline)) long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)
411 {
412 __asm__
413 (
414 "lock; add %[Value], %[Lo32];"
415 "jae LABEL%=;"
416 "lock; adc $0, %[Hi32];"
417 "LABEL%=:;" :
418 [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) :
419 [Value] "ir" (Value)
420 );
421
422 return Value;
423 }
424
425 static __inline__ __attribute__((always_inline)) long _InterlockedDecrement(volatile long * const lpAddend)
426 {
427 return _InterlockedExchangeAdd(lpAddend, -1) - 1;
428 }
429
430 static __inline__ __attribute__((always_inline)) long _InterlockedIncrement(volatile long * const lpAddend)
431 {
432 return _InterlockedExchangeAdd(lpAddend, 1) + 1;
433 }
434
435 static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset(volatile long * a, const long b)
436 {
437 unsigned char retval;
438 __asm__("lock; btrl %[b], %[a]; setb %b[retval]" : [retval] "=r" (retval), [a] "=m" (a) : [b] "Ir" (b) : "memory");
439 return retval;
440 }
441
442 static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandset(volatile long * a, const long b)
443 {
444 unsigned char retval;
445 __asm__("lock; btsl %[b], %[a]; setc %b[retval]" : [retval] "=r" (retval), [a] "=m" (a) : [b] "Ir" (b) : "memory");
446 return retval;
447 }
448
449
450 /*** String operations ***/
451 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
452 static __inline__ __attribute__((always_inline)) void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)
453 {
454 __asm__ __volatile__
455 (
456 "rep; stosb" :
457 [Dest] "=D" (Dest), [Count] "=c" (Count) :
458 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
459 );
460 }
461
462 static __inline__ __attribute__((always_inline)) void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)
463 {
464 __asm__ __volatile__
465 (
466 "rep; stosw" :
467 [Dest] "=D" (Dest), [Count] "=c" (Count) :
468 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
469 );
470 }
471
472 static __inline__ __attribute__((always_inline)) void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)
473 {
474 __asm__ __volatile__
475 (
476 "rep; stosl" :
477 [Dest] "=D" (Dest), [Count] "=c" (Count) :
478 "[Dest]" (Dest), "a" (Data), "[Count]" (Count)
479 );
480 }
481
482 static __inline__ __attribute__((always_inline)) void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)
483 {
484 __asm__ __volatile__
485 (
486 "rep; movsb" :
487 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
488 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
489 );
490 }
491
492 static __inline__ __attribute__((always_inline)) void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)
493 {
494 __asm__ __volatile__
495 (
496 "rep; movsw" :
497 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
498 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
499 );
500 }
501
502 static __inline__ __attribute__((always_inline)) void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)
503 {
504 __asm__ __volatile__
505 (
506 "rep; movsd" :
507 [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
508 "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
509 );
510 }
511
512
513 /*** FS segment addressing ***/
514 static __inline__ __attribute__((always_inline)) void __writefsbyte(const unsigned long Offset, const unsigned char Data)
515 {
516 __asm__("movb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));
517 }
518
519 static __inline__ __attribute__((always_inline)) void __writefsword(const unsigned long Offset, const unsigned short Data)
520 {
521 __asm__("movw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));
522 }
523
524 static __inline__ __attribute__((always_inline)) void __writefsdword(const unsigned long Offset, const unsigned long Data)
525 {
526 __asm__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));
527 }
528
529 static __inline__ __attribute__((always_inline)) unsigned char __readfsbyte(const unsigned long Offset)
530 {
531 unsigned char value;
532 __asm__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
533 return value;
534 }
535
536 static __inline__ __attribute__((always_inline)) unsigned short __readfsword(const unsigned long Offset)
537 {
538 unsigned short value;
539 __asm__("movw %%fs:%a[Offset], %w[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
540 return value;
541 }
542
543 static __inline__ __attribute__((always_inline)) unsigned long __readfsdword(const unsigned long Offset)
544 {
545 unsigned long value;
546 __asm__("movl %%fs:%a[Offset], %k[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));
547 return value;
548 }
549
550 static __inline__ __attribute__((always_inline)) void __incfsbyte(const unsigned long Offset)
551 {
552 __asm__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset));
553 }
554
555 static __inline__ __attribute__((always_inline)) void __incfsword(const unsigned long Offset)
556 {
557 __asm__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset));
558 }
559
560 static __inline__ __attribute__((always_inline)) void __incfsdword(const unsigned long Offset)
561 {
562 __asm__("incl %%fs:%a[Offset]" : : [Offset] "ir" (Offset));
563 }
564
565 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
566 static __inline__ __attribute__((always_inline)) void __addfsbyte(const unsigned long Offset, const unsigned char Data)
567 {
568 if(!__builtin_constant_p(Offset))
569 __asm__("addb %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset));
570 else
571 __asm__("addb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));
572 }
573
574 static __inline__ __attribute__((always_inline)) void __addfsword(const unsigned long Offset, const unsigned short Data)
575 {
576 if(!__builtin_constant_p(Offset))
577 __asm__("addw %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset));
578 else
579 __asm__("addw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));
580 }
581
582 static __inline__ __attribute__((always_inline)) void __addfsdword(const unsigned long Offset, const unsigned int Data)
583 {
584 if(!__builtin_constant_p(Offset))
585 __asm__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset));
586 else
587 __asm__("addl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));
588 }
589
590
591 /*** Bit manipulation ***/
592 static __inline__ __attribute__((always_inline)) unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)
593 {
594 __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
595 return Mask ? 1 : 0;
596 }
597
598 static __inline__ __attribute__((always_inline)) unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)
599 {
600 __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));
601 return Mask ? 1 : 0;
602 }
603
604 /* NOTE: again, the bizarre implementation follows Visual C++ */
605 static __inline__ __attribute__((always_inline)) unsigned char _bittest(const long * const a, const long b)
606 {
607 unsigned char retval;
608
609 if(__builtin_constant_p(b))
610 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
611 else
612 __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
613
614 return retval;
615 }
616
617 static __inline__ __attribute__((always_inline)) unsigned char _bittestandcomplement(long * const a, const long b)
618 {
619 unsigned char retval;
620
621 if(__builtin_constant_p(b))
622 __asm__("btc %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
623 else
624 __asm__("btc %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
625
626 return retval;
627 }
628
629 static __inline__ __attribute__((always_inline)) unsigned char _bittestandreset(long * const a, const long b)
630 {
631 unsigned char retval;
632
633 if(__builtin_constant_p(b))
634 __asm__("btr %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
635 else
636 __asm__("btr %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
637
638 return retval;
639 }
640
641 static __inline__ __attribute__((always_inline)) unsigned char _bittestandset(long * const a, const long b)
642 {
643 unsigned char retval;
644
645 if(__builtin_constant_p(b))
646 __asm__("bts %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));
647 else
648 __asm__("bts %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));
649
650 return retval;
651 }
652
653 static __inline__ __attribute__((always_inline)) unsigned char _rotl8(const unsigned char value, const unsigned char shift)
654 {
655 unsigned char retval;
656 __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
657 return retval;
658 }
659
660 static __inline__ __attribute__((always_inline)) unsigned short _rotl16(const unsigned short value, const unsigned char shift)
661 {
662 unsigned short retval;
663 __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
664 return retval;
665 }
666
667 static __inline__ __attribute__((always_inline)) unsigned char _rotr8(const unsigned char value, const unsigned char shift)
668 {
669 unsigned char retval;
670 __asm__("rorb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
671 return retval;
672 }
673
674 static __inline__ __attribute__((always_inline)) unsigned short _rotr16(const unsigned short value, const unsigned char shift)
675 {
676 unsigned short retval;
677 __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));
678 return retval;
679 }
680
681 /*
682 NOTE: in __ll_lshift, __ll_rshift and __ull_rshift we use the "A"
683 constraint (edx:eax) for the Mask argument, because it's the only way GCC
684 can pass 64-bit operands around - passing the two 32 bit parts separately
685 just confuses it. Also we declare Bit as an int and then truncate it to
686 match Visual C++ behavior
687 */
688 static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, const int Bit)
689 {
690 unsigned long long retval = Mask;
691
692 __asm__
693 (
694 "shldl %b[Bit], %%eax, %%edx; sall %b[Bit], %%eax" :
695 "+A" (retval) :
696 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
697 );
698
699 return retval;
700 }
701
702 static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit)
703 {
704 unsigned long long retval = Mask;
705
706 __asm__
707 (
708 "shldl %b[Bit], %%eax, %%edx; sarl %b[Bit], %%eax" :
709 "+A" (retval) :
710 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
711 );
712
713 return retval;
714 }
715
716 static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)
717 {
718 unsigned long long retval = Mask;
719
720 __asm__
721 (
722 "shrdl %b[Bit], %%eax, %%edx; shrl %b[Bit], %%eax" :
723 "+A" (retval) :
724 [Bit] "Nc" ((unsigned char)((unsigned long)Bit) & 0xFF)
725 );
726
727 return retval;
728 }
729
730
731 /*** 64-bit math ***/
732 static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b)
733 {
734 long long retval;
735 __asm__("imull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
736 return retval;
737 }
738
739 static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b)
740 {
741 unsigned long long retval;
742 __asm__("mull %[b]" : "=A" (retval) : [a] "a" (a), [b] "rm" (b));
743 return retval;
744 }
745
746
747 /*** Port I/O ***/
748 static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port)
749 {
750 unsigned char byte;
751 __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port));
752 return byte;
753 }
754
755 static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port)
756 {
757 unsigned short word;
758 __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port));
759 return word;
760 }
761
762 static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port)
763 {
764 unsigned long dword;
765 __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port));
766 return dword;
767 }
768
769 static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)
770 {
771 __asm__ __volatile__
772 (
773 "rep; insb" :
774 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
775 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
776 "memory"
777 );
778 }
779
780 static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)
781 {
782 __asm__ __volatile__
783 (
784 "rep; insw" :
785 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
786 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
787 "memory"
788 );
789 }
790
791 static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)
792 {
793 __asm__ __volatile__
794 (
795 "rep; insl" :
796 [Buffer] "=D" (Buffer), [Count] "=c" (Count) :
797 "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :
798 "memory"
799 );
800 }
801
802 static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data)
803 {
804 __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
805 }
806
807 static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data)
808 {
809 __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
810 }
811
812 static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data)
813 {
814 __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));
815 }
816
817 static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)
818 {
819 __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
820 }
821
822 static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)
823 {
824 __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
825 }
826
827 static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)
828 {
829 __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));
830 }
831
832
833 /*** System information ***/
834 static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)
835 {
836 __asm__ __volatile__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType));
837 }
838
839 static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void)
840 {
841 unsigned long long retval;
842 __asm__ __volatile__("rdtsc" : "=A"(retval));
843 return retval;
844 }
845
846
847 /*** Interrupts ***/
848 static __inline__ __attribute__((always_inline)) void __debugbreak(void)
849 {
850 __asm__("int $3");
851 }
852
853 static __inline__ __attribute__((always_inline)) void __int2c(void)
854 {
855 __asm__("int $0x2c");
856 }
857
858 static __inline__ __attribute__((always_inline)) void _disable(void)
859 {
860 __asm__("cli");
861 }
862
863 static __inline__ __attribute__((always_inline)) void _enable(void)
864 {
865 __asm__("sti");
866 }
867
868
869 /*** Protected memory management ***/
870 static __inline__ __attribute__((always_inline)) unsigned long __readcr0(void)
871 {
872 unsigned long value;
873 __asm__ __volatile__("mov %%cr0, %[value]" : [value] "=q" (value));
874 return value;
875 }
876
877 static __inline__ __attribute__((always_inline)) unsigned long __readcr2(void)
878 {
879 unsigned long value;
880 __asm__ __volatile__("mov %%cr2, %[value]" : [value] "=q" (value));
881 return value;
882 }
883
884 static __inline__ __attribute__((always_inline)) unsigned long __readcr3(void)
885 {
886 unsigned long value;
887 __asm__ __volatile__("mov %%cr3, %[value]" : [value] "=q" (value));
888 return value;
889 }
890
891 static __inline__ __attribute__((always_inline)) unsigned long __readcr4(void)
892 {
893 unsigned long value;
894 __asm__ __volatile__("mov %%cr4, %[value]" : [value] "=q" (value));
895 return value;
896 }
897
898 static __inline__ __attribute__((always_inline)) void __writecr0(const unsigned long long Data)
899 {
900 __asm__("mov %[Data], %%cr0" : : [Data] "q" ((const unsigned long)(Data & 0xFFFFFFFF)) : "memory");
901 }
902
903 static __inline__ __attribute__((always_inline)) void __writecr3(const unsigned long long Data)
904 {
905 __asm__("mov %[Data], %%cr3" : : [Data] "q" ((const unsigned long)(Data & 0xFFFFFFFF)) : "memory");
906 }
907
908 static __inline__ __attribute__((always_inline)) void __writecr4(const unsigned long long Data)
909 {
910 __asm__("mov %[Data], %%cr4" : : [Data] "q" ((const unsigned long)(Data & 0xFFFFFFFF)) : "memory");
911 }
912
913 static __inline__ __attribute__((always_inline)) void __invlpg(void * const Address)
914 {
915 __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))));
916 }
917
918
919 /*** System operations ***/
920 static __inline__ __attribute__((always_inline)) unsigned long long __readmsr(const int reg)
921 {
922 unsigned long long retval;
923 __asm__ __volatile__("rdmsr" : "=A" (retval) : "c" (reg));
924 return retval;
925 }
926
927 static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Register, const unsigned long long Value)
928 {
929 __asm__ __volatile__("wrmsr" : : "A" (Value), "c" (Register));
930 }
931
932 static __inline__ __attribute__((always_inline)) unsigned long long __readpmc(const int counter)
933 {
934 unsigned long long retval;
935 __asm__ __volatile__("rdpmc" : "=A" (retval) : "c" (counter));
936 return retval;
937 }
938
939 /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */
940 static __inline__ __attribute__((always_inline)) unsigned long __segmentlimit(const unsigned long a)
941 {
942 unsigned long retval;
943 __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a));
944 return retval;
945 }
946
947 static __inline__ __attribute__((always_inline)) void __wbinvd(void)
948 {
949 __asm__ __volatile__("wbinvd");
950 }
951
952 #endif /* KJK_INTRIN_X86_H_ */
953
954 /* EOF */

  ViewVC Help
Powered by ViewVC 1.1.22