2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 /********************************************************************
27 ********************************************************************
29 ** objc-msg-x86_64.s - x86-64 code to support objc messaging.
31 ********************************************************************
32 ********************************************************************/
34 /********************************************************************
35 * Data used by the ObjC runtime.
37 ********************************************************************/
40 // Substitute receiver for messages sent to nil (usually also nil)
41 // id _objc_nilReceiver
43 .private_extern __objc_nilReceiver
47 // _objc_entryPoints and _objc_exitPoints are used by objc
48 // to get the critical regions for which method caches
49 // cannot be garbage collected.
51 .private_extern _objc_entryPoints
55 .quad _objc_msgSend_fpret
56 .quad _objc_msgSend_fp2ret
57 .quad _objc_msgSend_stret
58 .quad _objc_msgSendSuper
59 .quad _objc_msgSendSuper_stret
60 .quad _objc_msgSendSuper2
61 .quad _objc_msgSendSuper2_stret
64 .private_extern _objc_exitPoints
66 .quad LExit_cache_getImp
67 .quad LExit_objc_msgSend
68 .quad LExit_objc_msgSend_fpret
69 .quad LExit_objc_msgSend_fp2ret
70 .quad LExit_objc_msgSend_stret
71 .quad LExit_objc_msgSendSuper
72 .quad LExit_objc_msgSendSuper_stret
73 .quad LExit_objc_msgSendSuper2
74 .quad LExit_objc_msgSendSuper2_stret
78 /********************************************************************
79 * List every exit insn from every messenger for debugger use.
82 * 1 word instruction's address
83 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
87 * ENTER is the start of a dispatcher
88 * FAST_EXIT is method dispatch
89 * SLOW_EXIT is uncached method lookup
90 * NIL_EXIT is returning zero from a message sent to nil
91 * These must match objc-gdb.h.
92 ********************************************************************/
99 .section __DATA,__objc_msg_break
100 .globl _gdb_objc_messenger_breakpoints
101 _gdb_objc_messenger_breakpoints:
102 // contents populated by the macros below
104 .macro MESSENGER_START
106 .section __DATA,__objc_msg_break
111 .macro MESSENGER_END_FAST
113 .section __DATA,__objc_msg_break
118 .macro MESSENGER_END_SLOW
120 .section __DATA,__objc_msg_break
125 .macro MESSENGER_END_NIL
127 .section __DATA,__objc_msg_break
134 /********************************************************************
135 * Recommended multi-byte NOP instructions
136 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
137 ********************************************************************/
138 #define nop1 .byte 0x90
139 #define nop2 .byte 0x66,0x90
140 #define nop3 .byte 0x0F,0x1F,0x00
141 #define nop4 .byte 0x0F,0x1F,0x40,0x00
142 #define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
143 #define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
144 #define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
145 #define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
146 #define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
149 /********************************************************************
150 * Harmless branch prefix hint for instruction alignment
151 ********************************************************************/
153 #define PN .byte 0x2e
156 /********************************************************************
157 * Names for parameter registers.
158 ********************************************************************/
176 /********************************************************************
177 * Names for relative labels
178 * DO NOT USE THESE LABELS ELSEWHERE
179 * Reserved labels: 5: 6: 7: 8: 9:
180 ********************************************************************/
182 #define LCacheMiss_f 5f
183 #define LCacheMiss_b 5b
184 #define LNilTestDone 6
185 #define LNilTestDone_f 6f
186 #define LNilTestDone_b 6b
187 #define LNilTestSlow 7
188 #define LNilTestSlow_f 7f
189 #define LNilTestSlow_b 7b
190 #define LGetIsaDone 8
191 #define LGetIsaDone_f 8f
192 #define LGetIsaDone_b 8b
193 #define LGetIsaSlow 9
194 #define LGetIsaSlow_f 9f
195 #define LGetIsaSlow_b 9b
197 /********************************************************************
199 ********************************************************************/
207 #define SUPER_STRET 6
209 #define SUPER2_STRET 8
212 /********************************************************************
214 * Structure definitions.
216 ********************************************************************/
218 // objc_super parameter to sendSuper
222 // Selected field offsets in class structure
223 // #define isa 0 USE GetIsa INSTEAD
226 #define method_name 0
227 #define method_imp 16
230 // uint128_t floatingPointArgs[8]; // xmm0..xmm7
231 // long linkageArea[4]; // r10, rax, ebp, ret
232 // long registerArgs[6]; // a1..a6
233 // long stackArgs[0]; // variable-size
236 #define LINK_AREA (FP_AREA+8*16)
237 #define REG_AREA (LINK_AREA+4*8)
238 #define STACK_AREA (REG_AREA+6*8)
241 //////////////////////////////////////////////////////////////////////
243 // ENTRY functionName
245 // Assembly directives to begin an exported function.
247 // Takes: functionName - name of the exported function
248 //////////////////////////////////////////////////////////////////////
264 //////////////////////////////////////////////////////////////////////
266 // END_ENTRY functionName
268 // Assembly directives to end an exported function. Just a placeholder,
269 // a close-parenthesis for ENTRY, until it is needed for something.
271 // Takes: functionName - name of the exported function
272 //////////////////////////////////////////////////////////////////////
280 These macros work for objc_msgSend variants and others that call
281 CacheLookup/MethodTableLookup or SaveRegisters/RestoreRegisters
282 without otherwise building a frame or clobbering callee-save registers
284 The macros build appropriate FDEs and tie them to the CIE.
287 #define DW_CFA_offset 0x80
288 #define DW_CFA_restore 0xc0
289 #define DW_CFA_advance_loc4 0x4
290 #define DW_CFA_same_value 0x8
291 #define DW_CFA_def_cfa 0xc
292 #define DW_CFA_def_cfa_register 0xd
293 #define DW_CFA_def_cfa_offset 0xe
294 #define DW_CFA_offset_extended_sf 0x11
295 #define DW_CFA_def_cfa_offset_sf 0x13
323 // 8-byte data multiplier
324 // 1-byte insn multiplier
325 // PC-relative everything
328 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
330 .set L$set$0,LECIE1-LSCIE1
331 .long L$set$0 # Length of Common Information Entry
333 .long 0 # CIE Identifier Tag
334 .byte 0x3 # CIE Version
335 .ascii "zPR\0" # CIE Augmentation: size + personality + FDE encoding
336 .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
337 .byte 0x78 # sleb128 -0x8; CIE Data Alignment Factor
338 .byte 0x10 # CIE RA Column
339 .byte 0x6 # uleb128 0x1; Augmentation size
340 // Personality augmentation
342 .long ___objc_personality_v0+4@GOTPCREL
343 // FDE-encoding augmentation
345 // Prefix instructions
350 // RA is at 0(%rsp) aka 1*-8(CFA)
351 .byte DW_CFA_offset | DW_ra
360 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
366 .set LLENFDE$0, LEFDE$0-LASFDE$0
367 .long LLENFDE$0 # FDE Length
369 .long LASFDE$0-CIE # FDE CIE offset
370 .quad L_dw_start_$0-. # FDE address start
371 .quad L_dw_len_$0 # FDE address range
372 .byte 0x0 # uleb128 0x0; Augmentation size
374 // DW_START: set by CIE
377 // Save/RestoreRegisters or MethodTableLookup
380 .byte DW_CFA_advance_loc4
381 .long L_dw_enter_$0 - L_dw_start_$0
382 .byte DW_CFA_def_cfa_offset
384 .byte DW_CFA_offset | DW_rbp // rbp => 2*-8(CFA)
386 .byte DW_CFA_def_cfa_register // CFA = rbp+16 (offset unchanged)
390 .byte DW_CFA_advance_loc4
391 .long L_dw_leave_$0 - L_dw_enter_$0
393 .byte DW_CFA_same_value // rbp = original value
395 .byte DW_CFA_def_cfa // CFA = rsp+8
413 // After `enter` in SaveRegisters
418 // After `leave` in RestoreRegisters
424 // $1 == 1 iff you called MethodTableLookup or Save/RestoreRegsters
426 .set L_dw_len_$0, . - L_dw_start_$0
431 /////////////////////////////////////////////////////////////////////
433 // SaveRegisters caller
435 // Pushes a stack frame and saves all registers that might contain
438 // On entry: %0 = caller's symbol name for DWARF
442 // %rsp is 16-byte aligned
444 /////////////////////////////////////////////////////////////////////
447 // These instructions must match the DWARF data in EMIT_FDE.
449 enter $$0x80+8, $$0 // +8 for alignment
452 movdqa %xmm0, -0x80(%rbp)
453 push %rax // might be xmm parameter count
454 movdqa %xmm1, -0x70(%rbp)
456 movdqa %xmm2, -0x60(%rbp)
458 movdqa %xmm3, -0x50(%rbp)
460 movdqa %xmm4, -0x40(%rbp)
462 movdqa %xmm5, -0x30(%rbp)
464 movdqa %xmm6, -0x20(%rbp)
466 movdqa %xmm7, -0x10(%rbp)
468 // These instructions must match the DWARF data in EMIT_FDE.
471 /////////////////////////////////////////////////////////////////////
475 // Pops a stack frame pushed by SaveRegisters
477 // On entry: $0 = caller's symbol name for DWARF
478 // %rbp unchanged since SaveRegisters
483 /////////////////////////////////////////////////////////////////////
485 .macro RestoreRegisters
486 // These instructions must match the DWARF data in EMIT_FDE.
488 movdqa -0x80(%rbp), %xmm0
490 movdqa -0x70(%rbp), %xmm1
492 movdqa -0x60(%rbp), %xmm2
494 movdqa -0x50(%rbp), %xmm3
496 movdqa -0x40(%rbp), %xmm4
498 movdqa -0x30(%rbp), %xmm5
500 movdqa -0x20(%rbp), %xmm6
502 movdqa -0x10(%rbp), %xmm7
507 // These instructions must match the DWARF data in EMIT_FDE.
511 /////////////////////////////////////////////////////////////////////
513 // CacheLookup return-type, caller
515 // Locate the implementation for a class in a selector's method cache.
518 // $0 = NORMAL, FPRET, FP2RET, STRET, SUPER, SUPER_STRET, SUPER2, SUPER2_STRET, GETIMP
519 // a2 or a3 (STRET) = selector a.k.a. cache
520 // r11 = class to search
522 // On exit: r10 clobbered
523 // (found) calls or returns IMP, eq/ne/r11 set for forwarding
524 // (not found) jumps to LCacheMiss, class still in r11
526 /////////////////////////////////////////////////////////////////////
530 // CacheHit must always be preceded by a not-taken `jne` instruction
531 // in order to set the correct flags for _objc_msgForward_impcache.
533 // r10 = found bucket
536 movq 8(%r10), %rax // return imp
537 leaq __objc_msgSend_uncached_impcache(%rip), %r11
540 xorl %eax, %eax // don't return msgSend_uncached
542 .elseif $0 == NORMAL || $0 == FPRET || $0 == FP2RET
543 // eq already set for forwarding by `jne`
545 jmp *8(%r10) // call imp
548 movq receiver(%a1), %a1 // load real receiver
549 cmp %r10, %r10 // set eq for non-stret forwarding
551 jmp *8(%r10) // call imp
554 movq receiver(%a1), %a1 // load real receiver
555 cmp %r10, %r10 // set eq for non-stret forwarding
557 jmp *8(%r10) // call imp
560 test %r10, %r10 // set ne for stret forwarding
562 jmp *8(%r10) // call imp
564 .elseif $0 == SUPER_STRET
565 movq receiver(%a2), %a2 // load real receiver
566 test %r10, %r10 // set ne for stret forwarding
568 jmp *8(%r10) // call imp
570 .elseif $0 == SUPER2_STRET
571 movq receiver(%a2), %a2 // load real receiver
572 test %r10, %r10 // set ne for stret forwarding
574 jmp *8(%r10) // call imp
583 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
584 movq %a2, %r10 // r10 = _cmd
586 movq %a3, %r10 // r10 = _cmd
588 andl 24(%r11), %r10d // r10 = _cmd & class->cache.mask
589 shlq $$4, %r10 // r10 = offset = (_cmd & mask)<<4
590 addq 16(%r11), %r10 // r10 = class->cache.buckets + offset
592 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
593 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
595 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
598 // CacheHit must always be preceded by a not-taken `jne` instruction
599 CacheHit $0 // call or return imp
604 je LCacheMiss_f // if (bucket->sel == 0) cache miss
606 je 3f // if (bucket == cache->buckets) wrap
608 subq $$16, %r10 // bucket--
609 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
610 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
612 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
615 // CacheHit must always be preceded by a not-taken `jne` instruction
616 CacheHit $0 // call or return imp
620 movl 24(%r11), %r10d // r10 = mask a.k.a. last bucket index
621 shlq $$4, %r10 // r10 = offset = mask<<4
622 addq 16(%r11), %r10 // r10 = &cache->buckets[mask]
625 // clone scanning loop to crash instead of hang when cache is corrupt
630 je LCacheMiss_f // if (bucket->sel == 0) cache miss
632 je 3f // if (bucket == cache->buckets) wrap
634 subq $$16, %r10 // bucket--
636 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
637 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
639 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
642 // CacheHit must always be preceded by a not-taken `jne` instruction
643 CacheHit $0 // call or return imp
646 // double wrap - busted
647 .if $0 == STRET || $0 == SUPER_STRET || $0 == SUPER2_STRET
655 movq %r11, %a3 // a3 = isa
656 movq %r10, %a4 // a4 = bucket
658 jmp _cache_getImp_corrupt_cache_error
660 jmp _objc_msgSend_corrupt_cache_error
665 /////////////////////////////////////////////////////////////////////
667 // MethodTableLookup classRegister, selectorRegister, caller
669 // Takes: $0 = class to search (a1 or a2 or r10 ONLY)
670 // $1 = selector to search for (a2 or a3 ONLY)
671 // $2 = caller's symbol name for DWARF
672 // r11 = class to search
674 // On exit: imp in %r11
676 /////////////////////////////////////////////////////////////////////
677 .macro MethodTableLookup
683 // _class_lookupMethodAndLoadCache3(receiver, selector, class)
688 call __class_lookupMethodAndLoadCache3
690 // IMP is now in %rax
697 /////////////////////////////////////////////////////////////////////
699 // GetIsaFast return-type
700 // GetIsaSupport return-type
702 // Sets r11 = obj->isa. Consults the tagged isa table if necessary.
704 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
705 // a1 or a2 (STRET) = receiver
707 // On exit: r11 = receiver->isa
710 /////////////////////////////////////////////////////////////////////
727 .macro GetIsaSupport2
729 leaq _objc_debug_taggedpointer_classes(%rip), %r11
736 movq (%r11, %r10, 8), %r11 // read isa from table
752 /////////////////////////////////////////////////////////////////////
754 // NilTest return-type
756 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
757 // %a1 or %a2 (STRET) = receiver
759 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
761 // NilTestSupport return-type
763 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
764 // %a1 or %a2 (STRET) = receiver
766 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
768 /////////////////////////////////////////////////////////////////////
771 .if $0 == SUPER || $0 == SUPER_STRET
772 error super dispatch does not test for nil
785 .macro NilTestSupport
789 movq __objc_nilReceiver(%rip), %a1
790 testq %a1, %a1 // if (receiver != nil)
792 movq __objc_nilReceiver(%rip), %a2
793 testq %a2, %a2 // if (receiver != nil)
795 jne LNilTestDone_b // send to new receiver
816 /********************************************************************
817 * IMP cache_getImp(Class cls, SEL sel)
819 * On entry: a1 = class whose cache is to be searched
820 * a2 = selector to search for
822 * If found, returns method implementation.
823 * If not found, returns NULL.
824 ********************************************************************/
826 STATIC_ENTRY _cache_getImp
827 DW_START _cache_getImp
830 movq %a1, %r11 // move class to r11 for CacheLookup
831 CacheLookup GETIMP // returns IMP on success
834 // cache miss, return nil
839 DW_END _cache_getImp, 0
840 END_ENTRY _cache_getImp
843 /********************************************************************
845 * id objc_msgSend(id self, SEL _cmd,...);
847 ********************************************************************/
851 .globl _objc_debug_taggedpointer_classes
852 _objc_debug_taggedpointer_classes:
856 DW_START _objc_msgSend
861 GetIsaFast NORMAL // r11 = self->isa
862 CacheLookup NORMAL // calls IMP on success
864 NilTestSupport NORMAL
868 // cache miss: go search the method lists
871 MethodTableLookup %a1, %a2, _objc_msgSend // r11 = IMP
872 cmp %r11, %r11 // set eq (nonstret) for forwarding
873 jmp *%r11 // goto *imp
875 DW_END _objc_msgSend, 1
876 END_ENTRY _objc_msgSend
879 ENTRY _objc_msgSend_fixup
881 END_ENTRY _objc_msgSend_fixup
884 STATIC_ENTRY _objc_msgSend_fixedup
885 // Load _cmd from the message_ref
888 END_ENTRY _objc_msgSend_fixedup
891 /********************************************************************
893 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
895 * struct objc_super {
899 ********************************************************************/
901 ENTRY _objc_msgSendSuper
902 DW_START _objc_msgSendSuper
905 // search the cache (objc_super in %a1)
906 movq class(%a1), %r11 // class = objc_super->class
907 CacheLookup SUPER // calls IMP on success
909 // cache miss: go search the method lists
911 // class still in r11
912 movq receiver(%a1), %r10
913 MethodTableLookup %r10, %a2, _objc_msgSendSuper // r11 = IMP
914 movq receiver(%a1), %a1 // load real receiver
915 cmp %r11, %r11 // set eq (nonstret) for forwarding
916 jmp *%r11 // goto *imp
918 DW_END _objc_msgSendSuper, 1
919 END_ENTRY _objc_msgSendSuper
922 /********************************************************************
923 * id objc_msgSendSuper2
924 ********************************************************************/
926 ENTRY _objc_msgSendSuper2
927 DW_START _objc_msgSendSuper2
930 // objc_super->class is superclass of class to search
932 // search the cache (objc_super in %a1)
933 movq class(%a1), %r11 // cls = objc_super->class
934 movq 8(%r11), %r11 // cls = class->superclass
935 CacheLookup SUPER2 // calls IMP on success
937 // cache miss: go search the method lists
939 // superclass still in r11
940 movq receiver(%a1), %r10
941 MethodTableLookup %r10, %a2, _objc_msgSendSuper2 // r11 = IMP
942 movq receiver(%a1), %a1 // load real receiver
943 cmp %r11, %r11 // set eq (nonstret) for forwarding
944 jmp *%r11 // goto *imp
946 DW_END _objc_msgSendSuper2, 1
947 END_ENTRY _objc_msgSendSuper2
950 ENTRY _objc_msgSendSuper2_fixup
952 END_ENTRY _objc_msgSendSuper2_fixup
955 STATIC_ENTRY _objc_msgSendSuper2_fixedup
956 // Load _cmd from the message_ref
958 jmp _objc_msgSendSuper2
959 END_ENTRY _objc_msgSendSuper2_fixedup
962 /********************************************************************
964 * double objc_msgSend_fpret(id self, SEL _cmd,...);
965 * Used for `long double` return only. `float` and `double` use objc_msgSend.
967 ********************************************************************/
969 ENTRY _objc_msgSend_fpret
970 DW_START _objc_msgSend_fpret
975 GetIsaFast FPRET // r11 = self->isa
976 CacheLookup FPRET // calls IMP on success
982 // cache miss: go search the method lists
985 MethodTableLookup %a1, %a2, _objc_msgSend_fpret // r11 = IMP
986 cmp %r11, %r11 // set eq (nonstret) for forwarding
987 jmp *%r11 // goto *imp
989 DW_END _objc_msgSend_fpret, 1
990 END_ENTRY _objc_msgSend_fpret
993 ENTRY _objc_msgSend_fpret_fixup
995 END_ENTRY _objc_msgSend_fpret_fixup
998 STATIC_ENTRY _objc_msgSend_fpret_fixedup
999 // Load _cmd from the message_ref
1001 jmp _objc_msgSend_fpret
1002 END_ENTRY _objc_msgSend_fpret_fixedup
1005 /********************************************************************
1007 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
1008 * Used for `complex long double` return only.
1010 ********************************************************************/
1012 ENTRY _objc_msgSend_fp2ret
1013 DW_START _objc_msgSend_fp2ret
1018 GetIsaFast FP2RET // r11 = self->isa
1019 CacheLookup FP2RET // calls IMP on success
1021 NilTestSupport FP2RET
1023 GetIsaSupport FP2RET
1025 // cache miss: go search the method lists
1028 MethodTableLookup %a1, %a2, _objc_msgSend_fp2ret // r11 = IMP
1029 cmp %r11, %r11 // set eq (nonstret) for forwarding
1030 jmp *%r11 // goto *imp
1032 DW_END _objc_msgSend_fp2ret, 1
1033 END_ENTRY _objc_msgSend_fp2ret
1036 ENTRY _objc_msgSend_fp2ret_fixup
1038 END_ENTRY _objc_msgSend_fp2ret_fixup
1041 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
1042 // Load _cmd from the message_ref
1044 jmp _objc_msgSend_fp2ret
1045 END_ENTRY _objc_msgSend_fp2ret_fixedup
1048 /********************************************************************
1050 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
1052 * objc_msgSend_stret is the struct-return form of msgSend.
1053 * The ABI calls for %a1 to be used as the address of the structure
1054 * being returned, with the parameters in the succeeding locations.
1056 * On entry: %a1 is the address where the structure is returned,
1057 * %a2 is the message receiver,
1058 * %a3 is the selector
1059 ********************************************************************/
1061 ENTRY _objc_msgSend_stret
1062 DW_START _objc_msgSend_stret
1067 GetIsaFast STRET // r11 = self->isa
1068 CacheLookup STRET // calls IMP on success
1070 NilTestSupport STRET
1074 // cache miss: go search the method lists
1077 MethodTableLookup %a2, %a3, _objc_msgSend_stret // r11 = IMP
1078 test %r11, %r11 // set ne (stret) for forward; r11!=0
1079 jmp *%r11 // goto *imp
1081 DW_END _objc_msgSend_stret, 1
1082 END_ENTRY _objc_msgSend_stret
1085 ENTRY _objc_msgSend_stret_fixup
1087 END_ENTRY _objc_msgSend_stret_fixup
1090 STATIC_ENTRY _objc_msgSend_stret_fixedup
1091 // Load _cmd from the message_ref
1093 jmp _objc_msgSend_stret
1094 END_ENTRY _objc_msgSend_stret_fixedup
1097 /********************************************************************
1099 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
1101 * struct objc_super {
1106 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
1107 * The ABI calls for (sp+4) to be used as the address of the structure
1108 * being returned, with the parameters in the succeeding registers.
1110 * On entry: %a1 is the address where the structure is returned,
1111 * %a2 is the address of the objc_super structure,
1112 * %a3 is the selector
1114 ********************************************************************/
1116 ENTRY _objc_msgSendSuper_stret
1117 DW_START _objc_msgSendSuper_stret
1120 // search the cache (objc_super in %a2)
1121 movq class(%a2), %r11 // class = objc_super->class
1122 CacheLookup SUPER_STRET // calls IMP on success
1124 // cache miss: go search the method lists
1126 // class still in r11
1127 movq receiver(%a2), %r10
1128 MethodTableLookup %r10, %a3, _objc_msgSendSuper_stret // r11 = IMP
1129 movq receiver(%a2), %a2 // load real receiver
1130 test %r11, %r11 // set ne (stret) for forward; r11!=0
1131 jmp *%r11 // goto *imp
1133 DW_END _objc_msgSendSuper_stret, 1
1134 END_ENTRY _objc_msgSendSuper_stret
1137 /********************************************************************
1138 * id objc_msgSendSuper2_stret
1139 ********************************************************************/
1141 ENTRY _objc_msgSendSuper2_stret
1142 DW_START _objc_msgSendSuper2_stret
1145 // search the cache (objc_super in %a2)
1146 movq class(%a2), %r11 // class = objc_super->class
1147 movq 8(%r11), %r11 // class = class->superclass
1148 CacheLookup SUPER2_STRET // calls IMP on success
1150 // cache miss: go search the method lists
1152 // superclass still in r11
1153 movq receiver(%a2), %r10
1154 MethodTableLookup %r10, %a3, _objc_msgSendSuper2_stret // r11 = IMP
1155 movq receiver(%a2), %a2 // load real receiver
1156 test %r11, %r11 // set ne (stret) for forward; r11!=0
1157 jmp *%r11 // goto *imp
1159 DW_END _objc_msgSendSuper2_stret, 1
1160 END_ENTRY _objc_msgSendSuper2_stret
1163 ENTRY _objc_msgSendSuper2_stret_fixup
1165 END_ENTRY _objc_msgSendSuper2_stret_fixup
1168 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
1169 // Load _cmd from the message_ref
1171 jmp _objc_msgSendSuper2_stret
1172 END_ENTRY _objc_msgSendSuper2_stret_fixedup
1175 /********************************************************************
1177 * _objc_msgSend_uncached_impcache
1178 * _objc_msgSend_uncached
1179 * _objc_msgSend_stret_uncached
1181 * Used to erase method cache entries in-place by
1182 * bouncing them to the uncached lookup.
1184 ********************************************************************/
1186 STATIC_ENTRY __objc_msgSend_uncached_impcache
1187 // Method cache version
1189 // THIS IS NOT A CALLABLE C FUNCTION
1190 // Out-of-band condition register is NE for stret, EQ otherwise.
1191 // Out-of-band r11 is the searched class
1197 jne __objc_msgSend_stret_uncached
1198 jmp __objc_msgSend_uncached
1200 END_ENTRY __objc_msgSend_uncached_impcache
1203 STATIC_ENTRY __objc_msgSend_uncached
1204 DW_START __objc_msgSend_uncached
1206 // THIS IS NOT A CALLABLE C FUNCTION
1207 // Out-of-band r11 is the searched class
1209 // r11 is already the class to search
1210 MethodTableLookup %a1, %a2, __objc_msgSend_uncached // r11 = IMP
1211 cmp %r11, %r11 // set eq (nonstret) for forwarding
1212 jmp *%r11 // goto *imp
1214 DW_END __objc_msgSend_uncached, 1
1215 END_ENTRY __objc_msgSend_uncached
1218 STATIC_ENTRY __objc_msgSend_stret_uncached
1219 DW_START __objc_msgSend_stret_uncached
1220 // THIS IS NOT A CALLABLE C FUNCTION
1221 // Out-of-band r11 is the searched class
1223 // r11 is already the class to search
1224 MethodTableLookup %a2, %a3, __objc_msgSend_stret_uncached // r11 = IMP
1225 test %r11, %r11 // set ne (stret) for forward; r11!=0
1226 jmp *%r11 // goto *imp
1228 DW_END __objc_msgSend_stret_uncached, 1
1229 END_ENTRY __objc_msgSend_stret_uncached
1232 /********************************************************************
1234 * id _objc_msgForward(id self, SEL _cmd,...);
1236 ********************************************************************/
1238 // _FwdSel is @selector(forward::), set up in map_images().
1239 // ALWAYS dereference _FwdSel to get to "forward::" !!
1242 .private_extern _FwdSel
1247 LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0"
1251 .private_extern __objc_forward_handler
1252 __objc_forward_handler: .quad 0
1256 .private_extern __objc_forward_stret_handler
1257 __objc_forward_stret_handler: .quad 0
1260 STATIC_ENTRY __objc_msgForward_impcache
1261 // Method cache version
1263 // THIS IS NOT A CALLABLE C FUNCTION
1264 // Out-of-band condition register is NE for stret, EQ otherwise.
1270 jne __objc_msgForward_stret
1271 jmp __objc_msgForward
1273 END_ENTRY __objc_msgForward_impcache
1276 ENTRY __objc_msgForward
1277 // Non-stret version
1279 // Call user handler, if any
1280 movq __objc_forward_handler(%rip), %r11
1281 testq %r11, %r11 // if (handler == NULL)
1282 je 1f // skip handler
1283 jmp *%r11 // else goto handler
1287 // Die if forwarding "forward::"
1288 cmpq %a2, _FwdSel(%rip)
1291 // Record current return address. It will be copied elsewhere in
1292 // the marg_list because this location is needed for register args
1296 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1297 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1299 // Save return address in linkage area.
1300 movq %r11, 16+LINK_AREA(%rsp)
1302 // Save parameter registers
1303 movq %a1, 0+REG_AREA(%rsp)
1304 movq %a2, 8+REG_AREA(%rsp)
1305 movq %a3, 16+REG_AREA(%rsp)
1306 movq %a4, 24+REG_AREA(%rsp)
1307 movq %a5, 32+REG_AREA(%rsp)
1308 movq %a6, 40+REG_AREA(%rsp)
1310 // Save side parameter registers
1311 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
1312 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1313 // 16+LINK_AREA is return address
1315 // Save xmm registers
1316 movdqa %xmm0, 0+FP_AREA(%rsp)
1317 movdqa %xmm1, 16+FP_AREA(%rsp)
1318 movdqa %xmm2, 32+FP_AREA(%rsp)
1319 movdqa %xmm3, 48+FP_AREA(%rsp)
1320 movdqa %xmm4, 64+FP_AREA(%rsp)
1321 movdqa %xmm5, 80+FP_AREA(%rsp)
1322 movdqa %xmm6, 96+FP_AREA(%rsp)
1323 movdqa %xmm7, 112+FP_AREA(%rsp)
1325 // Call [receiver forward:sel :margs]
1326 movq %rsp, %a4 // marg_list
1327 movq %a2, %a3 // sel
1328 movq _FwdSel(%rip), %a2 // forward::
1329 // %a1 is already the receiver
1333 // Retrieve return address from linkage area
1334 movq 16+LINK_AREA(%rsp), %r11
1336 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
1337 // Put return address back
1342 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1343 // %a1 is already the receiver
1344 movq %a3, %a4 // the forwarded selector
1345 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s"
1346 movq _FwdSel(%rip), %a3 // forward::
1347 jmp ___objc_error // never returns
1349 END_ENTRY __objc_msgForward
1352 ENTRY __objc_msgForward_stret
1353 // Struct-return version
1355 // Call user handler, if any
1356 movq __objc_forward_stret_handler(%rip), %r11
1357 testq %r11, %r11 // if (handler == NULL)
1358 je 1f // skip handler
1359 jmp *%r11 // else goto handler
1362 // Die if forwarding "forward::"
1363 cmpq %a3, _FwdSel(%rip)
1364 je LMsgForwardStretError
1366 // Record current return address. It will be copied elsewhere in
1367 // the marg_list because this location is needed for register args
1371 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1372 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1374 // Save return address in linkage area.
1375 movq %r11, 16+LINK_AREA(%rsp)
1377 // Save parameter registers
1378 movq %a1, 0+REG_AREA(%rsp) // note: used again below
1379 movq %a2, 8+REG_AREA(%rsp)
1380 movq %a3, 16+REG_AREA(%rsp)
1381 movq %a4, 24+REG_AREA(%rsp)
1382 movq %a5, 32+REG_AREA(%rsp)
1383 movq %a6, 40+REG_AREA(%rsp)
1385 // Save side parameter registers
1386 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
1387 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1388 // 16+LINK_AREA is return address
1390 // Save xmm registers
1391 movdqa %xmm0, 0+FP_AREA(%rsp)
1392 movdqa %xmm1, 16+FP_AREA(%rsp)
1393 movdqa %xmm2, 32+FP_AREA(%rsp)
1394 movdqa %xmm3, 48+FP_AREA(%rsp)
1395 movdqa %xmm4, 64+FP_AREA(%rsp)
1396 movdqa %xmm5, 80+FP_AREA(%rsp)
1397 movdqa %xmm6, 96+FP_AREA(%rsp)
1398 movdqa %xmm7, 112+FP_AREA(%rsp)
1400 // Call [receiver forward:sel :margs]
1401 movq %a2, %a1 // receiver
1402 movq _FwdSel(%rip), %a2 // forward::
1403 // %a3 is already the selector
1404 movq %rsp, %a4 // marg_list
1406 call _objc_msgSend // forward:: is NOT struct-return
1408 // Set return value register to the passed-in struct address
1409 movq 0+REG_AREA(%rsp), %rax
1410 // Retrieve return address from linkage area
1411 movq 16+LINK_AREA(%rsp), %r11
1413 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
1414 // Put return address back
1418 LMsgForwardStretError:
1419 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1420 // %a4 is already the forwarded selector
1421 movq %a2, %a1 // receiver
1422 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s"
1423 movq _FwdSel(%rip), %a3 // forward::
1424 jmp ___objc_error // never returns
1426 END_ENTRY __objc_msgForward_stret
1429 ENTRY _objc_msgSend_debug
1431 END_ENTRY _objc_msgSend_debug
1433 ENTRY _objc_msgSendSuper2_debug
1434 jmp _objc_msgSendSuper2
1435 END_ENTRY _objc_msgSendSuper2_debug
1437 ENTRY _objc_msgSend_stret_debug
1438 jmp _objc_msgSend_stret
1439 END_ENTRY _objc_msgSend_stret_debug
1441 ENTRY _objc_msgSendSuper2_stret_debug
1442 jmp _objc_msgSendSuper2_stret
1443 END_ENTRY _objc_msgSendSuper2_stret_debug
1445 ENTRY _objc_msgSend_fpret_debug
1446 jmp _objc_msgSend_fpret
1447 END_ENTRY _objc_msgSend_fpret_debug
1449 ENTRY _objc_msgSend_fp2ret_debug
1450 jmp _objc_msgSend_fp2ret
1451 END_ENTRY _objc_msgSend_fp2ret_debug
1454 ENTRY _objc_msgSend_noarg
1456 END_ENTRY _objc_msgSend_noarg
1459 ENTRY _method_invoke
1461 movq method_imp(%a2), %r11
1462 movq method_name(%a2), %a2
1465 END_ENTRY _method_invoke
1468 ENTRY _method_invoke_stret
1470 movq method_imp(%a3), %r11
1471 movq method_name(%a3), %a3
1474 END_ENTRY _method_invoke_stret
1477 STATIC_ENTRY __objc_ignored_method
1482 END_ENTRY __objc_ignored_method
1485 .section __DATA,__objc_msg_break