]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-sparc.s
6be70b7b650b3bd6d4f787633d6f5490766820d9
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-sparc.s
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
12 * this file.
13 *
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
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 #ifdef DYLIB
25 #warning Building of SPARC dynashlib not fully supported yet!
26 #endif
27
28 #ifdef KERNEL
29 #define OBJC_LOCK_ROUTINE _simple_lock
30 #else
31 #define OBJC_LOCK_ROUTINE _spin_lock
32 #endif /* KERNEL */
33
34 #define CLEARLOW22 0xffc00000 /* mask to clear off low 22 bits */
35
36
37 #define isa 0
38 #define cache 32
39 #define mask 0
40 #define buckets 8
41 #define method_name 0
42 #define method_imp 8
43 #define receiver 0
44 #define class 4
45
46 ! optimized for sparc: 26 clocks (best case) + 7 clocks/probe
47
48 .text
49 .globl _objc_msgSend
50
51 ! ObjC message send:
52 ! Arguments: %i0 - receiver (self)
53 ! %i1 - selector
54 ! %i2.. - arguments
55
56 _objc_msgSend:
57 save %sp,-96,%sp ! save register windows
58
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)
65
66 tst %i0 ! if (self)
67 bnz L_sendLocking ! lockingcase
68 nop
69 ! self is NIL, return
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
74 nop //
75 ret // Get back, JoJo
76 restore // <ds>
77 L_struct_returnSend0:
78 jmp %i7 + 12 // convention for returning structs
79 restore // <ds>
80
81 ! Init pointers to class and cache
82 L_normalCase:
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
87
88 ! Try to find a method in the cache
89 L_loop:
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
95
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
100
101 inc %l1 ! index++
102 b L_loop ! check next cache entry
103 and %l1,%l3,%l1 ! index = index & mask
104 L_cacheMiss:
105 CALL_EXTERN(__class_lookupMethodAndLoadCache)
106 L_cacheHit:
107 jmp %o0 !
108 restore
109
110 ! Locking version of objc_msgSend
111 ! spins on the mutex lock.
112
113 L_sendLocking:
114 set (_messageLock),%l7! get the lock addr
115 set 1,%l1 ! lock code (1)
116 L_lockspin:
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)
121
122 ! got the lock, ready to proceed
123
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
129
130 L_loop_lk:
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
136
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
141
142 inc %l1 ! index++
143 b L_loop_lk ! check next cache entry
144 and %l1,%l3,%l1 ! index = index & mask
145
146 L_cacheMiss_lk:
147 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
148 L_cacheHit_lk:
149 swap [%l7],%g0 ! clear the lock
150 jmp %o0
151 restore
152
153
154 .globl _objc_msgSendSuper
155 _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
166 nop //
167 ret // Get back, JoJo
168 restore // <ds>
169 L_struct_returnSend1:
170 jmp %i7 + 12 // convention for returning structs
171 restore // <ds>
172
173 L_receiver:
174 sethi %hi(__objc_multithread_mask),%l1
175 ld [%l1+%lo(__objc_multithread_mask)],%l1
176 tst %l1
177 bz L_superLock
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
183
184 L_super_loop:
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
190
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]
195
196 inc %l1 ! index++
197 b L_super_loop ! check next cache entry
198 and %l1,%l3,%l1 ! index = index & mask
199
200 L_super_cacheMiss:
201 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
202 mov %o0,%g1 ! save result from Loadcache
203 restore
204 jmp %g1
205 ld [%sp+68],%o0 ! restore receiver
206
207
208 L_super_cacheHit:
209 restore
210 jmp %g1
211 ld [%sp+68],%o0 ! restore receiver
212
213
214 ! locking version of objc_msgSendSuper
215 ! spins on the mutex lock
216
217 L_superLock:
218 sethi %hi(_messageLock),%l1! aquire the lock addr
219 or %l1,%lo(_messageLock),%l7
220 L_super_lockspin:
221 ldstub [%l7],%l1 ! try to set the lock
222 tst %l1 ! if lock was already set
223 bne L_super_lockspin ! try again
224 nop
225
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
232
233 L_super_loop_lk:
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
239
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
244
245 inc %l1 ! index++
246 b L_super_loop_lk ! check next cache entry
247 and %l1,%l3,%l1 ! index = index & mask
248
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
253 restore
254 jmp %g1
255 ld [%sp+68],%o0 ! restore receiver
256
257 L_super_cacheHit_lk:
258 st %g0,[%l7] ! clear the lock
259 restore
260 jmp %g1
261 ld [%sp+68],%o0 ! restore receiver
262
263
264 .objc_meth_var_names
265 .align 1
266 L30: .ascii "forward::\0"
267
268 .objc_message_refs
269 .align 2
270 L31: .long L30
271
272 .cstring
273 .align 1
274 L32: .ascii "Does not recognize selector %s\0"
275
276 .text
277 .align 2
278
279 .globl __objc_msgForward
280 __objc_msgForward:
281 save %sp,-96,%sp
282 sethi %hi(L31),%g2
283 ld [%g2+%lo(L31)],%g2
284 cmp %i1,%g2 ! if (selector == @selector(forward::))
285 be L_error
286 nop
287 add %fp,68,%g1 ! ptr to stack area
288 st %i0,[%g1]
289 st %i1,[%g1+4]
290 st %i2,[%g1+8]
291 st %i3,[%g1+12]
292 st %i4,[%g1+16]
293 st %i5,[%g1+20]
294 mov %i1,%o2
295 mov %g2,%o1
296 mov %g1,%o3
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
302
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
307 ret ! Return
308 restore %o1,0,%o1 !In case long long returned
309
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
317 restore
318
319 L_error:
320 mov %i1, %o2
321 set L32,%i1
322 BRANCH_EXTERN(__objc_error) ! never returns
323
324
325 ! id objc_msgSendv(id self, SEL sel, unsigned size, marg_list args)
326
327 .globl _objc_msgSendv
328 _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
334 Lsave_stack:
335 save %sp,%g1,%sp ! Save min stack + 4 for 8 byte bound! ...
336 mov %i0,%o0
337 mov %i1,%o1
338 addcc %i2,-8,%i2 ! adjust for first 2 args (self & sel)
339 be L_send_msg
340 nop
341
342 ld [%i3+8],%o2 ! get 3rd arg
343 addcc %i2,-4,%i2 ! size--
344 be L_send_msg
345 nop
346
347 ld [%i3+12],%o3 ! arg 4
348 addcc %i2,-4,%i2 ! size--
349 be L_send_msg
350 nop
351
352 ld [%i3+16],%o4 ! arg 5
353 addcc %i2,-4,%i2 ! size--
354 be L_send_msg
355 nop
356
357 ld [%i3+20],%o5 ! arg 6
358 addcc %i2,-4,%i2 ! size--
359 be L_send_msg
360 nop
361 add %i3,24,%i1 ! %i1 = args + 24
362 add %sp,92,%i5
363 L_loopv: ! deal with remaining args
364 ld [%i1],%i3
365 addcc %i2,-4,%i2 ! size--
366 st %i3,[%i5]
367 add %i5,4,%i5
368 bnz L_loopv
369 add %i1,4,%i1 ! arg++
370
371 L_send_msg:
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
376 nop
377
378 ! Case of no struct returned
379
380 call _objc_msgSend
381 nop
382 mov %o0,%i0 ! Ret int, 1st half
383 ret ! ... of long long
384 restore %o1,0,%o1 ! 2nd half of ll
385
386 L_struct_returnSendv:
387 ld [%fp+64],%g2
388 st %g2,[%sp+64]
389 call _objc_msgSend
390 nop
391 unimp 0
392 jmp %i7+12
393 restore