1; Licensed to the .NET Foundation under one or more agreements.
2; The .NET Foundation licenses this file to you under the MIT license.
3; See the LICENSE file in the project root for more information.
4
5include <AsmMacros.inc>
6include <AsmConstants.inc>
7
8extern CallDescrWorkerUnwindFrameChainHandler:proc
9
10;;
11;;      EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr);
12;;
13        NESTED_ENTRY FastCallFinalizeWorker, _TEXT, CallDescrWorkerUnwindFrameChainHandler
14        alloc_stack     28h     ;; alloc callee scratch and align the stack
15        END_PROLOGUE
16
17        ;
18        ; RCX: already contains obj*
19        ; RDX: address of finalizer method to call
20        ;
21
22        ; !!!!!!!!!
23        ; NOTE:  you cannot tail call here because we must have the CallDescrWorkerUnwindFrameChainHandler
24        ;        personality routine on the stack.
25        ; !!!!!!!!!
26        call    rdx
27        xor     rax, rax
28
29        ; epilog
30        add     rsp, 28h
31        ret
32
33
34        NESTED_END FastCallFinalizeWorker, _TEXT
35
36;;extern "C" void CallDescrWorkerInternal(CallDescrData * pCallDescrData);
37
38        NESTED_ENTRY CallDescrWorkerInternal, _TEXT, CallDescrWorkerUnwindFrameChainHandler
39
40        push_nonvol_reg rbx             ; save nonvolatile registers
41        push_nonvol_reg rsi             ;
42        push_nonvol_reg rbp             ;
43        set_frame rbp, 0                ; set frame pointer
44
45        END_PROLOGUE
46
47        mov     rbx, rcx                ; save pCallDescrData in rbx
48
49        mov     ecx, dword ptr [rbx + CallDescrData__numStackSlots]
50
51        test    ecx, 1
52        jz      StackAligned
53        push    rax
54StackAligned:
55
56        mov     rsi, [rbx + CallDescrData__pSrc] ; set source argument list address
57        lea     rsi, [rsi + 8 * rcx]
58
59StackCopyLoop:                          ; copy the arguments to stack top-down to carefully probe for sufficient stack space
60        sub     rsi, 8
61        push    qword ptr [rsi]
62        dec     ecx
63        jnz     StackCopyLoop
64
65        ;
66        ; N.B. All four argument registers are loaded regardless of the actual number
67        ;      of arguments.
68        ;
69
70        mov     rax, [rbx + CallDescrData__dwRegTypeMap] ; save the reg (arg) type map
71
72        mov     rcx, 0[rsp]             ; load first four argument registers
73        movss   xmm0, real4 ptr 0[rsp]  ;
74        cmp     al, ASM_ELEMENT_TYPE_R8 ;
75        jnz     Arg2                    ;
76        movsd   xmm0, real8 ptr 0[rsp]  ;
77Arg2:
78        mov     rdx, 8[rsp]             ;
79        movss   xmm1, real4 ptr 8[rsp]  ;
80        cmp     ah, ASM_ELEMENT_TYPE_R8 ;
81        jnz     Arg3                    ;
82        movsd   xmm1, real8 ptr 8[rsp]  ;
83Arg3:
84        mov     r8, 10h[rsp]            ;
85        movss   xmm2, real4 ptr 10h[rsp];
86        shr     eax, 16                 ;
87        cmp     al, ASM_ELEMENT_TYPE_R8 ;
88        jnz     Arg4                    ;
89        movsd   xmm2, real8 ptr 10h[rsp];
90Arg4:
91        mov     r9, 18h[rsp]            ;
92        movss   xmm3, real4 ptr 18h[rsp];
93        cmp     ah, ASM_ELEMENT_TYPE_R8 ;
94        jnz     DoCall                  ;
95        movsd   xmm3, real8 ptr 18h[rsp];
96DoCall:
97        call    qword ptr [rbx+CallDescrData__pTarget]     ; call target function
98
99        ; Save FP return value
100
101        mov     ecx, dword ptr [rbx+CallDescrData__fpReturnSize]
102        test    ecx, ecx
103        jz      ReturnsInt
104
105        cmp     ecx, 4
106        je      ReturnsFloat
107        cmp     ecx, 8
108        je      ReturnsDouble
109        ; unexpected
110        jmp     Epilog
111
112ReturnsInt:
113        mov     [rbx+CallDescrData__returnValue], rax
114
115Epilog:
116        lea     rsp, 0[rbp]             ; deallocate argument list
117        pop     rbp                     ; restore nonvolatile register
118        pop     rsi                     ;
119        pop     rbx                     ;
120        ret
121
122ReturnsFloat:
123        movss   real4 ptr [rbx+CallDescrData__returnValue], xmm0
124        jmp     Epilog
125
126ReturnsDouble:
127        movsd   real8 ptr [rbx+CallDescrData__returnValue], xmm0
128        jmp     Epilog
129
130        NESTED_END CallDescrWorkerInternal, _TEXT
131
132        end
133