111595172SStefan Kristiansson /* 211595172SStefan Kristiansson * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> 311595172SStefan Kristiansson * 411595172SStefan Kristiansson * This file is licensed under the terms of the GNU General Public License 511595172SStefan Kristiansson * version 2. This program is licensed "as is" without any warranty of any 611595172SStefan Kristiansson * kind, whether express or implied. 711595172SStefan Kristiansson */ 811595172SStefan Kristiansson 911595172SStefan Kristiansson #ifndef __ASM_OPENRISC_CMPXCHG_H 1011595172SStefan Kristiansson #define __ASM_OPENRISC_CMPXCHG_H 1111595172SStefan Kristiansson 1211595172SStefan Kristiansson #include <linux/types.h> 1311595172SStefan Kristiansson 1411595172SStefan Kristiansson /* 1511595172SStefan Kristiansson * This function doesn't exist, so you'll get a linker error 1611595172SStefan Kristiansson * if something tries to do an invalid cmpxchg(). 1711595172SStefan Kristiansson */ 1811595172SStefan Kristiansson extern void __cmpxchg_called_with_bad_pointer(void); 1911595172SStefan Kristiansson 2011595172SStefan Kristiansson #define __HAVE_ARCH_CMPXCHG 1 2111595172SStefan Kristiansson 2211595172SStefan Kristiansson static inline unsigned long 2311595172SStefan Kristiansson __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) 2411595172SStefan Kristiansson { 2511595172SStefan Kristiansson if (size != 4) { 2611595172SStefan Kristiansson __cmpxchg_called_with_bad_pointer(); 2711595172SStefan Kristiansson return old; 2811595172SStefan Kristiansson } 2911595172SStefan Kristiansson 3011595172SStefan Kristiansson __asm__ __volatile__( 3111595172SStefan Kristiansson "1: l.lwa %0, 0(%1) \n" 3211595172SStefan Kristiansson " l.sfeq %0, %2 \n" 3311595172SStefan Kristiansson " l.bnf 2f \n" 3411595172SStefan Kristiansson " l.nop \n" 3511595172SStefan Kristiansson " l.swa 0(%1), %3 \n" 3611595172SStefan Kristiansson " l.bnf 1b \n" 3711595172SStefan Kristiansson " l.nop \n" 3811595172SStefan Kristiansson "2: \n" 3911595172SStefan Kristiansson : "=&r"(old) 4011595172SStefan Kristiansson : "r"(ptr), "r"(old), "r"(new) 4111595172SStefan Kristiansson : "cc", "memory"); 4211595172SStefan Kristiansson 4311595172SStefan Kristiansson return old; 4411595172SStefan Kristiansson } 4511595172SStefan Kristiansson 4611595172SStefan Kristiansson #define cmpxchg(ptr, o, n) \ 4711595172SStefan Kristiansson ({ \ 4811595172SStefan Kristiansson (__typeof__(*(ptr))) __cmpxchg((ptr), \ 4911595172SStefan Kristiansson (unsigned long)(o), \ 5011595172SStefan Kristiansson (unsigned long)(n), \ 5111595172SStefan Kristiansson sizeof(*(ptr))); \ 5211595172SStefan Kristiansson }) 5311595172SStefan Kristiansson 5411595172SStefan Kristiansson /* 5511595172SStefan Kristiansson * This function doesn't exist, so you'll get a linker error if 5611595172SStefan Kristiansson * something tries to do an invalidly-sized xchg(). 5711595172SStefan Kristiansson */ 5811595172SStefan Kristiansson extern void __xchg_called_with_bad_pointer(void); 5911595172SStefan Kristiansson 6011595172SStefan Kristiansson static inline unsigned long __xchg(unsigned long val, volatile void *ptr, 6111595172SStefan Kristiansson int size) 6211595172SStefan Kristiansson { 6311595172SStefan Kristiansson if (size != 4) { 6411595172SStefan Kristiansson __xchg_called_with_bad_pointer(); 6511595172SStefan Kristiansson return val; 6611595172SStefan Kristiansson } 6711595172SStefan Kristiansson 6811595172SStefan Kristiansson __asm__ __volatile__( 6911595172SStefan Kristiansson "1: l.lwa %0, 0(%1) \n" 7011595172SStefan Kristiansson " l.swa 0(%1), %2 \n" 7111595172SStefan Kristiansson " l.bnf 1b \n" 7211595172SStefan Kristiansson " l.nop \n" 7311595172SStefan Kristiansson : "=&r"(val) 7411595172SStefan Kristiansson : "r"(ptr), "r"(val) 7511595172SStefan Kristiansson : "cc", "memory"); 7611595172SStefan Kristiansson 7711595172SStefan Kristiansson return val; 7811595172SStefan Kristiansson } 7911595172SStefan Kristiansson 8011595172SStefan Kristiansson #define xchg(ptr, with) \ 81*8af42949SStafford Horne ({ \ 82*8af42949SStafford Horne (__typeof__(*(ptr))) __xchg((unsigned long)(with), \ 83*8af42949SStafford Horne (ptr), \ 84*8af42949SStafford Horne sizeof(*(ptr))); \ 85*8af42949SStafford Horne }) 8611595172SStefan Kristiansson 8711595172SStefan Kristiansson #endif /* __ASM_OPENRISC_CMPXCHG_H */ 88