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
|
;
; Copyright (c) Microsoft. All rights reserved.
; Licensed under the MIT license. See LICENSE file in the project root for full license information.
;
include <AsmMacros.inc>
include <AsmConstants.inc>
extern CallDescrWorkerUnwindFrameChainHandler:proc
;;
;; EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr);
;;
NESTED_ENTRY FastCallFinalizeWorker, _TEXT, CallDescrWorkerUnwindFrameChainHandler
alloc_stack 28h ;; alloc callee scratch and align the stack
END_PROLOGUE
;
; RCX: already contains obj*
; RDX: address of finalizer method to call
;
; !!!!!!!!!
; NOTE: you cannot tail call here because we must have the CallDescrWorkerUnwindFrameChainHandler
; personality routine on the stack.
; !!!!!!!!!
call rdx
xor rax, rax
; epilog
add rsp, 28h
ret
NESTED_END FastCallFinalizeWorker, _TEXT
;;extern "C" void CallDescrWorkerInternal(CallDescrData * pCallDescrData);
NESTED_ENTRY CallDescrWorkerInternal, _TEXT, CallDescrWorkerUnwindFrameChainHandler
push_nonvol_reg rbx ; save nonvolatile registers
push_nonvol_reg rsi ;
push_nonvol_reg rbp ;
set_frame rbp, 0 ; set frame pointer
END_PROLOGUE
mov rbx, rcx ; save pCallDescrData in rbx
mov ecx, dword ptr [rbx + CallDescrData__numStackSlots]
test ecx, 1
jz StackAligned
push rax
StackAligned:
mov rsi, [rbx + CallDescrData__pSrc] ; set source argument list address
lea rsi, [rsi + 8 * rcx]
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 StackCopyLoop
;
; N.B. All four argument registers are loaded regardless of the actual number
; of arguments.
;
mov rax, [rbx + CallDescrData__dwRegTypeMap] ; save the reg (arg) type map
mov rcx, 0[rsp] ; load first four argument registers
movss xmm0, real4 ptr 0[rsp] ;
cmp al, ASM_ELEMENT_TYPE_R8 ;
jnz Arg2 ;
movsd xmm0, real8 ptr 0[rsp] ;
Arg2:
mov rdx, 8[rsp] ;
movss xmm1, real4 ptr 8[rsp] ;
cmp ah, ASM_ELEMENT_TYPE_R8 ;
jnz Arg3 ;
movsd xmm1, real8 ptr 8[rsp] ;
Arg3:
mov r8, 10h[rsp] ;
movss xmm2, real4 ptr 10h[rsp];
shr eax, 16 ;
cmp al, ASM_ELEMENT_TYPE_R8 ;
jnz Arg4 ;
movsd xmm2, real8 ptr 10h[rsp];
Arg4:
mov r9, 18h[rsp] ;
movss xmm3, real4 ptr 18h[rsp];
cmp ah, ASM_ELEMENT_TYPE_R8 ;
jnz DoCall ;
movsd xmm3, real8 ptr 18h[rsp];
DoCall:
call qword ptr [rbx+CallDescrData__pTarget] ; call target function
; Save FP return value
mov ecx, dword ptr [rbx+CallDescrData__fpReturnSize]
test ecx, ecx
jz ReturnsInt
cmp ecx, 4
je ReturnsFloat
cmp ecx, 8
je ReturnsDouble
; unexpected
jmp Epilog
ReturnsInt:
mov [rbx+CallDescrData__returnValue], rax
Epilog:
lea rsp, 0[rbp] ; deallocate argument list
pop rbp ; restore nonvolatile register
pop rsi ;
pop rbx ;
ret
ReturnsFloat:
movss real4 ptr [rbx+CallDescrData__returnValue], xmm0
jmp Epilog
ReturnsDouble:
movsd real8 ptr [rbx+CallDescrData__returnValue], xmm0
jmp Epilog
NESTED_END CallDescrWorkerInternal, _TEXT
end
|