]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-simulator-i386.s
objc4-750.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-simulator-i386.s
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_OS_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 .align 2
36 .private_extern _objc_entryPoints
37 _objc_entryPoints:
38 .long _cache_getImp
39 .long _objc_msgSend
40 .long _objc_msgSend_fpret
41 .long _objc_msgSend_stret
42 .long _objc_msgSendSuper
43 .long _objc_msgSendSuper2
44 .long _objc_msgSendSuper_stret
45 .long _objc_msgSendSuper2_stret
46 .long _objc_msgLookup
47 .long _objc_msgLookup_fpret
48 .long _objc_msgLookup_stret
49 .long _objc_msgLookupSuper2
50 .long _objc_msgLookupSuper2_stret
51 .long 0
52
53 .private_extern _objc_exitPoints
54 _objc_exitPoints:
55 .long LExit_cache_getImp
56 .long LExit_objc_msgSend
57 .long LExit_objc_msgSend_fpret
58 .long LExit_objc_msgSend_stret
59 .long LExit_objc_msgSendSuper
60 .long LExit_objc_msgSendSuper2
61 .long LExit_objc_msgSendSuper_stret
62 .long LExit_objc_msgSendSuper2_stret
63 .long LExit_objc_msgLookup
64 .long LExit_objc_msgLookup_fpret
65 .long LExit_objc_msgLookup_stret
66 .long LExit_objc_msgLookupSuper2
67 .long LExit_objc_msgLookupSuper2_stret
68 .long 0
69
70
71 /********************************************************************
72 * Names for relative labels
73 * DO NOT USE THESE LABELS ELSEWHERE
74 * Reserved labels: 5: 6: 7: 8: 9:
75 ********************************************************************/
76 #define LCacheMiss 5
77 #define LCacheMiss_f 5f
78 #define LCacheMiss_b 5b
79 #define LNilTestDone 6
80 #define LNilTestDone_f 6f
81 #define LNilTestDone_b 6b
82 #define LNilTestSlow 7
83 #define LNilTestSlow_f 7f
84 #define LNilTestSlow_b 7b
85 #define LGetIsaDone 8
86 #define LGetIsaDone_f 8f
87 #define LGetIsaDone_b 8b
88 #define LGetIsaSlow 9
89 #define LGetIsaSlow_f 9f
90 #define LGetIsaSlow_b 9b
91
92 /********************************************************************
93 * Macro parameters
94 ********************************************************************/
95
96
97 #define NORMAL 0
98 #define FPRET 1
99 #define STRET 2
100
101 #define CALL 100
102 #define GETIMP 101
103 #define LOOKUP 102
104
105
106 /********************************************************************
107 *
108 * Structure definitions.
109 *
110 ********************************************************************/
111
112 // Offsets from %esp
113 #define self 4
114 #define super 4
115 #define selector 8
116 #define marg_size 12
117 #define marg_list 16
118 #define first_arg 12
119
120 #define struct_addr 4
121
122 #define self_stret 8
123 #define super_stret 8
124 #define selector_stret 12
125 #define marg_size_stret 16
126 #define marg_list_stret 20
127
128 // objc_super parameter to sendSuper
129 #define receiver 0
130 #define class 4
131
132 // Selected field offsets in class structure
133 #define isa 0
134 #define superclass 4
135 #define cache_buckets 8
136 #define cache_mask 12
137
138 // Method cache
139 #define cached_sel 0
140 #define cached_imp 4
141
142 // Method descriptor
143 #define method_name 0
144 #define method_imp 8
145
146
147 //////////////////////////////////////////////////////////////////////
148 //
149 // ENTRY functionName
150 //
151 // Assembly directives to begin an exported function.
152 //
153 // Takes: functionName - name of the exported function
154 //////////////////////////////////////////////////////////////////////
155
156 .macro ENTRY
157 .text
158 .globl $0
159 .align 2, 0x90
160 $0:
161 .endmacro
162
163 .macro STATIC_ENTRY
164 .text
165 .private_extern $0
166 .align 4, 0x90
167 $0:
168 .endmacro
169
170 //////////////////////////////////////////////////////////////////////
171 //
172 // END_ENTRY functionName
173 //
174 // Assembly directives to end an exported function. Just a placeholder,
175 // a close-parenthesis for ENTRY, until it is needed for something.
176 //
177 // Takes: functionName - name of the exported function
178 //////////////////////////////////////////////////////////////////////
179
180 .macro END_ENTRY
181 LExit$0:
182 .endmacro
183
184
185 /********************************************************************
186 * UNWIND name, flags
187 * Unwind info generation
188 ********************************************************************/
189 .macro UNWIND
190 .section __LD,__compact_unwind,regular,debug
191 .long $0
192 .set LUnwind$0, LExit$0 - $0
193 .long LUnwind$0
194 .long $1
195 .long 0 /* no personality */
196 .long 0 /* no LSDA */
197 .text
198 .endmacro
199
200 #define NoFrame 0x02010000 // no frame, no SP adjustment except return address
201 #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
202
203
204 /////////////////////////////////////////////////////////////////////
205 //
206 // CacheLookup return-type, caller
207 //
208 // Locate the implementation for a selector in a class method cache.
209 //
210 // Takes:
211 // $0 = NORMAL, FPRET, STRET
212 // $1 = CALL, LOOKUP, GETIMP
213 // ecx = selector to search for
214 // edx = class to search
215 //
216 // On exit: ecx clobbered
217 // (found) calls or returns IMP in eax, eq/ne set for forwarding
218 // (not found) jumps to LCacheMiss, class still in edx
219 //
220 /////////////////////////////////////////////////////////////////////
221
222 .macro CacheHit
223
224 // CacheHit must always be preceded by a not-taken `jne` instruction
225 // in case the imp is _objc_msgForward_impcache.
226
227 // eax = found bucket
228
229 .if $1 == GETIMP
230 movl cached_imp(%eax), %eax // return imp
231 ret
232
233 .else
234
235 .if $0 != STRET
236 // eq already set for forwarding by `jne`
237 .else
238 test %eax, %eax // set ne for stret forwarding
239 .endif
240
241 .if $1 == CALL
242 jmp *cached_imp(%eax) // call imp
243
244 .elseif $1 == LOOKUP
245 movl cached_imp(%eax), %eax // return imp
246 ret
247
248 .else
249 .abort oops
250 .endif
251
252 .endif
253
254 .endmacro
255
256
257 .macro CacheLookup
258
259 movzwl cache_mask(%edx), %eax // eax = mask
260 andl %ecx, %eax // eax = SEL & mask
261 shll $$3, %eax // eax = offset = (SEL & mask) * 8
262 addl cache_buckets(%edx), %eax // eax = bucket = buckets+offset
263 cmpl cached_sel(%eax), %ecx // if (bucket->sel != SEL)
264 jne 1f // scan more
265 // The `jne` above sets flags for CacheHit
266 CacheHit $0, $1 // call or return imp
267
268 1:
269 // loop
270 cmpl $$1, cached_sel(%eax)
271 jbe 3f // if (bucket->sel <= 1) wrap or miss
272
273 addl $$8, %eax // bucket++
274 2:
275 cmpl cached_sel(%eax), %ecx // if (bucket->sel != sel)
276 jne 1b // scan more
277 // The `jne` above sets flags for CacheHit
278 CacheHit $0, $1 // call or return imp
279
280 3:
281 // wrap or miss
282 jb LCacheMiss_f // if (bucket->sel < 1) cache miss
283 // wrap
284 movl cached_imp(%eax), %eax // bucket->imp is really first bucket
285 jmp 2f
286
287 // Clone scanning loop to miss instead of hang when cache is corrupt.
288 // The slow path may detect any corruption and halt later.
289
290 1:
291 // loop
292 cmpl $$1, cached_sel(%eax)
293 jbe 3f // if (bucket->sel <= 1) wrap or miss
294
295 addl $$8, %eax // bucket++
296 2:
297 cmpl cached_sel(%eax), %ecx // if (bucket->sel != sel)
298 jne 1b // scan more
299 // The `jne` above sets flags for CacheHit
300 CacheHit $0, $1 // call or return imp
301
302 3:
303 // double wrap or miss
304 jmp LCacheMiss_f
305
306 .endmacro
307
308
309 /////////////////////////////////////////////////////////////////////
310 //
311 // MethodTableLookup NORMAL|STRET
312 //
313 // Takes:
314 // receiver (not struct objc_super) and selector on stack
315 // edx = class to search
316 //
317 // On exit: IMP in eax, eq/ne set for forwarding
318 //
319 /////////////////////////////////////////////////////////////////////
320
321 .macro MethodTableLookup
322 pushl %ebp
323 movl %esp, %ebp
324
325 subl $$(8+5*16), %esp
326
327 .if $0 == NORMAL
328 movl self+4(%ebp), %eax
329 movl selector+4(%ebp), %ecx
330 .else
331 movl self_stret+4(%ebp), %eax
332 movl selector_stret+4(%ebp), %ecx
333 .endif
334
335 movdqa %xmm3, 4*16(%esp)
336 movdqa %xmm2, 3*16(%esp)
337 movdqa %xmm1, 2*16(%esp)
338 movdqa %xmm0, 1*16(%esp)
339
340 movl %edx, 8(%esp) // class
341 movl %ecx, 4(%esp) // selector
342 movl %eax, 0(%esp) // receiver
343 call __class_lookupMethodAndLoadCache3
344
345 // imp in eax
346
347 movdqa 4*16(%esp), %xmm3
348 movdqa 3*16(%esp), %xmm2
349 movdqa 2*16(%esp), %xmm1
350 movdqa 1*16(%esp), %xmm0
351
352 .if $0 == NORMAL
353 cmp %eax, %eax // set eq for nonstret forwarding
354 .else
355 test %eax, %eax // set ne for stret forwarding
356 .endif
357
358 leave
359
360 .endmacro
361
362
363 /////////////////////////////////////////////////////////////////////
364 //
365 // NilTest return-type
366 //
367 // Takes: $0 = NORMAL or FPRET or STRET
368 // eax = receiver
369 //
370 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
371 // or returns zero.
372 //
373 // NilTestReturnZero return-type
374 //
375 // Takes: $0 = NORMAL or FPRET or STRET
376 // eax = receiver
377 //
378 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
379 // or returns zero.
380 //
381 // NilTestReturnIMP return-type
382 //
383 // Takes: $0 = NORMAL or FPRET or STRET
384 // eax = receiver
385 //
386 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
387 // or returns an IMP in eax that returns zero.
388 //
389 /////////////////////////////////////////////////////////////////////
390
391 .macro ZeroReturn
392 xorl %eax, %eax
393 xorl %edx, %edx
394 xorps %xmm0, %xmm0
395 xorps %xmm1, %xmm1
396 .endmacro
397
398 .macro ZeroReturnFPRET
399 fldz
400 .endmacro
401
402 .macro ZeroReturnSTRET
403 // empty
404 .endmacro
405
406 STATIC_ENTRY __objc_msgNil
407 ZeroReturn
408 ret
409 END_ENTRY __objc_msgNil
410
411 STATIC_ENTRY __objc_msgNil_fpret
412 ZeroReturnFPRET
413 ret
414 END_ENTRY __objc_msgNil_fpret
415
416 STATIC_ENTRY __objc_msgNil_stret
417 ZeroReturnSTRET
418 ret $4
419 END_ENTRY __objc_msgNil_stret
420
421
422 .macro NilTest
423 testl %eax, %eax
424 jz LNilTestSlow_f
425 LNilTestDone:
426 .endmacro
427
428 .macro NilTestReturnZero
429 .align 3
430 LNilTestSlow:
431
432 .if $0 == NORMAL
433 ZeroReturn
434 ret
435 .elseif $0 == FPRET
436 ZeroReturnFPRET
437 ret
438 .elseif $0 == STRET
439 ZeroReturnSTRET
440 ret $$4
441 .else
442 .abort oops
443 .endif
444 .endmacro
445
446 .macro NilTestReturnIMP
447 .align 3
448 LNilTestSlow:
449
450 call 1f
451 1: pop %eax
452 .if $0 == NORMAL
453 leal __objc_msgNil-1b(%eax), %eax
454 .elseif $0 == FPRET
455 leal __objc_msgNil_fpret-1b(%eax), %eax
456 .elseif $0 == STRET
457 leal __objc_msgNil_stret-1b(%eax), %eax
458 .else
459 .abort oops
460 .endif
461 ret
462 .endmacro
463
464
465 /********************************************************************
466 * IMP _cache_getImp(Class cls, SEL sel)
467 *
468 * If found, returns method implementation.
469 * If not found, returns NULL.
470 ********************************************************************/
471
472 STATIC_ENTRY _cache_getImp
473
474 // load the class and selector
475 movl selector(%esp), %ecx
476 movl self(%esp), %edx
477
478 CacheLookup NORMAL, GETIMP // returns IMP on success
479
480 LCacheMiss:
481 // cache miss, return nil
482 xorl %eax, %eax
483 ret
484
485 END_ENTRY _cache_getImp
486
487
488 /********************************************************************
489 *
490 * id objc_msgSend(id self, SEL _cmd, ...);
491 * IMP objc_msgLookup(id self, SEL _cmd, ...);
492 *
493 * objc_msgLookup ABI:
494 * IMP returned in eax
495 * Forwarding returned in Z flag
496 * edx reserved for our use but not used
497 *
498 ********************************************************************/
499
500 ENTRY _objc_msgSend
501 UNWIND _objc_msgSend, NoFrame
502
503 movl selector(%esp), %ecx
504 movl self(%esp), %eax
505
506 NilTest NORMAL
507
508 movl isa(%eax), %edx // class = self->isa
509 CacheLookup NORMAL, CALL // calls IMP on success
510
511 NilTestReturnZero NORMAL
512
513 LCacheMiss:
514 // isa still in edx
515 jmp __objc_msgSend_uncached
516
517 END_ENTRY _objc_msgSend
518
519
520 ENTRY _objc_msgLookup
521 UNWIND _objc_msgLookup, NoFrame
522
523 movl selector(%esp), %ecx
524 movl self(%esp), %eax
525
526 NilTest NORMAL
527
528 movl isa(%eax), %edx // class = self->isa
529 CacheLookup NORMAL, LOOKUP // returns IMP on success
530
531 NilTestReturnIMP NORMAL
532
533 LCacheMiss:
534 // isa still in edx
535 jmp __objc_msgLookup_uncached
536
537 END_ENTRY _objc_msgLookup
538
539
540 /********************************************************************
541 *
542 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd, ...);
543 *
544 ********************************************************************/
545
546 ENTRY _objc_msgSendSuper
547 UNWIND _objc_msgSendSuper, NoFrame
548
549 movl selector(%esp), %ecx
550 movl super(%esp), %eax // struct objc_super
551 movl class(%eax), %edx // struct objc_super->class
552 movl receiver(%eax), %eax // struct objc_super->receiver
553 movl %eax, super(%esp) // replace super arg with receiver
554 CacheLookup NORMAL, CALL // calls IMP on success
555
556 LCacheMiss:
557 // class still in edx
558 jmp __objc_msgSend_uncached
559
560 END_ENTRY _objc_msgSendSuper
561
562
563 /********************************************************************
564 *
565 * id objc_msgSendSuper2(struct objc_super *super, SEL _cmd, ...);
566 * IMP objc_msgLookupSuper2(struct objc_super *super, SEL _cmd, ...);
567 *
568 ********************************************************************/
569
570 ENTRY _objc_msgSendSuper2
571 UNWIND _objc_msgSendSuper2, NoFrame
572
573 movl selector(%esp), %ecx
574 movl super(%esp), %eax // struct objc_super
575 movl class(%eax), %edx // struct objc_super->class
576 movl receiver(%eax), %eax // struct objc_super->receiver
577 movl %eax, super(%esp) // replace super arg with receiver
578 movl superclass(%edx), %edx // edx = objc_super->class->super_class
579 CacheLookup NORMAL, CALL // calls IMP on success
580
581 LCacheMiss:
582 // class still in edx
583 jmp __objc_msgSend_uncached
584
585 END_ENTRY _objc_msgSendSuper2
586
587
588 ENTRY _objc_msgLookupSuper2
589 UNWIND _objc_msgLookupSuper2, NoFrame
590
591 movl selector(%esp), %ecx
592 movl super(%esp), %eax // struct objc_super
593 movl class(%eax), %edx // struct objc_super->class
594 movl receiver(%eax), %eax // struct objc_super->receiver
595 movl %eax, super(%esp) // replace super arg with receiver
596 movl superclass(%edx), %edx // edx = objc_super->class->super_class
597 CacheLookup NORMAL, LOOKUP // returns IMP on success
598
599 LCacheMiss:
600 // class still in edx
601 jmp __objc_msgLookup_uncached
602
603 END_ENTRY _objc_msgLookupSuper2
604
605
606 /********************************************************************
607 *
608 * double objc_msgSend_fpret(id self, SEL _cmd, ...);
609 * IMP objc_msgLookup_fpret(id self, SEL _cmd, ...);
610 *
611 ********************************************************************/
612
613 ENTRY _objc_msgSend_fpret
614 UNWIND _objc_msgSend_fpret, NoFrame
615
616 movl selector(%esp), %ecx
617 movl self(%esp), %eax
618
619 NilTest FPRET
620
621 movl isa(%eax), %edx // class = self->isa
622 CacheLookup FPRET, CALL // calls IMP on success
623
624 NilTestReturnZero FPRET
625
626 LCacheMiss:
627 // class still in edx
628 jmp __objc_msgSend_uncached
629
630 END_ENTRY _objc_msgSend_fpret
631
632
633 ENTRY _objc_msgLookup_fpret
634 UNWIND _objc_msgLookup_fpret, NoFrame
635
636 movl selector(%esp), %ecx
637 movl self(%esp), %eax
638
639 NilTest FPRET
640
641 movl isa(%eax), %edx // class = self->isa
642 CacheLookup FPRET, LOOKUP // returns IMP on success
643
644 NilTestReturnIMP FPRET
645
646 LCacheMiss:
647 // class still in edx
648 jmp __objc_msgLookup_uncached
649
650 END_ENTRY _objc_msgLookup_fpret
651
652
653 /********************************************************************
654 *
655 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
656 * IMP objc_msgLookup_stret(void *st_addr, id self, SEL _cmd, ...);
657 *
658 ********************************************************************/
659
660 ENTRY _objc_msgSend_stret
661 UNWIND _objc_msgSend_stret, NoFrame
662
663 movl selector_stret(%esp), %ecx
664 movl self_stret(%esp), %eax
665
666 NilTest STRET
667
668 movl isa(%eax), %edx // class = self->isa
669 CacheLookup STRET, CALL // calls IMP on success
670
671 NilTestReturnZero STRET
672
673 LCacheMiss:
674 // class still in edx
675 jmp __objc_msgSend_stret_uncached
676
677 END_ENTRY _objc_msgSend_stret
678
679
680 ENTRY _objc_msgLookup_stret
681 UNWIND _objc_msgLookup_stret, NoFrame
682
683 movl selector_stret(%esp), %ecx
684 movl self_stret(%esp), %eax
685
686 NilTest STRET
687
688 movl isa(%eax), %edx // class = self->isa
689 CacheLookup STRET, LOOKUP // returns IMP on success
690
691 NilTestReturnIMP STRET
692
693 LCacheMiss:
694 // class still in edx
695 jmp __objc_msgLookup_stret_uncached
696
697 END_ENTRY _objc_msgLookup_stret
698
699
700 /********************************************************************
701 *
702 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
703 *
704 ********************************************************************/
705
706 ENTRY _objc_msgSendSuper_stret
707 UNWIND _objc_msgSendSuper_stret, NoFrame
708
709 movl selector_stret(%esp), %ecx
710 movl super_stret(%esp), %eax // struct objc_super
711 movl class(%eax), %edx // struct objc_super->class
712 movl receiver(%eax), %eax // struct objc_super->receiver
713 movl %eax, super_stret(%esp) // replace super arg with receiver
714 CacheLookup STRET, CALL // calls IMP on success
715
716 LCacheMiss:
717 // class still in edx
718 jmp __objc_msgSend_stret_uncached
719
720 END_ENTRY _objc_msgSendSuper_stret
721
722
723 /********************************************************************
724 *
725 * void objc_msgSendSuper2_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
726 * IMP objc_msgLookupSuper2_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
727 *
728 ********************************************************************/
729
730 ENTRY _objc_msgSendSuper2_stret
731 UNWIND _objc_msgSendSuper2_stret, NoFrame
732
733 movl selector_stret(%esp), %ecx
734 movl super_stret(%esp), %eax // struct objc_super
735 movl class(%eax), %edx // struct objc_super->class
736 movl receiver(%eax), %eax // struct objc_super->receiver
737 movl %eax, super_stret(%esp) // replace super arg with receiver
738 mov superclass(%edx), %edx // edx = objc_super->class->super_class
739 CacheLookup STRET, CALL // calls IMP on success
740
741 // cache miss: go search the method lists
742 LCacheMiss:
743 // class still in edx
744 jmp __objc_msgSend_stret_uncached
745
746 END_ENTRY _objc_msgSendSuper2_stret
747
748
749 ENTRY _objc_msgLookupSuper2_stret
750 UNWIND _objc_msgLookupSuper2_stret, NoFrame
751
752 movl selector_stret(%esp), %ecx
753 movl super_stret(%esp), %eax // struct objc_super
754 movl class(%eax), %edx // struct objc_super->class
755 movl receiver(%eax), %eax // struct objc_super->receiver
756 movl %eax, super_stret(%esp) // replace super arg with receiver
757 mov superclass(%edx), %edx // edx = objc_super->class->super_class
758 CacheLookup STRET, LOOKUP // returns IMP on success
759
760 // cache miss: go search the method lists
761 LCacheMiss:
762 // class still in edx
763 jmp __objc_msgLookup_stret_uncached
764
765 END_ENTRY _objc_msgLookupSuper2_stret
766
767
768 /********************************************************************
769 *
770 * _objc_msgSend_uncached
771 * _objc_msgSend_stret_uncached
772 * _objc_msgLookup_uncached
773 * _objc_msgLookup_stret_uncached
774 *
775 * The uncached method lookup.
776 *
777 ********************************************************************/
778
779 STATIC_ENTRY __objc_msgSend_uncached
780 UNWIND __objc_msgSend_uncached, FrameWithNoSaves
781
782 // THIS IS NOT A CALLABLE C FUNCTION
783 // Out-of-band edx is the searched class
784
785 // edx is already the class to search
786 MethodTableLookup NORMAL
787 jmp *%eax // call imp
788
789 END_ENTRY __objc_msgSend_uncached
790
791
792 STATIC_ENTRY __objc_msgSend_stret_uncached
793 UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves
794
795 // THIS IS NOT A CALLABLE C FUNCTION
796 // Out-of-band edx is the searched class
797
798 // edx is already the class to search
799 MethodTableLookup STRET
800 jmp *%eax // call imp
801
802 END_ENTRY __objc_msgSend_stret_uncached
803
804
805 STATIC_ENTRY __objc_msgLookup_uncached
806 UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
807
808 // THIS IS NOT A CALLABLE C FUNCTION
809 // Out-of-band edx is the searched class
810
811 // edx is already the class to search
812 MethodTableLookup NORMAL // eax = IMP
813 ret
814
815 END_ENTRY __objc_msgLookup_uncached
816
817
818 STATIC_ENTRY __objc_msgLookup_stret_uncached
819 UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves
820
821 // THIS IS NOT A CALLABLE C FUNCTION
822 // Out-of-band edx is the searched class
823
824 // edx is already the class to search
825 MethodTableLookup STRET // eax = IMP
826 ret
827
828 END_ENTRY __objc_msgLookup_stret_uncached
829
830
831 /********************************************************************
832 *
833 * id _objc_msgForward(id self, SEL _cmd,...);
834 *
835 * _objc_msgForward and _objc_msgForward_stret are the externally-callable
836 * functions returned by things like method_getImplementation().
837 * _objc_msgForward_impcache is the function pointer actually stored in
838 * method caches.
839 *
840 ********************************************************************/
841
842 .non_lazy_symbol_pointer
843 L_forward_handler:
844 .indirect_symbol __objc_forward_handler
845 .long 0
846 L_forward_stret_handler:
847 .indirect_symbol __objc_forward_stret_handler
848 .long 0
849
850 STATIC_ENTRY __objc_msgForward_impcache
851 // Method cache version
852
853 // THIS IS NOT A CALLABLE C FUNCTION
854 // Out-of-band condition register is NE for stret, EQ otherwise.
855
856 jne __objc_msgForward_stret
857 jmp __objc_msgForward
858
859 END_ENTRY _objc_msgForward_impcache
860
861
862 ENTRY __objc_msgForward
863 // Non-struct return version
864
865 call 1f
866 1: popl %edx
867 movl L_forward_handler-1b(%edx), %edx
868 jmp *(%edx)
869
870 END_ENTRY __objc_msgForward
871
872
873 ENTRY __objc_msgForward_stret
874 // Struct return version
875
876 call 1f
877 1: popl %edx
878 movl L_forward_stret_handler-1b(%edx), %edx
879 jmp *(%edx)
880
881 END_ENTRY __objc_msgForward_stret
882
883
884 ENTRY _objc_msgSend_debug
885 jmp _objc_msgSend
886 END_ENTRY _objc_msgSend_debug
887
888 ENTRY _objc_msgSendSuper2_debug
889 jmp _objc_msgSendSuper2
890 END_ENTRY _objc_msgSendSuper2_debug
891
892 ENTRY _objc_msgSend_stret_debug
893 jmp _objc_msgSend_stret
894 END_ENTRY _objc_msgSend_stret_debug
895
896 ENTRY _objc_msgSendSuper2_stret_debug
897 jmp _objc_msgSendSuper2_stret
898 END_ENTRY _objc_msgSendSuper2_stret_debug
899
900 ENTRY _objc_msgSend_fpret_debug
901 jmp _objc_msgSend_fpret
902 END_ENTRY _objc_msgSend_fpret_debug
903
904
905 ENTRY _objc_msgSend_noarg
906 jmp _objc_msgSend
907 END_ENTRY _objc_msgSend_noarg
908
909
910 ENTRY _method_invoke
911
912 movl selector(%esp), %ecx
913 movl method_name(%ecx), %edx
914 movl method_imp(%ecx), %eax
915 movl %edx, selector(%esp)
916 jmp *%eax
917
918 END_ENTRY _method_invoke
919
920
921 ENTRY _method_invoke_stret
922
923 movl selector_stret(%esp), %ecx
924 movl method_name(%ecx), %edx
925 movl method_imp(%ecx), %eax
926 movl %edx, selector_stret(%esp)
927 jmp *%eax
928
929 END_ENTRY _method_invoke_stret
930
931
932 .section __DATA,__objc_msg_break
933 .long 0
934 .long 0
935
936 #endif