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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
.intel_syntax noprefix
#include "unixasmmacros.inc"
#include "asmconstants.h"
#define real4 dword
#define real8 qword
//extern CallDescrWorkerUnwindFrameChainHandler:proc
//
// EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr);
//
NESTED_ENTRY FastCallFinalizeWorker, _TEXT, NoHandler
push_nonvol_reg rbp
mov rbp, rsp
END_PROLOGUE
//
// RDI: already contains obj*
// RSI: address of finalizer method to call
//
// !!!!!!!!!
// NOTE: you cannot tail call here because we must have the CallDescrWorkerUnwindFrameChainHandler
// personality routine on the stack.
// !!!!!!!!!
call rsi
xor rax, rax
// epilog
pop_nonvol_reg rbp
ret
NESTED_END FastCallFinalizeWorker, _TEXT
//extern "C" void CallDescrWorkerInternal(CallDescrData * pCallDescrData);
NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler
push_nonvol_reg rbp
mov rbp, rsp
push_nonvol_reg rbx
alloc_stack 8 // ensure proper alignment of the rsp
set_cfa_register rbp, (2*8)
END_PROLOGUE
mov rbx, rdi // save pCallDescrData in rbx
mov ecx, dword ptr [rbx + CallDescrData__numStackSlots]
and ecx, ecx
jz LOCAL_LABEL(NoStackArguments)
test ecx, 1
jz LOCAL_LABEL(StackAligned)
push rax
LOCAL_LABEL(StackAligned):
mov rsi, [rbx + CallDescrData__pSrc] // set source argument list address
lea rsi, [rsi + 8 * rcx]
LOCAL_LABEL(StackCopyLoop): // copy the arguments to stack top-down to carefully probe for sufficient stack space
sub rsi, 8
push qword ptr [rsi]
dec ecx
jnz LOCAL_LABEL(StackCopyLoop)
LOCAL_LABEL(NoStackArguments):
// All argument registers are loaded regardless of the actual number
// of arguments.
mov rax, [rbx + CallDescrData__pArgumentRegisters]
mov rdi, [rax + 0]
mov rsi, [rax + 8]
mov rdx, [rax + 16]
mov rcx, [rax + 24]
mov r8, [rax + 32]
mov r9, [rax + 40]
// All float argument registers are loaded regardless of the actual number
// of arguments.
mov rax, [rbx + CallDescrData__pFloatArgumentRegisters]
and rax, rax
jz LOCAL_LABEL(NoFloatArguments)
movsd xmm0, [rax + 0]
movsd xmm1, [rax + 16]
movsd xmm2, [rax + 32]
movsd xmm3, [rax + 48]
movsd xmm4, [rax + 64]
movsd xmm5, [rax + 80]
movsd xmm6, [rax + 96]
movsd xmm7, [rax + 112]
LOCAL_LABEL(NoFloatArguments):
call qword ptr [rbx + CallDescrData__pTarget] // call target function
// Save FP return value
mov ecx, dword ptr [rbx + CallDescrData__fpReturnSize]
test ecx, ecx
jz LOCAL_LABEL(ReturnsInt)
cmp ecx, 4
je LOCAL_LABEL(ReturnsFloat)
cmp ecx, 8
je LOCAL_LABEL(ReturnsDouble)
#if defined(UNIX_AMD64_ABI)
// Struct with two integer eightbytes
cmp ecx, 16
jne LOCAL_LABEL(NotTwoIntegerEightbytes)
mov qword ptr [rbx+CallDescrData__returnValue], rax
mov qword ptr [rbx+CallDescrData__returnValue + 8], rdx
jmp LOCAL_LABEL(Epilog)
LOCAL_LABEL(NotTwoIntegerEightbytes):
// Struct with the first eightbyte SSE and the second one integer
cmp ecx, 16 + 1
jne LOCAL_LABEL(NotFirstSSESecondIntegerEightbyte)
movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0
mov qword ptr [rbx+CallDescrData__returnValue + 8], rax
jmp LOCAL_LABEL(Epilog)
LOCAL_LABEL(NotFirstSSESecondIntegerEightbyte):
// Struct with the first eightbyte integer and the second one SSE
cmp ecx, 16 + 2
jne LOCAL_LABEL(NotFirstIntegerSecondSSEEightbyte)
mov qword ptr [rbx+CallDescrData__returnValue], rax
movsd real8 ptr [rbx+CallDescrData__returnValue + 8], xmm0
jmp LOCAL_LABEL(Epilog)
LOCAL_LABEL(NotFirstIntegerSecondSSEEightbyte):
// Struct with two SSE eightbytes
cmp ecx, 16 + 3
jne LOCAL_LABEL(Epilog) // unexpected
movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0
movsd real8 ptr [rbx+CallDescrData__returnValue + 8], xmm1
#endif // UNIX_AMD64_ABI
jmp LOCAL_LABEL(Epilog)
LOCAL_LABEL(ReturnsInt):
mov qword ptr [rbx+CallDescrData__returnValue], rax
LOCAL_LABEL(Epilog):
lea rsp, [rbp - 8] // deallocate arguments
set_cfa_register rsp, (3*8)
pop_nonvol_reg rbx
pop_nonvol_reg rbp
ret
LOCAL_LABEL(ReturnsFloat):
movss real4 ptr [rbx+CallDescrData__returnValue], xmm0
jmp LOCAL_LABEL(Epilog)
LOCAL_LABEL(ReturnsDouble):
movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0
jmp LOCAL_LABEL(Epilog)
NESTED_END CallDescrWorkerInternal, _TEXT
|