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
1054:
106	.section __DATA,__objc_msg_break
107	.quad 4b
108	.quad ENTER
109	.text
110.endmacro
111.macro MESSENGER_END_FAST
1124:
113	.section __DATA,__objc_msg_break
114	.quad 4b
115	.quad FAST_EXIT
116	.text
117.endmacro
118.macro MESSENGER_END_SLOW
1194:
120	.section __DATA,__objc_msg_break
121	.quad 4b
122	.quad SLOW_EXIT
123	.text
124.endmacro
125.macro MESSENGER_END_NIL
1264:
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
275LExit$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
329CIE:
330	.set	L$set$0,LECIE1-LSCIE1
331	.long	L$set$0	# Length of Common Information Entry
332LSCIE1:
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
355LECIE1:
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:
365LSFDE$0:
366	.set 	LLENFDE$0, LEFDE$0-LASFDE$0
367	.long 	LLENFDE$0		# FDE Length
368LASFDE$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
402LEFDE$0:
403	.text
404
405.endmacro
406
407
408// Start of function
409.macro DW_START
410L_dw_start_$0:
411.endmacro
412
413// After `enter` in SaveRegisters
414.macro DW_ENTER
415L_dw_enter_$0:
416.endmacro
417
418// After `leave` in RestoreRegisters
419.macro DW_LEAVE
420L_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
5414:	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
6011:
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
6183:
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
6271:
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--
6352:
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
6453:
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
724LGetIsaDone:
725.endmacro
726
727.macro GetIsaSupport2
728LGetIsaSlow:
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
748LGetIsaDone:
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
782LNilTestDone:
783.endmacro
784
785.macro NilTestSupport
786	.align 3
787LNilTestSlow:
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
833LCacheMiss:
834// cache miss, return nil
835	xorl	%eax, %eax
836	ret
837
838LGetImpExit:
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
869LCacheMiss:
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
910LCacheMiss:
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
938LCacheMiss:
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
983LCacheMiss:
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
1026LCacheMiss:
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
1075LCacheMiss:
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
1125LCacheMiss:
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
1151LCacheMiss:
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
1247LUnkSelStr: .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
12841:
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
1341LMsgForwardError:
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
13601:
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
1418LMsgForwardStretError:
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
1490