update ppc
[lttv.git] / ltt-usertrace / ltt / ltt-usertrace-ppc.h
1 /*
2 * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
3 */
4 #ifndef __LTT_USERTRACE_PPC_H
5 #define __LTT_USERTRACE_PPC_H
6
7 #ifdef __powerpc64__
8 #include "ltt/atomic-ppc64.h"
9 #else
10 #include "ltt/atomic-ppc.h"
11 #endif
12
13 static __inline__ unsigned long
14 xchg_u32(volatile void *p, unsigned long val)
15 {
16 unsigned long prev;
17
18 __asm__ __volatile__ ("\n\
19 1: lwarx %0,0,%2 \n"
20 " stwcx. %3,0,%2 \n\
21 bne- 1b"
22 : "=&r" (prev), "=m" (*(volatile unsigned long *)p)
23 : "r" (p), "r" (val), "m" (*(volatile unsigned long *)p)
24 : "cc", "memory");
25
26 return prev;
27 }
28
29 /*
30 * This function doesn't exist, so you'll get a linker error
31 * if something tries to do an invalid xchg().
32 */
33 extern void __xchg_called_with_bad_pointer(void);
34
35 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
36 #define tas(ptr) (xchg((ptr),1))
37
38 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
39 {
40 switch (size) {
41 case 4:
42 return (unsigned long) xchg_u32(ptr, x);
43 #if 0 /* xchg_u64 doesn't exist on 32-bit PPC */
44 case 8:
45 return (unsigned long) xchg_u64(ptr, x);
46 #endif /* 0 */
47 }
48 __xchg_called_with_bad_pointer();
49 return x;
50
51
52 }
53
54 extern inline void * xchg_ptr(void * m, void * val)
55 {
56 return (void *) xchg_u32(m, (unsigned long) val);
57 }
58
59
60 #define __HAVE_ARCH_CMPXCHG 1
61
62 static __inline__ unsigned long
63 __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
64 {
65 unsigned int prev;
66
67 __asm__ __volatile__ ("\n\
68 1: lwarx %0,0,%2 \n\
69 cmpw 0,%0,%3 \n\
70 bne 2f \n"
71 " stwcx. %4,0,%2 \n\
72 bne- 1b\n"
73 #ifdef CONFIG_SMP
74 " sync\n"
75 #endif /* CONFIG_SMP */
76 "2:"
77 : "=&r" (prev), "=m" (*p)
78 : "r" (p), "r" (old), "r" (new), "m" (*p)
79 : "cc", "memory");
80
81 return prev;
82 }
83
84 /* This function doesn't exist, so you'll get a linker error
85 if something tries to do an invalid cmpxchg(). */
86 extern void __cmpxchg_called_with_bad_pointer(void);
87
88 static __inline__ unsigned long
89 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
90 {
91 switch (size) {
92 case 4:
93 return __cmpxchg_u32(ptr, old, new);
94 #if 0 /* we don't have __cmpxchg_u64 on 32-bit PPC */
95 case 8:
96 return __cmpxchg_u64(ptr, old, new);
97 #endif /* 0 */
98 }
99 __cmpxchg_called_with_bad_pointer();
100 return old;
101 }
102
103 #define cmpxchg(ptr,o,n) \
104 ({ \
105 __typeof__(*(ptr)) _o_ = (o); \
106 __typeof__(*(ptr)) _n_ = (n); \
107 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
108 (unsigned long)_n_, sizeof(*(ptr))); \
109 })
110
111
112 #define CPU_FTR_601 0x00000100
113
114 #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
115
116 typedef uint64_t cycles_t;
117
118 /* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */
119 static inline unsigned long get_tbl(void)
120 {
121 unsigned long tbl;
122
123 //#if defined(CONFIG_403GCX)
124 // asm volatile("mfspr %0, 0x3dd" : "=r" (tbl));
125 //#else
126 asm volatile("mftb %0" : "=r" (tbl));
127 //#endif
128 return tbl;
129 }
130
131 static inline unsigned int get_tbu(void)
132 {
133 unsigned int tbu;
134
135 //#if defined(CONFIG_403GCX)
136 // asm volatile("mfspr %0, 0x3dc" : "=r" (tbu));
137 //#else
138 asm volatile("mftbu %0" : "=r" (tbu));
139 //#endif
140 return tbu;
141 }
142
143
144 #ifdef __powerpc64__
145 static inline uint64_t get_tb(void)
146 {
147 return mftb();
148 }
149 #else
150 static inline uint64_t get_tb(void)
151 {
152 unsigned int tbhi, tblo, tbhi2;
153
154 do {
155 tbhi = get_tbu();
156 tblo = get_tbl();
157 tbhi2 = get_tbu();
158 } while (tbhi != tbhi2);
159
160 return ((uint64_t)tbhi << 32) | tblo;
161 }
162 #endif
163
164 static inline cycles_t get_cycles(void)
165 {
166 return get_tb();
167 }
168
169
170 #endif /* __LTT_USERTRACE_PPC_H */
This page took 0.035685 seconds and 4 git commands to generate.