t's a bit embarrasing that some of this was undone until recently, but we now
[reactos.git] / reactos / include / psdk / intrin_ppc.h
1 /*
2 Compatibility <intrin.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_PPC_H_
29 #define KJK_INTRIN_PPC_H_
30
31 //#define PPC_QUAL static __inline__ __attribute__((always_inline))
32 #define PPC_QUAL extern __inline__
33
34 #ifndef __GNUC__
35 #error Unsupported compiler
36 #endif
37
38 /*** Stack frame juggling ***/
39 #define _ReturnAddress() (__builtin_return_address(0))
40 #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))
41 /* TODO: __getcallerseflags but how??? */
42
43
44 /*** Atomic operations ***/
45 /* TODO: _ReadBarrier */
46 /* TODO: _WriteBarrier */
47
48 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
49 #define _ReadWriteBarrier() __sync_synchronize()
50 #else
51 /* TODO: _ReadWriteBarrier() */
52 #endif
53
54 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
55
56 PPC_QUAL char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
57 {
58 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
59 }
60
61 PPC_QUAL short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
62 {
63 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
64 }
65
66 PPC_QUAL long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
67 {
68 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
69 }
70
71 PPC_QUAL long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
72 {
73 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
74 }
75
76 PPC_QUAL void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
77 {
78 return __sync_val_compare_and_swap(Destination, Comperand, Exchange);
79 }
80
81 PPC_QUAL long _InterlockedExchange(volatile long * const Target, const long Value)
82 {
83 /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */
84 __sync_synchronize();
85 return __sync_lock_test_and_set(Target, Value);
86 }
87
88 PPC_QUAL void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
89 {
90 /* NOTE: ditto */
91 __sync_synchronize();
92 return __sync_lock_test_and_set(Target, Value);
93 }
94
95 PPC_QUAL long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
96 {
97 return __sync_fetch_and_add(Addend, Value);
98 }
99
100 PPC_QUAL char _InterlockedAnd8(volatile char * const value, const char mask)
101 {
102 return __sync_fetch_and_and(value, mask);
103 }
104
105 PPC_QUAL short _InterlockedAnd16(volatile short * const value, const short mask)
106 {
107 return __sync_fetch_and_and(value, mask);
108 }
109
110 PPC_QUAL long _InterlockedAnd(volatile long * const value, const long mask)
111 {
112 return __sync_fetch_and_and(value, mask);
113 }
114
115 PPC_QUAL char _InterlockedOr8(volatile char * const value, const char mask)
116 {
117 return __sync_fetch_and_or(value, mask);
118 }
119
120 PPC_QUAL short _InterlockedOr16(volatile short * const value, const short mask)
121 {
122 return __sync_fetch_and_or(value, mask);
123 }
124
125 PPC_QUAL long _InterlockedOr(volatile long * const value, const long mask)
126 {
127 return __sync_fetch_and_or(value, mask);
128 }
129
130 PPC_QUAL char _InterlockedXor8(volatile char * const value, const char mask)
131 {
132 return __sync_fetch_and_xor(value, mask);
133 }
134
135 PPC_QUAL short _InterlockedXor16(volatile short * const value, const short mask)
136 {
137 return __sync_fetch_and_xor(value, mask);
138 }
139
140 PPC_QUAL long _InterlockedXor(volatile long * const value, const long mask)
141 {
142 return __sync_fetch_and_xor(value, mask);
143 }
144
145 #else
146
147 PPC_QUAL char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)
148 {
149 char retval = Comperand;
150 __asm__ __volatile__ (
151 "sync\n"
152 "1: lbarx %0,0,%1\n"
153 " subf. %0,%2,%0\n"
154 " bne 2f\n"
155 " stbcx. %3,0,%1\n"
156 " bne- 1b\n"
157 "2: isync"
158 : "=b" (retval)
159 : "b" (Destination), "r" (Comperand), "r" (Exchange)
160 : "cr0", "memory");
161 return retval;
162 }
163
164 PPC_QUAL short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)
165 {
166 short retval = Comperand;
167 __asm__ __volatile__ (
168 "sync\n"
169 "1: lharx %0,0,%1\n"
170 " subf. %0,%2,%0\n"
171 " bne 2f\n"
172 " sthcx. %3,0,%1\n"
173 " bne- 1b\n"
174 "2: isync"
175 : "=r" (retval)
176 : "r" (Destination), "r" (Comperand), "r" (Exchange)
177 : "memory");
178 return retval;
179 }
180
181 PPC_QUAL long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)
182 {
183 short retval = Comperand;
184 __asm__ __volatile__ (
185 "sync\n"
186 "1: lwarx %0,0,%1\n"
187 " subf. %0,%2,%0\n"
188 " bne 2f\n"
189 " stwcx. %3,0,%1\n"
190 " bne- 1b\n"
191 "2: isync"
192 : "=r" (retval)
193 : "r" (Destination), "r" (Comperand), "r" (Exchange)
194 : "memory");
195 return retval;
196 }
197
198 PPC_QUAL long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)
199 {
200 return 0;
201 }
202
203 PPC_QUAL void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)
204 {
205 return (void *)_InterlockedCompareExchange
206 ((long *)Destination, (long) Exchange, (long) Comperand);
207 }
208
209 PPC_QUAL long _InterlockedExchange(volatile long * const Target, const long Value)
210 {
211 long retval;
212 __asm__ __volatile__ (
213 "sync\n"
214 "1: lwarx %0,0,%1\n"
215 " stwcx. %2,0,%1\n"
216 " bne- 1b\n"
217 : "=b" (retval)
218 : "b" (Target), "b" (Value)
219 : "cr0", "memory");
220 return retval;
221 }
222
223 PPC_QUAL void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)
224 {
225 void * retval;
226 __asm__ __volatile__ (
227 "sync\n"
228 "1: lwarx %0,0,%1\n"
229 " stwcx. %2,0,%1\n"
230 " bne- 1b\n"
231 : "=b" (retval)
232 : "b" (Target), "b" (Value)
233 : "cr0", "memory");
234 return retval;
235 }
236
237 PPC_QUAL long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)
238 {
239 long x;
240 long y = *Addend;
241 long addend = y;
242
243 do
244 {
245 x = y;
246 y = _InterlockedCompareExchange(Addend, addend + Value, x);
247 }
248 while(y != x);
249
250 return y;
251 }
252
253 PPC_QUAL char _InterlockedAnd8(volatile char * const value, const char mask)
254 {
255 char x;
256 char y;
257
258 y = *value;
259
260 do
261 {
262 x = y;
263 y = _InterlockedCompareExchange8(value, x & mask, x);
264 }
265 while(y != x);
266
267 return y;
268 }
269
270 PPC_QUAL short _InterlockedAnd16(volatile short * const value, const short mask)
271 {
272 short x;
273 short y;
274
275 y = *value;
276
277 do
278 {
279 x = y;
280 y = _InterlockedCompareExchange16(value, x & mask, x);
281 }
282 while(y != x);
283
284 return y;
285 }
286
287 PPC_QUAL long _InterlockedAnd(volatile long * const value, const long mask)
288 {
289 long x;
290 long y;
291
292 y = *value;
293
294 do
295 {
296 x = y;
297 y = _InterlockedCompareExchange(value, x & mask, x);
298 }
299 while(y != x);
300
301 return y;
302 }
303
304 PPC_QUAL char _InterlockedOr8(volatile char * const value, const char mask)
305 {
306 char x;
307 char y;
308
309 y = *value;
310
311 do
312 {
313 x = y;
314 y = _InterlockedCompareExchange8(value, x | mask, x);
315 }
316 while(y != x);
317
318 return y;
319 }
320
321 PPC_QUAL short _InterlockedOr16(volatile short * const value, const short mask)
322 {
323 short x;
324 short y;
325
326 y = *value;
327
328 do
329 {
330 x = y;
331 y = _InterlockedCompareExchange16(value, x | mask, x);
332 }
333 while(y != x);
334
335 return y;
336 }
337
338 PPC_QUAL long _InterlockedOr(volatile long * const value, const long mask)
339 {
340 long x;
341 long y;
342
343 y = *value;
344
345 do
346 {
347 x = y;
348 y = _InterlockedCompareExchange(value, x | mask, x);
349 }
350 while(y != x);
351
352 return y;
353 }
354
355 PPC_QUAL char _InterlockedXor8(volatile char * const value, const char mask)
356 {
357 char x;
358 char y;
359
360 y = *value;
361
362 do
363 {
364 x = y;
365 y = _InterlockedCompareExchange8(value, x ^ mask, x);
366 }
367 while(y != x);
368
369 return y;
370 }
371
372 PPC_QUAL short _InterlockedXor16(volatile short * const value, const short mask)
373 {
374 short x;
375 short y;
376
377 y = *value;
378
379 do
380 {
381 x = y;
382 y = _InterlockedCompareExchange16(value, x ^ mask, x);
383 }
384 while(y != x);
385
386 return y;
387 }
388
389 PPC_QUAL long _InterlockedXor(volatile long * const value, const long mask)
390 {
391 long x;
392 long y;
393
394 y = *value;
395
396 do
397 {
398 x = y;
399 y = _InterlockedCompareExchange(value, x ^ mask, x);
400 }
401 while(y != x);
402
403 return y;
404 }
405
406 PPC_QUAL unsigned char _interlockedbittestandreset(volatile long * const a, const long b)
407 {
408 long x;
409 long y;
410 long mask = ~(1<<b);
411
412 y = *a;
413
414 do
415 {
416 x = y;
417 y = _InterlockedCompareExchange(a, x & mask, x);
418 }
419 while(y != x);
420
421 return (y & ~mask) != 0;
422 }
423
424 PPC_QUAL unsigned char _interlockedbittestandset(volatile long * const a, const long b)
425 {
426 long x;
427 long y;
428 long mask = 1<<b;
429
430 y = *a;
431
432 do
433 {
434 x = y;
435 y = _InterlockedCompareExchange(a, x | mask, x);
436 }
437 while(y != x);
438
439 return (y & ~mask) != 0;
440 }
441 #endif
442
443 PPC_QUAL long _InterlockedDecrement(volatile long * const lpAddend)
444 {
445 return _InterlockedExchangeAdd(lpAddend, -1) - 1;
446 }
447
448 PPC_QUAL long _InterlockedIncrement(volatile long * const lpAddend)
449 {
450 return _InterlockedExchangeAdd(lpAddend, 1) + 1;
451 }
452
453 /*** String operations ***/
454 /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */
455 /* Note that the PPC store multiple operations may raise an exception in LE
456 * mode */
457 PPC_QUAL void __stosb(unsigned char * Dest, const unsigned char Data, unsigned long Count)
458 {
459 memset(Dest, Data, Count);
460 }
461
462 PPC_QUAL void __stosw(unsigned short * Dest, const unsigned short Data, unsigned long Count)
463 {
464 while(Count--)
465 *Dest++ = Data;
466 }
467
468 PPC_QUAL void __stosd(unsigned long * Dest, const unsigned long Data, unsigned long Count)
469 {
470 while(Count--)
471 *Dest++ = Data;
472 }
473
474 PPC_QUAL void __movsb(unsigned char * Destination, const unsigned char * Source, unsigned long Count)
475 {
476 memcpy(Destination, Source, Count);
477 }
478
479 PPC_QUAL void __movsw(unsigned short * Destination, const unsigned short * Source, unsigned long Count)
480 {
481 memcpy(Destination, Source, Count * sizeof(*Source));
482 }
483
484 PPC_QUAL void __movsd(unsigned long * Destination, const unsigned long * Source, unsigned long Count)
485 {
486 memcpy(Destination, Source, Count * sizeof(*Source));
487 }
488
489
490 /*** FS segment addressing ***/
491 /* On PowerPC, r13 points to TLS data, including the TEB at 0(r13) from what I
492 * can tell */
493 PPC_QUAL void __writefsbyte(const unsigned long Offset, const unsigned char Data)
494 {
495 char *addr;
496 __asm__("\tadd %0,13,%1\n\tstb %2,0(%0)" : "=r" (addr) : "r" (Offset), "r" (Data));
497 }
498
499 PPC_QUAL void __writefsword(const unsigned long Offset, const unsigned short Data)
500 {
501 char *addr;
502 __asm__("\tadd %0,13,%1\n\tsth %2,0(%0)" : "=r" (addr) : "r" (Offset), "r" (Data));
503 }
504
505 PPC_QUAL void __writefsdword(const unsigned long Offset, const unsigned long Data)
506 {
507 char *addr;
508 __asm__("\tadd %0,13,%1\n\tstw %2,0(%0)" : "=r" (addr) : "r" (Offset), "r" (Data));
509 }
510
511 PPC_QUAL unsigned char __readfsbyte(const unsigned long Offset)
512 {
513 unsigned short result;
514 __asm__("\tadd 7,13,%1\n"
515 "\tlbz %0,0(7)\n"
516 : "=r" (result)
517 : "r" (Offset)
518 : "r7");
519 return result;
520 }
521
522 PPC_QUAL unsigned short __readfsword(const unsigned long Offset)
523 {
524 unsigned short result;
525 __asm__("\tadd 7,13,%1\n"
526 "\tlhz %0,0(7)\n"
527 : "=r" (result)
528 : "r" (Offset)
529 : "r7");
530 return result;
531 }
532
533 PPC_QUAL unsigned long __readfsdword(const unsigned long Offset)
534 {
535 unsigned long result;
536 __asm__("\tadd 7,13,%1\n"
537 "\tlwz %0,0(7)\n"
538 : "=r" (result)
539 : "r" (Offset)
540 : "r7");
541 return result;
542 }
543
544 PPC_QUAL void __incfsbyte(const unsigned long Offset)
545 {
546 __writefsbyte(Offset, __readfsbyte(Offset)+1);
547 }
548
549 PPC_QUAL void __incfsword(const unsigned long Offset)
550 {
551 __writefsword(Offset, __readfsword(Offset)+1);
552 }
553
554 PPC_QUAL void __incfsdword(const unsigned long Offset)
555 {
556 __writefsdword(Offset, __readfsdword(Offset)+1);
557 }
558
559 /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */
560 /* PPC Note: Not sure about the bizarre behavior. We'll try to emulate it later */
561 PPC_QUAL void __addfsbyte(const unsigned long Offset, const unsigned char Data)
562 {
563 __writefsbyte(Offset, __readfsbyte(Offset) + Data);
564 }
565
566 PPC_QUAL void __addfsword(const unsigned long Offset, const unsigned short Data)
567 {
568 __writefsword(Offset, __readfsword(Offset) + Data);
569 }
570
571 PPC_QUAL void __addfsdword(const unsigned long Offset, const unsigned int Data)
572 {
573 __writefsdword(Offset, __readfsdword(Offset) + Data);
574 }
575
576
577 /*** Bit manipulation ***/
578 PPC_QUAL unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)
579 {
580 if(Mask == 0) return 0;
581 else {
582 unsigned long mask = Mask;
583 mask &= -mask;
584 *Index =
585 ((mask & 0xffff0000) ? 16 : 0) +
586 ((mask & 0xff00ff00) ? 8 : 0) +
587 ((mask & 0xf0f0f0f0) ? 4 : 0) +
588 ((mask & 0xcccccccc) ? 2 : 0) +
589 ((mask & 0xaaaaaaaa) ? 1 : 0);
590 return 1;
591 }
592 }
593
594 /* Thanks http://www.jjj.de/bitwizardry/files/bithigh.h */
595 PPC_QUAL unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)
596 {
597 unsigned long check = 16, checkmask;
598 if(Mask == 0) return 0;
599 else {
600 unsigned long mask = Mask;
601 *Index = 0;
602 while(check) {
603 checkmask = ((1<<check)-1) << check;
604 if( mask & checkmask ) {
605 mask >>= check;
606 *Index += check;
607 }
608 check >>= 1;
609 }
610 return 1;
611 }
612 }
613
614 /* NOTE: again, the bizarre implementation follows Visual C++ */
615 PPC_QUAL unsigned char _bittest(const long * const a, const long b)
616 {
617 return ((*a) & (1<<b)) != 0;
618 }
619
620 PPC_QUAL unsigned char _bittestandcomplement(long * const a, const long b)
621 {
622 unsigned char ret = ((*a) & (1<<b)) != 0;
623 (*a) ^= (1<<b);
624 return ret;
625 }
626
627 PPC_QUAL unsigned char _bittestandreset(long * const a, const long b)
628 {
629 unsigned char ret = ((*a) & (1<<b)) != 0;
630 (*a) &= ~(1<<b);
631 return ret;
632 }
633
634 PPC_QUAL unsigned char _bittestandset(long * const a, const long b)
635 {
636 unsigned char ret = ((*a) & (1<<b)) != 0;
637 (*a) |= (1<<b);
638 return ret;
639 }
640
641 PPC_QUAL unsigned char _rotl8(const unsigned char value, const unsigned char shift)
642 {
643 return (value << shift) | (value >> (8-shift));
644 }
645
646 PPC_QUAL unsigned short _rotl16(const unsigned short value, const unsigned char shift)
647 {
648 return (value << shift) | (value >> (16-shift));
649 }
650
651 PPC_QUAL unsigned char _rotr8(const unsigned char value, const unsigned char shift)
652 {
653 return (value >> shift) | (value << (8-shift));
654 }
655
656 PPC_QUAL unsigned short _rotr16(const unsigned short value, const unsigned char shift)
657 {
658 return (value >> shift) | (value << (16-shift));
659 }
660
661 PPC_QUAL unsigned long long __ll_lshift(const unsigned long long Mask, int Bit)
662 {
663 return Mask << Bit;
664 }
665
666 PPC_QUAL long long __ll_rshift(const long long Mask, const int Bit)
667 {
668 return Mask >> Bit;
669 }
670
671 PPC_QUAL unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)
672 {
673 return Mask >> Bit;
674 }
675
676
677 /*** 64-bit math ***/
678 PPC_QUAL long long __emul(const int a, const int b)
679 {
680 return a * b;
681 }
682
683 PPC_QUAL unsigned long long __emulu(const unsigned int a, const unsigned int b)
684 {
685 return a * b;
686 }
687
688
689 /*** Port I/O ***/
690 PPC_QUAL unsigned char __inbyte(const unsigned long Port)
691 {
692 int ret;
693 __asm__(
694 "mfmsr 5\n\t"
695 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
696 "mtmsr 6\n\t"
697 "isync\n\t"
698 "sync\n\t"
699 "lbz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */
700 "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)
701 );
702 return ret;
703 }
704
705 PPC_QUAL unsigned short __inword(const unsigned long Port)
706 {
707 int ret;
708 __asm__(
709 "mfmsr 5\n\t"
710 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
711 "mtmsr 6\n\t"
712 "isync\n\t"
713 "sync\n\t"
714 "lhz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */
715 "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)
716 );
717 return ret;
718 }
719
720 PPC_QUAL unsigned long __indword(const unsigned long Port)
721 {
722 int ret;
723 __asm__(
724 "mfmsr 5\n\t"
725 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
726 "mtmsr 6\n\t"
727 "isync\n\t"
728 "sync\n\t"
729 "lwz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */
730 "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)
731 );
732 return ret;
733 }
734
735 PPC_QUAL void __inbytestring(unsigned long Port, unsigned char * Buffer, unsigned long Count)
736 {
737 while(Count--) {
738 *Buffer++ = __inbyte(Port);
739 }
740 }
741
742 PPC_QUAL void __inwordstring(unsigned long Port, unsigned short * Buffer, unsigned long Count)
743 {
744 while(Count--) {
745 *Buffer++ = __inword(Port);
746 }
747 }
748
749 PPC_QUAL void __indwordstring(unsigned long Port, unsigned long * Buffer, unsigned long Count)
750 {
751 while(Count--) {
752 *Buffer++ = __indword(Port);
753 }
754 }
755
756 PPC_QUAL void __outbyte(unsigned long const Port, const unsigned char Data)
757 {
758 __asm__(
759 "mfmsr 5\n\t"
760 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
761 "mtmsr 6\n\t"
762 "sync\n\t"
763 "eieio\n\t"
764 "stb %1,0(%0)\n\t" /* Set actual value at phys addr r3 */
765 "dcbst 0,%1\n\t"
766 "mtmsr 5\n\t"
767 "sync\n\t"
768 "eieio\n\t" : : "b" (Port), "r" (Data)
769 );
770 }
771
772 PPC_QUAL void __outword(unsigned long const Port, const unsigned short Data)
773 {
774 __asm__(
775 "mfmsr 5\n\t"
776 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
777 "mtmsr 6\n\t"
778 "sync\n\t"
779 "eieio\n\t"
780 "sth %1,0(%0)\n\t" /* Set actual value at phys addr r3 */
781 "dcbst 0,%1\n\t"
782 "mtmsr 5\n\t"
783 "sync\n\t"
784 "eieio\n\t" : : "b" (Port), "b" (Data)
785 );
786 }
787
788 PPC_QUAL void __outdword(unsigned long const Port, const unsigned long Data)
789 {
790 __asm__(
791 "mfmsr 5\n\t"
792 "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
793 "mtmsr 6\n\t"
794 "sync\n\t"
795 "eieio\n\t"
796 "stw %1,0(%0)\n\t" /* Set actual value at phys addr r3 */
797 "dcbst 0,%1\n\t"
798 "mtmsr 5\n\t"
799 "sync\n\t"
800 "eieio\n\t" : : "b" (Port), "b" (Data)
801 );
802 }
803
804 PPC_QUAL void __outbytestring(unsigned long const Port, const unsigned char * const Buffer, const unsigned long Count)
805 {
806 unsigned long count = Count;
807 const unsigned char *buffer = Buffer;
808 while(count--) {
809 __outbyte(Port, *buffer++);
810 }
811 }
812
813 PPC_QUAL void __outwordstring(unsigned long const Port, const unsigned short * const Buffer, const unsigned long Count)
814 {
815 unsigned long count = Count;
816 const unsigned short *buffer = Buffer;
817 while(count--) {
818 __outword(Port, *buffer++);
819 }
820 }
821
822 PPC_QUAL void __outdwordstring(unsigned long const Port, const unsigned long * const Buffer, const unsigned long Count)
823 {
824 unsigned long count = Count;
825 const unsigned long *buffer = Buffer;
826 while(count--) {
827 __outdword(Port, *buffer++);
828 }
829 }
830
831
832 /*** System information ***/
833 PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType)
834 {
835 unsigned long lo32;
836 __asm__("mfpvr" : "=b" (lo32));
837 }
838
839 PPC_QUAL unsigned long long __rdtsc(void)
840 {
841 unsigned long lo32;
842 __asm__("mfdec %0" : "=b" (lo32));
843 return -lo32;
844 }
845
846
847 /*** Interrupts ***/
848 /* Finally decided to do this by enabling single step trap */
849 PPC_QUAL void __debugbreak(void)
850 {
851
852 }
853
854 PPC_QUAL void __int2c(void)
855 {
856 /* Not sure yet */
857 }
858
859 #ifndef _ENABLE_DISABLE_DEFINED
860 #define _ENABLE_DISABLE_DEFINED
861 PPC_QUAL void _disable(void)
862 {
863 __asm__ __volatile__("mfmsr 0\n\t" \
864 "li 8,0x7fff\n\t" \
865 "and 0,8,0\n\t" \
866 "mtmsr 0\n\t");
867 }
868
869 PPC_QUAL void _enable(void)
870 {
871 __asm__ __volatile__("mfmsr 8\n\t" \
872 "ori 8,8,0x8000\n\t" \
873 "mtmsr 8\n\t");
874 }
875
876 /*** Protected memory management ***/
877 PPC_QUAL unsigned long __readsdr1(void)
878 {
879 unsigned long value;
880 __asm__("mfsdr1 %0" : "=b" (value));
881 return value;
882 }
883
884 PPC_QUAL void __writesdr1(const unsigned long long Data)
885 {
886 __asm__("mtsdr1 %0" : : "b" (Data));
887 }
888
889 /*** System operations ***/
890 /* This likely has a different meaning from the X86 equivalent. We'll keep
891 * the name cause it fits */
892 PPC_QUAL unsigned long long __readmsr()
893 {
894 unsigned long temp;
895 __asm__("mfmsr %0" : "=b" (temp));
896 return temp;
897 }
898
899 PPC_QUAL void __writemsr(const unsigned long Value)
900 {
901 __asm__("mtmsr %0" : : "b" (Value));
902 }
903
904 /* We'll make sure of the following:
905 * IO operations have completed
906 * Write operations through cache have completed
907 * We've reloaded anything in the data or instruction cache that might have
908 * changed in real ram.
909 */
910 PPC_QUAL void __wbinvd(void)
911 {
912 __asm__("eieio\n\t"
913 "dcs\n\t"
914 "sync\n\t"
915 "isync\n\t");
916 }
917 #endif
918
919 PPC_QUAL long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)
920 {
921 #if 0
922 __asm__
923 (
924 "lock; add %[Value], %[Lo32];"
925 "jae LABEL%=;"
926 "lock; adc $0, %[Hi32];"
927 "LABEL%=:;" :
928 [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) :
929 [Value] "ir" (Value)
930 );
931 #endif
932 return Value;
933 }
934
935 /*** Miscellaneous ***/
936 /* BUGBUG: only good for use in macros. Cannot be taken the address of */
937 #define __noop(...) ((void)0)
938
939 /* TODO: __assume. GCC only supports the weaker __builtin_expect */
940
941 #endif
942 /* EOF */