blob: a440a82fde93fbe78783af37a250834b39014c0e [file] [log] [blame]
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! sparc/atomic.s
!
! $Id$
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! 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