xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/rseq/rseq-ppc.h (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker  * rseq-ppc.h
4*053f45beSAndroid Build Coastguard Worker  *
5*053f45beSAndroid Build Coastguard Worker  * (C) Copyright 2016-2018 - Mathieu Desnoyers <[email protected]>
6*053f45beSAndroid Build Coastguard Worker  * (C) Copyright 2016-2018 - Boqun Feng <[email protected]>
7*053f45beSAndroid Build Coastguard Worker  */
8*053f45beSAndroid Build Coastguard Worker 
9*053f45beSAndroid Build Coastguard Worker /*
10*053f45beSAndroid Build Coastguard Worker  * RSEQ_SIG is used with the following trap instruction:
11*053f45beSAndroid Build Coastguard Worker  *
12*053f45beSAndroid Build Coastguard Worker  * powerpc-be:    0f e5 00 0b           twui   r5,11
13*053f45beSAndroid Build Coastguard Worker  * powerpc64-le:  0b 00 e5 0f           twui   r5,11
14*053f45beSAndroid Build Coastguard Worker  * powerpc64-be:  0f e5 00 0b           twui   r5,11
15*053f45beSAndroid Build Coastguard Worker  */
16*053f45beSAndroid Build Coastguard Worker 
17*053f45beSAndroid Build Coastguard Worker #define RSEQ_SIG	0x0fe5000b
18*053f45beSAndroid Build Coastguard Worker 
19*053f45beSAndroid Build Coastguard Worker #define rseq_smp_mb()		__asm__ __volatile__ ("sync"	::: "memory", "cc")
20*053f45beSAndroid Build Coastguard Worker #define rseq_smp_lwsync()	__asm__ __volatile__ ("lwsync"	::: "memory", "cc")
21*053f45beSAndroid Build Coastguard Worker #define rseq_smp_rmb()		rseq_smp_lwsync()
22*053f45beSAndroid Build Coastguard Worker #define rseq_smp_wmb()		rseq_smp_lwsync()
23*053f45beSAndroid Build Coastguard Worker 
24*053f45beSAndroid Build Coastguard Worker #define rseq_smp_load_acquire(p)					\
25*053f45beSAndroid Build Coastguard Worker __extension__ ({							\
26*053f45beSAndroid Build Coastguard Worker 	__typeof(*p) ____p1 = RSEQ_READ_ONCE(*p);			\
27*053f45beSAndroid Build Coastguard Worker 	rseq_smp_lwsync();						\
28*053f45beSAndroid Build Coastguard Worker 	____p1;								\
29*053f45beSAndroid Build Coastguard Worker })
30*053f45beSAndroid Build Coastguard Worker 
31*053f45beSAndroid Build Coastguard Worker #define rseq_smp_acquire__after_ctrl_dep()	rseq_smp_lwsync()
32*053f45beSAndroid Build Coastguard Worker 
33*053f45beSAndroid Build Coastguard Worker #define rseq_smp_store_release(p, v)					\
34*053f45beSAndroid Build Coastguard Worker do {									\
35*053f45beSAndroid Build Coastguard Worker 	rseq_smp_lwsync();						\
36*053f45beSAndroid Build Coastguard Worker 	RSEQ_WRITE_ONCE(*p, v);						\
37*053f45beSAndroid Build Coastguard Worker } while (0)
38*053f45beSAndroid Build Coastguard Worker 
39*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_SKIP_FASTPATH
40*053f45beSAndroid Build Coastguard Worker #include "rseq-skip.h"
41*053f45beSAndroid Build Coastguard Worker #else /* !RSEQ_SKIP_FASTPATH */
42*053f45beSAndroid Build Coastguard Worker 
43*053f45beSAndroid Build Coastguard Worker /*
44*053f45beSAndroid Build Coastguard Worker  * The __rseq_cs_ptr_array and __rseq_cs sections can be used by debuggers to
45*053f45beSAndroid Build Coastguard Worker  * better handle single-stepping through the restartable critical sections.
46*053f45beSAndroid Build Coastguard Worker  */
47*053f45beSAndroid Build Coastguard Worker 
48*053f45beSAndroid Build Coastguard Worker #ifdef __PPC64__
49*053f45beSAndroid Build Coastguard Worker 
50*053f45beSAndroid Build Coastguard Worker #define RSEQ_STORE_LONG(arg)	"std%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "	/* To memory ("m" constraint) */
51*053f45beSAndroid Build Coastguard Worker #define RSEQ_STORE_INT(arg)	"stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "	/* To memory ("m" constraint) */
52*053f45beSAndroid Build Coastguard Worker #define RSEQ_LOAD_LONG(arg)	"ld%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "	/* From memory ("m" constraint) */
53*053f45beSAndroid Build Coastguard Worker #define RSEQ_LOAD_INT(arg)	"lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "	/* From memory ("m" constraint) */
54*053f45beSAndroid Build Coastguard Worker #define RSEQ_LOADX_LONG		"ldx "							/* From base register ("b" constraint) */
55*053f45beSAndroid Build Coastguard Worker #define RSEQ_CMP_LONG		"cmpd "
56*053f45beSAndroid Build Coastguard Worker #define RSEQ_CMP_LONG_INT	"cmpdi "
57*053f45beSAndroid Build Coastguard Worker 
58*053f45beSAndroid Build Coastguard Worker #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,				\
59*053f45beSAndroid Build Coastguard Worker 			start_ip, post_commit_offset, abort_ip)			\
60*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs, \"aw\"\n\t"				\
61*053f45beSAndroid Build Coastguard Worker 		".balign 32\n\t"						\
62*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"					\
63*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t"	\
64*053f45beSAndroid Build Coastguard Worker 		".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
65*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"						\
66*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"			\
67*053f45beSAndroid Build Coastguard Worker 		".quad " __rseq_str(label) "b\n\t"				\
68*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
69*053f45beSAndroid Build Coastguard Worker 
70*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)			\
71*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(1)						\
72*053f45beSAndroid Build Coastguard Worker 		"lis %%r17, (" __rseq_str(cs_label) ")@highest\n\t"		\
73*053f45beSAndroid Build Coastguard Worker 		"ori %%r17, %%r17, (" __rseq_str(cs_label) ")@higher\n\t"	\
74*053f45beSAndroid Build Coastguard Worker 		"rldicr %%r17, %%r17, 32, 31\n\t"				\
75*053f45beSAndroid Build Coastguard Worker 		"oris %%r17, %%r17, (" __rseq_str(cs_label) ")@high\n\t"	\
76*053f45beSAndroid Build Coastguard Worker 		"ori %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t"		\
77*053f45beSAndroid Build Coastguard Worker 		"std %%r17, %[" __rseq_str(rseq_cs) "]\n\t"			\
78*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"
79*053f45beSAndroid Build Coastguard Worker 
80*053f45beSAndroid Build Coastguard Worker /*
81*053f45beSAndroid Build Coastguard Worker  * Exit points of a rseq critical section consist of all instructions outside
82*053f45beSAndroid Build Coastguard Worker  * of the critical section where a critical section can either branch to or
83*053f45beSAndroid Build Coastguard Worker  * reach through the normal course of its execution. The abort IP and the
84*053f45beSAndroid Build Coastguard Worker  * post-commit IP are already part of the __rseq_cs section and should not be
85*053f45beSAndroid Build Coastguard Worker  * explicitly defined as additional exit points. Knowing all exit points is
86*053f45beSAndroid Build Coastguard Worker  * useful to assist debuggers stepping over the critical section.
87*053f45beSAndroid Build Coastguard Worker  */
88*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)			\
89*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_exit_point_array, \"aw\"\n\t"	\
90*053f45beSAndroid Build Coastguard Worker 		".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
91*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
92*053f45beSAndroid Build Coastguard Worker 
93*053f45beSAndroid Build Coastguard Worker #else /* #ifdef __PPC64__ */
94*053f45beSAndroid Build Coastguard Worker 
95*053f45beSAndroid Build Coastguard Worker #define RSEQ_STORE_LONG(arg)	"stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "	/* To memory ("m" constraint) */
96*053f45beSAndroid Build Coastguard Worker #define RSEQ_STORE_INT(arg)	RSEQ_STORE_LONG(arg)					/* To memory ("m" constraint) */
97*053f45beSAndroid Build Coastguard Worker #define RSEQ_LOAD_LONG(arg)	"lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "	/* From memory ("m" constraint) */
98*053f45beSAndroid Build Coastguard Worker #define RSEQ_LOAD_INT(arg)	RSEQ_LOAD_LONG(arg)					/* From memory ("m" constraint) */
99*053f45beSAndroid Build Coastguard Worker #define RSEQ_LOADX_LONG		"lwzx "							/* From base register ("b" constraint) */
100*053f45beSAndroid Build Coastguard Worker #define RSEQ_CMP_LONG		"cmpw "
101*053f45beSAndroid Build Coastguard Worker #define RSEQ_CMP_LONG_INT	"cmpwi "
102*053f45beSAndroid Build Coastguard Worker 
103*053f45beSAndroid Build Coastguard Worker #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags,				\
104*053f45beSAndroid Build Coastguard Worker 			start_ip, post_commit_offset, abort_ip)			\
105*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs, \"aw\"\n\t"				\
106*053f45beSAndroid Build Coastguard Worker 		".balign 32\n\t"						\
107*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"					\
108*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t"	\
109*053f45beSAndroid Build Coastguard Worker 		/* 32-bit only supported on BE */				\
110*053f45beSAndroid Build Coastguard Worker 		".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \
111*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"					\
112*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_cs_ptr_array, \"aw\"\n\t"		\
113*053f45beSAndroid Build Coastguard Worker 		".long 0x0, " __rseq_str(label) "b\n\t"			\
114*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
115*053f45beSAndroid Build Coastguard Worker 
116*053f45beSAndroid Build Coastguard Worker /*
117*053f45beSAndroid Build Coastguard Worker  * Exit points of a rseq critical section consist of all instructions outside
118*053f45beSAndroid Build Coastguard Worker  * of the critical section where a critical section can either branch to or
119*053f45beSAndroid Build Coastguard Worker  * reach through the normal course of its execution. The abort IP and the
120*053f45beSAndroid Build Coastguard Worker  * post-commit IP are already part of the __rseq_cs section and should not be
121*053f45beSAndroid Build Coastguard Worker  * explicitly defined as additional exit points. Knowing all exit points is
122*053f45beSAndroid Build Coastguard Worker  * useful to assist debuggers stepping over the critical section.
123*053f45beSAndroid Build Coastguard Worker  */
124*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip)				\
125*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_exit_point_array, \"aw\"\n\t"		\
126*053f45beSAndroid Build Coastguard Worker 		/* 32-bit only supported on BE */				\
127*053f45beSAndroid Build Coastguard Worker 		".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t"	\
128*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
129*053f45beSAndroid Build Coastguard Worker 
130*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)			\
131*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(1)						\
132*053f45beSAndroid Build Coastguard Worker 		"lis %%r17, (" __rseq_str(cs_label) ")@ha\n\t"			\
133*053f45beSAndroid Build Coastguard Worker 		"addi %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t"		\
134*053f45beSAndroid Build Coastguard Worker 		RSEQ_STORE_INT(rseq_cs) "%%r17, %[" __rseq_str(rseq_cs) "]\n\t"	\
135*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"
136*053f45beSAndroid Build Coastguard Worker 
137*053f45beSAndroid Build Coastguard Worker #endif /* #ifdef __PPC64__ */
138*053f45beSAndroid Build Coastguard Worker 
139*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip)	\
140*053f45beSAndroid Build Coastguard Worker 		__RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,		\
141*053f45beSAndroid Build Coastguard Worker 					(post_commit_ip - start_ip), abort_ip)
142*053f45beSAndroid Build Coastguard Worker 
143*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label)			\
144*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(2)						\
145*053f45beSAndroid Build Coastguard Worker 		RSEQ_LOAD_INT(current_cpu_id) "%%r17, %[" __rseq_str(current_cpu_id) "]\n\t" \
146*053f45beSAndroid Build Coastguard Worker 		"cmpw cr7, %[" __rseq_str(cpu_id) "], %%r17\n\t"		\
147*053f45beSAndroid Build Coastguard Worker 		"bne- cr7, " __rseq_str(label) "\n\t"
148*053f45beSAndroid Build Coastguard Worker 
149*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_DEFINE_ABORT(label, abort_label)				\
150*053f45beSAndroid Build Coastguard Worker 		".pushsection __rseq_failure, \"ax\"\n\t"			\
151*053f45beSAndroid Build Coastguard Worker 		".long " __rseq_str(RSEQ_SIG) "\n\t"				\
152*053f45beSAndroid Build Coastguard Worker 		__rseq_str(label) ":\n\t"					\
153*053f45beSAndroid Build Coastguard Worker 		"b %l[" __rseq_str(abort_label) "]\n\t"				\
154*053f45beSAndroid Build Coastguard Worker 		".popsection\n\t"
155*053f45beSAndroid Build Coastguard Worker 
156*053f45beSAndroid Build Coastguard Worker /*
157*053f45beSAndroid Build Coastguard Worker  * RSEQ_ASM_OPs: asm operations for rseq
158*053f45beSAndroid Build Coastguard Worker  * 	RSEQ_ASM_OP_R_*: has hard-code registers in it
159*053f45beSAndroid Build Coastguard Worker  * 	RSEQ_ASM_OP_* (else): doesn't have hard-code registers(unless cr7)
160*053f45beSAndroid Build Coastguard Worker  */
161*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_CMPEQ(var, expect, label)					\
162*053f45beSAndroid Build Coastguard Worker 		RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"		\
163*053f45beSAndroid Build Coastguard Worker 		RSEQ_CMP_LONG "cr7, %%r17, %[" __rseq_str(expect) "]\n\t"		\
164*053f45beSAndroid Build Coastguard Worker 		"bne- cr7, " __rseq_str(label) "\n\t"
165*053f45beSAndroid Build Coastguard Worker 
166*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_CMPNE(var, expectnot, label)				\
167*053f45beSAndroid Build Coastguard Worker 		RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"		\
168*053f45beSAndroid Build Coastguard Worker 		RSEQ_CMP_LONG "cr7, %%r17, %[" __rseq_str(expectnot) "]\n\t"		\
169*053f45beSAndroid Build Coastguard Worker 		"beq- cr7, " __rseq_str(label) "\n\t"
170*053f45beSAndroid Build Coastguard Worker 
171*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_STORE(value, var)						\
172*053f45beSAndroid Build Coastguard Worker 		RSEQ_STORE_LONG(var) "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t"
173*053f45beSAndroid Build Coastguard Worker 
174*053f45beSAndroid Build Coastguard Worker /* Load @var to r17 */
175*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_LOAD(var)							\
176*053f45beSAndroid Build Coastguard Worker 		RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"
177*053f45beSAndroid Build Coastguard Worker 
178*053f45beSAndroid Build Coastguard Worker /* Store r17 to @var */
179*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_STORE(var)						\
180*053f45beSAndroid Build Coastguard Worker 		RSEQ_STORE_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"
181*053f45beSAndroid Build Coastguard Worker 
182*053f45beSAndroid Build Coastguard Worker /* Add @count to r17 */
183*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_ADD(count)						\
184*053f45beSAndroid Build Coastguard Worker 		"add %%r17, %[" __rseq_str(count) "], %%r17\n\t"
185*053f45beSAndroid Build Coastguard Worker 
186*053f45beSAndroid Build Coastguard Worker /* Load (r17 + voffp) to r17 */
187*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_LOADX(voffp)						\
188*053f45beSAndroid Build Coastguard Worker 		RSEQ_LOADX_LONG "%%r17, %[" __rseq_str(voffp) "], %%r17\n\t"
189*053f45beSAndroid Build Coastguard Worker 
190*053f45beSAndroid Build Coastguard Worker /* TODO: implement a faster memcpy. */
191*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_MEMCPY() \
192*053f45beSAndroid Build Coastguard Worker 		RSEQ_CMP_LONG_INT "%%r19, 0\n\t" \
193*053f45beSAndroid Build Coastguard Worker 		"beq 333f\n\t" \
194*053f45beSAndroid Build Coastguard Worker 		"addi %%r20, %%r20, -1\n\t" \
195*053f45beSAndroid Build Coastguard Worker 		"addi %%r21, %%r21, -1\n\t" \
196*053f45beSAndroid Build Coastguard Worker 		"222:\n\t" \
197*053f45beSAndroid Build Coastguard Worker 		"lbzu %%r18, 1(%%r20)\n\t" \
198*053f45beSAndroid Build Coastguard Worker 		"stbu %%r18, 1(%%r21)\n\t" \
199*053f45beSAndroid Build Coastguard Worker 		"addi %%r19, %%r19, -1\n\t" \
200*053f45beSAndroid Build Coastguard Worker 		RSEQ_CMP_LONG_INT "%%r19, 0\n\t" \
201*053f45beSAndroid Build Coastguard Worker 		"bne 222b\n\t" \
202*053f45beSAndroid Build Coastguard Worker 		"333:\n\t" \
203*053f45beSAndroid Build Coastguard Worker 
204*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label)			\
205*053f45beSAndroid Build Coastguard Worker 		RSEQ_STORE_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"			\
206*053f45beSAndroid Build Coastguard Worker 		__rseq_str(post_commit_label) ":\n\t"
207*053f45beSAndroid Build Coastguard Worker 
208*053f45beSAndroid Build Coastguard Worker #define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label)			\
209*053f45beSAndroid Build Coastguard Worker 		RSEQ_STORE_LONG(var) "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t" \
210*053f45beSAndroid Build Coastguard Worker 		__rseq_str(post_commit_label) ":\n\t"
211*053f45beSAndroid Build Coastguard Worker 
212*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t newv,int cpu)213*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
214*053f45beSAndroid Build Coastguard Worker {
215*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
216*053f45beSAndroid Build Coastguard Worker 
217*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
218*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
219*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
220*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
221*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
222*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
223*053f45beSAndroid Build Coastguard Worker #endif
224*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
225*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
226*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
227*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
228*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
229*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
230*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
231*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
232*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
233*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
234*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
235*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
236*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
237*053f45beSAndroid Build Coastguard Worker #endif
238*053f45beSAndroid Build Coastguard Worker 		/* final store */
239*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
240*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
241*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
242*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
243*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
244*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
245*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
246*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
247*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
248*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
249*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
250*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17"
251*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
252*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
253*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
254*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
255*053f45beSAndroid Build Coastguard Worker #endif
256*053f45beSAndroid Build Coastguard Worker 	);
257*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
258*053f45beSAndroid Build Coastguard Worker 	return 0;
259*053f45beSAndroid Build Coastguard Worker abort:
260*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
261*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
262*053f45beSAndroid Build Coastguard Worker 	return -1;
263*053f45beSAndroid Build Coastguard Worker cmpfail:
264*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
265*053f45beSAndroid Build Coastguard Worker 	return 1;
266*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
267*053f45beSAndroid Build Coastguard Worker error1:
268*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
269*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
270*053f45beSAndroid Build Coastguard Worker error2:
271*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
272*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
273*053f45beSAndroid Build Coastguard Worker #endif
274*053f45beSAndroid Build Coastguard Worker }
275*053f45beSAndroid Build Coastguard Worker 
276*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpnev_storeoffp_load(intptr_t * v,intptr_t expectnot,long voffp,intptr_t * load,int cpu)277*053f45beSAndroid Build Coastguard Worker int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
278*053f45beSAndroid Build Coastguard Worker 			       long voffp, intptr_t *load, int cpu)
279*053f45beSAndroid Build Coastguard Worker {
280*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
281*053f45beSAndroid Build Coastguard Worker 
282*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
283*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
284*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
285*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
286*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
287*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
288*053f45beSAndroid Build Coastguard Worker #endif
289*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
290*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
291*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
292*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
293*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
294*053f45beSAndroid Build Coastguard Worker 		/* cmp @v not equal to @expectnot */
295*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPNE(v, expectnot, %l[cmpfail])
296*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
297*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
298*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
299*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
300*053f45beSAndroid Build Coastguard Worker 		/* cmp @v not equal to @expectnot */
301*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPNE(v, expectnot, %l[error2])
302*053f45beSAndroid Build Coastguard Worker #endif
303*053f45beSAndroid Build Coastguard Worker 		/* load the value of @v */
304*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_LOAD(v)
305*053f45beSAndroid Build Coastguard Worker 		/* store it in @load */
306*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_STORE(load)
307*053f45beSAndroid Build Coastguard Worker 		/* dereference voffp(v) */
308*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_LOADX(voffp)
309*053f45beSAndroid Build Coastguard Worker 		/* final store the value at voffp(v) */
310*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_FINAL_STORE(v, 2)
311*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
312*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
313*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
314*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
315*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
316*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
317*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
318*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
319*053f45beSAndroid Build Coastguard Worker 		  [expectnot]		"r" (expectnot),
320*053f45beSAndroid Build Coastguard Worker 		  [voffp]		"b" (voffp),
321*053f45beSAndroid Build Coastguard Worker 		  [load]		"m" (*load)
322*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
323*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17"
324*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
325*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
326*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
327*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
328*053f45beSAndroid Build Coastguard Worker #endif
329*053f45beSAndroid Build Coastguard Worker 	);
330*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
331*053f45beSAndroid Build Coastguard Worker 	return 0;
332*053f45beSAndroid Build Coastguard Worker abort:
333*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
334*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
335*053f45beSAndroid Build Coastguard Worker 	return -1;
336*053f45beSAndroid Build Coastguard Worker cmpfail:
337*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
338*053f45beSAndroid Build Coastguard Worker 	return 1;
339*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
340*053f45beSAndroid Build Coastguard Worker error1:
341*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
342*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
343*053f45beSAndroid Build Coastguard Worker error2:
344*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
345*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
346*053f45beSAndroid Build Coastguard Worker #endif
347*053f45beSAndroid Build Coastguard Worker }
348*053f45beSAndroid Build Coastguard Worker 
349*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_addv(intptr_t * v,intptr_t count,int cpu)350*053f45beSAndroid Build Coastguard Worker int rseq_addv(intptr_t *v, intptr_t count, int cpu)
351*053f45beSAndroid Build Coastguard Worker {
352*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
353*053f45beSAndroid Build Coastguard Worker 
354*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
355*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
356*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
357*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
358*053f45beSAndroid Build Coastguard Worker #endif
359*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
360*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
361*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
362*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
363*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
364*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
365*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
366*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
367*053f45beSAndroid Build Coastguard Worker #endif
368*053f45beSAndroid Build Coastguard Worker 		/* load the value of @v */
369*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_LOAD(v)
370*053f45beSAndroid Build Coastguard Worker 		/* add @count to it */
371*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_ADD(count)
372*053f45beSAndroid Build Coastguard Worker 		/* final store */
373*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_FINAL_STORE(v, 2)
374*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
375*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
376*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
377*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
378*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
379*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
380*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
381*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
382*053f45beSAndroid Build Coastguard Worker 		  [count]		"r" (count)
383*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
384*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17"
385*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
386*053f45beSAndroid Build Coastguard Worker 		: abort
387*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
388*053f45beSAndroid Build Coastguard Worker 		  , error1
389*053f45beSAndroid Build Coastguard Worker #endif
390*053f45beSAndroid Build Coastguard Worker 	);
391*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
392*053f45beSAndroid Build Coastguard Worker 	return 0;
393*053f45beSAndroid Build Coastguard Worker abort:
394*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
395*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
396*053f45beSAndroid Build Coastguard Worker 	return -1;
397*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
398*053f45beSAndroid Build Coastguard Worker error1:
399*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
400*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
401*053f45beSAndroid Build Coastguard Worker #endif
402*053f45beSAndroid Build Coastguard Worker }
403*053f45beSAndroid Build Coastguard Worker 
404*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trystorev_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)405*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
406*053f45beSAndroid Build Coastguard Worker 				 intptr_t *v2, intptr_t newv2,
407*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
408*053f45beSAndroid Build Coastguard Worker {
409*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
410*053f45beSAndroid Build Coastguard Worker 
411*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
412*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
413*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
414*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
415*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
416*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
417*053f45beSAndroid Build Coastguard Worker #endif
418*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
419*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
420*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
421*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
422*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
423*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
424*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
425*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
426*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
427*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
428*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
429*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
430*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
431*053f45beSAndroid Build Coastguard Worker #endif
432*053f45beSAndroid Build Coastguard Worker 		/* try store */
433*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_STORE(newv2, v2)
434*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
435*053f45beSAndroid Build Coastguard Worker 		/* final store */
436*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
437*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
438*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
439*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
440*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
441*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
442*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
443*053f45beSAndroid Build Coastguard Worker 		  /* try store input */
444*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
445*053f45beSAndroid Build Coastguard Worker 		  [newv2]		"r" (newv2),
446*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
447*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
448*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
449*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
450*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
451*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17"
452*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
453*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
454*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
455*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
456*053f45beSAndroid Build Coastguard Worker #endif
457*053f45beSAndroid Build Coastguard Worker 	);
458*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
459*053f45beSAndroid Build Coastguard Worker 	return 0;
460*053f45beSAndroid Build Coastguard Worker abort:
461*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
462*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
463*053f45beSAndroid Build Coastguard Worker 	return -1;
464*053f45beSAndroid Build Coastguard Worker cmpfail:
465*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
466*053f45beSAndroid Build Coastguard Worker 	return 1;
467*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
468*053f45beSAndroid Build Coastguard Worker error1:
469*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
470*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
471*053f45beSAndroid Build Coastguard Worker error2:
472*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
473*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
474*053f45beSAndroid Build Coastguard Worker #endif
475*053f45beSAndroid Build Coastguard Worker }
476*053f45beSAndroid Build Coastguard Worker 
477*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trystorev_storev_release(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t newv2,intptr_t newv,int cpu)478*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
479*053f45beSAndroid Build Coastguard Worker 					 intptr_t *v2, intptr_t newv2,
480*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
481*053f45beSAndroid Build Coastguard Worker {
482*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
483*053f45beSAndroid Build Coastguard Worker 
484*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
485*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
486*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
487*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
488*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
489*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
490*053f45beSAndroid Build Coastguard Worker #endif
491*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
492*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
493*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
494*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
495*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
496*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
497*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
498*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
499*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
500*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
501*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
502*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
503*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
504*053f45beSAndroid Build Coastguard Worker #endif
505*053f45beSAndroid Build Coastguard Worker 		/* try store */
506*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_STORE(newv2, v2)
507*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
508*053f45beSAndroid Build Coastguard Worker 		/* for 'release' */
509*053f45beSAndroid Build Coastguard Worker 		"lwsync\n\t"
510*053f45beSAndroid Build Coastguard Worker 		/* final store */
511*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
512*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
513*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
514*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
515*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
516*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
517*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
518*053f45beSAndroid Build Coastguard Worker 		  /* try store input */
519*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
520*053f45beSAndroid Build Coastguard Worker 		  [newv2]		"r" (newv2),
521*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
522*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
523*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
524*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
525*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
526*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17"
527*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
528*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
529*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
530*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
531*053f45beSAndroid Build Coastguard Worker #endif
532*053f45beSAndroid Build Coastguard Worker 	);
533*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
534*053f45beSAndroid Build Coastguard Worker 	return 0;
535*053f45beSAndroid Build Coastguard Worker abort:
536*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
537*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
538*053f45beSAndroid Build Coastguard Worker 	return -1;
539*053f45beSAndroid Build Coastguard Worker cmpfail:
540*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
541*053f45beSAndroid Build Coastguard Worker 	return 1;
542*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
543*053f45beSAndroid Build Coastguard Worker error1:
544*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
545*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
546*053f45beSAndroid Build Coastguard Worker error2:
547*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
548*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
549*053f45beSAndroid Build Coastguard Worker #endif
550*053f45beSAndroid Build Coastguard Worker }
551*053f45beSAndroid Build Coastguard Worker 
552*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_cmpeqv_storev(intptr_t * v,intptr_t expect,intptr_t * v2,intptr_t expect2,intptr_t newv,int cpu)553*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
554*053f45beSAndroid Build Coastguard Worker 			      intptr_t *v2, intptr_t expect2,
555*053f45beSAndroid Build Coastguard Worker 			      intptr_t newv, int cpu)
556*053f45beSAndroid Build Coastguard Worker {
557*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
558*053f45beSAndroid Build Coastguard Worker 
559*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
560*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
561*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
562*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
563*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
564*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
565*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
566*053f45beSAndroid Build Coastguard Worker #endif
567*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
568*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
569*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
570*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
571*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
572*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
573*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
574*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
575*053f45beSAndroid Build Coastguard Worker 		/* cmp @v2 equal to @expct2 */
576*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[cmpfail])
577*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
578*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
579*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
580*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
581*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
582*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
583*053f45beSAndroid Build Coastguard Worker 		/* cmp @v2 equal to @expct2 */
584*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[error3])
585*053f45beSAndroid Build Coastguard Worker #endif
586*053f45beSAndroid Build Coastguard Worker 		/* final store */
587*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
588*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
589*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
590*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
591*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
592*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
593*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
594*053f45beSAndroid Build Coastguard Worker 		  /* cmp2 input */
595*053f45beSAndroid Build Coastguard Worker 		  [v2]			"m" (*v2),
596*053f45beSAndroid Build Coastguard Worker 		  [expect2]		"r" (expect2),
597*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
598*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
599*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
600*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv)
601*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
602*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17"
603*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
604*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
605*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
606*053f45beSAndroid Build Coastguard Worker 		  , error1, error2, error3
607*053f45beSAndroid Build Coastguard Worker #endif
608*053f45beSAndroid Build Coastguard Worker 	);
609*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
610*053f45beSAndroid Build Coastguard Worker 	return 0;
611*053f45beSAndroid Build Coastguard Worker abort:
612*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
613*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
614*053f45beSAndroid Build Coastguard Worker 	return -1;
615*053f45beSAndroid Build Coastguard Worker cmpfail:
616*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
617*053f45beSAndroid Build Coastguard Worker 	return 1;
618*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
619*053f45beSAndroid Build Coastguard Worker error1:
620*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
621*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
622*053f45beSAndroid Build Coastguard Worker error2:
623*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
624*053f45beSAndroid Build Coastguard Worker 	rseq_bug("1st expected value comparison failed");
625*053f45beSAndroid Build Coastguard Worker error3:
626*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
627*053f45beSAndroid Build Coastguard Worker 	rseq_bug("2nd expected value comparison failed");
628*053f45beSAndroid Build Coastguard Worker #endif
629*053f45beSAndroid Build Coastguard Worker }
630*053f45beSAndroid Build Coastguard Worker 
631*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trymemcpy_storev(intptr_t * v,intptr_t expect,void * dst,void * src,size_t len,intptr_t newv,int cpu)632*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
633*053f45beSAndroid Build Coastguard Worker 				 void *dst, void *src, size_t len,
634*053f45beSAndroid Build Coastguard Worker 				 intptr_t newv, int cpu)
635*053f45beSAndroid Build Coastguard Worker {
636*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
637*053f45beSAndroid Build Coastguard Worker 
638*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
639*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
640*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
641*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
642*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
643*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
644*053f45beSAndroid Build Coastguard Worker #endif
645*053f45beSAndroid Build Coastguard Worker 		/* setup for mempcy */
646*053f45beSAndroid Build Coastguard Worker 		"mr %%r19, %[len]\n\t"
647*053f45beSAndroid Build Coastguard Worker 		"mr %%r20, %[src]\n\t"
648*053f45beSAndroid Build Coastguard Worker 		"mr %%r21, %[dst]\n\t"
649*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
650*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
651*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
652*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
653*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
654*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
655*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
656*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
657*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
658*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
659*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
660*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
661*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
662*053f45beSAndroid Build Coastguard Worker #endif
663*053f45beSAndroid Build Coastguard Worker 		/* try memcpy */
664*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_MEMCPY()
665*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
666*053f45beSAndroid Build Coastguard Worker 		/* final store */
667*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
668*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
669*053f45beSAndroid Build Coastguard Worker 		/* teardown */
670*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
671*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
672*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
673*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
674*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
675*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
676*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
677*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
678*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv),
679*053f45beSAndroid Build Coastguard Worker 		  /* try memcpy input */
680*053f45beSAndroid Build Coastguard Worker 		  [dst]			"r" (dst),
681*053f45beSAndroid Build Coastguard Worker 		  [src]			"r" (src),
682*053f45beSAndroid Build Coastguard Worker 		  [len]			"r" (len)
683*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
684*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17", "r18", "r19", "r20", "r21"
685*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
686*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
687*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
688*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
689*053f45beSAndroid Build Coastguard Worker #endif
690*053f45beSAndroid Build Coastguard Worker 	);
691*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
692*053f45beSAndroid Build Coastguard Worker 	return 0;
693*053f45beSAndroid Build Coastguard Worker abort:
694*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
695*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
696*053f45beSAndroid Build Coastguard Worker 	return -1;
697*053f45beSAndroid Build Coastguard Worker cmpfail:
698*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
699*053f45beSAndroid Build Coastguard Worker 	return 1;
700*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
701*053f45beSAndroid Build Coastguard Worker error1:
702*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
703*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
704*053f45beSAndroid Build Coastguard Worker error2:
705*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
706*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
707*053f45beSAndroid Build Coastguard Worker #endif
708*053f45beSAndroid Build Coastguard Worker }
709*053f45beSAndroid Build Coastguard Worker 
710*053f45beSAndroid Build Coastguard Worker static inline __attribute__((always_inline))
rseq_cmpeqv_trymemcpy_storev_release(intptr_t * v,intptr_t expect,void * dst,void * src,size_t len,intptr_t newv,int cpu)711*053f45beSAndroid Build Coastguard Worker int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
712*053f45beSAndroid Build Coastguard Worker 					 void *dst, void *src, size_t len,
713*053f45beSAndroid Build Coastguard Worker 					 intptr_t newv, int cpu)
714*053f45beSAndroid Build Coastguard Worker {
715*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_C(9)
716*053f45beSAndroid Build Coastguard Worker 
717*053f45beSAndroid Build Coastguard Worker 	__asm__ __volatile__ goto (
718*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
719*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
720*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
721*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
722*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
723*053f45beSAndroid Build Coastguard Worker #endif
724*053f45beSAndroid Build Coastguard Worker 		/* setup for mempcy */
725*053f45beSAndroid Build Coastguard Worker 		"mr %%r19, %[len]\n\t"
726*053f45beSAndroid Build Coastguard Worker 		"mr %%r20, %[src]\n\t"
727*053f45beSAndroid Build Coastguard Worker 		"mr %%r21, %[dst]\n\t"
728*053f45beSAndroid Build Coastguard Worker 		/* Start rseq by storing table entry pointer into rseq_cs. */
729*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
730*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
731*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
732*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(3)
733*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
734*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
735*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(4)
736*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
737*053f45beSAndroid Build Coastguard Worker 		/* cmp cpuid */
738*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
739*053f45beSAndroid Build Coastguard Worker 		/* cmp @v equal to @expect */
740*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
741*053f45beSAndroid Build Coastguard Worker #endif
742*053f45beSAndroid Build Coastguard Worker 		/* try memcpy */
743*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_R_MEMCPY()
744*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(5)
745*053f45beSAndroid Build Coastguard Worker 		/* for 'release' */
746*053f45beSAndroid Build Coastguard Worker 		"lwsync\n\t"
747*053f45beSAndroid Build Coastguard Worker 		/* final store */
748*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
749*053f45beSAndroid Build Coastguard Worker 		RSEQ_INJECT_ASM(6)
750*053f45beSAndroid Build Coastguard Worker 		/* teardown */
751*053f45beSAndroid Build Coastguard Worker 		RSEQ_ASM_DEFINE_ABORT(4, abort)
752*053f45beSAndroid Build Coastguard Worker 		: /* gcc asm goto does not allow outputs */
753*053f45beSAndroid Build Coastguard Worker 		: [cpu_id]		"r" (cpu),
754*053f45beSAndroid Build Coastguard Worker 		  [current_cpu_id]	"m" (rseq_get_abi()->cpu_id),
755*053f45beSAndroid Build Coastguard Worker 		  [rseq_cs]		"m" (rseq_get_abi()->rseq_cs.arch.ptr),
756*053f45beSAndroid Build Coastguard Worker 		  /* final store input */
757*053f45beSAndroid Build Coastguard Worker 		  [v]			"m" (*v),
758*053f45beSAndroid Build Coastguard Worker 		  [expect]		"r" (expect),
759*053f45beSAndroid Build Coastguard Worker 		  [newv]		"r" (newv),
760*053f45beSAndroid Build Coastguard Worker 		  /* try memcpy input */
761*053f45beSAndroid Build Coastguard Worker 		  [dst]			"r" (dst),
762*053f45beSAndroid Build Coastguard Worker 		  [src]			"r" (src),
763*053f45beSAndroid Build Coastguard Worker 		  [len]			"r" (len)
764*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_INPUT
765*053f45beSAndroid Build Coastguard Worker 		: "memory", "cc", "r17", "r18", "r19", "r20", "r21"
766*053f45beSAndroid Build Coastguard Worker 		  RSEQ_INJECT_CLOBBER
767*053f45beSAndroid Build Coastguard Worker 		: abort, cmpfail
768*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
769*053f45beSAndroid Build Coastguard Worker 		  , error1, error2
770*053f45beSAndroid Build Coastguard Worker #endif
771*053f45beSAndroid Build Coastguard Worker 	);
772*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
773*053f45beSAndroid Build Coastguard Worker 	return 0;
774*053f45beSAndroid Build Coastguard Worker abort:
775*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
776*053f45beSAndroid Build Coastguard Worker 	RSEQ_INJECT_FAILED
777*053f45beSAndroid Build Coastguard Worker 	return -1;
778*053f45beSAndroid Build Coastguard Worker cmpfail:
779*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
780*053f45beSAndroid Build Coastguard Worker 	return 1;
781*053f45beSAndroid Build Coastguard Worker #ifdef RSEQ_COMPARE_TWICE
782*053f45beSAndroid Build Coastguard Worker error1:
783*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
784*053f45beSAndroid Build Coastguard Worker 	rseq_bug("cpu_id comparison failed");
785*053f45beSAndroid Build Coastguard Worker error2:
786*053f45beSAndroid Build Coastguard Worker 	rseq_after_asm_goto();
787*053f45beSAndroid Build Coastguard Worker 	rseq_bug("expected value comparison failed");
788*053f45beSAndroid Build Coastguard Worker #endif
789*053f45beSAndroid Build Coastguard Worker }
790*053f45beSAndroid Build Coastguard Worker 
791*053f45beSAndroid Build Coastguard Worker #endif /* !RSEQ_SKIP_FASTPATH */
792