1/*
2 * Copyright (c) 1999-2009 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 defined(__i386__)  &&  TARGET_IPHONE_SIMULATOR
26
27#include "objc-config.h"
28
29.data
30
31// _objc_entryPoints and _objc_exitPoints are used by objc
32// to get the critical regions for which method caches
33// cannot be garbage collected.
34
35.private_extern _objc_entryPoints
36_objc_entryPoints:
37	.long	_cache_getImp
38	.long	_objc_msgSend
39	.long	_objc_msgSend_fpret
40	.long	_objc_msgSend_stret
41	.long	_objc_msgSendSuper
42	.long	_objc_msgSendSuper2
43	.long	_objc_msgSendSuper_stret
44	.long	_objc_msgSendSuper2_stret
45	.long	0
46
47.private_extern _objc_exitPoints
48_objc_exitPoints:
49	.long	LGetImpExit
50	.long	LMsgSendExit
51	.long	LMsgSendFpretExit
52	.long	LMsgSendStretExit
53	.long	LMsgSendSuperExit
54	.long	LMsgSendSuper2Exit
55	.long	LMsgSendSuperStretExit
56	.long	LMsgSendSuper2StretExit
57	.long	0
58
59
60/********************************************************************
61* List every exit insn from every messenger for debugger use.
62* Format:
63* (
64*   1 word instruction's address
65*   1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
66* )
67* 1 word zero
68*
69* ENTER is the start of a dispatcher
70* FAST_EXIT is method dispatch
71* SLOW_EXIT is uncached method lookup
72* NIL_EXIT is returning zero from a message sent to nil
73* These must match objc-gdb.h.
74********************************************************************/
75
76#define ENTER     1
77#define FAST_EXIT 2
78#define SLOW_EXIT 3
79#define NIL_EXIT  4
80
81.section __DATA,__objc_msg_break
82.globl _gdb_objc_messenger_breakpoints
83_gdb_objc_messenger_breakpoints:
84// contents populated by the macros below
85
86.macro MESSENGER_START
874:
88	.section __DATA,__objc_msg_break
89	.long 4b
90	.long ENTER
91	.text
92.endmacro
93.macro MESSENGER_END_FAST
944:
95	.section __DATA,__objc_msg_break
96	.long 4b
97	.long FAST_EXIT
98	.text
99.endmacro
100.macro MESSENGER_END_SLOW
1014:
102	.section __DATA,__objc_msg_break
103	.long 4b
104	.long SLOW_EXIT
105	.text
106.endmacro
107.macro MESSENGER_END_NIL
1084:
109	.section __DATA,__objc_msg_break
110	.long 4b
111	.long NIL_EXIT
112	.text
113.endmacro
114
115
116/********************************************************************
117 * Names for relative labels
118 * DO NOT USE THESE LABELS ELSEWHERE
119 * Reserved labels: 5: 6: 7: 8: 9:
120 ********************************************************************/
121#define LCacheMiss 	5
122#define LCacheMiss_f 	5f
123#define LCacheMiss_b 	5b
124#define LNilTestDone 	6
125#define LNilTestDone_f 	6f
126#define LNilTestDone_b 	6b
127#define LNilTestSlow 	7
128#define LNilTestSlow_f 	7f
129#define LNilTestSlow_b 	7b
130#define LGetIsaDone 	8
131#define LGetIsaDone_f 	8f
132#define LGetIsaDone_b 	8b
133#define LGetIsaSlow 	9
134#define LGetIsaSlow_f 	9f
135#define LGetIsaSlow_b 	9b
136
137/********************************************************************
138 * Macro parameters
139 ********************************************************************/
140
141#define NORMAL 0
142#define FPRET 1
143#define GETIMP 3
144#define STRET 4
145#define SUPER 5
146#define SUPER_STRET 6
147
148
149/********************************************************************
150 *
151 * Structure definitions.
152 *
153 ********************************************************************/
154
155// Offsets from %esp
156#define self            4
157#define super           4
158#define selector        8
159#define marg_size       12
160#define marg_list       16
161#define first_arg       12
162
163#define struct_addr     4
164
165#define self_stret      8
166#define super_stret     8
167#define selector_stret  12
168#define marg_size_stret 16
169#define marg_list_stret 20
170
171// objc_super parameter to sendSuper
172#define receiver        0
173#define class           4
174
175// Selected field offsets in class structure
176#define isa             0
177#define superclass	4
178
179// Method descriptor
180#define method_name     0
181#define method_imp      8
182
183
184//////////////////////////////////////////////////////////////////////
185//
186// ENTRY		functionName
187//
188// Assembly directives to begin an exported function.
189//
190// Takes: functionName - name of the exported function
191//////////////////////////////////////////////////////////////////////
192
193.macro ENTRY
194	.text
195	.globl	$0
196	.align	2, 0x90
197$0:
198	.cfi_startproc
199.endmacro
200
201.macro STATIC_ENTRY
202	.text
203	.private_extern	$0
204	.align	4, 0x90
205$0:
206	.cfi_startproc
207.endmacro
208
209//////////////////////////////////////////////////////////////////////
210//
211// END_ENTRY	functionName
212//
213// Assembly directives to end an exported function.  Just a placeholder,
214// a close-parenthesis for ENTRY, until it is needed for something.
215//
216// Takes: functionName - name of the exported function
217//////////////////////////////////////////////////////////////////////
218
219.macro END_ENTRY
220	.cfi_endproc
221.endmacro
222
223
224/////////////////////////////////////////////////////////////////////
225//
226// CacheLookup	return-type
227//
228// Locate the implementation for a selector in a class method cache.
229//
230// Takes:
231//	  $0 = NORMAL, FPRET, STRET, SUPER, SUPER_STRET, GETIMP
232//	  ecx = selector to search for
233//	  edx = class to search
234//
235// On exit: ecx clobbered
236//	    (found) calls or returns IMP in eax, eq/ne set for forwarding
237//	    (not found) jumps to LCacheMiss, class still in edx
238//
239/////////////////////////////////////////////////////////////////////
240
241.macro CacheHit
242
243	// CacheHit must always be preceded by a not-taken `jne` instruction
244	// in case the imp is _objc_msgForward_impcache.
245
246.if $0 == GETIMP
247	movl	4(%eax), %eax		// return imp
248	call	4f
2494:	pop	%edx
250	leal	__objc_msgSend_uncached_impcache-4b(%edx), %edx
251	cmpl	%edx, %eax
252	jne	4f
253	xor	%eax, %eax		// don't return msgSend_uncached
2544:	ret
255.elseif $0 == NORMAL  ||  $0 == FPRET
256	// eq already set for forwarding by `jne`
257	MESSENGER_END_FAST
258	jmp	*4(%eax)		// call imp
259.elseif $0 == STRET
260	test	%eax, %eax		// set ne for stret forwarding
261	MESSENGER_END_FAST
262	jmp	*4(%eax)		// call imp
263.elseif $0 == SUPER
264	// replace "super" arg with "receiver"
265	movl	super(%esp), %ecx	// get super structure
266	movl	receiver(%ecx), %ecx	// get messaged object
267	movl	%ecx, super(%esp)	// make it the first argument
268	cmp	%eax, %eax		// set eq for non-stret forwarding
269	MESSENGER_END_FAST
270	jmp	*4(%eax)		// call imp
271.elseif $0 == SUPER_STRET
272	// replace "super" arg with "receiver"
273	movl	super_stret(%esp), %ecx	// get super structure
274	movl	receiver(%ecx), %ecx	// get messaged object
275	movl	%ecx, super_stret(%esp)	// make it the first argument
276	test	%eax, %eax		// set ne for stret forwarding
277	MESSENGER_END_FAST
278	jmp	*4(%eax)		// call imp
279.else
280.abort oops
281.endif
282
283.endmacro
284
285
286.macro	CacheLookup
287
288	movzwl	12(%edx), %eax		// eax = mask
289	andl	%ecx, %eax		// eax = SEL & mask
290	shll	$$3, %eax		// eax = offset = (SEL & mask) * 8
291	addl	8(%edx), %eax		// eax = bucket = cache->buckets+offset
292	cmpl	(%eax), %ecx		// if (bucket->sel != SEL)
293	jne	1f			//     scan more
294	// The `jne` above sets flags for CacheHit
295	CacheHit $0			// call or return imp
296
2971:
298	// loop
299	cmpl	$$0, (%eax)
300	je	LCacheMiss_f		// if (bucket->sel == 0) cache miss
301	cmpl	8(%edx), %eax
302	je	3f			// if (bucket = cache->buckets) wrap
303
304	subl	$$8, %eax		// bucket--
3052:
306	cmpl	(%eax), %ecx		// if (bucket->sel != sel)
307	jne	1b			//     scan more
308	// The `jne` above sets flags for CacheHit
309	CacheHit $0			// call or return imp
310
3113:
312	// wrap
313	movzwl	12(%edx), %eax		// eax = mask
314	shll	$$3, %eax		// eax = offset = mask * 8
315	addl	8(%edx), %eax		// eax = bucket = cache->buckets+offset
316	jmp	2f
317
318	// clone scanning loop to crash instead of hang when cache is corrupt
319
3201:
321	// loop
322	cmpl	$$0, (%eax)
323	je	LCacheMiss_f		// if (bucket->sel == 0) cache miss
324	cmpl	8(%edx), %eax
325	je	3f			// if (bucket = cache->buckets) wrap
326
327	subl	$$8, %eax		// bucket--
3282:
329	cmpl	(%eax), %ecx		// if (bucket->sel != sel)
330	jne	1b			//     scan more
331	// The `jne` above sets flags for CacheHit
332	CacheHit $0			// call or return imp
333
3343:
335	// double wrap - busted
336
337	pushl	%ebp
338	movl	%esp, %ebp
339	pushl	$$0
340	pushl	$$0
341	pushl	$$0		// stack alignment
342	pushl	%edx		// isa
343	pushl	%ecx		// SEL
344.if $0 == STRET  ||  $0 == SUPER_STRET
345	movl	self_stret+4(%ebp), %ecx
346.elseif $0 == GETIMP
347	movl	$$0, %ecx
348.else
349	movl	self+4(%ebp), %ecx
350.endif
351	pushl	%ecx		// receiver
352
353.if $0 == GETIMP
354	call	_cache_getImp_corrupt_cache_error
355.else
356	call	_objc_msgSend_corrupt_cache_error
357.endif
358
359.endmacro
360
361
362/////////////////////////////////////////////////////////////////////
363//
364// MethodTableLookup
365//
366// Takes:
367//	  $0 = NORMAL, FPRET, STRET, SUPER, SUPER_STRET
368//	  eax = receiver
369// 	  ecx = selector
370// 	  edx = class to search
371//
372// On exit: calls IMP, eq/ne set for forwarding
373//
374/////////////////////////////////////////////////////////////////////
375
376.macro MethodTableLookup
377	MESSENGER_END_SLOW
378	pushl	%ebp
379	.cfi_def_cfa_offset 8
380	.cfi_offset ebp, -8
381
382	movl	%esp, %ebp
383	.cfi_def_cfa_register ebp
384
385	sub	$$12, %esp		// align stack
386
387	pushl	%edx			// class
388	pushl	%ecx			// selector
389	pushl	%eax			// receiver
390	call	__class_lookupMethodAndLoadCache3
391
392	// imp in eax
393
394	leave
395	.cfi_def_cfa esp, 4
396	.cfi_same_value ebp
397
398.if $0 == SUPER
399	// replace "super" arg with "receiver"
400	movl	super(%esp), %ecx	//  get super structure
401	movl	receiver(%ecx), %ecx	//  get messaged object
402	movl	%ecx, super(%esp)	//  make it the first argument
403.elseif $0 == SUPER_STRET
404	// replace "super" arg with "receiver"
405	movl	super_stret(%esp), %ecx	//  get super structure
406	movl	receiver(%ecx), %ecx	//  get messaged object
407	movl	%ecx, super_stret(%esp)	//  make it the first argument
408.endif
409
410.if $0 == STRET  ||  $0 == SUPER_STRET
411	// set ne (stret) for forwarding; eax != 0
412	test	%eax, %eax
413	jmp	*%eax		// call imp
414.else
415	// set eq (non-stret) for forwarding
416	cmp	%eax, %eax
417	jmp	*%eax		// call imp
418.endif
419
420.endmacro
421
422
423/////////////////////////////////////////////////////////////////////
424//
425// NilTest return-type
426//
427// Takes:	$0 = NORMAL or FPRET or STRET
428//		eax = receiver
429//
430// On exit: 	Loads non-nil receiver in eax and self(esp) or self_stret(esp),
431//		or returns zero.
432//
433// NilTestSupport return-type
434//
435// Takes:	$0 = NORMAL or FPRET or STRET
436//		eax = receiver
437//
438// On exit: 	Loads non-nil receiver in eax and self(esp) or self_stret(esp),
439//		or returns zero.
440//
441/////////////////////////////////////////////////////////////////////
442
443.macro NilTest
444	testl	%eax, %eax
445	jz	LNilTestSlow_f
446LNilTestDone:
447.endmacro
448
449.macro NilTestSupport
450	.align 3
451LNilTestSlow:
452
453.if $0 == FPRET
454	fldz
455	MESSENGER_END_NIL
456	ret
457.elseif $0 == STRET
458	MESSENGER_END_NIL
459	ret $$4
460.elseif $0 == NORMAL
461	// eax is already zero
462	xorl	%edx, %edx
463	xorps	%xmm0, %xmm0
464	xorps	%xmm1, %xmm1
465	MESSENGER_END_NIL
466	ret
467.endif
468.endmacro
469
470
471/********************************************************************
472 * IMP _cache_getImp(Class cls, SEL sel)
473 *
474 * If found, returns method implementation.
475 * If not found, returns NULL.
476 ********************************************************************/
477
478	STATIC_ENTRY _cache_getImp
479
480// load the class and selector
481	movl    selector(%esp), %ecx
482	movl	self(%esp), %edx
483
484	CacheLookup GETIMP		// returns IMP on success
485
486LCacheMiss:
487// cache miss, return nil
488	xorl    %eax, %eax
489	ret
490
491LGetImpExit:
492	END_ENTRY _cache_getImp
493
494
495/********************************************************************
496 *
497 * id objc_msgSend(id self, SEL	_cmd,...);
498 *
499 ********************************************************************/
500
501	ENTRY	_objc_msgSend
502	MESSENGER_START
503
504	movl    selector(%esp), %ecx
505	movl	self(%esp), %eax
506
507	NilTest NORMAL
508
509	movl	isa(%eax), %edx		// class = self->isa
510	CacheLookup NORMAL		// calls IMP on success
511
512	NilTestSupport NORMAL
513
514LCacheMiss:
515	// isa still in edx
516	movl    selector(%esp), %ecx
517	movl	self(%esp), %eax
518	MethodTableLookup NORMAL	// calls IMP
519
520LMsgSendExit:
521	END_ENTRY	_objc_msgSend
522
523
524/********************************************************************
525 *
526 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
527 *
528 * struct objc_super {
529 *		id	receiver;
530 *		Class	class;
531 * };
532 ********************************************************************/
533
534	ENTRY	_objc_msgSendSuper
535	MESSENGER_START
536
537	movl    selector(%esp), %ecx
538	movl	super(%esp), %eax	// struct objc_super
539	movl	class(%eax), %edx	// struct objc_super->class
540	CacheLookup SUPER		// calls IMP on success
541
542LCacheMiss:
543	// class still in edx
544	movl    selector(%esp), %ecx
545	movl	super(%esp), %eax
546	movl	receiver(%eax), %eax
547	MethodTableLookup SUPER		// calls IMP
548
549LMsgSendSuperExit:
550	END_ENTRY	_objc_msgSendSuper
551
552
553	ENTRY	_objc_msgSendSuper2
554	MESSENGER_START
555
556	movl    selector(%esp), %ecx
557	movl	super(%esp), %eax	// struct objc_super
558	movl	class(%eax), %eax	// struct objc_super->class
559	mov	superclass(%eax), %edx	// edx = objc_super->class->super_class
560	CacheLookup SUPER		// calls IMP on success
561
562LCacheMiss:
563	// class still in edx
564	movl    selector(%esp), %ecx
565	movl	super(%esp), %eax
566	movl	receiver(%eax), %eax
567	MethodTableLookup SUPER		// calls IMP
568
569LMsgSendSuper2Exit:
570	END_ENTRY	_objc_msgSendSuper2
571
572
573/********************************************************************
574 *
575 * double objc_msgSend_fpret(id self, SEL _cmd,...);
576 *
577 ********************************************************************/
578
579	ENTRY	_objc_msgSend_fpret
580	MESSENGER_START
581
582	movl    selector(%esp), %ecx
583	movl	self(%esp), %eax
584
585	NilTest FPRET
586
587	movl	isa(%eax), %edx		// class = self->isa
588	CacheLookup FPRET		// calls IMP on success
589
590	NilTestSupport FPRET
591
592LCacheMiss:
593	// class still in edx
594	movl    selector(%esp), %ecx
595	movl	self(%esp), %eax
596	MethodTableLookup FPRET		// calls IMP
597
598LMsgSendFpretExit:
599	END_ENTRY	_objc_msgSend_fpret
600
601
602/********************************************************************
603 *
604 * void	objc_msgSend_stret(void *st_addr	, id self, SEL _cmd, ...);
605 *
606 *
607 * objc_msgSend_stret is the struct-return form of msgSend.
608 * The ABI calls for (sp+4) to be used as the address of the structure
609 * being returned, with the parameters in the succeeding locations.
610 *
611 * On entry:	(sp+4)is the address where the structure is returned,
612 *		(sp+8) is the message receiver,
613 *		(sp+12) is the selector
614 ********************************************************************/
615
616	ENTRY	_objc_msgSend_stret
617	MESSENGER_START
618
619	movl	selector_stret(%esp), %ecx
620	movl	self_stret(%esp), %eax
621
622	NilTest STRET
623
624	movl	isa(%eax), %edx		// class = self->isa
625	CacheLookup STRET		// calls IMP on success
626
627	NilTestSupport STRET
628
629LCacheMiss:
630	// class still in edx
631	movl	selector_stret(%esp), %ecx
632	movl	self_stret(%esp), %eax
633	MethodTableLookup STRET		// calls IMP
634
635LMsgSendStretExit:
636	END_ENTRY	_objc_msgSend_stret
637
638
639/********************************************************************
640 *
641 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
642 *
643 * struct objc_super {
644 *		id	receiver;
645 *		Class	class;
646 * };
647 *
648 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
649 * The ABI calls for (sp+4) to be used as the address of the structure
650 * being returned, with the parameters in the succeeding registers.
651 *
652 * On entry:	(sp+4)is the address where the structure is returned,
653 *		(sp+8) is the address of the objc_super structure,
654 *		(sp+12) is the selector
655 *
656 ********************************************************************/
657
658	ENTRY	_objc_msgSendSuper_stret
659	MESSENGER_START
660
661	movl	selector_stret(%esp), %ecx
662	movl	super_stret(%esp), %eax	// struct objc_super
663	movl	class(%eax), %edx	// struct objc_super->class
664	CacheLookup SUPER_STRET		// calls IMP on success
665
666LCacheMiss:
667	// class still in edx
668	movl	selector_stret(%esp), %ecx
669	movl	super_stret(%esp), %eax
670	movl	receiver(%eax), %eax
671	MethodTableLookup SUPER_STRET	// calls IMP
672
673LMsgSendSuperStretExit:
674	END_ENTRY	_objc_msgSendSuper_stret
675
676
677	ENTRY	_objc_msgSendSuper2_stret
678	MESSENGER_START
679
680	movl	selector_stret(%esp), %ecx
681	movl	super_stret(%esp), %eax	// struct objc_super
682	movl	class(%eax), %eax	// struct objc_super->class
683	mov	superclass(%eax), %edx	// edx = objc_super->class->super_class
684	CacheLookup SUPER_STRET		// calls IMP on success
685
686// cache miss: go search the method lists
687LCacheMiss:
688	// class still in edx
689	movl	selector_stret(%esp), %ecx
690	movl	super_stret(%esp), %eax
691	movl	receiver(%eax), %eax
692	MethodTableLookup SUPER_STRET	// calls IMP
693
694LMsgSendSuper2StretExit:
695	END_ENTRY	_objc_msgSendSuper2_stret
696
697
698/********************************************************************
699 *
700 * _objc_msgSend_uncached_impcache
701 * _objc_msgSend_uncached
702 * _objc_msgSend_stret_uncached
703 *
704 * Used to erase method cache entries in-place by
705 * bouncing them to the uncached lookup.
706 *
707 ********************************************************************/
708
709	STATIC_ENTRY __objc_msgSend_uncached_impcache
710	// Method cache version
711
712	// THIS IS NOT A CALLABLE C FUNCTION
713	// Out-of-band condition register is NE for stret, EQ otherwise.
714	// Out-of-band edx is the searched class
715
716	MESSENGER_START
717	nop
718	MESSENGER_END_SLOW
719
720	jne	__objc_msgSend_stret_uncached
721	jmp	__objc_msgSend_uncached
722
723	END_ENTRY __objc_msgSend_uncached_impcache
724
725
726	STATIC_ENTRY __objc_msgSend_uncached
727
728	// THIS IS NOT A CALLABLE C FUNCTION
729	// Out-of-band edx is the searched class
730
731	// edx is already the class to search
732	movl    selector(%esp), %ecx
733	MethodTableLookup NORMAL	// calls IMP
734
735	END_ENTRY __objc_msgSend_uncached
736
737
738	STATIC_ENTRY __objc_msgSend_stret_uncached
739
740	// THIS IS NOT A CALLABLE C FUNCTION
741	// Out-of-band edx is the searched class
742
743	// edx is already the class to search
744	movl    selector_stret(%esp), %ecx
745	MethodTableLookup STRET		// calls IMP
746
747	END_ENTRY __objc_msgSend_stret_uncached
748
749
750
751/********************************************************************
752*
753* id _objc_msgForward(id self, SEL _cmd,...);
754*
755* _objc_msgForward and _objc_msgForward_stret are the externally-callable
756*   functions returned by things like method_getImplementation().
757* _objc_msgForward_impcache is the function pointer actually stored in
758*   method caches.
759*
760********************************************************************/
761
762	.non_lazy_symbol_pointer
763L_forward_handler:
764	.indirect_symbol __objc_forward_handler
765	.long 0
766L_forward_stret_handler:
767	.indirect_symbol __objc_forward_stret_handler
768	.long 0
769
770	STATIC_ENTRY	__objc_msgForward_impcache
771	// Method cache version
772
773	// THIS IS NOT A CALLABLE C FUNCTION
774	// Out-of-band condition register is NE for stret, EQ otherwise.
775
776	MESSENGER_START
777	nop
778	MESSENGER_END_SLOW
779
780	jne	__objc_msgForward_stret
781	jmp	__objc_msgForward
782
783	END_ENTRY	_objc_msgForward_impcache
784
785
786	ENTRY	__objc_msgForward
787	// Non-struct return version
788
789	call	1f
7901:	popl	%edx
791	movl	L_forward_handler-1b(%edx), %edx
792	jmp	*(%edx)
793
794	END_ENTRY	__objc_msgForward
795
796
797	ENTRY	__objc_msgForward_stret
798	// Struct return version
799
800	call	1f
8011:	popl	%edx
802	movl	L_forward_stret_handler-1b(%edx), %edx
803	jmp	*(%edx)
804
805	END_ENTRY	__objc_msgForward_stret
806
807
808	ENTRY _objc_msgSend_debug
809	jmp	_objc_msgSend
810	END_ENTRY _objc_msgSend_debug
811
812	ENTRY _objc_msgSendSuper2_debug
813	jmp	_objc_msgSendSuper2
814	END_ENTRY _objc_msgSendSuper2_debug
815
816	ENTRY _objc_msgSend_stret_debug
817	jmp	_objc_msgSend_stret
818	END_ENTRY _objc_msgSend_stret_debug
819
820	ENTRY _objc_msgSendSuper2_stret_debug
821	jmp	_objc_msgSendSuper2_stret
822	END_ENTRY _objc_msgSendSuper2_stret_debug
823
824	ENTRY _objc_msgSend_fpret_debug
825	jmp	_objc_msgSend_fpret
826	END_ENTRY _objc_msgSend_fpret_debug
827
828
829	ENTRY _objc_msgSend_noarg
830	jmp	_objc_msgSend
831	END_ENTRY _objc_msgSend_noarg
832
833
834	ENTRY _method_invoke
835
836	movl	selector(%esp), %ecx
837	movl	method_name(%ecx), %edx
838	movl	method_imp(%ecx), %eax
839	movl	%edx, selector(%esp)
840	jmp	*%eax
841
842	END_ENTRY _method_invoke
843
844
845	ENTRY _method_invoke_stret
846
847	movl	selector_stret(%esp), %ecx
848	movl	method_name(%ecx), %edx
849	movl	method_imp(%ecx), %eax
850	movl	%edx, selector_stret(%esp)
851	jmp	*%eax
852
853	END_ENTRY _method_invoke_stret
854
855#if !defined(NDEBUG)
856	STATIC_ENTRY __objc_ignored_method
857
858	movl	self(%esp), %eax
859	ret
860
861	END_ENTRY __objc_ignored_method
862#endif
863
864
865.section __DATA,__objc_msg_break
866.long 0
867.long 0
868
869#endif
870