]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/arm/freebsd-atomic.c
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / arm / freebsd-atomic.c
CommitLineData
82a19768 1/* FreeBSD specific atomic operations for ARM EABI.
a5544970 2 Copyright (C) 2015-2019 Free Software Foundation, Inc.
82a19768
AT
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23<http://www.gnu.org/licenses/>. */
24
25#include <sys/types.h>
26
27#define HIDDEN __attribute__ ((visibility ("hidden")))
28
29#define ARM_VECTORS_HIGH 0xffff0000U
30#define ARM_TP_ADDRESS (ARM_VECTORS_HIGH + 0x1000)
31#define ARM_RAS_START (ARM_TP_ADDRESS + 4)
32
33void HIDDEN
34__sync_synchronize (void)
35{
36#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) \
37 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__) \
38 || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__) \
39 || defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
40#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
41 __asm __volatile ("dmb" : : : "memory");
42#else
43 __asm __volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory");
44#endif
45#else
46 __asm __volatile ("nop" : : : "memory");
47#endif
48}
49
50#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) \
51 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__) \
52 || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__) \
53 || defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
54
55/* These systems should be supported by the compiler. */
56
57#else /* __ARM_ARCH_5__ */
58
59#define SYNC_LOCK_TEST_AND_SET_N(N, TYPE, LDR, STR) \
60TYPE HIDDEN \
61__sync_lock_test_and_set_##N (TYPE *mem, TYPE val) \
62{ \
63 unsigned int old, temp, ras_start; \
64 \
65 ras_start = ARM_RAS_START; \
66 __asm volatile ( \
67 /* Set up Restartable Atomic Sequence. */ \
68 "1:" \
69 "\tadr %2, 1b\n" \
70 "\tstr %2, [%5]\n" \
71 "\tadr %2, 2f\n" \
72 "\tstr %2, [%5, #4]\n" \
73 \
74 "\t"LDR" %0, %4\n" /* Load old value. */ \
75 "\t"STR" %3, %1\n" /* Store new value. */ \
76 \
77 /* Tear down Restartable Atomic Sequence. */ \
78 "2:" \
79 "\tmov %2, #0x00000000\n" \
80 "\tstr %2, [%5]\n" \
81 "\tmov %2, #0xffffffff\n" \
82 "\tstr %2, [%5, #4]\n" \
83 : "=&r" (old), "=m" (*mem), "=&r" (temp) \
84 : "r" (val), "m" (*mem), "r" (ras_start)); \
85 return (old); \
86}
87
88#define SYNC_LOCK_RELEASE_N(N, TYPE) \
89void HIDDEN \
90__sync_lock_release_##N (TYPE *ptr) \
91{ \
92 /* All writes before this point must be seen before we release \
93 the lock itself. */ \
94 __sync_synchronize (); \
95 *ptr = 0; \
96}
97
98#define SYNC_VAL_CAS_N(N, TYPE, LDR, STREQ) \
99TYPE HIDDEN \
100__sync_val_compare_and_swap_##N (TYPE *mem, TYPE expected, \
101 TYPE desired) \
102{ \
103 unsigned int old, temp, ras_start; \
104 \
105 ras_start = ARM_RAS_START; \
106 __asm volatile ( \
107 /* Set up Restartable Atomic Sequence. */ \
108 "1:" \
109 "\tadr %2, 1b\n" \
110 "\tstr %2, [%6]\n" \
111 "\tadr %2, 2f\n" \
112 "\tstr %2, [%6, #4]\n" \
113 \
114 "\t"LDR" %0, %5\n" /* Load old value. */ \
115 "\tcmp %0, %3\n" /* Compare to expected value. */\
116 "\t"STREQ" %4, %1\n" /* Store new value. */ \
117 \
118 /* Tear down Restartable Atomic Sequence. */ \
119 "2:" \
120 "\tmov %2, #0x00000000\n" \
121 "\tstr %2, [%6]\n" \
122 "\tmov %2, #0xffffffff\n" \
123 "\tstr %2, [%6, #4]\n" \
124 : "=&r" (old), "=m" (*mem), "=&r" (temp) \
125 : "r" (expected), "r" (desired), "m" (*mem), \
126 "r" (ras_start)); \
127 return (old); \
128}
129
130typedef unsigned char bool;
131
132#define SYNC_BOOL_CAS_N(N, TYPE) \
133bool HIDDEN \
134__sync_bool_compare_and_swap_##N (TYPE *ptr, TYPE oldval, \
135 TYPE newval) \
136{ \
137 TYPE actual_oldval \
138 = __sync_val_compare_and_swap_##N (ptr, oldval, newval); \
139 return (oldval == actual_oldval); \
140}
141
142#define SYNC_FETCH_AND_OP_N(N, TYPE, LDR, STR, NAME, OP) \
143TYPE HIDDEN \
144__sync_fetch_and_##NAME##_##N (TYPE *mem, TYPE val) \
145{ \
146 unsigned int old, temp, ras_start; \
147 \
148 ras_start = ARM_RAS_START; \
149 __asm volatile ( \
150 /* Set up Restartable Atomic Sequence. */ \
151 "1:" \
152 "\tadr %2, 1b\n" \
153 "\tstr %2, [%5]\n" \
154 "\tadr %2, 2f\n" \
155 "\tstr %2, [%5, #4]\n" \
156 \
157 "\t"LDR" %0, %4\n" /* Load old value. */ \
158 "\t"OP" %2, %0, %3\n" /* Calculate new value. */ \
159 "\t"STR" %2, %1\n" /* Store new value. */ \
160 \
161 /* Tear down Restartable Atomic Sequence. */ \
162 "2:" \
163 "\tmov %2, #0x00000000\n" \
164 "\tstr %2, [%5]\n" \
165 "\tmov %2, #0xffffffff\n" \
166 "\tstr %2, [%5, #4]\n" \
167 : "=&r" (old), "=m" (*mem), "=&r" (temp) \
168 : "r" (val), "m" (*mem), "r" (ras_start)); \
169 return (old); \
170}
171
172#define SYNC_OP_AND_FETCH_N(N, TYPE, LDR, STR, NAME, OP) \
173TYPE HIDDEN \
8f479d7a 174__sync_##NAME##_and_fetch_##N (TYPE *mem, TYPE val) \
82a19768 175{ \
8f479d7a 176 unsigned int old, temp, ras_start, res; \
82a19768
AT
177 \
178 ras_start = ARM_RAS_START; \
179 __asm volatile ( \
180 /* Set up Restartable Atomic Sequence. */ \
181 "1:" \
182 "\tadr %2, 1b\n" \
8f479d7a 183 "\tstr %2, [%6]\n" \
82a19768 184 "\tadr %2, 2f\n" \
8f479d7a 185 "\tstr %2, [%6, #4]\n" \
82a19768 186 \
8f479d7a
AT
187 "\t"LDR" %0, %5\n" /* Load old value. */ \
188 "\t"OP" %3, %0, %4\n" /* Calculate new value. */ \
189 "\t"STR" %3, %1\n" /* Store new value. */ \
82a19768
AT
190 \
191 /* Tear down Restartable Atomic Sequence. */ \
192 "2:" \
193 "\tmov %2, #0x00000000\n" \
8f479d7a 194 "\tstr %2, [%6]\n" \
82a19768 195 "\tmov %2, #0xffffffff\n" \
8f479d7a
AT
196 "\tstr %2, [%6, #4]\n" \
197 : "=&r" (old), "=m" (*mem), "=&r" (temp), "=&r" (res) \
82a19768 198 : "r" (val), "m" (*mem), "r" (ras_start)); \
8f479d7a 199 return (res); \
82a19768
AT
200}
201
202#define EMIT_ALL_OPS_N(N, TYPE, LDR, STR, STREQ) \
203SYNC_LOCK_TEST_AND_SET_N (N, TYPE, LDR, STR) \
204SYNC_LOCK_RELEASE_N (N, TYPE) \
205SYNC_VAL_CAS_N (N, TYPE, LDR, STREQ) \
206SYNC_BOOL_CAS_N (N, TYPE) \
207SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, add, "add") \
208SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, and, "and") \
209SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, or, "orr") \
210SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, sub, "sub") \
211SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, xor, "eor") \
212SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, add, "add") \
213SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, and, "and") \
214SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, or, "orr") \
215SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, sub, "sub") \
216SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, xor, "eor")
217
218
219
220EMIT_ALL_OPS_N (1, unsigned char, "ldrb", "strb", "streqb")
221EMIT_ALL_OPS_N (2, unsigned short, "ldrh", "strh", "streqh")
222EMIT_ALL_OPS_N (4, unsigned int, "ldr", "str", "streq")
223
224#endif