1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
9 #include "rseq-bits-template.h"
11 #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
12 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
14 static inline __attribute__((always_inline))
15 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
19 __asm__ __volatile__ goto (
20 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
21 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
22 #ifdef RSEQ_COMPARE_TWICE
23 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
24 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
26 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
27 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
29 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
31 #ifdef RSEQ_COMPARE_TWICE
32 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
33 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
35 RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
37 RSEQ_ASM_DEFINE_ABORT(4, abort)
38 : /* gcc asm goto does not allow outputs */
40 [current_cpu_id] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
41 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
43 [expect] "r" (expect),
46 : "memory", RSEQ_ASM_TMP_REG
48 #ifdef RSEQ_COMPARE_TWICE
52 rseq_after_asm_goto();
55 rseq_after_asm_goto();
59 rseq_after_asm_goto();
61 #ifdef RSEQ_COMPARE_TWICE
63 rseq_after_asm_goto();
64 rseq_bug("cpu_id comparison failed");
66 rseq_after_asm_goto();
67 rseq_bug("expected value comparison failed");
71 static inline __attribute__((always_inline))
72 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot,
73 long voffp, intptr_t *load, int cpu)
77 __asm__ __volatile__ goto (
78 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
79 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
80 #ifdef RSEQ_COMPARE_TWICE
81 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
82 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
84 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
85 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
87 RSEQ_ASM_OP_CMPNE(v, expectnot, %l[cmpfail])
89 #ifdef RSEQ_COMPARE_TWICE
90 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
91 RSEQ_ASM_OP_CMPNE(v, expectnot, %l[error2])
94 RSEQ_ASM_OP_R_STORE(load)
95 RSEQ_ASM_OP_R_LOAD_OFF(voffp)
96 RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
98 RSEQ_ASM_DEFINE_ABORT(4, abort)
99 : /* gcc asm goto does not allow outputs */
100 : [cpu_id] "r" (cpu),
101 [current_cpu_id] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
102 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
104 [expectnot] "r" (expectnot),
108 : "memory", RSEQ_ASM_TMP_REG
110 #ifdef RSEQ_COMPARE_TWICE
114 rseq_after_asm_goto();
117 rseq_after_asm_goto();
121 rseq_after_asm_goto();
123 #ifdef RSEQ_COMPARE_TWICE
125 rseq_after_asm_goto();
126 rseq_bug("cpu_id comparison failed");
128 rseq_after_asm_goto();
129 rseq_bug("expected value comparison failed");
133 static inline __attribute__((always_inline))
134 int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu)
138 __asm__ __volatile__ goto (
139 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
140 #ifdef RSEQ_COMPARE_TWICE
141 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
143 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
144 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
146 #ifdef RSEQ_COMPARE_TWICE
147 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
149 RSEQ_ASM_OP_R_LOAD(v)
150 RSEQ_ASM_OP_R_ADD(count)
151 RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
153 RSEQ_ASM_DEFINE_ABORT(4, abort)
154 : /* gcc asm goto does not allow outputs */
155 : [cpu_id] "r" (cpu),
156 [current_cpu_id] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
157 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
161 : "memory", RSEQ_ASM_TMP_REG
163 #ifdef RSEQ_COMPARE_TWICE
167 rseq_after_asm_goto();
170 rseq_after_asm_goto();
173 #ifdef RSEQ_COMPARE_TWICE
175 rseq_after_asm_goto();
176 rseq_bug("cpu_id comparison failed");
180 static inline __attribute__((always_inline))
181 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect,
182 intptr_t *v2, intptr_t expect2,
183 intptr_t newv, int cpu)
187 __asm__ __volatile__ goto (
188 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
189 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
190 #ifdef RSEQ_COMPARE_TWICE
191 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
192 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
193 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error3])
195 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
196 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
198 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
200 RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[cmpfail])
202 #ifdef RSEQ_COMPARE_TWICE
203 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
204 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
205 RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[error3])
207 RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
209 RSEQ_ASM_DEFINE_ABORT(4, abort)
210 : /* gcc asm goto does not allow outputs */
211 : [cpu_id] "r" (cpu),
212 [current_cpu_id] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
213 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
215 [expect] "r" (expect),
217 [expect2] "r" (expect2),
220 : "memory", RSEQ_ASM_TMP_REG
222 #ifdef RSEQ_COMPARE_TWICE
223 , error1, error2, error3
226 rseq_after_asm_goto();
229 rseq_after_asm_goto();
233 rseq_after_asm_goto();
235 #ifdef RSEQ_COMPARE_TWICE
237 rseq_after_asm_goto();
238 rseq_bug("cpu_id comparison failed");
240 rseq_after_asm_goto();
241 rseq_bug("expected value comparison failed");
243 rseq_after_asm_goto();
244 rseq_bug("2nd expected value comparison failed");
248 #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
249 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
251 #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
252 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
254 static inline __attribute__((always_inline))
255 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect,
256 intptr_t *v2, intptr_t newv2,
257 intptr_t newv, int cpu)
261 __asm__ __volatile__ goto (
262 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
263 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
264 #ifdef RSEQ_COMPARE_TWICE
265 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
266 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
268 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
269 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
271 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
273 #ifdef RSEQ_COMPARE_TWICE
274 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
275 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
277 RSEQ_ASM_OP_STORE(newv2, v2)
279 #ifdef RSEQ_TEMPLATE_MO_RELEASE
280 RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
282 RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
285 RSEQ_ASM_DEFINE_ABORT(4, abort)
286 : /* gcc asm goto does not allow outputs */
287 : [cpu_id] "r" (cpu),
288 [current_cpu_id] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
289 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
290 [expect] "r" (expect),
296 : "memory", RSEQ_ASM_TMP_REG
298 #ifdef RSEQ_COMPARE_TWICE
302 rseq_after_asm_goto();
305 rseq_after_asm_goto();
309 rseq_after_asm_goto();
311 #ifdef RSEQ_COMPARE_TWICE
313 rseq_after_asm_goto();
314 rseq_bug("cpu_id comparison failed");
316 rseq_after_asm_goto();
317 rseq_bug("expected value comparison failed");
321 static inline __attribute__((always_inline))
322 int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect,
323 void *dst, void *src, size_t len,
324 intptr_t newv, int cpu)
328 __asm__ __volatile__ goto (
329 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
330 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail])
331 #ifdef RSEQ_COMPARE_TWICE
332 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1])
333 RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2])
335 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
336 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
338 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
340 #ifdef RSEQ_COMPARE_TWICE
341 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
342 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
344 RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
346 #ifdef RSEQ_TEMPLATE_MO_RELEASE
347 RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
349 RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
352 RSEQ_ASM_DEFINE_ABORT(4, abort)
353 : /* gcc asm goto does not allow outputs */
354 : [cpu_id] "r" (cpu),
355 [current_cpu_id] "Qo" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
356 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
357 [expect] "r" (expect),
364 : "memory", RSEQ_ASM_TMP_REG, RSEQ_ASM_TMP_REG_2
366 #ifdef RSEQ_COMPARE_TWICE
370 rseq_after_asm_goto();
373 rseq_after_asm_goto();
377 rseq_after_asm_goto();
379 #ifdef RSEQ_COMPARE_TWICE
381 rseq_after_asm_goto();
382 rseq_bug("cpu_id comparison failed");
384 rseq_after_asm_goto();
385 rseq_bug("expected value comparison failed");
389 #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
390 (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
392 #include "rseq-bits-reset.h"