blob: f918990c8f9894ebeacfadf92043c6a0c6aa147c [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andy McFaddenac322da2010-05-19 22:33:28 -070017/* TODO: insert memory barriers on SMP */
18
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019#include <machine/cpu-features.h>
20
21/*
Vinay HARUGOP02608472009-09-10 00:31:12 +053022 * NOTE: these atomic operations are SMP safe on all architectures.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023 */
24
25 .text
26 .align
27
28 .global android_atomic_write
Doug Kwan09279902009-12-03 17:20:58 -080029 .type android_atomic_write, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030
31 .global android_atomic_inc
Doug Kwan09279902009-12-03 17:20:58 -080032 .type android_atomic_inc, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033 .global android_atomic_dec
Doug Kwan09279902009-12-03 17:20:58 -080034 .type android_atomic_dec, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035
36 .global android_atomic_add
Doug Kwan09279902009-12-03 17:20:58 -080037 .type android_atomic_add, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038 .global android_atomic_and
Doug Kwan09279902009-12-03 17:20:58 -080039 .type android_atomic_and, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040 .global android_atomic_or
Doug Kwan09279902009-12-03 17:20:58 -080041 .type android_atomic_or, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042
43 .global android_atomic_swap
Doug Kwan09279902009-12-03 17:20:58 -080044 .type android_atomic_swap, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045
46 .global android_atomic_cmpxchg
Doug Kwan09279902009-12-03 17:20:58 -080047 .type android_atomic_cmpxchg, %function
Andy McFaddenac322da2010-05-19 22:33:28 -070048 .global android_atomic_acquire_cmpxchg
49 .type android_atomic_acquire_cmpxchg, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
51/*
52 * ----------------------------------------------------------------------------
53 * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
54 * clobbered: r3, ip, flags
55 * return 0 if a swap was made, non-zero otherwise.
56 */
57
58 .equ kernel_cmpxchg, 0xFFFF0FC0
59 .equ kernel_atomic_base, 0xFFFF0FFF
60
61/*
62 * ----------------------------------------------------------------------------
63 * android_atomic_write
64 * input: r0=value, r1=address
65 * output: void
66 */
67
68android_atomic_write:
Mathias Agopianca5e0bc2009-09-03 14:49:58 -070069 str r0, [r1]
70 bx lr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071
72/*
73 * ----------------------------------------------------------------------------
74 * android_atomic_inc
75 * input: r0 = address
76 * output: r0 = old value
77 */
78
79android_atomic_inc:
Ben Cheng8a0a5272009-10-12 16:51:23 -070080 .fnstart
81 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080082 stmdb sp!, {r4, lr}
83 mov r2, r0
841: @ android_atomic_inc
85 ldr r0, [r2]
86 mov r3, #kernel_atomic_base
87#ifdef __ARM_HAVE_PC_INTERWORK
88 add lr, pc, #4
89 add r1, r0, #1
90 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
91#else
92 add r1, r0, #1
93 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
94 mov lr, pc
95 bx r3
96#endif
97 bcc 1b
98 sub r0, r1, #1
99 ldmia sp!, {r4, lr}
100 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700101 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102
103/*
104 * ----------------------------------------------------------------------------
105 * android_atomic_dec
106 * input: r0=address
107 * output: r0 = old value
108 */
109
110android_atomic_dec:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700111 .fnstart
112 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 stmdb sp!, {r4, lr}
114 mov r2, r0
1151: @ android_atomic_dec
116 ldr r0, [r2]
117 mov r3, #kernel_atomic_base
118#ifdef __ARM_HAVE_PC_INTERWORK
119 add lr, pc, #4
120 sub r1, r0, #1
121 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
122#else
123 sub r1, r0, #1
124 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
125 mov lr, pc
126 bx r3
127#endif
128 bcc 1b
129 add r0, r1, #1
130 ldmia sp!, {r4, lr}
131 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700132 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800133
134/*
135 * ----------------------------------------------------------------------------
136 * android_atomic_add
137 * input: r0=value, r1=address
138 * output: r0 = old value
139 */
140
141android_atomic_add:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700142 .fnstart
143 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800144 stmdb sp!, {r4, lr}
145 mov r2, r1
146 mov r4, r0
1471: @ android_atomic_add
148 ldr r0, [r2]
149 mov r3, #kernel_atomic_base
150#ifdef __ARM_HAVE_PC_INTERWORK
151 add lr, pc, #4
152 add r1, r0, r4
153 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
154#else
155 add r1, r0, r4
156 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
157 mov lr, pc
158 bx r3
159#endif
160 bcc 1b
161 sub r0, r1, r4
162 ldmia sp!, {r4, lr}
163 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700164 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165
166
167/*
168 * ----------------------------------------------------------------------------
169 * android_atomic_and
170 * input: r0=value, r1=address
171 * output: r0 = old value
172 */
173
174android_atomic_and:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700175 .fnstart
176 .save {r4, r5, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800177 stmdb sp!, {r4, r5, lr}
178 mov r2, r1 /* r2 = address */
179 mov r4, r0 /* r4 = the value */
1801: @ android_atomic_and
181 ldr r0, [r2] /* r0 = address[0] */
182 mov r3, #kernel_atomic_base
183#ifdef __ARM_HAVE_PC_INTERWORK
184 add lr, pc, #8
185 mov r5, r0 /* r5 = save address[0] */
186 and r1, r0, r4 /* r1 = new value */
187 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
188#else
189 mov r5, r0 /* r5 = save address[0] */
190 and r1, r0, r4 /* r1 = new value */
191 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
192 mov lr, pc
193 bx r3
194#endif
195 bcc 1b
196 mov r0, r5
197 ldmia sp!, {r4, r5, lr}
198 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700199 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200
201/*
202 * ----------------------------------------------------------------------------
203 * android_atomic_or
204 * input: r0=value, r1=address
205 * output: r0 = old value
206 */
207
208android_atomic_or:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700209 .fnstart
210 .save {r4, r5, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800211 stmdb sp!, {r4, r5, lr}
212 mov r2, r1 /* r2 = address */
213 mov r4, r0 /* r4 = the value */
2141: @ android_atomic_or
215 ldr r0, [r2] /* r0 = address[0] */
216 mov r3, #kernel_atomic_base
217#ifdef __ARM_HAVE_PC_INTERWORK
218 add lr, pc, #8
219 mov r5, r0 /* r5 = save address[0] */
220 orr r1, r0, r4 /* r1 = new value */
221 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
222#else
223 mov r5, r0 /* r5 = save address[0] */
224 orr r1, r0, r4 /* r1 = new value */
225 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
226 mov lr, pc
227 bx r3
228#endif
229 bcc 1b
230 mov r0, r5
231 ldmia sp!, {r4, r5, lr}
232 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700233 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234
235/*
236 * ----------------------------------------------------------------------------
237 * android_atomic_swap
238 * input: r0=value, r1=address
239 * output: r0 = old value
240 */
241
Vinay HARUGOP02608472009-09-10 00:31:12 +0530242/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800243android_atomic_swap:
Andy McFaddenac322da2010-05-19 22:33:28 -0700244#if defined (__ARM_HAVE_LDREX_STREX)
Vinay HARUGOP02608472009-09-10 00:31:12 +05302451: ldrex r2, [r1]
246 strex r3, r0, [r1]
247 teq r3, #0
248 bne 1b
249 mov r0, r2
250 mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */
251#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800252 swp r0, r0, [r1]
Vinay HARUGOP02608472009-09-10 00:31:12 +0530253#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800254 bx lr
255
256/*
257 * ----------------------------------------------------------------------------
258 * android_atomic_cmpxchg
259 * input: r0=oldvalue, r1=newvalue, r2=address
260 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
261 */
262
Andy McFaddenac322da2010-05-19 22:33:28 -0700263android_atomic_acquire_cmpxchg:
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800264android_atomic_cmpxchg:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700265 .fnstart
266 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 stmdb sp!, {r4, lr}
268 mov r4, r0 /* r4 = save oldvalue */
2691: @ android_atomic_cmpxchg
270 mov r3, #kernel_atomic_base
271#ifdef __ARM_HAVE_PC_INTERWORK
272 add lr, pc, #4
273 mov r0, r4 /* r0 = oldvalue */
274 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
275#else
276 mov r0, r4 /* r0 = oldvalue */
277 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
278 mov lr, pc
279 bx r3
280#endif
281 bcs 2f /* swap was made. we're good, return. */
282 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
283 cmp r3, r4
284 beq 1b
2852: @ android_atomic_cmpxchg
286 ldmia sp!, {r4, lr}
287 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700288 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800289