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