00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef _OASYS_ATOMIC_MIPS_H_
00040 #define _OASYS_ATOMIC_MIPS_H_
00041
00042 namespace oasys {
00043
00049 struct atomic_t {
00050 atomic_t(u_int32_t v = 0) : value(v) {}
00051
00052 volatile u_int32_t value;
00053 };
00054
00062 static inline u_int32_t
00063 atomic_add_ret(volatile atomic_t *v, u_int32_t i)
00064 {
00065 u_int32_t ret;
00066 u_int32_t temp;
00067
00068 __asm__ __volatile__(
00069 " .set mips3 \n"
00070 "1: ll %1, %2 # atomic_add_return \n"
00071 " addu %0, %1, %3 \n"
00072 " sc %0, %2 \n"
00073 " beqzl %0, 1b \n"
00074 " addu %0, %1, %3 \n"
00075 " sync \n"
00076 " .set mips0 \n"
00077 : "=&r" (ret), "=&r" (temp), "=m" (v->value)
00078 : "Ir" (i), "m" (v->value)
00079 : "memory");
00080
00081 return ret;
00082 }
00083
00090 static inline u_int32_t
00091 atomic_sub_ret(volatile atomic_t * v, u_int32_t i)
00092 {
00093 u_int32_t ret;
00094 u_int32_t temp;
00095
00096 __asm__ __volatile__(
00097 " .set mips3 \n"
00098 "1: ll %1, %2 # atomic_sub_return \n"
00099 " subu %0, %1, %3 \n"
00100 " sc %0, %2 \n"
00101 " beqzl %0, 1b \n"
00102 " subu %0, %1, %3 \n"
00103 " sync \n"
00104 " .set mips0 \n"
00105 : "=&r" (ret), "=&r" (temp), "=m" (v->value)
00106 : "Ir" (i), "m" (v->value)
00107 : "memory");
00108
00109 return ret;
00110 }
00111
00112
00115
00116 static inline void
00117 atomic_add(volatile atomic_t* v, u_int32_t i)
00118 {
00119 atomic_add_ret(v, i);
00120 }
00121
00122 static inline void
00123 atomic_sub(volatile atomic_t* v, u_int32_t i)
00124 {
00125 atomic_sub_ret(v, i);
00126 }
00127
00128 static inline void
00129 atomic_incr(volatile atomic_t* v)
00130 {
00131 atomic_add(v, 1);
00132 }
00133
00134 static inline void
00135 atomic_decr(volatile atomic_t* v)
00136 {
00137 atomic_sub(v, 1);
00138 }
00139
00140 static inline u_int32_t
00141 atomic_incr_ret(volatile atomic_t* v)
00142 {
00143 return atomic_add_ret(v, 1);
00144 }
00145
00146 static inline u_int32_t
00147 atomic_decr_ret(volatile atomic_t* v)
00148 {
00149 return atomic_sub_ret(v, 1);
00150 }
00151
00152 static inline bool
00153 atomic_decr_test(volatile atomic_t* v)
00154 {
00155 return (atomic_sub_ret(v, 1) == 0);
00156 }
00157
00158
00159
00171 static inline u_int32_t
00172 atomic_cmpxchg32(volatile atomic_t* v, u_int32_t o, u_int32_t n)
00173 {
00174 u_int32_t ret;
00175
00176 __asm__ __volatile__(
00177 " .set push \n"
00178 " .set noat \n"
00179 " .set mips3 \n"
00180 "1: ll %0, %2 # __cmpxchg_u32 \n"
00181 " bne %0, %z3, 2f \n"
00182 " .set mips0 \n"
00183 " move $1, %z4 \n"
00184 " .set mips3 \n"
00185 " sc $1, %1 \n"
00186 " beqzl $1, 1b \n"
00187 #ifdef CONFIG_SMP
00188 " sync \n"
00189 #endif
00190 "2: \n"
00191 " .set pop \n"
00192 : "=&r" (ret), "=R" (*v)
00193 : "R" (*v), "Jr" (o), "Jr" (n)
00194 : "memory");
00195
00196 return ret;
00197 }
00198
00199 }
00200
00201
00202
00203 #endif