blob: 7befd780268a735cfe219993494d8999bde985e7 [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/*
20 * NOTE: these atomic operations are SMP safe on all architectures,
21 * except swap(), see below.
22 */
23
24 .text
25 .align
26
27 .global android_atomic_write
28
29 .global android_atomic_inc
30 .global android_atomic_dec
31
32 .global android_atomic_add
33 .global android_atomic_and
34 .global android_atomic_or
35
36 .global android_atomic_swap
37
38 .global android_atomic_cmpxchg
39
40/*
41 * ----------------------------------------------------------------------------
42 * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
43 * clobbered: r3, ip, flags
44 * return 0 if a swap was made, non-zero otherwise.
45 */
46
47 .equ kernel_cmpxchg, 0xFFFF0FC0
48 .equ kernel_atomic_base, 0xFFFF0FFF
49
50/*
51 * ----------------------------------------------------------------------------
52 * android_atomic_write
53 * input: r0=value, r1=address
54 * output: void
55 */
56
57android_atomic_write:
Mathias Agopianca5e0bc2009-09-03 14:49:58 -070058 str r0, [r1]
59 bx lr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
61/*
62 * ----------------------------------------------------------------------------
63 * android_atomic_inc
64 * input: r0 = address
65 * output: r0 = old value
66 */
67
68android_atomic_inc:
Ben Cheng21ec7792009-10-12 16:51:23 -070069 .fnstart
70 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071 stmdb sp!, {r4, lr}
72 mov r2, r0
731: @ android_atomic_inc
74 ldr r0, [r2]
75 mov r3, #kernel_atomic_base
76#ifdef __ARM_HAVE_PC_INTERWORK
77 add lr, pc, #4
78 add r1, r0, #1
79 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
80#else
81 add r1, r0, #1
82 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
83 mov lr, pc
84 bx r3
85#endif
86 bcc 1b
87 sub r0, r1, #1
88 ldmia sp!, {r4, lr}
89 bx lr
Ben Cheng21ec7792009-10-12 16:51:23 -070090 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080091
92/*
93 * ----------------------------------------------------------------------------
94 * android_atomic_dec
95 * input: r0=address
96 * output: r0 = old value
97 */
98
99android_atomic_dec:
Ben Cheng21ec7792009-10-12 16:51:23 -0700100 .fnstart
101 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 stmdb sp!, {r4, lr}
103 mov r2, r0
1041: @ android_atomic_dec
105 ldr r0, [r2]
106 mov r3, #kernel_atomic_base
107#ifdef __ARM_HAVE_PC_INTERWORK
108 add lr, pc, #4
109 sub r1, r0, #1
110 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
111#else
112 sub r1, r0, #1
113 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
114 mov lr, pc
115 bx r3
116#endif
117 bcc 1b
118 add r0, r1, #1
119 ldmia sp!, {r4, lr}
120 bx lr
Ben Cheng21ec7792009-10-12 16:51:23 -0700121 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800122
123/*
124 * ----------------------------------------------------------------------------
125 * android_atomic_add
126 * input: r0=value, r1=address
127 * output: r0 = old value
128 */
129
130android_atomic_add:
Ben Cheng21ec7792009-10-12 16:51:23 -0700131 .fnstart
132 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800133 stmdb sp!, {r4, lr}
134 mov r2, r1
135 mov r4, r0
1361: @ android_atomic_add
137 ldr r0, [r2]
138 mov r3, #kernel_atomic_base
139#ifdef __ARM_HAVE_PC_INTERWORK
140 add lr, pc, #4
141 add r1, r0, r4
142 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
143#else
144 add r1, r0, r4
145 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
146 mov lr, pc
147 bx r3
148#endif
149 bcc 1b
150 sub r0, r1, r4
151 ldmia sp!, {r4, lr}
152 bx lr
Ben Cheng21ec7792009-10-12 16:51:23 -0700153 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800154
155
156/*
157 * ----------------------------------------------------------------------------
158 * android_atomic_and
159 * input: r0=value, r1=address
160 * output: r0 = old value
161 */
162
163android_atomic_and:
Ben Cheng21ec7792009-10-12 16:51:23 -0700164 .fnstart
165 .save {r4, r5, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166 stmdb sp!, {r4, r5, lr}
167 mov r2, r1 /* r2 = address */
168 mov r4, r0 /* r4 = the value */
1691: @ android_atomic_and
170 ldr r0, [r2] /* r0 = address[0] */
171 mov r3, #kernel_atomic_base
172#ifdef __ARM_HAVE_PC_INTERWORK
173 add lr, pc, #8
174 mov r5, r0 /* r5 = save address[0] */
175 and r1, r0, r4 /* r1 = new value */
176 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
177#else
178 mov r5, r0 /* r5 = save address[0] */
179 and r1, r0, r4 /* r1 = new value */
180 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
181 mov lr, pc
182 bx r3
183#endif
184 bcc 1b
185 mov r0, r5
186 ldmia sp!, {r4, r5, lr}
187 bx lr
Ben Cheng21ec7792009-10-12 16:51:23 -0700188 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189
190/*
191 * ----------------------------------------------------------------------------
192 * android_atomic_or
193 * input: r0=value, r1=address
194 * output: r0 = old value
195 */
196
197android_atomic_or:
Ben Cheng21ec7792009-10-12 16:51:23 -0700198 .fnstart
199 .save {r4, r5, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 stmdb sp!, {r4, r5, lr}
201 mov r2, r1 /* r2 = address */
202 mov r4, r0 /* r4 = the value */
2031: @ android_atomic_or
204 ldr r0, [r2] /* r0 = address[0] */
205 mov r3, #kernel_atomic_base
206#ifdef __ARM_HAVE_PC_INTERWORK
207 add lr, pc, #8
208 mov r5, r0 /* r5 = save address[0] */
209 orr r1, r0, r4 /* r1 = new value */
210 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
211#else
212 mov r5, r0 /* r5 = save address[0] */
213 orr r1, r0, r4 /* r1 = new value */
214 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
215 mov lr, pc
216 bx r3
217#endif
218 bcc 1b
219 mov r0, r5
220 ldmia sp!, {r4, r5, lr}
221 bx lr
Ben Cheng21ec7792009-10-12 16:51:23 -0700222 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800223
224/*
225 * ----------------------------------------------------------------------------
226 * android_atomic_swap
227 * input: r0=value, r1=address
228 * output: r0 = old value
229 */
230
231/* FIXME: this is not safe on SMP systems
232 * a general way to do it is to use kernel_cmpxchg */
233
234android_atomic_swap:
235 swp r0, r0, [r1]
236 bx lr
237
238/*
239 * ----------------------------------------------------------------------------
240 * android_atomic_cmpxchg
241 * input: r0=oldvalue, r1=newvalue, r2=address
242 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
243 */
244
245android_atomic_cmpxchg:
Ben Cheng21ec7792009-10-12 16:51:23 -0700246 .fnstart
247 .save {r4, lr}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248 stmdb sp!, {r4, lr}
249 mov r4, r0 /* r4 = save oldvalue */
2501: @ android_atomic_cmpxchg
251 mov r3, #kernel_atomic_base
252#ifdef __ARM_HAVE_PC_INTERWORK
253 add lr, pc, #4
254 mov r0, r4 /* r0 = oldvalue */
255 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
256#else
257 mov r0, r4 /* r0 = oldvalue */
258 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
259 mov lr, pc
260 bx r3
261#endif
262 bcs 2f /* swap was made. we're good, return. */
263 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
264 cmp r3, r4
265 beq 1b
2662: @ android_atomic_cmpxchg
267 ldmia sp!, {r4, lr}
268 bx lr
Ben Cheng21ec7792009-10-12 16:51:23 -0700269 .fnend
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270
271/*
272 * ----------------------------------------------------------------------------
273 * android_atomic_cmpxchg_64
274 * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
275 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
276 */
277/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */