]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-arm.s
objc4-818.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
bc4fafce
A
225//////////////////////////////////////////////////////////////////////
226//
227// SAVE_REGS
228//
229// Create a stack frame and save all argument registers in preparation
230// for a function call.
231//////////////////////////////////////////////////////////////////////
232
233.macro SAVE_REGS
234
235 stmfd sp!, {r0-r3,r7,lr}
236 add r7, sp, #16
237 sub sp, #8 // align stack
238 FP_SAVE
239
240.endmacro
241
242
243//////////////////////////////////////////////////////////////////////
244//
245// RESTORE_REGS
246//
247// Restore all argument registers and pop the stack frame created by
248// SAVE_REGS.
249//////////////////////////////////////////////////////////////////////
250
251.macro RESTORE_REGS
252
253 FP_RESTORE
254 add sp, #8 // align stack
255 ldmfd sp!, {r0-r3,r7,lr}
256
257.endmacro
258
7257e56c
A
259/////////////////////////////////////////////////////////////////////
260//
1807f628
A
261// CacheLookup NORMAL|STRET <function>
262// CacheLookup2 NORMAL|STRET <function>
7257e56c
A
263//
264// Locate the implementation for a selector in a class's method cache.
265//
266// Takes:
c1e772c4 267// $0 = NORMAL, STRET
7257e56c
A
268// r0 or r1 (STRET) = receiver
269// r1 or r2 (STRET) = selector
270// r9 = class to search in
271//
c1e772c4
A
272// On exit: r9 clobbered
273// (found) continues after CacheLookup, IMP in r12, eq set
274// (not found) continues after CacheLookup2
7257e56c
A
275//
276/////////////////////////////////////////////////////////////////////
7af964d1 277
7257e56c 278.macro CacheLookup
1807f628
A
279 //
280 // Restart protocol:
281 //
282 // As soon as we're past the LLookupStart$1 label we may have loaded
283 // an invalid cache pointer or mask.
284 //
285 // When task_restartable_ranges_synchronize() is called,
286 // (or when a signal hits us) before we're past LLookupEnd$1,
287 // then our PC will be reset to LCacheMiss$1 which forcefully
288 // jumps to the cache-miss codepath.
289 //
290 // It is assumed that the CacheMiss codepath starts right at the end
291 // of CacheLookup2 and will re-setup the registers to meet the cache-miss
292 // requirements:
293 //
294 // GETIMP:
295 // The cache-miss is just returning NULL (setting r9 to 0)
296 //
297 // NORMAL and STRET:
298 // - r0 or r1 (STRET) contains the receiver
299 // - r1 or r2 (STRET) contains the selector
300 // - r9 contains the isa (reloaded from r0/r1)
301 // - other registers are set as per calling conventions
302 //
303LLookupStart$1:
304
7257e56c
A
305 ldrh r12, [r9, #CACHE_MASK] // r12 = mask
306 ldr r9, [r9, #CACHE] // r9 = buckets
c1e772c4 307.if $0 == STRET
7257e56c
A
308 and r12, r12, r2 // r12 = index = SEL & mask
309.else
310 and r12, r12, r1 // r12 = index = SEL & mask
311.endif
312 add r9, r9, r12, LSL #3 // r9 = bucket = buckets+index*8
66799735 313 ldr r12, [r9, #CACHED_SEL] // r12 = bucket->sel
c1e772c4
A
3146:
315.if $0 == STRET
7257e56c
A
316 teq r12, r2
317.else
318 teq r12, r1
319.endif
c1e772c4 320 bne 8f
66799735 321 ldr r12, [r9, #CACHED_IMP] // r12 = bucket->imp
c1e772c4
A
322
323.if $0 == STRET
324 tst r12, r12 // set ne for stret forwarding
325.else
326 // eq already set for nonstret forwarding by `teq` above
327.endif
328
329.endmacro
330
331.macro CacheLookup2
66799735
A
332#if CACHED_SEL != 0
333# error this code requires that SEL be at offset 0
334#endif
c1e772c4 3358:
7257e56c 336 cmp r12, #1
1807f628 337 blo LCacheMiss$1 // if (bucket->sel == 0) cache miss
7257e56c 338 it eq // if (bucket->sel == 1) cache wrap
66799735 339 ldreq r9, [r9, #CACHED_IMP] // bucket->imp is before first bucket
7257e56c 340 ldr r12, [r9, #8]! // r12 = (++bucket)->sel
c1e772c4 341 b 6b
1807f628
A
342
343LLookupEnd$1:
344LCacheMiss$1:
c1e772c4
A
345
346.endmacro
347
348/////////////////////////////////////////////////////////////////////
349//
350// GetClassFromIsa return-type
351//
352// Given an Isa, return the class for the Isa.
353//
354// Takes:
355// r9 = class
356//
357// On exit: r12 clobbered
358// r9 contains the class for this Isa.
359//
360/////////////////////////////////////////////////////////////////////
361.macro GetClassFromIsa
362
363#if SUPPORT_INDEXED_ISA
364 // Note: We are doing a little wasted work here to load values we might not
365 // need. Branching turns out to be even worse when performance was measured.
366 MI_GET_ADDRESS(r12, _objc_indexed_classes)
66799735 367 tst.w r9, #ISA_INDEX_IS_NPI_MASK
c1e772c4
A
368 itt ne
369 ubfxne r9, r9, #ISA_INDEX_SHIFT, #ISA_INDEX_BITS
370 ldrne.w r9, [r12, r9, lsl #2]
371#endif
7af964d1 372
7257e56c 373.endmacro
7af964d1
A
374
375
376/********************************************************************
7257e56c 377 * IMP cache_getImp(Class cls, SEL sel)
7af964d1 378 *
7257e56c
A
379 * On entry: r0 = class whose cache is to be searched
380 * r1 = selector to search for
7af964d1
A
381 *
382 * If found, returns method implementation.
383 * If not found, returns NULL.
384 ********************************************************************/
385
c1e772c4 386 STATIC_ENTRY _cache_getImp
7af964d1 387
7257e56c 388 mov r9, r0
1807f628 389 CacheLookup NORMAL, _cache_getImp
c1e772c4
A
390 // cache hit, IMP in r12
391 mov r0, r12
392 bx lr // return imp
7af964d1 393
1807f628 394 CacheLookup2 GETIMP, _cache_getImp
c1e772c4
A
395 // cache miss, return nil
396 mov r0, #0
8972963c 397 bx lr
7af964d1 398
c1e772c4 399 END_ENTRY _cache_getImp
7af964d1
A
400
401
402/********************************************************************
7af964d1 403 *
c1e772c4
A
404 * id objc_msgSend(id self, SEL _cmd, ...);
405 * IMP objc_msgLookup(id self, SEL _cmd, ...);
406 *
407 * objc_msgLookup ABI:
408 * IMP returned in r12
409 * Forwarding returned in Z flag
410 * r9 reserved for our use but not used
7257e56c 411 *
7af964d1
A
412 ********************************************************************/
413
c1e772c4 414 ENTRY _objc_msgSend
7af964d1 415
7257e56c 416 cbz r0, LNilReceiver_f
7af964d1 417
7257e56c 418 ldr r9, [r0] // r9 = self->isa
c1e772c4 419 GetClassFromIsa // r9 = class
1807f628 420 CacheLookup NORMAL, _objc_msgSend
c1e772c4 421 // cache hit, IMP in r12, eq already set for nonstret forwarding
c1e772c4 422 bx r12 // call imp
7af964d1 423
1807f628 424 CacheLookup2 NORMAL, _objc_msgSend
c1e772c4
A
425 // cache miss
426 ldr r9, [r0] // r9 = self->isa
427 GetClassFromIsa // r9 = class
7257e56c 428 b __objc_msgSend_uncached
7af964d1 429
7257e56c 430LNilReceiver:
31875a97
A
431 // r0 is already zero
432 mov r1, #0
433 mov r2, #0
434 mov r3, #0
435 FP_RETURN_ZERO
31875a97 436 bx lr
cd5f04f5 437
c1e772c4 438 END_ENTRY _objc_msgSend
7af964d1 439
c1e772c4
A
440
441 ENTRY _objc_msgLookup
7af964d1 442
c1e772c4 443 cbz r0, LNilReceiver_f
8972963c 444
c1e772c4
A
445 ldr r9, [r0] // r9 = self->isa
446 GetClassFromIsa // r9 = class
1807f628 447 CacheLookup NORMAL, _objc_msgLookup
c1e772c4
A
448 // cache hit, IMP in r12, eq already set for nonstret forwarding
449 bx lr
450
1807f628 451 CacheLookup2 NORMAL, _objc_msgLookup
c1e772c4
A
452 // cache miss
453 ldr r9, [r0] // r9 = self->isa
454 GetClassFromIsa // r9 = class
455 b __objc_msgLookup_uncached
456
457LNilReceiver:
458 MI_GET_ADDRESS(r12, __objc_msgNil)
459 bx lr
460
461 END_ENTRY _objc_msgLookup
462
463
464 STATIC_ENTRY __objc_msgNil
465
466 // r0 is already zero
467 mov r1, #0
468 mov r2, #0
469 mov r3, #0
470 FP_RETURN_ZERO
471 bx lr
472
473 END_ENTRY __objc_msgNil
8972963c 474
7af964d1
A
475
476/********************************************************************
7257e56c 477 * void objc_msgSend_stret(void *st_addr, id self, SEL op, ...);
c1e772c4 478 * IMP objc_msgLookup_stret(void *st_addr, id self, SEL op, ...);
7af964d1
A
479 *
480 * objc_msgSend_stret is the struct-return form of msgSend.
7257e56c 481 * The ABI calls for r0 to be used as the address of the structure
7af964d1
A
482 * being returned, with the parameters in the succeeding registers.
483 *
7257e56c
A
484 * On entry: r0 is the address where the structure is returned,
485 * r1 is the message receiver,
486 * r2 is the selector
7af964d1
A
487 ********************************************************************/
488
c1e772c4 489 ENTRY _objc_msgSend_stret
7257e56c
A
490
491 cbz r1, LNilReceiver_f
7af964d1 492
7257e56c 493 ldr r9, [r1] // r9 = self->isa
c1e772c4 494 GetClassFromIsa // r9 = class
1807f628 495 CacheLookup STRET, _objc_msgSend_stret
c1e772c4 496 // cache hit, IMP in r12, ne already set for stret forwarding
c1e772c4 497 bx r12
7af964d1 498
1807f628 499 CacheLookup2 STRET, _objc_msgSend_stret
c1e772c4 500 // cache miss
7257e56c 501 ldr r9, [r1] // r9 = self->isa
c1e772c4 502 GetClassFromIsa // r9 = class
7257e56c 503 b __objc_msgSend_stret_uncached
7af964d1 504
7257e56c 505LNilReceiver:
7257e56c 506 bx lr
7af964d1 507
c1e772c4
A
508 END_ENTRY _objc_msgSend_stret
509
510
511 ENTRY _objc_msgLookup_stret
512
513 cbz r1, LNilReceiver_f
514
515 ldr r9, [r1] // r9 = self->isa
516 GetClassFromIsa // r9 = class
1807f628 517 CacheLookup STRET, _objc_msgLookup_stret
c1e772c4
A
518 // cache hit, IMP in r12, ne already set for stret forwarding
519 bx lr
520
1807f628 521 CacheLookup2 STRET, _objc_msgLookup_stret
c1e772c4
A
522 // cache miss
523 ldr r9, [r1] // r9 = self->isa
524 GetClassFromIsa // r9 = class
525 b __objc_msgLookup_stret_uncached
526
527LNilReceiver:
528 MI_GET_ADDRESS(r12, __objc_msgNil_stret)
529 bx lr
530
531 END_ENTRY _objc_msgLookup_stret
532
533
534 STATIC_ENTRY __objc_msgNil_stret
535
536 bx lr
537
538 END_ENTRY __objc_msgNil_stret
7af964d1
A
539
540
7af964d1 541/********************************************************************
7257e56c 542 * id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
7af964d1
A
543 *
544 * struct objc_super {
7257e56c
A
545 * id receiver;
546 * Class cls; // the class to search
7af964d1
A
547 * }
548 ********************************************************************/
549
c1e772c4 550 ENTRY _objc_msgSendSuper
7257e56c
A
551
552 ldr r9, [r0, #CLASS] // r9 = struct super->class
1807f628 553 CacheLookup NORMAL, _objc_msgSendSuper
c1e772c4
A
554 // cache hit, IMP in r12, eq already set for nonstret forwarding
555 ldr r0, [r0, #RECEIVER] // load real receiver
c1e772c4 556 bx r12 // call imp
7257e56c 557
1807f628 558 CacheLookup2 NORMAL, _objc_msgSendSuper
c1e772c4 559 // cache miss
7257e56c
A
560 ldr r9, [r0, #CLASS] // r9 = struct super->class
561 ldr r0, [r0, #RECEIVER] // load real receiver
562 b __objc_msgSend_uncached
563
c1e772c4 564 END_ENTRY _objc_msgSendSuper
7af964d1
A
565
566
8972963c 567/********************************************************************
7257e56c
A
568 * id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
569 *
570 * struct objc_super {
571 * id receiver;
572 * Class cls; // SUBCLASS of the class to search
573 * }
8972963c
A
574 ********************************************************************/
575
c1e772c4 576 ENTRY _objc_msgSendSuper2
7257e56c
A
577
578 ldr r9, [r0, #CLASS] // class = struct super->class
c1e772c4 579 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 580 CacheLookup NORMAL, _objc_msgSendSuper2
c1e772c4
A
581 // cache hit, IMP in r12, eq already set for nonstret forwarding
582 ldr r0, [r0, #RECEIVER] // load real receiver
c1e772c4 583 bx r12 // call imp
7257e56c 584
1807f628 585 CacheLookup2 NORMAL, _objc_msgSendSuper2
c1e772c4 586 // cache miss
7257e56c 587 ldr r9, [r0, #CLASS] // class = struct super->class
c1e772c4 588 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
7257e56c
A
589 ldr r0, [r0, #RECEIVER] // load real receiver
590 b __objc_msgSend_uncached
591
c1e772c4
A
592 END_ENTRY _objc_msgSendSuper2
593
594
595 ENTRY _objc_msgLookupSuper2
596
597 ldr r9, [r0, #CLASS] // class = struct super->class
598 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 599 CacheLookup NORMAL, _objc_msgLookupSuper2
c1e772c4
A
600 // cache hit, IMP in r12, eq already set for nonstret forwarding
601 ldr r0, [r0, #RECEIVER] // load real receiver
602 bx lr
603
1807f628 604 CacheLookup2 NORMAL, _objc_msgLookupSuper2
c1e772c4
A
605 // cache miss
606 ldr r9, [r0, #CLASS]
607 ldr r9, [r9, #SUPERCLASS] // r9 = class to search
608 ldr r0, [r0, #RECEIVER] // load real receiver
609 b __objc_msgLookup_uncached
610
611 END_ENTRY _objc_msgLookupSuper2
8972963c
A
612
613
7af964d1 614/********************************************************************
7257e56c 615 * void objc_msgSendSuper_stret(void *st_addr, objc_super *self, SEL op, ...);
7af964d1
A
616 *
617 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
7257e56c 618 * The ABI calls for r0 to be used as the address of the structure
7af964d1
A
619 * being returned, with the parameters in the succeeding registers.
620 *
7257e56c
A
621 * On entry: r0 is the address where the structure is returned,
622 * r1 is the address of the objc_super structure,
623 * r2 is the selector
7af964d1
A
624 ********************************************************************/
625
c1e772c4 626 ENTRY _objc_msgSendSuper_stret
7257e56c 627
c1e772c4 628 ldr r9, [r1, #CLASS] // r9 = struct super->class
1807f628 629 CacheLookup STRET, _objc_msgSendSuper_stret
c1e772c4
A
630 // cache hit, IMP in r12, ne already set for stret forwarding
631 ldr r1, [r1, #RECEIVER] // load real receiver
c1e772c4 632 bx r12 // call imp
7af964d1 633
1807f628 634 CacheLookup2 STRET, _objc_msgSendSuper_stret
c1e772c4
A
635 // cache miss
636 ldr r9, [r1, #CLASS] // r9 = struct super->class
637 ldr r1, [r1, #RECEIVER] // load real receiver
7257e56c 638 b __objc_msgSend_stret_uncached
7af964d1 639
c1e772c4 640 END_ENTRY _objc_msgSendSuper_stret
7af964d1
A
641
642
7257e56c
A
643/********************************************************************
644 * id objc_msgSendSuper2_stret
645 ********************************************************************/
7af964d1 646
c1e772c4 647 ENTRY _objc_msgSendSuper2_stret
7257e56c 648
c1e772c4
A
649 ldr r9, [r1, #CLASS] // class = struct super->class
650 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 651 CacheLookup STRET, _objc_msgSendSuper2_stret
c1e772c4
A
652 // cache hit, IMP in r12, ne already set for stret forwarding
653 ldr r1, [r1, #RECEIVER] // load real receiver
c1e772c4 654 bx r12 // call imp
7257e56c 655
1807f628 656 CacheLookup2 STRET, _objc_msgSendSuper2_stret
c1e772c4
A
657 // cache miss
658 ldr r9, [r1, #CLASS] // class = struct super->class
659 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
7257e56c
A
660 ldr r1, [r1, #RECEIVER] // load real receiver
661 b __objc_msgSend_stret_uncached
662
c1e772c4
A
663 END_ENTRY _objc_msgSendSuper2_stret
664
665
666 ENTRY _objc_msgLookupSuper2_stret
667
668 ldr r9, [r1, #CLASS] // class = struct super->class
669 ldr r9, [r9, #SUPERCLASS] // class = class->superclass
1807f628 670 CacheLookup STRET, _objc_msgLookupSuper2_stret
c1e772c4
A
671 // cache hit, IMP in r12, ne already set for stret forwarding
672 ldr r1, [r1, #RECEIVER] // load real receiver
673 bx lr
674
1807f628 675 CacheLookup2 STRET, _objc_msgLookupSuper2_stret
c1e772c4
A
676 // cache miss
677 ldr r9, [r1, #CLASS]
678 ldr r9, [r9, #SUPERCLASS] // r9 = class to search
679 ldr r1, [r1, #RECEIVER] // load real receiver
680 b __objc_msgLookup_stret_uncached
681
682 END_ENTRY _objc_msgLookupSuper2_stret
683
684
685/////////////////////////////////////////////////////////////////////
686//
687// MethodTableLookup NORMAL|STRET
688//
689// Locate the implementation for a selector in a class's method lists.
690//
691// Takes:
692// $0 = NORMAL, STRET
693// r0 or r1 (STRET) = receiver
694// r1 or r2 (STRET) = selector
695// r9 = class to search in
696//
697// On exit: IMP in r12, eq/ne set for forwarding
698//
699/////////////////////////////////////////////////////////////////////
700
701.macro MethodTableLookup
702
bc4fafce 703 SAVE_REGS
c1e772c4 704
1807f628 705 // lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
c1e772c4
A
706.if $0 == NORMAL
707 // receiver already in r0
708 // selector already in r1
709.else
710 mov r0, r1 // receiver
711 mov r1, r2 // selector
712.endif
713 mov r2, r9 // class to search
34d5b5e8 714 mov r3, #3 // LOOKUP_INITIALIZE | LOOKUP_RESOLVER
1807f628 715 blx _lookUpImpOrForward
c1e772c4
A
716 mov r12, r0 // r12 = IMP
717
718.if $0 == NORMAL
719 cmp r12, r12 // set eq for nonstret forwarding
720.else
721 tst r12, r12 // set ne for stret forwarding
722.endif
723
bc4fafce 724 RESTORE_REGS
c1e772c4
A
725
726.endmacro
7af964d1 727
7af964d1 728
7257e56c 729/********************************************************************
7257e56c
A
730 *
731 * _objc_msgSend_uncached
732 * _objc_msgSend_stret_uncached
c1e772c4
A
733 * _objc_msgLookup_uncached
734 * _objc_msgLookup_stret_uncached
735 * The uncached method lookup.
7257e56c
A
736 *
737 ********************************************************************/
7257e56c 738
c1e772c4 739 STATIC_ENTRY __objc_msgSend_uncached
8972963c 740
c1e772c4
A
741 // THIS IS NOT A CALLABLE C FUNCTION
742 // Out-of-band r9 is the class to search
8972963c 743
c1e772c4
A
744 MethodTableLookup NORMAL // returns IMP in r12
745 bx r12
8972963c 746
c1e772c4 747 END_ENTRY __objc_msgSend_uncached
8972963c 748
8972963c 749
c1e772c4 750 STATIC_ENTRY __objc_msgSend_stret_uncached
8972963c 751
7257e56c
A
752 // THIS IS NOT A CALLABLE C FUNCTION
753 // Out-of-band r9 is the class to search
8972963c 754
c1e772c4 755 MethodTableLookup STRET // returns IMP in r12
7257e56c 756 bx r12
c1e772c4
A
757
758 END_ENTRY __objc_msgSend_stret_uncached
8972963c 759
c1e772c4
A
760
761 STATIC_ENTRY __objc_msgLookup_uncached
7257e56c
A
762
763 // THIS IS NOT A CALLABLE C FUNCTION
764 // Out-of-band r9 is the class to search
765
c1e772c4
A
766 MethodTableLookup NORMAL // returns IMP in r12
767 bx lr
8972963c 768
c1e772c4 769 END_ENTRY __objc_msgLookup_uncached
8972963c 770
8972963c 771
c1e772c4
A
772 STATIC_ENTRY __objc_msgLookup_stret_uncached
773
774 // THIS IS NOT A CALLABLE C FUNCTION
775 // Out-of-band r9 is the class to search
776
777 MethodTableLookup STRET // returns IMP in r12
778 bx lr
8972963c 779
c1e772c4 780 END_ENTRY __objc_msgLookup_stret_uncached
7af964d1 781
7257e56c 782
7af964d1 783/********************************************************************
8070259c
A
784*
785* id _objc_msgForward(id self, SEL _cmd,...);
786*
787* _objc_msgForward and _objc_msgForward_stret are the externally-callable
788* functions returned by things like method_getImplementation().
789* _objc_msgForward_impcache is the function pointer actually stored in
790* method caches.
791*
792********************************************************************/
7af964d1 793
8070259c
A
794 MI_EXTERN(__objc_forward_handler)
795 MI_EXTERN(__objc_forward_stret_handler)
796
c1e772c4 797 STATIC_ENTRY __objc_msgForward_impcache
7af964d1
A
798 // Method cache version
799
800 // THIS IS NOT A CALLABLE C FUNCTION
c1e772c4 801 // Out-of-band Z is 0 (EQ) for normal, 1 (NE) for stret
7257e56c 802
7257e56c
A
803 beq __objc_msgForward
804 b __objc_msgForward_stret
7af964d1 805
c1e772c4 806 END_ENTRY __objc_msgForward_impcache
7af964d1
A
807
808
c1e772c4 809 ENTRY __objc_msgForward
7af964d1
A
810 // Non-stret version
811
8070259c 812 MI_GET_EXTERN(r12, __objc_forward_handler)
7257e56c 813 ldr r12, [r12]
8070259c 814 bx r12
7257e56c 815
c1e772c4 816 END_ENTRY __objc_msgForward
7af964d1
A
817
818
c1e772c4 819 ENTRY __objc_msgForward_stret
7af964d1 820 // Struct-return version
8972963c 821
8070259c 822 MI_GET_EXTERN(r12, __objc_forward_stret_handler)
7257e56c 823 ldr r12, [r12]
8070259c 824 bx r12
7257e56c 825
c1e772c4 826 END_ENTRY __objc_msgForward_stret
7af964d1
A
827
828
c1e772c4
A
829 ENTRY _objc_msgSend_noarg
830 b _objc_msgSend
831 END_ENTRY _objc_msgSend_noarg
832
833 ENTRY _objc_msgSend_debug
8972963c 834 b _objc_msgSend
c1e772c4 835 END_ENTRY _objc_msgSend_debug
7af964d1 836
c1e772c4 837 ENTRY _objc_msgSendSuper2_debug
8972963c 838 b _objc_msgSendSuper2
c1e772c4 839 END_ENTRY _objc_msgSendSuper2_debug
7af964d1 840
c1e772c4 841 ENTRY _objc_msgSend_stret_debug
8972963c 842 b _objc_msgSend_stret
c1e772c4 843 END_ENTRY _objc_msgSend_stret_debug
7af964d1 844
c1e772c4 845 ENTRY _objc_msgSendSuper2_stret_debug
8972963c 846 b _objc_msgSendSuper2_stret
c1e772c4 847 END_ENTRY _objc_msgSendSuper2_stret_debug
7af964d1
A
848
849
c1e772c4 850 ENTRY _method_invoke
bc4fafce
A
851
852 // See if this is a small method.
853 lsls r12, r1, #31
854 bne.w L_method_invoke_small
855
856 // We can directly load the IMP from big methods.
7257e56c
A
857 // r1 is method triplet instead of SEL
858 ldr r12, [r1, #METHOD_IMP]
859 ldr r1, [r1, #METHOD_NAME]
860 bx r12
bc4fafce
A
861
862L_method_invoke_small:
863 // Small methods require a call to handle swizzling.
864 SAVE_REGS
865 mov r0, r1
866 bl __method_getImplementationAndName
867 mov r12, r0
868 mov r9, r1
869 RESTORE_REGS
870 mov r1, r9
871 bx r12
872
873
c1e772c4 874 END_ENTRY _method_invoke
7af964d1
A
875
876
c1e772c4 877 ENTRY _method_invoke_stret
bc4fafce
A
878
879 // See if this is a small method.
880 lsls r12, r2, #31
881 bne.w L_method_invoke_stret_small
882
883 // We can directly load the IMP from big methods.
7257e56c
A
884 // r2 is method triplet instead of SEL
885 ldr r12, [r2, #METHOD_IMP]
886 ldr r2, [r2, #METHOD_NAME]
887 bx r12
bc4fafce
A
888
889L_method_invoke_stret_small:
890 // Small methods require a call to handle swizzling.
891 SAVE_REGS
892 mov r0, r2
893 bl __method_getImplementationAndName
894 mov r12, r0
895 mov r9, r1
896 RESTORE_REGS
897 mov r2, r9
898 bx r12
899
c1e772c4 900 END_ENTRY _method_invoke_stret
8972963c 901
7257e56c
A
902
903.section __DATA,__objc_msg_break
904.long 0
905.long 0
906
7af964d1 907#endif