1 /* 2 * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> 3 * 4 * This file is licensed under the terms of the GNU General Public License 5 * version 2. This program is licensed "as is" without any warranty of any 6 * kind, whether express or implied. 7 */ 8 9 #ifndef __ASM_OPENRISC_CMPXCHG_H 10 #define __ASM_OPENRISC_CMPXCHG_H 11 12 #include <linux/types.h> 13 14 /* 15 * This function doesn't exist, so you'll get a linker error 16 * if something tries to do an invalid cmpxchg(). 17 */ 18 extern void __cmpxchg_called_with_bad_pointer(void); 19 20 #define __HAVE_ARCH_CMPXCHG 1 21 22 static inline unsigned long 23 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) 24 { 25 if (size != 4) { 26 __cmpxchg_called_with_bad_pointer(); 27 return old; 28 } 29 30 __asm__ __volatile__( 31 "1: l.lwa %0, 0(%1) \n" 32 " l.sfeq %0, %2 \n" 33 " l.bnf 2f \n" 34 " l.nop \n" 35 " l.swa 0(%1), %3 \n" 36 " l.bnf 1b \n" 37 " l.nop \n" 38 "2: \n" 39 : "=&r"(old) 40 : "r"(ptr), "r"(old), "r"(new) 41 : "cc", "memory"); 42 43 return old; 44 } 45 46 #define cmpxchg(ptr, o, n) \ 47 ({ \ 48 (__typeof__(*(ptr))) __cmpxchg((ptr), \ 49 (unsigned long)(o), \ 50 (unsigned long)(n), \ 51 sizeof(*(ptr))); \ 52 }) 53 54 /* 55 * This function doesn't exist, so you'll get a linker error if 56 * something tries to do an invalidly-sized xchg(). 57 */ 58 extern void __xchg_called_with_bad_pointer(void); 59 60 static inline unsigned long __xchg(unsigned long val, volatile void *ptr, 61 int size) 62 { 63 if (size != 4) { 64 __xchg_called_with_bad_pointer(); 65 return val; 66 } 67 68 __asm__ __volatile__( 69 "1: l.lwa %0, 0(%1) \n" 70 " l.swa 0(%1), %2 \n" 71 " l.bnf 1b \n" 72 " l.nop \n" 73 : "=&r"(val) 74 : "r"(ptr), "r"(val) 75 : "cc", "memory"); 76 77 return val; 78 } 79 80 #define xchg(ptr, with) \ 81 ({ \ 82 (__typeof__(*(ptr))) __xchg((unsigned long)(with), \ 83 (ptr), \ 84 sizeof(*(ptr))); \ 85 }) 86 87 #endif /* __ASM_OPENRISC_CMPXCHG_H */ 88