blob: 9a24976c3dcccf7e0d5f5e1a216a4599b1bb1c23 [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
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -080017#include <machine/cpu-features.h>
18
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -070019/*
Vinay HARUGOP02608472009-09-10 00:31:12 +053020 * NOTE: these atomic operations are SMP safe on all architectures.
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -070021 */
22
23 .text
24 .align
25
26 .global android_atomic_write
27
28 .global android_atomic_inc
29 .global android_atomic_dec
30
31 .global android_atomic_add
32 .global android_atomic_and
33 .global android_atomic_or
34
35 .global android_atomic_swap
36
37 .global android_atomic_cmpxchg
38
39/*
40 * ----------------------------------------------------------------------------
41 * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
42 * clobbered: r3, ip, flags
43 * return 0 if a swap was made, non-zero otherwise.
44 */
45
46 .equ kernel_cmpxchg, 0xFFFF0FC0
47 .equ kernel_atomic_base, 0xFFFF0FFF
48
49/*
50 * ----------------------------------------------------------------------------
51 * android_atomic_write
52 * input: r0=value, r1=address
53 * output: void
54 */
55
56android_atomic_write:
57 stmdb sp!, {r4, lr}
58 mov r2, r1
59 mov r1, r0
601: @ android_atomic_write
61 ldr r0, [r2]
62 mov r3, #kernel_atomic_base
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -080063#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -070064 add lr, pc, #4
65 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -080066#else
67 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
68 mov lr, pc
69 bx r3
70#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -070071 bcc 1b
72 ldmia sp!, {r4, lr}
73 bx lr
74
75/*
76 * ----------------------------------------------------------------------------
77 * android_atomic_inc
78 * input: r0 = address
79 * output: r0 = old value
80 */
81
82android_atomic_inc:
83 stmdb sp!, {r4, lr}
84 mov r2, r0
851: @ android_atomic_inc
86 ldr r0, [r2]
87 mov r3, #kernel_atomic_base
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -080088#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -070089 add lr, pc, #4
90 add r1, r0, #1
91 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -080092#else
93 add r1, r0, #1
94 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
95 mov lr, pc
96 bx r3
97#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -070098 bcc 1b
99 sub r0, r1, #1
100 ldmia sp!, {r4, lr}
101 bx lr
102
103/*
104 * ----------------------------------------------------------------------------
105 * android_atomic_dec
106 * input: r0=address
107 * output: r0 = old value
108 */
109
110android_atomic_dec:
111 stmdb sp!, {r4, lr}
112 mov r2, r0
1131: @ android_atomic_dec
114 ldr r0, [r2]
115 mov r3, #kernel_atomic_base
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800116#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700117 add lr, pc, #4
118 sub r1, r0, #1
119 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800120#else
121 sub r1, r0, #1
122 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
123 mov lr, pc
124 bx r3
125#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700126 bcc 1b
127 add r0, r1, #1
128 ldmia sp!, {r4, lr}
129 bx lr
130
131/*
132 * ----------------------------------------------------------------------------
133 * android_atomic_add
134 * input: r0=value, r1=address
135 * output: r0 = old value
136 */
137
138android_atomic_add:
139 stmdb sp!, {r4, lr}
140 mov r2, r1
141 mov r4, r0
1421: @ android_atomic_add
143 ldr r0, [r2]
144 mov r3, #kernel_atomic_base
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800145#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700146 add lr, pc, #4
147 add r1, r0, r4
148 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800149#else
150 add r1, r0, r4
151 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
152 mov lr, pc
153 bx r3
154#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700155 bcc 1b
156 sub r0, r1, r4
157 ldmia sp!, {r4, lr}
158 bx lr
159
160
161/*
162 * ----------------------------------------------------------------------------
163 * android_atomic_and
164 * input: r0=value, r1=address
165 * output: r0 = old value
166 */
167
168android_atomic_and:
169 stmdb sp!, {r4, r5, lr}
170 mov r2, r1 /* r2 = address */
171 mov r4, r0 /* r4 = the value */
1721: @ android_atomic_and
173 ldr r0, [r2] /* r0 = address[0] */
174 mov r3, #kernel_atomic_base
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800175#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700176 add lr, pc, #8
177 mov r5, r0 /* r5 = save address[0] */
178 and r1, r0, r4 /* r1 = new value */
179 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800180#else
181 mov r5, r0 /* r5 = save address[0] */
182 and r1, r0, r4 /* r1 = new value */
183 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base) /* call cmpxchg() */
184 mov lr, pc
185 bx r3
186#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700187 bcc 1b
188 mov r0, r5
189 ldmia sp!, {r4, r5, lr}
190 bx lr
191
192/*
193 * ----------------------------------------------------------------------------
194 * android_atomic_or
195 * input: r0=value, r1=address
196 * output: r0 = old value
197 */
198
199android_atomic_or:
200 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
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800206#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700207 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() */
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800211#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
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700218 bcc 1b
219 mov r0, r5
220 ldmia sp!, {r4, r5, lr}
221 bx lr
222
223/*
224 * ----------------------------------------------------------------------------
225 * android_atomic_swap
226 * input: r0=value, r1=address
227 * output: r0 = old value
228 */
229
Vinay HARUGOP02608472009-09-10 00:31:12 +0530230/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700231android_atomic_swap:
Vinay HARUGOP02608472009-09-10 00:31:12 +0530232#if defined (_ARM_HAVE_LDREX_STREX)
2331: ldrex r2, [r1]
234 strex r3, r0, [r1]
235 teq r3, #0
236 bne 1b
237 mov r0, r2
238 mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */
239#else
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700240 swp r0, r0, [r1]
Vinay HARUGOP02608472009-09-10 00:31:12 +0530241#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700242 bx lr
243
244/*
245 * ----------------------------------------------------------------------------
246 * android_atomic_cmpxchg
247 * input: r0=oldvalue, r1=newvalue, r2=address
248 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
249 */
250
251android_atomic_cmpxchg:
252 stmdb sp!, {r4, lr}
253 mov r4, r0 /* r4 = save oldvalue */
2541: @ android_atomic_cmpxchg
255 mov r3, #kernel_atomic_base
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800256#ifdef __ARM_HAVE_PC_INTERWORK
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700257 add lr, pc, #4
258 mov r0, r4 /* r0 = oldvalue */
259 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
Jean-Baptiste Queru829dd452008-12-04 12:07:05 -0800260#else
261 mov r0, r4 /* r0 = oldvalue */
262 add r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
263 mov lr, pc
264 bx r3
265#endif
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -0700266 bcs 2f /* swap was made. we're good, return. */
267 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
268 cmp r3, r4
269 beq 1b
2702: @ android_atomic_cmpxchg
271 ldmia sp!, {r4, lr}
272 bx lr
273
274/*
275 * ----------------------------------------------------------------------------
276 * android_atomic_cmpxchg_64
277 * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address
278 * output: r0 = 0 (xchg done) or non-zero (xchg not done)
279 */
280/* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */