blob: 68fa1197394dab1804cc923ea46a9a2107e4ab7d [file] [log] [blame]
/**************************************************************
*
* 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.
*
*************************************************************/
/*
* Implements osl_[increment|decrement]InterlockedCount in two ways:
* sparcv8 architecture: use the "swap" instruction
* sparcv9/sparcv8plus architecture: use the "cas" instruction
*
* 32 bit mode with v8 and v8plus support:
* Initialize once with osl_InterlockedCountSetV9(int bv9) if you want to
* use the "cas" instruction, which is faster (no spinlock needed)
* Default is to use the "swap" instruction, which works on all supported
* SPARC cpu's
*
* osl_InterlockedCountSetV9(int bv9)
* bv9 = 0 use sparcv8 "swap" (spinlock)
* bv9 = 1 use sparcv9/sparcv8plus "cas" (no spinlock)
*
* 32 bit mode without v8 support (implies v8plus) or 64 bit mode:
* No need (nor the possibilty) to call osl_InterlockedCountSetV9(),
* sparcv9 mode is implied. Assemble with -xarch=v8plus (32 bit) or
* -xarch=v9 (64 bit).
*
*/
#if !defined(__sparcv8plus) && !defined(__sparcv9) && !defined(__sparc_v9__)
.section ".data"
.align 4
osl_incrementInterLockCountFuncPtr:
.word osl_incrementInterlockedCountV8
.type osl_incrementInterLockCountFuncPtr,#object
.size osl_incrementInterLockCountFuncPtr,4
.align 4
osl_decrementInterLockCountFuncPtr:
.word osl_decrementInterlockedCountV8
.type osl_decrementInterLockCountFuncPtr,#object
.size osl_decrementInterLockCountFuncPtr,4
.section ".text"
#if defined(NETBSD) || defined(LINUX)
/* add the address of the calling "call" instruction (stored in %o7) to
* %o5 which contains _GLOBAL_OFFSET_TABLE_
*/
.Laddoseven:
retl
add %o7, %o5, %o5
#endif
.global osl_incrementInterlockedCount
.align 4
osl_incrementInterlockedCount:
#if defined(NETBSD) || defined(LINUX)
mov %o7, %g1
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
call .Laddoseven
add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
mov %g1, %o7
#endif
set osl_incrementInterLockCountFuncPtr, %o1
#if defined(NETBSD)
ld [%o1 + %o5], %o1
#endif
ld [%o1], %o1
jmp %o1
nop ! delay slot
.type osl_incrementInterlockedCount,#function
.size osl_incrementInterlockedCount,.-osl_incrementInterlockedCount
.section ".text"
.global osl_decrementInterlockedCount
.align 4
osl_decrementInterlockedCount:
#if defined(NETBSD) || defined(LINUX)
mov %o7, %g1
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
call .Laddoseven
add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
mov %g1, %o7
#endif
set osl_decrementInterLockCountFuncPtr, %o1
#if defined(NETBSD) || defined(LINUX)
ld [%o1 + %o5], %o1
#endif
ld [%o1], %o1
jmp %o1
nop ! delay slot
.type osl_decrementInterlockedCount,#function
.size osl_decrementInterlockedCount,.-osl_decrementInterlockedCount
.section ".text"
.global osl_InterlockedCountSetV9
.align 4
osl_InterlockedCountSetV9:
#if defined(NETBSD) || defined(LINUX)
mov %o7, %g1
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
call .Laddoseven
add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
mov %g1, %o7
#endif
set osl_incrementInterLockCountFuncPtr, %o1
set osl_decrementInterLockCountFuncPtr, %o2
cmp %o0, %g0
bnz 1f
nop ! delay slot
set osl_incrementInterlockedCountV8, %o0
set osl_decrementInterlockedCountV8, %o3
#if defined(NETBSD) || defined(LINUX)
ld [%o0 + %o5], %o0
ld [%o1 + %o5], %o1
ld [%o2 + %o5], %o2
ld [%o3 + %o5], %o3
#endif
st %o3,[%o2]
retl
st %o0,[%o1]
1: set osl_incrementInterlockedCountV9, %o0
set osl_decrementInterlockedCountV9, %o3
#if defined(NETBSD) || defined(LINUX)
ld [%o0 + %o5], %o0
ld [%o1 + %o5], %o1
ld [%o2 + %o5], %o2
ld [%o3 + %o5], %o3
#endif
st %o3,[%o2]
retl
st %o0,[%o1]
.type osl_InterlockedCountSetV9,#function
.size osl_InterlockedCountSetV9,.-osl_InterlockedCountSetV9
.section ".text"
.local osl_incrementInterlockedCountV8
.align 4
! Implements osl_[increment|decrement]InterlockedCount with sparcv8 "swap" instruction.
! Uses -4096 as lock value for spinlock to allow for small negative counts.
osl_incrementInterlockedCountV8:
1: ld [%o0], %o1
cmp %o1, -4096 ! test spinlock
be 1b
mov -4096, %o1 ! delay slot
swap [%o0], %o1
cmp %o1, -4096
be 1b
inc %o1 ! delay slot, if we got spinlock, increment count
st %o1, [%o0]
retl
mov %o1, %o0 ! delay slot
.type osl_incrementInterlockedCountV8,#function
.size osl_incrementInterlockedCountV8,.-osl_incrementInterlockedCountV8
.section ".text"
.local osl_decrementInterlockedCountV8
.align 4
osl_decrementInterlockedCountV8:
1: ld [%o0], %o1
cmp %o1, -4096 ! test spinlock
be 1b
mov -4096, %o1 ! delay slot
swap [%o0], %o1
cmp %o1, -4096
be 1b
dec %o1 ! delay slot, if we got spinlock, decrement count
st %o1, [%o0] ! delay slot
retl
mov %o1, %o0 ! delay slot
.type osl_decrementInterlockedCountV8,#function
.size osl_decrementInterlockedCountV8,.-osl_decrementInterlockedCountV8
#endif /* !__sparcv8plus && !__sparcv9 && !_sparcv9__ */
.section ".text"
#if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
#define osl_incrementInterlockedCountV9 osl_incrementInterlockedCount
.global osl_incrementInterlockedCountV9
#else
.local osl_incrementInterlockedCountV9
#endif
.align 8
! Implements osl_[increment|decrement]InterlockedCount with sparcv9(sparcv8plus) "cas"
! instruction.
osl_incrementInterlockedCountV9:
1: ld [%o0], %o1
add %o1, 1, %o2
! allow linux to build for v8
.word 0xD5E21009
! cas [%o0], %o1, %o2
cmp %o1, %o2
bne 1b
nop ! delay slot
retl
add %o2, 1, %o0 ! delay slot
.type osl_incrementInterlockedCountV9,#function
.size osl_incrementInterlockedCountV9,.-osl_incrementInterlockedCountV9
.section ".text"
#if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
#define osl_decrementInterlockedCountV9 osl_decrementInterlockedCount
.global osl_decrementInterlockedCountV9
#else
.local osl_decrementInterlockedCountV9
#endif
.align 8
osl_decrementInterlockedCountV9:
1: ld [%o0], %o1
sub %o1, 1, %o2
! allow linux to build for v8
.word 0xD5E21009
! cas [%o0], %o1, %o2
cmp %o1, %o2
bne 1b
nop ! delay slot
retl
sub %o2, 1, %o0 ! delay slot
.type osl_decrementInterlockedCountV9,#function
.size osl_decrementInterlockedCountV9,.-osl_decrementInterlockedCountV9