162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Compiler-dependent intrinsics.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2002-2003 Hewlett-Packard Co
662306a36Sopenharmony_ci *	David Mosberger-Tang <davidm@hpl.hp.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef _UAPI_ASM_IA64_INTRINSICS_H
962306a36Sopenharmony_ci#define _UAPI_ASM_IA64_INTRINSICS_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifndef __ASSEMBLY__
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/types.h>
1562306a36Sopenharmony_ci/* include compiler specific intrinsics */
1662306a36Sopenharmony_ci#include <asm/ia64regs.h>
1762306a36Sopenharmony_ci#include <asm/gcc_intrin.h>
1862306a36Sopenharmony_ci#include <asm/cmpxchg.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4)		\
2162306a36Sopenharmony_cido {									\
2262306a36Sopenharmony_ci	ia64_set_rr(0x0000000000000000UL, (val0));			\
2362306a36Sopenharmony_ci	ia64_set_rr(0x2000000000000000UL, (val1));			\
2462306a36Sopenharmony_ci	ia64_set_rr(0x4000000000000000UL, (val2));			\
2562306a36Sopenharmony_ci	ia64_set_rr(0x6000000000000000UL, (val3));			\
2662306a36Sopenharmony_ci	ia64_set_rr(0x8000000000000000UL, (val4));			\
2762306a36Sopenharmony_ci} while (0)
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * Force an unresolved reference if someone tries to use
3162306a36Sopenharmony_ci * ia64_fetch_and_add() with a bad value.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ciextern unsigned long __bad_size_for_ia64_fetch_and_add (void);
3462306a36Sopenharmony_ciextern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define IA64_FETCHADD(tmp,v,n,sz,sem)						\
3762306a36Sopenharmony_ci({										\
3862306a36Sopenharmony_ci	switch (sz) {								\
3962306a36Sopenharmony_ci	      case 4:								\
4062306a36Sopenharmony_ci	        tmp = ia64_fetchadd4_##sem((unsigned int *) v, n);		\
4162306a36Sopenharmony_ci		break;								\
4262306a36Sopenharmony_ci										\
4362306a36Sopenharmony_ci	      case 8:								\
4462306a36Sopenharmony_ci	        tmp = ia64_fetchadd8_##sem((unsigned long *) v, n);		\
4562306a36Sopenharmony_ci		break;								\
4662306a36Sopenharmony_ci										\
4762306a36Sopenharmony_ci	      default:								\
4862306a36Sopenharmony_ci		__bad_size_for_ia64_fetch_and_add();				\
4962306a36Sopenharmony_ci	}									\
5062306a36Sopenharmony_ci})
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define ia64_fetchadd(i,v,sem)								\
5362306a36Sopenharmony_ci({											\
5462306a36Sopenharmony_ci	__u64 _tmp;									\
5562306a36Sopenharmony_ci	volatile __typeof__(*(v)) *_v = (v);						\
5662306a36Sopenharmony_ci	/* Can't use a switch () here: gcc isn't always smart enough for that... */	\
5762306a36Sopenharmony_ci	if ((i) == -16)									\
5862306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v)), sem);			\
5962306a36Sopenharmony_ci	else if ((i) == -8)								\
6062306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v)), sem);				\
6162306a36Sopenharmony_ci	else if ((i) == -4)								\
6262306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v)), sem);				\
6362306a36Sopenharmony_ci	else if ((i) == -1)								\
6462306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v)), sem);				\
6562306a36Sopenharmony_ci	else if ((i) == 1)								\
6662306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v)), sem);				\
6762306a36Sopenharmony_ci	else if ((i) == 4)								\
6862306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v)), sem);				\
6962306a36Sopenharmony_ci	else if ((i) == 8)								\
7062306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v)), sem);				\
7162306a36Sopenharmony_ci	else if ((i) == 16)								\
7262306a36Sopenharmony_ci		IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v)), sem);				\
7362306a36Sopenharmony_ci	else										\
7462306a36Sopenharmony_ci		_tmp = __bad_increment_for_ia64_fetch_and_add();			\
7562306a36Sopenharmony_ci	(__typeof__(*(v))) (_tmp);	/* return old value */				\
7662306a36Sopenharmony_ci})
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define ia64_fetch_and_add(i,v)	(ia64_fetchadd(i, v, rel) + (i)) /* return new value */
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#endif
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#endif /* _UAPI_ASM_IA64_INTRINSICS_H */
83