134f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker/*
234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker * cmpxchg.h -- forked from asm/atomic.h with this copyright:
334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *
434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker * Copyright 2010 Tilera Corporation. All Rights Reserved.
534f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *
634f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   This program is free software; you can redistribute it and/or
734f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   modify it under the terms of the GNU General Public License
834f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   as published by the Free Software Foundation, version 2.
934f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *
1034f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   This program is distributed in the hope that it will be useful, but
1134f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   WITHOUT ANY WARRANTY; without even the implied warranty of
1234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
1334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   NON INFRINGEMENT.  See the GNU General Public License for
1434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *   more details.
1534f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker *
1634f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker */
1734f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
1834f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker#ifndef _ASM_TILE_CMPXCHG_H
1934f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker#define _ASM_TILE_CMPXCHG_H
2034f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
2134f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker#ifndef __ASSEMBLY__
2234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
236dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#include <asm/barrier.h>
2434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
256dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf/* Nonexistent functions intended to cause compile errors. */
266dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalfextern void __xchg_called_with_bad_pointer(void)
276dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	__compiletime_error("Bad argument size for xchg");
286dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalfextern void __cmpxchg_called_with_bad_pointer(void)
296dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	__compiletime_error("Bad argument size for cmpxchg");
306dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
316dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#ifndef __tilegx__
326dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
336dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf/* Note the _atomic_xxx() routines include a final mb(). */
346dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalfint _atomic_xchg(int *ptr, int n);
356dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalfint _atomic_xchg_add(int *v, int i);
366dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalfint _atomic_xchg_add_unless(int *v, int a, int u);
376dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalfint _atomic_cmpxchg(int *ptr, int o, int n);
38b924a69067b00d3121debae5a738fb0bcbbbb03cChen Ganglong long _atomic64_xchg(long long *v, long long n);
39b924a69067b00d3121debae5a738fb0bcbbbb03cChen Ganglong long _atomic64_xchg_add(long long *v, long long i);
40b924a69067b00d3121debae5a738fb0bcbbbb03cChen Ganglong long _atomic64_xchg_add_unless(long long *v, long long a, long long u);
41b924a69067b00d3121debae5a738fb0bcbbbb03cChen Ganglong long _atomic64_cmpxchg(long long *v, long long o, long long n);
426dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
436dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define xchg(ptr, n)							\
446dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	({								\
456dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		if (sizeof(*(ptr)) != 4)				\
466dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			__xchg_called_with_bad_pointer();		\
476dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
486dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		(typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n));	\
496dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	})
506dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
516dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define cmpxchg(ptr, o, n)						\
526dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	({								\
536dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		if (sizeof(*(ptr)) != 4)				\
546dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			__cmpxchg_called_with_bad_pointer();		\
556dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
56b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang		(typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o,	\
57b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang						(int)n);		\
586dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	})
596dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
606dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define xchg64(ptr, n)							\
616dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	({								\
626dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		if (sizeof(*(ptr)) != 8)				\
636dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			__xchg_called_with_bad_pointer();		\
646dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
65b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang		(typeof(*(ptr)))_atomic64_xchg((long long *)(ptr),	\
66b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang						(long long)(n));	\
676dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	})
686dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
696dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define cmpxchg64(ptr, o, n)						\
706dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	({								\
716dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		if (sizeof(*(ptr)) != 8)				\
726dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			__cmpxchg_called_with_bad_pointer();		\
736dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
74b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang		(typeof(*(ptr)))_atomic64_cmpxchg((long long *)ptr,	\
75b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang					(long long)o, (long long)n);	\
766dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf	})
776dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
786dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#else
796dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
806dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define xchg(ptr, n)							\
8134f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker	({								\
8234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		typeof(*(ptr)) __x;					\
836dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
8434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		switch (sizeof(*(ptr))) {				\
8534f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		case 4:							\
866dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			__x = (typeof(__x))(unsigned long)		\
87b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang				__insn_exch4((ptr),			\
88b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang					(u32)(unsigned long)(n));	\
8934f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker			break;						\
9034f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		case 8:							\
91b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang			__x = (typeof(__x))				\
926dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf				__insn_exch((ptr), (unsigned long)(n));	\
9334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker			break;						\
9434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		default:						\
9534f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker			__xchg_called_with_bad_pointer();		\
966dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			break;						\
9734f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		}							\
986dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
9934f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		__x;							\
10034f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker	})
10134f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
10234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker#define cmpxchg(ptr, o, n)						\
10334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker	({								\
10434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		typeof(*(ptr)) __x;					\
1056dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		__insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o));	\
1066dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
10734f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		switch (sizeof(*(ptr))) {				\
10834f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		case 4:							\
1096dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			__x = (typeof(__x))(unsigned long)		\
110b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang				__insn_cmpexch4((ptr),			\
111b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang					(u32)(unsigned long)(n));	\
11234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker			break;						\
11334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		case 8:							\
114b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang			__x = (typeof(__x))__insn_cmpexch((ptr),	\
115b924a69067b00d3121debae5a738fb0bcbbbb03cChen Gang						(long long)(n));	\
11634f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker			break;						\
11734f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		default:						\
11834f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker			__cmpxchg_called_with_bad_pointer();		\
1196dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf			break;						\
12034f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		}							\
1216dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf		smp_mb();						\
12234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker		__x;							\
12334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker	})
12434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
1256dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define xchg64 xchg
1266dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define cmpxchg64 cmpxchg
12734f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
1286dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#endif
1296dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf
1306dc9658fa1af9f58d358692b68135f464c167e10Chris Metcalf#define tas(ptr) xchg((ptr), 1)
131cf3a13d790f9760c4bfcae802aaba80efb3519afChen Gang
13234f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker#endif /* __ASSEMBLY__ */
13334f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker
13434f2c0ac111aaf090c7d2432dab532640870733aPaul Gortmaker#endif /* _ASM_TILE_CMPXCHG_H */
135