]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-x86_64.s
objc4-532.2.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-x86_64.s
CommitLineData
b3962a83
A
1/*
2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
7af964d1
A
23
24#ifdef __x86_64__
25
b3962a83
A
26/********************************************************************
27 ********************************************************************
28 **
29 ** objc-msg-x86_64.s - x86-64 code to support objc messaging.
30 **
31 ********************************************************************
32 ********************************************************************/
33
34#define __OBJC2__ 1
35
b3962a83
A
36/********************************************************************
37* Data used by the ObjC runtime.
38*
39********************************************************************/
40
41.data
42// Substitute receiver for messages sent to nil (usually also nil)
43// id _objc_nilReceiver
44.align 4
8972963c 45.private_extern __objc_nilReceiver
b3962a83
A
46__objc_nilReceiver:
47 .quad 0
48
49// _objc_entryPoints and _objc_exitPoints are used by objc
50// to get the critical regions for which method caches
51// cannot be garbage collected.
52
8972963c 53.private_extern _objc_entryPoints
b3962a83
A
54_objc_entryPoints:
55 .quad __cache_getImp
56 .quad __cache_getMethod
57 .quad _objc_msgSend
58 .quad _objc_msgSend_fpret
59 .quad _objc_msgSend_fp2ret
60 .quad _objc_msgSend_stret
61 .quad _objc_msgSendSuper
62 .quad _objc_msgSendSuper_stret
8972963c
A
63 .quad _objc_msgSendSuper2
64 .quad _objc_msgSendSuper2_stret
b3962a83
A
65 .quad 0
66
8972963c 67.private_extern _objc_exitPoints
b3962a83 68_objc_exitPoints:
8972963c
A
69 .quad LExit__cache_getImp
70 .quad LExit__cache_getMethod
71 .quad LExit_objc_msgSend
72 .quad LExit_objc_msgSend_fpret
73 .quad LExit_objc_msgSend_fp2ret
74 .quad LExit_objc_msgSend_stret
75 .quad LExit_objc_msgSendSuper
76 .quad LExit_objc_msgSendSuper_stret
77 .quad LExit_objc_msgSendSuper2
78 .quad LExit_objc_msgSendSuper2_stret
b3962a83
A
79 .quad 0
80
81
82/********************************************************************
8972963c
A
83 * Recommended multi-byte NOP instructions
84 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
85 ********************************************************************/
86#define nop1 .byte 0x90
87#define nop2 .byte 0x66,0x90
88#define nop3 .byte 0x0F,0x1F,0x00
89#define nop4 .byte 0x0F,0x1F,0x40,0x00
90#define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
91#define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
92#define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
93#define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
94#define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
95
96
97/********************************************************************
b3962a83 98 * Names for parameter registers.
b3962a83
A
99 ********************************************************************/
100
8972963c
A
101#define a1 rdi
102#define a1d edi
103#define a1b dil
104#define a2 rsi
105#define a2d esi
106#define a2b sil
107#define a3 rdx
108#define a3d edx
109#define a4 rcx
110#define a4d ecx
111#define a5 r8
112#define a5d r8d
113#define a6 r9
b3962a83
A
114#define a6d r9d
115
116
8972963c
A
117/********************************************************************
118 * Names for relative labels
119 * DO NOT USE THESE LABELS ELSEWHERE
120 * Reserved labels: 5: 6: 7: 8: 9:
121 ********************************************************************/
122#define LCacheMiss 5
123#define LCacheMiss_f 5f
124#define LCacheMiss_b 5b
125#define LNilTestDone 6
126#define LNilTestDone_f 6f
127#define LNilTestDone_b 6b
128#define LNilTestSlow 7
129#define LNilTestSlow_f 7f
130#define LNilTestSlow_b 7b
131#define LGetIsaDone 8
132#define LGetIsaDone_f 8f
133#define LGetIsaDone_b 8b
134#define LGetIsaSlow 9
135#define LGetIsaSlow_f 9f
136#define LGetIsaSlow_b 9b
137
138/********************************************************************
139 * Macro parameters
140 ********************************************************************/
141
142#define STRET -1
143#define NORMAL 0
144#define FPRET 1
145#define FP2RET 2
146
147
b3962a83
A
148/********************************************************************
149 *
150 * Structure definitions.
151 *
152 ********************************************************************/
153
154// objc_super parameter to sendSuper
8972963c
A
155#define receiver 0
156#define class 8
b3962a83
A
157
158// Selected field offsets in class structure
8972963c
A
159// #define isa 0 USE GetIsa INSTEAD
160#define cache 16
b3962a83
A
161
162// Method descriptor
8972963c
A
163#define method_name 0
164#define method_imp 16
b3962a83
A
165
166// Cache header
8972963c
A
167#define mask 0
168#define occupied 8
169#define buckets 16
b3962a83
A
170
171// typedef struct {
172// uint128_t floatingPointArgs[8]; // xmm0..xmm7
173// long linkageArea[4]; // r10, rax, ebp, ret
174// long registerArgs[6]; // a1..a6
175// long stackArgs[0]; // variable-size
176// } *marg_list;
177#define FP_AREA 0
178#define LINK_AREA (FP_AREA+8*16)
179#define REG_AREA (LINK_AREA+4*8)
180#define STACK_AREA (REG_AREA+6*8)
181
182
b3962a83
A
183//////////////////////////////////////////////////////////////////////
184//
185// ENTRY functionName
186//
187// Assembly directives to begin an exported function.
188//
189// Takes: functionName - name of the exported function
190//////////////////////////////////////////////////////////////////////
191
192.macro ENTRY
193 .text
194 .globl $0
8972963c
A
195 .align 6, 0x90
196$0:
197.endmacro
198
199.macro STATIC_ENTRY
200 .text
201 .private_extern $0
b3962a83
A
202 .align 2, 0x90
203$0:
204.endmacro
205
206//////////////////////////////////////////////////////////////////////
207//
208// END_ENTRY functionName
209//
210// Assembly directives to end an exported function. Just a placeholder,
211// a close-parenthesis for ENTRY, until it is needed for something.
212//
213// Takes: functionName - name of the exported function
214//////////////////////////////////////////////////////////////////////
215
216.macro END_ENTRY
8972963c 217LExit$0:
b3962a83
A
218.endmacro
219
b3962a83 220
7af964d1
A
221/* DWARF support
222 These macros work for objc_msgSend variants and others that call
223 CacheLookup/MethodTableLookup or SaveRegisters/RestoreRegisters
224 without otherwise building a frame or clobbering callee-save registers
225
226 The macros build appropriate FDEs and tie them to the CIE.
227*/
228
229#define DW_CFA_offset 0x80
230#define DW_CFA_restore 0xc0
231#define DW_CFA_advance_loc4 0x4
232#define DW_CFA_same_value 0x8
233#define DW_CFA_def_cfa 0xc
234#define DW_CFA_def_cfa_register 0xd
235#define DW_CFA_def_cfa_offset 0xe
236#define DW_CFA_offset_extended_sf 0x11
237#define DW_CFA_def_cfa_offset_sf 0x13
238#define DW_rax 0
239#define DW_rdx 1
240#define DW_rcx 2
241#define DW_rsi 4
242#define DW_rdi 5
243#define DW_rbp 6
244#define DW_rsp 7
245#define DW_r8 8
246#define DW_r9 9
247#define DW_r10 10
248#define DW_ra 16
249#define DW_xmm0 17
250#define DW_xmm1 18
251#define DW_xmm2 19
252#define DW_xmm3 20
253#define DW_xmm4 21
254#define DW_xmm5 22
255#define DW_xmm6 23
256#define DW_xmm7 24
257#define DW_a1 DW_rdi
258#define DW_a2 DW_rsi
259#define DW_a3 DW_rdx
260#define DW_a4 DW_rcx
261#define DW_a5 DW_r8
262#define DW_a6 DW_r9
263
264// CIE
265// 8-byte data multiplier
266// 1-byte insn multiplier
267// PC-relative everything
268// No prologue
269
270 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
271CIE:
272 .set L$set$0,LECIE1-LSCIE1
273 .long L$set$0 # Length of Common Information Entry
274LSCIE1:
275 .long 0 # CIE Identifier Tag
276 .byte 0x3 # CIE Version
277 .ascii "zPR\0" # CIE Augmentation: size + personality + FDE encoding
278 .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
279 .byte 0x78 # sleb128 -0x8; CIE Data Alignment Factor
280 .byte 0x10 # CIE RA Column
281 .byte 0x6 # uleb128 0x1; Augmentation size
282 // Personality augmentation
283 .byte 0x9b
284 .long ___objc_personality_v0+4@GOTPCREL
285 // FDE-encoding augmentation
286 .byte 0x10
287 // Prefix instructions
288 // CFA is %rsp+8
289 .byte DW_CFA_def_cfa
290 .byte DW_rsp
291 .byte 8
cd5f04f5 292 // RA is at 0(%rsp) aka 1*-8(CFA)
7af964d1
A
293 .byte DW_CFA_offset | DW_ra
294 .byte 1
295
296 .align 3
297LECIE1:
298
299
300.macro EMIT_FDE
301
302 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
303
304// FDE header
305.globl $0.eh
306$0.eh:
307LSFDE$0:
308 .set LLENFDE$0, LEFDE$0-LASFDE$0
309 .long LLENFDE$0 # FDE Length
310LASFDE$0:
311 .long LASFDE$0-CIE # FDE CIE offset
cd5f04f5
A
312 .quad L_dw_start_$0-. # FDE address start
313 .quad L_dw_len_$0 # FDE address range
7af964d1
A
314 .byte 0x0 # uleb128 0x0; Augmentation size
315
316 // DW_START: set by CIE
317
cd5f04f5
A
318.if $1 == 1
319 // CacheLookup
7af964d1 320
cd5f04f5 321 // push
7af964d1 322 .byte DW_CFA_advance_loc4
cd5f04f5
A
323 .long L_dw_push_$0 - L_dw_start_$0
324 .byte DW_CFA_def_cfa_offset // CFA = rsp+16
7af964d1 325 .byte 16
cd5f04f5
A
326
327 // pop
328 .byte DW_CFA_advance_loc4
329 .long L_dw_pop_$0 - L_dw_push_$0
330 .byte DW_CFA_def_cfa_offset // CFA = rsp+8
331 .byte 8
332
333 // cache miss: push is back in effect
334 .byte DW_CFA_advance_loc4
335 .long L_dw_miss_$0 - L_dw_pop_$0
336 .byte DW_CFA_def_cfa_offset // CFA = rsp+16
337 .byte 16
338
339 // pop during cache miss
340 .byte DW_CFA_advance_loc4
341 .long L_dw_miss_pop_$0 - L_dw_miss_$0
342 .byte DW_CFA_def_cfa_offset // CFA = rsp+8
343 .byte 8
344
345.endif
346
347.if $2 == 1
348 // Save/RestoreRegisters or MethodTableLookup
349
350 // enter
7af964d1 351 .byte DW_CFA_advance_loc4
cd5f04f5
A
352.if $1 == 1
353 .long L_dw_enter_$0 - L_dw_miss_pop_$0
354.else
355 .long L_dw_enter_$0 - L_dw_start_$0
356.endif
357 .byte DW_CFA_def_cfa_offset
358 .byte 16
359 .byte DW_CFA_offset | DW_rbp // rbp => 2*-8(CFA)
360 .byte 2
361 .byte DW_CFA_def_cfa_register // CFA = rbp+16 (offset unchanged)
7af964d1 362 .byte DW_rbp
cd5f04f5
A
363
364 // leave
365 .byte DW_CFA_advance_loc4
366 .long L_dw_leave_$0 - L_dw_enter_$0
367
368 .byte DW_CFA_same_value // rbp = original value
369 .byte DW_rbp
370 .byte DW_CFA_def_cfa // CFA = rsp+8
371 .byte DW_rsp
372 .byte 8
7af964d1
A
373
374.endif
375
376 .align 3
377LEFDE$0:
378 .text
379
380.endmacro
381
382
cd5f04f5 383// Start of function
7af964d1 384.macro DW_START
cd5f04f5 385L_dw_start_$0:
7af964d1 386.endmacro
cd5f04f5
A
387
388// After `push` in CacheLookup
389.macro DW_PUSH
390L_dw_push_$0:
391.endmacro
392
393// After `pop` in CacheLookup
394.macro DW_POP
395L_dw_pop_$0:
396.endmacro
397
398// After cache miss label
399.macro DW_MISS
400L_dw_miss_$0:
401.endmacro
402
403// After pop in MethodTableLookup
404.macro DW_MISS_POP
405L_dw_miss_pop_$0:
7af964d1
A
406.endmacro
407
cd5f04f5
A
408// After `enter` in SaveRegisters
409.macro DW_ENTER
410L_dw_enter_$0:
7af964d1
A
411.endmacro
412
cd5f04f5
A
413// After `leave` in RestoreRegisters
414.macro DW_LEAVE
415L_dw_leave_$0:
416.endmacro
417
418// End of function
419// $1 == 1 iff you called CacheLookup
420// $2 == 1 iff you called MethodTableLookup or Save/RestoreRegsters
421.macro DW_END
422 .set L_dw_len_$0, . - L_dw_start_$0
423 EMIT_FDE $0, $1, $2
b3962a83
A
424.endmacro
425
426
427/////////////////////////////////////////////////////////////////////
428//
8972963c 429// SaveRegisters caller
b3962a83
A
430//
431// Pushes a stack frame and saves all registers that might contain
432// parameter values.
433//
8972963c
A
434// On entry: %0 = caller's symbol name for DWARF
435// stack = ret
b3962a83
A
436//
437// On exit:
8972963c 438// %rsp is 16-byte aligned
b3962a83
A
439//
440/////////////////////////////////////////////////////////////////////
7af964d1 441
b3962a83 442.macro SaveRegisters
cd5f04f5
A
443 // These instructions must match the DWARF data in EMIT_FDE.
444
8972963c 445 enter $$0x80+8, $$0 // +8 for alignment
cd5f04f5
A
446 DW_ENTER $0
447
8972963c
A
448 movdqa %xmm0, -0x80(%rbp)
449 push %rax // might be xmm parameter count
450 movdqa %xmm1, -0x70(%rbp)
451 push %a1
452 movdqa %xmm2, -0x60(%rbp)
453 push %a2
454 movdqa %xmm3, -0x50(%rbp)
455 push %a3
456 movdqa %xmm4, -0x40(%rbp)
457 push %a4
458 movdqa %xmm5, -0x30(%rbp)
459 push %a5
460 movdqa %xmm6, -0x20(%rbp)
461 push %a6
462 movdqa %xmm7, -0x10(%rbp)
cd5f04f5
A
463
464 // These instructions must match the DWARF data in EMIT_FDE.
b3962a83
A
465.endmacro
466
467/////////////////////////////////////////////////////////////////////
468//
469// RestoreRegisters
470//
471// Pops a stack frame pushed by SaveRegisters
472//
8972963c
A
473// On entry: $0 = caller's symbol name for DWARF
474// %rbp unchanged since SaveRegisters
b3962a83
A
475//
476// On exit:
8972963c 477// stack = ret
b3962a83
A
478//
479/////////////////////////////////////////////////////////////////////
480
481.macro RestoreRegisters
cd5f04f5
A
482 // These instructions must match the DWARF data in EMIT_FDE.
483
8972963c
A
484 movdqa -0x80(%rbp), %xmm0
485 pop %a6
486 movdqa -0x70(%rbp), %xmm1
487 pop %a5
488 movdqa -0x60(%rbp), %xmm2
489 pop %a4
490 movdqa -0x50(%rbp), %xmm3
491 pop %a3
492 movdqa -0x40(%rbp), %xmm4
493 pop %a2
494 movdqa -0x30(%rbp), %xmm5
495 pop %a1
496 movdqa -0x20(%rbp), %xmm6
497 pop %rax
498 movdqa -0x10(%rbp), %xmm7
cd5f04f5 499
8972963c 500 leave
cd5f04f5
A
501 DW_LEAVE $0
502
503 // These instructions must match the DWARF data in EMIT_FDE.
b3962a83
A
504.endmacro
505
506
507/////////////////////////////////////////////////////////////////////
508//
509//
cd5f04f5 510// CacheLookup return-type, caller
b3962a83
A
511//
512// Locate the implementation for a selector in a class method cache.
513//
514// Takes:
8972963c 515// $0 = NORMAL, FPRET, FP2RET, STRET
cd5f04f5 516// $1 = caller's symbol name for DWARF
8972963c 517// a2 or a3 (STRET) = selector
b3962a83 518// %r11 = class whose cache is to be searched
b3962a83 519//
8972963c
A
520// On exit: (found) method in %r11, stack unchanged, eq/ne set for forwarding
521// (not found) jumps to LCacheMiss, %rax on stack
522//
b3962a83
A
523/////////////////////////////////////////////////////////////////////
524
b3962a83
A
525.macro CacheLookup
526
8972963c 527 push %rax
cd5f04f5
A
528 DW_PUSH $1
529
8972963c
A
530 movq cache(%r11), %r10 // cache = class->cache
531.if $0 != STRET
532 mov %a2d, %eax // index = sel
533.else
534 mov %a3d, %eax // index = sel
535.endif
b3962a83
A
536
537// search the receiver's cache
538// r11 = method (soon)
8972963c
A
539// eax = index
540// r10 = cache
541// a2 or a3 = sel
5421:
543 andl mask(%r10), %eax // index &= mask
544 movq buckets(%r10, %rax, 8), %r11 // method = cache->buckets[index]
545 incl %eax // index++
b3962a83 546 testq %r11, %r11 // if (method == NULL)
8972963c
A
547 je LCacheMiss_f // goto cacheMissLabel
548.if $0 != STRET
549 cmpq method_name(%r11), %a2 // if (method_name != sel)
550.else
551 cmpq method_name(%r11), %a3 // if (method_name != sel)
552.endif
553 jne 1b // goto loop
b3962a83
A
554
555 // cache hit, r11 = method triplet
b3962a83 556 // restore saved registers
8972963c 557 pop %rax
cd5f04f5 558 DW_POP $1
8972963c
A
559
560.if $0 != STRET
561 // eq (non-stret) flag already set above
562.else
563 // set ne (stret) for forwarding; r11 != 0
564 test %r11, %r11
565.endif
b3962a83 566
b3962a83
A
567.endmacro
568
569
570/////////////////////////////////////////////////////////////////////
571//
cd5f04f5 572// MethodTableLookup classRegister, selectorRegister, caller
b3962a83 573//
8972963c
A
574// Takes: $0 = class to search (a1 or a2 or r10 ONLY)
575// $1 = selector to search for (a2 or a3 ONLY)
576// $2 = caller's symbol name for DWARF
577// r11 = class to search
b3962a83 578//
8972963c 579// Stack: ret, rax (pushed by CacheLookup)
b3962a83 580//
8972963c 581// On exit: pops registers pushed by CacheLookup
b3962a83
A
582// imp in %r11
583//
584/////////////////////////////////////////////////////////////////////
585.macro MethodTableLookup
8972963c
A
586
587 pop %rax // saved by CacheLookup
cd5f04f5
A
588 DW_MISS_POP $2
589
8972963c 590 SaveRegisters $2
b3962a83 591
8972963c 592 // _class_lookupMethodAndLoadCache3(receiver, selector, class)
b3962a83 593
b3962a83
A
594 movq $0, %a1
595 movq $1, %a2
8972963c
A
596 movq %r11, %a3
597 call __class_lookupMethodAndLoadCache3
b3962a83
A
598
599 // IMP is now in %rax
600 movq %rax, %r11
601
7af964d1 602 RestoreRegisters $2
b3962a83
A
603
604.endmacro
605
8972963c
A
606/////////////////////////////////////////////////////////////////////
607//
608// GetIsa return-type
609// GetIsaFast return-type
610// GetIsaSupport return-type
611//
612// Sets r11 = obj->isa. Consults the tagged isa table if necessary.
613//
614// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
615// a1 or a2 (STRET) = receiver
616//
617// On exit: r11 = receiver->isa
618// r10 is clobbered
619//
620/////////////////////////////////////////////////////////////////////
621
622.macro GetIsa
623
624.if $0 != STRET
625 testb $$1, %a1b
626 jnz 1f
627 movq (%a1), %r11
628 jmp 2f
6291: movl %a1d, %r10d
630.else
631 testb $$1, %a2b
632 jnz 1f
633 movq (%a2), %r11
634 jmp 2f
6351: movl %a2d, %r10d
636.endif
637 andl $$0xF, %r10d
638 leaq __objc_tagged_isa_table(%rip), %r11
639 movq (%r11, %r10, 8), %r11 // read isa from table
6402:
641.endmacro
642
643.macro GetIsaFast
644.if $0 != STRET
645 testb $$1, %a1b
646 .byte 0x2e // harmless branch hint prefix to align IFETCH blocks
647 jnz LGetIsaSlow_f
648 movq (%a1), %r11
649.else
650 testb $$1, %a2b
651 .byte 0x2e // harmless branch hint prefix to align IFETCH blocks
652 jnz LGetIsaSlow_f
653 movq (%a2), %r11
654.endif
655LGetIsaDone:
656.endmacro
657
658.macro GetIsaSupport
659LGetIsaSlow:
660 leaq __objc_tagged_isa_table(%rip), %r11
661.if $0 != STRET
662 movl %a1d, %r10d
663.else
664 movl %a2d, %r10d
665.endif
666 andl $$0xF, %r10d
667 movq (%r11, %r10, 8), %r11 // read isa from table
668 jmp LGetIsaDone_b
669.endmacro
670
671/////////////////////////////////////////////////////////////////////
672//
673// NilTest return-type
674//
675// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
676// %a1 or %a2 (STRET) = receiver
677//
678// On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
679//
680// NilTestSupport return-type
681//
682// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
683// %a1 or %a2 (STRET) = receiver
684//
685// On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
686//
687/////////////////////////////////////////////////////////////////////
688
689.macro NilTest
690.if $0 != STRET
691 testq %a1, %a1
692.else
693 testq %a2, %a2
694.endif
695 jz LNilTestSlow_f
696LNilTestDone:
697.endmacro
698
699.macro NilTestSupport
700 .align 3
701LNilTestSlow:
702.if $0 != STRET
703 movq __objc_nilReceiver(%rip), %a1
704 testq %a1, %a1 // if (receiver != nil)
705.else
706 movq __objc_nilReceiver(%rip), %a2
707 testq %a2, %a2 // if (receiver != nil)
708.endif
709 jne LNilTestDone_b // send to new receiver
710
711.if $0 == FPRET
712 fldz
713.elseif $0 == FP2RET
714 fldz
715 fldz
716.endif
717.if $0 != STRET
718 xorl %eax, %eax
719 xorl %edx, %edx
720 xorps %xmm0, %xmm0
721 xorps %xmm1, %xmm1
722.endif
723 ret
724.endmacro
725
b3962a83
A
726
727/********************************************************************
7af964d1 728 * Method _cache_getMethod(Class cls, SEL sel, IMP msgForward_internal_imp)
b3962a83
A
729 *
730 * On entry: a1 = class whose cache is to be searched
731 * a2 = selector to search for
7af964d1 732 * a3 = _objc_msgForward_internal IMP
b3962a83
A
733 *
734 * If found, returns method triplet pointer.
735 * If not found, returns NULL.
736 *
737 * NOTE: _cache_getMethod never returns any cache entry whose implementation
7af964d1
A
738 * is _objc_msgForward_internal. It returns 1 instead. This prevents thread-
739 * thread-safety and memory management bugs in _class_lookupMethodAndLoadCache.
b3962a83
A
740 * See _class_lookupMethodAndLoadCache for details.
741 *
7af964d1
A
742 * _objc_msgForward_internal is passed as a parameter because it's more
743 * efficient to do the (PIC) lookup once in the caller than repeatedly here.
b3962a83 744 ********************************************************************/
8972963c
A
745
746 STATIC_ENTRY __cache_getMethod
7af964d1 747 DW_START __cache_getMethod
b3962a83
A
748
749// do lookup
750 movq %a1, %r11 // move class to r11 for CacheLookup
cd5f04f5 751 CacheLookup NORMAL, __cache_getMethod
b3962a83
A
752
753// cache hit, method triplet in %r11
8972963c
A
754 cmpq method_imp(%r11), %a3 // if (imp==_objc_msgForward_internal)
755 je 1f // return (Method)1
b3962a83
A
756 movq %r11, %rax // return method triplet address
757 ret
8972963c 7581: movl $1, %eax
7af964d1 759 ret
b3962a83 760
8972963c 761LCacheMiss:
b3962a83 762// cache miss, return nil
cd5f04f5 763 DW_MISS __cache_getMethod
8972963c 764 pop %rax // pushed by CacheLookup
cd5f04f5 765 DW_MISS_POP __cache_getMethod
8972963c 766 xorl %eax, %eax
b3962a83
A
767 ret
768
769LGetMethodExit:
cd5f04f5 770 DW_END __cache_getMethod, 1, 0
7af964d1 771 END_ENTRY __cache_getMethod
b3962a83
A
772
773
774/********************************************************************
775 * IMP _cache_getImp(Class cls, SEL sel)
776 *
777 * On entry: a1 = class whose cache is to be searched
778 * a2 = selector to search for
779 *
780 * If found, returns method implementation.
781 * If not found, returns NULL.
782 ********************************************************************/
783
8972963c 784 STATIC_ENTRY __cache_getImp
7af964d1 785 DW_START __cache_getImp
b3962a83
A
786
787// do lookup
788 movq %a1, %r11 // move class to r11 for CacheLookup
cd5f04f5 789 CacheLookup NORMAL, __cache_getImp
b3962a83
A
790
791// cache hit, method triplet in %r11
792 movq method_imp(%r11), %rax // return method imp address
793 ret
794
8972963c 795LCacheMiss:
b3962a83 796// cache miss, return nil
cd5f04f5 797 DW_MISS __cache_getImp
8972963c 798 pop %rax // pushed by CacheLookup
cd5f04f5 799 DW_MISS_POP __cache_getImp
8972963c 800 xorl %eax, %eax
b3962a83
A
801 ret
802
803LGetImpExit:
cd5f04f5 804 DW_END __cache_getImp, 1, 0
7af964d1 805 END_ENTRY __cache_getImp
b3962a83
A
806
807
808/********************************************************************
809 *
810 * id objc_msgSend(id self, SEL _cmd,...);
811 *
812 ********************************************************************/
813
8972963c
A
814 .data
815 .align 3
816 .private_extern __objc_tagged_isa_table
817__objc_tagged_isa_table:
818 .fill 16, 8, 0
819
b3962a83 820 ENTRY _objc_msgSend
7af964d1 821 DW_START _objc_msgSend
b3962a83 822
8972963c 823 NilTest NORMAL
b3962a83 824
8972963c 825 GetIsaFast NORMAL // r11 = self->isa
cd5f04f5 826 CacheLookup NORMAL, _objc_msgSend // r11=method, eq set (nonstret fwd)
8972963c 827 jmp *method_imp(%r11) // goto *imp
b3962a83 828
8972963c 829 NilTestSupport NORMAL
b3962a83 830
8972963c 831 GetIsaSupport NORMAL
b3962a83 832
8972963c
A
833// cache miss: go search the method lists
834LCacheMiss:
cd5f04f5 835 DW_MISS _objc_msgSend
8972963c
A
836 GetIsa NORMAL // r11 = self->isa
837 MethodTableLookup %a1, %a2, _objc_msgSend // r11 = IMP
838 cmp %r11, %r11 // set eq (nonstret) for forwarding
839 jmp *%r11 // goto *imp
b3962a83 840
cd5f04f5 841 DW_END _objc_msgSend, 1, 1
b3962a83
A
842 END_ENTRY _objc_msgSend
843
844#if __OBJC2__
845 ENTRY _objc_msgSend_fixup
7af964d1 846 DW_START _objc_msgSend_fixup
b3962a83 847
8972963c 848 NilTest NORMAL
7af964d1 849
8972963c
A
850 SaveRegisters _objc_msgSend_fixup
851
7af964d1 852 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
853 movq 8(%a2), %a6 // selector
854 GetIsa NORMAL // r11 = isa = *receiver
855 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
856 movq mask(%a5), %a4 // *cache
857
b3962a83
A
858 // a1 = receiver
859 // a2 = address of message ref
860 movq %a2, %a3
8972963c 861 xorl %a2d, %a2d
b3962a83
A
862 // __objc_fixupMessageRef(receiver, 0, ref)
863 call __objc_fixupMessageRef
864 movq %rax, %r11
7af964d1
A
865
866 RestoreRegisters _objc_msgSend_fixup
b3962a83
A
867
868 // imp is in r11
869 // Load _cmd from the message_ref
870 movq 8(%a2), %a2
7af964d1 871 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
872 jmp *%r11
873
8972963c 874 NilTestSupport NORMAL
b3962a83 875
cd5f04f5 876 DW_END _objc_msgSend_fixup, 0, 1
7af964d1 877 END_ENTRY _objc_msgSend_fixup
b3962a83
A
878
879
8972963c 880 STATIC_ENTRY _objc_msgSend_fixedup
b3962a83
A
881 // Load _cmd from the message_ref
882 movq 8(%a2), %a2
883 jmp _objc_msgSend
884 END_ENTRY _objc_msgSend_fixedup
885#endif
886
887
888/********************************************************************
889 *
890 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
891 *
892 * struct objc_super {
893 * id receiver;
894 * Class class;
895 * };
896 ********************************************************************/
897
898 ENTRY _objc_msgSendSuper
7af964d1 899 DW_START _objc_msgSendSuper
b3962a83 900
b3962a83
A
901// search the cache (objc_super in %a1)
902 movq class(%a1), %r11 // class = objc_super->class
cd5f04f5 903 CacheLookup NORMAL, _objc_msgSendSuper // r11 = method, eq set (nonstret fwd)
b3962a83 904 movq receiver(%a1), %a1 // load real receiver
8972963c 905 jmp *method_imp(%r11) // goto *imp
b3962a83
A
906
907// cache miss: go search the method lists
8972963c 908LCacheMiss:
cd5f04f5 909 DW_MISS _objc_msgSendSuper
8972963c
A
910 movq receiver(%a1), %r10
911 movq class(%a1), %r11
912 MethodTableLookup %r10, %a2, _objc_msgSendSuper // r11 = IMP
b3962a83 913 movq receiver(%a1), %a1 // load real receiver
8972963c 914 cmp %r11, %r11 // set eq (nonstret) for forwarding
b3962a83 915 jmp *%r11 // goto *imp
b3962a83 916
cd5f04f5 917 DW_END _objc_msgSendSuper, 1, 1
b3962a83
A
918 END_ENTRY _objc_msgSendSuper
919
8972963c
A
920
921/********************************************************************
922 * id objc_msgSendSuper2
923 ********************************************************************/
924
b3962a83
A
925#if __OBJC2__
926 ENTRY _objc_msgSendSuper2_fixup
7af964d1 927 DW_START _objc_msgSendSuper2_fixup
b3962a83 928
8972963c 929 SaveRegisters _objc_msgSendSuper2_fixup
b3962a83
A
930 // a1 = address of objc_super2
931 // a2 = address of message ref
932 movq %a2, %a3
933 movq %a1, %a2
934 movq receiver(%a1), %a1
935 // __objc_fixupMessageRef(receiver, objc_super, ref)
936 call __objc_fixupMessageRef
937 movq %rax, %r11
7af964d1 938 RestoreRegisters _objc_msgSendSuper2_fixup
b3962a83
A
939
940 // imp is in r11
941 // Load _cmd from the message_ref
942 movq 8(%a2), %a2
943 // Load receiver from objc_super2
944 movq receiver(%a1), %a1
7af964d1 945 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
946 jmp *%r11
947
cd5f04f5 948 DW_END _objc_msgSendSuper2_fixup, 0, 1
7af964d1 949 END_ENTRY _objc_msgSendSuper2_fixup
b3962a83
A
950
951
8972963c 952 STATIC_ENTRY _objc_msgSendSuper2_fixedup
b3962a83 953 movq 8(%a2), %a2 // load _cmd from message_ref
8972963c 954 jmp _objc_msgSendSuper2
b3962a83 955 END_ENTRY _objc_msgSendSuper2_fixedup
7af964d1
A
956
957
958 ENTRY _objc_msgSendSuper2
8972963c 959 DW_START _objc_msgSendSuper2
7af964d1 960 // objc_super->class is superclass of class to search
8972963c
A
961
962// search the cache (objc_super in %a1)
7af964d1 963 movq class(%a1), %r11 // cls = objc_super->class
8972963c 964 movq 8(%r11), %r11 // cls = class->superclass
cd5f04f5 965 CacheLookup NORMAL, _objc_msgSendSuper2 // r11 = method, eq set (nonstret fwd)
8972963c
A
966 movq receiver(%a1), %a1 // load real receiver
967 jmp *method_imp(%r11) // goto *imp
968
969// cache miss: go search the method lists
970LCacheMiss:
cd5f04f5 971 DW_MISS _objc_msgSendSuper2
8972963c
A
972 movq receiver(%a1), %r10
973 movq class(%a1), %r11
974 movq 8(%r11), %r11
975 MethodTableLookup %r10, %a2, _objc_msgSendSuper2 // r11 = IMP
976 movq receiver(%a1), %a1 // load real receiver
977 cmp %r11, %r11 // set eq (nonstret) for forwarding
978 jmp *%r11 // goto *imp
979
cd5f04f5 980 DW_END _objc_msgSendSuper2, 1, 1
8972963c 981 END_ENTRY _objc_msgSendSuper2
b3962a83
A
982#endif
983
984
985/********************************************************************
986 *
987 * double objc_msgSend_fpret(id self, SEL _cmd,...);
988 * Used for `long double` return only. `float` and `double` use objc_msgSend.
989 *
990 ********************************************************************/
991
992 ENTRY _objc_msgSend_fpret
7af964d1 993 DW_START _objc_msgSend_fpret
b3962a83 994
8972963c 995 NilTest FPRET
b3962a83 996
8972963c 997 GetIsaFast FPRET // r11 = self->isa
cd5f04f5 998 CacheLookup FPRET, _objc_msgSend_fpret // r11 = method, eq set (nonstret fwd)
8972963c 999 jmp *method_imp(%r11) // goto *imp
b3962a83 1000
8972963c 1001 NilTestSupport FPRET
b3962a83 1002
8972963c 1003 GetIsaSupport FPRET
b3962a83 1004
8972963c
A
1005// cache miss: go search the method lists
1006LCacheMiss:
cd5f04f5 1007 DW_MISS _objc_msgSend_fpret
8972963c
A
1008 GetIsa FPRET // r11 = self->isa
1009 MethodTableLookup %a1, %a2, _objc_msgSend_fpret // r11 = IMP
1010 cmp %r11, %r11 // set eq (nonstret) for forwarding
1011 jmp *%r11 // goto *imp
b3962a83 1012
cd5f04f5 1013 DW_END _objc_msgSend_fpret, 1, 1
b3962a83
A
1014 END_ENTRY _objc_msgSend_fpret
1015
1016#if __OBJC2__
1017 ENTRY _objc_msgSend_fpret_fixup
7af964d1 1018 DW_START _objc_msgSend_fpret_fixup
b3962a83 1019
8972963c 1020 NilTest FPRET
b3962a83 1021
8972963c 1022 SaveRegisters _objc_msgSend_fpret_fixup
7af964d1
A
1023
1024 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
1025 movq 8(%a2), %a6 // selector
1026 GetIsa FPRET // r11 = isa = *receiver
1027 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
1028 movq mask(%a5), %a4 // *cache
1029
b3962a83
A
1030 // a1 = receiver
1031 // a2 = address of message ref
1032 movq %a2, %a3
8972963c 1033 xorl %a2d, %a2d
b3962a83
A
1034 // __objc_fixupMessageRef(receiver, 0, ref)
1035 call __objc_fixupMessageRef
1036 movq %rax, %r11
7af964d1
A
1037
1038 RestoreRegisters _objc_msgSend_fpret_fixup
b3962a83
A
1039
1040 // imp is in r11
1041 // Load _cmd from the message_ref
1042 movq 8(%a2), %a2
7af964d1 1043 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
1044 jmp *%r11
1045
8972963c 1046 NilTestSupport FPRET
b3962a83 1047
cd5f04f5 1048 DW_END _objc_msgSend_fpret_fixup, 0, 1
7af964d1 1049 END_ENTRY _objc_msgSend_fpret_fixup
b3962a83
A
1050
1051
8972963c 1052 STATIC_ENTRY _objc_msgSend_fpret_fixedup
b3962a83
A
1053 // Load _cmd from the message_ref
1054 movq 8(%a2), %a2
1055 jmp _objc_msgSend_fpret
1056 END_ENTRY _objc_msgSend_fpret_fixedup
1057#endif
1058
1059
1060/********************************************************************
1061 *
1062 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
1063 * Used for `complex long double` return only.
1064 *
1065 ********************************************************************/
1066
1067 ENTRY _objc_msgSend_fp2ret
7af964d1 1068 DW_START _objc_msgSend_fp2ret
b3962a83 1069
8972963c 1070 NilTest FP2RET
b3962a83 1071
8972963c 1072 GetIsaFast FP2RET // r11 = self->isa
cd5f04f5 1073 CacheLookup FP2RET, _objc_msgSend_fp2ret // r11 = method, eq set (nonstret fwd)
8972963c 1074 jmp *method_imp(%r11) // goto *imp
b3962a83 1075
8972963c
A
1076 NilTestSupport FP2RET
1077
1078 GetIsaSupport FP2RET
1079
b3962a83 1080// cache miss: go search the method lists
8972963c 1081LCacheMiss:
cd5f04f5 1082 DW_MISS _objc_msgSend_fp2ret
8972963c
A
1083 GetIsa FP2RET // r11 = self->isa
1084 MethodTableLookup %a1, %a2, _objc_msgSend_fp2ret // r11 = IMP
1085 cmp %r11, %r11 // set eq (nonstret) for forwarding
b3962a83
A
1086 jmp *%r11 // goto *imp
1087
cd5f04f5 1088 DW_END _objc_msgSend_fp2ret, 1, 1
b3962a83
A
1089 END_ENTRY _objc_msgSend_fp2ret
1090
1091#if __OBJC2__
1092 ENTRY _objc_msgSend_fp2ret_fixup
7af964d1 1093 DW_START _objc_msgSend_fp2ret_fixup
b3962a83 1094
8972963c 1095 NilTest FP2RET
b3962a83 1096
8972963c 1097 SaveRegisters _objc_msgSend_fp2ret_fixup
7af964d1
A
1098
1099 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
1100 movq 8(%a2), %a6 // selector
1101 GetIsa FP2RET // r11 = isa = *receiver
1102 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
1103 movq mask(%a5), %a4 // *cache
1104
b3962a83
A
1105 // a1 = receiver
1106 // a2 = address of message ref
1107 movq %a2, %a3
8972963c 1108 xorl %a2d, %a2d
b3962a83
A
1109 // __objc_fixupMessageRef(receiver, 0, ref)
1110 call __objc_fixupMessageRef
1111 movq %rax, %r11
7af964d1
A
1112
1113 RestoreRegisters _objc_msgSend_fp2ret_fixup
b3962a83
A
1114
1115 // imp is in r11
1116 // Load _cmd from the message_ref
1117 movq 8(%a2), %a2
7af964d1 1118 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
1119 jmp *%r11
1120
8972963c 1121 NilTestSupport FP2RET
b3962a83 1122
cd5f04f5 1123 DW_END _objc_msgSend_fp2ret_fixup, 0, 1
7af964d1 1124 END_ENTRY _objc_msgSend_fp2ret_fixup
b3962a83
A
1125
1126
8972963c 1127 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
b3962a83
A
1128 // Load _cmd from the message_ref
1129 movq 8(%a2), %a2
1130 jmp _objc_msgSend_fp2ret
1131 END_ENTRY _objc_msgSend_fp2ret_fixedup
1132#endif
1133
1134
1135/********************************************************************
1136 *
1137 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
1138 *
1139 * objc_msgSend_stret is the struct-return form of msgSend.
1140 * The ABI calls for %a1 to be used as the address of the structure
1141 * being returned, with the parameters in the succeeding locations.
1142 *
1143 * On entry: %a1 is the address where the structure is returned,
1144 * %a2 is the message receiver,
1145 * %a3 is the selector
1146 ********************************************************************/
1147
1148 ENTRY _objc_msgSend_stret
7af964d1 1149 DW_START _objc_msgSend_stret
b3962a83 1150
8972963c
A
1151 NilTest STRET
1152
1153 GetIsaFast STRET // r11 = self->isa
cd5f04f5 1154 CacheLookup STRET, _objc_msgSend_stret // r11 = method, ne set (stret fwd)
8972963c
A
1155 jmp *method_imp(%r11) // goto *imp
1156
1157 NilTestSupport STRET
1158
1159 GetIsaSupport STRET
b3962a83
A
1160
1161// cache miss: go search the method lists
8972963c 1162LCacheMiss:
cd5f04f5 1163 DW_MISS _objc_msgSend_stret
8972963c
A
1164 GetIsa STRET // r11 = self->isa
1165 MethodTableLookup %a2, %a3, _objc_msgSend_stret // r11 = IMP
1166 test %r11, %r11 // set ne (stret) for forward; r11!=0
7af964d1 1167 jmp *%r11 // goto *imp
b3962a83 1168
cd5f04f5 1169 DW_END _objc_msgSend_stret, 1, 1
b3962a83
A
1170 END_ENTRY _objc_msgSend_stret
1171
1172#if __OBJC2__
1173 ENTRY _objc_msgSend_stret_fixup
7af964d1 1174 DW_START _objc_msgSend_stret_fixup
b3962a83 1175
8972963c 1176 NilTest STRET
b3962a83 1177
8972963c 1178 SaveRegisters _objc_msgSend_stret_fixup
7af964d1
A
1179
1180 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
1181 movq 8(%a3), %a6 // selector
1182 GetIsa STRET // r11 = isa = *receiver
1183 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
1184 movq mask(%a5), %a4 // *cache
1185
b3962a83
A
1186 // a2 = receiver
1187 // a3 = address of message ref
1188 movq %a2, %a1
8972963c 1189 xorl %a2d, %a2d
b3962a83
A
1190 // __objc_fixupMessageRef(receiver, 0, ref)
1191 call __objc_fixupMessageRef
1192 movq %rax, %r11
7af964d1
A
1193
1194 RestoreRegisters _objc_msgSend_stret_fixup
b3962a83
A
1195
1196 // imp is in r11
1197 // Load _cmd from the message_ref
1198 movq 8(%a3), %a3
7af964d1
A
1199 test %r11, %r11 // set stret (ne) for forward; r11!=0
1200 jmp *%r11 // goto *imp
b3962a83 1201
8972963c 1202 NilTestSupport STRET
b3962a83 1203
cd5f04f5 1204 DW_END _objc_msgSend_stret_fixup, 0, 1
7af964d1 1205 END_ENTRY _objc_msgSend_stret_fixup
b3962a83
A
1206
1207
8972963c 1208 STATIC_ENTRY _objc_msgSend_stret_fixedup
b3962a83
A
1209 // Load _cmd from the message_ref
1210 movq 8(%a3), %a3
1211 jmp _objc_msgSend_stret
1212 END_ENTRY _objc_msgSend_stret_fixedup
1213#endif
1214
1215
1216/********************************************************************
1217 *
1218 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
1219 *
1220 * struct objc_super {
1221 * id receiver;
1222 * Class class;
1223 * };
1224 *
1225 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
1226 * The ABI calls for (sp+4) to be used as the address of the structure
1227 * being returned, with the parameters in the succeeding registers.
1228 *
1229 * On entry: %a1 is the address where the structure is returned,
1230 * %a2 is the address of the objc_super structure,
1231 * %a3 is the selector
1232 *
1233 ********************************************************************/
1234
1235 ENTRY _objc_msgSendSuper_stret
7af964d1 1236 DW_START _objc_msgSendSuper_stret
b3962a83
A
1237
1238// search the cache (objc_super in %a2)
8972963c 1239 movq class(%a2), %r11 // class = objc_super->class
cd5f04f5 1240 CacheLookup STRET, _objc_msgSendSuper_stret // r11 = method, ne set (stret fwd)
7af964d1 1241 movq receiver(%a2), %a2 // load real receiver
8972963c 1242 jmp *method_imp(%r11) // goto *imp
b3962a83
A
1243
1244// cache miss: go search the method lists
8972963c 1245LCacheMiss:
cd5f04f5 1246 DW_MISS _objc_msgSendSuper_stret
8972963c
A
1247 movq receiver(%a2), %r10
1248 movq class(%a2), %r11
1249 MethodTableLookup %r10, %a3, _objc_msgSendSuper_stret // r11 = IMP
7af964d1 1250 movq receiver(%a2), %a2 // load real receiver
8972963c 1251 test %r11, %r11 // set ne (stret) for forward; r11!=0
7af964d1 1252 jmp *%r11 // goto *imp
b3962a83 1253
cd5f04f5 1254 DW_END _objc_msgSendSuper_stret, 1, 1
b3962a83
A
1255 END_ENTRY _objc_msgSendSuper_stret
1256
8972963c
A
1257
1258/********************************************************************
1259 * id objc_msgSendSuper2_stret
1260 ********************************************************************/
1261
b3962a83
A
1262#if __OBJC2__
1263 ENTRY _objc_msgSendSuper2_stret_fixup
7af964d1 1264 DW_START _objc_msgSendSuper2_stret_fixup
b3962a83 1265
8972963c 1266 SaveRegisters _objc_msgSendSuper2_stret_fixup
b3962a83
A
1267 // a2 = address of objc_super2
1268 // a3 = address of message ref
1269 movq receiver(%a2), %a1
1270 // __objc_fixupMessageRef(receiver, objc_super, ref)
1271 call __objc_fixupMessageRef
1272 movq %rax, %r11
7af964d1 1273 RestoreRegisters _objc_msgSendSuper2_stret_fixup
b3962a83
A
1274
1275 // imp is in r11
1276 // Load _cmd from the message_ref
1277 movq 8(%a3), %a3
1278 // Load receiver from objc_super2
1279 movq receiver(%a2), %a2
7af964d1
A
1280 test %r11, %r11 // set stret (ne) for forward; r11!=0
1281 jmp *%r11 // goto *imp
b3962a83 1282
cd5f04f5 1283 DW_END _objc_msgSendSuper2_stret_fixup, 0, 1
7af964d1 1284 END_ENTRY _objc_msgSendSuper2_stret_fixup
b3962a83
A
1285
1286
8972963c 1287 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
b3962a83 1288 movq 8(%a3), %a3 // load _cmd from message_ref
8972963c 1289 jmp _objc_msgSendSuper2_stret
b3962a83 1290 END_ENTRY _objc_msgSendSuper2_stret_fixedup
7af964d1
A
1291
1292
8972963c
A
1293 ENTRY _objc_msgSendSuper2_stret
1294 DW_START _objc_msgSendSuper2_stret
1295
1296// search the cache (objc_super in %a2)
1297 movq class(%a2), %r11 // class = objc_super->class
1298 movq 8(%r11), %r11 // class = class->super_class
cd5f04f5 1299 CacheLookup STRET, _objc_msgSendSuper2_stret // r11 = method, ne set (stret fwd)
8972963c
A
1300 movq receiver(%a2), %a2 // load real receiver
1301 jmp *method_imp(%r11) // goto *imp
1302
1303// cache miss: go search the method lists
1304LCacheMiss:
cd5f04f5 1305 DW_MISS _objc_msgSendSuper2_stret
8972963c
A
1306 movq receiver(%a2), %r10
1307 movq class(%a2), %r11
1308 movq 8(%r11), %r11
1309 MethodTableLookup %r10, %a3, _objc_msgSendSuper2_stret // r11 = IMP
1310 movq receiver(%a2), %a2 // load real receiver
1311 test %r11, %r11 // set ne (stret) for forward; r11!=0
1312 jmp *%r11 // goto *imp
1313
cd5f04f5 1314 DW_END _objc_msgSendSuper2_stret, 1, 1
8972963c 1315 END_ENTRY _objc_msgSendSuper2_stret
b3962a83
A
1316#endif
1317
1318
1319/********************************************************************
1320 *
1321 * id _objc_msgForward(id self, SEL _cmd,...);
1322 *
1323 ********************************************************************/
1324
1325// _FwdSel is @selector(forward::), set up in map_images().
1326// ALWAYS dereference _FwdSel to get to "forward::" !!
1327 .data
1328 .align 3
1329 .private_extern _FwdSel
1330_FwdSel: .quad 0
1331
1332 .cstring
1333 .align 3
cd5f04f5 1334LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0"
b3962a83
A
1335
1336 .data
1337 .align 3
1338 .private_extern __objc_forward_handler
1339__objc_forward_handler: .quad 0
1340
1341 .data
1342 .align 3
1343 .private_extern __objc_forward_stret_handler
1344__objc_forward_stret_handler: .quad 0
1345
b3962a83 1346
8972963c 1347 STATIC_ENTRY __objc_msgForward_internal
7af964d1
A
1348 // Method cache version
1349
1350 // THIS IS NOT A CALLABLE C FUNCTION
1351 // Out-of-band condition register is NE for stret, EQ otherwise.
b3962a83 1352
7af964d1
A
1353 jne __objc_msgForward_stret
1354 jmp __objc_msgForward
1355
1356 END_ENTRY __objc_msgForward_internal
1357
1358
1359 ENTRY __objc_msgForward
1360 // Non-stret version
b3962a83
A
1361
1362 // Call user handler, if any
1363 movq __objc_forward_handler(%rip), %r11
1364 testq %r11, %r11 // if (handler == NULL)
1365 je 1f // skip handler
1366 jmp *%r11 // else goto handler
13671:
1368 // No user handler
1369
1370 // Die if forwarding "forward::"
1371 cmpq %a2, _FwdSel(%rip)
1372 je LMsgForwardError
1373
1374 // Record current return address. It will be copied elsewhere in
1375 // the marg_list because this location is needed for register args
1376 movq (%rsp), %r11
1377
1378 // Push stack frame
1379 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1380 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1381
1382 // Save return address in linkage area.
1383 movq %r11, 16+LINK_AREA(%rsp)
1384
1385 // Save parameter registers
1386 movq %a1, 0+REG_AREA(%rsp)
1387 movq %a2, 8+REG_AREA(%rsp)
1388 movq %a3, 16+REG_AREA(%rsp)
1389 movq %a4, 24+REG_AREA(%rsp)
1390 movq %a5, 32+REG_AREA(%rsp)
1391 movq %a6, 40+REG_AREA(%rsp)
1392
1393 // Save side parameter registers
8972963c 1394 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
b3962a83
A
1395 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1396 // 16+LINK_AREA is return address
1397
1398 // Save xmm registers
1399 movdqa %xmm0, 0+FP_AREA(%rsp)
1400 movdqa %xmm1, 16+FP_AREA(%rsp)
1401 movdqa %xmm2, 32+FP_AREA(%rsp)
1402 movdqa %xmm3, 48+FP_AREA(%rsp)
1403 movdqa %xmm4, 64+FP_AREA(%rsp)
1404 movdqa %xmm5, 80+FP_AREA(%rsp)
1405 movdqa %xmm6, 96+FP_AREA(%rsp)
1406 movdqa %xmm7, 112+FP_AREA(%rsp)
1407
1408 // Call [receiver forward:sel :margs]
1409 movq %rsp, %a4 // marg_list
1410 movq %a2, %a3 // sel
1411 movq _FwdSel(%rip), %a2 // forward::
1412 // %a1 is already the receiver
1413
1414 call _objc_msgSend
1415
1416 // Retrieve return address from linkage area
1417 movq 16+LINK_AREA(%rsp), %r11
1418 // Pop stack frame
8972963c 1419 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
b3962a83
A
1420 // Put return address back
1421 movq %r11, (%rsp)
1422 ret
1423
1424LMsgForwardError:
cd5f04f5 1425 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
b3962a83 1426 // %a1 is already the receiver
cd5f04f5
A
1427 movq %a3, %a4 // the forwarded selector
1428 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s"
b3962a83
A
1429 movq _FwdSel(%rip), %a3 // forward::
1430 jmp ___objc_error // never returns
1431
1432 END_ENTRY __objc_msgForward
1433
1434
1435 ENTRY __objc_msgForward_stret
7af964d1
A
1436 // Struct-return version
1437
b3962a83
A
1438 // Call user handler, if any
1439 movq __objc_forward_stret_handler(%rip), %r11
1440 testq %r11, %r11 // if (handler == NULL)
1441 je 1f // skip handler
1442 jmp *%r11 // else goto handler
14431:
1444 // No user handler
1445 // Die if forwarding "forward::"
1446 cmpq %a3, _FwdSel(%rip)
1447 je LMsgForwardStretError
1448
1449 // Record current return address. It will be copied elsewhere in
1450 // the marg_list because this location is needed for register args
1451 movq (%rsp), %r11
1452
1453 // Push stack frame
1454 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1455 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1456
1457 // Save return address in linkage area.
1458 movq %r11, 16+LINK_AREA(%rsp)
1459
1460 // Save parameter registers
1461 movq %a1, 0+REG_AREA(%rsp)
1462 movq %a2, 8+REG_AREA(%rsp)
1463 movq %a3, 16+REG_AREA(%rsp)
1464 movq %a4, 24+REG_AREA(%rsp)
1465 movq %a5, 32+REG_AREA(%rsp)
1466 movq %a6, 40+REG_AREA(%rsp)
1467
1468 // Save side parameter registers
8972963c 1469 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
b3962a83
A
1470 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1471 // 16+LINK_AREA is return address
1472
1473 // Save xmm registers
1474 movdqa %xmm0, 0+FP_AREA(%rsp)
1475 movdqa %xmm1, 16+FP_AREA(%rsp)
1476 movdqa %xmm2, 32+FP_AREA(%rsp)
1477 movdqa %xmm3, 48+FP_AREA(%rsp)
1478 movdqa %xmm4, 64+FP_AREA(%rsp)
1479 movdqa %xmm5, 80+FP_AREA(%rsp)
1480 movdqa %xmm6, 96+FP_AREA(%rsp)
1481 movdqa %xmm7, 112+FP_AREA(%rsp)
1482
1483 // Call [receiver forward:sel :margs]
1484 movq %a2, %a1 // receiver
1485 movq _FwdSel(%rip), %a2 // forward::
1486 // %a3 is already the selector
1487 movq %rsp, %a4 // marg_list
1488
1489 call _objc_msgSend // forward:: is NOT struct-return
1490
1491 // Retrieve return address from linkage area
1492 movq 16+LINK_AREA(%rsp), %r11
1493 // Pop stack frame
8972963c 1494 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
b3962a83
A
1495 // Put return address back
1496 movq %r11, (%rsp)
1497 ret
1498
1499LMsgForwardStretError:
cd5f04f5
A
1500 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1501 // %a4 is already the forwarded selector
b3962a83 1502 movq %a2, %a1 // receiver
cd5f04f5 1503 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s"
b3962a83
A
1504 movq _FwdSel(%rip), %a3 // forward::
1505 jmp ___objc_error // never returns
1506
1507 END_ENTRY __objc_msgForward_stret
1508
1509
8972963c
A
1510 ENTRY _objc_msgSend_debug
1511 jmp _objc_msgSend
1512 END_ENTRY _objc_msgSend_debug
1513
1514 ENTRY _objc_msgSendSuper2_debug
1515 jmp _objc_msgSendSuper2
1516 END_ENTRY _objc_msgSendSuper2_debug
1517
1518 ENTRY _objc_msgSend_stret_debug
1519 jmp _objc_msgSend_stret
1520 END_ENTRY _objc_msgSend_stret_debug
1521
1522 ENTRY _objc_msgSendSuper2_stret_debug
1523 jmp _objc_msgSendSuper2_stret
1524 END_ENTRY _objc_msgSendSuper2_stret_debug
1525
1526 ENTRY _objc_msgSend_fpret_debug
1527 jmp _objc_msgSend_fpret
1528 END_ENTRY _objc_msgSend_fpret_debug
1529
1530 ENTRY _objc_msgSend_fp2ret_debug
1531 jmp _objc_msgSend_fp2ret
1532 END_ENTRY _objc_msgSend_fp2ret_debug
1533
1534
1535 ENTRY _objc_msgSend_noarg
1536 jmp _objc_msgSend
1537 END_ENTRY _objc_msgSend_noarg
1538
1539
b3962a83
A
1540 ENTRY _method_invoke
1541
1542 movq method_imp(%a2), %r11
1543 movq method_name(%a2), %a2
1544 jmp *%r11
1545
1546 END_ENTRY _method_invoke
1547
1548
1549 ENTRY _method_invoke_stret
1550
1551 movq method_imp(%a3), %r11
1552 movq method_name(%a3), %a3
1553 jmp *%r11
1554
1555 END_ENTRY _method_invoke_stret
7af964d1 1556
8972963c
A
1557
1558 STATIC_ENTRY __objc_ignored_method
1559
1560 movq %a1, %rax
1561 ret
1562
1563 END_ENTRY __objc_ignored_method
1564
7af964d1
A
1565
1566/********************************************************************
1567 *
1568 * id vtable_prototype(id self, message_ref *msg, ...)
1569 *
1570 * This code is copied to create vtable trampolines.
1571 * The instruction following LvtableIndex is modified to
1572 * insert each vtable index.
8972963c
A
1573 * The instructions following LvtableTagTable are modified to
1574 * load the tagged isa table.
7af964d1
A
1575 *
1576 * This code is placed in its own section to prevent dtrace from
1577 * instrumenting it. Otherwise, dtrace would insert an INT3, the
1578 * code would be copied, and the copied INT3 would cause a crash.
8972963c
A
1579 *
1580 * ABI WARNING ABI WARNING ABI WARNING ABI WARNING ABI WARNING
1581 * vtable_prototype steals %rax and does not clear %rdx on return
1582 * in order to precisely pack instructions into ifetch and cache lines
1583 * This means vtable dispatch must never be used for vararg calls
1584 * or very large return values.
1585 * ABI WARNING ABI WARNING ABI WARNING ABI WARNING ABI WARNING
7af964d1
A
1586 *
1587 ********************************************************************/
1588
1589.macro VTABLE /* byte-offset, name */
1590
8972963c 1591 .align 6
7af964d1
A
1592 .private_extern _$1
1593_$1:
1594 test %a1, %a1
8972963c
A
1595 je LvtableReturnZero_$1 // nil check
1596 testl $$1, %a1d
1597 jne LvtableTaggedPointer_$1 // tag check
1598
1599 movq (%a1), %rax // load isa (see ABI WARNING)
1600 movq 24(%rax), %rax // load vtable
1601 movq 8(%a2), %a2 // load _cmd
7af964d1 1602LvtableIndex_$1:
8972963c
A
1603 jmpq * $0 (%rax) // load imp (DO NOT CHANGE)
1604
7af964d1
A
1605LvtableReturnZero_$1:
1606 // integer registers only; not used for fpret / stret / etc
8972963c
A
1607 xorl %eax, %eax
1608 // xorl %edx, %edx (see ABI WARNING)
7af964d1 1609 ret
8972963c 1610
7af964d1 1611 nop
8972963c
A
1612LvtableTaggedPointer_$1:
1613 // extract isa (bits 1-2-3) from %a1, bit 0 is kept around for the heck of it
1614 movl %a1d, %eax
1615 andl $$0xF, %eax
1616LvtableTagTable_$1:
1617.if $0 == 0x7fff
1618 movq $$0x1122334455667788, %r10 // vtable_prototype (DO NOT CHANGE)
1619.else
1620 leaq __objc_tagged_isa_table(%rip), %r10
1621.endif
1622LvtableTagTableEnd_$1:
1623 movq (%r10, %rax, 8), %r10 // load isa from table (see ABI WARNING
1624 movq 24(%r10), %rax // load vtable
1625 movq 8(%a2), %a2 // load _cmd
1626LvtableIndex2_$1:
1627 jmpq * $0 (%rax) // load imp (DO NOT CHANGE)
1628
1629LvtableEnd_$1:
7af964d1
A
1630
1631.endmacro
1632
1633 .section __TEXT,__objc_codegen,regular
1634 VTABLE 0x7fff, vtable_prototype
1635
1636 .data
1637 .align 2
1638 .private_extern _vtable_prototype_size
1639_vtable_prototype_size:
1640 .long LvtableEnd_vtable_prototype - _vtable_prototype
1641
1642 .private_extern _vtable_prototype_index_offset
1643_vtable_prototype_index_offset:
1644 .long LvtableIndex_vtable_prototype - _vtable_prototype
1645
8972963c
A
1646 .private_extern _vtable_prototype_index2_offset
1647_vtable_prototype_index2_offset:
1648 .long LvtableIndex2_vtable_prototype - _vtable_prototype
1649
1650 .private_extern _vtable_prototype_tagtable_offset
1651_vtable_prototype_tagtable_offset:
1652 .long LvtableTagTable_vtable_prototype - _vtable_prototype
1653
1654 .private_extern _vtable_prototype_tagtable_size
1655_vtable_prototype_tagtable_size:
1656 .long LvtableTagTableEnd_vtable_prototype - LvtableTagTable_vtable_prototype
7af964d1
A
1657
1658/********************************************************************
1659 *
1660 * id vtable_ignored(id self, message_ref *msg, ...)
1661 *
1662 * Vtable trampoline for GC-ignored selectors. Immediately returns self.
1663 *
1664 ********************************************************************/
1665
8972963c 1666 STATIC_ENTRY _vtable_ignored
7af964d1
A
1667 movq %a1, %rax
1668 ret
1669
1670
1671/********************************************************************
1672 *
1673 * id objc_msgSend_vtable<n>(id self, message_ref *msg, ...)
1674 *
1675 * Built-in expansions of vtable_prototype for the default vtable.
1676 *
1677 ********************************************************************/
1678
1679 .text
1680
1681 .align 4
1682 .private_extern _defaultVtableTrampolineDescriptors
1683_defaultVtableTrampolineDescriptors:
1684 // objc_trampoline_header
1685 .short 16 // headerSize
1686 .short 8 // descSize
1687 .long 16 // descCount
1688 .quad 0 // next
1689
1690 // objc_trampoline_descriptor[16]
1691.macro TDESC /* n */
1692L_tdesc$0:
1693 .long _objc_msgSend_vtable$0 - L_tdesc$0
1694 .long (1<<0) + (1<<2) // MESSAGE and VTABLE
1695.endmacro
1696
1697 TDESC 0
1698 TDESC 1
1699 TDESC 2
1700 TDESC 3
1701 TDESC 4
1702 TDESC 5
1703 TDESC 6
1704 TDESC 7
1705 TDESC 8
1706 TDESC 9
1707 TDESC 10
1708 TDESC 11
1709 TDESC 12
1710 TDESC 13
1711 TDESC 14
1712 TDESC 15
1713
1714 // trampoline code
1715 .align 4
1716 VTABLE 0*8, objc_msgSend_vtable0
1717 VTABLE 1*8, objc_msgSend_vtable1
1718 VTABLE 2*8, objc_msgSend_vtable2
1719 VTABLE 3*8, objc_msgSend_vtable3
1720 VTABLE 4*8, objc_msgSend_vtable4
1721 VTABLE 5*8, objc_msgSend_vtable5
1722 VTABLE 6*8, objc_msgSend_vtable6
1723 VTABLE 7*8, objc_msgSend_vtable7
1724 VTABLE 8*8, objc_msgSend_vtable8
1725 VTABLE 9*8, objc_msgSend_vtable9
1726 VTABLE 10*8, objc_msgSend_vtable10
1727 VTABLE 11*8, objc_msgSend_vtable11
1728 VTABLE 12*8, objc_msgSend_vtable12
1729 VTABLE 13*8, objc_msgSend_vtable13
1730 VTABLE 14*8, objc_msgSend_vtable14
1731 VTABLE 15*8, objc_msgSend_vtable15
1732
1733#endif