!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! sparc/atomic.s
!
! $Id: atomic.s 580483 2007-09-28 20:55:52Z sebor $
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Licensed to the Apache Software  Foundation (ASF) under one or more
! contributor  license agreements.  See  the NOTICE  file distributed
! with  this  work  for  additional information  regarding  copyright
! ownership.   The ASF  licenses this  file to  you 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.
!
! Copyright 2002-2006 Rogue Wave Software.
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    .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
