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