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