]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-arm.s
objc4-781.2.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-arm.s
CommitLineData
7af964d1
A
1/*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 1999-2007 Apple Computer, Inc. All Rights Reserved.
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 */
7af964d1
A
23/********************************************************************
24 *
25 * objc-msg-arm.s - ARM code to support objc messaging
26 *
27 ********************************************************************/
28
8972963c
A
29#ifdef __arm__
30
31#include <arm/arch.h>
66799735
A
32#include "objc-config.h"
33#include "isa.h"
7af964d1 34
7257e56c
A
35#ifndef _ARM_ARCH_7
36# error requires armv7
7af964d1
A
37#endif
38
31875a97
A
39// Set FP=1 on architectures that pass parameters in floating-point registers
40#if __ARM_ARCH_7K__
41# define FP 1
42#else
43# define FP 0
44#endif
45
46#if FP
47
48# if !__ARM_NEON__
49# error sorry
50# endif
51
52# define FP_RETURN_ZERO \
53 vmov.i32 q0, #0 ; \
54 vmov.i32 q1, #0 ; \
55 vmov.i32 q2, #0 ; \
56 vmov.i32 q3, #0
57
58# define FP_SAVE \
59 vpush {q0-q3}
60
61# define FP_RESTORE \
62 vpop {q0-q3}
63
64#else
65
66# define FP_RETURN_ZERO
67# define FP_SAVE
68# define FP_RESTORE
69
70#endif
71
8972963c 72.syntax unified
7af964d1 73
7af964d1
A
74#define MI_EXTERN(var) \
75 .non_lazy_symbol_pointer ;\
c1e772c4 76L##var##$$non_lazy_ptr: ;\
7af964d1
A
77 .indirect_symbol var ;\
78 .long 0
7af964d1 79
7257e56c 80#define MI_GET_EXTERN(reg,var) \
c1e772c4
A
81 movw reg, :lower16:(L##var##$$non_lazy_ptr-7f-4) ;\
82 movt reg, :upper16:(L##var##$$non_lazy_ptr-7f-4) ;\
837: add reg, pc ;\
7257e56c 84 ldr reg, [reg]
7257e56c
A
85
86#define MI_GET_ADDRESS(reg,var) \
c1e772c4
A
87 movw reg, :lower16:(var-7f-4) ;\
88 movt reg, :upper16:(var-7f-4) ;\
897: add reg, pc ;\
7af964d1
A
90
91
c1e772c4
A
92.data
93
94#if SUPPORT_INDEXED_ISA
95
96 .align 2
97 .globl _objc_indexed_classes
98_objc_indexed_classes:
99 .fill ISA_INDEX_COUNT, 4, 0
100
101#endif
7af964d1
A
102
103
31875a97 104
1807f628 105// _objc_restartableRanges is used by method dispatch
7257e56c
A
106// caching code to figure out whether any threads are actively
107// in the cache for dispatching. The labels surround the asm code
108// that do cache lookups. The tables are zero-terminated.
31875a97 109
1807f628
A
110.macro RestartableEntry
111 .long LLookupStart$0
112 .long 0
113 .short LLookupEnd$0 - LLookupStart$0
114 .short 0xffff // poor ol' armv7 doesn't support kernel based recovery
115 .long 0
116.endmacro
117
118 .align 4
119 .private_extern _objc_restartableRanges
120_objc_restartableRanges:
121 RestartableEntry _cache_getImp
122 RestartableEntry _objc_msgSend
123 RestartableEntry _objc_msgSend_stret
124 RestartableEntry _objc_msgSendSuper
125 RestartableEntry _objc_msgSendSuper_stret
126 RestartableEntry _objc_msgSendSuper2
127 RestartableEntry _objc_msgSendSuper2_stret
128 RestartableEntry _objc_msgLookup
129 RestartableEntry _objc_msgLookup_stret
130 RestartableEntry _objc_msgLookupSuper2
131 RestartableEntry _objc_msgLookupSuper2_stret
132 .fill 16, 1, 0
7af964d1 133
7257e56c
A
134
135/********************************************************************
136 * Names for relative labels
137 * DO NOT USE THESE LABELS ELSEWHERE
c1e772c4 138 * Reserved labels: 6: 7: 8: 9:
7257e56c 139 ********************************************************************/
c1e772c4 140// 6: used by CacheLookup
66799735 141// 7: used by MI_GET_ADDRESS etc
c1e772c4 142// 8: used by CacheLookup
7257e56c
A
143#define LNilReceiver 9
144#define LNilReceiver_f 9f
145#define LNilReceiver_b 9b
146
147
148/********************************************************************
149 * Macro parameters
150 ********************************************************************/
151
152#define NORMAL 0
c1e772c4 153#define STRET 1
7257e56c
A
154
155
156/********************************************************************
157 *
158 * Structure definitions.
159 *
160 ********************************************************************/
161
7af964d1 162/* objc_super parameter to sendSuper */
7257e56c
A
163#define RECEIVER 0
164#define CLASS 4
7af964d1
A
165
166/* Selected field offsets in class structure */
7257e56c
A
167#define ISA 0
168#define SUPERCLASS 4
169#define CACHE 8
170#define CACHE_MASK 12
171
66799735
A
172/* Field offsets in method cache bucket */
173#define CACHED_SEL 0
174#define CACHED_IMP 4
175
7257e56c
A
176/* Selected field offsets in method structure */
177#define METHOD_NAME 0
178#define METHOD_TYPES 4
179#define METHOD_IMP 8
180
181
182//////////////////////////////////////////////////////////////////////
183//
184// ENTRY functionName
185//
186// Assembly directives to begin an exported function.
187//
188// Takes: functionName - name of the exported function
189//////////////////////////////////////////////////////////////////////
7af964d1
A
190
191.macro ENTRY /* name */
192 .text
8972963c 193 .thumb
cd5f04f5 194 .align 5
c1e772c4 195 .globl $0
8972963c 196 .thumb_func
c1e772c4 197$0:
7af964d1
A
198.endmacro
199
8972963c
A
200.macro STATIC_ENTRY /*name*/
201 .text
8972963c 202 .thumb
cd5f04f5 203 .align 5
c1e772c4 204 .private_extern $0
8972963c 205 .thumb_func
c1e772c4 206$0:
8972963c
A
207.endmacro
208
209
7257e56c
A
210//////////////////////////////////////////////////////////////////////
211//
212// END_ENTRY functionName
213//
214// Assembly directives to end an exported function. Just a placeholder,
215// a close-parenthesis for ENTRY, until it is needed for something.
216//
217// Takes: functionName - name of the exported function
218//////////////////////////////////////////////////////////////////////
7af964d1
A
219
220.macro END_ENTRY /* name */
c1e772c4 221LExit$0:
7af964d1
A
222.endmacro
223
224
7257e56c
A
225/////////////////////////////////////////////////////////////////////
226//
1807f628
A
227// CacheLookup NORMAL|STRET <function>
228// CacheLookup2 NORMAL|STRET <function>
7257e56c
A
229//
230// Locate the implementation for a selector in a class's method cache.
231//
232// Takes:
c1e772c4 233// $0 = NORMAL, STRET
7257e56c
A
234// r0 or r1 (STRET) = receiver
235// r1 or r2 (STRET) = selector
236// r9 = class to search in
237//
c1e772c4
A
238// On exit: r9 clobbered
239// (found) continues after CacheLookup, IMP in r12, eq set
240// (not found) continues after CacheLookup2
7257e56c
A
241//
242/////////////////////////////////////////////////////////////////////
7af964d1 243
7257e56c 244.macro CacheLookup
1807f628
A
245 //
246 // Restart protocol:
247 //
248 // As soon as we're past the LLookupStart$1 label we may have loaded
249 // an invalid cache pointer or mask.
250 //
251 // When task_restartable_ranges_synchronize() is called,
252 // (or when a signal hits us) before we're past LLookupEnd$1,
253 // then our PC will be reset to LCacheMiss$1 which forcefully
254 // jumps to the cache-miss codepath.
255 //
256 // It is assumed that the CacheMiss codepath starts right at the end
257 // of CacheLookup2 and will re-setup the registers to meet the cache-miss
258 // requirements:
259 //
260 // GETIMP:
261 // The cache-miss is just returning NULL (setting r9 to 0)
262 //
263 // NORMAL and STRET:
264 // - r0 or r1 (STRET) contains the receiver
265 // - r1 or r2 (STRET) contains the selector
266 // - r9 contains the isa (reloaded from r0/r1)
267 // - other registers are set as per calling conventions
268 //
269LLookupStart$1:
270
7257e56c
A
271 ldrh r12, [r9, #CACHE_MASK] // r12 = mask
272 ldr r9, [r9, #CACHE] // r9 = buckets
c1e772c4 273.if $0 == STRET
7257e56c
A
274 and r12, r12, r2 // r12 = index = SEL & mask
275.else
276 and r12, r12, r1 // r12 = index = SEL & mask
277.endif
278 add r9, r9, r12, LSL #3 // r9 = bucket = buckets+index*8
66799735 279 ldr r12, [r9, #CACHED_SEL] // r12 = bucket->sel
c1e772c4
A
2806:
281.if $0 == STRET
7257e56c
A
282 teq r12, r2
283.else
284 teq r12, r1
285.endif
c1e772c4 286 bne 8f
66799735 287 ldr r12, [r9, #CACHED_IMP] // r12 = bucket->imp
c1e772c4
A
288
289.if $0 == STRET
290 tst r12, r12 // set ne for stret forwarding
291.else
292 // eq already set for nonstret forwarding by `teq` above
293.endif
294
295.endmacro
296
297.macro CacheLookup2
66799735
A
298#if CACHED_SEL != 0
299# error this code requires that SEL be at offset 0
300#endif
c1e772c4 3018:
7257e56c 302 cmp r12, #1
1807f628 303 blo LCacheMiss$1 // if (bucket->sel == 0) cache miss
7257e56c 304 it eq // if (bucket->sel == 1) cache wrap
66799735 305 ldreq r9, [r9, #CACHED_IMP] // bucket->imp is before first bucket
7257e56c 306 ldr r12, [r9, #8]! // r12 = (++bucket)->sel
c1e772c4 307 b 6b
1807f628
A
308
309LLookupEnd$1:
310LCacheMiss$1:
c1e772c4
A
311
312.endmacro
313
314/////////////////////////////////////////////////////////////////////
315//
316// GetClassFromIsa return-type
317//
318// Given an Isa, return the class for the Isa.
319//
320// Takes:
321// r9 = class
322//
323// On exit: r12 clobbered
324// r9 contains the class for this Isa.
325//
326/////////////////////////////////////////////////////////////////////
327.macro GetClassFromIsa
328
329#if SUPPORT_INDEXED_ISA
330 // Note: We are doing a little wasted work here to load values we might not
331 // need. Branching turns out to be even worse when performance was measured.
332 MI_GET_ADDRESS(r12, _objc_indexed_classes)
66799735 333 tst.w r9, #ISA_INDEX_IS_NPI_MASK
c1e772c4
A
334 itt ne
335 ubfxne r9, r9, #ISA_INDEX_SHIFT, #ISA_INDEX_BITS
336 ldrne.w r9, [r12, r9, lsl #2]
337#endif
7af964d1 338
7257e56c 339.endmacro
7af964d1
A
340
341
342/********************************************************************
7257e56c 343 * IMP cache_getImp(Class cls, SEL sel)
7af964d1 344 *
7257e56c
A
345 * On entry: r0 = class whose cache is to be searched
346 * r1 = selector to search for
7af964d1
A
347 *
348 * If found, returns method implementation.
349 * If not found, returns NULL.
350 ********************************************************************/
351
c1e772c4 352 STATIC_ENTRY _cache_getImp
7af964d1 353
7257e56c 354 mov r9, r0
1807f628 355 CacheLookup NORMAL, _cache_getImp
c1e772c4
A
356 // cache hit, IMP in r12
357 mov r0, r12
358 bx lr // return imp
7af964d1 359
1807f628 360 CacheLookup2 GETIMP, _cache_getImp
c1e772c4
A
361 // cache miss, return nil
362 mov r0, #0
8972963c 363 bx lr
7af964d1 364
c1e772c4 365 END_ENTRY _cache_getImp
7af964d1
A
366
367
368/********************************************************************
7af964d1 369 *
c1e772c4
A
370 * id objc_msgSend(id self, SEL _cmd, ...);
371 * IMP objc_msgLookup(id self, SEL _cmd, ...);
372 *
373 * objc_msgLookup ABI:
374 * IMP returned in r12
375 * Forwarding returned in Z flag
376 * r9 reserved for our use but not used
7257e56c 377 *
7af964d1
A
378 ********************************************************************/
379
c1e772c4 380 ENTRY _objc_msgSend
7af964d1 381
7257e56c 382 cbz r0, LNilReceiver_f
7af964d1 383
7257e56c 384 ldr r9, [r0] // r9 = self->isa
c1e772c4 385 GetClassFromIsa // r9 = class
1807f628 386 CacheLookup NORMAL, _objc_msgSend
c1e772c4 387 // cache hit, IMP in r12, eq already set for nonstret forwarding
c1e772c4 388 bx r12 // call imp
7af964d1 389
1807f628 390 CacheLookup2 NORMAL, _objc_msgSend
c1e772c4
A
391 // cache miss
392 ldr r9, [r0] // r9 = self->isa
393 GetClassFromIsa // r9 = class
7257e56c 394 b __objc_msgSend_uncached
7af964d1 395
7257e56c 396LNilReceiver:
31875a97
A
397 // r0 is already zero
398 mov r1, #0
399 mov r2, #0
400 mov r3, #0
401 FP_RETURN_ZERO
31875a97 402 bx lr
cd5f04f5 403
c1e772c4 404 END_ENTRY _objc_msgSend
7af964d1 405
c1e772c4
A
406
407 ENTRY _objc_msgLookup
7af964d1 408
c1e772c4 409 cbz r0, LNilReceiver_f
8972963c 410
c1e772c4
A
411 ldr r9, [r0] // r9 = self->isa
412 GetClassFromIsa // r9 = class
1807f628 413 CacheLookup NORMAL, _objc_msgLookup
c1e772c4
A
414 // cache hit, IMP in r12, eq already set for nonstret forwarding
415 bx lr
416
1807f628 417 CacheLookup2 NORMAL, _objc_msgLookup
c1e772c4
A
418 // cache miss
419 ldr r9, [r0] // r9 = self->isa
420 GetClassFromIsa // r9 = class
421 b __objc_msgLookup_uncached
422
423LNilReceiver:
424 MI_GET_ADDRESS(r12, __objc_msgNil)
425 bx lr
426
427 END_ENTRY _objc_msgLookup
428
429
430 STATIC_ENTRY __objc_msgNil
431
432 // r0 is already zero
433 mov r1, #0
434 mov r2, #0
435 mov r3, #0
436 FP_RETURN_ZERO
437 bx lr
438
439 END_ENTRY __objc_msgNil
8972963c 440
7af964d1
A
441
442/********************************************************************
7257e56c 443 * void objc_msgSend_stret(void *st_addr, id self, SEL op, ...);
c1e772c4 444 * IMP objc_msgLookup_stret(void *st_addr, id self, SEL op, ...);
7af964d1
A
445 *
446 * objc_msgSend_stret is the struct-return form of msgSend.
7257e56c 447 * The ABI calls for r0 to be used as the address of the structure
7af964d1
A
448 * being returned, with the parameters in the succeeding registers.
449 *
7257e56c
A
450 * On entry: r0 is the address where the structure is returned,
451 * r1 is the message receiver,
452 * r2 is the selector
7af964d1
A
453 ********************************************************************/
454
c1e772c4 455 ENTRY _objc_msgSend_stret
7257e56c
A
456
457 cbz r1, LNilReceiver_f
7af964d1 458
7257e56c 459 ldr r9, [r1] // r9 = self->isa
c1e772c4 460 GetClassFromIsa // r9 = class
1807f628 461 CacheLookup STRET, _objc_msgSend_stret
c1e772c4 462 // cache hit, IMP in r12, ne already set for stret forwarding
c1e772c4 463 bx r12
7af964d1 464
1807f628 465 CacheLookup2 STRET, _objc_msgSend_stret
c1e772c4 466 // cache miss
7257e56c 467 ldr r9, [r1] // r9 = self->isa
c1e772c4 468 GetClassFromIsa // r9 = class
7257e56c 469 b __objc_msgSend_stret_uncached
7af964d1 470
7257e56c 471LNilReceiver:
7257e56c 472 bx lr
7af964d1 473
c1e772c4
A
474 END_ENTRY _objc_msgSend_stret
475
476
477 ENTRY _objc_msgLookup_stret
478
479 cbz r1, LNilReceiver_f
480
481 ldr r9, [r1] // r9 = self->isa
482 GetClassFromIsa // r9 = class
1807f628 483 CacheLookup STRET, _objc_msgLookup_stret
c1e772c4
A
484 // cache hit, IMP in r12, ne already set for stret forwarding
485 bx lr
486
1807f628 487 CacheLookup2 STRET, _objc_msgLookup_stret
c1e772c4
A
488 // cache miss
489 ldr r9, [r1] // r9 = self->isa
490 GetClassFromIsa // r9 = class
491 b __objc_msgLookup_stret_uncached
492
493LNilReceiver:
494 MI_GET_ADDRESS(r12, __objc_msgNil_stret)
495 bx lr
496
497 END_ENTRY _objc_msgLookup_stret
498
499
500 STATIC_ENTRY __objc_msgNil_stret
501
502 bx lr
503
504 END_ENTRY __objc_msgNil_stret
7af964d1
A
505
506
7af964d1 507/********************************************************************
7257e56c 508 * id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
7af964d1
A
509 *
510 * struct objc_super {
7257e56c
A
511 * id receiver;
512 * Class cls; // the class to search
7af964d1
A
513 * }
514 ********************************************************************/
515
c1e772c4 516 ENTRY _objc_msgSendSuper
7257e56c
A
517
518 ldr r9, [r0, #CLASS] // r9 = struct super->class
1807f628 519 CacheLookup NORMAL, _objc_msgSendSuper
c1e772c4
A
520 // cache hit, IMP in r12, eq already set for nonstret forwarding
521 ldr r0, [r0, #RECEIVER] // load real receiver
c1e772c4 522 bx r12 // call imp
7257e56c 523
1807f628 524 CacheLookup2 NORMAL, _objc_msgSendSuper
c1e772c4 525 // cache miss
7257e56c
A
526 ldr r9, [r0, #CLASS] // r9 = struct super->class
527 ldr r0, [r0, #RECEIVER] // load real receiver
528 b __objc_msgSend_uncached
529
c1e772c4 530 END_ENTRY _objc_msgSendSuper
7af964d1
A
531
532
8972963c 533/********************************************************************
7257e56c
A
534 * id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
535 *
536 * struct objc_super {
537 * id receiver;
538 * Class cls; // SUBCLASS of the class to search
539 * }
8972963c
A
540 ********************************************************************/
541
c1e772c4 542 ENTRY _objc_msgSendSuper2
7257e56c
A
543
544 ldr r9, [r0, #CLASS] // class = struct super->class
c1e772c4 545 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 546 CacheLookup NORMAL, _objc_msgSendSuper2
c1e772c4
A
547 // cache hit, IMP in r12, eq already set for nonstret forwarding
548 ldr r0, [r0, #RECEIVER] // load real receiver
c1e772c4 549 bx r12 // call imp
7257e56c 550
1807f628 551 CacheLookup2 NORMAL, _objc_msgSendSuper2
c1e772c4 552 // cache miss
7257e56c 553 ldr r9, [r0, #CLASS] // class = struct super->class
c1e772c4 554 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
7257e56c
A
555 ldr r0, [r0, #RECEIVER] // load real receiver
556 b __objc_msgSend_uncached
557
c1e772c4
A
558 END_ENTRY _objc_msgSendSuper2
559
560
561 ENTRY _objc_msgLookupSuper2
562
563 ldr r9, [r0, #CLASS] // class = struct super->class
564 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 565 CacheLookup NORMAL, _objc_msgLookupSuper2
c1e772c4
A
566 // cache hit, IMP in r12, eq already set for nonstret forwarding
567 ldr r0, [r0, #RECEIVER] // load real receiver
568 bx lr
569
1807f628 570 CacheLookup2 NORMAL, _objc_msgLookupSuper2
c1e772c4
A
571 // cache miss
572 ldr r9, [r0, #CLASS]
573 ldr r9, [r9, #SUPERCLASS] // r9 = class to search
574 ldr r0, [r0, #RECEIVER] // load real receiver
575 b __objc_msgLookup_uncached
576
577 END_ENTRY _objc_msgLookupSuper2
8972963c
A
578
579
7af964d1 580/********************************************************************
7257e56c 581 * void objc_msgSendSuper_stret(void *st_addr, objc_super *self, SEL op, ...);
7af964d1
A
582 *
583 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
7257e56c 584 * The ABI calls for r0 to be used as the address of the structure
7af964d1
A
585 * being returned, with the parameters in the succeeding registers.
586 *
7257e56c
A
587 * On entry: r0 is the address where the structure is returned,
588 * r1 is the address of the objc_super structure,
589 * r2 is the selector
7af964d1
A
590 ********************************************************************/
591
c1e772c4 592 ENTRY _objc_msgSendSuper_stret
7257e56c 593
c1e772c4 594 ldr r9, [r1, #CLASS] // r9 = struct super->class
1807f628 595 CacheLookup STRET, _objc_msgSendSuper_stret
c1e772c4
A
596 // cache hit, IMP in r12, ne already set for stret forwarding
597 ldr r1, [r1, #RECEIVER] // load real receiver
c1e772c4 598 bx r12 // call imp
7af964d1 599
1807f628 600 CacheLookup2 STRET, _objc_msgSendSuper_stret
c1e772c4
A
601 // cache miss
602 ldr r9, [r1, #CLASS] // r9 = struct super->class
603 ldr r1, [r1, #RECEIVER] // load real receiver
7257e56c 604 b __objc_msgSend_stret_uncached
7af964d1 605
c1e772c4 606 END_ENTRY _objc_msgSendSuper_stret
7af964d1
A
607
608
7257e56c
A
609/********************************************************************
610 * id objc_msgSendSuper2_stret
611 ********************************************************************/
7af964d1 612
c1e772c4 613 ENTRY _objc_msgSendSuper2_stret
7257e56c 614
c1e772c4
A
615 ldr r9, [r1, #CLASS] // class = struct super->class
616 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 617 CacheLookup STRET, _objc_msgSendSuper2_stret
c1e772c4
A
618 // cache hit, IMP in r12, ne already set for stret forwarding
619 ldr r1, [r1, #RECEIVER] // load real receiver
c1e772c4 620 bx r12 // call imp
7257e56c 621
1807f628 622 CacheLookup2 STRET, _objc_msgSendSuper2_stret
c1e772c4
A
623 // cache miss
624 ldr r9, [r1, #CLASS] // class = struct super->class
625 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
7257e56c
A
626 ldr r1, [r1, #RECEIVER] // load real receiver
627 b __objc_msgSend_stret_uncached
628
c1e772c4
A
629 END_ENTRY _objc_msgSendSuper2_stret
630
631
632 ENTRY _objc_msgLookupSuper2_stret
633
634 ldr r9, [r1, #CLASS] // class = struct super->class
635 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 636 CacheLookup STRET, _objc_msgLookupSuper2_stret
c1e772c4
A
637 // cache hit, IMP in r12, ne already set for stret forwarding
638 ldr r1, [r1, #RECEIVER] // load real receiver
639 bx lr
640
1807f628 641 CacheLookup2 STRET, _objc_msgLookupSuper2_stret
c1e772c4
A
642 // cache miss
643 ldr r9, [r1, #CLASS]
644 ldr r9, [r9, #SUPERCLASS] // r9 = class to search
645 ldr r1, [r1, #RECEIVER] // load real receiver
646 b __objc_msgLookup_stret_uncached
647
648 END_ENTRY _objc_msgLookupSuper2_stret
649
650
651/////////////////////////////////////////////////////////////////////
652//
653// MethodTableLookup NORMAL|STRET
654//
655// Locate the implementation for a selector in a class's method lists.
656//
657// Takes:
658// $0 = NORMAL, STRET
659// r0 or r1 (STRET) = receiver
660// r1 or r2 (STRET) = selector
661// r9 = class to search in
662//
663// On exit: IMP in r12, eq/ne set for forwarding
664//
665/////////////////////////////////////////////////////////////////////
666
667.macro MethodTableLookup
668
669 stmfd sp!, {r0-r3,r7,lr}
670 add r7, sp, #16
671 sub sp, #8 // align stack
672 FP_SAVE
673
1807f628 674 // lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
c1e772c4
A
675.if $0 == NORMAL
676 // receiver already in r0
677 // selector already in r1
678.else
679 mov r0, r1 // receiver
680 mov r1, r2 // selector
681.endif
682 mov r2, r9 // class to search
1807f628
A
683 mov r3, #3 // LOOKUP_INITIALIZE | LOOKUP_INITIALIZE
684 blx _lookUpImpOrForward
c1e772c4
A
685 mov r12, r0 // r12 = IMP
686
687.if $0 == NORMAL
688 cmp r12, r12 // set eq for nonstret forwarding
689.else
690 tst r12, r12 // set ne for stret forwarding
691.endif
692
693 FP_RESTORE
694 add sp, #8 // align stack
695 ldmfd sp!, {r0-r3,r7,lr}
696
697.endmacro
7af964d1 698
7af964d1 699
7257e56c 700/********************************************************************
7257e56c
A
701 *
702 * _objc_msgSend_uncached
703 * _objc_msgSend_stret_uncached
c1e772c4
A
704 * _objc_msgLookup_uncached
705 * _objc_msgLookup_stret_uncached
706 * The uncached method lookup.
7257e56c
A
707 *
708 ********************************************************************/
7257e56c 709
c1e772c4 710 STATIC_ENTRY __objc_msgSend_uncached
8972963c 711
c1e772c4
A
712 // THIS IS NOT A CALLABLE C FUNCTION
713 // Out-of-band r9 is the class to search
8972963c 714
c1e772c4
A
715 MethodTableLookup NORMAL // returns IMP in r12
716 bx r12
8972963c 717
c1e772c4 718 END_ENTRY __objc_msgSend_uncached
8972963c 719
8972963c 720
c1e772c4 721 STATIC_ENTRY __objc_msgSend_stret_uncached
8972963c 722
7257e56c
A
723 // THIS IS NOT A CALLABLE C FUNCTION
724 // Out-of-band r9 is the class to search
8972963c 725
c1e772c4 726 MethodTableLookup STRET // returns IMP in r12
7257e56c 727 bx r12
c1e772c4
A
728
729 END_ENTRY __objc_msgSend_stret_uncached
8972963c 730
c1e772c4
A
731
732 STATIC_ENTRY __objc_msgLookup_uncached
7257e56c
A
733
734 // THIS IS NOT A CALLABLE C FUNCTION
735 // Out-of-band r9 is the class to search
736
c1e772c4
A
737 MethodTableLookup NORMAL // returns IMP in r12
738 bx lr
8972963c 739
c1e772c4 740 END_ENTRY __objc_msgLookup_uncached
8972963c 741
8972963c 742
c1e772c4
A
743 STATIC_ENTRY __objc_msgLookup_stret_uncached
744
745 // THIS IS NOT A CALLABLE C FUNCTION
746 // Out-of-band r9 is the class to search
747
748 MethodTableLookup STRET // returns IMP in r12
749 bx lr
8972963c 750
c1e772c4 751 END_ENTRY __objc_msgLookup_stret_uncached
7af964d1 752
7257e56c 753
7af964d1 754/********************************************************************
8070259c
A
755*
756* id _objc_msgForward(id self, SEL _cmd,...);
757*
758* _objc_msgForward and _objc_msgForward_stret are the externally-callable
759* functions returned by things like method_getImplementation().
760* _objc_msgForward_impcache is the function pointer actually stored in
761* method caches.
762*
763********************************************************************/
7af964d1 764
8070259c
A
765 MI_EXTERN(__objc_forward_handler)
766 MI_EXTERN(__objc_forward_stret_handler)
767
c1e772c4 768 STATIC_ENTRY __objc_msgForward_impcache
7af964d1
A
769 // Method cache version
770
771 // THIS IS NOT A CALLABLE C FUNCTION
c1e772c4 772 // Out-of-band Z is 0 (EQ) for normal, 1 (NE) for stret
7257e56c 773
7257e56c
A
774 beq __objc_msgForward
775 b __objc_msgForward_stret
7af964d1 776
c1e772c4 777 END_ENTRY __objc_msgForward_impcache
7af964d1
A
778
779
c1e772c4 780 ENTRY __objc_msgForward
7af964d1
A
781 // Non-stret version
782
8070259c 783 MI_GET_EXTERN(r12, __objc_forward_handler)
7257e56c 784 ldr r12, [r12]
8070259c 785 bx r12
7257e56c 786
c1e772c4 787 END_ENTRY __objc_msgForward
7af964d1
A
788
789
c1e772c4 790 ENTRY __objc_msgForward_stret
7af964d1 791 // Struct-return version
8972963c 792
8070259c 793 MI_GET_EXTERN(r12, __objc_forward_stret_handler)
7257e56c 794 ldr r12, [r12]
8070259c 795 bx r12
7257e56c 796
c1e772c4 797 END_ENTRY __objc_msgForward_stret
7af964d1
A
798
799
c1e772c4
A
800 ENTRY _objc_msgSend_noarg
801 b _objc_msgSend
802 END_ENTRY _objc_msgSend_noarg
803
804 ENTRY _objc_msgSend_debug
8972963c 805 b _objc_msgSend
c1e772c4 806 END_ENTRY _objc_msgSend_debug
7af964d1 807
c1e772c4 808 ENTRY _objc_msgSendSuper2_debug
8972963c 809 b _objc_msgSendSuper2
c1e772c4 810 END_ENTRY _objc_msgSendSuper2_debug
7af964d1 811
c1e772c4 812 ENTRY _objc_msgSend_stret_debug
8972963c 813 b _objc_msgSend_stret
c1e772c4 814 END_ENTRY _objc_msgSend_stret_debug
7af964d1 815
c1e772c4 816 ENTRY _objc_msgSendSuper2_stret_debug
8972963c 817 b _objc_msgSendSuper2_stret
c1e772c4 818 END_ENTRY _objc_msgSendSuper2_stret_debug
7af964d1
A
819
820
c1e772c4 821 ENTRY _method_invoke
7257e56c
A
822 // r1 is method triplet instead of SEL
823 ldr r12, [r1, #METHOD_IMP]
824 ldr r1, [r1, #METHOD_NAME]
825 bx r12
c1e772c4 826 END_ENTRY _method_invoke
7af964d1
A
827
828
c1e772c4 829 ENTRY _method_invoke_stret
7257e56c
A
830 // r2 is method triplet instead of SEL
831 ldr r12, [r2, #METHOD_IMP]
832 ldr r2, [r2, #METHOD_NAME]
833 bx r12
c1e772c4 834 END_ENTRY _method_invoke_stret
8972963c 835
7257e56c
A
836
837.section __DATA,__objc_msg_break
838.long 0
839.long 0
840
7af964d1 841#endif