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