162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_SH_ATOMIC_GRB_H
362306a36Sopenharmony_ci#define __ASM_SH_ATOMIC_GRB_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#define ATOMIC_OP(op)							\
662306a36Sopenharmony_cistatic inline void arch_atomic_##op(int i, atomic_t *v)			\
762306a36Sopenharmony_ci{									\
862306a36Sopenharmony_ci	int tmp;							\
962306a36Sopenharmony_ci									\
1062306a36Sopenharmony_ci	__asm__ __volatile__ (						\
1162306a36Sopenharmony_ci		"   .align 2              \n\t"				\
1262306a36Sopenharmony_ci		"   mova    1f,   r0      \n\t" /* r0 = end point */	\
1362306a36Sopenharmony_ci		"   mov    r15,   r1      \n\t" /* r1 = saved sp */	\
1462306a36Sopenharmony_ci		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */	\
1562306a36Sopenharmony_ci		"   mov.l  @%1,   %0      \n\t" /* load  old value */	\
1662306a36Sopenharmony_ci		" " #op "   %2,   %0      \n\t" /* $op */		\
1762306a36Sopenharmony_ci		"   mov.l   %0,   @%1     \n\t" /* store new value */	\
1862306a36Sopenharmony_ci		"1: mov     r1,   r15     \n\t" /* LOGOUT */		\
1962306a36Sopenharmony_ci		: "=&r" (tmp),						\
2062306a36Sopenharmony_ci		  "+r"  (v)						\
2162306a36Sopenharmony_ci		: "r"   (i)						\
2262306a36Sopenharmony_ci		: "memory" , "r0", "r1");				\
2362306a36Sopenharmony_ci}									\
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define ATOMIC_OP_RETURN(op)						\
2662306a36Sopenharmony_cistatic inline int arch_atomic_##op##_return(int i, atomic_t *v)		\
2762306a36Sopenharmony_ci{									\
2862306a36Sopenharmony_ci	int tmp;							\
2962306a36Sopenharmony_ci									\
3062306a36Sopenharmony_ci	__asm__ __volatile__ (						\
3162306a36Sopenharmony_ci		"   .align 2              \n\t"				\
3262306a36Sopenharmony_ci		"   mova    1f,   r0      \n\t" /* r0 = end point */	\
3362306a36Sopenharmony_ci		"   mov    r15,   r1      \n\t" /* r1 = saved sp */	\
3462306a36Sopenharmony_ci		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */	\
3562306a36Sopenharmony_ci		"   mov.l  @%1,   %0      \n\t" /* load  old value */	\
3662306a36Sopenharmony_ci		" " #op "   %2,   %0      \n\t" /* $op */		\
3762306a36Sopenharmony_ci		"   mov.l   %0,   @%1     \n\t" /* store new value */	\
3862306a36Sopenharmony_ci		"1: mov     r1,   r15     \n\t" /* LOGOUT */		\
3962306a36Sopenharmony_ci		: "=&r" (tmp),						\
4062306a36Sopenharmony_ci		  "+r"  (v)						\
4162306a36Sopenharmony_ci		: "r"   (i)						\
4262306a36Sopenharmony_ci		: "memory" , "r0", "r1");				\
4362306a36Sopenharmony_ci									\
4462306a36Sopenharmony_ci	return tmp;							\
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define ATOMIC_FETCH_OP(op)						\
4862306a36Sopenharmony_cistatic inline int arch_atomic_fetch_##op(int i, atomic_t *v)		\
4962306a36Sopenharmony_ci{									\
5062306a36Sopenharmony_ci	int res, tmp;							\
5162306a36Sopenharmony_ci									\
5262306a36Sopenharmony_ci	__asm__ __volatile__ (						\
5362306a36Sopenharmony_ci		"   .align 2              \n\t"				\
5462306a36Sopenharmony_ci		"   mova    1f,   r0      \n\t" /* r0 = end point */	\
5562306a36Sopenharmony_ci		"   mov    r15,   r1      \n\t" /* r1 = saved sp */	\
5662306a36Sopenharmony_ci		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */	\
5762306a36Sopenharmony_ci		"   mov.l  @%2,   %0      \n\t" /* load old value */	\
5862306a36Sopenharmony_ci		"   mov     %0,   %1      \n\t" /* save old value */	\
5962306a36Sopenharmony_ci		" " #op "   %3,   %0      \n\t" /* $op */		\
6062306a36Sopenharmony_ci		"   mov.l   %0,   @%2     \n\t" /* store new value */	\
6162306a36Sopenharmony_ci		"1: mov     r1,   r15     \n\t" /* LOGOUT */		\
6262306a36Sopenharmony_ci		: "=&r" (tmp), "=&r" (res), "+r"  (v)			\
6362306a36Sopenharmony_ci		: "r"   (i)						\
6462306a36Sopenharmony_ci		: "memory" , "r0", "r1");				\
6562306a36Sopenharmony_ci									\
6662306a36Sopenharmony_ci	return res;							\
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_FETCH_OP(op)
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciATOMIC_OPS(add)
7262306a36Sopenharmony_ciATOMIC_OPS(sub)
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#define arch_atomic_add_return	arch_atomic_add_return
7562306a36Sopenharmony_ci#define arch_atomic_sub_return	arch_atomic_sub_return
7662306a36Sopenharmony_ci#define arch_atomic_fetch_add	arch_atomic_fetch_add
7762306a36Sopenharmony_ci#define arch_atomic_fetch_sub	arch_atomic_fetch_sub
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#undef ATOMIC_OPS
8062306a36Sopenharmony_ci#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op)
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciATOMIC_OPS(and)
8362306a36Sopenharmony_ciATOMIC_OPS(or)
8462306a36Sopenharmony_ciATOMIC_OPS(xor)
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define arch_atomic_fetch_and	arch_atomic_fetch_and
8762306a36Sopenharmony_ci#define arch_atomic_fetch_or	arch_atomic_fetch_or
8862306a36Sopenharmony_ci#define arch_atomic_fetch_xor	arch_atomic_fetch_xor
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#undef ATOMIC_OPS
9162306a36Sopenharmony_ci#undef ATOMIC_FETCH_OP
9262306a36Sopenharmony_ci#undef ATOMIC_OP_RETURN
9362306a36Sopenharmony_ci#undef ATOMIC_OP
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#endif /* __ASM_SH_ATOMIC_GRB_H */
96