2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
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 OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 #warning Building of SPARC dynashlib not fully supported yet!
29 #define OBJC_LOCK_ROUTINE _simple_lock
31 #define OBJC_LOCK_ROUTINE _spin_lock
34 #define CLEARLOW22 0xffc00000 /* mask to clear off low 22 bits */
46 ! optimized for sparc: 26 clocks (best case) + 7 clocks/probe
52 ! Arguments: %i0 - receiver (self)
57 save %sp,-96,%sp ! save register windows
59 ! test for nil argument and locking requirements
60 sethi %hi(__objc_multithread_mask),%l1
61 ld [%l1+%lo(__objc_multithread_mask)],%l1
62 andcc %l1,%i0,%l1 ! if (self & multi)
63 bnz,a L_normalCase ! then normalcase
64 ld [%i0+isa],%o0 ! class = self->isa (class arg)
67 bnz L_sendLocking ! lockingcase
70 ld [%i7+8],%g3 // load instruction
71 sethi %hi(CLEARLOW22),%g2 // mask off low 22 bits
72 andcc %g3,%g2,%g0 // if 0, then its an UNIMP inst
73 bz L_struct_returnSend0 // and we will return a structure
78 jmp %i7 + 12 // convention for returning structs
81 ! Init pointers to class and cache
83 ld [%o0+cache],%l4 ! cache <- class->cache
84 ld [%l4+mask],%l3 ! mask <- cache->mask
85 add %l4,buckets,%l2 ! buckets <- cache->buckets
86 and %i1,%l3,%l1 ! index <- selector & mask
88 ! Try to find a method in the cache
90 sll %l1,2,%l6 ! adjust to word index
91 ld [%l2+%l6],%l4 ! method = buckets[index]
92 tst %l4 ! if (method == NULL)
93 bz,a L_cacheMiss ! handle cacheMiss case
94 mov %i1,%o1 ! (DS) selector arg for LoadCache
96 ld [%l4+method_name],%l5! name = method->method_name
97 cmp %l5,%i1 ! if (name == selector)
98 be,a L_cacheHit ! goto hit
99 ld [%l4+method_imp],%o0! load method_imp pointer to call
102 b L_loop ! check next cache entry
103 and %l1,%l3,%l1 ! index = index & mask
105 CALL_EXTERN(__class_lookupMethodAndLoadCache)
110 ! Locking version of objc_msgSend
111 ! spins on the mutex lock.
114 set (_messageLock),%l7! get the lock addr
115 set 1,%l1 ! lock code (1)
117 swap [%l7],%l1 ! try to set the lock
118 tst %l1 ! if lock was already set
119 bnz L_lockspin ! try again
120 set 1,%l1 ! lock code (1)
122 ! got the lock, ready to proceed
124 ld [%i0+isa],%o0 ! class = self->isa
125 ld [%o0+cache],%l4 ! cache = class->cache
126 ld [%l4+mask],%l3 ! mask = cache->mask
127 add %l4,buckets,%l2 ! buckets = cache->buckets
128 and %i1,%l3,%l1 ! index = selector & mask
131 sll %l1,2,%l6 ! adjust to word index
132 ld [%l2+%l6],%l4 ! method = buckets[index]
133 tst %l4 ! if (method == NULL)
134 bz,a L_cacheMiss_lk ! handle cacheMiss case
135 mov %i1,%o1 ! (DS) selector arg for LoadCache
137 ld [%l4+method_name],%l5! name = method->method_name
138 cmp %l5,%i1 ! if (name == selector)
139 be,a L_cacheHit_lk ! goto hit
140 ld [%l4+method_imp],%o0 ! impl = method->method_imp
143 b L_loop_lk ! check next cache entry
144 and %l1,%l3,%l1 ! index = index & mask
147 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
149 swap [%l7],%g0 ! clear the lock
154 .globl _objc_msgSendSuper
156 save %sp,-120,%sp ! save register window
157 ld [%i0+receiver],%l0 ! receiver = caller->receiver
158 tst %l0 ! if (receiver)
159 bnz L_receiver ! work on it
160 st %l0,[%fp+68] ! <delay slot> save a copy
161 L_noreceiver: ! return on NULL receiver
162 ld [%i7+8],%g3 // load instruction
163 sethi %hi(CLEARLOW22),%g2 // mask off low 22 bits
164 andcc %g3,%g2,%g0 // if 0, then its an UNIMP inst
165 bz L_struct_returnSend1 // and we will return a structure
167 ret // Get back, JoJo
169 L_struct_returnSend1:
170 jmp %i7 + 12 // convention for returning structs
174 sethi %hi(__objc_multithread_mask),%l1
175 ld [%l1+%lo(__objc_multithread_mask)],%l1
178 ld [%i0+class],%o0 ! class = caller->class
179 ld [%o0+cache],%l4 ! cache = class->cache
180 ld [%l4+mask],%l3 ! mask = cache->mask
181 add %l4,buckets,%l2 ! buckets = cache->buckets
182 and %i1,%l3,%l1 ! index = selector & mask
185 sll %l1,2,%l6 ! adjust to word index
186 ld [%l2+%l6],%l4 ! method = buckets[index]
187 tst %l4 ! if (method == NULL)
188 bz,a L_super_cacheMiss ! handle cacheMiss case
189 mov %i1,%o1 ! (DS) selector arg for LoadCache
191 ld [%l4+method_name],%l5! name = method->method_name
192 cmp %l5,%i1 ! if (name == selector)
193 be L_super_cacheHit ! goto hit
194 ld [%l4+method_imp],%g1 ! method = buckets[index]
197 b L_super_loop ! check next cache entry
198 and %l1,%l3,%l1 ! index = index & mask
201 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
202 mov %o0,%g1 ! save result from Loadcache
205 ld [%sp+68],%o0 ! restore receiver
211 ld [%sp+68],%o0 ! restore receiver
214 ! locking version of objc_msgSendSuper
215 ! spins on the mutex lock
218 sethi %hi(_messageLock),%l1! aquire the lock addr
219 or %l1,%lo(_messageLock),%l7
221 ldstub [%l7],%l1 ! try to set the lock
222 tst %l1 ! if lock was already set
223 bne L_super_lockspin ! try again
226 ! got the lock, ready to proceed
227 ! %o0 = class [set above]
228 ld [%o0+cache],%l4 ! cache = class->cache
229 ld [%l4+mask],%l3 ! mask = cache->mask
230 add %l4,buckets,%l2 ! buckets = cache->buckets
231 and %i1,%l3,%l1 ! index = selector & mask
234 sll %l1,2,%l6 ! adjust to word index
235 ld [%l2+%l6],%l4 ! method = buckets[index]
236 tst %l4 ! if (method == NULL)
237 bz,a L_super_cacheMiss_lk ! handle cacheMiss case
238 mov %i1,%o1 ! (DS) selector arg for LoadCache
240 ld [%l4+method_name],%l5! name = method->method_name
241 cmp %l5,%i1 ! if (name == selector)
242 be L_super_cacheHit_lk ! goto hit
243 ld [%l4+method_imp],%g1 ! impl = method->method_imp
246 b L_super_loop_lk ! check next cache entry
247 and %l1,%l3,%l1 ! index = index & mask
249 L_super_cacheMiss_lk:
250 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
251 mov %o0,%g1 ! save result from Loadcache
252 st %g0,[%l7] ! clear lock
255 ld [%sp+68],%o0 ! restore receiver
258 st %g0,[%l7] ! clear the lock
261 ld [%sp+68],%o0 ! restore receiver
266 L30: .ascii "forward::\0"
274 L32: .ascii "Does not recognize selector %s\0"
279 .globl __objc_msgForward
283 ld [%g2+%lo(L31)],%g2
284 cmp %i1,%g2 ! if (selector == @selector(forward::))
287 add %fp,68,%g1 ! ptr to stack area
297 ld [%i7+8],%g3 ! load instruction
298 sethi %hi(CLEARLOW22),%g2 ! mask off low 22 bits
299 andcc %g3,%g2,%g0 ! if 0, then its an UNIMP inst
300 be Lstruct_returnForward ! and we will return a structure
301 nop ! fill me in later
303 ! No structure is returned
304 call _objc_msgSend ! send the message
305 mov %i0,%o0 ! <ds> Set self
306 mov %o0,%i0 ! Restore return parameter
308 restore %o1,0,%o1 !In case long long returned
310 Lstruct_returnForward:
311 ld [%fp+64],%g2 ! get return struct ptr
312 st %g2,[%sp+64] ! save return struct pointer
313 call _objc_msgSend ! send the message
314 mov %i0,%o0 ! Set self
315 unimp 0 ! let 0 mean size = unknown
316 jmp %i7 + 12 ! convention for returning structs
322 BRANCH_EXTERN(__objc_error) ! never returns
325 ! id objc_msgSendv(id self, SEL sel, unsigned size, marg_list args)
327 .globl _objc_msgSendv
329 add %g0,-96,%g1 ! Get min stack size + 4 (rounded by 8)
330 subcc %o2,28,%g2 ! Get size of non reg params + 4
331 ble Lsave_stack ! None or 1, so skip making stack larger
332 sub %g1,%g2,%g2 ! Add local size to minimum stack
333 and %g2,-8,%g1 ! Need to round to 8 bit boundary
335 save %sp,%g1,%sp ! Save min stack + 4 for 8 byte bound! ...
338 addcc %i2,-8,%i2 ! adjust for first 2 args (self & sel)
342 ld [%i3+8],%o2 ! get 3rd arg
343 addcc %i2,-4,%i2 ! size--
347 ld [%i3+12],%o3 ! arg 4
348 addcc %i2,-4,%i2 ! size--
352 ld [%i3+16],%o4 ! arg 5
353 addcc %i2,-4,%i2 ! size--
357 ld [%i3+20],%o5 ! arg 6
358 addcc %i2,-4,%i2 ! size--
361 add %i3,24,%i1 ! %i1 = args + 24
363 L_loopv: ! deal with remaining args
365 addcc %i2,-4,%i2 ! size--
369 add %i1,4,%i1 ! arg++
372 ld [%i7+8],%g3 ! load instruction
373 sethi %hi(CLEARLOW22),%g2
374 andcc %g3,%g2,%g0 ! if 0 it is an UNIMP inst
375 be L_struct_returnSendv! return a structure
378 ! Case of no struct returned
382 mov %o0,%i0 ! Ret int, 1st half
383 ret ! ... of long long
384 restore %o1,0,%o1 ! 2nd half of ll
386 L_struct_returnSendv: