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