|
|
1.1 root 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.0 (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: #ifdef DYLIB
28: #define OBJC_LOCK_ROUTINE _spin_lock$non_lazy_ptr
29: #else
30: #define OBJC_LOCK_ROUTINE _spin_lock
31: #endif
32: #endif /* KERNEL */
33:
34: #define isa 0
35: #define cache 32
36: #define mask 0
37: #define buckets 8
38: #define method_name 0
39: #define method_imp 4
40:
41: ;; Optimized specifically for HP7100 (Gecko architecture)
42: ;; It is assumed, that the cache line containing __objc_multithread_mask
43: ;; is not missing. This version has only two (2) back-to-back insn
44: ;; output dependencies, of which one is in the inner loop at 2:.
45: ;; This version has also no read insns with output dependency on the
46: ;; following insn. It is optimized with regard to branch prediction for
47: ;; hit in the first probe (average probe length assumed to be .45), that
48: ;; is why the final branch is moved before _objc_msgSend.
49:
50: ;; non-pic: 14 clocks best case, 4 clock / probe
51: ;; (4miss + 1hit) + (2hit) / probe
52:
53: ;; pic: 16 clocks best case, 4 clocks / probe
54: ;; (4miss + 2hit) + (2hit) / probe
55:
56: .text
57: .align 2
58: .globl _objc_msgSend
59:
60: LX0: bv,n 0(%r1) ; goto *imp; (nullify delay)
61: _objc_msgSend:
62: comib,=,n 0,%r26, Lnull ; <?not taken?>
63: #ifdef DYLIB
64: bl LX1,%r21
65: ldw isa(0,%r26),%r19 ; class = self->isa;
66: LX1:
67: depi 0,31,2,%r21
68: addil L`__objc_multithread_mask$non_lazy_ptr-LX1,%r21
69: ldw cache(0,%r19),%r20 ; cache = class->cache
70: ldw R`__objc_multithread_mask$non_lazy_ptr-LX1(%r1),%r22
71: ldw mask(0,%r20),%r21 ; mask = cache->mask
72: ldw 0(%r22),%r22 ; <indirect non lazy pointer>
73: ldo buckets(%r20),%r20 ; buckets = cache->buckets
74: comib,=,n 0,%r22, SendLocking ; <?not taken?>
75: #else
76: ldil L`__objc_multithread_mask,%r1
77: ldw isa(0,%r26),%r19 ; class = self->isa;
78: ldw R`__objc_multithread_mask(%r1),%r22
79: ldw cache(0,%r19),%r20 ; cache = class->cache
80: comib,=,n 0,%r22, SendLocking ; <?not taken?>
81: ldw mask(0,%r20),%r21 ; mask = cache->mask
82: ldo buckets(%r20),%r20 ; buckets = cache->buckets
83: #endif
84:
85: and %r21,%r25,%r22 ; index = selector & mask;
86: 2: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets
87: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name
88:
89: ldo 1(%r22),%r22 ; index += 1
90: comb,= %r25,%r19,LX0 ; if (selector == op) goto Lexit1 <?taken?>
91: ldw method_imp(0,%r1),%r1 ; <delay slot> imp = bucket->selector_imp
92: comib,<> 0,%r19,2b ; if (op != 0) goto 2 <?taken?>
93:
94: and %r22,%r21,%r22 ; <delay slot> index &= mask
95: b,n L2 ; else goto cacheMiss
96: L2:
97: ; We have to save all the register based arguments (including floating
98: ; point) before calling _class_lookupMethodAndLoadCache. This is because
99: ; we do not know what arguments were passed to us, and the arguments are
100: ; not guaranteed to be saved across procedure calls (they are all caller-saved)
101: ; We also have to save the return address (since we did not save it on entry).
102:
103:
104: copy %r30,%r19
105: ldo 128(%r30),%r30 ; Allocate space on stack
106: stwm %r2,4(0,%r19) ; Save return pointer
107: stwm %r23,4(0,%r19) ; Save old args
108: stwm %r24,4(0,%r19) ;
109: stwm %r25,4(0,%r19) ;
110: stwm %r26,4(0,%r19) ;
111: #ifndef KERNEL
112: fstds,mb %fr4,4(0,%r19) ; Save floating point args
113: fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead
114: fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above
115: fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4
116: ; so that doubles are aligned
117: ; to 8 byte boundaries.
118: ; Arg 1 (selector) is the same
119: #endif /* KERNEL */
120:
121: stw %r28,8(0,%r19) ; save return struct ptr
122: jbsr __class_lookupMethodAndLoadCache,%r2,0f
123: ldw isa(0,%r26),%r26 ; <delay slot> arg 0 = self->isa
124:
125: ldo -128(%r30),%r30 ; deallocate
126: copy %r30,%r19 ;
127: ldwm 4(0,%r19),%r2 ; restore everything
128: ldwm 4(0,%r19),%r23 ;
129: ldwm 4(0,%r19),%r24 ;
130: ldwm 4(0,%r19),%r25 ;
131: ldwm 4(0,%r19),%r26 ;
132: #ifndef KERNEL
133: fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment
134: fldds,mb 8(0,%r19),%fr5 ;
135: fldds,mb 8(0,%r19),%fr6 ;
136: fldds,mb 8(0,%r19),%fr7 ;
137: #endif /* KERNEL */
138: ldw 8(0,%r19),%r20 ; get ret structure ptr
139:
140: copy %r28,%r19
141: copy %r20,%r28 ; restore ret structure ptr
142:
143: bv,n 0(%r19) ; goto *imp (nullify delay)
144:
145: ; stub for far call
146:
147: .align 2
148: #ifdef DYLIB
149: 0: bl LX5,%r1
150: nop
151: LX5: depi 0,31,2,%r1
152: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX5,%r1
153: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX5(%r1),%r1
154: be,n 0(4,%r1)
155: #else
156: 0: ldil L`__class_lookupMethodAndLoadCache,%r1
157: be,n R`__class_lookupMethodAndLoadCache(4,%r1)
158: #endif
159:
160: .align 2
161: Lnull:
162: bv 0(%r2) ; return null
163: copy 0,%r28 ; <delay slot> return val = 0
164:
165:
166:
167: ; Locking version of objc_msgSend
168: ; uses spin_lock() to lock the mutex.
169:
170: .align 2
171: SendLocking:
172: copy %r30,%r19
173: ldo 128(%r30),%r30 ; Allocate space on stack
174: stwm %r2,4(0,%r19) ; Save return pointer
175: stwm %r23,4(0,%r19) ; Save old args
176:
177: stwm %r24,4(0,%r19) ;
178: stwm %r25,4(0,%r19) ;
179: stwm %r26,4(0,%r19) ;
180: stwm %r28,4(0,%r19) ; save return struct ptr
181:
182: #ifndef KERNEL
183: fstds,ma %fr4,8(0,%r19) ; Save floating point args
184: fstds,ma %fr5,8(0,%r19) ;
185: fstds,ma %fr6,8(0,%r19) ;
186: fstds,ma %fr7,8(0,%r19) ;
187: #endif /* KERNEL */
188:
189: #ifdef DYLIB
190: 0: bl LX6,%r24
191: nop
192: LX6: depi 0,31,2,%r24
193: addil L`_messageLock$non_lazy_ptr-LX6,%r24
194: ldw R`_messageLock$non_lazy_ptr-LX6(%r1),%r26
195: addil L`OBJC_LOCK_ROUTINE -LX6,%r24 ; call spin_lock() with _messageLock
196: ldw R`OBJC_LOCK_ROUTINE -LX6(%r1),%r24
197: ble 0(%sr4,%r24)
198: #else
199: ldil L`_messageLock,%r1
200: ldo R`_messageLock(%r1),%r26
201: ldil L`OBJC_LOCK_ROUTINE,%r1 ; call spin_lock() with _messageLock
202: ble R`OBJC_LOCK_ROUTINE(%sr4,%r1)
203: #endif
204:
205: copy %r31,%r2
206: ldw -112(%r30),%r26 ; restore arg0
207: ldw -108(%r30),%r28 ; and ret0
208: ldw isa(0,%r26),%r19 ; class = self->isa;
209:
210: ldw cache(0,%r19),%r20 ; cache = class->cache
211: ldw mask(0,%r20),%r21 ; mask = cache->mask
212: ldo buckets(%r20),%r20 ; buckets = cache->buckets
213: and %r21,%r25,%r22 ; index = selector & mask;
214:
215: LL1: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets
216: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name
217: ldo 1(%r22),%r22 ; index += 1
218: comb,=,n %r25,%r19,LLhit1 ; if (selector == op) goto LLhit1
219:
220: comib,<> 0,%r19,LL1 ; if (op != 0) goto LL1
221: and %r22,%r21,%r22 ; <delay slot> index &= mask
222: b,n LL2 ; else goto cacheMiss
223: LLhit1:
224: ldw method_imp(0,%r1),%r19 ; imp = bucket->selector_imp
225: #if KERNEL
226: ldil L`_messageLock,%r1
227: ldo R`_messageLock(%r1),%r20
228: addi 0xc,%r20,%r20
229: depi 0,31,4,%r20
230: zdepi 1,31,1,%r1
231: stw %r1,0(0,%r20)
232: #else
233: #ifdef DYLIB
234: bl LX7,%r21
235: nop
236: LX7: depi 0,31,2,%r21
237: addil L`_messageLock$non_lazy_ptr-LX7,%r21
238: ldw R`_messageLock$non_lazy_ptr-LX7(%r1),%r21
239: stw %r0,0(%r21) ; unlock the lock
240: #else
241: ldil L`_messageLock,%r1
242: stw %r0,R`_messageLock(%r1) ; unlock the lock
243: #endif
244: #endif
245: ldwm -128(%r30),%r2 ; restore original rp and deallocate
246: bv,n 0(%r19) ; goto *imp; (nullify delay)
247:
248: LL2:
249: jbsr __class_lookupMethodAndLoadCache,%r2,0f
250: ldw isa(0,%r26),%r26 ; <delay slot> arg 0 = self->isa
251:
252: ldo -128(%r30),%r30 ; deallocate
253: copy %r30,%r19 ;
254: ldwm 4(0,%r19),%r2 ; restore everything
255: ldwm 4(0,%r19),%r23 ;
256: ldwm 4(0,%r19),%r24 ;
257: ldwm 4(0,%r19),%r25 ;
258: ldwm 4(0,%r19),%r26 ;
259: ldwm 4(0,%r19),%r20 ; get ret structure ptr
260: #ifndef KERNEL
261: fldds,ma 8(0,%r19),%fr4 ;
262: fldds,ma 8(0,%r19),%fr5 ;
263: fldds,ma 8(0,%r19),%fr6 ;
264: fldds,ma 8(0,%r19),%fr7 ;
265: #endif /* KERNEL */
266:
267: copy %r28,%r19
268: copy %r20,%r28 ; restore ret structure ptr
269: #if KERNEL
270: ldil L`_messageLock,%r1
271: ldo R`_messageLock(%r1),%r20
272: addi 0xc,%r20,%r20
273: depi 0,31,4,%r20
274: zdepi 1,31,1,%r1
275: stw %r1,0(0,%r20)
276: #else
277: #ifdef DYLIB
278: bl LX8,%r19
279: nop
280: LX8: depi 0,31,2,%r19
281: addil L`_messageLock$non_lazy_ptr-LX8,%r19
282: ldw _messageLock$non_lazy_ptr-LX8(%r1),%r19
283: stw %r0,0(%r19) ; unlock the lock
284: #else
285: ldil L`_messageLock,%r1
286: stw %r0,R`_messageLock(%r1) ; unlock the lock
287: #endif
288: #endif
289: bv,n 0(%r19) ; goto *imp (nullify delay)
290:
291: ; stub for far call
292:
293: .align 2
294: #ifdef DYLIB
295: 0: bl LX2,%r1
296: nop
297: LX2: depi 0,31,2,%r1
298: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX2,%r1
299: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX2(%r1),%r1
300: be,n 0(4,%r1)
301: #else
302: 0: ldil L`__class_lookupMethodAndLoadCache,%r1
303: be,n R`__class_lookupMethodAndLoadCache(4,%r1)
304: #endif
305:
306:
307: #define receiver 0
308: #define class 4
309:
310: .globl _objc_msgSendSuper
311: .align 2
312: _objc_msgSendSuper:
313: ldil L`__objc_multithread_mask,%r1
314: ldw R`__objc_multithread_mask(%r1),%r19
315: combt,= %r0,%r19,SuperLocking ;
316: ldw class(0,%r26),%r19 ; class = caller->class;
317:
318: ldw cache(0,%r19),%r20 ; cache = class->cache
319: ldw mask(0,%r20),%r21 ; mask = cache->mask
320: ldo buckets(%r20),%r20 ; buckets = cache->buckets
321: and %r21,%r25,%r22 ; index = selector & mask;
322:
323: LS1: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets
324: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name
325: ldo 1(%r22),%r22 ; index += 1
326: comb,= %r25,%r19,LShit1 ; if (selector == op) goto LShit1
327:
328: ldw method_imp(0,%r1),%r1 ; <delay slot> imp = bucket->selector_imp
329: comib,<> 0,%r19,LS1 ; if (op != 0) goto LS1
330: and %r22,%r21,%r22 ; <delay slot> index &= mask
331: b,n LS2 ; else goto cacheMiss
332:
333: LShit1:
334: bv 0(%r1) ; goto *imp; (nullify delay)
335: ldw receiver(0,%r26),%r26 ; <delay slot> self = caller->receiver;
336: ;
337: LS2: ;
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: #ifndef KERNEL
346: fstds,mb %fr4,4(0,%r19) ; Save floating point args
347: fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead
348: fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above
349: fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4
350: ; so that doubles are aligned
351: ; to 8 byte boundaries.
352: ; Arg 1 (selector) is the same
353: #endif /* KERNEL */
354: stw %r28,8(0,%r19) ; save return struct ptr
355: jbsr __class_lookupMethodAndLoadCache,%r2,0f
356: ldw class(0,%r26),%r26 ; <delay slot> arg 0 = caller->class;
357: ldo -128(%r30),%r30 ; deallocate
358: copy %r30,%r19 ;
359: ldwm 4(0,%r19),%r2 ; restore everything
360: ldwm 4(0,%r19),%r23 ;
361: ldwm 4(0,%r19),%r24 ;
362: ldwm 4(0,%r19),%r25 ;
363: ldwm 4(0,%r19),%r26 ;
364: #ifndef KERNEL
365: fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment
366: fldds,mb 8(0,%r19),%fr5 ;
367: fldds,mb 8(0,%r19),%fr6 ;
368: fldds,mb 8(0,%r19),%fr7 ;
369: #endif /* KERNEL */
370: ldw 8(0,%r19),%r20 ; get ret structure ptr
371: ldw receiver(0,%r26),%r26 ; self = caller->receiver;
372: copy %r28,%r19
373: copy %r20,%r28
374: bv,n 0(%r19) ; goto *imp (nullify delay)
375:
376: ; stub for far call
377:
378: .align 2
379: #ifdef DYLIB
380: 0: bl LX3,%r1
381: nop
382: LX3: depi 0,31,2,%r1
383: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX3,%r1
384: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX3(%r1),%r1
385: be,n 0(4,%r1)
386: #else
387: 0: ldil L`__class_lookupMethodAndLoadCache,%r1
388: be,n R`__class_lookupMethodAndLoadCache(4,%r1)
389: #endif
390:
391:
392:
393:
394: ; locking version of objc_msgSendSuper
395: ; uses spin_lock() to lock the lock.
396:
397: .align 2
398: SuperLocking:
399: copy %r30,%r19
400: ldo 128(%r30),%r30 ; Allocate space on stack
401: stwm %r2,4(0,%r19) ; Save return pointer
402: stwm %r23,4(0,%r19) ; Save old args
403: stwm %r24,4(0,%r19) ;
404: stwm %r25,4(0,%r19) ;
405: stwm %r26,4(0,%r19) ;
406: stwm %r28,4(0,%r19) ; save return struct ptr
407: #ifndef KERNEL
408: fstds,ma %fr4,8(0,%r19) ; Save floating point args
409: fstds,ma %fr5,8(0,%r19) ;
410: fstds,ma %fr6,8(0,%r19) ;
411: fstds,ma %fr7,8(0,%r19) ;
412: #endif /* KERNEL */
413: #ifdef DYLIB
414: 0: bl LX9,%r24
415: nop
416: LX9: depi 0,31,2,%r24
417: addil L`_messageLock$non_lazy_ptr-LX9,%r24
418: ldw R`_messageLock$non_lazy_ptr-LX9(%r1),%r26
419: addil L`OBJC_LOCK_ROUTINE-LX9,%r24 ; call spin_lock() with _messageLock
420: ldw R`OBJC_LOCK_ROUTINE-LX9(%r1),%r24
421: ble 0(%sr4,%r24)
422: #else
423: ldil L`_messageLock,%r1
424: ldo R`_messageLock(%r1),%r26
425: ldil L`OBJC_LOCK_ROUTINE,%r1 ; call spin_lock() with _messageLock
426: ble R`OBJC_LOCK_ROUTINE(%sr4,%r1)
427: #endif
428: copy %r31,%r2
429: ldw -112(%r30),%r26 ; restore arg0
430: ldw -108(%r30),%r28 ; and ret0 (spin_lock doesnt
431: ; touch anything else)
432: ldw class(0,%r26),%r19 ; class = caller->class;
433: ldw cache(0,%r19),%r20 ; cache = class->cache
434: ldw mask(0,%r20),%r21 ; mask = cache->mask
435: ldo buckets(%r20),%r20 ; buckets = cache->buckets
436: and %r21,%r25,%r22 ; index = selector & mask;
437:
438: LLS1: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets
439: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name
440: ldo 1(%r22),%r22 ; index += 1
441: comb,=,n %r25,%r19,LLShit1 ; if (selector == op) goto LShit1
442:
443: comib,<> 0,%r19,LLS1 ; if (op != 0) goto LS1
444: and %r22,%r21,%r22 ; <delay slot> index &= mask
445: b,n LLS2 ; else goto cacheMiss
446:
447: LLShit1:
448: ldw method_imp(0,%r1),%r19 ; imp = bucket->selector_imp
449: ldw receiver(0,%r26),%r26 ; self = caller->receiver;
450:
451: #if KERNEL
452: ldil L`_messageLock,%r1
453: ldo R`_messageLock(%r1),%r20
454: addi 0xc,%r20,%r20
455: depi 0,31,4,%r20
456: zdepi 1,31,1,%r1
457: stw %r1,0(0,%r20)
458: #else
459: #ifdef DYLIB
460: bl LX10,%r19
461: nop
462: LX10: depi 0,31,2,%r19
463: addil L`_messageLock$non_lazy_ptr-LX10,%r19
464: ldw R`_messageLock$non_lazy_ptr-LX10(%r1),%r19
465: stw %r0,0(%r19) ; unlock the lock
466: #else
467: ldil L`_messageLock,%r1
468: stw %r0,R`_messageLock(%r1) ; unlock the lock
469: #endif
470: #endif
471: ldwm -128(%r30),%r2 ; restore original rp and deallocate
472: bv,n 0(%r19) ; goto *imp; (nullify delay)
473: #ifdef MONINIT
474: .space 128 ; /* area for moninitobjc to write */
475: #endif
476:
477: ;
478: LLS2: ;
479: jbsr __class_lookupMethodAndLoadCache,%r2,0f
480: ldw class(0,%r26),%r26 ; <delay slot> arg 0 = caller->class;
481: ldo -128(%r30),%r30 ; deallocate
482: copy %r30,%r19 ;
483: ldwm 4(0,%r19),%r2 ; restore everything
484: ldwm 4(0,%r19),%r23 ;
485: ldwm 4(0,%r19),%r24 ;
486: ldwm 4(0,%r19),%r25 ;
487: ldwm 4(0,%r19),%r26 ;
488: ldwm 4(0,%r19),%r20 ; get ret structure ptr
489: #ifndef KERNEL
490: fldds,ma 8(0,%r19),%fr4 ;
491: fldds,ma 8(0,%r19),%fr5 ;
492: fldds,ma 8(0,%r19),%fr6 ;
493: fldds,ma 8(0,%r19),%fr7 ;
494: #endif /* KERNEL */
495: ldw receiver(0,%r26),%r26 ; self = caller->receiver;
496: copy %r28,%r19
497: copy %r20,%r28
498: #if KERNEL
499: ldil L`_messageLock,%r1
500: ldo R`_messageLock(%r1),%r20
501: addi 0xc,%r20,%r20
502: depi 0,31,4,%r20
503: zdepi 1,31,1,%r1
504: stw %r1,0(0,%r20)
505: #else
506: ldil L`_messageLock,%r1
507: stw %r0,R`_messageLock(%r1) ; unlock the lock
508: #endif
509: bv,n 0(%r19) ; goto *imp (nullify delay)
510:
511: ; stub for far call
512:
513: .align 2
514: #ifdef DYLIB
515: 0: bl LX4,%r1
516: nop
517: LX4: depi 0,31,2,%r1
518: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX4,%r1
519: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX4(%r1),%r1
520: be,n 0(4,%r1)
521: #else
522: 0: ldil L`__class_lookupMethodAndLoadCache,%r1
523: be,n R`__class_lookupMethodAndLoadCache(4,%r1)
524: #endif
525:
526:
527: .objc_meth_var_names
528: L30: .ascii "forward::\0"
529:
530: .objc_message_refs
531: .align 2
532: L31: .long L30
533:
534: .cstring
535: L32: .ascii "Does not recognize selector %s\0"
536:
537: .text
538: .align 2
539: ;
540: ; NOTE: Because the stack grows from low mem to high mem on this machine
541: ; and the args go the other way, the marg_list pointer is to the first argument
542: ; and subsequent arguments are at NEGATIVE offsets from the marg_list.
543: ; This means that marg_getValue() and related macros will have to be adjusted
544: ; appropriately.
545: ;
546: .globl __objc_msgForward
547: __objc_msgForward:
548: stw %r2,-20(0,%r30) ; save rp
549: ldo 64(%r30),%r30 ; create frame area (no locals needed)
550: ldil L`L31,%r1
551: ldo R`L31(%r1),%r19
552: ldw 0(0,%r19),%r19
553: combt,=,n %r19, %r25,L34 ; if (sel==@selector(forward::))
554: ldo -112(%r30),%r20 ; ptr to arg3 homing area
555: stwm %r23,4(0,%r20) ; Mirror registers onto stack
556: stwm %r24,4(0,%r20) ;
557: stwm %r25,4(0,%r20) ;
558: stwm %r26,4(0,%r20) ;
559:
560: copy %r25,%r24
561: copy %r19,%r25 ; [self forward:sel :marg_list]
562:
563: bl _objc_msgSend,%r2
564: copy %r20,%r23 ; <delay slot> copy original sel
565:
566: ldo -64(%r30),%r30 ; deallocate
567: ldw -20(0,%r30),%r2 ; restore rp
568: bv,n 0(%r2) ; return
569: L34:
570: ldil L`L32,%r1
571: ldo R`L32(%r1),%r25
572: ldil L`__objc_error,%r1
573: be R`__objc_error(%sr4,%r1) ; __objc_error never returns, so no
574: copy %r19,%r24 ; need to clean up.
575:
576:
577: ; Algorithm is as follows:
578: ; . Calculate how much stack size is needed for any arguments not in the
579: ; general registers and allocate space on stack.
580: ; . Restore general argument regs from the bottom of the marg_list.
581: ; . Restore fp argument regs from the same area.
582: ; (The first two args in the marg list are always old obj and old SEL.)
583: ; . Copy any remaining args from the marg_list to the new frame
584: ; . Call the new method.
585: .align 2
586: .globl _objc_msgSendv
587: _objc_msgSendv:
588: ; objc_msgSendv(self, sel, size, margs)
589: stw %r2,-20(0,%r30) ;
590: copy %r4, %r1 ; stanard prologue
591: copy %r30,%r4 ;
592: stw %r1,0(0,%r4) ;
593: ldo 99(%r24),%r19 ; Calculate frame size, rounded
594: depi 0,31,6,%r19 ; up to 64 byte boundary...
595:
596: add %r19,%r30,%r30 ; Allocate frame area (no locals)
597: copy %r24,%r20 ; r20 now holds arg size
598: ldo -16(%r23),%r21 ; r21 now holds marg_list+16
599: ldws 0(0,%r21),%r23 ; Get old general register args (dont
600: ldws 4(0,%r21),%r24 ; need first two: always self & SEL)
601: #ifndef KERNEL
602: fldds 0(0,%r21),%fr7 ; Mirror to fp regs
603: fldws 4(0,%r21),%fr6 ;
604: #endif /* KERNEL */
605:
606: ldo -52(%r30),%r22 ; newly allocated stack area.
607: ldo -16(%r20),%r20 ; Size -= 16
608: comibf,<,n 0,%r20,L36
609: L35: ldws,mb -4(0,%r21),%r19 ; while(size>0)
610: addibf,<= -4,%r20,L35 ; { *(dest--) = *(src--); size-=4; }
611: stws,ma %r19,-4(0,%r22) ; <delay slot>
612: L36: bl _objc_msgSend,%r2
613: nop
614: copy %r4,%r30 ; deallocate
615: ldw -20(0,%r30), %r2
616: bv 0(%r2)
617: ldw 0(0,%r30), %r4
618:
619: #ifdef DYLIB
620: .non_lazy_symbol_pointer
621: _messageLock$non_lazy_ptr:
622: .indirect_symbol _messageLock
623: .long 0
624: _spin_lock$non_lazy_ptr:
625: .indirect_symbol _spin_lock
626: .long 0
627: __objc_multithread_mask$non_lazy_ptr:
628: .indirect_symbol __objc_multithread_mask
629: .long 0
630: __class_lookupMethodAndLoadCache$non_lazy_ptr:
631: .indirect_symbol __class_lookupMethodAndLoadCache
632: .long 0
633: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.