summaryrefslogtreecommitdiff
path: root/sal/osl/unx/asm/interlck_sparc.s
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/unx/asm/interlck_sparc.s')
-rw-r--r--sal/osl/unx/asm/interlck_sparc.s267
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