blob: 1dd2363d66ac0271689e5f7b930df20400d131ff [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
17#include <machine/cpu-features.h>
18
19/*
Vinay HARUGOP02608472009-09-10 00:31:12 +053020 * NOTE: these atomic operations are SMP safe on all architectures.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021 */
22
23 .text
24 .align
25
26 .global android_atomic_write
Doug Kwan09279902009-12-03 17:20:58 -080027 .type android_atomic_write, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
29 .global android_atomic_inc
Doug Kwan09279902009-12-03 17:20:58 -080030 .type android_atomic_inc, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031 .global android_atomic_dec
Doug Kwan09279902009-12-03 17:20:58 -080032 .type android_atomic_dec, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033
34 .global android_atomic_add
Doug Kwan09279902009-12-03 17:20:58 -080035 .type android_atomic_add, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036 .global android_atomic_and
Doug Kwan09279902009-12-03 17:20:58 -080037 .type android_atomic_and, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038 .global android_atomic_or
Doug Kwan09279902009-12-03 17:20:58 -080039 .type android_atomic_or, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040
41 .global android_atomic_swap
Doug Kwan09279902009-12-03 17:20:58 -080042 .type android_atomic_swap, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043
44 .global android_atomic_cmpxchg
Doug Kwan09279902009-12-03 17:20:58 -080045 .type android_atomic_cmpxchg, %function
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046
47/*
48 * ----------------------------------------------------------------------------
49 * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
50 * clobbered: r3, ip, flags
51 * return 0 if a swap was made, non-zero otherwise.
52 */
53
54 .equ kernel_cmpxchg, 0xFFFF0FC0
55 .equ kernel_atomic_base, 0xFFFF0FFF
56
57/*
58 * ----------------------------------------------------------------------------
59 * android_atomic_write
60 * input: r0=value, r1=address
61 * output: void
62 */
63
64android_atomic_write:
Mathias Agopianca5e0bc2009-09-03 14:49:58 -070065 str r0, [r1]
66 bx lr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080067
68/*
69 * ----------------------------------------------------------------------------
70 * android_atomic_inc
71 * input: r0 = address
72 * output: r0 = old value
73 */
74
75android_atomic_inc:
Ben Cheng8a0a5272009-10-12 16:51:23 -070076 .fnstart
77 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080078 stmdb sp!, {r4, lr}
79 mov r2, r0
801: @ android_atomic_inc
81 ldr r0, [r2]
82 mov r3, #kernel_atomic_base
83#ifdef __ARM_HAVE_PC_INTERWORK
84 add lr, pc, #4
85 add r1, r0, #1
86 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
87#else
88 add r1, r0, #1
89 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
90 mov lr, pc
91 bx r3
92#endif
93 bcc 1b
94 sub r0, r1, #1
95 ldmia sp!, {r4, lr}
96 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -070097 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080098
99/*
100 * ----------------------------------------------------------------------------
101 * android_atomic_dec
102 * input: r0=address
103 * output: r0 = old value
104 */
105
106android_atomic_dec:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700107 .fnstart
108 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109 stmdb sp!, {r4, lr}
110 mov r2, r0
1111: @ android_atomic_dec
112 ldr r0, [r2]
113 mov r3, #kernel_atomic_base
114#ifdef __ARM_HAVE_PC_INTERWORK
115 add lr, pc, #4
116 sub r1, r0, #1
117 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
118#else
119 sub r1, r0, #1
120 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
121 mov lr, pc
122 bx r3
123#endif
124 bcc 1b
125 add r0, r1, #1
126 ldmia sp!, {r4, lr}
127 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700128 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129
130/*
131 * ----------------------------------------------------------------------------
132 * android_atomic_add
133 * input: r0=value, r1=address
134 * output: r0 = old value
135 */
136
137android_atomic_add:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700138 .fnstart
139 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800140 stmdb sp!, {r4, lr}
141 mov r2, r1
142 mov r4, r0
1431: @ android_atomic_add
144 ldr r0, [r2]
145 mov r3, #kernel_atomic_base
146#ifdef __ARM_HAVE_PC_INTERWORK
147 add lr, pc, #4
148 add r1, r0, r4
149 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
150#else
151 add r1, r0, r4
152 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
153 mov lr, pc
154 bx r3
155#endif
156 bcc 1b
157 sub r0, r1, r4
158 ldmia sp!, {r4, lr}
159 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700160 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800161
162
163/*
164 * ----------------------------------------------------------------------------
165 * android_atomic_and
166 * input: r0=value, r1=address
167 * output: r0 = old value
168 */
169
170android_atomic_and:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700171 .fnstart
172 .save {r4, r5, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800173 stmdb sp!, {r4, r5, lr}
174 mov r2, r1 /* r2 = address */
175 mov r4, r0 /* r4 = the value */
1761: @ android_atomic_and
177 ldr r0, [r2] /* r0 = address[0] */
178 mov r3, #kernel_atomic_base
179#ifdef __ARM_HAVE_PC_INTERWORK
180 add lr, pc, #8
181 mov r5, r0 /* r5 = save address[0] */
182 and r1, r0, r4 /* r1 = new value */
183 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
184#else
185 mov r5, r0 /* r5 = save address[0] */
186 and r1, r0, r4 /* r1 = new value */
187 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
188 mov lr, pc
189 bx r3
190#endif
191 bcc 1b
192 mov r0, r5
193 ldmia sp!, {r4, r5, lr}
194 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700195 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800196
197/*
198 * ----------------------------------------------------------------------------
199 * android_atomic_or
200 * input: r0=value, r1=address
201 * output: r0 = old value
202 */
203
204android_atomic_or:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700205 .fnstart
206 .save {r4, r5, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800207 stmdb sp!, {r4, r5, lr}
208 mov r2, r1 /* r2 = address */
209 mov r4, r0 /* r4 = the value */
2101: @ android_atomic_or
211 ldr r0, [r2] /* r0 = address[0] */
212 mov r3, #kernel_atomic_base
213#ifdef __ARM_HAVE_PC_INTERWORK
214 add lr, pc, #8
215 mov r5, r0 /* r5 = save address[0] */
216 orr r1, r0, r4 /* r1 = new value */
217 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
218#else
219 mov r5, r0 /* r5 = save address[0] */
220 orr r1, r0, r4 /* r1 = new value */
221 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
222 mov lr, pc
223 bx r3
224#endif
225 bcc 1b
226 mov r0, r5
227 ldmia sp!, {r4, r5, lr}
228 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700229 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230
231/*
232 * ----------------------------------------------------------------------------
233 * android_atomic_swap
234 * input: r0=value, r1=address
235 * output: r0 = old value
236 */
237
Vinay HARUGOP02608472009-09-10 00:31:12 +0530238/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239android_atomic_swap:
Vinay HARUGOP02608472009-09-10 00:31:12 +0530240#if defined (_ARM_HAVE_LDREX_STREX)
2411: ldrex r2, [r1]
242 strex r3, r0, [r1]
243 teq r3, #0
244 bne 1b
245 mov r0, r2
246 mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */
247#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248 swp r0, r0, [r1]
Vinay HARUGOP02608472009-09-10 00:31:12 +0530249#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800250 bx lr
251
252/*
253 * ----------------------------------------------------------------------------
254 * android_atomic_cmpxchg
255 * input: r0=oldvalue, r1=newvalue, r2=address
256 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
257 */
258
259android_atomic_cmpxchg:
Ben Cheng8a0a5272009-10-12 16:51:23 -0700260 .fnstart
261 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262 stmdb sp!, {r4, lr}
263 mov r4, r0 /* r4 = save oldvalue */
2641: @ android_atomic_cmpxchg
265 mov r3, #kernel_atomic_base
266#ifdef __ARM_HAVE_PC_INTERWORK
267 add lr, pc, #4
268 mov r0, r4 /* r0 = oldvalue */
269 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
270#else
271 mov r0, r4 /* r0 = oldvalue */
272 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
273 mov lr, pc
274 bx r3
275#endif
276 bcs 2f /* swap was made. we're good, return. */
277 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
278 cmp r3, r4
279 beq 1b
2802: @ android_atomic_cmpxchg
281 ldmia sp!, {r4, lr}
282 bx lr
Ben Cheng8a0a5272009-10-12 16:51:23 -0700283 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284
285/*
286 * ----------------------------------------------------------------------------
287 * android_atomic_cmpxchg_64
288 * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
289 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
290 */
291/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */