xref: /AOO41X/main/sal/osl/unx/asm/interlck_sparc.s (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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 possibilty) 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
51osl_incrementInterLockCountFuncPtr:
52.word osl_incrementInterlockedCountV8
53.type osl_incrementInterLockCountFuncPtr,#object
54.size osl_incrementInterLockCountFuncPtr,4
55
56.align 4
57osl_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
76osl_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
99osl_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
122osl_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]
1471:      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
170osl_incrementInterlockedCountV8:
171
1721:      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
192osl_decrementInterlockedCountV8:
193
1941:      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
223osl_incrementInterlockedCountV9:
224
2251:      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
249osl_decrementInterlockedCountV9:
250
2511:      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