]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-x86_64.s
objc4-551.1.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-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 #ifdef __x86_64__
25
26 /********************************************************************
27 ********************************************************************
28 **
29 ** objc-msg-x86_64.s - x86-64 code to support objc messaging.
30 **
31 ********************************************************************
32 ********************************************************************/
33
34 /********************************************************************
35 * Data used by the ObjC runtime.
36 *
37 ********************************************************************/
38
39 .data
40 // Substitute receiver for messages sent to nil (usually also nil)
41 // id _objc_nilReceiver
42 .align 4
43 .private_extern __objc_nilReceiver
44 __objc_nilReceiver:
45 .quad 0
46
47 // _objc_entryPoints and _objc_exitPoints are used by objc
48 // to get the critical regions for which method caches
49 // cannot be garbage collected.
50
51 .private_extern _objc_entryPoints
52 _objc_entryPoints:
53 .quad _cache_getImp
54 .quad _objc_msgSend
55 .quad _objc_msgSend_fpret
56 .quad _objc_msgSend_fp2ret
57 .quad _objc_msgSend_stret
58 .quad _objc_msgSendSuper
59 .quad _objc_msgSendSuper_stret
60 .quad _objc_msgSendSuper2
61 .quad _objc_msgSendSuper2_stret
62 .quad 0
63
64 .private_extern _objc_exitPoints
65 _objc_exitPoints:
66 .quad LExit_cache_getImp
67 .quad LExit_objc_msgSend
68 .quad LExit_objc_msgSend_fpret
69 .quad LExit_objc_msgSend_fp2ret
70 .quad LExit_objc_msgSend_stret
71 .quad LExit_objc_msgSendSuper
72 .quad LExit_objc_msgSendSuper_stret
73 .quad LExit_objc_msgSendSuper2
74 .quad LExit_objc_msgSendSuper2_stret
75 .quad 0
76
77
78 /********************************************************************
79 * List every exit insn from every messenger for debugger use.
80 * Format:
81 * (
82 * 1 word instruction's address
83 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
84 * )
85 * 1 word zero
86 *
87 * ENTER is the start of a dispatcher
88 * FAST_EXIT is method dispatch
89 * SLOW_EXIT is uncached method lookup
90 * NIL_EXIT is returning zero from a message sent to nil
91 * These must match objc-gdb.h.
92 ********************************************************************/
93
94 #define ENTER 1
95 #define FAST_EXIT 2
96 #define SLOW_EXIT 3
97 #define NIL_EXIT 4
98
99 .section __DATA,__objc_msg_break
100 .globl _gdb_objc_messenger_breakpoints
101 _gdb_objc_messenger_breakpoints:
102 // contents populated by the macros below
103
104 .macro MESSENGER_START
105 4:
106 .section __DATA,__objc_msg_break
107 .quad 4b
108 .quad ENTER
109 .text
110 .endmacro
111 .macro MESSENGER_END_FAST
112 4:
113 .section __DATA,__objc_msg_break
114 .quad 4b
115 .quad FAST_EXIT
116 .text
117 .endmacro
118 .macro MESSENGER_END_SLOW
119 4:
120 .section __DATA,__objc_msg_break
121 .quad 4b
122 .quad SLOW_EXIT
123 .text
124 .endmacro
125 .macro MESSENGER_END_NIL
126 4:
127 .section __DATA,__objc_msg_break
128 .quad 4b
129 .quad NIL_EXIT
130 .text
131 .endmacro
132
133
134 /********************************************************************
135 * Recommended multi-byte NOP instructions
136 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
137 ********************************************************************/
138 #define nop1 .byte 0x90
139 #define nop2 .byte 0x66,0x90
140 #define nop3 .byte 0x0F,0x1F,0x00
141 #define nop4 .byte 0x0F,0x1F,0x40,0x00
142 #define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
143 #define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
144 #define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
145 #define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
146 #define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
147
148
149 /********************************************************************
150 * Harmless branch prefix hint for instruction alignment
151 ********************************************************************/
152
153 #define PN .byte 0x2e
154
155
156 /********************************************************************
157 * Names for parameter registers.
158 ********************************************************************/
159
160 #define a1 rdi
161 #define a1d edi
162 #define a1b dil
163 #define a2 rsi
164 #define a2d esi
165 #define a2b sil
166 #define a3 rdx
167 #define a3d edx
168 #define a4 rcx
169 #define a4d ecx
170 #define a5 r8
171 #define a5d r8d
172 #define a6 r9
173 #define a6d r9d
174
175
176 /********************************************************************
177 * Names for relative labels
178 * DO NOT USE THESE LABELS ELSEWHERE
179 * Reserved labels: 5: 6: 7: 8: 9:
180 ********************************************************************/
181 #define LCacheMiss 5
182 #define LCacheMiss_f 5f
183 #define LCacheMiss_b 5b
184 #define LNilTestDone 6
185 #define LNilTestDone_f 6f
186 #define LNilTestDone_b 6b
187 #define LNilTestSlow 7
188 #define LNilTestSlow_f 7f
189 #define LNilTestSlow_b 7b
190 #define LGetIsaDone 8
191 #define LGetIsaDone_f 8f
192 #define LGetIsaDone_b 8b
193 #define LGetIsaSlow 9
194 #define LGetIsaSlow_f 9f
195 #define LGetIsaSlow_b 9b
196
197 /********************************************************************
198 * Macro parameters
199 ********************************************************************/
200
201 #define NORMAL 0
202 #define FPRET 1
203 #define FP2RET 2
204 #define GETIMP 3
205 #define STRET 4
206 #define SUPER 5
207 #define SUPER_STRET 6
208 #define SUPER2 7
209 #define SUPER2_STRET 8
210
211
212 /********************************************************************
213 *
214 * Structure definitions.
215 *
216 ********************************************************************/
217
218 // objc_super parameter to sendSuper
219 #define receiver 0
220 #define class 8
221
222 // Selected field offsets in class structure
223 // #define isa 0 USE GetIsa INSTEAD
224
225 // Method descriptor
226 #define method_name 0
227 #define method_imp 16
228
229 // typedef struct {
230 // uint128_t floatingPointArgs[8]; // xmm0..xmm7
231 // long linkageArea[4]; // r10, rax, ebp, ret
232 // long registerArgs[6]; // a1..a6
233 // long stackArgs[0]; // variable-size
234 // } *marg_list;
235 #define FP_AREA 0
236 #define LINK_AREA (FP_AREA+8*16)
237 #define REG_AREA (LINK_AREA+4*8)
238 #define STACK_AREA (REG_AREA+6*8)
239
240
241 //////////////////////////////////////////////////////////////////////
242 //
243 // ENTRY functionName
244 //
245 // Assembly directives to begin an exported function.
246 //
247 // Takes: functionName - name of the exported function
248 //////////////////////////////////////////////////////////////////////
249
250 .macro ENTRY
251 .text
252 .globl $0
253 .align 6, 0x90
254 $0:
255 .endmacro
256
257 .macro STATIC_ENTRY
258 .text
259 .private_extern $0
260 .align 2, 0x90
261 $0:
262 .endmacro
263
264 //////////////////////////////////////////////////////////////////////
265 //
266 // END_ENTRY functionName
267 //
268 // Assembly directives to end an exported function. Just a placeholder,
269 // a close-parenthesis for ENTRY, until it is needed for something.
270 //
271 // Takes: functionName - name of the exported function
272 //////////////////////////////////////////////////////////////////////
273
274 .macro END_ENTRY
275 LExit$0:
276 .endmacro
277
278
279 /* DWARF support
280 These macros work for objc_msgSend variants and others that call
281 CacheLookup/MethodTableLookup or SaveRegisters/RestoreRegisters
282 without otherwise building a frame or clobbering callee-save registers
283
284 The macros build appropriate FDEs and tie them to the CIE.
285 */
286
287 #define DW_CFA_offset 0x80
288 #define DW_CFA_restore 0xc0
289 #define DW_CFA_advance_loc4 0x4
290 #define DW_CFA_same_value 0x8
291 #define DW_CFA_def_cfa 0xc
292 #define DW_CFA_def_cfa_register 0xd
293 #define DW_CFA_def_cfa_offset 0xe
294 #define DW_CFA_offset_extended_sf 0x11
295 #define DW_CFA_def_cfa_offset_sf 0x13
296 #define DW_rax 0
297 #define DW_rdx 1
298 #define DW_rcx 2
299 #define DW_rsi 4
300 #define DW_rdi 5
301 #define DW_rbp 6
302 #define DW_rsp 7
303 #define DW_r8 8
304 #define DW_r9 9
305 #define DW_r10 10
306 #define DW_ra 16
307 #define DW_xmm0 17
308 #define DW_xmm1 18
309 #define DW_xmm2 19
310 #define DW_xmm3 20
311 #define DW_xmm4 21
312 #define DW_xmm5 22
313 #define DW_xmm6 23
314 #define DW_xmm7 24
315 #define DW_a1 DW_rdi
316 #define DW_a2 DW_rsi
317 #define DW_a3 DW_rdx
318 #define DW_a4 DW_rcx
319 #define DW_a5 DW_r8
320 #define DW_a6 DW_r9
321
322 // CIE
323 // 8-byte data multiplier
324 // 1-byte insn multiplier
325 // PC-relative everything
326 // No prologue
327
328 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
329 CIE:
330 .set L$set$0,LECIE1-LSCIE1
331 .long L$set$0 # Length of Common Information Entry
332 LSCIE1:
333 .long 0 # CIE Identifier Tag
334 .byte 0x3 # CIE Version
335 .ascii "zPR\0" # CIE Augmentation: size + personality + FDE encoding
336 .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
337 .byte 0x78 # sleb128 -0x8; CIE Data Alignment Factor
338 .byte 0x10 # CIE RA Column
339 .byte 0x6 # uleb128 0x1; Augmentation size
340 // Personality augmentation
341 .byte 0x9b
342 .long ___objc_personality_v0+4@GOTPCREL
343 // FDE-encoding augmentation
344 .byte 0x10
345 // Prefix instructions
346 // CFA is %rsp+8
347 .byte DW_CFA_def_cfa
348 .byte DW_rsp
349 .byte 8
350 // RA is at 0(%rsp) aka 1*-8(CFA)
351 .byte DW_CFA_offset | DW_ra
352 .byte 1
353
354 .align 3
355 LECIE1:
356
357
358 .macro EMIT_FDE
359
360 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
361
362 // FDE header
363 .globl $0.eh
364 $0.eh:
365 LSFDE$0:
366 .set LLENFDE$0, LEFDE$0-LASFDE$0
367 .long LLENFDE$0 # FDE Length
368 LASFDE$0:
369 .long LASFDE$0-CIE # FDE CIE offset
370 .quad L_dw_start_$0-. # FDE address start
371 .quad L_dw_len_$0 # FDE address range
372 .byte 0x0 # uleb128 0x0; Augmentation size
373
374 // DW_START: set by CIE
375
376 .if $1 == 1
377 // Save/RestoreRegisters or MethodTableLookup
378
379 // enter
380 .byte DW_CFA_advance_loc4
381 .long L_dw_enter_$0 - L_dw_start_$0
382 .byte DW_CFA_def_cfa_offset
383 .byte 16
384 .byte DW_CFA_offset | DW_rbp // rbp => 2*-8(CFA)
385 .byte 2
386 .byte DW_CFA_def_cfa_register // CFA = rbp+16 (offset unchanged)
387 .byte DW_rbp
388
389 // leave
390 .byte DW_CFA_advance_loc4
391 .long L_dw_leave_$0 - L_dw_enter_$0
392
393 .byte DW_CFA_same_value // rbp = original value
394 .byte DW_rbp
395 .byte DW_CFA_def_cfa // CFA = rsp+8
396 .byte DW_rsp
397 .byte 8
398
399 .endif
400
401 .align 3
402 LEFDE$0:
403 .text
404
405 .endmacro
406
407
408 // Start of function
409 .macro DW_START
410 L_dw_start_$0:
411 .endmacro
412
413 // After `enter` in SaveRegisters
414 .macro DW_ENTER
415 L_dw_enter_$0:
416 .endmacro
417
418 // After `leave` in RestoreRegisters
419 .macro DW_LEAVE
420 L_dw_leave_$0:
421 .endmacro
422
423 // End of function
424 // $1 == 1 iff you called MethodTableLookup or Save/RestoreRegsters
425 .macro DW_END
426 .set L_dw_len_$0, . - L_dw_start_$0
427 EMIT_FDE $0, $1
428 .endmacro
429
430
431 /////////////////////////////////////////////////////////////////////
432 //
433 // SaveRegisters caller
434 //
435 // Pushes a stack frame and saves all registers that might contain
436 // parameter values.
437 //
438 // On entry: %0 = caller's symbol name for DWARF
439 // stack = ret
440 //
441 // On exit:
442 // %rsp is 16-byte aligned
443 //
444 /////////////////////////////////////////////////////////////////////
445
446 .macro SaveRegisters
447 // These instructions must match the DWARF data in EMIT_FDE.
448
449 enter $$0x80+8, $$0 // +8 for alignment
450 DW_ENTER $0
451
452 movdqa %xmm0, -0x80(%rbp)
453 push %rax // might be xmm parameter count
454 movdqa %xmm1, -0x70(%rbp)
455 push %a1
456 movdqa %xmm2, -0x60(%rbp)
457 push %a2
458 movdqa %xmm3, -0x50(%rbp)
459 push %a3
460 movdqa %xmm4, -0x40(%rbp)
461 push %a4
462 movdqa %xmm5, -0x30(%rbp)
463 push %a5
464 movdqa %xmm6, -0x20(%rbp)
465 push %a6
466 movdqa %xmm7, -0x10(%rbp)
467
468 // These instructions must match the DWARF data in EMIT_FDE.
469 .endmacro
470
471 /////////////////////////////////////////////////////////////////////
472 //
473 // RestoreRegisters
474 //
475 // Pops a stack frame pushed by SaveRegisters
476 //
477 // On entry: $0 = caller's symbol name for DWARF
478 // %rbp unchanged since SaveRegisters
479 //
480 // On exit:
481 // stack = ret
482 //
483 /////////////////////////////////////////////////////////////////////
484
485 .macro RestoreRegisters
486 // These instructions must match the DWARF data in EMIT_FDE.
487
488 movdqa -0x80(%rbp), %xmm0
489 pop %a6
490 movdqa -0x70(%rbp), %xmm1
491 pop %a5
492 movdqa -0x60(%rbp), %xmm2
493 pop %a4
494 movdqa -0x50(%rbp), %xmm3
495 pop %a3
496 movdqa -0x40(%rbp), %xmm4
497 pop %a2
498 movdqa -0x30(%rbp), %xmm5
499 pop %a1
500 movdqa -0x20(%rbp), %xmm6
501 pop %rax
502 movdqa -0x10(%rbp), %xmm7
503
504 leave
505 DW_LEAVE $0
506
507 // These instructions must match the DWARF data in EMIT_FDE.
508 .endmacro
509
510
511 /////////////////////////////////////////////////////////////////////
512 //
513 // CacheLookup return-type, caller
514 //
515 // Locate the implementation for a class in a selector's method cache.
516 //
517 // Takes:
518 // $0 = NORMAL, FPRET, FP2RET, STRET, SUPER, SUPER_STRET, SUPER2, SUPER2_STRET, GETIMP
519 // a2 or a3 (STRET) = selector a.k.a. cache
520 // r11 = class to search
521 //
522 // On exit: r10 clobbered
523 // (found) calls or returns IMP, eq/ne/r11 set for forwarding
524 // (not found) jumps to LCacheMiss, class still in r11
525 //
526 /////////////////////////////////////////////////////////////////////
527
528 .macro CacheHit
529
530 // CacheHit must always be preceded by a not-taken `jne` instruction
531 // in order to set the correct flags for _objc_msgForward_impcache.
532
533 // r10 = found bucket
534
535 .if $0 == GETIMP
536 movq 8(%r10), %rax // return imp
537 leaq __objc_msgSend_uncached_impcache(%rip), %r11
538 cmpq %rax, %r11
539 jne 4f
540 xorl %eax, %eax // don't return msgSend_uncached
541 4: ret
542 .elseif $0 == NORMAL || $0 == FPRET || $0 == FP2RET
543 // eq already set for forwarding by `jne`
544 MESSENGER_END_FAST
545 jmp *8(%r10) // call imp
546
547 .elseif $0 == SUPER
548 movq receiver(%a1), %a1 // load real receiver
549 cmp %r10, %r10 // set eq for non-stret forwarding
550 MESSENGER_END_FAST
551 jmp *8(%r10) // call imp
552
553 .elseif $0 == SUPER2
554 movq receiver(%a1), %a1 // load real receiver
555 cmp %r10, %r10 // set eq for non-stret forwarding
556 MESSENGER_END_FAST
557 jmp *8(%r10) // call imp
558
559 .elseif $0 == STRET
560 test %r10, %r10 // set ne for stret forwarding
561 MESSENGER_END_FAST
562 jmp *8(%r10) // call imp
563
564 .elseif $0 == SUPER_STRET
565 movq receiver(%a2), %a2 // load real receiver
566 test %r10, %r10 // set ne for stret forwarding
567 MESSENGER_END_FAST
568 jmp *8(%r10) // call imp
569
570 .elseif $0 == SUPER2_STRET
571 movq receiver(%a2), %a2 // load real receiver
572 test %r10, %r10 // set ne for stret forwarding
573 MESSENGER_END_FAST
574 jmp *8(%r10) // call imp
575 .else
576 .abort oops
577 .endif
578
579 .endmacro
580
581
582 .macro CacheLookup
583 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
584 movq %a2, %r10 // r10 = _cmd
585 .else
586 movq %a3, %r10 // r10 = _cmd
587 .endif
588 andl 24(%r11), %r10d // r10 = _cmd & class->cache.mask
589 shlq $$4, %r10 // r10 = offset = (_cmd & mask)<<4
590 addq 16(%r11), %r10 // r10 = class->cache.buckets + offset
591
592 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
593 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
594 .else
595 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
596 .endif
597 jne 1f // scan more
598 // CacheHit must always be preceded by a not-taken `jne` instruction
599 CacheHit $0 // call or return imp
600
601 1:
602 // loop
603 cmpq $$0, (%r10)
604 je LCacheMiss_f // if (bucket->sel == 0) cache miss
605 cmpq 16(%r11), %r10
606 je 3f // if (bucket == cache->buckets) wrap
607
608 subq $$16, %r10 // bucket--
609 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
610 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
611 .else
612 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
613 .endif
614 jne 1b // scan more
615 // CacheHit must always be preceded by a not-taken `jne` instruction
616 CacheHit $0 // call or return imp
617
618 3:
619 // wrap
620 movl 24(%r11), %r10d // r10 = mask a.k.a. last bucket index
621 shlq $$4, %r10 // r10 = offset = mask<<4
622 addq 16(%r11), %r10 // r10 = &cache->buckets[mask]
623 jmp 2f
624
625 // clone scanning loop to crash instead of hang when cache is corrupt
626
627 1:
628 // loop
629 cmpq $$0, (%r10)
630 je LCacheMiss_f // if (bucket->sel == 0) cache miss
631 cmpq 16(%r11), %r10
632 je 3f // if (bucket == cache->buckets) wrap
633
634 subq $$16, %r10 // bucket--
635 2:
636 .if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
637 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
638 .else
639 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
640 .endif
641 jne 1b // scan more
642 // CacheHit must always be preceded by a not-taken `jne` instruction
643 CacheHit $0 // call or return imp
644
645 3:
646 // double wrap - busted
647 .if $0 == STRET || $0 == SUPER_STRET || $0 == SUPER2_STRET
648 movq %a2, %a1
649 movq %a3, %a2
650 .elseif $0 == GETIMP
651 movq $$0, %a1
652 .endif
653 // a1 = receiver
654 // a2 = SEL
655 movq %r11, %a3 // a3 = isa
656 movq %r10, %a4 // a4 = bucket
657 .if $0 == GETIMP
658 jmp _cache_getImp_corrupt_cache_error
659 .else
660 jmp _objc_msgSend_corrupt_cache_error
661 .endif
662 .endmacro
663
664
665 /////////////////////////////////////////////////////////////////////
666 //
667 // MethodTableLookup classRegister, selectorRegister, caller
668 //
669 // Takes: $0 = class to search (a1 or a2 or r10 ONLY)
670 // $1 = selector to search for (a2 or a3 ONLY)
671 // $2 = caller's symbol name for DWARF
672 // r11 = class to search
673 //
674 // On exit: imp in %r11
675 //
676 /////////////////////////////////////////////////////////////////////
677 .macro MethodTableLookup
678
679 MESSENGER_END_SLOW
680
681 SaveRegisters $2
682
683 // _class_lookupMethodAndLoadCache3(receiver, selector, class)
684
685 movq $0, %a1
686 movq $1, %a2
687 movq %r11, %a3
688 call __class_lookupMethodAndLoadCache3
689
690 // IMP is now in %rax
691 movq %rax, %r11
692
693 RestoreRegisters $2
694
695 .endmacro
696
697 /////////////////////////////////////////////////////////////////////
698 //
699 // GetIsaFast return-type
700 // GetIsaSupport return-type
701 //
702 // Sets r11 = obj->isa. Consults the tagged isa table if necessary.
703 //
704 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
705 // a1 or a2 (STRET) = receiver
706 //
707 // On exit: r11 = receiver->isa
708 // r10 is clobbered
709 //
710 /////////////////////////////////////////////////////////////////////
711
712 .macro GetIsaFast
713 .if $0 != STRET
714 testb $$1, %a1b
715 PN
716 jnz LGetIsaSlow_f
717 movq (%a1), %r11
718 .else
719 testb $$1, %a2b
720 PN
721 jnz LGetIsaSlow_f
722 movq (%a2), %r11
723 .endif
724 LGetIsaDone:
725 .endmacro
726
727 .macro GetIsaSupport2
728 LGetIsaSlow:
729 leaq _objc_debug_taggedpointer_classes(%rip), %r11
730 .if $0 != STRET
731 movl %a1d, %r10d
732 .else
733 movl %a2d, %r10d
734 .endif
735 andl $$0xF, %r10d
736 movq (%r11, %r10, 8), %r11 // read isa from table
737 .endmacro
738
739 .macro GetIsaSupport
740 GetIsaSupport2 $0
741 jmp LGetIsaDone_b
742 .endmacro
743
744 .macro GetIsa
745 GetIsaFast $0
746 jmp LGetIsaDone_f
747 GetIsaSupport2 $0
748 LGetIsaDone:
749 .endmacro
750
751
752 /////////////////////////////////////////////////////////////////////
753 //
754 // NilTest return-type
755 //
756 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
757 // %a1 or %a2 (STRET) = receiver
758 //
759 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
760 //
761 // NilTestSupport return-type
762 //
763 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
764 // %a1 or %a2 (STRET) = receiver
765 //
766 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
767 //
768 /////////////////////////////////////////////////////////////////////
769
770 .macro NilTest
771 .if $0 == SUPER || $0 == SUPER_STRET
772 error super dispatch does not test for nil
773 .endif
774
775 .if $0 != STRET
776 testq %a1, %a1
777 .else
778 testq %a2, %a2
779 .endif
780 PN
781 jz LNilTestSlow_f
782 LNilTestDone:
783 .endmacro
784
785 .macro NilTestSupport
786 .align 3
787 LNilTestSlow:
788 .if $0 != STRET
789 movq __objc_nilReceiver(%rip), %a1
790 testq %a1, %a1 // if (receiver != nil)
791 .else
792 movq __objc_nilReceiver(%rip), %a2
793 testq %a2, %a2 // if (receiver != nil)
794 .endif
795 jne LNilTestDone_b // send to new receiver
796
797 .if $0 == FPRET
798 fldz
799 .elseif $0 == FP2RET
800 fldz
801 fldz
802 .endif
803 .if $0 == STRET
804 movq %rdi, %rax
805 .else
806 xorl %eax, %eax
807 xorl %edx, %edx
808 xorps %xmm0, %xmm0
809 xorps %xmm1, %xmm1
810 .endif
811 MESSENGER_END_NIL
812 ret
813 .endmacro
814
815
816 /********************************************************************
817 * IMP cache_getImp(Class cls, SEL sel)
818 *
819 * On entry: a1 = class whose cache is to be searched
820 * a2 = selector to search for
821 *
822 * If found, returns method implementation.
823 * If not found, returns NULL.
824 ********************************************************************/
825
826 STATIC_ENTRY _cache_getImp
827 DW_START _cache_getImp
828
829 // do lookup
830 movq %a1, %r11 // move class to r11 for CacheLookup
831 CacheLookup GETIMP // returns IMP on success
832
833 LCacheMiss:
834 // cache miss, return nil
835 xorl %eax, %eax
836 ret
837
838 LGetImpExit:
839 DW_END _cache_getImp, 0
840 END_ENTRY _cache_getImp
841
842
843 /********************************************************************
844 *
845 * id objc_msgSend(id self, SEL _cmd,...);
846 *
847 ********************************************************************/
848
849 .data
850 .align 3
851 .globl _objc_debug_taggedpointer_classes
852 _objc_debug_taggedpointer_classes:
853 .fill 16, 8, 0
854
855 ENTRY _objc_msgSend
856 DW_START _objc_msgSend
857 MESSENGER_START
858
859 NilTest NORMAL
860
861 GetIsaFast NORMAL // r11 = self->isa
862 CacheLookup NORMAL // calls IMP on success
863
864 NilTestSupport NORMAL
865
866 GetIsaSupport NORMAL
867
868 // cache miss: go search the method lists
869 LCacheMiss:
870 // isa still in r11
871 MethodTableLookup %a1, %a2, _objc_msgSend // r11 = IMP
872 cmp %r11, %r11 // set eq (nonstret) for forwarding
873 jmp *%r11 // goto *imp
874
875 DW_END _objc_msgSend, 1
876 END_ENTRY _objc_msgSend
877
878
879 ENTRY _objc_msgSend_fixup
880 int3
881 END_ENTRY _objc_msgSend_fixup
882
883
884 STATIC_ENTRY _objc_msgSend_fixedup
885 // Load _cmd from the message_ref
886 movq 8(%a2), %a2
887 jmp _objc_msgSend
888 END_ENTRY _objc_msgSend_fixedup
889
890
891 /********************************************************************
892 *
893 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
894 *
895 * struct objc_super {
896 * id receiver;
897 * Class class;
898 * };
899 ********************************************************************/
900
901 ENTRY _objc_msgSendSuper
902 DW_START _objc_msgSendSuper
903 MESSENGER_START
904
905 // search the cache (objc_super in %a1)
906 movq class(%a1), %r11 // class = objc_super->class
907 CacheLookup SUPER // calls IMP on success
908
909 // cache miss: go search the method lists
910 LCacheMiss:
911 // class still in r11
912 movq receiver(%a1), %r10
913 MethodTableLookup %r10, %a2, _objc_msgSendSuper // r11 = IMP
914 movq receiver(%a1), %a1 // load real receiver
915 cmp %r11, %r11 // set eq (nonstret) for forwarding
916 jmp *%r11 // goto *imp
917
918 DW_END _objc_msgSendSuper, 1
919 END_ENTRY _objc_msgSendSuper
920
921
922 /********************************************************************
923 * id objc_msgSendSuper2
924 ********************************************************************/
925
926 ENTRY _objc_msgSendSuper2
927 DW_START _objc_msgSendSuper2
928 MESSENGER_START
929
930 // objc_super->class is superclass of class to search
931
932 // search the cache (objc_super in %a1)
933 movq class(%a1), %r11 // cls = objc_super->class
934 movq 8(%r11), %r11 // cls = class->superclass
935 CacheLookup SUPER2 // calls IMP on success
936
937 // cache miss: go search the method lists
938 LCacheMiss:
939 // superclass still in r11
940 movq receiver(%a1), %r10
941 MethodTableLookup %r10, %a2, _objc_msgSendSuper2 // r11 = IMP
942 movq receiver(%a1), %a1 // load real receiver
943 cmp %r11, %r11 // set eq (nonstret) for forwarding
944 jmp *%r11 // goto *imp
945
946 DW_END _objc_msgSendSuper2, 1
947 END_ENTRY _objc_msgSendSuper2
948
949
950 ENTRY _objc_msgSendSuper2_fixup
951 int3
952 END_ENTRY _objc_msgSendSuper2_fixup
953
954
955 STATIC_ENTRY _objc_msgSendSuper2_fixedup
956 // Load _cmd from the message_ref
957 movq 8(%a2), %a2
958 jmp _objc_msgSendSuper2
959 END_ENTRY _objc_msgSendSuper2_fixedup
960
961
962 /********************************************************************
963 *
964 * double objc_msgSend_fpret(id self, SEL _cmd,...);
965 * Used for `long double` return only. `float` and `double` use objc_msgSend.
966 *
967 ********************************************************************/
968
969 ENTRY _objc_msgSend_fpret
970 DW_START _objc_msgSend_fpret
971 MESSENGER_START
972
973 NilTest FPRET
974
975 GetIsaFast FPRET // r11 = self->isa
976 CacheLookup FPRET // calls IMP on success
977
978 NilTestSupport FPRET
979
980 GetIsaSupport FPRET
981
982 // cache miss: go search the method lists
983 LCacheMiss:
984 // isa still in r11
985 MethodTableLookup %a1, %a2, _objc_msgSend_fpret // r11 = IMP
986 cmp %r11, %r11 // set eq (nonstret) for forwarding
987 jmp *%r11 // goto *imp
988
989 DW_END _objc_msgSend_fpret, 1
990 END_ENTRY _objc_msgSend_fpret
991
992
993 ENTRY _objc_msgSend_fpret_fixup
994 int3
995 END_ENTRY _objc_msgSend_fpret_fixup
996
997
998 STATIC_ENTRY _objc_msgSend_fpret_fixedup
999 // Load _cmd from the message_ref
1000 movq 8(%a2), %a2
1001 jmp _objc_msgSend_fpret
1002 END_ENTRY _objc_msgSend_fpret_fixedup
1003
1004
1005 /********************************************************************
1006 *
1007 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
1008 * Used for `complex long double` return only.
1009 *
1010 ********************************************************************/
1011
1012 ENTRY _objc_msgSend_fp2ret
1013 DW_START _objc_msgSend_fp2ret
1014 MESSENGER_START
1015
1016 NilTest FP2RET
1017
1018 GetIsaFast FP2RET // r11 = self->isa
1019 CacheLookup FP2RET // calls IMP on success
1020
1021 NilTestSupport FP2RET
1022
1023 GetIsaSupport FP2RET
1024
1025 // cache miss: go search the method lists
1026 LCacheMiss:
1027 // isa still in r11
1028 MethodTableLookup %a1, %a2, _objc_msgSend_fp2ret // r11 = IMP
1029 cmp %r11, %r11 // set eq (nonstret) for forwarding
1030 jmp *%r11 // goto *imp
1031
1032 DW_END _objc_msgSend_fp2ret, 1
1033 END_ENTRY _objc_msgSend_fp2ret
1034
1035
1036 ENTRY _objc_msgSend_fp2ret_fixup
1037 int3
1038 END_ENTRY _objc_msgSend_fp2ret_fixup
1039
1040
1041 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
1042 // Load _cmd from the message_ref
1043 movq 8(%a2), %a2
1044 jmp _objc_msgSend_fp2ret
1045 END_ENTRY _objc_msgSend_fp2ret_fixedup
1046
1047
1048 /********************************************************************
1049 *
1050 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
1051 *
1052 * objc_msgSend_stret is the struct-return form of msgSend.
1053 * The ABI calls for %a1 to be used as the address of the structure
1054 * being returned, with the parameters in the succeeding locations.
1055 *
1056 * On entry: %a1 is the address where the structure is returned,
1057 * %a2 is the message receiver,
1058 * %a3 is the selector
1059 ********************************************************************/
1060
1061 ENTRY _objc_msgSend_stret
1062 DW_START _objc_msgSend_stret
1063 MESSENGER_START
1064
1065 NilTest STRET
1066
1067 GetIsaFast STRET // r11 = self->isa
1068 CacheLookup STRET // calls IMP on success
1069
1070 NilTestSupport STRET
1071
1072 GetIsaSupport STRET
1073
1074 // cache miss: go search the method lists
1075 LCacheMiss:
1076 // isa still in r11
1077 MethodTableLookup %a2, %a3, _objc_msgSend_stret // r11 = IMP
1078 test %r11, %r11 // set ne (stret) for forward; r11!=0
1079 jmp *%r11 // goto *imp
1080
1081 DW_END _objc_msgSend_stret, 1
1082 END_ENTRY _objc_msgSend_stret
1083
1084
1085 ENTRY _objc_msgSend_stret_fixup
1086 int3
1087 END_ENTRY _objc_msgSend_stret_fixup
1088
1089
1090 STATIC_ENTRY _objc_msgSend_stret_fixedup
1091 // Load _cmd from the message_ref
1092 movq 8(%a3), %a3
1093 jmp _objc_msgSend_stret
1094 END_ENTRY _objc_msgSend_stret_fixedup
1095
1096
1097 /********************************************************************
1098 *
1099 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
1100 *
1101 * struct objc_super {
1102 * id receiver;
1103 * Class class;
1104 * };
1105 *
1106 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
1107 * The ABI calls for (sp+4) to be used as the address of the structure
1108 * being returned, with the parameters in the succeeding registers.
1109 *
1110 * On entry: %a1 is the address where the structure is returned,
1111 * %a2 is the address of the objc_super structure,
1112 * %a3 is the selector
1113 *
1114 ********************************************************************/
1115
1116 ENTRY _objc_msgSendSuper_stret
1117 DW_START _objc_msgSendSuper_stret
1118 MESSENGER_START
1119
1120 // search the cache (objc_super in %a2)
1121 movq class(%a2), %r11 // class = objc_super->class
1122 CacheLookup SUPER_STRET // calls IMP on success
1123
1124 // cache miss: go search the method lists
1125 LCacheMiss:
1126 // class still in r11
1127 movq receiver(%a2), %r10
1128 MethodTableLookup %r10, %a3, _objc_msgSendSuper_stret // r11 = IMP
1129 movq receiver(%a2), %a2 // load real receiver
1130 test %r11, %r11 // set ne (stret) for forward; r11!=0
1131 jmp *%r11 // goto *imp
1132
1133 DW_END _objc_msgSendSuper_stret, 1
1134 END_ENTRY _objc_msgSendSuper_stret
1135
1136
1137 /********************************************************************
1138 * id objc_msgSendSuper2_stret
1139 ********************************************************************/
1140
1141 ENTRY _objc_msgSendSuper2_stret
1142 DW_START _objc_msgSendSuper2_stret
1143 MESSENGER_START
1144
1145 // search the cache (objc_super in %a2)
1146 movq class(%a2), %r11 // class = objc_super->class
1147 movq 8(%r11), %r11 // class = class->superclass
1148 CacheLookup SUPER2_STRET // calls IMP on success
1149
1150 // cache miss: go search the method lists
1151 LCacheMiss:
1152 // superclass still in r11
1153 movq receiver(%a2), %r10
1154 MethodTableLookup %r10, %a3, _objc_msgSendSuper2_stret // r11 = IMP
1155 movq receiver(%a2), %a2 // load real receiver
1156 test %r11, %r11 // set ne (stret) for forward; r11!=0
1157 jmp *%r11 // goto *imp
1158
1159 DW_END _objc_msgSendSuper2_stret, 1
1160 END_ENTRY _objc_msgSendSuper2_stret
1161
1162
1163 ENTRY _objc_msgSendSuper2_stret_fixup
1164 int3
1165 END_ENTRY _objc_msgSendSuper2_stret_fixup
1166
1167
1168 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
1169 // Load _cmd from the message_ref
1170 movq 8(%a3), %a3
1171 jmp _objc_msgSendSuper2_stret
1172 END_ENTRY _objc_msgSendSuper2_stret_fixedup
1173
1174
1175 /********************************************************************
1176 *
1177 * _objc_msgSend_uncached_impcache
1178 * _objc_msgSend_uncached
1179 * _objc_msgSend_stret_uncached
1180 *
1181 * Used to erase method cache entries in-place by
1182 * bouncing them to the uncached lookup.
1183 *
1184 ********************************************************************/
1185
1186 STATIC_ENTRY __objc_msgSend_uncached_impcache
1187 // Method cache version
1188
1189 // THIS IS NOT A CALLABLE C FUNCTION
1190 // Out-of-band condition register is NE for stret, EQ otherwise.
1191 // Out-of-band r11 is the searched class
1192
1193 MESSENGER_START
1194 nop
1195 MESSENGER_END_SLOW
1196
1197 jne __objc_msgSend_stret_uncached
1198 jmp __objc_msgSend_uncached
1199
1200 END_ENTRY __objc_msgSend_uncached_impcache
1201
1202
1203 STATIC_ENTRY __objc_msgSend_uncached
1204 DW_START __objc_msgSend_uncached
1205
1206 // THIS IS NOT A CALLABLE C FUNCTION
1207 // Out-of-band r11 is the searched class
1208
1209 // r11 is already the class to search
1210 MethodTableLookup %a1, %a2, __objc_msgSend_uncached // r11 = IMP
1211 cmp %r11, %r11 // set eq (nonstret) for forwarding
1212 jmp *%r11 // goto *imp
1213
1214 DW_END __objc_msgSend_uncached, 1
1215 END_ENTRY __objc_msgSend_uncached
1216
1217
1218 STATIC_ENTRY __objc_msgSend_stret_uncached
1219 DW_START __objc_msgSend_stret_uncached
1220 // THIS IS NOT A CALLABLE C FUNCTION
1221 // Out-of-band r11 is the searched class
1222
1223 // r11 is already the class to search
1224 MethodTableLookup %a2, %a3, __objc_msgSend_stret_uncached // r11 = IMP
1225 test %r11, %r11 // set ne (stret) for forward; r11!=0
1226 jmp *%r11 // goto *imp
1227
1228 DW_END __objc_msgSend_stret_uncached, 1
1229 END_ENTRY __objc_msgSend_stret_uncached
1230
1231
1232 /********************************************************************
1233 *
1234 * id _objc_msgForward(id self, SEL _cmd,...);
1235 *
1236 ********************************************************************/
1237
1238 // _FwdSel is @selector(forward::), set up in map_images().
1239 // ALWAYS dereference _FwdSel to get to "forward::" !!
1240 .data
1241 .align 3
1242 .private_extern _FwdSel
1243 _FwdSel: .quad 0
1244
1245 .cstring
1246 .align 3
1247 LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0"
1248
1249 .data
1250 .align 3
1251 .private_extern __objc_forward_handler
1252 __objc_forward_handler: .quad 0
1253
1254 .data
1255 .align 3
1256 .private_extern __objc_forward_stret_handler
1257 __objc_forward_stret_handler: .quad 0
1258
1259
1260 STATIC_ENTRY __objc_msgForward_impcache
1261 // Method cache version
1262
1263 // THIS IS NOT A CALLABLE C FUNCTION
1264 // Out-of-band condition register is NE for stret, EQ otherwise.
1265
1266 MESSENGER_START
1267 nop
1268 MESSENGER_END_SLOW
1269
1270 jne __objc_msgForward_stret
1271 jmp __objc_msgForward
1272
1273 END_ENTRY __objc_msgForward_impcache
1274
1275
1276 ENTRY __objc_msgForward
1277 // Non-stret version
1278
1279 // Call user handler, if any
1280 movq __objc_forward_handler(%rip), %r11
1281 testq %r11, %r11 // if (handler == NULL)
1282 je 1f // skip handler
1283 jmp *%r11 // else goto handler
1284 1:
1285 // No user handler
1286
1287 // Die if forwarding "forward::"
1288 cmpq %a2, _FwdSel(%rip)
1289 je LMsgForwardError
1290
1291 // Record current return address. It will be copied elsewhere in
1292 // the marg_list because this location is needed for register args
1293 movq (%rsp), %r11
1294
1295 // Push stack frame
1296 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1297 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1298
1299 // Save return address in linkage area.
1300 movq %r11, 16+LINK_AREA(%rsp)
1301
1302 // Save parameter registers
1303 movq %a1, 0+REG_AREA(%rsp)
1304 movq %a2, 8+REG_AREA(%rsp)
1305 movq %a3, 16+REG_AREA(%rsp)
1306 movq %a4, 24+REG_AREA(%rsp)
1307 movq %a5, 32+REG_AREA(%rsp)
1308 movq %a6, 40+REG_AREA(%rsp)
1309
1310 // Save side parameter registers
1311 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
1312 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1313 // 16+LINK_AREA is return address
1314
1315 // Save xmm registers
1316 movdqa %xmm0, 0+FP_AREA(%rsp)
1317 movdqa %xmm1, 16+FP_AREA(%rsp)
1318 movdqa %xmm2, 32+FP_AREA(%rsp)
1319 movdqa %xmm3, 48+FP_AREA(%rsp)
1320 movdqa %xmm4, 64+FP_AREA(%rsp)
1321 movdqa %xmm5, 80+FP_AREA(%rsp)
1322 movdqa %xmm6, 96+FP_AREA(%rsp)
1323 movdqa %xmm7, 112+FP_AREA(%rsp)
1324
1325 // Call [receiver forward:sel :margs]
1326 movq %rsp, %a4 // marg_list
1327 movq %a2, %a3 // sel
1328 movq _FwdSel(%rip), %a2 // forward::
1329 // %a1 is already the receiver
1330
1331 call _objc_msgSend
1332
1333 // Retrieve return address from linkage area
1334 movq 16+LINK_AREA(%rsp), %r11
1335 // Pop stack frame
1336 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
1337 // Put return address back
1338 movq %r11, (%rsp)
1339 ret
1340
1341 LMsgForwardError:
1342 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1343 // %a1 is already the receiver
1344 movq %a3, %a4 // the forwarded selector
1345 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s"
1346 movq _FwdSel(%rip), %a3 // forward::
1347 jmp ___objc_error // never returns
1348
1349 END_ENTRY __objc_msgForward
1350
1351
1352 ENTRY __objc_msgForward_stret
1353 // Struct-return version
1354
1355 // Call user handler, if any
1356 movq __objc_forward_stret_handler(%rip), %r11
1357 testq %r11, %r11 // if (handler == NULL)
1358 je 1f // skip handler
1359 jmp *%r11 // else goto handler
1360 1:
1361 // No user handler
1362 // Die if forwarding "forward::"
1363 cmpq %a3, _FwdSel(%rip)
1364 je LMsgForwardStretError
1365
1366 // Record current return address. It will be copied elsewhere in
1367 // the marg_list because this location is needed for register args
1368 movq (%rsp), %r11
1369
1370 // Push stack frame
1371 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1372 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1373
1374 // Save return address in linkage area.
1375 movq %r11, 16+LINK_AREA(%rsp)
1376
1377 // Save parameter registers
1378 movq %a1, 0+REG_AREA(%rsp) // note: used again below
1379 movq %a2, 8+REG_AREA(%rsp)
1380 movq %a3, 16+REG_AREA(%rsp)
1381 movq %a4, 24+REG_AREA(%rsp)
1382 movq %a5, 32+REG_AREA(%rsp)
1383 movq %a6, 40+REG_AREA(%rsp)
1384
1385 // Save side parameter registers
1386 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
1387 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1388 // 16+LINK_AREA is return address
1389
1390 // Save xmm registers
1391 movdqa %xmm0, 0+FP_AREA(%rsp)
1392 movdqa %xmm1, 16+FP_AREA(%rsp)
1393 movdqa %xmm2, 32+FP_AREA(%rsp)
1394 movdqa %xmm3, 48+FP_AREA(%rsp)
1395 movdqa %xmm4, 64+FP_AREA(%rsp)
1396 movdqa %xmm5, 80+FP_AREA(%rsp)
1397 movdqa %xmm6, 96+FP_AREA(%rsp)
1398 movdqa %xmm7, 112+FP_AREA(%rsp)
1399
1400 // Call [receiver forward:sel :margs]
1401 movq %a2, %a1 // receiver
1402 movq _FwdSel(%rip), %a2 // forward::
1403 // %a3 is already the selector
1404 movq %rsp, %a4 // marg_list
1405
1406 call _objc_msgSend // forward:: is NOT struct-return
1407
1408 // Set return value register to the passed-in struct address
1409 movq 0+REG_AREA(%rsp), %rax
1410 // Retrieve return address from linkage area
1411 movq 16+LINK_AREA(%rsp), %r11
1412 // Pop stack frame
1413 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
1414 // Put return address back
1415 movq %r11, (%rsp)
1416 ret
1417
1418 LMsgForwardStretError:
1419 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1420 // %a4 is already the forwarded selector
1421 movq %a2, %a1 // receiver
1422 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s"
1423 movq _FwdSel(%rip), %a3 // forward::
1424 jmp ___objc_error // never returns
1425
1426 END_ENTRY __objc_msgForward_stret
1427
1428
1429 ENTRY _objc_msgSend_debug
1430 jmp _objc_msgSend
1431 END_ENTRY _objc_msgSend_debug
1432
1433 ENTRY _objc_msgSendSuper2_debug
1434 jmp _objc_msgSendSuper2
1435 END_ENTRY _objc_msgSendSuper2_debug
1436
1437 ENTRY _objc_msgSend_stret_debug
1438 jmp _objc_msgSend_stret
1439 END_ENTRY _objc_msgSend_stret_debug
1440
1441 ENTRY _objc_msgSendSuper2_stret_debug
1442 jmp _objc_msgSendSuper2_stret
1443 END_ENTRY _objc_msgSendSuper2_stret_debug
1444
1445 ENTRY _objc_msgSend_fpret_debug
1446 jmp _objc_msgSend_fpret
1447 END_ENTRY _objc_msgSend_fpret_debug
1448
1449 ENTRY _objc_msgSend_fp2ret_debug
1450 jmp _objc_msgSend_fp2ret
1451 END_ENTRY _objc_msgSend_fp2ret_debug
1452
1453
1454 ENTRY _objc_msgSend_noarg
1455 jmp _objc_msgSend
1456 END_ENTRY _objc_msgSend_noarg
1457
1458
1459 ENTRY _method_invoke
1460
1461 movq method_imp(%a2), %r11
1462 movq method_name(%a2), %a2
1463 jmp *%r11
1464
1465 END_ENTRY _method_invoke
1466
1467
1468 ENTRY _method_invoke_stret
1469
1470 movq method_imp(%a3), %r11
1471 movq method_name(%a3), %a3
1472 jmp *%r11
1473
1474 END_ENTRY _method_invoke_stret
1475
1476
1477 STATIC_ENTRY __objc_ignored_method
1478
1479 movq %a1, %rax
1480 ret
1481
1482 END_ENTRY __objc_ignored_method
1483
1484
1485 .section __DATA,__objc_msg_break
1486 .quad 0
1487 .quad 0
1488
1489 #endif