forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalldescrworkeramd64.S
138 lines (111 loc) · 4.78 KB
/
calldescrworkeramd64.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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
.intel_syntax noprefix
#include "unixasmmacros.inc"
#include "asmconstants.h"
#define real4 dword
#define real8 qword
//extern CallDescrWorkerUnwindFrameChainHandler:proc
//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
LOCAL_LABEL(CallDescrWorkerInternalReturnAddress):
// 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)
PATCH_LABEL CallDescrWorkerInternalReturnAddressOffset
.quad LOCAL_LABEL(CallDescrWorkerInternalReturnAddress) - C_FUNC(CallDescrWorkerInternal)
NESTED_END CallDescrWorkerInternal, _TEXT