xref: /aoo41x/main/sal/osl/unx/asm/interlck_sparc.s (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 
29 /*
30  * Implements osl_[increment|decrement]InterlockedCount in two ways:
31  * sparcv8 architecture:                use the "swap" instruction
32  * sparcv9/sparcv8plus architecture:    use the "cas"  instruction
33  *
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
39  *
40  * osl_InterlockedCountSetV9(int bv9)
41  *    bv9 = 0   use sparcv8 "swap" (spinlock)
42  *    bv9 = 1   use sparcv9/sparcv8plus "cas" (no spinlock)
43  *
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).
48  *
49  */
50 
51 #if !defined(__sparcv8plus) && !defined(__sparcv9) && !defined(__sparc_v9__)
52 
53 .section ".data"
54 .align 4
55 osl_incrementInterLockCountFuncPtr:
56 .word osl_incrementInterlockedCountV8
57 .type osl_incrementInterLockCountFuncPtr,#object
58 .size osl_incrementInterLockCountFuncPtr,4
59 
60 .align 4
61 osl_decrementInterLockCountFuncPtr:
62 .word osl_decrementInterlockedCountV8
63 .type osl_decrementInterLockCountFuncPtr,#object
64 .size osl_decrementInterLockCountFuncPtr,4
65 
66 .section   ".text"
67 
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_
71  */
72 .Laddoseven:
73         retl
74         add %o7, %o5, %o5
75 #endif
76 
77  .global   osl_incrementInterlockedCount
78  .align   4
79 
80 osl_incrementInterlockedCount:
81 
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
98 
99 .section   ".text"
100  .global   osl_decrementInterlockedCount
101  .align   4
102 
103 osl_decrementInterlockedCount:
104 
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
121 
122 .section   ".text"
123  .global   osl_InterlockedCountSetV9
124  .align   4
125 
126 osl_InterlockedCountSetV9:
127 
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]
162 
163  .type  osl_InterlockedCountSetV9,#function
164  .size  osl_InterlockedCountSetV9,.-osl_InterlockedCountSetV9
165 
166 
167 .section   ".text"
168  .local   osl_incrementInterlockedCountV8
169  .align   4
170 
171 ! Implements osl_[increment|decrement]InterlockedCount with sparcv8 "swap" instruction.
172 ! Uses -4096 as lock value for spinlock to allow for small negative counts.
173 
174 osl_incrementInterlockedCountV8:
175 
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
187 
188  .type  osl_incrementInterlockedCountV8,#function
189  .size  osl_incrementInterlockedCountV8,.-osl_incrementInterlockedCountV8
190 
191 
192 .section   ".text"
193  .local osl_decrementInterlockedCountV8
194  .align   4
195 
196 osl_decrementInterlockedCountV8:
197 
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
209 
210  .type  osl_decrementInterlockedCountV8,#function
211  .size  osl_decrementInterlockedCountV8,.-osl_decrementInterlockedCountV8
212 
213 #endif /* !__sparcv8plus && !__sparcv9 && !_sparcv9__ */
214 
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
223 
224 !   Implements osl_[increment|decrement]InterlockedCount with sparcv9(sparcv8plus) "cas"
225 !   instruction.
226 
227 osl_incrementInterlockedCountV9:
228 
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
239 
240  .type  osl_incrementInterlockedCountV9,#function
241  .size  osl_incrementInterlockedCountV9,.-osl_incrementInterlockedCountV9
242 
243 
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
252 
253 osl_decrementInterlockedCountV9:
254 
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
265 
266  .type  osl_decrementInterlockedCountV9,#function
267  .size  osl_decrementInterlockedCountV9,.-osl_decrementInterlockedCountV9
268