18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_RMWcc
38c2ecf20Sopenharmony_ci#define _ASM_X86_RMWcc
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/* This counts to 12. Any more, it will return 13th argument. */
68c2ecf20Sopenharmony_ci#define __RMWcc_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _n, X...) _n
78c2ecf20Sopenharmony_ci#define RMWcc_ARGS(X...) __RMWcc_ARGS(, ##X, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define __RMWcc_CONCAT(a, b) a ## b
108c2ecf20Sopenharmony_ci#define RMWcc_CONCAT(a, b) __RMWcc_CONCAT(a, b)
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#define __CLOBBERS_MEM(clb...)	"memory", ## clb
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#if !defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(CONFIG_CC_HAS_ASM_GOTO)
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* Use asm goto */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define __GEN_RMWcc(fullop, _var, cc, clobbers, ...)			\
198c2ecf20Sopenharmony_ci({									\
208c2ecf20Sopenharmony_ci	bool c = false;							\
218c2ecf20Sopenharmony_ci	asm_volatile_goto (fullop "; j" #cc " %l[cc_label]"		\
228c2ecf20Sopenharmony_ci			: : [var] "m" (_var), ## __VA_ARGS__		\
238c2ecf20Sopenharmony_ci			: clobbers : cc_label);				\
248c2ecf20Sopenharmony_ci	if (0) {							\
258c2ecf20Sopenharmony_cicc_label:	c = true;						\
268c2ecf20Sopenharmony_ci	}								\
278c2ecf20Sopenharmony_ci	c;								\
288c2ecf20Sopenharmony_ci})
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#else /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CONFIG_CC_HAS_ASM_GOTO) */
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* Use flags output or a set instruction */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define __GEN_RMWcc(fullop, _var, cc, clobbers, ...)			\
358c2ecf20Sopenharmony_ci({									\
368c2ecf20Sopenharmony_ci	bool c;								\
378c2ecf20Sopenharmony_ci	asm volatile (fullop CC_SET(cc)					\
388c2ecf20Sopenharmony_ci			: [var] "+m" (_var), CC_OUT(cc) (c)		\
398c2ecf20Sopenharmony_ci			: __VA_ARGS__ : clobbers);			\
408c2ecf20Sopenharmony_ci	c;								\
418c2ecf20Sopenharmony_ci})
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CONFIG_CC_HAS_ASM_GOTO) */
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define GEN_UNARY_RMWcc_4(op, var, cc, arg0)				\
468c2ecf20Sopenharmony_ci	__GEN_RMWcc(op " " arg0, var, cc, __CLOBBERS_MEM())
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define GEN_UNARY_RMWcc_3(op, var, cc)					\
498c2ecf20Sopenharmony_ci	GEN_UNARY_RMWcc_4(op, var, cc, "%[var]")
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define GEN_UNARY_RMWcc(X...) RMWcc_CONCAT(GEN_UNARY_RMWcc_, RMWcc_ARGS(X))(X)
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define GEN_BINARY_RMWcc_6(op, var, cc, vcon, _val, arg0)		\
548c2ecf20Sopenharmony_ci	__GEN_RMWcc(op " %[val], " arg0, var, cc,			\
558c2ecf20Sopenharmony_ci		    __CLOBBERS_MEM(), [val] vcon (_val))
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define GEN_BINARY_RMWcc_5(op, var, cc, vcon, val)			\
588c2ecf20Sopenharmony_ci	GEN_BINARY_RMWcc_6(op, var, cc, vcon, val, "%[var]")
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define GEN_BINARY_RMWcc(X...) RMWcc_CONCAT(GEN_BINARY_RMWcc_, RMWcc_ARGS(X))(X)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define GEN_UNARY_SUFFIXED_RMWcc(op, suffix, var, cc, clobbers...)	\
638c2ecf20Sopenharmony_ci	__GEN_RMWcc(op " %[var]\n\t" suffix, var, cc,			\
648c2ecf20Sopenharmony_ci		    __CLOBBERS_MEM(clobbers))
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define GEN_BINARY_SUFFIXED_RMWcc(op, suffix, var, cc, vcon, _val, clobbers...)\
678c2ecf20Sopenharmony_ci	__GEN_RMWcc(op " %[val], %[var]\n\t" suffix, var, cc,		\
688c2ecf20Sopenharmony_ci		    __CLOBBERS_MEM(clobbers), [val] vcon (_val))
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#endif /* _ASM_X86_RMWcc */
71