Commit b387dc04 authored by Max Filippov's avatar Max Filippov
Browse files

xtensa: use macros to generate *_bit and test_and_*_bit functions



Parameterize macros with function name, opcode and inversion pattern.
This reduces code duplication removing 2/3 of definitions.

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent cbc6e287
Loading
Loading
Loading
Loading
+92 −229
Original line number Diff line number Diff line
@@ -98,247 +98,110 @@ static inline unsigned long __fls(unsigned long word)

#if XCHAL_HAVE_EXCLUSIVE

static inline void set_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32ex   %0, %2\n"
			"       or      %0, %0, %1\n"
			"       s32ex   %0, %2\n"
			"       getex   %0\n"
			"       beqz    %0, 1b\n"
			: "=&a" (tmp)
			: "a" (mask), "a" (p)
			: "memory");
}

static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32ex   %0, %2\n"
			"       and     %0, %0, %1\n"
			"       s32ex   %0, %2\n"
			"       getex   %0\n"
			"       beqz    %0, 1b\n"
			: "=&a" (tmp)
			: "a" (~mask), "a" (p)
			: "memory");
}

static inline void change_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32ex   %0, %2\n"
			"       xor     %0, %0, %1\n"
			"       s32ex   %0, %2\n"
			"       getex   %0\n"
			"       beqz    %0, 1b\n"
			: "=&a" (tmp)
			: "a" (mask), "a" (p)
			: "memory");
}

static inline int
test_and_set_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32ex   %1, %3\n"
			"       or      %0, %1, %2\n"
			"       s32ex   %0, %3\n"
			"       getex   %0\n"
			"       beqz    %0, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (mask), "a" (p)
			: "memory");

	return value & mask;
}

static inline int
test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32ex   %1, %3\n"
			"       and     %0, %1, %2\n"
			"       s32ex   %0, %3\n"
			"       getex   %0\n"
			"       beqz    %0, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (~mask), "a" (p)
			: "memory");

	return value & mask;
}

static inline int
test_and_change_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32ex   %1, %3\n"
			"       xor     %0, %1, %2\n"
			"       s32ex   %0, %3\n"
			"       getex   %0\n"
			"       beqz    %0, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (mask), "a" (p)
			: "memory");

	return value & mask;
#define BIT_OP(op, insn, inv)						\
static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\
{									\
	unsigned long tmp;						\
	unsigned long mask = 1UL << (bit & 31);				\
									\
	p += bit >> 5;							\
									\
	__asm__ __volatile__(						\
			"1:     l32ex   %0, %2\n"			\
			"      "insn"   %0, %0, %1\n"			\
			"       s32ex   %0, %2\n"			\
			"       getex   %0\n"				\
			"       beqz    %0, 1b\n"			\
			: "=&a" (tmp)					\
			: "a" (inv mask), "a" (p)			\
			: "memory");					\
}

#define TEST_AND_BIT_OP(op, insn, inv)					\
static inline int							\
test_and_##op##_bit(unsigned int bit, volatile unsigned long *p)	\
{									\
	unsigned long tmp, value;					\
	unsigned long mask = 1UL << (bit & 31);				\
									\
	p += bit >> 5;							\
									\
	__asm__ __volatile__(						\
			"1:     l32ex   %1, %3\n"			\
			"      "insn"   %0, %1, %2\n"			\
			"       s32ex   %0, %3\n"			\
			"       getex   %0\n"				\
			"       beqz    %0, 1b\n"			\
			: "=&a" (tmp), "=&a" (value)			\
			: "a" (inv mask), "a" (p)			\
			: "memory");					\
									\
	return value & mask;						\
}

#elif XCHAL_HAVE_S32C1I

static inline void set_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32i    %1, %3, 0\n"
			"       wsr     %1, scompare1\n"
			"       or      %0, %1, %2\n"
			"       s32c1i  %0, %3, 0\n"
			"       bne     %0, %1, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (mask), "a" (p)
			: "memory");
}

