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 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