merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / asm / interlck_sparc.s
bloba33e3539398e63021c3d49f810975b5cc63eca6b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
30 * Implements osl_[increment|decrement]InterlockedCount in two ways:
31 * sparcv8 architecture: use the "swap" instruction
32 * sparcv9/sparcv8plus architecture: use the "cas" instruction
34 * 32 bit mode with v8 and v8plus support:
35 * Initialize once with osl_InterlockedCountSetV9(int bv9) if you want to
36 * use the "cas" instruction, which is faster (no spinlock needed)
37 * Default is to use the "swap" instruction, which works on all supported
38 * SPARC cpu's
40 * osl_InterlockedCountSetV9(int bv9)
41 * bv9 = 0 use sparcv8 "swap" (spinlock)
42 * bv9 = 1 use sparcv9/sparcv8plus "cas" (no spinlock)
44 * 32 bit mode without v8 support (implies v8plus) or 64 bit mode:
45 * No need (nor the possibilty) to call osl_InterlockedCountSetV9(),
46 * sparcv9 mode is implied. Assemble with -xarch=v8plus (32 bit) or
47 * -xarch=v9 (64 bit).
51 #if !defined(__sparcv8plus) && !defined(__sparcv9) && !defined(__sparc_v9__)
53 .section ".data"
54 .align 4
55 osl_incrementInterLockCountFuncPtr:
56 .word osl_incrementInterlockedCountV8
57 .type osl_incrementInterLockCountFuncPtr,#object
58 .size osl_incrementInterLockCountFuncPtr,4
60 .align 4
61 osl_decrementInterLockCountFuncPtr:
62 .word osl_decrementInterlockedCountV8
63 .type osl_decrementInterLockCountFuncPtr,#object
64 .size osl_decrementInterLockCountFuncPtr,4
66 .section ".text"
68 #if defined(NETBSD) || defined(LINUX)
69 /* add the address of the calling "call" instruction (stored in %o7) to
70 * %o5 which contains _GLOBAL_OFFSET_TABLE_
72 .Laddoseven:
73 retl
74 add %o7, %o5, %o5
75 #endif
77 .global osl_incrementInterlockedCount
78 .align 4
80 osl_incrementInterlockedCount:
82 #if defined(NETBSD) || defined(LINUX)
83 mov %o7, %g1
84 sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
85 call .Laddoseven
86 add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
87 mov %g1, %o7
88 #endif
89 set osl_incrementInterLockCountFuncPtr, %o1
90 #if defined(NETBSD)
91 ld [%o1 + %o5], %o1
92 #endif
93 ld [%o1], %o1
94 jmp %o1
95 nop ! delay slot
96 .type osl_incrementInterlockedCount,#function
97 .size osl_incrementInterlockedCount,.-osl_incrementInterlockedCount
99 .section ".text"
100 .global osl_decrementInterlockedCount
101 .align 4
103 osl_decrementInterlockedCount:
105 #if defined(NETBSD) || defined(LINUX)
106 mov %o7, %g1
107 sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
108 call .Laddoseven
109 add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
110 mov %g1, %o7
111 #endif
112 set osl_decrementInterLockCountFuncPtr, %o1
113 #if defined(NETBSD) || defined(LINUX)
114 ld [%o1 + %o5], %o1
115 #endif
116 ld [%o1], %o1
117 jmp %o1
118 nop ! delay slot
119 .type osl_decrementInterlockedCount,#function
120 .size osl_decrementInterlockedCount,.-osl_decrementInterlockedCount
122 .section ".text"
123 .global osl_InterlockedCountSetV9
124 .align 4
126 osl_InterlockedCountSetV9:
128 #if defined(NETBSD) || defined(LINUX)
129 mov %o7, %g1
130 sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
131 call .Laddoseven
132 add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
133 mov %g1, %o7
134 #endif
135 set osl_incrementInterLockCountFuncPtr, %o1
136 set osl_decrementInterLockCountFuncPtr, %o2
137 cmp %o0, %g0
138 bnz 1f
139 nop ! delay slot
140 set osl_incrementInterlockedCountV8, %o0
141 set osl_decrementInterlockedCountV8, %o3
142 #if defined(NETBSD) || defined(LINUX)
143 ld [%o0 + %o5], %o0
144 ld [%o1 + %o5], %o1
145 ld [%o2 + %o5], %o2
146 ld [%o3 + %o5], %o3
147 #endif
148 st %o3,[%o2]
149 retl
150 st %o0,[%o1]
151 1: set osl_incrementInterlockedCountV9, %o0
152 set osl_decrementInterlockedCountV9, %o3
153 #if defined(NETBSD) || defined(LINUX)
154 ld [%o0 + %o5], %o0
155 ld [%o1 + %o5], %o1
156 ld [%o2 + %o5], %o2
157 ld [%o3 + %o5], %o3
158 #endif
159 st %o3,[%o2]
160 retl
161 st %o0,[%o1]
163 .type osl_InterlockedCountSetV9,#function
164 .size osl_InterlockedCountSetV9,.-osl_InterlockedCountSetV9
167 .section ".text"
168 .local osl_incrementInterlockedCountV8
169 .align 4
171 ! Implements osl_[increment|decrement]InterlockedCount with sparcv8 "swap" instruction.
172 ! Uses -4096 as lock value for spinlock to allow for small negative counts.
174 osl_incrementInterlockedCountV8:
176 1: ld [%o0], %o1
177 cmp %o1, -4096 ! test spinlock
178 be 1b
179 mov -4096, %o1 ! delay slot
180 swap [%o0], %o1
181 cmp %o1, -4096
182 be 1b
183 inc %o1 ! delay slot, if we got spinlock, increment count
184 st %o1, [%o0]
185 retl
186 mov %o1, %o0 ! delay slot
188 .type osl_incrementInterlockedCountV8,#function
189 .size osl_incrementInterlockedCountV8,.-osl_incrementInterlockedCountV8
192 .section ".text"
193 .local osl_decrementInterlockedCountV8
194 .align 4
196 osl_decrementInterlockedCountV8:
198 1: ld [%o0], %o1
199 cmp %o1, -4096 ! test spinlock
200 be 1b
201 mov -4096, %o1 ! delay slot
202 swap [%o0], %o1
203 cmp %o1, -4096
204 be 1b
205 dec %o1 ! delay slot, if we got spinlock, decrement count
206 st %o1, [%o0] ! delay slot
207 retl
208 mov %o1, %o0 ! delay slot
210 .type osl_decrementInterlockedCountV8,#function
211 .size osl_decrementInterlockedCountV8,.-osl_decrementInterlockedCountV8
213 #endif /* !__sparcv8plus && !__sparcv9 && !_sparcv9__ */
215 .section ".text"
216 #if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
217 #define osl_incrementInterlockedCountV9 osl_incrementInterlockedCount
218 .global osl_incrementInterlockedCountV9
219 #else
220 .local osl_incrementInterlockedCountV9
221 #endif
222 .align 8
224 ! Implements osl_[increment|decrement]InterlockedCount with sparcv9(sparcv8plus) "cas"
225 ! instruction.
227 osl_incrementInterlockedCountV9:
229 1: ld [%o0], %o1
230 add %o1, 1, %o2
231 ! allow linux to build for v8
232 .word 0xD5E21009
233 ! cas [%o0], %o1, %o2
234 cmp %o1, %o2
235 bne 1b
236 nop ! delay slot
237 retl
238 add %o2, 1, %o0 ! delay slot
240 .type osl_incrementInterlockedCountV9,#function
241 .size osl_incrementInterlockedCountV9,.-osl_incrementInterlockedCountV9
244 .section ".text"
245 #if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
246 #define osl_decrementInterlockedCountV9 osl_decrementInterlockedCount
247 .global osl_decrementInterlockedCountV9
248 #else
249 .local osl_decrementInterlockedCountV9
250 #endif
251 .align 8
253 osl_decrementInterlockedCountV9:
255 1: ld [%o0], %o1
256 sub %o1, 1, %o2
257 ! allow linux to build for v8
258 .word 0xD5E21009
259 ! cas [%o0], %o1, %o2
260 cmp %o1, %o2
261 bne 1b
262 nop ! delay slot
263 retl
264 sub %o2, 1, %o0 ! delay slot
266 .type osl_decrementInterlockedCountV9,#function
267 .size osl_decrementInterlockedCountV9,.-osl_decrementInterlockedCountV9