forked from qmathe/gnustep-libobjc2
-
Notifications
You must be signed in to change notification settings - Fork 1
/
objc_msgSend.x86-64.S
142 lines (130 loc) · 4.41 KB
/
objc_msgSend.x86-64.S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#define DTABLE_OFFSET 64
#define SMALLOBJ_MASK 7
#define SHIFT_OFFSET 4
#define DATA_OFFSET 16
#define SLOT_OFFSET 32
.macro MSGSEND receiver, sel
.cfi_startproc # Start emitting unwind data. We
# don't actually care about any of
# the stuff except the slow call,
# because that's the only one that
# can throw.
test \receiver, \receiver # If the receiver is nil
jz 4f # return nil
movq $SMALLOBJ_MASK, %r10 # Load the small object mask
test \receiver, %r10 # Check if the receiver is a small object
jnz 6f # Get the small object class
mov (\receiver), %r10 # Load the dtable from the class
1: # classLoaded
mov DTABLE_OFFSET(%r10), %r10 # Load the dtable from the class
push %r12
push %r13
mov (\sel), %r11 # Load the selector index
mov SHIFT_OFFSET(%r10), %r13 # Load the shift (dtable size)
mov DATA_OFFSET(%r10), %r12 # load the address of the start of the array
cmpl $8, %r13d # If this is a small dtable, jump to the small dtable handlers
je 2f
cmpl $0, %r13d
je 3f
mov %r11, %r13
and $0xff0000, %r13
shrl $13, %r13d # Right shift 16, but then left shift by 3 *sizeof(void*)
add %r13, %r12
mov (%r12), %r12
mov DATA_OFFSET(%r12), %r12
2: # dtable16:
mov %r11, %r13
and $0xff00, %r13
shrl $5, %r13d
add %r13, %r12
mov (%r12), %r12
mov DATA_OFFSET(%r12), %r12
3: # dtable8:
mov %r11, %r13
and $0xff, %r13
shll $3, %r13d
add %r13, %r12
mov (%r12), %r10
pop %r13
pop %r12
test %r10, %r10
jz 5f # Nil slot - invoke some kind of forwarding mechanism
mov SLOT_OFFSET(%r10), %r10
jmp *%r10
4: # returnNil:
# Both of the return registers are
# callee-save on x86-64, so we can
# return 0 in both in the same code:
xor %rax, %rax # Return 0 as an integer
pxor %xmm0, %xmm0 # Return 0 as a floating point value
ret
5: # slowSend:
push %rax # We need to preserve all registers that may contain arguments:
push %rbx
push %rcx
push %r8
push %r9
sub $0x98, %rsp
movups %xmm0, 0x80(%rsp)
movups %xmm1, 0x70(%rsp)
movups %xmm2, 0x60(%rsp)
movups %xmm3, 0x50(%rsp)
movups %xmm4, 0x40(%rsp)
movups %xmm5, 0x30(%rsp)
movups %xmm6, 0x20(%rsp)
movups %xmm7, 0x10(%rsp)
#rdi rsi rdx
# We're (potentially) modifying the self argument with the lookup, so we don't want to be
.ifc "\receiver", "%rdi"
push %rdi
mov %rsp, %rdi
push %rsi # Save _cmd (not preserved across calls)
push %rdx
.else
push %rdi # Save the sret pointer
push %rsi # Save self where it can be modified
mov %rsp, %rdi
push %rdx
mov %rdx, %rsi # move _cmd to where the callee expects it to be
.endif
.cfi_adjust_cfa_offset 0xD8
call slowMsgLookup # Call the slow lookup function
mov %rax, %r10 # Load the returned IMP
pop %rdx
pop %rsi
pop %rdi
movups 0x80(%rsp), %xmm0
movups 0x70(%rsp), %xmm1
movups 0x60(%rsp), %xmm2
movups 0x50(%rsp), %xmm3
movups 0x40(%rsp), %xmm4
movups 0x30(%rsp), %xmm5
movups 0x20(%rsp), %xmm6
movups 0x10(%rsp), %xmm7
add $0x98, %rsp
pop %r9
pop %r8
pop %rcx
pop %rbx
pop %rax
jmp *%r10
6: # smallObject:
and \receiver, %r10 # Find the small int type
shll $3, %r10d
lea SmallObjectClasses(%rip), %r11
add %r11, %r10
mov (%r10), %r10
jmp 1b
.cfi_endproc
.endm
.globl objc_msgSend
.type objc_msgSend, @function
.globl objc_msgSend_fpret
.type objc_msgSend_fpret, @function
objc_msgSend_fpret:
objc_msgSend:
MSGSEND %rdi, %rsi
.globl objc_msgSend_stret
.type objc_msgSend_stret, @function
objc_msgSend_stret:
MSGSEND %rsi, %rdx