!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! atomic-sparc.s ! ! $Id$ ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave ! Software division. 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. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .section ".text" .align 8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! extern "C" int __rw_atomic_xchg32 (int *x, int y); ! ! Atomically assigns the 32-bit value value y to *x and returns ! the original (before assignment) 32-bit value of *x. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .type __rw_atomic_xchg32, #function .global __rw_atomic_xchg32 __rw_atomic_xchg32: ! (int *x: %o0, int y: %o1) swap [%o0], %o1 ! *x <-> y retl mov %o1, %o0 ! return original value of *x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! extern "C" int __rw_atomic_add32 (int *x, int y); ! ! Atomically increments the 32-bit value value *x by y and returns ! the new (after increment) 32-bit value of *x. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .type __rw_atomic_add32, #function .global __rw_atomic_add32 __rw_atomic_add32: ! (int *x: %o0, int y: %o1) mov -1, %o2 ! INT_MAX is reserved srl %o2, 1, %o2 ! %o2 = -1U >> 1 (== INT_MAX) .__rw_retry: mov %o2, %o3 ! make a copy for swap swap [%o0], %o3 ! swap *x for %o3 cmp %o3, %o2 ! if *x == INT_MAX (i.e., resource is locked) beq,a .__rw_busywait ! then busy-wait (else annul next insn) nop ! else perform add and return add %o3, %o1, %o2 ! %o2 = *x + y st %o2, [%o0] ! store the sum in *x retl ! return to caller mov %o2, %o0 ! (delayed) store result in %o0 .__rw_busywait: ! busy-wait with loads (cheaper than swaps) cmp %o3, %o2 ! if %o3 == INT_MAX be .__rw_busywait ! then spin ld [%o0], %o3 ! (delayed) %o3 = *x ba,a .__rw_retry ! otherwise, try again for lock nop