]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-x86_64.s
objc4-493.11.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
292 // RA is at 0(%rsp) aka -8(CFA)
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
312 .quad LF0$0-. # FDE address start
313 .quad LLEN$0 # FDE address range
314 .byte 0x0 # uleb128 0x0; Augmentation size
315
316 // DW_START: set by CIE
317
318.if $2 == 1
319
320 // pushq %rbp
321 .byte DW_CFA_advance_loc4
322 .long LFLEN0$0+1
323 .byte DW_CFA_def_cfa_offset
324 .byte 16
325 .byte DW_CFA_offset | DW_rbp
326 .byte -16/-8
327 // movq %rsp, %rbp
328 .byte DW_CFA_advance_loc4
329 .long 3
330 .byte DW_CFA_def_cfa_register
331 .byte DW_rbp
332
333.endif
334
335 .align 3
336LEFDE$0:
337 .text
338
339.endmacro
340
341
342.macro DW_START
343LF0$0:
344.endmacro
345
346.macro DW_FRAME
347LF1$0:
348 .set LFLEN0$0, LF1$0-LF0$0
349.endmacro
350
351.macro DW_END
352 .set LLEN$0, .-LF0$0
353 EMIT_FDE $0, LLEN$0, 1
354.endmacro
355
356.macro DW_END2
357 .set LLEN$0, .-LF0$0
358 EMIT_FDE $0, LLEN$0, 2
b3962a83
A
359.endmacro
360
361
362/////////////////////////////////////////////////////////////////////
363//
8972963c 364// SaveRegisters caller
b3962a83
A
365//
366// Pushes a stack frame and saves all registers that might contain
367// parameter values.
368//
8972963c
A
369// On entry: %0 = caller's symbol name for DWARF
370// stack = ret
b3962a83
A
371//
372// On exit:
8972963c 373// %rsp is 16-byte aligned
b3962a83
A
374//
375/////////////////////////////////////////////////////////////////////
7af964d1 376
b3962a83 377.macro SaveRegisters
8972963c
A
378 DW_FRAME $0
379 enter $$0x80+8, $$0 // +8 for alignment
380 movdqa %xmm0, -0x80(%rbp)
381 push %rax // might be xmm parameter count
382 movdqa %xmm1, -0x70(%rbp)
383 push %a1
384 movdqa %xmm2, -0x60(%rbp)
385 push %a2
386 movdqa %xmm3, -0x50(%rbp)
387 push %a3
388 movdqa %xmm4, -0x40(%rbp)
389 push %a4
390 movdqa %xmm5, -0x30(%rbp)
391 push %a5
392 movdqa %xmm6, -0x20(%rbp)
393 push %a6
394 movdqa %xmm7, -0x10(%rbp)
b3962a83
A
395.endmacro
396
397/////////////////////////////////////////////////////////////////////
398//
399// RestoreRegisters
400//
401// Pops a stack frame pushed by SaveRegisters
402//
8972963c
A
403// On entry: $0 = caller's symbol name for DWARF
404// %rbp unchanged since SaveRegisters
b3962a83
A
405//
406// On exit:
8972963c 407// stack = ret
b3962a83
A
408//
409/////////////////////////////////////////////////////////////////////
410
411.macro RestoreRegisters
8972963c
A
412 movdqa -0x80(%rbp), %xmm0
413 pop %a6
414 movdqa -0x70(%rbp), %xmm1
415 pop %a5
416 movdqa -0x60(%rbp), %xmm2
417 pop %a4
418 movdqa -0x50(%rbp), %xmm3
419 pop %a3
420 movdqa -0x40(%rbp), %xmm4
421 pop %a2
422 movdqa -0x30(%rbp), %xmm5
423 pop %a1
424 movdqa -0x20(%rbp), %xmm6
425 pop %rax
426 movdqa -0x10(%rbp), %xmm7
427 leave
b3962a83
A
428.endmacro
429
430
431/////////////////////////////////////////////////////////////////////
432//
433//
8972963c 434// CacheLookup return-type
b3962a83
A
435//
436// Locate the implementation for a selector in a class method cache.
437//
438// Takes:
8972963c
A
439// $0 = NORMAL, FPRET, FP2RET, STRET
440// a2 or a3 (STRET) = selector
b3962a83 441// %r11 = class whose cache is to be searched
b3962a83 442//
8972963c
A
443// On exit: (found) method in %r11, stack unchanged, eq/ne set for forwarding
444// (not found) jumps to LCacheMiss, %rax on stack
445//
b3962a83
A
446/////////////////////////////////////////////////////////////////////
447
b3962a83
A
448.macro CacheLookup
449
8972963c
A
450 push %rax
451 movq cache(%r11), %r10 // cache = class->cache
452.if $0 != STRET
453 mov %a2d, %eax // index = sel
454.else
455 mov %a3d, %eax // index = sel
456.endif
b3962a83
A
457
458// search the receiver's cache
459// r11 = method (soon)
8972963c
A
460// eax = index
461// r10 = cache
462// a2 or a3 = sel
4631:
464 andl mask(%r10), %eax // index &= mask
465 movq buckets(%r10, %rax, 8), %r11 // method = cache->buckets[index]
466 incl %eax // index++
b3962a83 467 testq %r11, %r11 // if (method == NULL)
8972963c
A
468 je LCacheMiss_f // goto cacheMissLabel
469.if $0 != STRET
470 cmpq method_name(%r11), %a2 // if (method_name != sel)
471.else
472 cmpq method_name(%r11), %a3 // if (method_name != sel)
473.endif
474 jne 1b // goto loop
b3962a83
A
475
476 // cache hit, r11 = method triplet
b3962a83 477 // restore saved registers
8972963c
A
478 pop %rax
479
480.if $0 != STRET
481 // eq (non-stret) flag already set above
482.else
483 // set ne (stret) for forwarding; r11 != 0
484 test %r11, %r11
485.endif
b3962a83 486
b3962a83
A
487.endmacro
488
489
490/////////////////////////////////////////////////////////////////////
491//
7af964d1 492// MethodTableLookup classRegister, selectorRegister, fn
b3962a83 493//
8972963c
A
494// Takes: $0 = class to search (a1 or a2 or r10 ONLY)
495// $1 = selector to search for (a2 or a3 ONLY)
496// $2 = caller's symbol name for DWARF
497// r11 = class to search
b3962a83 498//
8972963c 499// Stack: ret, rax (pushed by CacheLookup)
b3962a83 500//
8972963c 501// On exit: pops registers pushed by CacheLookup
b3962a83
A
502// imp in %r11
503//
504/////////////////////////////////////////////////////////////////////
505.macro MethodTableLookup
8972963c
A
506
507 pop %rax // saved by CacheLookup
508 SaveRegisters $2
b3962a83 509
8972963c 510 // _class_lookupMethodAndLoadCache3(receiver, selector, class)
b3962a83 511
b3962a83
A
512 movq $0, %a1
513 movq $1, %a2
8972963c
A
514 movq %r11, %a3
515 call __class_lookupMethodAndLoadCache3
b3962a83
A
516
517 // IMP is now in %rax
518 movq %rax, %r11
519
7af964d1 520 RestoreRegisters $2
b3962a83
A
521
522.endmacro
523
8972963c
A
524/////////////////////////////////////////////////////////////////////
525//
526// GetIsa return-type
527// GetIsaFast return-type
528// GetIsaSupport return-type
529//
530// Sets r11 = obj->isa. Consults the tagged isa table if necessary.
531//
532// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
533// a1 or a2 (STRET) = receiver
534//
535// On exit: r11 = receiver->isa
536// r10 is clobbered
537//
538/////////////////////////////////////////////////////////////////////
539
540.macro GetIsa
541
542.if $0 != STRET
543 testb $$1, %a1b
544 jnz 1f
545 movq (%a1), %r11
546 jmp 2f
5471: movl %a1d, %r10d
548.else
549 testb $$1, %a2b
550 jnz 1f
551 movq (%a2), %r11
552 jmp 2f
5531: movl %a2d, %r10d
554.endif
555 andl $$0xF, %r10d
556 leaq __objc_tagged_isa_table(%rip), %r11
557 movq (%r11, %r10, 8), %r11 // read isa from table
5582:
559.endmacro
560
561.macro GetIsaFast
562.if $0 != STRET
563 testb $$1, %a1b
564 .byte 0x2e // harmless branch hint prefix to align IFETCH blocks
565 jnz LGetIsaSlow_f
566 movq (%a1), %r11
567.else
568 testb $$1, %a2b
569 .byte 0x2e // harmless branch hint prefix to align IFETCH blocks
570 jnz LGetIsaSlow_f
571 movq (%a2), %r11
572.endif
573LGetIsaDone:
574.endmacro
575
576.macro GetIsaSupport
577LGetIsaSlow:
578 leaq __objc_tagged_isa_table(%rip), %r11
579.if $0 != STRET
580 movl %a1d, %r10d
581.else
582 movl %a2d, %r10d
583.endif
584 andl $$0xF, %r10d
585 movq (%r11, %r10, 8), %r11 // read isa from table
586 jmp LGetIsaDone_b
587.endmacro
588
589/////////////////////////////////////////////////////////////////////
590//
591// NilTest return-type
592//
593// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
594// %a1 or %a2 (STRET) = receiver
595//
596// On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
597//
598// NilTestSupport return-type
599//
600// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
601// %a1 or %a2 (STRET) = receiver
602//
603// On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero.
604//
605/////////////////////////////////////////////////////////////////////
606
607.macro NilTest
608.if $0 != STRET
609 testq %a1, %a1
610.else
611 testq %a2, %a2
612.endif
613 jz LNilTestSlow_f
614LNilTestDone:
615.endmacro
616
617.macro NilTestSupport
618 .align 3
619LNilTestSlow:
620.if $0 != STRET
621 movq __objc_nilReceiver(%rip), %a1
622 testq %a1, %a1 // if (receiver != nil)
623.else
624 movq __objc_nilReceiver(%rip), %a2
625 testq %a2, %a2 // if (receiver != nil)
626.endif
627 jne LNilTestDone_b // send to new receiver
628
629.if $0 == FPRET
630 fldz
631.elseif $0 == FP2RET
632 fldz
633 fldz
634.endif
635.if $0 != STRET
636 xorl %eax, %eax
637 xorl %edx, %edx
638 xorps %xmm0, %xmm0
639 xorps %xmm1, %xmm1
640.endif
641 ret
642.endmacro
643
b3962a83
A
644
645/********************************************************************
7af964d1 646 * Method _cache_getMethod(Class cls, SEL sel, IMP msgForward_internal_imp)
b3962a83
A
647 *
648 * On entry: a1 = class whose cache is to be searched
649 * a2 = selector to search for
7af964d1 650 * a3 = _objc_msgForward_internal IMP
b3962a83
A
651 *
652 * If found, returns method triplet pointer.
653 * If not found, returns NULL.
654 *
655 * NOTE: _cache_getMethod never returns any cache entry whose implementation
7af964d1
A
656 * is _objc_msgForward_internal. It returns 1 instead. This prevents thread-
657 * thread-safety and memory management bugs in _class_lookupMethodAndLoadCache.
b3962a83
A
658 * See _class_lookupMethodAndLoadCache for details.
659 *
7af964d1
A
660 * _objc_msgForward_internal is passed as a parameter because it's more
661 * efficient to do the (PIC) lookup once in the caller than repeatedly here.
b3962a83 662 ********************************************************************/
8972963c
A
663
664 STATIC_ENTRY __cache_getMethod
7af964d1 665 DW_START __cache_getMethod
b3962a83
A
666
667// do lookup
668 movq %a1, %r11 // move class to r11 for CacheLookup
8972963c 669 CacheLookup NORMAL
b3962a83
A
670
671// cache hit, method triplet in %r11
8972963c
A
672 cmpq method_imp(%r11), %a3 // if (imp==_objc_msgForward_internal)
673 je 1f // return (Method)1
b3962a83
A
674 movq %r11, %rax // return method triplet address
675 ret
8972963c 6761: movl $1, %eax
7af964d1 677 ret
b3962a83 678
8972963c 679LCacheMiss:
b3962a83 680// cache miss, return nil
8972963c
A
681 pop %rax // pushed by CacheLookup
682 xorl %eax, %eax
b3962a83
A
683 ret
684
685LGetMethodExit:
7af964d1
A
686 DW_END2 __cache_getMethod
687 END_ENTRY __cache_getMethod
b3962a83
A
688
689
690/********************************************************************
691 * IMP _cache_getImp(Class cls, SEL sel)
692 *
693 * On entry: a1 = class whose cache is to be searched
694 * a2 = selector to search for
695 *
696 * If found, returns method implementation.
697 * If not found, returns NULL.
698 ********************************************************************/
699
8972963c 700 STATIC_ENTRY __cache_getImp
7af964d1 701 DW_START __cache_getImp
b3962a83
A
702
703// do lookup
704 movq %a1, %r11 // move class to r11 for CacheLookup
8972963c 705 CacheLookup NORMAL
b3962a83
A
706
707// cache hit, method triplet in %r11
708 movq method_imp(%r11), %rax // return method imp address
709 ret
710
8972963c 711LCacheMiss:
b3962a83 712// cache miss, return nil
8972963c
A
713 pop %rax // pushed by CacheLookup
714 xorl %eax, %eax
b3962a83
A
715 ret
716
717LGetImpExit:
7af964d1
A
718 DW_END2 __cache_getImp
719 END_ENTRY __cache_getImp
b3962a83
A
720
721
722/********************************************************************
723 *
724 * id objc_msgSend(id self, SEL _cmd,...);
725 *
726 ********************************************************************/
727
8972963c
A
728 .data
729 .align 3
730 .private_extern __objc_tagged_isa_table
731__objc_tagged_isa_table:
732 .fill 16, 8, 0
733
b3962a83 734 ENTRY _objc_msgSend
7af964d1 735 DW_START _objc_msgSend
b3962a83 736
8972963c 737 NilTest NORMAL
b3962a83 738
8972963c
A
739 GetIsaFast NORMAL // r11 = self->isa
740 CacheLookup NORMAL // r11 = method, eq set (nonstret fwd)
741 jmp *method_imp(%r11) // goto *imp
b3962a83 742
8972963c 743 NilTestSupport NORMAL
b3962a83 744
8972963c 745 GetIsaSupport NORMAL
b3962a83 746
8972963c
A
747// cache miss: go search the method lists
748LCacheMiss:
749 GetIsa NORMAL // r11 = self->isa
750 MethodTableLookup %a1, %a2, _objc_msgSend // r11 = IMP
751 cmp %r11, %r11 // set eq (nonstret) for forwarding
752 jmp *%r11 // goto *imp
b3962a83 753
7af964d1 754 DW_END _objc_msgSend
b3962a83
A
755 END_ENTRY _objc_msgSend
756
757#if __OBJC2__
758 ENTRY _objc_msgSend_fixup
7af964d1 759 DW_START _objc_msgSend_fixup
b3962a83 760
8972963c 761 NilTest NORMAL
7af964d1 762
8972963c
A
763 SaveRegisters _objc_msgSend_fixup
764
7af964d1 765 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
766 movq 8(%a2), %a6 // selector
767 GetIsa NORMAL // r11 = isa = *receiver
768 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
769 movq mask(%a5), %a4 // *cache
770
b3962a83
A
771 // a1 = receiver
772 // a2 = address of message ref
773 movq %a2, %a3
8972963c 774 xorl %a2d, %a2d
b3962a83
A
775 // __objc_fixupMessageRef(receiver, 0, ref)
776 call __objc_fixupMessageRef
777 movq %rax, %r11
7af964d1
A
778
779 RestoreRegisters _objc_msgSend_fixup
b3962a83
A
780
781 // imp is in r11
782 // Load _cmd from the message_ref
783 movq 8(%a2), %a2
7af964d1 784 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
785 jmp *%r11
786
8972963c 787 NilTestSupport NORMAL
b3962a83 788
7af964d1
A
789 DW_END _objc_msgSend_fixup
790 END_ENTRY _objc_msgSend_fixup
b3962a83
A
791
792
8972963c 793 STATIC_ENTRY _objc_msgSend_fixedup
b3962a83
A
794 // Load _cmd from the message_ref
795 movq 8(%a2), %a2
796 jmp _objc_msgSend
797 END_ENTRY _objc_msgSend_fixedup
798#endif
799
800
801/********************************************************************
802 *
803 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
804 *
805 * struct objc_super {
806 * id receiver;
807 * Class class;
808 * };
809 ********************************************************************/
810
811 ENTRY _objc_msgSendSuper
7af964d1 812 DW_START _objc_msgSendSuper
b3962a83 813
b3962a83
A
814// search the cache (objc_super in %a1)
815 movq class(%a1), %r11 // class = objc_super->class
8972963c 816 CacheLookup NORMAL // r11 = method, eq set (nonstret fwd)
b3962a83 817 movq receiver(%a1), %a1 // load real receiver
8972963c 818 jmp *method_imp(%r11) // goto *imp
b3962a83
A
819
820// cache miss: go search the method lists
8972963c
A
821LCacheMiss:
822 movq receiver(%a1), %r10
823 movq class(%a1), %r11
824 MethodTableLookup %r10, %a2, _objc_msgSendSuper // r11 = IMP
b3962a83 825 movq receiver(%a1), %a1 // load real receiver
8972963c 826 cmp %r11, %r11 // set eq (nonstret) for forwarding
b3962a83 827 jmp *%r11 // goto *imp
b3962a83 828
7af964d1 829 DW_END _objc_msgSendSuper
b3962a83
A
830 END_ENTRY _objc_msgSendSuper
831
8972963c
A
832
833/********************************************************************
834 * id objc_msgSendSuper2
835 ********************************************************************/
836
b3962a83
A
837#if __OBJC2__
838 ENTRY _objc_msgSendSuper2_fixup
7af964d1 839 DW_START _objc_msgSendSuper2_fixup
b3962a83 840
8972963c 841 SaveRegisters _objc_msgSendSuper2_fixup
b3962a83
A
842 // a1 = address of objc_super2
843 // a2 = address of message ref
844 movq %a2, %a3
845 movq %a1, %a2
846 movq receiver(%a1), %a1
847 // __objc_fixupMessageRef(receiver, objc_super, ref)
848 call __objc_fixupMessageRef
849 movq %rax, %r11
7af964d1 850 RestoreRegisters _objc_msgSendSuper2_fixup
b3962a83
A
851
852 // imp is in r11
853 // Load _cmd from the message_ref
854 movq 8(%a2), %a2
855 // Load receiver from objc_super2
856 movq receiver(%a1), %a1
7af964d1 857 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
858 jmp *%r11
859
7af964d1
A
860 DW_END _objc_msgSendSuper2_fixup
861 END_ENTRY _objc_msgSendSuper2_fixup
b3962a83
A
862
863
8972963c 864 STATIC_ENTRY _objc_msgSendSuper2_fixedup
b3962a83 865 movq 8(%a2), %a2 // load _cmd from message_ref
8972963c 866 jmp _objc_msgSendSuper2
b3962a83 867 END_ENTRY _objc_msgSendSuper2_fixedup
7af964d1
A
868
869
870 ENTRY _objc_msgSendSuper2
8972963c 871 DW_START _objc_msgSendSuper2
7af964d1 872 // objc_super->class is superclass of class to search
8972963c
A
873
874// search the cache (objc_super in %a1)
7af964d1 875 movq class(%a1), %r11 // cls = objc_super->class
8972963c
A
876 movq 8(%r11), %r11 // cls = class->superclass
877 CacheLookup NORMAL // r11 = method, eq set (nonstret fwd)
878 movq receiver(%a1), %a1 // load real receiver
879 jmp *method_imp(%r11) // goto *imp
880
881// cache miss: go search the method lists
882LCacheMiss:
883 movq receiver(%a1), %r10
884 movq class(%a1), %r11
885 movq 8(%r11), %r11
886 MethodTableLookup %r10, %a2, _objc_msgSendSuper2 // r11 = IMP
887 movq receiver(%a1), %a1 // load real receiver
888 cmp %r11, %r11 // set eq (nonstret) for forwarding
889 jmp *%r11 // goto *imp
890
891 DW_END _objc_msgSendSuper2
892 END_ENTRY _objc_msgSendSuper2
b3962a83
A
893#endif
894
895
896/********************************************************************
897 *
898 * double objc_msgSend_fpret(id self, SEL _cmd,...);
899 * Used for `long double` return only. `float` and `double` use objc_msgSend.
900 *
901 ********************************************************************/
902
903 ENTRY _objc_msgSend_fpret
7af964d1 904 DW_START _objc_msgSend_fpret
b3962a83 905
8972963c 906 NilTest FPRET
b3962a83 907
8972963c
A
908 GetIsaFast FPRET // r11 = self->isa
909 CacheLookup FPRET // r11 = method, eq set (nonstret fwd)
910 jmp *method_imp(%r11) // goto *imp
b3962a83 911
8972963c 912 NilTestSupport FPRET
b3962a83 913
8972963c 914 GetIsaSupport FPRET
b3962a83 915
8972963c
A
916// cache miss: go search the method lists
917LCacheMiss:
918 GetIsa FPRET // r11 = self->isa
919 MethodTableLookup %a1, %a2, _objc_msgSend_fpret // r11 = IMP
920 cmp %r11, %r11 // set eq (nonstret) for forwarding
921 jmp *%r11 // goto *imp
b3962a83 922
7af964d1 923 DW_END _objc_msgSend_fpret
b3962a83
A
924 END_ENTRY _objc_msgSend_fpret
925
926#if __OBJC2__
927 ENTRY _objc_msgSend_fpret_fixup
7af964d1 928 DW_START _objc_msgSend_fpret_fixup
b3962a83 929
8972963c 930 NilTest FPRET
b3962a83 931
8972963c 932 SaveRegisters _objc_msgSend_fpret_fixup
7af964d1
A
933
934 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
935 movq 8(%a2), %a6 // selector
936 GetIsa FPRET // r11 = isa = *receiver
937 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
938 movq mask(%a5), %a4 // *cache
939
b3962a83
A
940 // a1 = receiver
941 // a2 = address of message ref
942 movq %a2, %a3
8972963c 943 xorl %a2d, %a2d
b3962a83
A
944 // __objc_fixupMessageRef(receiver, 0, ref)
945 call __objc_fixupMessageRef
946 movq %rax, %r11
7af964d1
A
947
948 RestoreRegisters _objc_msgSend_fpret_fixup
b3962a83
A
949
950 // imp is in r11
951 // Load _cmd from the message_ref
952 movq 8(%a2), %a2
7af964d1 953 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
954 jmp *%r11
955
8972963c 956 NilTestSupport FPRET
b3962a83 957
7af964d1
A
958 DW_END _objc_msgSend_fpret_fixup
959 END_ENTRY _objc_msgSend_fpret_fixup
b3962a83
A
960
961
8972963c 962 STATIC_ENTRY _objc_msgSend_fpret_fixedup
b3962a83
A
963 // Load _cmd from the message_ref
964 movq 8(%a2), %a2
965 jmp _objc_msgSend_fpret
966 END_ENTRY _objc_msgSend_fpret_fixedup
967#endif
968
969
970/********************************************************************
971 *
972 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
973 * Used for `complex long double` return only.
974 *
975 ********************************************************************/
976
977 ENTRY _objc_msgSend_fp2ret
7af964d1 978 DW_START _objc_msgSend_fp2ret
b3962a83 979
8972963c 980 NilTest FP2RET
b3962a83 981
8972963c
A
982 GetIsaFast FP2RET // r11 = self->isa
983 CacheLookup FP2RET // r11 = method, eq set (nonstret fwd)
984 jmp *method_imp(%r11) // goto *imp
b3962a83 985
8972963c
A
986 NilTestSupport FP2RET
987
988 GetIsaSupport FP2RET
989
b3962a83 990// cache miss: go search the method lists
8972963c
A
991LCacheMiss:
992 GetIsa FP2RET // r11 = self->isa
993 MethodTableLookup %a1, %a2, _objc_msgSend_fp2ret // r11 = IMP
994 cmp %r11, %r11 // set eq (nonstret) for forwarding
b3962a83
A
995 jmp *%r11 // goto *imp
996
7af964d1 997 DW_END _objc_msgSend_fp2ret
b3962a83
A
998 END_ENTRY _objc_msgSend_fp2ret
999
1000#if __OBJC2__
1001 ENTRY _objc_msgSend_fp2ret_fixup
7af964d1 1002 DW_START _objc_msgSend_fp2ret_fixup
b3962a83 1003
8972963c 1004 NilTest FP2RET
b3962a83 1005
8972963c 1006 SaveRegisters _objc_msgSend_fp2ret_fixup
7af964d1
A
1007
1008 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
1009 movq 8(%a2), %a6 // selector
1010 GetIsa FP2RET // r11 = isa = *receiver
1011 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
1012 movq mask(%a5), %a4 // *cache
1013
b3962a83
A
1014 // a1 = receiver
1015 // a2 = address of message ref
1016 movq %a2, %a3
8972963c 1017 xorl %a2d, %a2d
b3962a83
A
1018 // __objc_fixupMessageRef(receiver, 0, ref)
1019 call __objc_fixupMessageRef
1020 movq %rax, %r11
7af964d1
A
1021
1022 RestoreRegisters _objc_msgSend_fp2ret_fixup
b3962a83
A
1023
1024 // imp is in r11
1025 // Load _cmd from the message_ref
1026 movq 8(%a2), %a2
7af964d1 1027 cmp %r11, %r11 // set nonstret (eq) for forwarding
b3962a83
A
1028 jmp *%r11
1029
8972963c 1030 NilTestSupport FP2RET
b3962a83 1031
7af964d1
A
1032 DW_END _objc_msgSend_fp2ret_fixup
1033 END_ENTRY _objc_msgSend_fp2ret_fixup
b3962a83
A
1034
1035
8972963c 1036 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
b3962a83
A
1037 // Load _cmd from the message_ref
1038 movq 8(%a2), %a2
1039 jmp _objc_msgSend_fp2ret
1040 END_ENTRY _objc_msgSend_fp2ret_fixedup
1041#endif
1042
1043
1044/********************************************************************
1045 *
1046 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
1047 *
1048 * objc_msgSend_stret is the struct-return form of msgSend.
1049 * The ABI calls for %a1 to be used as the address of the structure
1050 * being returned, with the parameters in the succeeding locations.
1051 *
1052 * On entry: %a1 is the address where the structure is returned,
1053 * %a2 is the message receiver,
1054 * %a3 is the selector
1055 ********************************************************************/
1056
1057 ENTRY _objc_msgSend_stret
7af964d1 1058 DW_START _objc_msgSend_stret
b3962a83 1059
8972963c
A
1060 NilTest STRET
1061
1062 GetIsaFast STRET // r11 = self->isa
1063 CacheLookup STRET // r11 = method, ne set (stret fwd)
1064 jmp *method_imp(%r11) // goto *imp
1065
1066 NilTestSupport STRET
1067
1068 GetIsaSupport STRET
b3962a83
A
1069
1070// cache miss: go search the method lists
8972963c
A
1071LCacheMiss:
1072 GetIsa STRET // r11 = self->isa
1073 MethodTableLookup %a2, %a3, _objc_msgSend_stret // r11 = IMP
1074 test %r11, %r11 // set ne (stret) for forward; r11!=0
7af964d1 1075 jmp *%r11 // goto *imp
b3962a83 1076
7af964d1 1077 DW_END _objc_msgSend_stret
b3962a83
A
1078 END_ENTRY _objc_msgSend_stret
1079
1080#if __OBJC2__
1081 ENTRY _objc_msgSend_stret_fixup
7af964d1 1082 DW_START _objc_msgSend_stret_fixup
b3962a83 1083
8972963c 1084 NilTest STRET
b3962a83 1085
8972963c 1086 SaveRegisters _objc_msgSend_stret_fixup
7af964d1
A
1087
1088 // Dereference obj/isa/cache to crash before _objc_fixupMessageRef
8972963c
A
1089 movq 8(%a3), %a6 // selector
1090 GetIsa STRET // r11 = isa = *receiver
1091 movq cache(%r11), %a5 // cache = *isa
7af964d1
A
1092 movq mask(%a5), %a4 // *cache
1093
b3962a83
A
1094 // a2 = receiver
1095 // a3 = address of message ref
1096 movq %a2, %a1
8972963c 1097 xorl %a2d, %a2d
b3962a83
A
1098 // __objc_fixupMessageRef(receiver, 0, ref)
1099 call __objc_fixupMessageRef
1100 movq %rax, %r11
7af964d1
A
1101
1102 RestoreRegisters _objc_msgSend_stret_fixup
b3962a83
A
1103
1104 // imp is in r11
1105 // Load _cmd from the message_ref
1106 movq 8(%a3), %a3
7af964d1
A
1107 test %r11, %r11 // set stret (ne) for forward; r11!=0
1108 jmp *%r11 // goto *imp
b3962a83 1109
8972963c 1110 NilTestSupport STRET
b3962a83 1111
7af964d1
A
1112 DW_END _objc_msgSend_stret_fixup
1113 END_ENTRY _objc_msgSend_stret_fixup
b3962a83
A
1114
1115
8972963c 1116 STATIC_ENTRY _objc_msgSend_stret_fixedup
b3962a83
A
1117 // Load _cmd from the message_ref
1118 movq 8(%a3), %a3
1119 jmp _objc_msgSend_stret
1120 END_ENTRY _objc_msgSend_stret_fixedup
1121#endif
1122
1123
1124/********************************************************************
1125 *
1126 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
1127 *
1128 * struct objc_super {
1129 * id receiver;
1130 * Class class;
1131 * };
1132 *
1133 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
1134 * The ABI calls for (sp+4) to be used as the address of the structure
1135 * being returned, with the parameters in the succeeding registers.
1136 *
1137 * On entry: %a1 is the address where the structure is returned,
1138 * %a2 is the address of the objc_super structure,
1139 * %a3 is the selector
1140 *
1141 ********************************************************************/
1142
1143 ENTRY _objc_msgSendSuper_stret
7af964d1 1144 DW_START _objc_msgSendSuper_stret
b3962a83
A
1145
1146// search the cache (objc_super in %a2)
8972963c
A
1147 movq class(%a2), %r11 // class = objc_super->class
1148 CacheLookup STRET // r11 = method, ne set (stret fwd)
7af964d1 1149 movq receiver(%a2), %a2 // load real receiver
8972963c 1150 jmp *method_imp(%r11) // goto *imp
b3962a83
A
1151
1152// cache miss: go search the method lists
8972963c
A
1153LCacheMiss:
1154 movq receiver(%a2), %r10
1155 movq class(%a2), %r11
1156 MethodTableLookup %r10, %a3, _objc_msgSendSuper_stret // r11 = IMP
7af964d1 1157 movq receiver(%a2), %a2 // load real receiver
8972963c 1158 test %r11, %r11 // set ne (stret) for forward; r11!=0
7af964d1 1159 jmp *%r11 // goto *imp
b3962a83 1160
7af964d1 1161 DW_END _objc_msgSendSuper_stret
b3962a83
A
1162 END_ENTRY _objc_msgSendSuper_stret
1163
8972963c
A
1164
1165/********************************************************************
1166 * id objc_msgSendSuper2_stret
1167 ********************************************************************/
1168
b3962a83
A
1169#if __OBJC2__
1170 ENTRY _objc_msgSendSuper2_stret_fixup
7af964d1 1171 DW_START _objc_msgSendSuper2_stret_fixup
b3962a83 1172
8972963c 1173 SaveRegisters _objc_msgSendSuper2_stret_fixup
b3962a83
A
1174 // a2 = address of objc_super2
1175 // a3 = address of message ref
1176 movq receiver(%a2), %a1
1177 // __objc_fixupMessageRef(receiver, objc_super, ref)
1178 call __objc_fixupMessageRef
1179 movq %rax, %r11
7af964d1 1180 RestoreRegisters _objc_msgSendSuper2_stret_fixup
b3962a83
A
1181
1182 // imp is in r11
1183 // Load _cmd from the message_ref
1184 movq 8(%a3), %a3
1185 // Load receiver from objc_super2
1186 movq receiver(%a2), %a2
7af964d1
A
1187 test %r11, %r11 // set stret (ne) for forward; r11!=0
1188 jmp *%r11 // goto *imp
b3962a83 1189
7af964d1
A
1190 DW_END _objc_msgSendSuper2_stret_fixup
1191 END_ENTRY _objc_msgSendSuper2_stret_fixup
b3962a83
A
1192
1193
8972963c 1194 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
b3962a83 1195 movq 8(%a3), %a3 // load _cmd from message_ref
8972963c 1196 jmp _objc_msgSendSuper2_stret
b3962a83 1197 END_ENTRY _objc_msgSendSuper2_stret_fixedup
7af964d1
A
1198
1199
8972963c
A
1200 ENTRY _objc_msgSendSuper2_stret
1201 DW_START _objc_msgSendSuper2_stret
1202
1203// search the cache (objc_super in %a2)
1204 movq class(%a2), %r11 // class = objc_super->class
1205 movq 8(%r11), %r11 // class = class->super_class
1206 CacheLookup STRET // r11 = method, ne set (stret fwd)
1207 movq receiver(%a2), %a2 // load real receiver
1208 jmp *method_imp(%r11) // goto *imp
1209
1210// cache miss: go search the method lists
1211LCacheMiss:
1212 movq receiver(%a2), %r10
1213 movq class(%a2), %r11
1214 movq 8(%r11), %r11
1215 MethodTableLookup %r10, %a3, _objc_msgSendSuper2_stret // r11 = IMP
1216 movq receiver(%a2), %a2 // load real receiver
1217 test %r11, %r11 // set ne (stret) for forward; r11!=0
1218 jmp *%r11 // goto *imp
1219
1220 DW_END _objc_msgSendSuper2_stret
1221 END_ENTRY _objc_msgSendSuper2_stret
b3962a83
A
1222#endif
1223
1224
1225/********************************************************************
1226 *
1227 * id _objc_msgForward(id self, SEL _cmd,...);
1228 *
1229 ********************************************************************/
1230
1231// _FwdSel is @selector(forward::), set up in map_images().
1232// ALWAYS dereference _FwdSel to get to "forward::" !!
1233 .data
1234 .align 3
1235 .private_extern _FwdSel
1236_FwdSel: .quad 0
1237
1238 .cstring
1239 .align 3
1240LUnkSelStr: .ascii "Does not recognize selector %s\0"
1241
1242 .data
1243 .align 3
1244 .private_extern __objc_forward_handler
1245__objc_forward_handler: .quad 0
1246
1247 .data
1248 .align 3
1249 .private_extern __objc_forward_stret_handler
1250__objc_forward_stret_handler: .quad 0
1251
b3962a83 1252
8972963c 1253 STATIC_ENTRY __objc_msgForward_internal
7af964d1
A
1254 // Method cache version
1255
1256 // THIS IS NOT A CALLABLE C FUNCTION
1257 // Out-of-band condition register is NE for stret, EQ otherwise.
b3962a83 1258
7af964d1
A
1259 jne __objc_msgForward_stret
1260 jmp __objc_msgForward
1261
1262 END_ENTRY __objc_msgForward_internal
1263
1264
1265 ENTRY __objc_msgForward
1266 // Non-stret version
b3962a83
A
1267
1268 // Call user handler, if any
1269 movq __objc_forward_handler(%rip), %r11
1270 testq %r11, %r11 // if (handler == NULL)
1271 je 1f // skip handler
1272 jmp *%r11 // else goto handler
12731:
1274 // No user handler
1275
1276 // Die if forwarding "forward::"
1277 cmpq %a2, _FwdSel(%rip)
1278 je LMsgForwardError
1279
1280 // Record current return address. It will be copied elsewhere in
1281 // the marg_list because this location is needed for register args
1282 movq (%rsp), %r11
1283
1284 // Push stack frame
1285 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1286 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1287
1288 // Save return address in linkage area.
1289 movq %r11, 16+LINK_AREA(%rsp)
1290
1291 // Save parameter registers
1292 movq %a1, 0+REG_AREA(%rsp)
1293 movq %a2, 8+REG_AREA(%rsp)
1294 movq %a3, 16+REG_AREA(%rsp)
1295 movq %a4, 24+REG_AREA(%rsp)
1296 movq %a5, 32+REG_AREA(%rsp)
1297 movq %a6, 40+REG_AREA(%rsp)
1298
1299 // Save side parameter registers
8972963c 1300 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
b3962a83
A
1301 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1302 // 16+LINK_AREA is return address
1303
1304 // Save xmm registers
1305 movdqa %xmm0, 0+FP_AREA(%rsp)
1306 movdqa %xmm1, 16+FP_AREA(%rsp)
1307 movdqa %xmm2, 32+FP_AREA(%rsp)
1308 movdqa %xmm3, 48+FP_AREA(%rsp)
1309 movdqa %xmm4, 64+FP_AREA(%rsp)
1310 movdqa %xmm5, 80+FP_AREA(%rsp)
1311 movdqa %xmm6, 96+FP_AREA(%rsp)
1312 movdqa %xmm7, 112+FP_AREA(%rsp)
1313
1314 // Call [receiver forward:sel :margs]
1315 movq %rsp, %a4 // marg_list
1316 movq %a2, %a3 // sel
1317 movq _FwdSel(%rip), %a2 // forward::
1318 // %a1 is already the receiver
1319
1320 call _objc_msgSend
1321
1322 // Retrieve return address from linkage area
1323 movq 16+LINK_AREA(%rsp), %r11
1324 // Pop stack frame
8972963c 1325 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
b3962a83
A
1326 // Put return address back
1327 movq %r11, (%rsp)
1328 ret
1329
1330LMsgForwardError:
1331 // Tail-call __objc_error(receiver, "unknown selector %s", "forward::")
1332 // %a1 is already the receiver
1333 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s"
1334 movq _FwdSel(%rip), %a3 // forward::
1335 jmp ___objc_error // never returns
1336
1337 END_ENTRY __objc_msgForward
1338
1339
1340 ENTRY __objc_msgForward_stret
7af964d1
A
1341 // Struct-return version
1342
b3962a83
A
1343 // Call user handler, if any
1344 movq __objc_forward_stret_handler(%rip), %r11
1345 testq %r11, %r11 // if (handler == NULL)
1346 je 1f // skip handler
1347 jmp *%r11 // else goto handler
13481:
1349 // No user handler
1350 // Die if forwarding "forward::"
1351 cmpq %a3, _FwdSel(%rip)
1352 je LMsgForwardStretError
1353
1354 // Record current return address. It will be copied elsewhere in
1355 // the marg_list because this location is needed for register args
1356 movq (%rsp), %r11
1357
1358 // Push stack frame
1359 // Space for: fpArgs + regArgs + linkage - ret (already on stack)
1360 subq $ 8*16 + 6*8 + (4-1)*8, %rsp
1361
1362 // Save return address in linkage area.
1363 movq %r11, 16+LINK_AREA(%rsp)
1364
1365 // Save parameter registers
1366 movq %a1, 0+REG_AREA(%rsp)
1367 movq %a2, 8+REG_AREA(%rsp)
1368 movq %a3, 16+REG_AREA(%rsp)
1369 movq %a4, 24+REG_AREA(%rsp)
1370 movq %a5, 32+REG_AREA(%rsp)
1371 movq %a6, 40+REG_AREA(%rsp)
1372
1373 // Save side parameter registers
8972963c 1374 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal
b3962a83
A
1375 movq %rax, 8+LINK_AREA(%rsp) // xmm count
1376 // 16+LINK_AREA is return address
1377
1378 // Save xmm registers
1379 movdqa %xmm0, 0+FP_AREA(%rsp)
1380 movdqa %xmm1, 16+FP_AREA(%rsp)
1381 movdqa %xmm2, 32+FP_AREA(%rsp)
1382 movdqa %xmm3, 48+FP_AREA(%rsp)
1383 movdqa %xmm4, 64+FP_AREA(%rsp)
1384 movdqa %xmm5, 80+FP_AREA(%rsp)
1385 movdqa %xmm6, 96+FP_AREA(%rsp)
1386 movdqa %xmm7, 112+FP_AREA(%rsp)
1387
1388 // Call [receiver forward:sel :margs]
1389 movq %a2, %a1 // receiver
1390 movq _FwdSel(%rip), %a2 // forward::
1391 // %a3 is already the selector
1392 movq %rsp, %a4 // marg_list
1393
1394 call _objc_msgSend // forward:: is NOT struct-return
1395
1396 // Retrieve return address from linkage area
1397 movq 16+LINK_AREA(%rsp), %r11
1398 // Pop stack frame
8972963c 1399 addq $ 8*16 + 6*8 + (4-1)*8, %rsp
b3962a83
A
1400 // Put return address back
1401 movq %r11, (%rsp)
1402 ret
1403
1404LMsgForwardStretError:
1405 // Tail-call __objc_error(receiver, "unknown selector %s", "forward::")
1406 movq %a2, %a1 // receiver
1407 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s"
1408 movq _FwdSel(%rip), %a3 // forward::
1409 jmp ___objc_error // never returns
1410
1411 END_ENTRY __objc_msgForward_stret
1412
1413
8972963c
A
1414 ENTRY _objc_msgSend_debug
1415 jmp _objc_msgSend
1416 END_ENTRY _objc_msgSend_debug
1417
1418 ENTRY _objc_msgSendSuper2_debug
1419 jmp _objc_msgSendSuper2
1420 END_ENTRY _objc_msgSendSuper2_debug
1421
1422 ENTRY _objc_msgSend_stret_debug
1423 jmp _objc_msgSend_stret
1424 END_ENTRY _objc_msgSend_stret_debug
1425
1426 ENTRY _objc_msgSendSuper2_stret_debug
1427 jmp _objc_msgSendSuper2_stret
1428 END_ENTRY _objc_msgSendSuper2_stret_debug
1429
1430 ENTRY _objc_msgSend_fpret_debug
1431 jmp _objc_msgSend_fpret
1432 END_ENTRY _objc_msgSend_fpret_debug
1433
1434 ENTRY _objc_msgSend_fp2ret_debug
1435 jmp _objc_msgSend_fp2ret
1436 END_ENTRY _objc_msgSend_fp2ret_debug
1437
1438
1439 ENTRY _objc_msgSend_noarg
1440 jmp _objc_msgSend
1441 END_ENTRY _objc_msgSend_noarg
1442
1443
b3962a83
A
1444 ENTRY _method_invoke
1445
1446 movq method_imp(%a2), %r11
1447 movq method_name(%a2), %a2
1448 jmp *%r11
1449
1450 END_ENTRY _method_invoke
1451
1452
1453 ENTRY _method_invoke_stret
1454
1455 movq method_imp(%a3), %r11
1456 movq method_name(%a3), %a3
1457 jmp *%r11
1458
1459 END_ENTRY _method_invoke_stret
7af964d1 1460
8972963c
A
1461
1462 STATIC_ENTRY __objc_ignored_method
1463
1464 movq %a1, %rax
1465 ret
1466
1467 END_ENTRY __objc_ignored_method
1468
7af964d1
A
1469
1470/********************************************************************
1471 *
1472 * id vtable_prototype(id self, message_ref *msg, ...)
1473 *
1474 * This code is copied to create vtable trampolines.
1475 * The instruction following LvtableIndex is modified to
1476 * insert each vtable index.
8972963c
A
1477 * The instructions following LvtableTagTable are modified to
1478 * load the tagged isa table.
7af964d1
A
1479 *
1480 * This code is placed in its own section to prevent dtrace from
1481 * instrumenting it. Otherwise, dtrace would insert an INT3, the
1482 * code would be copied, and the copied INT3 would cause a crash.
8972963c
A
1483 *
1484 * ABI WARNING ABI WARNING ABI WARNING ABI WARNING ABI WARNING
1485 * vtable_prototype steals %rax and does not clear %rdx on return
1486 * in order to precisely pack instructions into ifetch and cache lines
1487 * This means vtable dispatch must never be used for vararg calls
1488 * or very large return values.
1489 * ABI WARNING ABI WARNING ABI WARNING ABI WARNING ABI WARNING
7af964d1
A
1490 *
1491 ********************************************************************/
1492
1493.macro VTABLE /* byte-offset, name */
1494
8972963c 1495 .align 6
7af964d1
A
1496 .private_extern _$1
1497_$1:
1498 test %a1, %a1
8972963c
A
1499 je LvtableReturnZero_$1 // nil check
1500 testl $$1, %a1d
1501 jne LvtableTaggedPointer_$1 // tag check
1502
1503 movq (%a1), %rax // load isa (see ABI WARNING)
1504 movq 24(%rax), %rax // load vtable
1505 movq 8(%a2), %a2 // load _cmd
7af964d1 1506LvtableIndex_$1:
8972963c
A
1507 jmpq * $0 (%rax) // load imp (DO NOT CHANGE)
1508
7af964d1
A
1509LvtableReturnZero_$1:
1510 // integer registers only; not used for fpret / stret / etc
8972963c
A
1511 xorl %eax, %eax
1512 // xorl %edx, %edx (see ABI WARNING)
7af964d1 1513 ret
8972963c 1514
7af964d1 1515 nop
8972963c
A
1516LvtableTaggedPointer_$1:
1517 // extract isa (bits 1-2-3) from %a1, bit 0 is kept around for the heck of it
1518 movl %a1d, %eax
1519 andl $$0xF, %eax
1520LvtableTagTable_$1:
1521.if $0 == 0x7fff
1522 movq $$0x1122334455667788, %r10 // vtable_prototype (DO NOT CHANGE)
1523.else
1524 leaq __objc_tagged_isa_table(%rip), %r10
1525.endif
1526LvtableTagTableEnd_$1:
1527 movq (%r10, %rax, 8), %r10 // load isa from table (see ABI WARNING
1528 movq 24(%r10), %rax // load vtable
1529 movq 8(%a2), %a2 // load _cmd
1530LvtableIndex2_$1:
1531 jmpq * $0 (%rax) // load imp (DO NOT CHANGE)
1532
1533LvtableEnd_$1:
7af964d1
A
1534
1535.endmacro
1536
1537 .section __TEXT,__objc_codegen,regular
1538 VTABLE 0x7fff, vtable_prototype
1539
1540 .data
1541 .align 2
1542 .private_extern _vtable_prototype_size
1543_vtable_prototype_size:
1544 .long LvtableEnd_vtable_prototype - _vtable_prototype
1545
1546 .private_extern _vtable_prototype_index_offset
1547_vtable_prototype_index_offset:
1548 .long LvtableIndex_vtable_prototype - _vtable_prototype
1549
8972963c
A
1550 .private_extern _vtable_prototype_index2_offset
1551_vtable_prototype_index2_offset:
1552 .long LvtableIndex2_vtable_prototype - _vtable_prototype
1553
1554 .private_extern _vtable_prototype_tagtable_offset
1555_vtable_prototype_tagtable_offset:
1556 .long LvtableTagTable_vtable_prototype - _vtable_prototype
1557
1558 .private_extern _vtable_prototype_tagtable_size
1559_vtable_prototype_tagtable_size:
1560 .long LvtableTagTableEnd_vtable_prototype - LvtableTagTable_vtable_prototype
7af964d1
A
1561
1562/********************************************************************
1563 *
1564 * id vtable_ignored(id self, message_ref *msg, ...)
1565 *
1566 * Vtable trampoline for GC-ignored selectors. Immediately returns self.
1567 *
1568 ********************************************************************/
1569
8972963c 1570 STATIC_ENTRY _vtable_ignored
7af964d1
A
1571 movq %a1, %rax
1572 ret
1573
1574
1575/********************************************************************
1576 *
1577 * id objc_msgSend_vtable<n>(id self, message_ref *msg, ...)
1578 *
1579 * Built-in expansions of vtable_prototype for the default vtable.
1580 *
1581 ********************************************************************/
1582
1583 .text
1584
1585 .align 4
1586 .private_extern _defaultVtableTrampolineDescriptors
1587_defaultVtableTrampolineDescriptors:
1588 // objc_trampoline_header
1589 .short 16 // headerSize
1590 .short 8 // descSize
1591 .long 16 // descCount
1592 .quad 0 // next
1593
1594 // objc_trampoline_descriptor[16]
1595.macro TDESC /* n */
1596L_tdesc$0:
1597 .long _objc_msgSend_vtable$0 - L_tdesc$0
1598 .long (1<<0) + (1<<2) // MESSAGE and VTABLE
1599.endmacro
1600
1601 TDESC 0
1602 TDESC 1
1603 TDESC 2
1604 TDESC 3
1605 TDESC 4
1606 TDESC 5
1607 TDESC 6
1608 TDESC 7
1609 TDESC 8
1610 TDESC 9
1611 TDESC 10
1612 TDESC 11
1613 TDESC 12
1614 TDESC 13
1615 TDESC 14
1616 TDESC 15
1617
1618 // trampoline code
1619 .align 4
1620 VTABLE 0*8, objc_msgSend_vtable0
1621 VTABLE 1*8, objc_msgSend_vtable1
1622 VTABLE 2*8, objc_msgSend_vtable2
1623 VTABLE 3*8, objc_msgSend_vtable3
1624 VTABLE 4*8, objc_msgSend_vtable4
1625 VTABLE 5*8, objc_msgSend_vtable5
1626 VTABLE 6*8, objc_msgSend_vtable6
1627 VTABLE 7*8, objc_msgSend_vtable7
1628 VTABLE 8*8, objc_msgSend_vtable8
1629 VTABLE 9*8, objc_msgSend_vtable9
1630 VTABLE 10*8, objc_msgSend_vtable10
1631 VTABLE 11*8, objc_msgSend_vtable11
1632 VTABLE 12*8, objc_msgSend_vtable12
1633 VTABLE 13*8, objc_msgSend_vtable13
1634 VTABLE 14*8, objc_msgSend_vtable14
1635 VTABLE 15*8, objc_msgSend_vtable15
1636
1637#endif