2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #define __APPLE_API_PRIVATE
25 #include <machine/cpu_capabilities.h>
26 #undef __APPLE_API_PRIVATE
28 #include <architecture/ppc/mode_independent_asm.h>
31 /* These are the functions in <libkern/OSAtomic.h>.
32 * The actual primitives are implemented on the commpage.
36 /* int32_t OSAtomicAdd32( int32_t theAmount, int32_t *theValue ); */
38 MI_ENTRY_POINT(_OSAtomicAdd32)
39 ba _COMM_PAGE_ATOMIC_ADD32
42 /* int32_t OSAtomicOr32( int32_t theMask, int32_t *theValue ); */
44 MI_ENTRY_POINT(_OSAtomicOr32)
45 mflr r12 // save return address
46 mr r5,r4 // move ptr to where compare-and-swap wants it
47 mr r11,r3 // copy mask
49 lwz r3,0(r5) // get old value
50 or r4,r3,r11 // make new value
51 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
52 cmpwi r3,0 // did swap occur?
53 beq-- 1b // compare-and-swap failed, try again
54 mtlr r12 // restore return adddress
55 mr r3,r4 // return new value
59 /* int32_t OSAtomicAnd32( int32_t theMask, int32_t *theValue ); */
61 MI_ENTRY_POINT(_OSAtomicAnd32)
62 mflr r12 // save return address
63 mr r5,r4 // move ptr to where compare-and-swap wants it
64 mr r11,r3 // copy mask
66 lwz r3,0(r5) // get old value
67 and r4,r3,r11 // make new value
68 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
69 cmpwi r3,0 // did swap occur?
70 beq-- 1b // compare-and-swap failed, try again
71 mtlr r12 // restore return adddress
72 mr r3,r4 // return new value
76 /* int32_t OSAtomicXor32( int32_t theMask, int32_t *theValue ); */
78 MI_ENTRY_POINT(_OSAtomicXor32)
79 mflr r12 // save return address
80 mr r5,r4 // move ptr to where compare-and-swap wants it
81 mr r11,r3 // copy mask
83 lwz r3,0(r5) // get old value
84 xor r4,r3,r11 // make new value
85 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
86 cmpwi r3,0 // did swap occur?
87 beq-- 1b // compare-and-swap failed, try again
88 mtlr r12 // restore return adddress
89 mr r3,r4 // return new value
93 /* int64_t OSAtomicAdd64( int64_t theAmount, int64_t *theValue ); */
95 #if defined(__ppc64__)
96 MI_ENTRY_POINT(_OSAtomicAdd64)
97 ba _COMM_PAGE_ATOMIC_ADD64
98 #endif /* defined(__ppc64__) */
101 /* bool OSAtomicCompareAndSwap32( int32_t oldValue, int32_t newValue, int32_t *theValue ); */
103 MI_ENTRY_POINT(_OSAtomicCompareAndSwap32)
104 ba _COMM_PAGE_COMPARE_AND_SWAP32
107 /* bool OSAtomicCompareAndSwap64( int364_t oldValue, int64_t newValue, int64_t *theValue ); */
109 #if defined(__ppc64__)
110 MI_ENTRY_POINT(_OSAtomicCompareAndSwap64)
111 ba _COMM_PAGE_COMPARE_AND_SWAP64
112 #endif /* defined(__ppc64__) */
115 /* bool OSAtomicTestAndSet( uint32_t n, void *theAddress ); */
117 MI_ENTRY_POINT(_OSAtomicTestAndSet)
118 mflr r12 // save return
119 srwi r5,r3,3 // get byte offset of n
120 rlwinm r6,r3,0,0x7 // get bit position within byte
121 add r4,r4,r5 // r4 points to byte containing the bit
122 lis r10,0x8000 // light bit 0
123 rlwimi r6,r4,3,0x18 // r6 is bit position within word
124 clrrgi r5,r4,2 // point to word containing the bit
125 srw r10,r10,r6 // get mask for bit
126 addi r9,r6,1 // save bit position + 1
128 lwz r3,0(r5) // get old word
129 rlwnm r11,r3,r9,0x1 // right justify old value of bit
130 or r4,r3,r10 // set it in new word
131 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
132 cmpwi r3,0 // did swap occur?
133 beq-- 1b // compare-and-swap failed, try again
134 mtlr r12 // restore return adddress
135 mr r3,r11 // return original value of bit
139 /* bool OSAtomicTestAndClear( uint32_t n, void *theAddress ); */
141 MI_ENTRY_POINT(_OSAtomicTestAndClear)
142 mflr r12 // save return
143 srwi r5,r3,3 // get byte offset of n
144 rlwinm r6,r3,0,0x7 // get bit position within byte
145 add r4,r4,r5 // r4 points to byte containing the bit
146 lis r10,0x8000 // light bit 0
147 rlwimi r6,r4,3,0x18 // r6 is bit position within word
148 clrrgi r5,r4,2 // point to word containing the bit
149 srw r10,r10,r6 // get mask for bit
150 addi r9,r6,1 // save bit position + 1
152 lwz r3,0(r5) // get old word
153 rlwnm r11,r3,r9,0x1 // right justify old value of bit
154 andc r4,r3,r10 // clear it in new word
155 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
156 cmpwi r3,0 // did swap occur?
157 beq-- 1b // compare-and-swap failed, try again
158 mtlr r12 // restore return adddress
159 mr r3,r11 // return original value of bit
163 /* int32_t OSAtomicAdd32Barrier( int32_t theAmount, int32_t *theValue ); */
165 MI_ENTRY_POINT(_OSAtomicAdd32Barrier)
166 mflr r12 // save return address
167 mr r5,r4 // move ptr to where compare-and-swap wants it
168 mr r11,r3 // copy theAmount
170 lwz r3,0(r5) // get old value
171 add r4,r3,r11 // make new value
172 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
173 cmpwi r3,0 // did swap occur?
174 beq-- 1b // compare-and-swap failed, try again
175 mtlr r12 // restore return adddress
176 mr r3,r4 // return new value
180 /* int32_t OSAtomicOr32Barrier( int32_t theMask, int32_t *theValue ); */
182 MI_ENTRY_POINT(_OSAtomicOr32Barrier)
183 mflr r12 // save return address
184 mr r5,r4 // move ptr to where compare-and-swap wants it
185 mr r11,r3 // copy mask
187 lwz r3,0(r5) // get old value
188 or r4,r3,r11 // make new value
189 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
190 cmpwi r3,0 // did swap occur?
191 beq-- 1b // compare-and-swap failed, try again
192 mtlr r12 // restore return adddress
193 mr r3,r4 // return new value
197 /* int32_t OSAtomicAnd32Barrier( int32_t theMask, int32_t *theValue ); */
199 MI_ENTRY_POINT(_OSAtomicAnd32Barrier)
200 mflr r12 // save return address
201 mr r5,r4 // move ptr to where compare-and-swap wants it
202 mr r11,r3 // copy mask
204 lwz r3,0(r5) // get old value
205 and r4,r3,r11 // make new value
206 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
207 cmpwi r3,0 // did swap occur?
208 beq-- 1b // compare-and-swap failed, try again
209 mtlr r12 // restore return adddress
210 mr r3,r4 // return new value
214 /* int32_t OSAtomicXor32Barrier( int32_t theMask, int32_t *theValue ); */
216 MI_ENTRY_POINT(_OSAtomicXor32Barrier)
217 mflr r12 // save return address
218 mr r5,r4 // move ptr to where compare-and-swap wants it
219 mr r11,r3 // copy mask
221 lwz r3,0(r5) // get old value
222 xor r4,r3,r11 // make new value
223 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
224 cmpwi r3,0 // did swap occur?
225 beq-- 1b // compare-and-swap failed, try again
226 mtlr r12 // restore return adddress
227 mr r3,r4 // return new value
231 /* int64_t OSAtomicAdd64Barrier( int64_t theAmount, int64_t *theValue ); */
233 #if defined(__ppc64__)
234 MI_ENTRY_POINT(_OSAtomicAdd64Barrier)
235 mflr r12 // save return address
236 mr r5,r4 // move ptr to where compare-and-swap wants it
237 mr r11,r3 // copy theAmount
239 ld r3,0(r5) // get old value
240 add r4,r3,r11 // make new value
241 bla _COMM_PAGE_COMPARE_AND_SWAP64B // preserves r4,r5,r9-r12
242 cmpwi r3,0 // did swap occur?
243 beq-- 1b // compare-and-swap failed, try again
244 mtlr r12 // restore return adddress
245 mr r3,r4 // return new value
247 #endif /* defined(__ppc64__) */
250 /* bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue, int32_t newValue, int32_t *theValue ); */
252 MI_ENTRY_POINT(_OSAtomicCompareAndSwap32Barrier)
253 ba _COMM_PAGE_COMPARE_AND_SWAP32B
256 /* bool OSAtomicCompareAndSwap64Barrier( int364_t oldValue, int64_t newValue, int64_t *theValue ); */
258 #if defined(__ppc64__)
259 MI_ENTRY_POINT(_OSAtomicCompareAndSwap64Barrier)
260 ba _COMM_PAGE_COMPARE_AND_SWAP64B
261 #endif /* defined(__ppc64__) */
264 /* bool OSAtomicTestAndSetBarrier( uint32_t n, void *theAddress ); */
266 MI_ENTRY_POINT(_OSAtomicTestAndSetBarrier)
267 mflr r12 // save return
268 srwi r5,r3,3 // get byte offset of n
269 rlwinm r6,r3,0,0x7 // get bit position within byte
270 add r4,r4,r5 // r4 points to byte containing the bit
271 lis r10,0x8000 // light bit 0
272 rlwimi r6,r4,3,0x18 // r6 is bit position within word
273 clrrgi r5,r4,2 // point to word containing the bit
274 srw r10,r10,r6 // get mask for bit
275 addi r9,r6,1 // save bit position + 1
277 lwz r3,0(r5) // get old word
278 rlwnm r11,r3,r9,0x1 // right justify old value of bit
279 or r4,r3,r10 // set it in new word
280 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
281 cmpwi r3,0 // did swap occur?
282 beq-- 1b // compare-and-swap failed, try again
283 mtlr r12 // restore return adddress
284 mr r3,r11 // return original value of bit
288 /* bool OSAtomicTestAndClearBarrier( uint32_t n, void *theAddress ); */
290 MI_ENTRY_POINT(_OSAtomicTestAndClearBarrier)
291 mflr r12 // save return
292 srwi r5,r3,3 // get byte offset of n
293 rlwinm r6,r3,0,0x7 // get bit position within byte
294 add r4,r4,r5 // r4 points to byte containing the bit
295 lis r10,0x8000 // light bit 0
296 rlwimi r6,r4,3,0x18 // r6 is bit position within word
297 clrrgi r5,r4,2 // point to word containing the bit
298 srw r10,r10,r6 // get mask for bit
299 addi r9,r6,1 // save bit position + 1
301 lwz r3,0(r5) // get old word
302 rlwnm r11,r3,r9,0x1 // right justify old value of bit
303 andc r4,r3,r10 // clear it in new word
304 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
305 cmpwi r3,0 // did swap occur?
306 beq-- 1b // compare-and-swap failed, try again
307 mtlr r12 // restore return adddress
308 mr r3,r11 // return original value of bit
311 /* bool OSSpinLockTry( OSSpinLock *lock ); */
313 MI_ENTRY_POINT(_OSSpinLockTry)
314 ba _COMM_PAGE_SPINLOCK_TRY
317 /* void OSSpinLockLock( OSSpinLock *lock ); */
319 MI_ENTRY_POINT(_OSSpinLockLock)
320 ba _COMM_PAGE_SPINLOCK_LOCK
323 /* void OSSpinLockUnlock( OSSpinLock *lock ); */
325 MI_ENTRY_POINT(_OSSpinLockUnlock)
326 ba _COMM_PAGE_SPINLOCK_UNLOCK
329 /* void OSMemoryBarrier( void ); */
331 MI_ENTRY_POINT(_OSMemoryBarrier)
332 ba _COMM_PAGE_MEMORY_BARRIER