]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-arm.s
objc4-706.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-arm.s
1 /*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 1999-2007 Apple Computer, Inc. All Rights Reserved.
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /********************************************************************
24 *
25 * objc-msg-arm.s - ARM code to support objc messaging
26 *
27 ********************************************************************/
28
29 #ifdef __arm__
30
31 #include <arm/arch.h>
32
33 #ifndef _ARM_ARCH_7
34 # error requires armv7
35 #endif
36
37 // Set FP=1 on architectures that pass parameters in floating-point registers
38 #if __ARM_ARCH_7K__
39 # define FP 1
40 #else
41 # define FP 0
42 #endif
43
44 #if FP
45
46 # if !__ARM_NEON__
47 # error sorry
48 # endif
49
50 # define FP_RETURN_ZERO \
51 vmov.i32 q0, #0 ; \
52 vmov.i32 q1, #0 ; \
53 vmov.i32 q2, #0 ; \
54 vmov.i32 q3, #0
55
56 # define FP_SAVE \
57 vpush {q0-q3}
58
59 # define FP_RESTORE \
60 vpop {q0-q3}
61
62 #else
63
64 # define FP_RETURN_ZERO
65 # define FP_SAVE
66 # define FP_RESTORE
67
68 #endif
69
70 // Define SUPPORT_INDEXED_ISA for targets which store the class in the ISA as
71 // an index in to a class table.
72 // Note, keep this in sync with objc-config.h.
73 // FIXME: Remove this duplication. We should get this from objc-config.h.
74 #if __ARM_ARCH_7K__ >= 2
75 # define SUPPORT_INDEXED_ISA 1
76 #else
77 # define SUPPORT_INDEXED_ISA 0
78 #endif
79
80 // Note, keep these in sync with objc-private.h
81 #define ISA_INDEX_IS_NPI 1
82 #define ISA_INDEX_MASK 0x0001FFFC
83 #define ISA_INDEX_SHIFT 2
84 #define ISA_INDEX_BITS 15
85 #define ISA_INDEX_COUNT (1 << ISA_INDEX_BITS)
86 #define ISA_INDEX_MAGIC_MASK 0x001E0001
87 #define ISA_INDEX_MAGIC_VALUE 0x001C0001
88
89 .syntax unified
90
91 #define MI_EXTERN(var) \
92 .non_lazy_symbol_pointer ;\
93 L##var##$$non_lazy_ptr: ;\
94 .indirect_symbol var ;\
95 .long 0
96
97 #define MI_GET_EXTERN(reg,var) \
98 movw reg, :lower16:(L##var##$$non_lazy_ptr-7f-4) ;\
99 movt reg, :upper16:(L##var##$$non_lazy_ptr-7f-4) ;\
100 7: add reg, pc ;\
101 ldr reg, [reg]
102
103 #define MI_GET_ADDRESS(reg,var) \
104 movw reg, :lower16:(var-7f-4) ;\
105 movt reg, :upper16:(var-7f-4) ;\
106 7: add reg, pc ;\
107
108
109 .data
110
111 #if SUPPORT_INDEXED_ISA
112
113 .align 2
114 .globl _objc_indexed_classes
115 _objc_indexed_classes:
116 .fill ISA_INDEX_COUNT, 4, 0
117
118 #endif
119
120
121
122 // _objc_entryPoints and _objc_exitPoints are used by method dispatch
123 // caching code to figure out whether any threads are actively
124 // in the cache for dispatching. The labels surround the asm code
125 // that do cache lookups. The tables are zero-terminated.
126
127 .align 2
128 .private_extern _objc_entryPoints
129 _objc_entryPoints:
130 .long _cache_getImp
131 .long _objc_msgSend
132 .long _objc_msgSend_stret
133 .long _objc_msgSendSuper
134 .long _objc_msgSendSuper_stret
135 .long _objc_msgSendSuper2
136 .long _objc_msgSendSuper2_stret
137 .long _objc_msgLookup
138 .long _objc_msgLookup_stret
139 .long _objc_msgLookupSuper2
140 .long _objc_msgLookupSuper2_stret
141 .long 0
142
143 .private_extern _objc_exitPoints
144 _objc_exitPoints:
145 .long LExit_cache_getImp
146 .long LExit_objc_msgSend
147 .long LExit_objc_msgSend_stret
148 .long LExit_objc_msgSendSuper
149 .long LExit_objc_msgSendSuper_stret
150 .long LExit_objc_msgSendSuper2
151 .long LExit_objc_msgSendSuper2_stret
152 .long LExit_objc_msgLookup
153 .long LExit_objc_msgLookup_stret
154 .long LExit_objc_msgLookupSuper2
155 .long LExit_objc_msgLookupSuper2_stret
156 .long 0
157
158
159 /********************************************************************
160 * List every exit insn from every messenger for debugger use.
161 * Format:
162 * (
163 * 1 word instruction's address
164 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
165 * )
166 * 1 word zero
167 *
168 * ENTER is the start of a dispatcher
169 * FAST_EXIT is method dispatch
170 * SLOW_EXIT is uncached method lookup
171 * NIL_EXIT is returning zero from a message sent to nil
172 * These must match objc-gdb.h.
173 ********************************************************************/
174
175 #define ENTER 1
176 #define FAST_EXIT 2
177 #define SLOW_EXIT 3
178 #define NIL_EXIT 4
179
180 .section __DATA,__objc_msg_break
181 .globl _gdb_objc_messenger_breakpoints
182 _gdb_objc_messenger_breakpoints:
183 // contents populated by the macros below
184
185 .macro MESSENGER_START
186 7:
187 .section __DATA,__objc_msg_break
188 .long 7b
189 .long ENTER
190 .text
191 .endmacro
192 .macro MESSENGER_END_FAST
193 7:
194 .section __DATA,__objc_msg_break
195 .long 7b
196 .long FAST_EXIT
197 .text
198 .endmacro
199 .macro MESSENGER_END_SLOW
200 7:
201 .section __DATA,__objc_msg_break
202 .long 7b
203 .long SLOW_EXIT
204 .text
205 .endmacro
206 .macro MESSENGER_END_NIL
207 7:
208 .section __DATA,__objc_msg_break
209 .long 7b
210 .long NIL_EXIT
211 .text
212 .endmacro
213
214
215 /********************************************************************
216 * Names for relative labels
217 * DO NOT USE THESE LABELS ELSEWHERE
218 * Reserved labels: 6: 7: 8: 9:
219 ********************************************************************/
220 // 6: used by CacheLookup
221 // 7: used by MI_GET_ADDRESS etc and MESSENGER_START etc
222 // 8: used by CacheLookup
223 #define LNilReceiver 9
224 #define LNilReceiver_f 9f
225 #define LNilReceiver_b 9b
226
227
228 /********************************************************************
229 * Macro parameters
230 ********************************************************************/
231
232 #define NORMAL 0
233 #define STRET 1
234
235
236 /********************************************************************
237 *
238 * Structure definitions.
239 *
240 ********************************************************************/
241
242 /* objc_super parameter to sendSuper */
243 #define RECEIVER 0
244 #define CLASS 4
245
246 /* Selected field offsets in class structure */
247 #define ISA 0
248 #define SUPERCLASS 4
249 #define CACHE 8
250 #define CACHE_MASK 12
251
252 /* Selected field offsets in method structure */
253 #define METHOD_NAME 0
254 #define METHOD_TYPES 4
255 #define METHOD_IMP 8
256
257
258 //////////////////////////////////////////////////////////////////////
259 //
260 // ENTRY functionName
261 //
262 // Assembly directives to begin an exported function.
263 //
264 // Takes: functionName - name of the exported function
265 //////////////////////////////////////////////////////////////////////
266
267 .macro ENTRY /* name */
268 .text
269 .thumb
270 .align 5
271 .globl $0
272 .thumb_func
273 $0:
274 .endmacro
275
276 .macro STATIC_ENTRY /*name*/
277 .text
278 .thumb
279 .align 5
280 .private_extern $0
281 .thumb_func
282 $0:
283 .endmacro
284
285
286 //////////////////////////////////////////////////////////////////////
287 //
288 // END_ENTRY functionName
289 //
290 // Assembly directives to end an exported function. Just a placeholder,
291 // a close-parenthesis for ENTRY, until it is needed for something.
292 //
293 // Takes: functionName - name of the exported function
294 //////////////////////////////////////////////////////////////////////
295
296 .macro END_ENTRY /* name */
297 LExit$0:
298 .endmacro
299
300
301 /////////////////////////////////////////////////////////////////////
302 //
303 // CacheLookup NORMAL|STRET
304 // CacheLookup2 NORMAL|STRET
305 //
306 // Locate the implementation for a selector in a class's method cache.
307 //
308 // Takes:
309 // $0 = NORMAL, STRET
310 // r0 or r1 (STRET) = receiver
311 // r1 or r2 (STRET) = selector
312 // r9 = class to search in
313 //
314 // On exit: r9 clobbered
315 // (found) continues after CacheLookup, IMP in r12, eq set
316 // (not found) continues after CacheLookup2
317 //
318 /////////////////////////////////////////////////////////////////////
319
320 .macro CacheLookup
321
322 ldrh r12, [r9, #CACHE_MASK] // r12 = mask
323 ldr r9, [r9, #CACHE] // r9 = buckets
324 .if $0 == STRET
325 and r12, r12, r2 // r12 = index = SEL & mask
326 .else
327 and r12, r12, r1 // r12 = index = SEL & mask
328 .endif
329 add r9, r9, r12, LSL #3 // r9 = bucket = buckets+index*8
330 ldr r12, [r9] // r12 = bucket->sel
331 6:
332 .if $0 == STRET
333 teq r12, r2
334 .else
335 teq r12, r1
336 .endif
337 bne 8f
338 ldr r12, [r9, #4] // r12 = bucket->imp
339
340 .if $0 == STRET
341 tst r12, r12 // set ne for stret forwarding
342 .else
343 // eq already set for nonstret forwarding by `teq` above
344 .endif
345
346 .endmacro
347
348 .macro CacheLookup2
349
350 8:
351 cmp r12, #1
352 blo 8f // if (bucket->sel == 0) cache miss
353 it eq // if (bucket->sel == 1) cache wrap
354 ldreq r9, [r9, #4] // bucket->imp is before first bucket
355 ldr r12, [r9, #8]! // r12 = (++bucket)->sel
356 b 6b
357 8:
358
359 .endmacro
360
361 /////////////////////////////////////////////////////////////////////
362 //
363 // GetClassFromIsa return-type
364 //
365 // Given an Isa, return the class for the Isa.
366 //
367 // Takes:
368 // r9 = class
369 //
370 // On exit: r12 clobbered
371 // r9 contains the class for this Isa.
372 //
373 /////////////////////////////////////////////////////////////////////
374 .macro GetClassFromIsa
375
376 #if SUPPORT_INDEXED_ISA
377 // Note: We are doing a little wasted work here to load values we might not
378 // need. Branching turns out to be even worse when performance was measured.
379 MI_GET_ADDRESS(r12, _objc_indexed_classes)
380 tst.w r9, #ISA_INDEX_IS_NPI
381 itt ne
382 ubfxne r9, r9, #ISA_INDEX_SHIFT, #ISA_INDEX_BITS
383 ldrne.w r9, [r12, r9, lsl #2]
384 #endif
385
386 .endmacro
387
388
389 /********************************************************************
390 * IMP cache_getImp(Class cls, SEL sel)
391 *
392 * On entry: r0 = class whose cache is to be searched
393 * r1 = selector to search for
394 *
395 * If found, returns method implementation.
396 * If not found, returns NULL.
397 ********************************************************************/
398
399 STATIC_ENTRY _cache_getImp
400
401 mov r9, r0
402 CacheLookup NORMAL
403 // cache hit, IMP in r12
404 mov r0, r12
405 bx lr // return imp
406
407 CacheLookup2 GETIMP
408 // cache miss, return nil
409 mov r0, #0
410 bx lr
411
412 END_ENTRY _cache_getImp
413
414
415 /********************************************************************
416 *
417 * id objc_msgSend(id self, SEL _cmd, ...);
418 * IMP objc_msgLookup(id self, SEL _cmd, ...);
419 *
420 * objc_msgLookup ABI:
421 * IMP returned in r12
422 * Forwarding returned in Z flag
423 * r9 reserved for our use but not used
424 *
425 ********************************************************************/
426
427 ENTRY _objc_msgSend
428 MESSENGER_START
429
430 cbz r0, LNilReceiver_f
431
432 ldr r9, [r0] // r9 = self->isa
433 GetClassFromIsa // r9 = class
434 CacheLookup NORMAL
435 // cache hit, IMP in r12, eq already set for nonstret forwarding
436 MESSENGER_END_FAST
437 bx r12 // call imp
438
439 CacheLookup2 NORMAL
440 // cache miss
441 ldr r9, [r0] // r9 = self->isa
442 GetClassFromIsa // r9 = class
443 MESSENGER_END_SLOW
444 b __objc_msgSend_uncached
445
446 LNilReceiver:
447 // r0 is already zero
448 mov r1, #0
449 mov r2, #0
450 mov r3, #0
451 FP_RETURN_ZERO
452 MESSENGER_END_NIL
453 bx lr
454
455 END_ENTRY _objc_msgSend
456
457
458 ENTRY _objc_msgLookup
459
460 cbz r0, LNilReceiver_f
461
462 ldr r9, [r0] // r9 = self->isa
463 GetClassFromIsa // r9 = class
464 CacheLookup NORMAL
465 // cache hit, IMP in r12, eq already set for nonstret forwarding
466 bx lr
467
468 CacheLookup2 NORMAL
469 // cache miss
470 ldr r9, [r0] // r9 = self->isa
471 GetClassFromIsa // r9 = class
472 b __objc_msgLookup_uncached
473
474 LNilReceiver:
475 MI_GET_ADDRESS(r12, __objc_msgNil)
476 bx lr
477
478 END_ENTRY _objc_msgLookup
479
480
481 STATIC_ENTRY __objc_msgNil
482
483 // r0 is already zero
484 mov r1, #0
485 mov r2, #0
486 mov r3, #0
487 FP_RETURN_ZERO
488 bx lr
489
490 END_ENTRY __objc_msgNil
491
492
493 /********************************************************************
494 * void objc_msgSend_stret(void *st_addr, id self, SEL op, ...);
495 * IMP objc_msgLookup_stret(void *st_addr, id self, SEL op, ...);
496 *
497 * objc_msgSend_stret is the struct-return form of msgSend.
498 * The ABI calls for r0 to be used as the address of the structure
499 * being returned, with the parameters in the succeeding registers.
500 *
501 * On entry: r0 is the address where the structure is returned,
502 * r1 is the message receiver,
503 * r2 is the selector
504 ********************************************************************/
505
506 ENTRY _objc_msgSend_stret
507 MESSENGER_START
508
509 cbz r1, LNilReceiver_f
510
511 ldr r9, [r1] // r9 = self->isa
512 GetClassFromIsa // r9 = class
513 CacheLookup STRET
514 // cache hit, IMP in r12, ne already set for stret forwarding
515 MESSENGER_END_FAST
516 bx r12
517
518 CacheLookup2 STRET
519 // cache miss
520 ldr r9, [r1] // r9 = self->isa
521 GetClassFromIsa // r9 = class
522 MESSENGER_END_SLOW
523 b __objc_msgSend_stret_uncached
524
525 LNilReceiver:
526 MESSENGER_END_NIL
527 bx lr
528
529 END_ENTRY _objc_msgSend_stret
530
531
532 ENTRY _objc_msgLookup_stret
533
534 cbz r1, LNilReceiver_f
535
536 ldr r9, [r1] // r9 = self->isa
537 GetClassFromIsa // r9 = class
538 CacheLookup STRET
539 // cache hit, IMP in r12, ne already set for stret forwarding
540 bx lr
541
542 CacheLookup2 STRET
543 // cache miss
544 ldr r9, [r1] // r9 = self->isa
545 GetClassFromIsa // r9 = class
546 b __objc_msgLookup_stret_uncached
547
548 LNilReceiver:
549 MI_GET_ADDRESS(r12, __objc_msgNil_stret)
550 bx lr
551
552 END_ENTRY _objc_msgLookup_stret
553
554
555 STATIC_ENTRY __objc_msgNil_stret
556
557 bx lr
558
559 END_ENTRY __objc_msgNil_stret
560
561
562 /********************************************************************
563 * id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
564 *
565 * struct objc_super {
566 * id receiver;
567 * Class cls; // the class to search
568 * }
569 ********************************************************************/
570
571 ENTRY _objc_msgSendSuper
572 MESSENGER_START
573
574 ldr r9, [r0, #CLASS] // r9 = struct super->class
575 CacheLookup NORMAL
576 // cache hit, IMP in r12, eq already set for nonstret forwarding
577 ldr r0, [r0, #RECEIVER] // load real receiver
578 MESSENGER_END_FAST
579 bx r12 // call imp
580
581 CacheLookup2 NORMAL
582 // cache miss
583 ldr r9, [r0, #CLASS] // r9 = struct super->class
584 ldr r0, [r0, #RECEIVER] // load real receiver
585 MESSENGER_END_SLOW
586 b __objc_msgSend_uncached
587
588 END_ENTRY _objc_msgSendSuper
589
590
591 /********************************************************************
592 * id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
593 *
594 * struct objc_super {
595 * id receiver;
596 * Class cls; // SUBCLASS of the class to search
597 * }
598 ********************************************************************/
599
600 ENTRY _objc_msgSendSuper2
601 MESSENGER_START
602
603 ldr r9, [r0, #CLASS] // class = struct super->class
604 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
605 CacheLookup NORMAL
606 // cache hit, IMP in r12, eq already set for nonstret forwarding
607 ldr r0, [r0, #RECEIVER] // load real receiver
608 MESSENGER_END_FAST
609 bx r12 // call imp
610
611 CacheLookup2 NORMAL
612 // cache miss
613 ldr r9, [r0, #CLASS] // class = struct super->class
614 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
615 ldr r0, [r0, #RECEIVER] // load real receiver
616 MESSENGER_END_SLOW
617 b __objc_msgSend_uncached
618
619 END_ENTRY _objc_msgSendSuper2
620
621
622 ENTRY _objc_msgLookupSuper2
623
624 ldr r9, [r0, #CLASS] // class = struct super->class
625 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
626 CacheLookup NORMAL
627 // cache hit, IMP in r12, eq already set for nonstret forwarding
628 ldr r0, [r0, #RECEIVER] // load real receiver
629 bx lr
630
631 CacheLookup2 NORMAL
632 // cache miss
633 ldr r9, [r0, #CLASS]
634 ldr r9, [r9, #SUPERCLASS] // r9 = class to search
635 ldr r0, [r0, #RECEIVER] // load real receiver
636 b __objc_msgLookup_uncached
637
638 END_ENTRY _objc_msgLookupSuper2
639
640
641 /********************************************************************
642 * void objc_msgSendSuper_stret(void *st_addr, objc_super *self, SEL op, ...);
643 *
644 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
645 * The ABI calls for r0 to be used as the address of the structure
646 * being returned, with the parameters in the succeeding registers.
647 *
648 * On entry: r0 is the address where the structure is returned,
649 * r1 is the address of the objc_super structure,
650 * r2 is the selector
651 ********************************************************************/
652
653 ENTRY _objc_msgSendSuper_stret
654 MESSENGER_START
655
656 ldr r9, [r1, #CLASS] // r9 = struct super->class
657 CacheLookup STRET
658 // cache hit, IMP in r12, ne already set for stret forwarding
659 ldr r1, [r1, #RECEIVER] // load real receiver
660 MESSENGER_END_FAST
661 bx r12 // call imp
662
663 CacheLookup2 STRET
664 // cache miss
665 ldr r9, [r1, #CLASS] // r9 = struct super->class
666 ldr r1, [r1, #RECEIVER] // load real receiver
667 MESSENGER_END_SLOW
668 b __objc_msgSend_stret_uncached
669
670 END_ENTRY _objc_msgSendSuper_stret
671
672
673 /********************************************************************
674 * id objc_msgSendSuper2_stret
675 ********************************************************************/
676
677 ENTRY _objc_msgSendSuper2_stret
678 MESSENGER_START
679
680 ldr r9, [r1, #CLASS] // class = struct super->class
681 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
682 CacheLookup STRET
683 // cache hit, IMP in r12, ne already set for stret forwarding
684 ldr r1, [r1, #RECEIVER] // load real receiver
685 MESSENGER_END_FAST
686 bx r12 // call imp
687
688 CacheLookup2 STRET
689 // cache miss
690 ldr r9, [r1, #CLASS] // class = struct super->class
691 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
692 ldr r1, [r1, #RECEIVER] // load real receiver
693 MESSENGER_END_SLOW
694 b __objc_msgSend_stret_uncached
695
696 END_ENTRY _objc_msgSendSuper2_stret
697
698
699 ENTRY _objc_msgLookupSuper2_stret
700
701 ldr r9, [r1, #CLASS] // class = struct super->class
702 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
703 CacheLookup STRET
704 // cache hit, IMP in r12, ne already set for stret forwarding
705 ldr r1, [r1, #RECEIVER] // load real receiver
706 bx lr
707
708 CacheLookup2 STRET
709 // cache miss
710 ldr r9, [r1, #CLASS]
711 ldr r9, [r9, #SUPERCLASS] // r9 = class to search
712 ldr r1, [r1, #RECEIVER] // load real receiver
713 b __objc_msgLookup_stret_uncached
714
715 END_ENTRY _objc_msgLookupSuper2_stret
716
717
718 /////////////////////////////////////////////////////////////////////
719 //
720 // MethodTableLookup NORMAL|STRET
721 //
722 // Locate the implementation for a selector in a class's method lists.
723 //
724 // Takes:
725 // $0 = NORMAL, STRET
726 // r0 or r1 (STRET) = receiver
727 // r1 or r2 (STRET) = selector
728 // r9 = class to search in
729 //
730 // On exit: IMP in r12, eq/ne set for forwarding
731 //
732 /////////////////////////////////////////////////////////////////////
733
734 .macro MethodTableLookup
735
736 stmfd sp!, {r0-r3,r7,lr}
737 add r7, sp, #16
738 sub sp, #8 // align stack
739 FP_SAVE
740
741 .if $0 == NORMAL
742 // receiver already in r0
743 // selector already in r1
744 .else
745 mov r0, r1 // receiver
746 mov r1, r2 // selector
747 .endif
748 mov r2, r9 // class to search
749
750 blx __class_lookupMethodAndLoadCache3
751 mov r12, r0 // r12 = IMP
752
753 .if $0 == NORMAL
754 cmp r12, r12 // set eq for nonstret forwarding
755 .else
756 tst r12, r12 // set ne for stret forwarding
757 .endif
758
759 FP_RESTORE
760 add sp, #8 // align stack
761 ldmfd sp!, {r0-r3,r7,lr}
762
763 .endmacro
764
765
766 /********************************************************************
767 *
768 * _objc_msgSend_uncached
769 * _objc_msgSend_stret_uncached
770 * _objc_msgLookup_uncached
771 * _objc_msgLookup_stret_uncached
772 * The uncached method lookup.
773 *
774 ********************************************************************/
775
776 STATIC_ENTRY __objc_msgSend_uncached
777
778 // THIS IS NOT A CALLABLE C FUNCTION
779 // Out-of-band r9 is the class to search
780
781 MethodTableLookup NORMAL // returns IMP in r12
782 bx r12
783
784 END_ENTRY __objc_msgSend_uncached
785
786
787 STATIC_ENTRY __objc_msgSend_stret_uncached
788
789 // THIS IS NOT A CALLABLE C FUNCTION
790 // Out-of-band r9 is the class to search
791
792 MethodTableLookup STRET // returns IMP in r12
793 bx r12
794
795 END_ENTRY __objc_msgSend_stret_uncached
796
797
798 STATIC_ENTRY __objc_msgLookup_uncached
799
800 // THIS IS NOT A CALLABLE C FUNCTION
801 // Out-of-band r9 is the class to search
802
803 MethodTableLookup NORMAL // returns IMP in r12
804 bx lr
805
806 END_ENTRY __objc_msgLookup_uncached
807
808
809 STATIC_ENTRY __objc_msgLookup_stret_uncached
810
811 // THIS IS NOT A CALLABLE C FUNCTION
812 // Out-of-band r9 is the class to search
813
814 MethodTableLookup STRET // returns IMP in r12
815 bx lr
816
817 END_ENTRY __objc_msgLookup_stret_uncached
818
819
820 /********************************************************************
821 *
822 * id _objc_msgForward(id self, SEL _cmd,...);
823 *
824 * _objc_msgForward and _objc_msgForward_stret are the externally-callable
825 * functions returned by things like method_getImplementation().
826 * _objc_msgForward_impcache is the function pointer actually stored in
827 * method caches.
828 *
829 ********************************************************************/
830
831 MI_EXTERN(__objc_forward_handler)
832 MI_EXTERN(__objc_forward_stret_handler)
833
834 STATIC_ENTRY __objc_msgForward_impcache
835 // Method cache version
836
837 // THIS IS NOT A CALLABLE C FUNCTION
838 // Out-of-band Z is 0 (EQ) for normal, 1 (NE) for stret
839
840 MESSENGER_START
841 nop
842 MESSENGER_END_SLOW
843
844 beq __objc_msgForward
845 b __objc_msgForward_stret
846
847 END_ENTRY __objc_msgForward_impcache
848
849
850 ENTRY __objc_msgForward
851 // Non-stret version
852
853 MI_GET_EXTERN(r12, __objc_forward_handler)
854 ldr r12, [r12]
855 bx r12
856
857 END_ENTRY __objc_msgForward
858
859
860 ENTRY __objc_msgForward_stret
861 // Struct-return version
862
863 MI_GET_EXTERN(r12, __objc_forward_stret_handler)
864 ldr r12, [r12]
865 bx r12
866
867 END_ENTRY __objc_msgForward_stret
868
869
870 ENTRY _objc_msgSend_noarg
871 b _objc_msgSend
872 END_ENTRY _objc_msgSend_noarg
873
874 ENTRY _objc_msgSend_debug
875 b _objc_msgSend
876 END_ENTRY _objc_msgSend_debug
877
878 ENTRY _objc_msgSendSuper2_debug
879 b _objc_msgSendSuper2
880 END_ENTRY _objc_msgSendSuper2_debug
881
882 ENTRY _objc_msgSend_stret_debug
883 b _objc_msgSend_stret
884 END_ENTRY _objc_msgSend_stret_debug
885
886 ENTRY _objc_msgSendSuper2_stret_debug
887 b _objc_msgSendSuper2_stret
888 END_ENTRY _objc_msgSendSuper2_stret_debug
889
890
891 ENTRY _method_invoke
892 // r1 is method triplet instead of SEL
893 ldr r12, [r1, #METHOD_IMP]
894 ldr r1, [r1, #METHOD_NAME]
895 bx r12
896 END_ENTRY _method_invoke
897
898
899 ENTRY _method_invoke_stret
900 // r2 is method triplet instead of SEL
901 ldr r12, [r2, #METHOD_IMP]
902 ldr r2, [r2, #METHOD_NAME]
903 bx r12
904 END_ENTRY _method_invoke_stret
905
906
907 .section __DATA,__objc_msg_break
908 .long 0
909 .long 0
910
911 #endif