]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-simulator-x86_64.s
objc4-787.1.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-simulator-x86_64.s
1 /*
2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
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 #include <TargetConditionals.h>
25 #if __x86_64__ && TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC
26
27 /********************************************************************
28 ********************************************************************
29 **
30 ** objc-msg-x86_64.s - x86-64 code to support objc messaging.
31 **
32 ********************************************************************
33 ********************************************************************/
34
35 .data
36
37 // _objc_restartableRanges is used by method dispatch
38 // to get the critical regions for which method caches
39 // cannot be garbage collected.
40
41 .macro RestartableEntry
42 .quad $0
43 .short LExit$0 - $0
44 .short 0xffff // The simulator doesn't support kernel based recovery
45 .long 0
46 .endmacro
47
48 .align 4
49 .private_extern _objc_restartableRanges
50 _objc_restartableRanges:
51 RestartableEntry _cache_getImp
52 RestartableEntry _objc_msgSend
53 RestartableEntry _objc_msgSend_fpret
54 RestartableEntry _objc_msgSend_fp2ret
55 RestartableEntry _objc_msgSend_stret
56 RestartableEntry _objc_msgSendSuper
57 RestartableEntry _objc_msgSendSuper_stret
58 RestartableEntry _objc_msgSendSuper2
59 RestartableEntry _objc_msgSendSuper2_stret
60 RestartableEntry _objc_msgLookup
61 RestartableEntry _objc_msgLookup_fpret
62 RestartableEntry _objc_msgLookup_fp2ret
63 RestartableEntry _objc_msgLookup_stret
64 RestartableEntry _objc_msgLookupSuper2
65 RestartableEntry _objc_msgLookupSuper2_stret
66 .fill 16, 1, 0
67
68
69 /********************************************************************
70 * Recommended multi-byte NOP instructions
71 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
72 ********************************************************************/
73 #define nop1 .byte 0x90
74 #define nop2 .byte 0x66,0x90
75 #define nop3 .byte 0x0F,0x1F,0x00
76 #define nop4 .byte 0x0F,0x1F,0x40,0x00
77 #define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
78 #define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
79 #define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
80 #define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
81 #define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
82
83
84 /********************************************************************
85 * Names for parameter registers.
86 ********************************************************************/
87
88 #define a1 rdi
89 #define a1d edi
90 #define a1b dil
91 #define a2 rsi
92 #define a2d esi
93 #define a2b sil
94 #define a3 rdx
95 #define a3d edx
96 #define a3b dl
97 #define a4 rcx
98 #define a4d ecx
99 #define a5 r8
100 #define a5d r8d
101 #define a6 r9
102 #define a6d r9d
103
104
105 /********************************************************************
106 * Names for relative labels
107 * DO NOT USE THESE LABELS ELSEWHERE
108 * Reserved labels: 6: 7: 8: 9:
109 ********************************************************************/
110 #define LCacheMiss 6
111 #define LCacheMiss_f 6f
112 #define LCacheMiss_b 6b
113 #define LGetIsaDone 7
114 #define LGetIsaDone_f 7f
115 #define LGetIsaDone_b 7b
116 #define LNilOrTagged 8
117 #define LNilOrTagged_f 8f
118 #define LNilOrTagged_b 8b
119 #define LNil 9
120 #define LNil_f 9f
121 #define LNil_b 9b
122
123 /********************************************************************
124 * Macro parameters
125 ********************************************************************/
126
127 #define NORMAL 0
128 #define FPRET 1
129 #define FP2RET 2
130 #define STRET 3
131
132 #define CALL 100
133 #define GETIMP 101
134 #define LOOKUP 102
135
136
137 /********************************************************************
138 *
139 * Structure definitions.
140 *
141 ********************************************************************/
142
143 // objc_super parameter to sendSuper
144 #define receiver 0
145 #define class 8
146
147 // Selected field offsets in class structure
148 // #define isa 0 USE GetIsa INSTEAD
149
150 // Method descriptor
151 #define method_name 0
152 #define method_imp 16
153
154 // Method cache
155 #define cached_sel 0
156 #define cached_imp 8
157
158
159 //////////////////////////////////////////////////////////////////////
160 //
161 // ENTRY functionName
162 //
163 // Assembly directives to begin an exported function.
164 //
165 // Takes: functionName - name of the exported function
166 //////////////////////////////////////////////////////////////////////
167
168 .macro ENTRY
169 .text
170 .globl $0
171 .align 6, 0x90
172 $0:
173 .endmacro
174
175 .macro STATIC_ENTRY
176 .text
177 .private_extern $0
178 .align 2, 0x90
179 $0:
180 .endmacro
181
182 //////////////////////////////////////////////////////////////////////
183 //
184 // END_ENTRY functionName
185 //
186 // Assembly directives to end an exported function. Just a placeholder,
187 // a close-parenthesis for ENTRY, until it is needed for something.
188 //
189 // Takes: functionName - name of the exported function
190 //////////////////////////////////////////////////////////////////////
191
192 .macro END_ENTRY
193 LExit$0:
194 .endmacro
195
196
197 /********************************************************************
198 * UNWIND name, flags
199 * Unwind info generation
200 ********************************************************************/
201 .macro UNWIND
202 .section __LD,__compact_unwind,regular,debug
203 .quad $0
204 .set LUnwind$0, LExit$0 - $0
205 .long LUnwind$0
206 .long $1
207 .quad 0 /* no personality */
208 .quad 0 /* no LSDA */
209 .text
210 .endmacro
211
212 #define NoFrame 0x02010000 // no frame, no SP adjustment except return address
213 #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
214
215
216 //////////////////////////////////////////////////////////////////////
217 //
218 // SAVE_REGS
219 //
220 // Create a stack frame and save all argument registers in preparation
221 // for a function call.
222 //////////////////////////////////////////////////////////////////////
223
224 .macro SAVE_REGS
225
226 push %rbp
227 mov %rsp, %rbp
228
229 sub $$0x80+8, %rsp // +8 for alignment
230
231 movdqa %xmm0, -0x80(%rbp)
232 push %rax // might be xmm parameter count
233 movdqa %xmm1, -0x70(%rbp)
234 push %a1
235 movdqa %xmm2, -0x60(%rbp)
236 push %a2
237 movdqa %xmm3, -0x50(%rbp)
238 push %a3
239 movdqa %xmm4, -0x40(%rbp)
240 push %a4
241 movdqa %xmm5, -0x30(%rbp)
242 push %a5
243 movdqa %xmm6, -0x20(%rbp)
244 push %a6
245 movdqa %xmm7, -0x10(%rbp)
246
247 .endmacro
248
249
250 //////////////////////////////////////////////////////////////////////
251 //
252 // RESTORE_REGS
253 //
254 // Restore all argument registers and pop the stack frame created by
255 // SAVE_REGS.
256 //////////////////////////////////////////////////////////////////////
257
258 .macro RESTORE_REGS
259
260 movdqa -0x80(%rbp), %xmm0
261 pop %a6
262 movdqa -0x70(%rbp), %xmm1
263 pop %a5
264 movdqa -0x60(%rbp), %xmm2
265 pop %a4
266 movdqa -0x50(%rbp), %xmm3
267 pop %a3
268 movdqa -0x40(%rbp), %xmm4
269 pop %a2
270 movdqa -0x30(%rbp), %xmm5
271 pop %a1
272 movdqa -0x20(%rbp), %xmm6
273 pop %rax
274 movdqa -0x10(%rbp), %xmm7
275 leave
276
277 .endmacro
278
279
280 /////////////////////////////////////////////////////////////////////
281 //
282 // CacheLookup return-type, caller
283 //
284 // Locate the implementation for a class in a selector's method cache.
285 //
286 // Takes:
287 // $0 = NORMAL, FPRET, FP2RET, STRET
288 // $1 = CALL, LOOKUP, GETIMP
289 // a1 or a2 (STRET) = receiver
290 // a2 or a3 (STRET) = selector
291 // r10 = class to search
292 //
293 // On exit: r10 clobbered
294 // (found) calls or returns IMP in r11, eq/ne set for forwarding
295 // (not found) jumps to LCacheMiss, class still in r10
296 //
297 /////////////////////////////////////////////////////////////////////
298
299 .macro CacheHit
300
301 // r11 = found bucket
302
303 .if $1 == GETIMP
304 movq cached_imp(%r11), %rax // return imp
305 cmpq $$0, %rax
306 jz 9f // don't xor a nil imp
307 xorq %r10, %rax // xor the isa with the imp
308 9: ret
309
310 .else
311
312 .if $1 == CALL
313 movq cached_imp(%r11), %r11 // load imp
314 xorq %r10, %r11 // xor imp and isa
315 .if $0 != STRET
316 // ne already set for forwarding by `xor`
317 .else
318 cmp %r11, %r11 // set eq for stret forwarding
319 .endif
320 jmp *%r11 // call imp
321
322 .elseif $1 == LOOKUP
323 movq cached_imp(%r11), %r11
324 xorq %r10, %r11 // return imp ^ isa
325 ret
326
327 .else
328 .abort oops
329 .endif
330
331 .endif
332
333 .endmacro
334
335
336 .macro CacheLookup
337 .if $0 != STRET
338 movq %a2, %r11 // r11 = _cmd
339 .else
340 movq %a3, %r11 // r11 = _cmd
341 .endif
342 andl 24(%r10), %r11d // r11 = _cmd & class->cache.mask
343 shlq $$4, %r11 // r11 = offset = (_cmd & mask)<<4
344 addq 16(%r10), %r11 // r11 = class->cache.buckets + offset
345
346 .if $0 != STRET
347 cmpq cached_sel(%r11), %a2 // if (bucket->sel != _cmd)
348 .else
349 cmpq cached_sel(%r11), %a3 // if (bucket->sel != _cmd)
350 .endif
351 jne 1f // scan more
352 CacheHit $0, $1 // call or return imp
353
354 1:
355 // loop
356 cmpq $$1, cached_sel(%r11)
357 jbe 3f // if (bucket->sel <= 1) wrap or miss
358
359 addq $$16, %r11 // bucket++
360 2:
361 .if $0 != STRET
362 cmpq cached_sel(%r11), %a2 // if (bucket->sel != _cmd)
363 .else
364 cmpq cached_sel(%r11), %a3 // if (bucket->sel != _cmd)
365 .endif
366 jne 1b // scan more
367 CacheHit $0, $1 // call or return imp
368
369 3:
370 // wrap or miss
371 jb LCacheMiss_f // if (bucket->sel < 1) cache miss
372 // wrap
373 movq cached_imp(%r11), %r11 // bucket->imp is really first bucket
374 jmp 2f
375
376 // Clone scanning loop to miss instead of hang when cache is corrupt.
377 // The slow path may detect any corruption and halt later.
378
379 1:
380 // loop
381 cmpq $$1, cached_sel(%r11)
382 jbe 3f // if (bucket->sel <= 1) wrap or miss
383
384 addq $$16, %r11 // bucket++
385 2:
386 .if $0 != STRET
387 cmpq cached_sel(%r11), %a2 // if (bucket->sel != _cmd)
388 .else
389 cmpq cached_sel(%r11), %a3 // if (bucket->sel != _cmd)
390 .endif
391 jne 1b // scan more
392 CacheHit $0, $1 // call or return imp
393
394 3:
395 // double wrap or miss
396 jmp LCacheMiss_f
397
398 .endmacro
399
400
401 /////////////////////////////////////////////////////////////////////
402 //
403 // MethodTableLookup NORMAL|STRET
404 //
405 // Takes: a1 or a2 (STRET) = receiver
406 // a2 or a3 (STRET) = selector to search for
407 // r10 = class to search
408 //
409 // On exit: imp in %r11, eq/ne set for forwarding
410 //
411 /////////////////////////////////////////////////////////////////////
412
413 .macro MethodTableLookup
414
415 SAVE_REGS
416
417 // lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
418 .if $0 == NORMAL
419 // receiver already in a1
420 // selector already in a2
421 .else
422 movq %a2, %a1
423 movq %a3, %a2
424 .endif
425 movq %r10, %a3
426 movl $$3, %a4d
427 call _lookUpImpOrForward
428
429 // IMP is now in %rax
430 movq %rax, %r11
431
432 RESTORE_REGS
433
434 .if $0 == NORMAL
435 test %r11, %r11 // set ne for stret forwarding
436 .else
437 cmp %r11, %r11 // set eq for nonstret forwarding
438 .endif
439
440 .endmacro
441
442
443 /////////////////////////////////////////////////////////////////////
444 //
445 // GetIsaCheckNil return-type
446 // GetIsaSupport return-type
447 // NilTestReturnZero return-type
448 // NilTestReturnIMP return-type
449 //
450 // Sets r10 = obj->isa.
451 // Looks up the real class if receiver is a tagged pointer object.
452 // Returns zero or a zero-returning IMP if obj is nil.
453 //
454 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
455 // a1 or a2 (STRET) = receiver
456 //
457 // On exit from GetIsaCheckNil:
458 // r10 = receiver->isa
459 // r11 is clobbered
460 //
461 /////////////////////////////////////////////////////////////////////
462
463 .macro ZeroReturn
464 xorl %eax, %eax
465 xorl %edx, %edx
466 xorps %xmm0, %xmm0
467 xorps %xmm1, %xmm1
468 .endmacro
469
470 .macro ZeroReturnFPRET
471 fldz
472 ZeroReturn
473 .endmacro
474
475 .macro ZeroReturnFP2RET
476 fldz
477 fldz
478 ZeroReturn
479 .endmacro
480
481 .macro ZeroReturnSTRET
482 // rax gets the struct-return address as passed in rdi
483 movq %rdi, %rax
484 .endmacro
485
486 STATIC_ENTRY __objc_msgNil
487 ZeroReturn
488 ret
489 END_ENTRY __objc_msgNil
490
491 STATIC_ENTRY __objc_msgNil_fpret
492 ZeroReturnFPRET
493 ret
494 END_ENTRY __objc_msgNil_fpret
495
496 STATIC_ENTRY __objc_msgNil_fp2ret
497 ZeroReturnFP2RET
498 ret
499 END_ENTRY __objc_msgNil_fp2ret
500
501 STATIC_ENTRY __objc_msgNil_stret
502 ZeroReturnSTRET
503 ret
504 END_ENTRY __objc_msgNil_stret
505
506
507 .macro GetIsaCheckNil
508 .if $0 != STRET
509 testq %a1, %a1
510 .else
511 testq %a2, %a2
512 .endif
513 jle LNilOrTagged_f // MSB tagged pointer looks negative
514
515 .if $0 != STRET
516 movq (%a1), %r10 // r10 = isa
517 .else
518 movq (%a2), %r10 // r10 = isa
519 .endif
520
521 LGetIsaDone:
522 .endmacro
523
524
525 .macro GetIsaSupport
526 .align 3
527 LNilOrTagged:
528 jz LNil_f // flags set by GetIsaCheckNil
529 .if $0 != STRET
530 movq %a1, %r11
531 .else
532 movq %a2, %r11
533 .endif
534 // basic tagged
535 shrq $$60, %r11
536 leaq _objc_debug_taggedpointer_classes(%rip), %r10
537 movq (%r10, %r11, 8), %r10 // read isa from table
538 leaq _OBJC_CLASS_$___NSUnrecognizedTaggedPointer(%rip), %r11
539 cmp %r10, %r11
540 jne LGetIsaDone_b
541 // ext tagged
542 .if $0 != STRET
543 movq %a1, %r11
544 .else
545 movq %a2, %r11
546 .endif
547 shrq $$52, %r11
548 andl $$0xff, %r11d
549 leaq _objc_debug_taggedpointer_ext_classes(%rip), %r10
550 movq (%r10, %r11, 8), %r10 // read isa from table
551 jmp LGetIsaDone_b
552 .endmacro
553
554
555 .macro NilTestReturnZero
556 LNil:
557 .if $0 == NORMAL
558 ZeroReturn
559 .elseif $0 == FPRET
560 ZeroReturnFPRET
561 .elseif $0 == FP2RET
562 ZeroReturnFP2RET
563 .elseif $0 == STRET
564 ZeroReturnSTRET
565 .else
566 .abort oops
567 .endif
568 ret
569 .endmacro
570
571
572 .macro NilTestReturnIMP
573 LNil:
574 .if $0 == NORMAL
575 leaq __objc_msgNil(%rip), %r11
576 .elseif $0 == FPRET
577 leaq __objc_msgNil_fpret(%rip), %r11
578 .elseif $0 == FP2RET
579 leaq __objc_msgNil_fp2ret(%rip), %r11
580 .elseif $0 == STRET
581 leaq __objc_msgNil_stret(%rip), %r11
582 .else
583 .abort oops
584 .endif
585 ret
586 .endmacro
587
588
589 /********************************************************************
590 * IMP cache_getImp(Class cls, SEL sel)
591 *
592 * On entry: a1 = class whose cache is to be searched
593 * a2 = selector to search for
594 *
595 * If found, returns method implementation.
596 * If not found, returns NULL.
597 ********************************************************************/
598
599 STATIC_ENTRY _cache_getImp
600
601 // do lookup
602 movq %a1, %r10 // move class to r10 for CacheLookup
603 CacheLookup NORMAL, GETIMP // returns IMP on success
604
605 LCacheMiss:
606 // cache miss, return nil
607 xorl %eax, %eax
608 ret
609
610 END_ENTRY _cache_getImp
611
612
613 /********************************************************************
614 *
615 * id objc_msgSend(id self, SEL _cmd,...);
616 * IMP objc_msgLookup(id self, SEL _cmd, ...);
617 *
618 * objc_msgLookup ABI:
619 * IMP returned in r11
620 * Forwarding returned in Z flag
621 * r10 reserved for our use but not used
622 *
623 ********************************************************************/
624
625 .data
626 .align 3
627 .globl _objc_debug_taggedpointer_classes
628 _objc_debug_taggedpointer_classes:
629 .fill 16, 8, 0
630 .globl _objc_debug_taggedpointer_ext_classes
631 _objc_debug_taggedpointer_ext_classes:
632 .fill 256, 8, 0
633
634 ENTRY _objc_msgSend
635 UNWIND _objc_msgSend, NoFrame
636
637 GetIsaCheckNil NORMAL // r10 = self->isa, or return zero
638 CacheLookup NORMAL, CALL // calls IMP on success
639
640 GetIsaSupport NORMAL
641 NilTestReturnZero NORMAL
642
643 // cache miss: go search the method lists
644 LCacheMiss:
645 // isa still in r10
646 jmp __objc_msgSend_uncached
647
648 END_ENTRY _objc_msgSend
649
650
651 ENTRY _objc_msgLookup
652
653 GetIsaCheckNil NORMAL // r10 = self->isa, or return zero IMP
654 CacheLookup NORMAL, LOOKUP // returns IMP on success
655
656 GetIsaSupport NORMAL
657 NilTestReturnIMP NORMAL
658
659 // cache miss: go search the method lists
660 LCacheMiss:
661 // isa still in r10
662 jmp __objc_msgLookup_uncached
663
664 END_ENTRY _objc_msgLookup
665
666
667 ENTRY _objc_msgSend_fixup
668 int3
669 END_ENTRY _objc_msgSend_fixup
670
671
672 STATIC_ENTRY _objc_msgSend_fixedup
673 // Load _cmd from the message_ref
674 movq 8(%a2), %a2
675 jmp _objc_msgSend
676 END_ENTRY _objc_msgSend_fixedup
677
678
679 /********************************************************************
680 *
681 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
682 *
683 * struct objc_super {
684 * id receiver;
685 * Class class;
686 * };
687 ********************************************************************/
688
689 ENTRY _objc_msgSendSuper
690 UNWIND _objc_msgSendSuper, NoFrame
691
692 // search the cache (objc_super in %a1)
693 movq class(%a1), %r10 // class = objc_super->class
694 movq receiver(%a1), %a1 // load real receiver
695 CacheLookup NORMAL, CALL // calls IMP on success
696
697 // cache miss: go search the method lists
698 LCacheMiss:
699 // class still in r10
700 jmp __objc_msgSend_uncached
701
702 END_ENTRY _objc_msgSendSuper
703
704
705 /********************************************************************
706 * id objc_msgSendSuper2
707 ********************************************************************/
708
709 ENTRY _objc_msgSendSuper2
710 UNWIND _objc_msgSendSuper2, NoFrame
711
712 // objc_super->class is superclass of class to search
713
714 // search the cache (objc_super in %a1)
715 movq class(%a1), %r10 // cls = objc_super->class
716 movq receiver(%a1), %a1 // load real receiver
717 movq 8(%r10), %r10 // cls = class->superclass
718 CacheLookup NORMAL, CALL // calls IMP on success
719
720 // cache miss: go search the method lists
721 LCacheMiss:
722 // superclass still in r10
723 jmp __objc_msgSend_uncached
724
725 END_ENTRY _objc_msgSendSuper2
726
727
728 ENTRY _objc_msgLookupSuper2
729
730 // objc_super->class is superclass of class to search
731
732 // search the cache (objc_super in %a1)
733 movq class(%a1), %r10 // cls = objc_super->class
734 movq receiver(%a1), %a1 // load real receiver
735 movq 8(%r10), %r10 // cls = class->superclass
736 CacheLookup NORMAL, LOOKUP // returns IMP on success
737
738 // cache miss: go search the method lists
739 LCacheMiss:
740 // superclass still in r10
741 jmp __objc_msgLookup_uncached
742
743 END_ENTRY _objc_msgLookupSuper2
744
745
746 ENTRY _objc_msgSendSuper2_fixup
747 int3
748 END_ENTRY _objc_msgSendSuper2_fixup
749
750
751 STATIC_ENTRY _objc_msgSendSuper2_fixedup
752 // Load _cmd from the message_ref
753 movq 8(%a2), %a2
754 jmp _objc_msgSendSuper2
755 END_ENTRY _objc_msgSendSuper2_fixedup
756
757
758 /********************************************************************
759 *
760 * double objc_msgSend_fpret(id self, SEL _cmd,...);
761 * Used for `long double` return only. `float` and `double` use objc_msgSend.
762 *
763 ********************************************************************/
764
765 ENTRY _objc_msgSend_fpret
766 UNWIND _objc_msgSend_fpret, NoFrame
767
768 GetIsaCheckNil FPRET // r10 = self->isa, or return zero
769 CacheLookup FPRET, CALL // calls IMP on success
770
771 GetIsaSupport FPRET
772 NilTestReturnZero FPRET
773
774 // cache miss: go search the method lists
775 LCacheMiss:
776 // isa still in r10
777 jmp __objc_msgSend_uncached
778
779 END_ENTRY _objc_msgSend_fpret
780
781
782 ENTRY _objc_msgLookup_fpret
783
784 GetIsaCheckNil FPRET // r10 = self->isa, or return zero IMP
785 CacheLookup FPRET, LOOKUP // returns IMP on success
786
787 GetIsaSupport FPRET
788 NilTestReturnIMP FPRET
789
790 // cache miss: go search the method lists
791 LCacheMiss:
792 // isa still in r10
793 jmp __objc_msgLookup_uncached
794
795 END_ENTRY _objc_msgLookup_fpret
796
797
798 ENTRY _objc_msgSend_fpret_fixup
799 int3
800 END_ENTRY _objc_msgSend_fpret_fixup
801
802
803 STATIC_ENTRY _objc_msgSend_fpret_fixedup
804 // Load _cmd from the message_ref
805 movq 8(%a2), %a2
806 jmp _objc_msgSend_fpret
807 END_ENTRY _objc_msgSend_fpret_fixedup
808
809
810 /********************************************************************
811 *
812 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
813 * Used for `complex long double` return only.
814 *
815 ********************************************************************/
816
817 ENTRY _objc_msgSend_fp2ret
818 UNWIND _objc_msgSend_fp2ret, NoFrame
819
820 GetIsaCheckNil FP2RET // r10 = self->isa, or return zero
821 CacheLookup FP2RET, CALL // calls IMP on success
822
823 GetIsaSupport FP2RET
824 NilTestReturnZero FP2RET
825
826 // cache miss: go search the method lists
827 LCacheMiss:
828 // isa still in r10
829 jmp __objc_msgSend_uncached
830
831 END_ENTRY _objc_msgSend_fp2ret
832
833
834 ENTRY _objc_msgLookup_fp2ret
835
836 GetIsaCheckNil FP2RET // r10 = self->isa, or return zero IMP
837 CacheLookup FP2RET, LOOKUP // returns IMP on success
838
839 GetIsaSupport FP2RET
840 NilTestReturnIMP FP2RET
841
842 // cache miss: go search the method lists
843 LCacheMiss:
844 // isa still in r10
845 jmp __objc_msgLookup_uncached
846
847 END_ENTRY _objc_msgLookup_fp2ret
848
849
850 ENTRY _objc_msgSend_fp2ret_fixup
851 int3
852 END_ENTRY _objc_msgSend_fp2ret_fixup
853
854
855 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
856 // Load _cmd from the message_ref
857 movq 8(%a2), %a2
858 jmp _objc_msgSend_fp2ret
859 END_ENTRY _objc_msgSend_fp2ret_fixedup
860
861
862 /********************************************************************
863 *
864 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
865 *
866 * objc_msgSend_stret is the struct-return form of msgSend.
867 * The ABI calls for %a1 to be used as the address of the structure
868 * being returned, with the parameters in the succeeding locations.
869 *
870 * On entry: %a1 is the address where the structure is returned,
871 * %a2 is the message receiver,
872 * %a3 is the selector
873 ********************************************************************/
874
875 ENTRY _objc_msgSend_stret
876 UNWIND _objc_msgSend_stret, NoFrame
877
878 GetIsaCheckNil STRET // r10 = self->isa, or return zero
879 CacheLookup STRET, CALL // calls IMP on success
880
881 GetIsaSupport STRET
882 NilTestReturnZero STRET
883
884 // cache miss: go search the method lists
885 LCacheMiss:
886 // isa still in r10
887 jmp __objc_msgSend_stret_uncached
888
889 END_ENTRY _objc_msgSend_stret
890
891
892 ENTRY _objc_msgLookup_stret
893
894 GetIsaCheckNil STRET // r10 = self->isa, or return zero IMP
895 CacheLookup STRET, LOOKUP // returns IMP on success
896
897 GetIsaSupport STRET
898 NilTestReturnIMP STRET
899
900 // cache miss: go search the method lists
901 LCacheMiss:
902 // isa still in r10
903 jmp __objc_msgLookup_stret_uncached
904
905 END_ENTRY _objc_msgLookup_stret
906
907
908 ENTRY _objc_msgSend_stret_fixup
909 int3
910 END_ENTRY _objc_msgSend_stret_fixup
911
912
913 STATIC_ENTRY _objc_msgSend_stret_fixedup
914 // Load _cmd from the message_ref
915 movq 8(%a3), %a3
916 jmp _objc_msgSend_stret
917 END_ENTRY _objc_msgSend_stret_fixedup
918
919
920 /********************************************************************
921 *
922 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
923 *
924 * struct objc_super {
925 * id receiver;
926 * Class class;
927 * };
928 *
929 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
930 * The ABI calls for (sp+4) to be used as the address of the structure
931 * being returned, with the parameters in the succeeding registers.
932 *
933 * On entry: %a1 is the address where the structure is returned,
934 * %a2 is the address of the objc_super structure,
935 * %a3 is the selector
936 *
937 ********************************************************************/
938
939 ENTRY _objc_msgSendSuper_stret
940 UNWIND _objc_msgSendSuper_stret, NoFrame
941
942 // search the cache (objc_super in %a2)
943 movq class(%a2), %r10 // class = objc_super->class
944 movq receiver(%a2), %a2 // load real receiver
945 CacheLookup STRET, CALL // calls IMP on success
946
947 // cache miss: go search the method lists
948 LCacheMiss:
949 // class still in r10
950 jmp __objc_msgSend_stret_uncached
951
952 END_ENTRY _objc_msgSendSuper_stret
953
954
955 /********************************************************************
956 * id objc_msgSendSuper2_stret
957 ********************************************************************/
958
959 ENTRY _objc_msgSendSuper2_stret
960 UNWIND _objc_msgSendSuper2_stret, NoFrame
961
962 // search the cache (objc_super in %a2)
963 movq class(%a2), %r10 // class = objc_super->class
964 movq receiver(%a2), %a2 // load real receiver
965 movq 8(%r10), %r10 // class = class->superclass
966 CacheLookup STRET, CALL // calls IMP on success
967
968 // cache miss: go search the method lists
969 LCacheMiss:
970 // superclass still in r10
971 jmp __objc_msgSend_stret_uncached
972
973 END_ENTRY _objc_msgSendSuper2_stret
974
975
976 ENTRY _objc_msgLookupSuper2_stret
977
978 // search the cache (objc_super in %a2)
979 movq class(%a2), %r10 // class = objc_super->class
980 movq receiver(%a2), %a2 // load real receiver
981 movq 8(%r10), %r10 // class = class->superclass
982 CacheLookup STRET, LOOKUP // returns IMP on success
983
984 // cache miss: go search the method lists
985 LCacheMiss:
986 // superclass still in r10
987 jmp __objc_msgLookup_stret_uncached
988
989 END_ENTRY _objc_msgLookupSuper2_stret
990
991
992 ENTRY _objc_msgSendSuper2_stret_fixup
993 int3
994 END_ENTRY _objc_msgSendSuper2_stret_fixup
995
996
997 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
998 // Load _cmd from the message_ref
999 movq 8(%a3), %a3
1000 jmp _objc_msgSendSuper2_stret
1001 END_ENTRY _objc_msgSendSuper2_stret_fixedup
1002
1003
1004 /********************************************************************
1005 *
1006 * _objc_msgSend_uncached
1007 * _objc_msgSend_stret_uncached
1008 * The uncached method lookup.
1009 *
1010 ********************************************************************/
1011
1012 STATIC_ENTRY __objc_msgSend_uncached
1013 UNWIND __objc_msgSend_uncached, FrameWithNoSaves
1014
1015 // THIS IS NOT A CALLABLE C FUNCTION
1016 // Out-of-band r10 is the searched class
1017
1018 // r10 is already the class to search
1019 MethodTableLookup NORMAL // r11 = IMP
1020 jmp *%r11 // goto *imp
1021
1022 END_ENTRY __objc_msgSend_uncached
1023
1024
1025 STATIC_ENTRY __objc_msgSend_stret_uncached
1026 UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves
1027
1028 // THIS IS NOT A CALLABLE C FUNCTION
1029 // Out-of-band r10 is the searched class
1030
1031 // r10 is already the class to search
1032 MethodTableLookup STRET // r11 = IMP
1033 jmp *%r11 // goto *imp
1034
1035 END_ENTRY __objc_msgSend_stret_uncached
1036
1037
1038 STATIC_ENTRY __objc_msgLookup_uncached
1039 UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
1040
1041 // THIS IS NOT A CALLABLE C FUNCTION
1042 // Out-of-band r10 is the searched class
1043
1044 // r10 is already the class to search
1045 MethodTableLookup NORMAL // r11 = IMP
1046 ret
1047
1048 END_ENTRY __objc_msgLookup_uncached
1049
1050
1051 STATIC_ENTRY __objc_msgLookup_stret_uncached
1052 UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves
1053
1054 // THIS IS NOT A CALLABLE C FUNCTION
1055 // Out-of-band r10 is the searched class
1056
1057 // r10 is already the class to search
1058 MethodTableLookup STRET // r11 = IMP
1059 ret
1060
1061 END_ENTRY __objc_msgLookup_stret_uncached
1062
1063
1064 /********************************************************************
1065 *
1066 * id _objc_msgForward(id self, SEL _cmd,...);
1067 *
1068 * _objc_msgForward and _objc_msgForward_stret are the externally-callable
1069 * functions returned by things like method_getImplementation().
1070 * _objc_msgForward_impcache is the function pointer actually stored in
1071 * method caches.
1072 *
1073 ********************************************************************/
1074
1075 STATIC_ENTRY __objc_msgForward_impcache
1076 // Method cache version
1077
1078 // THIS IS NOT A CALLABLE C FUNCTION
1079 // Out-of-band condition register is NE for stret, EQ otherwise.
1080
1081 je __objc_msgForward_stret
1082 jmp __objc_msgForward
1083
1084 END_ENTRY __objc_msgForward_impcache
1085
1086
1087 ENTRY __objc_msgForward
1088 // Non-stret version
1089
1090 movq __objc_forward_handler(%rip), %r11
1091 jmp *%r11
1092
1093 END_ENTRY __objc_msgForward
1094
1095
1096 ENTRY __objc_msgForward_stret
1097 // Struct-return version
1098
1099 movq __objc_forward_stret_handler(%rip), %r11
1100 jmp *%r11
1101
1102 END_ENTRY __objc_msgForward_stret
1103
1104
1105 ENTRY _objc_msgSend_debug
1106 jmp _objc_msgSend
1107 END_ENTRY _objc_msgSend_debug
1108
1109 ENTRY _objc_msgSendSuper2_debug
1110 jmp _objc_msgSendSuper2
1111 END_ENTRY _objc_msgSendSuper2_debug
1112
1113 ENTRY _objc_msgSend_stret_debug
1114 jmp _objc_msgSend_stret
1115 END_ENTRY _objc_msgSend_stret_debug
1116
1117 ENTRY _objc_msgSendSuper2_stret_debug
1118 jmp _objc_msgSendSuper2_stret
1119 END_ENTRY _objc_msgSendSuper2_stret_debug
1120
1121 ENTRY _objc_msgSend_fpret_debug
1122 jmp _objc_msgSend_fpret
1123 END_ENTRY _objc_msgSend_fpret_debug
1124
1125 ENTRY _objc_msgSend_fp2ret_debug
1126 jmp _objc_msgSend_fp2ret
1127 END_ENTRY _objc_msgSend_fp2ret_debug
1128
1129
1130 ENTRY _objc_msgSend_noarg
1131 jmp _objc_msgSend
1132 END_ENTRY _objc_msgSend_noarg
1133
1134
1135 ENTRY _method_invoke
1136
1137 // See if this is a small method.
1138 testb $1, %a2b
1139 jnz L_method_invoke_small
1140
1141 // We can directly load the IMP from big methods.
1142 movq method_imp(%a2), %r11
1143 movq method_name(%a2), %a2
1144 jmp *%r11
1145
1146 L_method_invoke_small:
1147 // Small methods require a call to handle swizzling.
1148 SAVE_REGS
1149 movq %a2, %a1
1150 call __method_getImplementationAndName
1151 movq %rdx, %r10
1152 movq %rax, %r11
1153 RESTORE_REGS
1154 movq %r10, %a2
1155 jmp *%r11
1156
1157 END_ENTRY _method_invoke
1158
1159
1160 ENTRY _method_invoke_stret
1161
1162 // See if this is a small method.
1163 testb $1, %a3b
1164 jnz L_method_invoke_stret_small
1165
1166 // We can directly load the IMP from big methods.
1167 movq method_imp(%a3), %r11
1168 movq method_name(%a3), %a3
1169 jmp *%r11
1170
1171 L_method_invoke_stret_small:
1172 // Small methods require a call to handle swizzling.
1173 SAVE_REGS
1174 movq %a3, %a1
1175 call __method_getImplementationAndName
1176 movq %rdx, %r10
1177 movq %rax, %r11
1178 RESTORE_REGS
1179 movq %r10, %a3
1180 jmp *%r11
1181
1182 END_ENTRY _method_invoke_stret
1183
1184
1185 .section __DATA,__objc_msg_break
1186 .quad 0
1187 .quad 0
1188
1189 #endif