| /************************************************************** |
| * |
| * 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 possibility) 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 |