#ifndef __ASM_METAG_ATOMIC_LNKGET_H #define __ASM_METAG_ATOMIC_LNKGET_H #define ATOMIC_INIT(i) { (i) } #define atomic_set(v, i) ((v)->counter = (i)) #include #include /* * None of these asm statements clobber memory as LNKSET writes around * the cache so the memory it modifies cannot safely be read by any means * other than these accessors. */ static inline int atomic_read(const atomic_t *v) { int temp; asm volatile ( "LNKGETD %0, [%1]\n" : "=da" (temp) : "da" (&v->counter)); return temp; } #define ATOMIC_OP(op) \ static inline void atomic_##op(int i, atomic_t *v) \ { \ int temp; \ \ asm volatile ( \ "1: LNKGETD %0, [%1]\n" \ " " #op " %0, %0, %2\n" \ " LNKSETD [%1], %0\n" \ " DEFR %0, TXSTAT\n" \ " ANDT %0, %0, #HI(0x3f000000)\n" \ " CMPT %0, #HI(0x02000000)\n" \ " BNZ 1b\n" \ : "=&d" (temp) \ : "da" (&v->counter), "bd" (i) \ : "cc"); \ } \ #define ATOMIC_OP_RETURN(op) \ static inline int atomic_##op##_return(int i, atomic_t *v) \ { \ int result, temp; \ \ smp_mb(); \ \ asm volatile ( \ "1: LNKGETD %1, [%2]\n" \ " " #op " %1, %1, %3\n" \ " LNKSETD [%2], %1\n" \ " DEFR %0, TXSTAT\n" \ " ANDT %0, %0, #HI(0x3f000000)\n" \ " CMPT %0, #HI(0x02000000)\n" \ " BNZ 1b\n" \ : "=&d" (temp), "=&da" (result) \ : "da" (&v->counter), "bd" (i) \ : "cc"); \ \ smp_mb(); \ \ return result; \ } #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_OPS(add) ATOMIC_OPS(sub) #undef ATOMIC_OPS #undef ATOMIC_OP_RETURN #undef ATOMIC_OP static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) { int temp; asm volatile ( "1: LNKGETD %0, [%1]\n" " AND %0, %0, %2\n" " LNKSETD [%1] %0\n" " DEFR %0, TXSTAT\n" " ANDT %0, %0, #HI(0x3f000000)\n" " CMPT %0, #HI(0x02000000)\n" " BNZ 1b\n" : "=&d" (temp) : "da" (&v->counter), "bd" (~mask) : "cc"); } static inline void atomic_set_mask(unsigned int mask, atomic_t *v) { int temp; asm volatile ( "1: LNKGETD %0, [%1]\n" " OR %0, %0, %2\n" " LNKSETD [%1], %0\n" " DEFR %0, TXSTAT\n" " ANDT %0, %0, #HI(0x3f000000)\n" " CMPT %0, #HI(0x02000000)\n" " BNZ 1b\n" : "=&d" (temp) : "da" (&v->counter), "bd" (mask) : "cc"); } static inline int atomic_cmpxchg(atomic_t *v, int old, int new) { int result, temp; smp_mb(); asm volatile ( "1: LNKGETD %1, [%2]\n" " CMP %1, %3\n" " LNKSETDEQ [%2], %4\n" " BNE 2f\n" " DEFR %0, TXSTAT\n" " ANDT %0, %0, #HI(0x3f000000)\n" " CMPT %0, #HI(0x02000000)\n" " BNZ 1b\n" "2:\n" : "=&d" (temp), "=&d" (result) : "da" (&v->counter), "bd" (old), "da" (new) : "cc"); smp_mb(); return result; } static inline int atomic_xchg(atomic_t *v, int new) { int temp, old; asm volatile ( "1: LNKGETD %1, [%2]\n" " LNKSETD [%2], %3\n" " DEFR %0, TXSTAT\n" " ANDT %0, %0, #HI(0x3f000000)\n" " CMPT %0, #HI(0x02000000)\n" " BNZ 1b\n" : "=&d" (temp), "=&d" (old) : "da" (&v->counter), "da" (new) : "cc"); return old; } static inline int __atomic_add_unless(atomic_t *v, int a, int u) { int result, temp; smp_mb(); asm volatile ( "1: LNKGETD %1, [%2]\n" " CMP %1, %3\n" " ADD %0, %1, %4\n" " LNKSETDNE [%2], %0\n" " BEQ 2f\n" " DEFR %0, TXSTAT\n" " ANDT %0, %0, #HI(0x3f000000)\n" " CMPT %0, #HI(0x02000000)\n" " BNZ 1b\n" "2:\n" : "=&d" (temp), "=&d" (result) : "da" (&v->counter), "bd" (u), "bd" (a) : "cc"); smp_mb(); return result; } static inline int atomic_sub_if_positive(int i, atomic_t *v) { int result, temp; asm volatile ( "1: LNKGETD %1, [%2]\n" " SUBS %1, %1, %3\n" " LNKSETDGE [%2], %1\n" " BLT 2f\n" " DEFR %0, TXSTAT\n" " ANDT %0, %0, #HI(0x3f000000)\n" " CMPT %0, #HI(0x02000000)\n" " BNZ 1b\n" "2:\n" : "=&d" (temp), "=&da" (result) : "da" (&v->counter), "bd" (i) : "cc"); return result; } #endif /* __ASM_METAG_ATOMIC_LNKGET_H */