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