162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_X86_RMWcc
362306a36Sopenharmony_ci#define _ASM_X86_RMWcc
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/args.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define __CLOBBERS_MEM(clb...)	"memory", ## clb
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __GCC_ASM_FLAG_OUTPUTS__
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/* Use asm goto */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define __GEN_RMWcc(fullop, _var, cc, clobbers, ...)			\
1462306a36Sopenharmony_ci({									\
1562306a36Sopenharmony_ci	bool c = false;							\
1662306a36Sopenharmony_ci	asm goto (fullop "; j" #cc " %l[cc_label]"		\
1762306a36Sopenharmony_ci			: : [var] "m" (_var), ## __VA_ARGS__		\
1862306a36Sopenharmony_ci			: clobbers : cc_label);				\
1962306a36Sopenharmony_ci	if (0) {							\
2062306a36Sopenharmony_cicc_label:	c = true;						\
2162306a36Sopenharmony_ci	}								\
2262306a36Sopenharmony_ci	c;								\
2362306a36Sopenharmony_ci})
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#else /* defined(__GCC_ASM_FLAG_OUTPUTS__) */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Use flags output or a set instruction */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define __GEN_RMWcc(fullop, _var, cc, clobbers, ...)			\
3062306a36Sopenharmony_ci({									\
3162306a36Sopenharmony_ci	bool c;								\
3262306a36Sopenharmony_ci	asm volatile (fullop CC_SET(cc)					\
3362306a36Sopenharmony_ci			: [var] "+m" (_var), CC_OUT(cc) (c)		\
3462306a36Sopenharmony_ci			: __VA_ARGS__ : clobbers);			\
3562306a36Sopenharmony_ci	c;								\
3662306a36Sopenharmony_ci})
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define GEN_UNARY_RMWcc_4(op, var, cc, arg0)				\
4162306a36Sopenharmony_ci	__GEN_RMWcc(op " " arg0, var, cc, __CLOBBERS_MEM())
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define GEN_UNARY_RMWcc_3(op, var, cc)					\
4462306a36Sopenharmony_ci	GEN_UNARY_RMWcc_4(op, var, cc, "%[var]")
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define GEN_UNARY_RMWcc(X...)	CONCATENATE(GEN_UNARY_RMWcc_, COUNT_ARGS(X))(X)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define GEN_BINARY_RMWcc_6(op, var, cc, vcon, _val, arg0)		\
4962306a36Sopenharmony_ci	__GEN_RMWcc(op " %[val], " arg0, var, cc,			\
5062306a36Sopenharmony_ci		    __CLOBBERS_MEM(), [val] vcon (_val))
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define GEN_BINARY_RMWcc_5(op, var, cc, vcon, val)			\
5362306a36Sopenharmony_ci	GEN_BINARY_RMWcc_6(op, var, cc, vcon, val, "%[var]")
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define GEN_BINARY_RMWcc(X...)	CONCATENATE(GEN_BINARY_RMWcc_, COUNT_ARGS(X))(X)
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define GEN_UNARY_SUFFIXED_RMWcc(op, suffix, var, cc, clobbers...)	\
5862306a36Sopenharmony_ci	__GEN_RMWcc(op " %[var]\n\t" suffix, var, cc,			\
5962306a36Sopenharmony_ci		    __CLOBBERS_MEM(clobbers))
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define GEN_BINARY_SUFFIXED_RMWcc(op, suffix, var, cc, vcon, _val, clobbers...)\
6262306a36Sopenharmony_ci	__GEN_RMWcc(op " %[val], %[var]\n\t" suffix, var, cc,		\
6362306a36Sopenharmony_ci		    __CLOBBERS_MEM(clobbers), [val] vcon (_val))
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#endif /* _ASM_X86_RMWcc */
66