xref: /trunk/main/sal/osl/unx/asm/interlck_sparc.s (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 
25 /*
26  * Implements osl_[increment|decrement]InterlockedCount in two ways:
27  * sparcv8 architecture:                use the "swap" instruction
28  * sparcv9/sparcv8plus architecture:    use the "cas"  instruction
29  *
30  * 32 bit mode with v8 and v8plus support:
31  * Initialize once with osl_InterlockedCountSetV9(int bv9) if you want to
32  * use the "cas" instruction, which is faster (no spinlock needed)
33  * Default is to use the "swap" instruction, which works on all supported
34  * SPARC cpu's
35  *
36  * osl_InterlockedCountSetV9(int bv9)
37  *    bv9 = 0   use sparcv8 "swap" (spinlock)
38  *    bv9 = 1   use sparcv9/sparcv8plus "cas" (no spinlock)
39  *
40  * 32 bit mode without v8 support (implies v8plus) or 64 bit mode:
41  * No need (nor the possibility) to call osl_InterlockedCountSetV9(),
42  * sparcv9 mode is implied. Assemble with -xarch=v8plus (32 bit) or
43  * -xarch=v9 (64 bit).
44  *
45  */
46 
47 #if !defined(__sparcv8plus) && !defined(__sparcv9) && !defined(__sparc_v9__)
48 
49 .section ".data"
50 .align 4
51 osl_incrementInterLockCountFuncPtr:
52 .word osl_incrementInterlockedCountV8
53 .type osl_incrementInterLockCountFuncPtr,#object
54 .size osl_incrementInterLockCountFuncPtr,4
55 
56 .align 4
57 osl_decrementInterLockCountFuncPtr:
58 .word osl_decrementInterlockedCountV8
59 .type osl_decrementInterLockCountFuncPtr,#object
60 .size osl_decrementInterLockCountFuncPtr,4
61 
62 .section   ".text"
63 
64 #if defined(NETBSD) || defined(LINUX)
65 /* add the address of the calling "call" instruction (stored in %o7) to
66  * %o5 which contains _GLOBAL_OFFSET_TABLE_
67  */
68 .Laddoseven:
69         retl
70         add %o7, %o5, %o5
71 #endif
72 
73  .global   osl_incrementInterlockedCount
74  .align   4
75 
76 osl_incrementInterlockedCount:
77 
78 #if defined(NETBSD) || defined(LINUX)
79         mov     %o7, %g1
80         sethi   %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
81         call    .Laddoseven
82         add     %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
83         mov     %g1, %o7
84 #endif
85         set     osl_incrementInterLockCountFuncPtr, %o1
86 #if defined(NETBSD)
87         ld      [%o1 + %o5], %o1
88 #endif
89         ld      [%o1], %o1
90         jmp     %o1
91         nop                                             ! delay slot
92  .type  osl_incrementInterlockedCount,#function
93  .size  osl_incrementInterlockedCount,.-osl_incrementInterlockedCount
94 
95 .section   ".text"
96  .global   osl_decrementInterlockedCount
97  .align   4
98 
99 osl_decrementInterlockedCount:
100 
101 #if defined(NETBSD) || defined(LINUX)
102         mov     %o7, %g1
103         sethi   %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
104         call    .Laddoseven
105         add     %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
106         mov     %g1, %o7
107 #endif
108         set     osl_decrementInterLockCountFuncPtr, %o1
109 #if defined(NETBSD) || defined(LINUX)
110         ld      [%o1 + %o5], %o1
111 #endif
112         ld      [%o1], %o1
113         jmp     %o1
114         nop                                             ! delay slot
115  .type  osl_decrementInterlockedCount,#function
116  .size  osl_decrementInterlockedCount,.-osl_decrementInterlockedCount
117 
118 .section   ".text"
119  .global   osl_InterlockedCountSetV9
120  .align   4
121 
122 osl_InterlockedCountSetV9:
123 
124 #if defined(NETBSD) || defined(LINUX)
125         mov	    %o7, %g1
126         sethi	%hi(_GLOBAL_OFFSET_TABLE_-4), %o5
127         call	.Laddoseven
128         add	    %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
129         mov	    %g1, %o7
130 #endif
131         set     osl_incrementInterLockCountFuncPtr, %o1
132         set     osl_decrementInterLockCountFuncPtr, %o2
133         cmp     %o0, %g0
134         bnz     1f
135         nop                                             ! delay slot
136         set     osl_incrementInterlockedCountV8, %o0
137         set     osl_decrementInterlockedCountV8, %o3
138 #if defined(NETBSD) || defined(LINUX)
139         ld      [%o0 + %o5], %o0
140         ld      [%o1 + %o5], %o1
141         ld      [%o2 + %o5], %o2
142         ld      [%o3 + %o5], %o3
143 #endif
144         st      %o3,[%o2]
145         retl
146         st      %o0,[%o1]
147 1:      set     osl_incrementInterlockedCountV9, %o0
148         set     osl_decrementInterlockedCountV9, %o3
149 #if defined(NETBSD) || defined(LINUX)
150         ld      [%o0 + %o5], %o0
151         ld      [%o1 + %o5], %o1
152         ld      [%o2 + %o5], %o2
153         ld      [%o3 + %o5], %o3
154 #endif
155         st      %o3,[%o2]
156         retl
157         st      %o0,[%o1]
158 
159  .type  osl_InterlockedCountSetV9,#function
160  .size  osl_InterlockedCountSetV9,.-osl_InterlockedCountSetV9
161 
162 
163 .section   ".text"
164  .local   osl_incrementInterlockedCountV8
165  .align   4
166 
167 ! Implements osl_[increment|decrement]InterlockedCount with sparcv8 "swap" instruction.
168 ! Uses -4096 as lock value for spinlock to allow for small negative counts.
169 
170 osl_incrementInterlockedCountV8:
171 
172 1:      ld      [%o0], %o1
173         cmp     %o1, -4096          ! test spinlock
174         be      1b
175         mov     -4096, %o1          ! delay slot
176         swap    [%o0], %o1
177         cmp     %o1, -4096
178         be      1b
179         inc     %o1                 ! delay slot, if we got spinlock, increment count
180         st      %o1, [%o0]
181         retl
182         mov     %o1, %o0            ! delay slot
183 
184  .type  osl_incrementInterlockedCountV8,#function
185  .size  osl_incrementInterlockedCountV8,.-osl_incrementInterlockedCountV8
186 
187 
188 .section   ".text"
189  .local osl_decrementInterlockedCountV8
190  .align   4
191 
192 osl_decrementInterlockedCountV8:
193 
194 1:      ld      [%o0], %o1
195         cmp     %o1, -4096          ! test spinlock
196         be      1b
197         mov     -4096, %o1          ! delay slot
198         swap    [%o0], %o1
199         cmp     %o1, -4096
200         be      1b
201         dec     %o1                 ! delay slot, if we got spinlock, decrement count
202         st      %o1, [%o0]          ! delay slot
203         retl
204         mov     %o1, %o0            ! delay slot
205 
206  .type  osl_decrementInterlockedCountV8,#function
207  .size  osl_decrementInterlockedCountV8,.-osl_decrementInterlockedCountV8
208 
209 #endif /* !__sparcv8plus && !__sparcv9 && !_sparcv9__ */
210 
211 .section   ".text"
212 #if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
213 #define   osl_incrementInterlockedCountV9 osl_incrementInterlockedCount
214  .global  osl_incrementInterlockedCountV9
215 #else
216  .local   osl_incrementInterlockedCountV9
217 #endif
218  .align   8
219 
220 !   Implements osl_[increment|decrement]InterlockedCount with sparcv9(sparcv8plus) "cas"
221 !   instruction.
222 
223 osl_incrementInterlockedCountV9:
224 
225 1:      ld      [%o0], %o1
226         add     %o1, 1, %o2
227 !       allow linux to build for v8
228         .word 0xD5E21009
229 !       cas     [%o0], %o1, %o2
230         cmp     %o1, %o2
231         bne     1b
232         nop                         ! delay slot
233         retl
234         add     %o2, 1, %o0         ! delay slot
235 
236  .type  osl_incrementInterlockedCountV9,#function
237  .size  osl_incrementInterlockedCountV9,.-osl_incrementInterlockedCountV9
238 
239 
240 .section   ".text"
241 #if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
242 #define   osl_decrementInterlockedCountV9 osl_decrementInterlockedCount
243  .global  osl_decrementInterlockedCountV9
244 #else
245  .local   osl_decrementInterlockedCountV9
246 #endif
247  .align   8
248 
249 osl_decrementInterlockedCountV9:
250 
251 1:      ld      [%o0], %o1
252         sub     %o1, 1, %o2
253 !       allow linux to build for v8
254         .word 0xD5E21009
255 !       cas     [%o0], %o1, %o2
256         cmp     %o1, %o2
257         bne     1b
258         nop                         ! delay slot
259         retl
260         sub     %o2, 1, %o0         ! delay slot
261 
262  .type  osl_decrementInterlockedCountV9,#function
263  .size  osl_decrementInterlockedCountV9,.-osl_decrementInterlockedCountV9
264