|
|
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: /*
25: * Copyright 1988-1996 NeXT Software, Inc.
26: *
27: * objc-msg-ppc.s
28: *
29: * 1-May-97 Umesh Vaishampayan ([email protected])
30: * Incorporated locking code fixes from David Harrison ([email protected])
31: *
32: * 2-Apr-97 Umesh Vaishampayan ([email protected])
33: * Incarporated changes for messanger with struct return
34: * Cleaned up the labels to use local labels
35: * Fixed bug in the msgSendSuper that did not do the locking.
36: *
37: * 31-Dec-96 Umesh Vaishampayan ([email protected])
38: * Created from m98k.
39: *
40: */
41:
42: #define STACK_ALIGN_MASK 0xfff0
43:
44: #ifndef KERNEL
45: ; _objc_entryPoints and _objc_exitPoints are used by moninitobjc() to setup
46: ; objective-C messages for profiling. The are made private_externs when in
47: ; a shared library.
48: .reference _moninitobjc
49: .const
50: .align 2
51: .globl _objc_entryPoints
52: _objc_entryPoints:
53: .long _objc_msgSend
54: .long _objc_msgSendSuper
55: .long _objc_msgSendv
56: .long _objc_msgSend_stret
57: .long _objc_msgSendSuper_stret
58: .long 0
59:
60: .globl _objc_exitPoints
61: _objc_exitPoints:
62: .long Lexit1
63: .long Lexit2
64: .long Lexit3
65: .long Lexit4
66: .long Lexit5
67: .long Lexit6
68: .long Lexit7
69: .long Lexit8
70: .long LRexit1
71: .long LRexit2
72: .long LRexit3
73: .long LRexit4
74: .long LRexit5
75: .long LRexit6
76: .long LRexit7
77: .long LRexit8
78: .long 0
79: #endif /* ! KERNEL */
80:
81: isa = 0
82: cache = 32
83: mask = 0
84: buckets = 8
85: method_name = 0
86: method_imp = 8
87:
88: .text
89: .align 2
90: .globl _objc_msgSend
91: _objc_msgSend:
92: stw r7, 40(r1) ; save r7 through r10 for use as temps
93: stw r8, 44(r1)
94: stw r9, 48(r1)
95: stw r10,52(r1)
96:
97: addis r7,0,hi16(__objc_multithread_mask)
98: ori r7,r7,lo16(__objc_multithread_mask)
99: lwz r7,0(r7)
100: and. r7,r3,r7
101: bne cr0,L0 ; branch to the "normal" case,
102: ; no locking, id != nil
103:
104: cmplwi cr0,r3,0 ; if id == nil
105: bne cr0,LL0 ; LL0 is the "locking" case
106: b L3 ; L3 is the return nil case
107: L0:
108: lwz r10,isa(r3) ; class = self->isa;
109: lwz r10,cache(r10) ; cache = class->cache
110: lwz r11,mask(r10) ; mask = cache->mask
111: addi r9,r10,buckets ; buckets = cache->buckets
112: and r10,r4,r11 ; index = selector & mask;
113: L1:
114: slwi r0,r10,2 ;
115: lwzx r7,r9,r0 ; method = cache->buckets[index];
116: cmplwi cr0,r7,0 ; if (method == NULL)
117: beq cr0,L2 ;
118: addi r10,r10,1 ; index++;
119: lwz r8,method_name(r7) ; name = method->method_name;
120: and r10,r10,r11 ; index &= mask
121: lwz r7,method_imp(r7) ; imp = method->method_imp;
122: cmpw r4,r8 ; if (name != selector)
123: bne cr0,L1 ; goto loop;
124: mtspr ctr,r7 ;
125: lwz r7, 40(r1) ; restore r7 through r10
126: lwz r8, 44(r1)
127: lwz r9, 48(r1) ;
128: lwz r10,52(r1) ;
129: Lexit1:
130: bctr ; goto *imp;
131: .space 112 ; /* area for moninitobjc to write */
132: L2: ;
133: lwz r10,isa(r3) ; class = self->isa;
134:
135: stw r3, 24(r1) ; save the other register parameters
136: stw r4, 28(r1) ;
137: stw r5, 32(r1) ;
138: stw r6, 36(r1) ;
139:
140: mflr r0 ; save LR
141: stw r0,8(r1) ;
142: stwu r1,-64(r1) ; grow the stack
143:
144: ori r3,r10,0 ; first arg is the isa pointer
145: bl __class_lookupMethodAndLoadCache
146: mtspr ctr,r3
147: lwz r1,0(r1) ; restore the stack pointer
148:
149: lwz r0,8(r1) ;
150: mtlr r0 ; restore return pc
151: lwz r3, 24(r1) ;
152: lwz r4, 28(r1) ;
153: lwz r5, 32(r1) ;
154: lwz r6, 36(r1) ;
155: lwz r7, 40(r1) ;
156: lwz r8, 44(r1) ;
157: lwz r9, 48(r1) ;
158: lwz r10,52(r1) ;
159: Lexit2:
160: bctr ; goto *imp;
161: .space 112 ; /* area for moninitobjc to write */
162: L3: ;
163: addi r3,0,0 ; (return value is nil)
164: blr ; (return)
165:
166: LL0:
167: stw r6, 36(r1) ; save r6
168: addis r6,0,hi16(_messageLock)
169: ori r6,r6,lo16(_messageLock)
170:
171: Lgetit:
172: lwarx r0,0,r6 ; try to get the lock
173: cmpwi cr0,r0,0
174: bne- Lgetit
175: addi r0,0,1
176: sync ; Bugfix for 3.2 and older cpus
177: stwcx. r0,0,r6
178: bne- Lgetit
179: isync
180:
181: lwz r10,isa(r3) ; class = self->isa;
182: lwz r10,cache(r10) ; cache = class->cache
183: lwz r11,mask(r10) ; mask = cache->mask
184: addi r9,r10,buckets ; buckets = cache->buckets
185: and r10,r4,r11 ; index = selector & mask;
186: LL1:
187: slwi r0,r10,2 ;
188: lwzx r7,r9,r0 ; method = cache->buckets[index];
189: cmplwi cr0,r7,0 ; if (method == NULL)
190: beq cr0,LL2 ;
191: addi r10,r10,1 ; index++;
192: lwz r8,method_name(r7) ; name = method->method_name;
193: and r10,r10,r11 ; index &= mask
194: lwz r7,method_imp(r7) ; imp = method->method_imp;
195: cmpw r4,r8 ; if (name != selector)
196: bne cr0,LL1 ; goto loop;
197: mtspr ctr,r7 ;
198: lwz r7, 40(r1) ; restore r7 through r10
199: lwz r8, 44(r1)
200: lwz r9, 48(r1) ;
201: lwz r10,52(r1) ;
202:
203: sync ; release the lock
204: addi r0,0,0
205: stw r0,0(r6)
206: lwz r6,36(r1); ; restore r6
207:
208: Lexit3:
209: bctr ; goto *imp;
210: .space 112 ; /* area for moninitobjc to write */
211: LL2: ;
212: lwz r10,isa(r3) ; class = self->isa;
213:
214: stw r3, 24(r1) ; save the other register parameters
215: stw r4, 28(r1) ;
216: stw r5, 32(r1) ;
217:
218: mflr r0 ; move LR to r0
219: stw r0,8(r1) ; save LR
220: stwu r1,-64(r1) ; grow the stack
221:
222: ori r3,r10,0 ; first arg is the isa pointer
223: bl __class_lookupMethodAndLoadCache
224: mtspr ctr,r3
225: lwz r1,0(r1) ; restore the stack pointer
226:
227: lwz r0,8(r1) ;
228: mtlr r0 ; restore return pc
229: lwz r3, 24(r1) ;
230: lwz r4, 28(r1) ;
231: lwz r5, 32(r1) ;
232:
233: sync ; release the lock
234: addis r6,0,hi16(_messageLock)
235: ori r6,r6,lo16(_messageLock)
236: addi r0,0,0
237: stw r0,0(r6)
238:
239: lwz r6, 36(r1) ;
240: lwz r7, 40(r1) ;
241: lwz r8, 44(r1) ;
242: lwz r9, 48(r1) ;
243: lwz r10,52(r1) ;
244: Lexit4:
245: bctr ; goto *imp;
246: .space 112 ; /* area for moninitobjc to write */
247:
248:
249: receiver = 0
250: class = 4
251:
252: .text
253: .align 2
254: .globl _objc_msgSendSuper
255: _objc_msgSendSuper:
256: stw r7, 40(r1) ; save r7 through r10 for use as temps
257: stw r8, 44(r1)
258: stw r9, 48(r1)
259: stw r10,52(r1)
260:
261: addis r7,0,hi16(__objc_multithread_mask)
262: ori r7,r7,lo16(__objc_multithread_mask)
263: lwz r7,0(r7)
264: cmplwi cr0,r7,0
265: beq cr0,LSL0 ; branch to the "locking" case,
266: ; normal case, id != nil
267: lwz r10,class(r3) ; class = super->class;
268: lwz r10,cache(r10) ; cache = class->cache
269: lwz r11,mask(r10) ; mask = cache->mask
270: addi r9,r10,buckets ; buckets = cache->buckets
271: and r10,r4,r11 ; index = selector & mask;
272: LS1: ;
273: slwi r0,r10,2
274: lwzx r7,r9,r0 ; method = cache->buckets[index];
275: cmplwi cr0,r7,0 ; if (method == NULL)
276: beq cr0,LS2 ;
277: addi r10,r10,1 ; index++;
278: lwz r8,method_name(r7) ; name = method->method_name;
279: and r10,r10,r11 ; index &= mask
280: lwz r7,method_imp(r7) ; imp = method->method_imp;
281: cmpw r4,r8 ; if (name != selector)
282: bne cr0,LS1 ; goto loop;
283: mtspr ctr,r7 ;
284: lwz r7, 40(r1) ; restore r7 through r10
285: lwz r8, 44(r1)
286: lwz r9, 48(r1) ;
287: lwz r10,52(r1) ;
288: lwz r3,receiver(r3) ; restore the receiver
289: Lexit5: bctr ; goto *imp;
290: .space 112 ; /* area for moninitobjc to write */
291: LS2: ;
292: lwz r10,class(r3) ; class = self->class;
293: lwz r3,receiver(r3) ; restore the receiver
294:
295: stw r3, 24(r1) ; save the other register parameters
296: stw r4, 28(r1) ;
297: stw r5, 32(r1) ;
298: stw r6, 36(r1) ;
299:
300: mflr r0 ; save LR
301: stw r0,8(r1) ;
302: stwu r1,-64(r1) ; grow the stack
303:
304: ori r3,r10,0 ; first arg is the isa pointer
305: bl __class_lookupMethodAndLoadCache
306: mtspr ctr,r3
307: lwz r1,0(r1) ; restore the stack pointer
308:
309: lwz r0,8(r1) ;
310: mtlr r0 ; restore return pc
311: lwz r3, 24(r1) ;
312: lwz r4, 28(r1) ;
313: lwz r5, 32(r1) ;
314: lwz r6, 36(r1) ;
315: lwz r7, 40(r1) ;
316: lwz r8, 44(r1) ;
317: lwz r9, 48(r1) ;
318: lwz r10,52(r1) ;
319: Lexit6:
320: bctr ; goto *imp;
321: .space 112 ; /* area for moninitobjc to write */
322:
323: LSL0: ; Locking case for _objc_msgSendSuper
324: stw r6,36(r1) ; save r6
325: addis r6,0,hi16(_messageLock)
326: ori r6,r6,lo16(_messageLock)
327:
328: LSgetit:
329: lwarx r0,0,r6 ; try to get the lock
330: cmpwi cr0,r0,0
331: bne- LSgetit
332: addi r0,0,1
333: sync ; Bugfix for 3.2 and older cpus
334: stwcx. r0,0,r6
335: bne- LSgetit
336: isync
337:
338: lwz r10,class(r3) ; class = super->class;
339: lwz r10,cache(r10) ; cache = class->cache
340: lwz r11,mask(r10) ; mask = cache->mask
341: addi r9,r10,buckets ; buckets = cache->buckets
342: and r10,r4,r11 ; index = selector & mask;
343: LSL1: ;
344: slwi r0,r10,2
345: lwzx r7,r9,r0 ; method = cache->buckets[index];
346: cmplwi cr0,r7,0 ; if (method == NULL)
347: beq cr0,LSL2 ;
348: addi r10,r10,1 ; index++;
349: lwz r8,method_name(r7) ; name = method->method_name;
350: and r10,r10,r11 ; index &= mask
351: lwz r7,method_imp(r7) ; imp = method->method_imp;
352: cmpw r4,r8 ; if (name != selector)
353: bne cr0,LSL1 ; goto loop;
354: mtspr ctr,r7 ;
355: lwz r7, 40(r1) ; restore r7 through r10
356: lwz r8, 44(r1) ;
357: lwz r9, 48(r1) ;
358: lwz r10,52(r1) ;
359:
360: sync ; release the lock
361: addi r0,0,0
362: stw r0,0(r6)
363: lwz r6,36(r1); ; restore r6
364: lwz r3,receiver(r3) ; r3 = self
365:
366: Lexit7:
367: bctr ; goto *imp;
368: .space 112 ; /* area for moninitobjc to write */
369: LSL2: ;
370: lwz r10,class(r3) ; class = self->class;
371: lwz r3,receiver(r3) ; r3 = self for implementation
372:
373: stw r3, 24(r1) ; save the other register parameters
374: stw r4, 28(r1) ;
375: stw r5, 32(r1) ;
376:
377: mflr r0 ; save LR
378: stw r0,8(r1) ;
379: stwu r1,-64(r1) ; grow the stack
380:
381: ori r3,r10,0 ; first arg is the isa pointer
382: bl __class_lookupMethodAndLoadCache
383: mtspr ctr,r3
384: lwz r1,0(r1) ; restore the stack pointer
385:
386: lwz r0,8(r1) ;
387: mtlr r0 ; restore return pc
388: lwz r3, 24(r1) ;
389: lwz r4, 28(r1) ;
390: lwz r5, 32(r1) ;
391:
392: sync ; release the lock
393: addis r6,0,hi16(_messageLock)
394: ori r6,r6,lo16(_messageLock)
395: addi r0,0,0
396: stw r0,0(r6)
397:
398: lwz r6, 36(r1) ;
399: lwz r7, 40(r1) ;
400: lwz r8, 44(r1) ;
401: lwz r9, 48(r1) ;
402: lwz r10,52(r1) ;
403: Lexit8:
404: bctr ; goto *imp;
405: .space 112 ; /* area for moninitobjc to write */
406:
407:
408: ;--------------------------------------------------------------------
409: ;
410: ; _objc_msgSend_stret is the [Apple/Rhapsody] PowerPC struct-return
411: ; version. The ABI calls for r3 to be used as the address of
412: ; the structure being returned; and the other args are in the
413: ; next couple of registers.
414: ;
415: ; This is a pasted copy of _objc_msgSend above, mutatis mutandis.
416: ;
417: ;
418: ; On entry: r3 is the address in which the returned struct is put,
419: ; r4 is the message receiver,
420: ; r5 is the selector
421: ;
422: .text
423: .align 2
424: .globl _objc_msgSend_stret
425: _objc_msgSend_stret:
426: stw r7, 40(r1) ; save r7 through r10 for use as temps
427: stw r8, 44(r1)
428: stw r9, 48(r1)
429: stw r10,52(r1)
430:
431: addis r7,0,hi16(__objc_multithread_mask)
432: ori r7,r7,lo16(__objc_multithread_mask)
433: lwz r7,0(r7)
434: and. r7,r4,r7
435: bne cr0,LR0 ; branch to the "normal" case,
436: ; no locking, id != nil
437:
438: cmplwi cr0,r4,0 ; if id == nil
439: bne cr0,LRL0 ; LRL0 is the "locking" case
440: b LR3 ; LR3 is the return nil case
441: LR0:
442: lwz r10,isa(r4) ; class = self->isa;
443: lwz r10,cache(r10) ; cache = class->cache
444: lwz r11,mask(r10) ; mask = cache->mask
445: addi r9,r10,buckets ; buckets = cache->buckets
446: and r10,r5,r11 ; index = selector & mask;
447: LR1:
448: slwi r0,r10,2 ;
449: lwzx r7,r9,r0 ; method = cache->buckets[index];
450: cmplwi cr0,r7,0 ; if (method == NULL)
451: beq cr0,LR2 ;
452: addi r10,r10,1 ; index++;
453: lwz r8,method_name(r7) ; name = method->method_name;
454: and r10,r10,r11 ; index &= mask
455: lwz r7,method_imp(r7) ; imp = method->method_imp;
456: cmpw r5,r8 ; if (name != selector)
457: bne cr0,LR1 ; goto loop;
458: mtspr ctr,r7 ;
459: lwz r7, 40(r1) ; restore r7 through r10
460: lwz r8, 44(r1)
461: lwz r9, 48(r1) ;
462: lwz r10,52(r1) ;
463: LRexit1:
464: bctr ; goto *imp;
465: .space 112 ; /* area for moninitobjc to write */
466: LR2: ;
467: lwz r10,isa(r4) ; class = self->isa;
468:
469: stw r3, 24(r1) ; save the other register parameters
470: stw r4, 28(r1) ;
471: stw r5, 32(r1) ;
472: stw r6, 36(r1) ;
473:
474: mflr r0 ; save LR
475: stw r0,8(r1) ;
476: stwu r1,-64(r1) ; grow the stack
477:
478: ori r3,r10,0 ; first arg is the isa pointer
479: ori r4,r5,0 ; second arg is the selector
480: bl __class_lookupMethodAndLoadCache
481: mtspr ctr,r3
482: lwz r1,0(r1) ; restore the stack pointer
483:
484: lwz r0,8(r1) ;
485: mtlr r0 ; restore return pc
486: lwz r3, 24(r1) ;
487: lwz r4, 28(r1) ;
488: lwz r5, 32(r1) ;
489: lwz r6, 36(r1) ;
490: lwz r7, 40(r1) ;
491: lwz r8, 44(r1) ;
492: lwz r9, 48(r1) ;
493: lwz r10,52(r1) ;
494: LRexit2:
495: bctr ; goto *imp;
496: .space 112 ; /* area for moninitobjc to write */
497: LR3: ;
498: addi r3,0,0 ; (return value is nil)
499: blr ; (return)
500:
501: LRL0:
502: stw r6, 36(r1) ; save r6
503: addis r6,0,hi16(_messageLock)
504: ori r6,r6,lo16(_messageLock)
505:
506: LRgetit:
507: lwarx r0,0,r6 ; try to get the lock
508: cmpwi cr0,r0,0
509: bne- LRgetit
510: addi r0,0,1
511: sync ; Bugfix for 3.2 and older cpus
512: stwcx. r0,0,r6
513: bne- LRgetit
514: isync
515:
516: lwz r10,isa(r4) ; class = self->isa;
517: lwz r10,cache(r10) ; cache = class->cache
518: lwz r11,mask(r10) ; mask = cache->mask
519: addi r9,r10,buckets ; buckets = cache->buckets
520: and r10,r5,r11 ; index = selector & mask;
521: LRL1:
522: slwi r0,r10,2 ;
523: lwzx r7,r9,r0 ; method = cache->buckets[index];
524: cmplwi cr0,r7,0 ; if (method == NULL)
525: beq cr0,LRL2 ;
526: addi r10,r10,1 ; index++;
527: lwz r8,method_name(r7) ; name = method->method_name;
528: and r10,r10,r11 ; index &= mask
529: lwz r7,method_imp(r7) ; imp = method->method_imp;
530: cmpw r5,r8 ; if (name != selector)
531: bne cr0,LRL1 ; goto loop;
532: mtspr ctr,r7 ;
533: lwz r7, 40(r1) ; restore r7 through r10
534: lwz r8, 44(r1)
535: lwz r9, 48(r1) ;
536: lwz r10,52(r1) ;
537:
538: sync ; release the lock
539: addi r0,0,0
540: stw r0,0(r6)
541: lwz r6,36(r1); ; restore r6
542:
543: LRexit3:
544: bctr ; goto *imp;
545: .space 112 ; /* area for moninitobjc to write */
546: LRL2: ;
547: lwz r10,isa(r4) ; class = self->isa;
548:
549: stw r3, 24(r1) ; save the other register parameters
550: stw r4, 28(r1) ;
551: stw r5, 32(r1) ;
552:
553: mflr r0 ; save LR
554: stw r0,8(r1) ;
555: stwu r1,-64(r1) ; grow the stack
556:
557: ori r3,r10,0 ; first arg is the isa pointer
558: ori r4,r5,0 ; second arg is the selector
559: bl __class_lookupMethodAndLoadCache
560: mtspr ctr,r3
561: lwz r1,0(r1) ; restore the stack pointer
562:
563: lwz r0,8(r1) ;
564: mtlr r0 ; restore return pc
565: lwz r3, 24(r1) ;
566: lwz r4, 28(r1) ;
567: lwz r5, 32(r1) ;
568:
569: sync ; release the lock
570: addis r6,0,hi16(_messageLock)
571: ori r6,r6,lo16(_messageLock)
572: addi r0,0,0
573: stw r0,0(r6)
574:
575: lwz r6, 36(r1) ;
576: lwz r7, 40(r1) ;
577: lwz r8, 44(r1) ;
578: lwz r9, 48(r1) ;
579: lwz r10,52(r1) ;
580: LRexit4:
581: bctr ; goto *imp;
582: .space 112 ; /* area for moninitobjc to write */
583:
584:
585: .text
586: .align 2
587: .globl _objc_msgSendSuper_stret
588: _objc_msgSendSuper_stret:
589: stw r7, 40(r1) ; save r7 through r10 for use as temps
590: stw r8, 44(r1)
591: stw r9, 48(r1)
592: stw r10,52(r1)
593:
594: addis r7,0,hi16(__objc_multithread_mask)
595: ori r7,r7,lo16(__objc_multithread_mask)
596: lwz r7,0(r7)
597: cmplwi cr0,r7,0
598: beq cr0,LRSL0 ; branch to the "locking" case
599: ; "normal" case, no locking, id != nil
600: lwz r10,class(r4) ; class = super->class;
601: lwz r10,cache(r10) ; cache = class->cache
602: lwz r11,mask(r10) ; mask = cache->mask
603: addi r9,r10,buckets ; buckets = cache->buckets
604: and r10,r5,r11 ; index = selector & mask;
605: LRS1: ;
606: slwi r0,r10,2
607: lwzx r7,r9,r0 ; method = cache->buckets[index];
608: cmplwi cr0,r7,0 ; if (method == NULL)
609: beq cr0,LRS2 ;
610: addi r10,r10,1 ; index++;
611: lwz r8,method_name(r7) ; name = method->method_name;
612: and r10,r10,r11 ; index &= mask
613: lwz r7,method_imp(r7) ; imp = method->method_imp;
614: cmpw r5,r8 ; if (name != selector)
615: bne cr0,LRS1 ; goto loop;
616: mtspr ctr,r7 ;
617: lwz r7, 40(r1) ; restore r7 through r10
618: lwz r8, 44(r1)
619: lwz r9, 48(r1) ;
620: lwz r10,52(r1) ;
621: lwz r4,receiver(r4) ; restore the receiver
622: LRexit5:
623: bctr ; goto *imp;
624: .space 112 ; /* area for moninitobjc to write */
625: LRS2: ;
626: lwz r10,class(r4) ; class = self->class;
627: lwz r4,receiver(r4) ; restore the receiver
628:
629: stw r3, 24(r1) ; save the other register parameters
630: stw r4, 28(r1) ;
631: stw r5, 32(r1) ;
632: stw r6, 36(r1) ;
633:
634: mflr r0 ; save LR
635: stw r0,8(r1) ;
636: stwu r1,-64(r1) ; grow the stack
637:
638: ori r3,r10,0 ; first arg is the isa pointer
639: ori r4,r5,0 ; second arg is the selector
640: bl __class_lookupMethodAndLoadCache
641: mtspr ctr,r3
642: lwz r1,0(r1) ; restore the stack pointer
643:
644: lwz r0,8(r1) ;
645: mtlr r0 ; restore return pc
646: lwz r3, 24(r1) ;
647: lwz r4, 28(r1) ;
648: lwz r5, 32(r1) ;
649: lwz r6, 36(r1) ;
650: lwz r7, 40(r1) ;
651: lwz r8, 44(r1) ;
652: lwz r9, 48(r1) ;
653: lwz r10,52(r1) ;
654: LRexit6:
655: bctr ; goto *imp;
656: .space 112 ; /* area for moninitobjc to write */
657:
658: LRSL0: ; Locking case _objc_msgSendSuper_stret
659: stw r6,36(r1) ; save r6
660: addis r6,0,hi16(_messageLock)
661: ori r6,r6,lo16(_messageLock)
662:
663: LRSgetit:
664: lwarx r0,0,r6 ; try to get the lock
665: cmpwi cr0,r0,0
666: bne- LRSgetit
667: addi r0,0,1
668: sync ; Bugfix for 3.2 and older cpus
669: stwcx. r0,0,r6
670: bne- LRSgetit
671: isync
672:
673: lwz r10,class(r4) ; class = super->class;
674: lwz r10,cache(r10) ; cache = class->cache
675: lwz r11,mask(r10) ; mask = cache->mask
676: addi r9,r10,buckets ; buckets = cache->buckets
677: and r10,r5,r11 ; index = selector & mask;
678: LRSL1: ;
679: slwi r0,r10,2
680: lwzx r7,r9,r0 ; method = cache->buckets[index];
681: cmplwi cr0,r7,0 ; if (method == NULL)
682: beq cr0,LRSL2 ;
683: addi r10,r10,1 ; index++;
684: lwz r8,method_name(r7) ; name = method->method_name;
685: and r10,r10,r11 ; index &= mask
686: lwz r7,method_imp(r7) ; imp = method->method_imp;
687: cmpw r5,r8 ; if (name != selector)
688: bne cr0,LRSL1 ; goto loop;
689: mtspr ctr,r7 ;
690: lwz r7, 40(r1) ; restore r7 through r10
691: lwz r8, 44(r1) ;
692: lwz r9, 48(r1) ;
693: lwz r10,52(r1) ;
694:
695: sync ; release the lock
696: addi r0,0,0
697: stw r0,0(r6)
698: lwz r6,36(r1); ; restore r6
699: lwz r4,receiver(r4) ; r4 = self for implementation
700:
701: LRexit7:
702: bctr ; goto *imp;
703: .space 112 ; /* area for moninitobjc to write */
704: LRSL2: ;
705: lwz r10,class(r4) ; class = super->class;
706: lwz r4,receiver(r4) ; r4 = self for implementation
707:
708: stw r3, 24(r1) ; save the other register parameters
709: stw r4, 28(r1) ;
710: stw r5, 32(r1) ;
711:
712: mflr r0 ; save LR
713: stw r0,8(r1) ;
714: stwu r1,-64(r1) ; grow the stack
715:
716: ori r3,r10,0 ; first arg is the isa pointer
717: ori r4,r5,0 ; second arg is the selector
718: bl __class_lookupMethodAndLoadCache
719: mtspr ctr,r3
720: lwz r1,0(r1) ; restore the stack pointer
721:
722: lwz r0,8(r1) ;
723: lwz r3, 24(r1) ;
724: lwz r4, 28(r1) ;
725: lwz r5, 32(r1) ;
726:
727: sync ; release the lock
728: addis r6,0,hi16(_messageLock)
729: ori r6,r6,lo16(_messageLock)
730: addi r0,0,0
731: stw r0,0(r6)
732:
733: lwz r6, 36(r1) ;
734: lwz r7, 40(r1) ;
735: lwz r8, 44(r1) ;
736: lwz r9, 48(r1) ;
737: lwz r10,52(r1) ;
738: LRexit8:
739: bctr ; goto *imp;
740: .space 112 ; /* area for moninitobjc to write */
741:
742: ;
743: ; End of code duplicated for struct-returns
744: ;--------------------------------------------------------------------
745:
746: # Location L30 contains the string forward::
747: # Location L31 contains a pointer to L30, that can be changed
748: # to point to another forward:: string for selector uniquing
749: # purposes. ALWAYS dereference L31 to get to forward:: !!
750: .objc_meth_var_names
751: .align 1
752: L30: .ascii "forward::\0"
753:
754: .objc_message_refs
755: .align 2
756: L31: .long L30
757:
758: .cstring
759: .align 1
760: L32: .ascii "Does not recognize selector %s\0"
761:
762: .text
763: .align 2
764: .globl __objc_msgForward
765: __objc_msgForward:
766: #if defined(KERNEL)
767: trap ; this code isnt ready yet!!!!!!!!!!!
768: #else
769: addis r11,0,hi16(L31) ;
770: addi r11,r11,lo16(L31) ;
771: cmpw cr0,r11,r4 ; if (sel == @selector (forward::))
772: bne L_error ;
773:
774: stw r3, 24(r1) ; home the register arguments, is there a "float" problem?
775: stw r4, 28(r1)
776: stw r5, 32(r1)
777: stw r6, 36(r1)
778: stw r7, 40(r1)
779: stw r8, 44(r1)
780: stw r9, 48(r1)
781: stw r10,52(r1)
782: ; (first arg remains self)
783: addis r4,0,hi16(L30) ; (second arg is "forward:")
784: addi r4,r4,lo16(L30)
785: andi. r5,r4,0 ; (third arg is previous selector)
786: addi r6,r1,24 ; (forth arg is &self)
787:
788: addi r1,r1,64 ; (grow the stack)
789: bl _objc_msgSend ; [self forward: sel : &self]
790: addi r1,r1,-64 ; (deallocate storage)
791: blr ; return
792: L_error:
793: addis r4,0,hi16(L32)
794: addi r4,r4,lo16(L32)
795: addis r5,0,hi16(L30)
796: addi r5,r5,lo16(L30)
797: bl ___objc_error ;
798: #endif /* ! KERNEL */
799:
800: .text
801: .align 2
802: .globl _objc_msgSendv
803: _objc_msgSendv:
804: #if defined(KERNEL)
805: trap ; this code isnt ready yet!!!!!!!!!!!
806: #else
807: mflr r0
808: stw r0,8(r1) ; (save return pc)
809: addi r1,r1,32 ; (allocate storage)
810:
811: cmpwi cr0,r5,0
812: bgt cr0,L34 ; if (size > 0) ...
813:
814: lwz r10,28(r6) ; (restore some of the args)
815: lwz r9, 24(r6)
816: lwz r8, 20(r6)
817: lwz r7, 16(r6)
818: lwz r1,0(r1) ; restore stack pointer
819: lwz r0,8(r1) ; restore return pc
820:
821: bl _objc_msgSend ; objc_msgSend (self, selector, ...)
822:
823: subi r31,r30,32 ; (deallocate variable storage)
824: addi r31,r31,16 ; (deallocate storage)
825: lwz r0,8(r1)
826: mtlr r0
827: blr ; return
828: #endif /* ! KERNEL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.