static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32i    %1, %3, 0\n"
			"       wsr     %1, scompare1\n"
			"       and     %0, %1, %2\n"
			"       s32c1i  %0, %3, 0\n"
			"       bne     %0, %1, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (~mask), "a" (p)
			: "memory");
#define BIT_OP(op, insn, inv)						\
static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\
{									\
	unsigned long tmp, value;					\
	unsigned long mask = 1UL << (bit & 31);				\
									\
	p += bit >> 5;							\
									\
	__asm__ __volatile__(						\
			"1:     l32i    %1, %3, 0\n"			\
			"       wsr     %1, scompare1\n"		\
			"      "insn"   %0, %1, %2\n"			\
			"       s32c1i  %0, %3, 0\n"			\
			"       bne     %0, %1, 1b\n"			\
			: "=&a" (tmp), "=&a" (value)			\
			: "a" (inv mask), "a" (p)			\
			: "memory");					\
}

#define TEST_AND_BIT_OP(op, insn, inv)					\
static inline int							\
test_and_##op##_bit(unsigned int bit, volatile unsigned long *p)	\
{									\
	unsigned long tmp, value;					\
	unsigned long mask = 1UL << (bit & 31);				\
									\
	p += bit >> 5;							\
									\
	__asm__ __volatile__(						\
			"1:     l32i    %1, %3, 0\n"			\
			"       wsr     %1, scompare1\n"		\
			"      "insn"   %0, %1, %2\n"			\
			"       s32c1i  %0, %3, 0\n"			\
			"       bne     %0, %1, 1b\n"			\
			: "=&a" (tmp), "=&a" (value)			\
			: "a" (inv mask), "a" (p)			\
			: "memory");					\
									\
	return tmp & mask;						\
}

static inline void change_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32i    %1, %3, 0\n"
			"       wsr     %1, scompare1\n"
			"       xor     %0, %1, %2\n"
			"       s32c1i  %0, %3, 0\n"
			"       bne     %0, %1, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (mask), "a" (p)
			: "memory");
}
#else

static inline int
test_and_set_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32i    %1, %3, 0\n"
			"       wsr     %1, scompare1\n"
			"       or      %0, %1, %2\n"
			"       s32c1i  %0, %3, 0\n"
			"       bne     %0, %1, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (mask), "a" (p)
			: "memory");

	return tmp & mask;
}
#define BIT_OP(op, insn, inv)
#define TEST_AND_BIT_OP(op, insn, inv)

static inline int
test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32i    %1, %3, 0\n"
			"       wsr     %1, scompare1\n"
			"       and     %0, %1, %2\n"
			"       s32c1i  %0, %3, 0\n"
			"       bne     %0, %1, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (~mask), "a" (p)
			: "memory");

	return tmp & mask;
}
#include <asm-generic/bitops/atomic.h>

static inline int
test_and_change_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long tmp, value;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	__asm__ __volatile__(
			"1:     l32i    %1, %3, 0\n"
			"       wsr     %1, scompare1\n"
			"       xor     %0, %1, %2\n"
			"       s32c1i  %0, %3, 0\n"
			"       bne     %0, %1, 1b\n"
			: "=&a" (tmp), "=&a" (value)
			: "a" (mask), "a" (p)
			: "memory");

	return tmp & mask;
}
#endif /* XCHAL_HAVE_S32C1I */

#else
#define BIT_OPS(op, insn, inv)		\
	BIT_OP(op, insn, inv)		\
	TEST_AND_BIT_OP(op, insn, inv)

#include <asm-generic/bitops/atomic.h>
BIT_OPS(set, "or", )
BIT_OPS(clear, "and", ~)
BIT_OPS(change, "xor", )

#endif /* XCHAL_HAVE_S32C1I */
#undef BIT_OPS
#undef BIT_OP
#undef TEST_AND_BIT_OP

#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/le.h>