blob: 2a4c34f06851a879f86d67cbfc074bea9218bb77 [file] [log] [blame]
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -07001/*
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/*
18 * NOTE: these atomic operations are SMP safe on all architectures,
19 * except swap(), see below.
20 */
21
22 .text
23 .align
24
25 .global android_atomic_write
26
27 .global android_atomic_inc
28 .global android_atomic_dec
29
30 .global android_atomic_add
31 .global android_atomic_and
32 .global android_atomic_or
33
34 .global android_atomic_swap
35
36 .global android_atomic_cmpxchg
37
38/*
39 * ----------------------------------------------------------------------------
40 * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
41 * clobbered: r3, ip, flags
42 * return 0 if a swap was made, non-zero otherwise.
43 */
44
45 .equ kernel_cmpxchg, 0xFFFF0FC0
46 .equ kernel_atomic_base, 0xFFFF0FFF
47
48/*
49 * ----------------------------------------------------------------------------
50 * android_atomic_write
51 * input: r0=value, r1=address
52 * output: void
53 */
54
55android_atomic_write:
56 stmdb sp!, {r4, lr}
57 mov r2, r1
58 mov r1, r0
591: @ android_atomic_write
60 ldr r0, [r2]
61 mov r3, #kernel_atomic_base
62 add lr, pc, #4
63 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
64 bcc 1b
65 ldmia sp!, {r4, lr}
66 bx lr
67
68/*
69 * ----------------------------------------------------------------------------
70 * android_atomic_inc
71 * input: r0 = address
72 * output: r0 = old value
73 */
74
75android_atomic_inc:
76 stmdb sp!, {r4, lr}
77 mov r2, r0
781: @ android_atomic_inc
79 ldr r0, [r2]
80 mov r3, #kernel_atomic_base
81 add lr, pc, #4
82 add r1, r0, #1
83 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
84 bcc 1b
85 sub r0, r1, #1
86 ldmia sp!, {r4, lr}
87 bx lr
88
89/*
90 * ----------------------------------------------------------------------------
91 * android_atomic_dec
92 * input: r0=address
93 * output: r0 = old value
94 */
95
96android_atomic_dec:
97 stmdb sp!, {r4, lr}
98 mov r2, r0
991: @ android_atomic_dec
100 ldr r0, [r2]
101 mov r3, #kernel_atomic_base
102 add lr, pc, #4
103 sub r1, r0, #1
104 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
105 bcc 1b
106 add r0, r1, #1
107 ldmia sp!, {r4, lr}
108 bx lr
109
110/*
111 * ----------------------------------------------------------------------------
112 * android_atomic_add
113 * input: r0=value, r1=address
114 * output: r0 = old value
115 */
116
117android_atomic_add:
118 stmdb sp!, {r4, lr}
119 mov r2, r1
120 mov r4, r0
1211: @ android_atomic_add
122 ldr r0, [r2]
123 mov r3, #kernel_atomic_base
124 add lr, pc, #4
125 add r1, r0, r4
126 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
127 bcc 1b
128 sub r0, r1, r4
129 ldmia sp!, {r4, lr}
130 bx lr
131
132
133/*
134 * ----------------------------------------------------------------------------
135 * android_atomic_and
136 * input: r0=value, r1=address
137 * output: r0 = old value
138 */
139
140android_atomic_and:
141 stmdb sp!, {r4, r5, lr}
142 mov r2, r1 /* r2 = address */
143 mov r4, r0 /* r4 = the value */
1441: @ android_atomic_and
145 ldr r0, [r2] /* r0 = address[0] */
146 mov r3, #kernel_atomic_base
147 add lr, pc, #8
148 mov r5, r0 /* r5 = save address[0] */
149 and r1, r0, r4 /* r1 = new value */
150 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
151 bcc 1b
152 mov r0, r5
153 ldmia sp!, {r4, r5, lr}
154 bx lr
155
156/*
157 * ----------------------------------------------------------------------------
158 * android_atomic_or
159 * input: r0=value, r1=address
160 * output: r0 = old value
161 */
162
163android_atomic_or:
164 stmdb sp!, {r4, r5, lr}
165 mov r2, r1 /* r2 = address */
166 mov r4, r0 /* r4 = the value */
1671: @ android_atomic_or
168 ldr r0, [r2] /* r0 = address[0] */
169 mov r3, #kernel_atomic_base
170 add lr, pc, #8
171 mov r5, r0 /* r5 = save address[0] */
172 orr r1, r0, r4 /* r1 = new value */
173 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
174 bcc 1b
175 mov r0, r5
176 ldmia sp!, {r4, r5, lr}
177 bx lr
178
179/*
180 * ----------------------------------------------------------------------------
181 * android_atomic_swap
182 * input: r0=value, r1=address
183 * output: r0 = old value
184 */
185
186/* FIXME: this is not safe on SMP systems
187 * a general way to do it is to use kernel_cmpxchg */
188
189android_atomic_swap:
190 swp r0, r0, [r1]
191 bx lr
192
193/*
194 * ----------------------------------------------------------------------------
195 * android_atomic_cmpxchg
196 * input: r0=oldvalue, r1=newvalue, r2=address
197 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
198 */
199
200android_atomic_cmpxchg:
201 stmdb sp!, {r4, lr}
202 mov r4, r0 /* r4 = save oldvalue */
2031: @ android_atomic_cmpxchg
204 mov r3, #kernel_atomic_base
205 add lr, pc, #4
206 mov r0, r4 /* r0 = oldvalue */
207 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
208 bcs 2f /* swap was made. we're good, return. */
209 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
210 cmp r3, r4
211 beq 1b
2122: @ android_atomic_cmpxchg
213 ldmia sp!, {r4, lr}
214 bx lr
215
216/*
217 * ----------------------------------------------------------------------------
218 * android_atomic_cmpxchg_64
219 * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
220 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
221 */
222/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */