e754794e282ff33af6ec41fc4a5ae53aec302883
[cascardo/linux.git] / arch / sh / include / asm / cmpxchg-llsc.h
1 #ifndef __ASM_SH_CMPXCHG_LLSC_H
2 #define __ASM_SH_CMPXCHG_LLSC_H
3
4 #include <linux/bitops.h>
5 #include <asm/byteorder.h>
6
7 static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
8 {
9         unsigned long retval;
10         unsigned long tmp;
11
12         __asm__ __volatile__ (
13                 "1:                                     \n\t"
14                 "movli.l        @%2, %0 ! xchg_u32      \n\t"
15                 "mov            %0, %1                  \n\t"
16                 "mov            %3, %0                  \n\t"
17                 "movco.l        %0, @%2                 \n\t"
18                 "bf             1b                      \n\t"
19                 "synco                                  \n\t"
20                 : "=&z"(tmp), "=&r" (retval)
21                 : "r" (m), "r" (val)
22                 : "t", "memory"
23         );
24
25         return retval;
26 }
27
28 static inline unsigned long
29 __cmpxchg_u32(volatile u32 *m, unsigned long old, unsigned long new)
30 {
31         unsigned long retval;
32         unsigned long tmp;
33
34         __asm__ __volatile__ (
35                 "1:                                             \n\t"
36                 "movli.l        @%2, %0 ! __cmpxchg_u32         \n\t"
37                 "mov            %0, %1                          \n\t"
38                 "cmp/eq         %1, %3                          \n\t"
39                 "bf             2f                              \n\t"
40                 "mov            %4, %0                          \n\t"
41                 "2:                                             \n\t"
42                 "movco.l        %0, @%2                         \n\t"
43                 "bf             1b                              \n\t"
44                 "synco                                          \n\t"
45                 : "=&z" (tmp), "=&r" (retval)
46                 : "r" (m), "r" (old), "r" (new)
47                 : "t", "memory"
48         );
49
50         return retval;
51 }
52
53 static inline u32 __xchg_cmpxchg(volatile void *ptr, u32 x, int size)
54 {
55         int off = (unsigned long)ptr % sizeof(u32);
56         volatile u32 *p = ptr - off;
57 #ifdef __BIG_ENDIAN
58         int bitoff = (sizeof(u32) - 1 - off) * BITS_PER_BYTE;
59 #else
60         int bitoff = off * BITS_PER_BYTE;
61 #endif
62         u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff;
63         u32 oldv, newv;
64         u32 ret;
65
66         do {
67                 oldv = READ_ONCE(*p);
68                 ret = (oldv & bitmask) >> bitoff;
69                 newv = (oldv & ~bitmask) | (x << bitoff);
70         } while (__cmpxchg_u32(p, oldv, newv) != oldv);
71
72         return ret;
73 }
74
75 static inline unsigned long xchg_u16(volatile u16 *m, unsigned long val)
76 {
77         return __xchg_cmpxchg(m, val, sizeof *m);
78 }
79
80 static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
81 {
82         return __xchg_cmpxchg(m, val, sizeof *m);
83 }
84
85 #endif /* __ASM_SH_CMPXCHG_LLSC_H */