| /* | 
 |  * Copyright (C) 2008 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 |  | 
 |     .text | 
 |     .align | 
 |      | 
 |     .global android_atomic_write | 
 |      | 
 |     .global android_atomic_inc | 
 |     .global android_atomic_dec | 
 |      | 
 |     .global android_atomic_add | 
 |     .global android_atomic_and | 
 |     .global android_atomic_or | 
 |      | 
 |     .global android_atomic_swap | 
 |      | 
 |     .global android_atomic_cmpxchg | 
 |      | 
 |  | 
 |  | 
 | /* FIXME: On SMP systems memory barriers may be needed */ | 
 | #warning  "this file is not safe with SMP systems" | 
 |  | 
 |  | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_write | 
 |  * input: r0=value, r1=address | 
 |  * output: void | 
 |  */ | 
 |  | 
 | android_atomic_write: | 
 | 1:  ldrex   r12, [r1] | 
 |     strex   r12, r0, [r1] | 
 |     cmp     r12, #0 | 
 |     bne     1b | 
 |     bx      lr | 
 |  | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_inc | 
 |  * input: r0 = address | 
 |  * output: r0 = old value | 
 |  */ | 
 |   | 
 | android_atomic_inc: | 
 |     mov     r12, r0 | 
 | 1:  ldrex   r0, [r12] | 
 |     add     r2, r0, #1 | 
 |     strex   r1, r2, [r12] | 
 |     cmp     r1, #0 | 
 |     bxeq    lr | 
 |     b       1b | 
 |  | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_dec | 
 |  * input: r0=address | 
 |  * output: r0 = old value | 
 |  */ | 
 |   | 
 | android_atomic_dec: | 
 |     mov     r12, r0 | 
 | 1:  ldrex   r0, [r12] | 
 |     sub     r2, r0, #1 | 
 |     strex   r1, r2, [r12] | 
 |     cmp     r1, #0 | 
 |     bxeq    lr | 
 |     b       1b | 
 |  | 
 |      | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_add | 
 |  * input: r0=value, r1=address | 
 |  * output: r0 = old value | 
 |  */ | 
 |  | 
 | android_atomic_add: | 
 |     mov     r12, r0 | 
 | 1:  ldrex   r0, [r1] | 
 |     add     r2, r0, r12 | 
 |     strex   r3, r2, [r1] | 
 |     cmp     r3, #0 | 
 |     bxeq    lr | 
 |     b       1b | 
 |      | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_and | 
 |  * input: r0=value, r1=address | 
 |  * output: r0 = old value | 
 |  */ | 
 |  | 
 | android_atomic_and: | 
 |     mov     r12, r0 | 
 | 1:  ldrex   r0, [r1] | 
 |     and     r2, r0, r12 | 
 |     strex   r3, r2, [r1] | 
 |     cmp     r3, #0 | 
 |     bxeq    lr | 
 |     b       1b | 
 |  | 
 |      | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_or | 
 |  * input: r0=value, r1=address | 
 |  * output: r0 = old value | 
 |  */ | 
 |  | 
 | android_atomic_or: | 
 |     mov     r12, r0 | 
 | 1:  ldrex   r0, [r1] | 
 |     orr     r2, r0, r12 | 
 |     strex   r3, r2, [r1] | 
 |     cmp     r3, #0 | 
 |     bxeq    lr | 
 |     b       1b | 
 |  | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_swap | 
 |  * input: r0=value, r1=address | 
 |  * output: r0 = old value | 
 |  */ | 
 |  | 
 | android_atomic_swap: | 
 |     swp     r0, r0, [r1] | 
 |     bx      lr | 
 |  | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_cmpxchg | 
 |  * input: r0=oldvalue, r1=newvalue, r2=address | 
 |  * output: r0 = 0 (xchg done) or non-zero (xchg not done) | 
 |  */ | 
 |  | 
 | android_atomic_cmpxchg: | 
 |     mov     r12, r1 | 
 |     ldrex   r3, [r2] | 
 |     eors    r0, r0, r3 | 
 |     strexeq r0, r12, [r2] | 
 |     bx      lr | 
 |  | 
 |  | 
 |  | 
 | /* | 
 |  * ---------------------------------------------------------------------------- | 
 |  * android_atomic_cmpxchg_64 | 
 |  * input: r0-r1=oldvalue, r2-r3=newvalue, arg4 (on stack)=address | 
 |  * output: r0 = 0 (xchg done) or non-zero (xchg not done) | 
 |  */ | 
 | /* TODO: NEED IMPLEMENTATION FOR THIS ARCHITECTURE */ |