1 /* Machine-dependent pthreads configuration and inline functions.
2    Xtensa version.
3 
4    Copyright (C) 2007 Free Software Foundation, Inc.
5    This file is part of the GNU C Library.
6 
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11 
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16 
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, see
19    <http://www.gnu.org/licenses/>.  */
20 
21 #ifndef _PT_MACHINE_H
22 #define _PT_MACHINE_H   1
23 
24 #include <bits/xtensa-config.h>
25 #include <sys/syscall.h>
26 #include <asm/unistd.h>
27 
28 #ifndef PT_EI
29 # define PT_EI extern inline __attribute__ ((gnu_inline))
30 #endif
31 
32 #define MEMORY_BARRIER() __asm__ ("memw" : : : "memory")
33 #define HAS_COMPARE_AND_SWAP
34 
35 extern long int testandset (int *spinlock);
36 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
37 
38 #if XCHAL_HAVE_EXCLUSIVE
39 
40 /* Spinlock implementation; required.  */
41 PT_EI long int
testandset(int * spinlock)42 testandset (int *spinlock)
43 {
44 	unsigned long tmp;
45 	__asm__ volatile (
46 "	memw				\n"
47 "1:	l32ex	%0, %1			\n"
48 "	bnez	%0, 2f			\n"
49 "	movi	%0, 1			\n"
50 "	s32ex	%0, %1			\n"
51 "	getex	%0			\n"
52 "	beqz	%0, 1b			\n"
53 "	movi	%0, 0			\n"
54 "	memw				\n"
55 "2:					\n"
56 	: "=&a" (tmp)
57 	: "a" (spinlock)
58 	: "memory"
59 	);
60 	return tmp;
61 }
62 
63 PT_EI int
__compare_and_swap(long int * p,long int oldval,long int newval)64 __compare_and_swap (long int *p, long int oldval, long int newval)
65 {
66         unsigned long tmp;
67         unsigned long value;
68         __asm__ volatile (
69 "       memw                         \n"
70 "1:     l32ex   %0, %2               \n"
71 "       bne     %0, %4, 2f           \n"
72 "       mov     %1, %3               \n"
73 "       s32ex   %1, %2               \n"
74 "       getex   %1                   \n"
75 "       beqz    %1, 1b               \n"
76 "       memw                         \n"
77 "2:                                  \n"
78           : "=&a" (tmp), "=&a" (value)
79           : "a" (p), "a" (newval), "a" (oldval)
80           : "memory" );
81 
82         return tmp == oldval;
83 }
84 
85 #elif XCHAL_HAVE_S32C1I
86 
87 /* Spinlock implementation; required.  */
88 PT_EI long int
testandset(int * spinlock)89 testandset (int *spinlock)
90 {
91 	unsigned long tmp;
92 	__asm__ volatile (
93 "	movi	%0, 0			\n"
94 "	wsr	%0, SCOMPARE1		\n"
95 "	movi	%0, 1			\n"
96 "	s32c1i	%0, %1			\n"
97 	: "=&a" (tmp), "+m" (*spinlock)
98 	:: "memory"
99 	);
100 	return tmp;
101 }
102 
103 PT_EI int
__compare_and_swap(long int * p,long int oldval,long int newval)104 __compare_and_swap (long int *p, long int oldval, long int newval)
105 {
106         unsigned long tmp;
107         unsigned long value;
108         __asm__ volatile (
109 "1:     l32i    %0, %2               \n"
110 "       bne     %0, %4, 2f           \n"
111 "       wsr     %0, SCOMPARE1        \n"
112 "       mov     %1, %0               \n"
113 "       mov     %0, %3               \n"
114 "       s32c1i  %0, %2               \n"
115 "       bne     %1, %0, 1b           \n"
116 "2:                                  \n"
117           : "=&a" (tmp), "=&a" (value), "+m" (*p)
118           : "a" (newval), "a" (oldval)
119           : "memory" );
120 
121         return tmp == oldval;
122 }
123 
124 #else
125 
126 #error No hardware atomic operations
127 
128 #endif
129 
130 /* Get some notion of the current stack.  Need not be exactly the top
131    of the stack, just something somewhere in the current frame.  */
132 #define CURRENT_STACK_FRAME __builtin_frame_address (0)
133 
134 #endif /* _PT_MACHINE_H */
135