Linux 3.11-rc3
[cris-mirror.git] / arch / mn10300 / include / asm / cmpxchg.h
blob97a4aaf387a67197e89066e72b5ea1b3ce800837
1 /* MN10300 Atomic xchg/cmpxchg operations
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
11 #ifndef _ASM_CMPXCHG_H
12 #define _ASM_CMPXCHG_H
14 #include <asm/irqflags.h>
16 #ifdef CONFIG_SMP
17 #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
18 static inline
19 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
21 unsigned long status;
22 unsigned long oldval;
24 asm volatile(
25 "1: mov %4,(_AAR,%3) \n"
26 " mov (_ADR,%3),%1 \n"
27 " mov %5,(_ADR,%3) \n"
28 " mov (_ADR,%3),%0 \n" /* flush */
29 " mov (_ASR,%3),%0 \n"
30 " or %0,%0 \n"
31 " bne 1b \n"
32 : "=&r"(status), "=&r"(oldval), "=m"(*m)
33 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
34 : "memory", "cc");
36 return oldval;
39 static inline unsigned long __cmpxchg(volatile unsigned long *m,
40 unsigned long old, unsigned long new)
42 unsigned long status;
43 unsigned long oldval;
45 asm volatile(
46 "1: mov %4,(_AAR,%3) \n"
47 " mov (_ADR,%3),%1 \n"
48 " cmp %5,%1 \n"
49 " bne 2f \n"
50 " mov %6,(_ADR,%3) \n"
51 "2: mov (_ADR,%3),%0 \n" /* flush */
52 " mov (_ASR,%3),%0 \n"
53 " or %0,%0 \n"
54 " bne 1b \n"
55 : "=&r"(status), "=&r"(oldval), "=m"(*m)
56 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
57 "r"(old), "r"(new)
58 : "memory", "cc");
60 return oldval;
62 #else /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
63 #error "No SMP atomic operation support!"
64 #endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
66 #else /* CONFIG_SMP */
69 * Emulate xchg for non-SMP MN10300
71 struct __xchg_dummy { unsigned long a[100]; };
72 #define __xg(x) ((struct __xchg_dummy *)(x))
74 static inline
75 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
77 unsigned long oldval;
78 unsigned long flags;
80 flags = arch_local_cli_save();
81 oldval = *m;
82 *m = val;
83 arch_local_irq_restore(flags);
84 return oldval;
88 * Emulate cmpxchg for non-SMP MN10300
90 static inline unsigned long __cmpxchg(volatile unsigned long *m,
91 unsigned long old, unsigned long new)
93 unsigned long oldval;
94 unsigned long flags;
96 flags = arch_local_cli_save();
97 oldval = *m;
98 if (oldval == old)
99 *m = new;
100 arch_local_irq_restore(flags);
101 return oldval;
104 #endif /* CONFIG_SMP */
106 #define xchg(ptr, v) \
107 ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \
108 (unsigned long)(v)))
110 #define cmpxchg(ptr, o, n) \
111 ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
112 (unsigned long)(o), \
113 (unsigned long)(n)))
115 #endif /* _ASM_CMPXCHG_H */