2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
25 #define __APPLE_API_PRIVATE
26 #include <machine/cpu_capabilities.h>
27 #undef __APPLE_API_PRIVATE
29 #include <architecture/ppc/mode_independent_asm.h>
32 /* These are the functions in <libkern/OSAtomic.h>.
33 * The actual primitives are implemented on the commpage.
37 /* int32_t OSAtomicAdd32( int32_t theAmount, int32_t *theValue ); */
39 MI_ENTRY_POINT(_OSAtomicAdd32)
40 ba _COMM_PAGE_ATOMIC_ADD32
43 /* int32_t OSAtomicOr32( int32_t theMask, int32_t *theValue ); */
45 MI_ENTRY_POINT(_OSAtomicOr32)
46 mflr r12 // save return address
47 mr r5,r4 // move ptr to where compare-and-swap wants it
48 mr r11,r3 // copy mask
50 lwz r3,0(r5) // get old value
51 or r4,r3,r11 // make new value
52 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
53 cmpwi r3,0 // did swap occur?
54 beq-- 1b // compare-and-swap failed, try again
55 mtlr r12 // restore return adddress
56 mr r3,r4 // return new value
60 /* int32_t OSAtomicAnd32( int32_t theMask, int32_t *theValue ); */
62 MI_ENTRY_POINT(_OSAtomicAnd32)
63 mflr r12 // save return address
64 mr r5,r4 // move ptr to where compare-and-swap wants it
65 mr r11,r3 // copy mask
67 lwz r3,0(r5) // get old value
68 and r4,r3,r11 // make new value
69 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
70 cmpwi r3,0 // did swap occur?
71 beq-- 1b // compare-and-swap failed, try again
72 mtlr r12 // restore return adddress
73 mr r3,r4 // return new value
77 /* int32_t OSAtomicXor32( int32_t theMask, int32_t *theValue ); */
79 MI_ENTRY_POINT(_OSAtomicXor32)
80 mflr r12 // save return address
81 mr r5,r4 // move ptr to where compare-and-swap wants it
82 mr r11,r3 // copy mask
84 lwz r3,0(r5) // get old value
85 xor r4,r3,r11 // make new value
86 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
87 cmpwi r3,0 // did swap occur?
88 beq-- 1b // compare-and-swap failed, try again
89 mtlr r12 // restore return adddress
90 mr r3,r4 // return new value
94 /* int32_t OSAtomicOr32Orig( int32_t theMask, int32_t *theValue ); */
96 MI_ENTRY_POINT(_OSAtomicOr32Orig)
97 mflr r12 // save return address
98 mr r5,r4 // move ptr to where compare-and-swap wants it
99 mr r11,r3 // copy mask
101 lwz r3,0(r5) // get old value
102 mr r10,r3 // save old value
103 or r4,r3,r11 // make new value
104 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
105 cmpwi r3,0 // did swap occur?
106 beq-- 1b // compare-and-swap failed, try again
107 mtlr r12 // restore return adddress
108 mr r3,r10 // return old value
112 /* int32_t OSAtomicAnd32Orig( int32_t theMask, int32_t *theValue ); */
114 MI_ENTRY_POINT(_OSAtomicAnd32Orig)
115 mflr r12 // save return address
116 mr r5,r4 // move ptr to where compare-and-swap wants it
117 mr r11,r3 // copy mask
119 lwz r3,0(r5) // get old value
120 mr r10,r3 // save old value
121 and r4,r3,r11 // make new value
122 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
123 cmpwi r3,0 // did swap occur?
124 beq-- 1b // compare-and-swap failed, try again
125 mtlr r12 // restore return adddress
126 mr r3,r10 // return old value
130 /* int32_t OSAtomicXor32Orig( int32_t theMask, int32_t *theValue ); */
132 MI_ENTRY_POINT(_OSAtomicXor32Orig)
133 mflr r12 // save return address
134 mr r5,r4 // move ptr to where compare-and-swap wants it
135 mr r11,r3 // copy mask
137 lwz r3,0(r5) // get old value
138 mr r10,r3 // save old value
139 xor r4,r3,r11 // make new value
140 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
141 cmpwi r3,0 // did swap occur?
142 beq-- 1b // compare-and-swap failed, try again
143 mtlr r12 // restore return adddress
144 mr r3,r10 // return old value
148 /* int64_t OSAtomicAdd64( int64_t theAmount, int64_t *theValue ); */
150 #if defined(__ppc64__)
151 MI_ENTRY_POINT(_OSAtomicAdd64)
152 ba _COMM_PAGE_ATOMIC_ADD64
153 #endif /* defined(__ppc64__) */
156 /* bool OSAtomicCompareAndSwap32( int32_t oldValue, int32_t newValue, int32_t *theValue ); */
157 /* bool OSAtomicCompareAndSwap64( int64_t oldValue, int64_t newValue, int64_t *theValue ); */
158 /* bool OSAtomicCompareAndSwapPtr( void* oldValue, void* newValue, void* *theValue ); */
159 /* bool OSAtomicCompareAndSwapInt( int oldValue, int newValue, int *theValue ); */
160 /* bool OSAtomicCompareAndSwapLong( long oldValue, long newValue, long *theValue ); */
162 MI_ENTRY_POINT(_OSAtomicCompareAndSwap32)
163 ba _COMM_PAGE_COMPARE_AND_SWAP32
164 MI_ENTRY_POINT(_OSAtomicCompareAndSwapInt)
165 ba _COMM_PAGE_COMPARE_AND_SWAP32
167 #if defined(__ppc64__)
168 MI_ENTRY_POINT(_OSAtomicCompareAndSwap64)
169 ba _COMM_PAGE_COMPARE_AND_SWAP64
170 MI_ENTRY_POINT(_OSAtomicCompareAndSwapPtr)
171 ba _COMM_PAGE_COMPARE_AND_SWAP64
172 MI_ENTRY_POINT(_OSAtomicCompareAndSwapLong)
173 ba _COMM_PAGE_COMPARE_AND_SWAP64
174 #else /* !defined(__ppc64__) */
175 MI_ENTRY_POINT(_OSAtomicCompareAndSwapPtr)
176 ba _COMM_PAGE_COMPARE_AND_SWAP32
177 MI_ENTRY_POINT(_OSAtomicCompareAndSwapLong)
178 ba _COMM_PAGE_COMPARE_AND_SWAP32
179 #endif /* defined(__ppc64__) */
182 /* bool OSAtomicTestAndSet( uint32_t n, void *theAddress ); */
184 MI_ENTRY_POINT(_OSAtomicTestAndSet)
185 mflr r12 // save return
186 srwi r5,r3,3 // get byte offset of n
187 rlwinm r6,r3,0,0x7 // get bit position within byte
188 add r4,r4,r5 // r4 points to byte containing the bit
189 lis r10,0x8000 // light bit 0
190 rlwimi r6,r4,3,0x18 // r6 is bit position within word
191 clrrgi r5,r4,2 // point to word containing the bit
192 srw r10,r10,r6 // get mask for bit
193 addi r9,r6,1 // save bit position + 1
195 lwz r3,0(r5) // get old word
196 rlwnm r11,r3,r9,0x1 // right justify old value of bit
197 or r4,r3,r10 // set it in new word
198 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
199 cmpwi r3,0 // did swap occur?
200 beq-- 1b // compare-and-swap failed, try again
201 mtlr r12 // restore return adddress
202 mr r3,r11 // return original value of bit
206 /* bool OSAtomicTestAndClear( uint32_t n, void *theAddress ); */
208 MI_ENTRY_POINT(_OSAtomicTestAndClear)
209 mflr r12 // save return
210 srwi r5,r3,3 // get byte offset of n
211 rlwinm r6,r3,0,0x7 // get bit position within byte
212 add r4,r4,r5 // r4 points to byte containing the bit
213 lis r10,0x8000 // light bit 0
214 rlwimi r6,r4,3,0x18 // r6 is bit position within word
215 clrrgi r5,r4,2 // point to word containing the bit
216 srw r10,r10,r6 // get mask for bit
217 addi r9,r6,1 // save bit position + 1
219 lwz r3,0(r5) // get old word
220 rlwnm r11,r3,r9,0x1 // right justify old value of bit
221 andc r4,r3,r10 // clear it in new word
222 bla _COMM_PAGE_COMPARE_AND_SWAP32 // preserves r4,r5,r9-r12
223 cmpwi r3,0 // did swap occur?
224 beq-- 1b // compare-and-swap failed, try again
225 mtlr r12 // restore return adddress
226 mr r3,r11 // return original value of bit
230 /* int32_t OSAtomicAdd32Barrier( int32_t theAmount, int32_t *theValue ); */
232 MI_ENTRY_POINT(_OSAtomicAdd32Barrier)
233 mflr r12 // save return address
234 mr r5,r4 // move ptr to where compare-and-swap wants it
235 mr r11,r3 // copy theAmount
237 lwz r3,0(r5) // get old value
238 add r4,r3,r11 // make new value
239 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
240 cmpwi r3,0 // did swap occur?
241 beq-- 1b // compare-and-swap failed, try again
242 mtlr r12 // restore return adddress
243 mr r3,r4 // return new value
247 /* int32_t OSAtomicOr32Barrier( int32_t theMask, int32_t *theValue ); */
249 MI_ENTRY_POINT(_OSAtomicOr32Barrier)
250 mflr r12 // save return address
251 mr r5,r4 // move ptr to where compare-and-swap wants it
252 mr r11,r3 // copy mask
254 lwz r3,0(r5) // get old value
255 or r4,r3,r11 // make new value
256 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
257 cmpwi r3,0 // did swap occur?
258 beq-- 1b // compare-and-swap failed, try again
259 mtlr r12 // restore return adddress
260 mr r3,r4 // return new value
264 /* int32_t OSAtomicAnd32Barrier( int32_t theMask, int32_t *theValue ); */
266 MI_ENTRY_POINT(_OSAtomicAnd32Barrier)
267 mflr r12 // save return address
268 mr r5,r4 // move ptr to where compare-and-swap wants it
269 mr r11,r3 // copy mask
271 lwz r3,0(r5) // get old value
272 and r4,r3,r11 // make new value
273 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
274 cmpwi r3,0 // did swap occur?
275 beq-- 1b // compare-and-swap failed, try again
276 mtlr r12 // restore return adddress
277 mr r3,r4 // return new value
281 /* int32_t OSAtomicXor32Barrier( int32_t theMask, int32_t *theValue ); */
283 MI_ENTRY_POINT(_OSAtomicXor32Barrier)
284 mflr r12 // save return address
285 mr r5,r4 // move ptr to where compare-and-swap wants it
286 mr r11,r3 // copy mask
288 lwz r3,0(r5) // get old value
289 xor r4,r3,r11 // make new value
290 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
291 cmpwi r3,0 // did swap occur?
292 beq-- 1b // compare-and-swap failed, try again
293 mtlr r12 // restore return adddress
294 mr r3,r4 // return new value
298 /* int32_t OSAtomicOr32OrigBarrier( int32_t theMask, int32_t *theValue ); */
300 MI_ENTRY_POINT(_OSAtomicOr32OrigBarrier)
301 mflr r12 // save return address
302 mr r5,r4 // move ptr to where compare-and-swap wants it
303 mr r11,r3 // copy mask
305 lwz r3,0(r5) // get old value
306 mr r10,r3 // save old value
307 or r4,r3,r11 // make new value
308 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
309 cmpwi r3,0 // did swap occur?
310 beq-- 1b // compare-and-swap failed, try again
311 mtlr r12 // restore return adddress
312 mr r3,r10 // return old value
316 /* int32_t OSAtomicAnd32OrigBarrier( int32_t theMask, int32_t *theValue ); */
318 MI_ENTRY_POINT(_OSAtomicAnd32OrigBarrier)
319 mflr r12 // save return address
320 mr r5,r4 // move ptr to where compare-and-swap wants it
321 mr r11,r3 // copy mask
323 lwz r3,0(r5) // get old value
324 mr r10,r3 // save old value
325 and r4,r3,r11 // make new value
326 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
327 cmpwi r3,0 // did swap occur?
328 beq-- 1b // compare-and-swap failed, try again
329 mtlr r12 // restore return adddress
330 mr r3,r10 // return old value
334 /* int32_t OSAtomicXor32OrigBarrier( int32_t theMask, int32_t *theValue ); */
336 MI_ENTRY_POINT(_OSAtomicXor32OrigBarrier)
337 mflr r12 // save return address
338 mr r5,r4 // move ptr to where compare-and-swap wants it
339 mr r11,r3 // copy mask
341 lwz r3,0(r5) // get old value
342 mr r10,r3 // save old value
343 xor r4,r3,r11 // make new value
344 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
345 cmpwi r3,0 // did swap occur?
346 beq-- 1b // compare-and-swap failed, try again
347 mtlr r12 // restore return adddress
348 mr r3,r10 // return old value
352 /* int64_t OSAtomicAdd64Barrier( int64_t theAmount, int64_t *theValue ); */
354 #if defined(__ppc64__)
355 MI_ENTRY_POINT(_OSAtomicAdd64Barrier)
356 mflr r12 // save return address
357 mr r5,r4 // move ptr to where compare-and-swap wants it
358 mr r11,r3 // copy theAmount
360 ld r3,0(r5) // get old value
361 add r4,r3,r11 // make new value
362 bla _COMM_PAGE_COMPARE_AND_SWAP64B // preserves r4,r5,r9-r12
363 cmpwi r3,0 // did swap occur?
364 beq-- 1b // compare-and-swap failed, try again
365 mtlr r12 // restore return adddress
366 mr r3,r4 // return new value
368 #endif /* defined(__ppc64__) */
371 /* bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue, int32_t newValue, int32_t *theValue ); */
372 /* bool OSAtomicCompareAndSwap64Barrier( int64_t oldValue, int64_t newValue, int64_t *theValue ); */
373 /* bool OSAtomicCompareAndSwapPtrBarrier( void* oldValue, void* newValue, void* *theValue ); */
374 /* bool OSAtomicCompareAndSwapIntBarrier( int oldValue, int newValue, int *theValue ); */
375 /* bool OSAtomicCompareAndSwapLongBarrier( long oldValue, long newValue, long *theValue ); */
377 MI_ENTRY_POINT(_OSAtomicCompareAndSwap32Barrier)
378 ba _COMM_PAGE_COMPARE_AND_SWAP32B
379 MI_ENTRY_POINT(_OSAtomicCompareAndSwapIntBarrier)
380 ba _COMM_PAGE_COMPARE_AND_SWAP32B
382 #if defined(__ppc64__)
383 MI_ENTRY_POINT(_OSAtomicCompareAndSwap64Barrier)
384 ba _COMM_PAGE_COMPARE_AND_SWAP64B
385 MI_ENTRY_POINT(_OSAtomicCompareAndSwapPtrBarrier)
386 ba _COMM_PAGE_COMPARE_AND_SWAP64B
387 MI_ENTRY_POINT(_OSAtomicCompareAndSwapLongBarrier)
388 ba _COMM_PAGE_COMPARE_AND_SWAP64B
389 #else /* !defined(__ppc64__) */
390 MI_ENTRY_POINT(_OSAtomicCompareAndSwapPtrBarrier)
391 ba _COMM_PAGE_COMPARE_AND_SWAP32B
392 MI_ENTRY_POINT(_OSAtomicCompareAndSwapLongBarrier)
393 ba _COMM_PAGE_COMPARE_AND_SWAP32B
394 #endif /* defined(__ppc64__) */
397 /* bool OSAtomicTestAndSetBarrier( uint32_t n, void *theAddress ); */
399 MI_ENTRY_POINT(_OSAtomicTestAndSetBarrier)
400 mflr r12 // save return
401 srwi r5,r3,3 // get byte offset of n
402 rlwinm r6,r3,0,0x7 // get bit position within byte
403 add r4,r4,r5 // r4 points to byte containing the bit
404 lis r10,0x8000 // light bit 0
405 rlwimi r6,r4,3,0x18 // r6 is bit position within word
406 clrrgi r5,r4,2 // point to word containing the bit
407 srw r10,r10,r6 // get mask for bit
408 addi r9,r6,1 // save bit position + 1
410 lwz r3,0(r5) // get old word
411 rlwnm r11,r3,r9,0x1 // right justify old value of bit
412 or r4,r3,r10 // set it in new word
413 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
414 cmpwi r3,0 // did swap occur?
415 beq-- 1b // compare-and-swap failed, try again
416 mtlr r12 // restore return adddress
417 mr r3,r11 // return original value of bit
421 /* bool OSAtomicTestAndClearBarrier( uint32_t n, void *theAddress ); */
423 MI_ENTRY_POINT(_OSAtomicTestAndClearBarrier)
424 mflr r12 // save return
425 srwi r5,r3,3 // get byte offset of n
426 rlwinm r6,r3,0,0x7 // get bit position within byte
427 add r4,r4,r5 // r4 points to byte containing the bit
428 lis r10,0x8000 // light bit 0
429 rlwimi r6,r4,3,0x18 // r6 is bit position within word
430 clrrgi r5,r4,2 // point to word containing the bit
431 srw r10,r10,r6 // get mask for bit
432 addi r9,r6,1 // save bit position + 1
434 lwz r3,0(r5) // get old word
435 rlwnm r11,r3,r9,0x1 // right justify old value of bit
436 andc r4,r3,r10 // clear it in new word
437 bla _COMM_PAGE_COMPARE_AND_SWAP32B // preserves r4,r5,r9-r12
438 cmpwi r3,0 // did swap occur?
439 beq-- 1b // compare-and-swap failed, try again
440 mtlr r12 // restore return adddress
441 mr r3,r11 // return original value of bit
444 /* bool OSSpinLockTry( OSSpinLock *lock ); */
446 MI_ENTRY_POINT(_OSSpinLockTry)
447 .globl __spin_lock_try
449 ba _COMM_PAGE_SPINLOCK_TRY
452 /* void OSSpinLockLock( OSSpinLock *lock ); */
454 MI_ENTRY_POINT(_OSSpinLockLock)
459 ba _COMM_PAGE_SPINLOCK_LOCK
462 /* void OSSpinLockUnlock( OSSpinLock *lock ); */
464 MI_ENTRY_POINT(_OSSpinLockUnlock)
469 ba _COMM_PAGE_SPINLOCK_UNLOCK
472 /* void OSMemoryBarrier( void ); */
474 MI_ENTRY_POINT(_OSMemoryBarrier)
475 ba _COMM_PAGE_MEMORY_BARRIER
478 /* void OSAtomicEnqueue( OSQueueHead *list, void *new, size_t offset); */
480 MI_ENTRY_POINT(_OSAtomicEnqueue)
481 ba _COMM_PAGE_ENQUEUE
484 /* void* OSAtomicDequeue( OSQueueHead *list, size_t offset); */
486 MI_ENTRY_POINT(_OSAtomicDequeue)
487 ba _COMM_PAGE_DEQUEUE