1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- /*
- * Hacked atomics with hpa-specific lw.l/sw.u instructions
- */
- #ifndef ATOMIC_H
- #define ATOMIC_H
- #include "compiler.h"
- typedef uint32_t atomic_t;
- #define lw_l(x) ({ \
- volatile atomic_t *__p = (volatile atomic_t *)(x); \
- atomic_t __v; \
- asm inline volatile("lw.l %0,%1" \
- : "=r" (__v), "+m" (*__p) \
- : : "memory"); \
- (typeof(*(x))) __v; \
- })
- static inline void _sw_u(volatile atomic_t *__p, atomic_t __v)
- {
- asm inline volatile("sw.u %1,%0"
- : "+m" (*__p) : "r" (__v)
- : "memory");
- }
- #define sw_u(x,v) _sw_u((volatile atomic_t *)(x), (v))
- /* Simple barrier-enforcing accessors */
- static inline atomic_t atomic_get(const volatile atomic_t *_p)
- {
- atomic_t _v;
- asm inline volatile("lw %0,%1" : "=r" (_v) : "m" (*_p) : "memory");
- return _v;
- }
- static inline void atomic_set(volatile atomic_t *_p, atomic_t _v)
- {
- asm inline volatile("sw %1,%0" : "=m" (*_p) : "r" (_v) : "memory");
- }
- static inline atomic_t atomic_swap(volatile atomic_t *_p, atomic_t _v)
- {
- atomic_t _o = lw_l(_p);
- sw_u(_p, _v);
- return _o;
- }
- /* These functions all do read-modify-write returning the old or new values */
- #define ATOMIC_OP2_RET(name, op, ret) \
- static inline atomic_t \
- atomic_ ## name (volatile atomic_t *_p, atomic_t _v) \
- { \
- atomic_t _o = lw_l(_p); \
- atomic_t _n = _o op _v; \
- sw_u(_p, _n); \
- return ret; \
- }
- #define ATOMIC_OP2(name, op) \
- ATOMIC_OP2_RET(name, op, _n) \
- ATOMIC_OP2_RET(xchg_ ## name, op, _o)
- ATOMIC_OP2(add, +)
- ATOMIC_OP2(sub, -)
- ATOMIC_OP2(and, &)
- ATOMIC_OP2(or, |)
- ATOMIC_OP2(xor, ^)
- static inline atomic_t atomic_xchg_and_xor(volatile atomic_t *_p, atomic_t _va, atomic_t _vx)
- {
- atomic_t _o = lw_l(_p);
- atomic_t _n = (_o & _va) ^ _vx;
- sw_u(_p, _n);
- return _o;
- }
- #endif /* ATOMIC_H */
|