00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _OASYS_ATOMIC_MIPS_H_
00019 #define _OASYS_ATOMIC_MIPS_H_
00020
00021 namespace oasys {
00022
00028 struct atomic_t {
00029 atomic_t(u_int32_t v = 0) : value(v) {}
00030
00031 volatile u_int32_t value;
00032 };
00033
00041 static inline u_int32_t
00042 atomic_add_ret(volatile atomic_t *v, u_int32_t i)
00043 {
00044 u_int32_t ret;
00045 u_int32_t temp;
00046
00047 __asm__ __volatile__(
00048 " .set mips3 \n"
00049 "1: ll %1, %2 # atomic_add_return \n"
00050 " addu %0, %1, %3 \n"
00051 " sc %0, %2 \n"
00052 " beqzl %0, 1b \n"
00053 " addu %0, %1, %3 \n"
00054 " sync \n"
00055 " .set mips0 \n"
00056 : "=&r" (ret), "=&r" (temp), "=m" (v->value)
00057 : "Ir" (i), "m" (v->value)
00058 : "memory");
00059
00060 return ret;
00061 }
00062
00069 static inline u_int32_t
00070 atomic_sub_ret(volatile atomic_t * v, u_int32_t i)
00071 {
00072 u_int32_t ret;
00073 u_int32_t temp;
00074
00075 __asm__ __volatile__(
00076 " .set mips3 \n"
00077 "1: ll %1, %2 # atomic_sub_return \n"
00078 " subu %0, %1, %3 \n"
00079 " sc %0, %2 \n"
00080 " beqzl %0, 1b \n"
00081 " subu %0, %1, %3 \n"
00082 " sync \n"
00083 " .set mips0 \n"
00084 : "=&r" (ret), "=&r" (temp), "=m" (v->value)
00085 : "Ir" (i), "m" (v->value)
00086 : "memory");
00087
00088 return ret;
00089 }
00090
00091
00094
00095 static inline void
00096 atomic_add(volatile atomic_t* v, u_int32_t i)
00097 {
00098 atomic_add_ret(v, i);
00099 }
00100
00101 static inline void
00102 atomic_sub(volatile atomic_t* v, u_int32_t i)
00103 {
00104 atomic_sub_ret(v, i);
00105 }
00106
00107 static inline void
00108 atomic_incr(volatile atomic_t* v)
00109 {
00110 atomic_add(v, 1);
00111 }
00112
00113 static inline void
00114 atomic_decr(volatile atomic_t* v)
00115 {
00116 atomic_sub(v, 1);
00117 }
00118
00119 static inline u_int32_t
00120 atomic_incr_ret(volatile atomic_t* v)
00121 {
00122 return atomic_add_ret(v, 1);
00123 }
00124
00125 static inline u_int32_t
00126 atomic_decr_ret(volatile atomic_t* v)
00127 {
00128 return atomic_sub_ret(v, 1);
00129 }
00130
00131 static inline bool
00132 atomic_decr_test(volatile atomic_t* v)
00133 {
00134 return (atomic_sub_ret(v, 1) == 0);
00135 }
00136
00137
00138
00150 static inline u_int32_t
00151 atomic_cmpxchg32(volatile atomic_t* v, u_int32_t o, u_int32_t n)
00152 {
00153 u_int32_t ret;
00154
00155 __asm__ __volatile__(
00156 " .set push \n"
00157 " .set noat \n"
00158 " .set mips3 \n"
00159 "1: ll %0, %2 # __cmpxchg_u32 \n"
00160 " bne %0, %z3, 2f \n"
00161 " .set mips0 \n"
00162 " move $1, %z4 \n"
00163 " .set mips3 \n"
00164 " sc $1, %1 \n"
00165 " beqzl $1, 1b \n"
00166 #ifdef CONFIG_SMP
00167 " sync \n"
00168 #endif
00169 "2: \n"
00170 " .set pop \n"
00171 : "=&r" (ret), "=R" (*v)
00172 : "R" (*v), "Jr" (o), "Jr" (n)
00173 : "memory");
00174
00175 return ret;
00176 }
00177
00178 }
00179
00180
00181
00182 #endif