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