summaryrefslogtreecommitdiff
path: root/src/vm/amd64/CallDescrWorkerAMD64.asm
blob: ed51e57fe3c083bca7f97ace829d53eb130e318c (plain)
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