diff options
Diffstat (limited to 'sal/osl/unx/asm/interlck_sparc.s')
-rw-r--r-- | sal/osl/unx/asm/interlck_sparc.s | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/sal/osl/unx/asm/interlck_sparc.s b/sal/osl/unx/asm/interlck_sparc.s new file mode 100644 index 000000000000..a33e3539398e --- /dev/null +++ b/sal/osl/unx/asm/interlck_sparc.s @@ -0,0 +1,267 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 |