]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-hppa-lock.s
objc4-208.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-hppa-lock.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 KERNEL
25 #define OBJC_LOCK_ROUTINE _simple_lock
26 #else
27 ; _objc_entryPoints and _objc_exitPoints are used by moninitobjc() to setup
28 ; objective-C messages for profiling. The are made private_externs when in
29 ; a shared library.
30 .reference _moninitobjc
31 .const
32 .align 2
33 .globl _objc_entryPoints
34 _objc_entryPoints:
35 .long _objc_msgSend
36 .long _objc_msgSendSuper
37 .long _objc_msgSendv
38 .long 0
39
40 .globl _objc_exitPoints
41 _objc_exitPoints:
42 .long Lexit1
43 .long Lexit2
44 .long Lexit3
45 .long Lexit4
46 .long Lexit5
47 .long Lexit6
48 .long Lexit7
49 .long Lexit8
50 .long 0
51
52 #define OBJC_LOCK_ROUTINE _spin_lock
53 #endif /* KERNEL */
54
55 #define isa 0
56 #define cache 32
57 #define mask 0
58 #define buckets 8
59 #define method_name 0
60 #define method_imp 8
61
62
63 ; optimized for hppa: 20? clocks (best case) + 6 clocks / probe
64
65 .text
66 .align 4
67 .globl _objc_msgSend
68
69 _objc_msgSend:
70 ldil L`__objc_multithread_mask,%r1
71 ldw R`__objc_multithread_mask(%r1),%r19
72 and,= %r19,%r26,%r19
73 b,n L0 ; if (self & multi) goto normalcase
74 comiclr,= 0,%r26,0
75 b,n LSendLocking ; else if (self) goto lockingcase
76 nop
77 bv 0(%r2) ; else return null
78 copy 0,%r28 ; <delay slot> return val = 0
79 L0:
80 ldw isa(0,%r26),%r19 ; class = self->isa;
81 ldw cache(0,%r19),%r20 ; cache = class->cache
82 ldw mask(0,%r20),%r21 ; mask = cache->mask
83 ldo buckets(%r20),%r20 ; buckets = cache->buckets
84 and %r21,%r25,%r22 ; index = selector & mask;
85 L1:
86 ldwx,s %r22(0,%r20),%r19 ; method = cache->buckets[index];
87 comib,=,n 0,%r19,LcacheMiss ; if (method == NULL)
88 ldw method_name(0,%r19),%r1 ;
89 addi 1,%r22,%r22 ; ++index
90 comb,<> %r1, %r25, L1 ; if (name!=sel) continue loop
91 and %r21,%r22,%r22 ; <delay slot> index &=mask
92 ldw method_imp(0,%r19),%r19
93 Lexit1:
94 bv,n 0(%r19) ; goto *imp; (nullify delay)
95
96 #ifdef MONINIT
97 .space 128 ; /* area for moninitobjc to write */
98 #endif
99
100 LcacheMiss:
101 ; We have to save all the register based arguments (including floating
102 ; point) before calling _class_lookupMethodAndLoadCache. This is because
103 ; we do not know what arguments were passed to us, and the arguments are
104 ; not guaranteed to be saved across procedure calls (they are all caller-saved)
105 ; We also have to save the return address (since we did not save it on entry).
106
107
108 copy %r30,%r19
109 ldo 128(%r30),%r30 ; Allocate space on stack
110 stwm %r2,4(0,%r19) ; Save return pointer
111 stwm %r23,4(0,%r19) ; Save old args
112 stwm %r24,4(0,%r19) ;
113 stwm %r25,4(0,%r19) ;
114 stwm %r26,4(0,%r19) ;
115 #ifndef KERNEL
116 fstds,mb %fr4,4(0,%r19) ; Save floating point args
117 fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead
118 fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above
119 fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4
120 ; so that doubles are aligned
121 ; to 8 byte boundaries.
122 ; Arg 1 (selector) is the same
123 #endif /* KERNEL */
124
125 stw %r28,8(0,%r19) ; save return struct ptr
126 ldw isa(0,%r26),%r26 ; <delay slot> arg 0 = self->isa
127 CALL_EXTERN(__class_lookupMethodAndLoadCache)
128
129 ldo -128(%r30),%r30 ; deallocate
130 copy %r30,%r19 ;
131 ldwm 4(0,%r19),%r2 ; restore everything
132 ldwm 4(0,%r19),%r23 ;
133 ldwm 4(0,%r19),%r24 ;
134 ldwm 4(0,%r19),%r25 ;
135 ldwm 4(0,%r19),%r26 ;
136 #ifndef KERNEL
137 fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment
138 fldds,mb 8(0,%r19),%fr5 ;
139 fldds,mb 8(0,%r19),%fr6 ;
140 fldds,mb 8(0,%r19),%fr7 ;
141 #endif /* KERNEL */
142 ldw 8(0,%r19),%r20 ; get ret structure ptr
143
144 copy %r28,%r19
145 copy %r20,%r28 ; restore ret structure ptr
146 Lexit2:
147 bv,n 0(%r19) ; goto *imp (nullify delay)
148
149 #ifdef MONINIT
150 .space 128 ; /* area for moninitobjc to write */
151 #endif
152
153
154
155 ; Locking version of objc_msgSend
156 ; uses spin_lock() to lock the mutex.
157
158 LSendLocking:
159 copy %r30,%r19
160 ldo 128(%r30),%r30 ; Allocate space on stack
161 stwm %r2,4(0,%r19) ; Save return pointer
162 stwm %r23,4(0,%r19) ; Save old args
163 stwm %r24,4(0,%r19) ;
164 stwm %r25,4(0,%r19) ;
165 stwm %r26,4(0,%r19) ;
166 stwm %r28,4(0,%r19) ; save return struct ptr
167 #ifndef KERNEL
168 fstds,ma %fr4,8(0,%r19) ; Save floating point args
169 fstds,ma %fr5,8(0,%r19) ;
170 fstds,ma %fr6,8(0,%r19) ;
171 fstds,ma %fr7,8(0,%r19) ;
172 #endif /* KERNEL */
173
174 ldil L`_messageLock,%r1
175 ldo R`_messageLock(%r1),%r26
176 ldil L`OBJC_LOCK_ROUTINE,%r1 ; call spin_lock() with _messageLock
177 ble R`OBJC_LOCK_ROUTINE(%sr4,%r1)
178 copy %r31,%r2
179 ldw -112(%r30),%r26 ; restore arg0
180 ldw -108(%r30),%r28 ; and ret0 (spin_lock doesnt
181 ; touch anything else important)
182 ldw isa(0,%r26),%r19 ; class = self->isa;
183 ldw cache(0,%r19),%r20 ; cache = class->cache
184 ldw mask(0,%r20),%r21 ; mask = cache->mask
185 ldo buckets(%r20),%r20 ; buckets = cache->buckets
186 and %r21,%r25,%r22 ; index = selector & mask;
187 LL1:
188 ldwx,s %r22(0,%r20),%r19 ; method = cache->buckets[index];
189 comib,=,n 0,%r19,LL2 ; if (method == NULL)
190 ldw method_name(0,%r19),%r1 ;
191 addi 1,%r22,%r22 ; ++index
192 comb,<> %r1, %r25, LL1 ; if (name!=sel) continue loop
193 and %r21,%r22,%r22 ; <delay slot> index &=mask
194 ldw method_imp(0,%r19),%r19
195 #if KERNEL
196 ldil L`_messageLock,%r1
197 ldo R`_messageLock(%r1),%r20
198 addi 0xc,%r20,%r20
199 depi 0,31,4,%r20
200 zdepi 1,31,1,%r1
201 stw %r1,0(0,%r20)
202 #else
203 ldil L`_messageLock,%r1
204 stw %r0,R`_messageLock(%r1) ; unlock the lock
205 #endif
206 ldwm -128(%r30),%r2 ; restore original rp and deallocate
207 Lexit3:
208 bv,n 0(%r19) ; goto *imp; (nullify delay)
209
210 #ifdef MONINIT
211 .space 128 ; /* area for moninitobjc to write */
212 #endif
213
214 LL2:
215 ldw isa(0,%r26),%r26 ; arg 0 = self->isa
216 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
217
218 ldo -128(%r30),%r30 ; deallocate
219 copy %r30,%r19 ;
220 ldwm 4(0,%r19),%r2 ; restore everything
221 ldwm 4(0,%r19),%r23 ;
222 ldwm 4(0,%r19),%r24 ;
223 ldwm 4(0,%r19),%r25 ;
224 ldwm 4(0,%r19),%r26 ;
225 ldwm 4(0,%r19),%r20 ; get ret structure ptr
226 #ifndef KERNEL
227 fldds,ma 8(0,%r19),%fr4 ;
228 fldds,ma 8(0,%r19),%fr5 ;
229 fldds,ma 8(0,%r19),%fr6 ;
230 fldds,ma 8(0,%r19),%fr7 ;
231 #endif /* KERNEL */
232
233 copy %r28,%r19
234 copy %r20,%r28 ; restore ret structure ptr
235 #if KERNEL
236 ldil L`_messageLock,%r1
237 ldo R`_messageLock(%r1),%r20
238 addi 0xc,%r20,%r20
239 depi 0,31,4,%r20
240 zdepi 1,31,1,%r1
241 stw %r1,0(0,%r20)
242 #else
243 ldil L`_messageLock,%r1
244 stw %r0,R`_messageLock(%r1) ; unlock the lock
245 #endif
246 Lexit4:
247 bv,n 0(%r19) ; goto *imp (nullify delay)
248
249 #ifdef MONINIT
250 .space 128 ; /* area for moninitobjc to write */
251 #endif
252
253
254
255
256
257 #define receiver 0
258 #define class 4
259
260 .globl _objc_msgSendSuper
261 _objc_msgSendSuper:
262 ldil L`__objc_multithread_mask,%r1
263 ldw R`__objc_multithread_mask(%r1),%r19
264 combt,= %r0,%r19,LSuperLocking ;
265 ldw class(0,%r26),%r19 ; class = caller->class;
266 ldw cache(0,%r19),%r20 ; cache = class->cache
267 ldw mask(0,%r20),%r21 ; mask = cache->mask
268 ldo buckets(%r20),%r20 ; buckets = cache->buckets
269 and %r21,%r25,%r22 ; index = selector & mask;
270 LS1: ;
271 ldwx,s %r22(0,%r20),%r19 ; method = cache->buckets[index];
272 comib,=,n 0,%r19,LS2 ; if (method == NULL)
273 ldw method_name(0,%r19),%r1;
274 addi 1,%r22,%r22 ; ++index
275 comb,<> %r1, %r25, LS1 ; if (name!=sel) continue loop
276 and %r21,%r22,%r22 ; <delay slot> index &=mask
277 ldw method_imp(0,%r19),%r19
278 ldw receiver(0,%r26),%r26 ; self = caller->receiver;
279 Lexit5:
280 bv,n 0(%r19) ; goto *imp; (nullify delay)
281 #ifdef MONINIT
282 .space 128 ; /* area for moninitobjc to write */
283 #endif
284
285 ;
286 LS2: ;
287 copy %r30,%r19
288 ldo 128(%r30),%r30 ; Allocate space on stack
289 stwm %r2,4(0,%r19) ; Save return pointer
290 stwm %r23,4(0,%r19) ; Save old args
291 stwm %r24,4(0,%r19) ;
292 stwm %r25,4(0,%r19) ;
293 stwm %r26,4(0,%r19) ;
294 #ifndef KERNEL
295 fstds,mb %fr4,4(0,%r19) ; Save floating point args
296 fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead
297 fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above
298 fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4
299 ; so that doubles are aligned
300 ; to 8 byte boundaries.
301 ; Arg 1 (selector) is the same
302 #endif /* KERNEL */
303 stw %r28,8(0,%r19) ; save return struct ptr
304 ldw class(0,%r26),%r26 ; arg 0 = caller->class;
305 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
306 ldo -128(%r30),%r30 ; deallocate
307 copy %r30,%r19 ;
308 ldwm 4(0,%r19),%r2 ; restore everything
309 ldwm 4(0,%r19),%r23 ;
310 ldwm 4(0,%r19),%r24 ;
311 ldwm 4(0,%r19),%r25 ;
312 ldwm 4(0,%r19),%r26 ;
313 #ifndef KERNEL
314 fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment
315 fldds,mb 8(0,%r19),%fr5 ;
316 fldds,mb 8(0,%r19),%fr6 ;
317 fldds,mb 8(0,%r19),%fr7 ;
318 #endif /* KERNEL */
319 ldw 8(0,%r19),%r20 ; get ret structure ptr
320 ldw receiver(0,%r26),%r26 ; self = caller->receiver;
321 copy %r28,%r19
322 copy %r20,%r28
323 Lexit6: bv,n 0(%r19) ; goto *imp (nullify delay)
324
325 #ifdef MONINIT
326 .space 128 ; /* area for moninitobjc to write */
327 #endif
328
329
330
331
332
333 ; locking version of objc_msgSendSuper
334 ; uses spin_lock() to lock the lock.
335
336
337 LSuperLocking:
338 copy %r30,%r19
339 ldo 128(%r30),%r30 ; Allocate space on stack
340 stwm %r2,4(0,%r19) ; Save return pointer
341 stwm %r23,4(0,%r19) ; Save old args
342 stwm %r24,4(0,%r19) ;
343 stwm %r25,4(0,%r19) ;
344 stwm %r26,4(0,%r19) ;
345 stwm %r28,4(0,%r19) ; save return struct ptr
346 #ifndef KERNEL
347 fstds,ma %fr4,8(0,%r19) ; Save floating point args
348 fstds,ma %fr5,8(0,%r19) ;
349 fstds,ma %fr6,8(0,%r19) ;
350 fstds,ma %fr7,8(0,%r19) ;
351 #endif /* KERNEL */
352 ldil L`_messageLock,%r1
353 ldo R`_messageLock(%r1),%r26
354 ldil L`OBJC_LOCK_ROUTINE,%r1 ; call spin_lock() with _messageLock
355 ble R`OBJC_LOCK_ROUTINE(%sr4,%r1)
356 copy %r31,%r2
357 ldw -112(%r30),%r26 ; restore arg0
358 ldw -108(%r30),%r28 ; and ret0 (spin_lock doesnt
359 ; touch anything else)
360 ldw class(0,%r26),%r19 ; class = caller->class;
361 ldw cache(0,%r19),%r20 ; cache = class->cache
362 ldw mask(0,%r20),%r21 ; mask = cache->mask
363 ldo buckets(%r20),%r20 ; buckets = cache->buckets
364 and %r21,%r25,%r22 ; index = selector & mask;
365 LLS1: ;
366 ldwx,s %r22(0,%r20),%r19 ; method = cache->buckets[index];
367 comib,=,n 0,%r19,LLS2 ; if (method == NULL)
368 ldw method_name(0,%r19),%r1;
369 addi 1,%r22,%r22 ; ++index
370 comb,<> %r1, %r25, LLS1 ; if (name!=sel) continue loop
371 and %r21,%r22,%r22 ; <delay slot> index &=mask
372 ldw method_imp(0,%r19),%r19
373 ldw receiver(0,%r26),%r26 ; self = caller->receiver;
374 #if KERNEL
375 ldil L`_messageLock,%r1
376 ldo R`_messageLock(%r1),%r20
377 addi 0xc,%r20,%r20
378 depi 0,31,4,%r20
379 zdepi 1,31,1,%r1
380 stw %r1,0(0,%r20)
381 #else
382 ldil L`_messageLock,%r1
383 stw %r0,R`_messageLock(%r1) ; unlock the lock
384 #endif
385 ldwm -128(%r30),%r2 ; restore original rp and deallocate
386 Lexit7:
387 bv,n 0(%r19) ; goto *imp; (nullify delay)
388 #ifdef MONINIT
389 .space 128 ; /* area for moninitobjc to write */
390 #endif
391
392 ;
393 LLS2: ;
394 ldw class(0,%r26),%r26 ; <delay slot> arg 0 = caller->class;
395 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache)
396 ldo -128(%r30),%r30 ; deallocate
397 copy %r30,%r19 ;
398 ldwm 4(0,%r19),%r2 ; restore everything
399 ldwm 4(0,%r19),%r23 ;
400 ldwm 4(0,%r19),%r24 ;
401 ldwm 4(0,%r19),%r25 ;
402 ldwm 4(0,%r19),%r26 ;
403 ldwm 4(0,%r19),%r20 ; get ret structure ptr
404 #ifndef KERNEL
405 fldds,ma 8(0,%r19),%fr4 ;
406 fldds,ma 8(0,%r19),%fr5 ;
407 fldds,ma 8(0,%r19),%fr6 ;
408 fldds,ma 8(0,%r19),%fr7 ;
409 #endif /* KERNEL */
410 ldw receiver(0,%r26),%r26 ; self = caller->receiver;
411 copy %r28,%r19
412 copy %r20,%r28
413 #if KERNEL
414 ldil L`_messageLock,%r1
415 ldo R`_messageLock(%r1),%r20
416 addi 0xc,%r20,%r20
417 depi 0,31,4,%r20
418 zdepi 1,31,1,%r1
419 stw %r1,0(0,%r20)
420 #else
421 ldil L`_messageLock,%r1
422 stw %r0,R`_messageLock(%r1) ; unlock the lock
423 #endif
424 Lexit8: bv,n 0(%r19) ; goto *imp (nullify delay)
425
426 #ifdef MONINIT
427 .space 128 ; /* area for moninitobjc to write */
428 #endif
429
430
431
432
433 .objc_meth_var_names
434 .align 1
435 L30: .ascii "forward::\0"
436
437 .objc_message_refs
438 .align 2
439 L31: .long L30
440
441 .cstring
442 .align 1
443 L32: .ascii "Does not recognize selector %s\0"
444
445 .text
446 .align 1
447 ;
448 ; NOTE: Because the stack grows from low mem to high mem on this machine
449 ; and the args go the other way, the marg_list pointer is to the first argument
450 ; and subsequent arguments are at NEGATIVE offsets from the marg_list.
451 ; This means that marg_getValue() and related macros will have to be adjusted
452 ; appropriately.
453 ;
454 .globl __objc_msgForward
455 __objc_msgForward:
456 stw %r2,-20(0,%r30) ; save rp
457 ldo 64(%r30),%r30 ; create frame area (no locals needed)
458 ldil L`L31,%r1
459 ldo R`L31(%r1),%r19
460 ldw 0(0,%r19),%r19
461 combt,=,n %r19, %r25,L34 ; if (sel==@selector(forward::))
462 ldo -112(%r30),%r20 ; ptr to arg3 homing area
463 stwm %r23,4(0,%r20) ; Mirror registers onto stack
464 stwm %r24,4(0,%r20) ;
465 stwm %r25,4(0,%r20) ;
466 stwm %r26,4(0,%r20) ;
467
468 copy %r25,%r24
469 copy %r19,%r25 ; [self forward:sel :marg_list]
470
471 bl _objc_msgSend,%r2
472 copy %r20,%r23 ; <delay slot> copy original sel
473
474 ldo -64(%r30),%r30 ; deallocate
475 ldw -20(0,%r30),%r2 ; restore rp
476 bv,n 0(%r2) ; return
477 L34:
478 ldil L`L32,%r1
479 ldo R`L32(%r1),%r25
480 copy %r19,%r24 ;
481 BRANCH_EXTERN(__objc_error)
482
483
484 ; Algorithm is as follows:
485 ; . Calculate how much stack size is needed for any arguments not in the
486 ; general registers and allocate space on stack.
487 ; . Restore general argument regs from the bottom of the marg_list.
488 ; . Restore fp argument regs from the same area.
489 ; (The first two args in the marg list are always old obj and old SEL.)
490 ; . Call the new method.
491 .globl _objc_msgSendv
492 _objc_msgSendv:
493 ; objc_msgSendv(self, sel, size, margs)
494 stw %r2,-20(0,%r30) ; Save rp
495 stw %r4,-36(0,%r30) ; Save callee-saved r4
496 copy %r30,%r4 ; Save old sp vale
497 ldo 95(%r24),%r19 ; Calculate frame size, rounded
498 depi 0,31,6,%r19 ; up to 64 byte boundary...
499
500 add %r19,%r30,%r30 ; Allocate frame area (no locals)
501 copy %r24,%r20 ; r20 now holds arg size
502 ldo -16(%r23),%r21 ; r21 now holds marg_list+16
503 ldws 0(0,%r21),%r23 ; Get old general register args (dont
504 ldws 4(0,%r21),%r24 ; need first two: always self & SEL)
505 #ifndef KERNEL
506 fldds 0(0,%r21),%fr7 ; Mirror to fp regs
507 fldws 4(0,%r21),%fr6 ;
508 #endif /* KERNEL */
509
510 ldo -52(%r30),%r22 ; newly allocated stack area.
511 ldo -8(%r20),%r20 ; Size -= 8
512 comibf,<,n 0,%r20,L36
513 L35: ldws,mb -4(0,%r21),%r19 ; while(size>0)
514 addibf,<= -4,%r20,L35 ; { *(dest--) = *(src--); size-=4; }
515 stws,ma %r19,-4(0,%r22) ; <delay slot>
516 L36: bl _objc_msgSend,%r2
517 nop
518 copy %r4,%r30 ; deallocate
519 ldw -36(0,%r30), %r4
520 ldw -20(0,%r30), %r2
521 bv,n 0(%r2)
522
523