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