3 #define LLSC_CLOBBERS "r0", "t", "memory"
4 #define LLSC_START(mem) "synco\n" \
5 "0: movli.l @" mem ", r0\n"
6 #define LLSC_END(mem) \
7 "1: movco.l r0, @" mem "\n" \
11 /* gusa is a hack in the kernel which lets you create a sequence of instructions
12 * which will be restarted if the process is preempted in the middle of the
13 * sequence. It will do for implementing atomics on non-smp systems. ABI is:
14 * r0 = address of first instruction after the atomic sequence
15 * r1 = original stack pointer
16 * r15 = -1 * length of atomic sequence in bytes
18 #define GUSA_CLOBBERS "r0", "r1", "memory"
19 #define GUSA_START(mem,old,nop) \
24 " mov #(0f-1f), r15\n" \
25 "0: mov.l @" mem ", " old "\n"
26 /* the target of mova must be 4 byte aligned, so we may need a nop */
27 #define GUSA_START_ODD(mem,old) GUSA_START(mem,old,"")
28 #define GUSA_START_EVEN(mem,old) GUSA_START(mem,old,"\tnop\n")
29 #define GUSA_END(mem,new) \
30 " mov.l " new ", @" mem "\n" \
33 #define CPU_HAS_LLSC 0x0040
35 int __sh_cas(volatile int *p, int t, int s)
38 if (__hwcap & CPU_HAS_LLSC) {
46 : "=&r"(old) : "r"(p), "r"(t), "r"(s) : LLSC_CLOBBERS);
49 GUSA_START_EVEN("%1", "%0")
53 : "=&r"(old) : "r"(p), "r"(t), "r"(s) : GUSA_CLOBBERS, "t");
58 int __sh_swap(volatile int *x, int v)
61 if (__hwcap & CPU_HAS_LLSC) {
67 : "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS);
70 GUSA_START_EVEN("%1", "%0")
72 : "=&r"(old) : "r"(x), "r"(v) : GUSA_CLOBBERS);
77 int __sh_fetch_add(volatile int *x, int v)
80 if (__hwcap & CPU_HAS_LLSC) {
86 : "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS);
89 GUSA_START_EVEN("%2", "%0")
93 : "=&r"(old), "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS);
98 void __sh_store(volatile int *p, int x)
100 if (__hwcap & CPU_HAS_LLSC) {
101 __asm__ __volatile__(
105 : : "r"(p), "r"(x) : "memory");
107 __asm__ __volatile__(
109 : : "r"(p), "r"(x) : "memory");
113 void __sh_and(volatile int *x, int v)
116 if (__hwcap & CPU_HAS_LLSC) {
117 __asm__ __volatile__(
121 : : "r"(x), "r"(v) : LLSC_CLOBBERS);
123 __asm__ __volatile__(
124 GUSA_START_ODD("%1", "%0")
127 : "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS);
131 void __sh_or(volatile int *x, int v)
134 if (__hwcap & CPU_HAS_LLSC) {
135 __asm__ __volatile__(
139 : : "r"(x), "r"(v) : LLSC_CLOBBERS);
141 __asm__ __volatile__(
142 GUSA_START_ODD("%1", "%0")
145 : "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS);