xref: /trunk/main/bridges/source/cpp_uno/msvc_win64_x86-64/call.asm (revision b146d3b3d71aec159e3fe3467f81d89bd9d862f8)
1*b146d3b3SDamjan Jovanovic;
2*b146d3b3SDamjan Jovanovic; Licensed to the Apache Software Foundation (ASF) under one
3*b146d3b3SDamjan Jovanovic; or more contributor license agreements.  See the NOTICE file
4*b146d3b3SDamjan Jovanovic; distributed with this work for additional information
5*b146d3b3SDamjan Jovanovic; regarding copyright ownership.  The ASF licenses this file
6*b146d3b3SDamjan Jovanovic; to you under the Apache License, Version 2.0 (the
7*b146d3b3SDamjan Jovanovic; "License"); you may not use this file except in compliance
8*b146d3b3SDamjan Jovanovic; with the License.  You may obtain a copy of the License at
9*b146d3b3SDamjan Jovanovic;
10*b146d3b3SDamjan Jovanovic;   http://www.apache.org/licenses/LICENSE-2.0
11*b146d3b3SDamjan Jovanovic;
12*b146d3b3SDamjan Jovanovic; Unless required by applicable law or agreed to in writing,
13*b146d3b3SDamjan Jovanovic; software distributed under the License is distributed on an
14*b146d3b3SDamjan Jovanovic; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*b146d3b3SDamjan Jovanovic; KIND, either express or implied.  See the License for the
16*b146d3b3SDamjan Jovanovic; specific language governing permissions and limitations
17*b146d3b3SDamjan Jovanovic; under the License.
18*b146d3b3SDamjan Jovanovic;
19*b146d3b3SDamjan Jovanovic
20*b146d3b3SDamjan Jovanovic
21*b146d3b3SDamjan Jovanovictypelib_TypeClass_VOID equ 0
22*b146d3b3SDamjan Jovanovictypelib_TypeClass_CHAR equ 1
23*b146d3b3SDamjan Jovanovictypelib_TypeClass_BOOLEAN equ 2
24*b146d3b3SDamjan Jovanovictypelib_TypeClass_BYTE equ 3
25*b146d3b3SDamjan Jovanovictypelib_TypeClass_SHORT equ 4
26*b146d3b3SDamjan Jovanovictypelib_TypeClass_UNSIGNED_SHORT equ 5
27*b146d3b3SDamjan Jovanovictypelib_TypeClass_LONG equ 6
28*b146d3b3SDamjan Jovanovictypelib_TypeClass_UNSIGNED_LONG equ 7
29*b146d3b3SDamjan Jovanovictypelib_TypeClass_HYPER equ 8
30*b146d3b3SDamjan Jovanovictypelib_TypeClass_UNSIGNED_HYPER equ 9
31*b146d3b3SDamjan Jovanovictypelib_TypeClass_FLOAT equ 10
32*b146d3b3SDamjan Jovanovictypelib_TypeClass_DOUBLE equ 11
33*b146d3b3SDamjan Jovanovictypelib_TypeClass_ENUM equ 15
34*b146d3b3SDamjan Jovanovic
35*b146d3b3SDamjan JovanovicEXTERN cpp_vtable_call: PROC
36*b146d3b3SDamjan Jovanovic
37*b146d3b3SDamjan Jovanovic.CODE
38*b146d3b3SDamjan Jovanovic
39*b146d3b3SDamjan Jovanovic;
40*b146d3b3SDamjan Jovanovic;               | ...                        |
41*b146d3b3SDamjan Jovanovic;               +----------------------------+
42*b146d3b3SDamjan Jovanovic;               | argument 4                 |
43*b146d3b3SDamjan Jovanovic; rbp+48 rsp+40 +----------------------------+ -------
44*b146d3b3SDamjan Jovanovic;               | argument 3, r9/xmm3 home   | ^ shadow
45*b146d3b3SDamjan Jovanovic; rbp+40 rsp+32 +----------------------------+ | space,
46*b146d3b3SDamjan Jovanovic;               | argument 2, r8/xmm2 home   | | guaranteed to be present but uninitialized,
47*b146d3b3SDamjan Jovanovic; rbp+32 rsp+24 +----------------------------+ | we have to copy
48*b146d3b3SDamjan Jovanovic;               | argument 1, rdx/xmm1 home  | | the first 4 parameters there from the registers,
49*b146d3b3SDamjan Jovanovic; rbp+24 rsp+16 +----------------------------+ | to form the continuous array of arguments.
50*b146d3b3SDamjan Jovanovic;               | argument 0, rcx/xmm0 home  | v
51*b146d3b3SDamjan Jovanovic; rbp+16 rsp+08 +----------------------------+ -------
52*b146d3b3SDamjan Jovanovic;               | return address             |
53*b146d3b3SDamjan Jovanovic; rbp+08 rsp--> +----------------------------+
54*b146d3b3SDamjan Jovanovic;               | old rbp                    |
55*b146d3b3SDamjan Jovanovic; rbp---------> +----------------------------+
56*b146d3b3SDamjan Jovanovic;               | pRegisterReturn memory     |
57*b146d3b3SDamjan Jovanovic; rbp-08 -----> +----------------------------+
58*b146d3b3SDamjan Jovanovic;               |                            |
59*b146d3b3SDamjan Jovanovic; rbp-16 -----> +----------------------------+ -------
60*b146d3b3SDamjan Jovanovic;               |                            | ^
61*b146d3b3SDamjan Jovanovic; rbp-24 -----> +----------------------------+ | shadow space
62*b146d3b3SDamjan Jovanovic;               |                            | | for cpp_vtable_call
63*b146d3b3SDamjan Jovanovic; rbp-32 -----> +----------------------------+ |
64*b146d3b3SDamjan Jovanovic;               |                            | |
65*b146d3b3SDamjan Jovanovic; rbp-40 -----> +----------------------------+ |
66*b146d3b3SDamjan Jovanovic;               |                            | v
67*b146d3b3SDamjan Jovanovic; rbp-48 -----> +----------------------------+ -------
68*b146d3b3SDamjan Jovanovic;
69*b146d3b3SDamjan Jovanovic; rax = functionIndex
70*b146d3b3SDamjan Jovanovic; r10 = vtableOffset
71*b146d3b3SDamjan Jovanovic; r11 = &privateSnippetExecutor
72*b146d3b3SDamjan Jovanovic;
73*b146d3b3SDamjan Jovanovic
74*b146d3b3SDamjan JovanovicprivateSnippetExecutor PROC FRAME
75*b146d3b3SDamjan Jovanovic
76*b146d3b3SDamjan Jovanovic    push    rbp
77*b146d3b3SDamjan Jovanovic    mov rbp, rsp
78*b146d3b3SDamjan Jovanovic    sub rsp, 48
79*b146d3b3SDamjan Jovanovic    .ALLOCSTACK(48)
80*b146d3b3SDamjan Jovanovic    .ENDPROLOG
81*b146d3b3SDamjan Jovanovic
82*b146d3b3SDamjan Jovanovic    ; 4th param: sal_uInt64 *pRegisterReturn
83*b146d3b3SDamjan Jovanovic    lea r9, -8[rbp]
84*b146d3b3SDamjan Jovanovic
85*b146d3b3SDamjan Jovanovic    ; 3rd param: sal_Int32 nVtableOffset
86*b146d3b3SDamjan Jovanovic    mov r8, r10
87*b146d3b3SDamjan Jovanovic
88*b146d3b3SDamjan Jovanovic    ; 2nd param: sal_Int32 nFunctionIndex
89*b146d3b3SDamjan Jovanovic    mov rdx, rax
90*b146d3b3SDamjan Jovanovic
91*b146d3b3SDamjan Jovanovic    ; 1st param: void ** pCallStack
92*b146d3b3SDamjan Jovanovic    lea rcx, 8[rbp]
93*b146d3b3SDamjan Jovanovic
94*b146d3b3SDamjan Jovanovic    call cpp_vtable_call
95*b146d3b3SDamjan Jovanovic
96*b146d3b3SDamjan Jovanovic    ; Integers would return in RAX and floats in XMM0, but both are free for us to clobber,
97*b146d3b3SDamjan Jovanovic    ; and the caller knows where to look:
98*b146d3b3SDamjan Jovanovic    mov rax, -8[rbp]
99*b146d3b3SDamjan Jovanovic    movsd xmm0, qword ptr -8[rbp]
100*b146d3b3SDamjan Jovanovic
101*b146d3b3SDamjan Jovanovic    leave
102*b146d3b3SDamjan Jovanovic    ret
103*b146d3b3SDamjan Jovanovic
104*b146d3b3SDamjan JovanovicprivateSnippetExecutor ENDP
105*b146d3b3SDamjan Jovanovic
106*b146d3b3SDamjan Jovanovic
107*b146d3b3SDamjan Jovanovic;
108*b146d3b3SDamjan Jovanovic;               | ...                                         |
109*b146d3b3SDamjan Jovanovic; rbp+64 -----> +---------------------------------------------+
110*b146d3b3SDamjan Jovanovic;               | sal_uInt32 nStack                           |
111*b146d3b3SDamjan Jovanovic; rbp+56 -----> +---------------------------------------------+
112*b146d3b3SDamjan Jovanovic;               | sal_uInt64 *pStack                          |
113*b146d3b3SDamjan Jovanovic; rbp+48 -----> +---------------------------------------------+ -------
114*b146d3b3SDamjan Jovanovic;               | typelib_TypeClass eReturnTypeClass, r9 home | ^ shadow
115*b146d3b3SDamjan Jovanovic; rbp+40 -----> +---------------------------------------------+ | space,
116*b146d3b3SDamjan Jovanovic;               | void *pRegisterReturn,              r8 home | | guaranteed to be present but uninitialized,
117*b146d3b3SDamjan Jovanovic; rbp+32 -----> +---------------------------------------------+ | we have to copy
118*b146d3b3SDamjan Jovanovic;               | sal_Int32 nVtableIndex,            rdx home | | the first 4 parameters there from the registers,
119*b146d3b3SDamjan Jovanovic; rbp+24 -----> +---------------------------------------------+ | to form the continuous array of arguments.
120*b146d3b3SDamjan Jovanovic;               | void* pAdjustedThisPtr,            rcx home | v
121*b146d3b3SDamjan Jovanovic; rbp+16 -----> +---------------------------------------------+ -------
122*b146d3b3SDamjan Jovanovic;               | return address                              |
123*b146d3b3SDamjan Jovanovic; rbp+08 -----> +---------------------------------------------+
124*b146d3b3SDamjan Jovanovic;               | old rbp                                     |
125*b146d3b3SDamjan Jovanovic; rbp --------> +---------------------------------------------+ <---- 16 byte boundary
126*b146d3b3SDamjan Jovanovic;               | (possible 16 byte alignment placeholder)    |
127*b146d3b3SDamjan Jovanovic; rbp-08 -----> +---------------------------------------------+
128*b146d3b3SDamjan Jovanovic;               | (stack for virtual method)                  |
129*b146d3b3SDamjan Jovanovic;               | ...                                         |
130*b146d3b3SDamjan Jovanovic;               | (shadow space for virtual method)           |
131*b146d3b3SDamjan Jovanovic; rsp --------> +---------------------------------------------+ <---- 16 byte boundary
132*b146d3b3SDamjan Jovanovic
133*b146d3b3SDamjan JovanoviccallVirtualMethod PROC FRAME
134*b146d3b3SDamjan Jovanovic
135*b146d3b3SDamjan Jovanovic    push rbp
136*b146d3b3SDamjan Jovanovic    mov rbp, rsp
137*b146d3b3SDamjan Jovanovic    .ENDPROLOG
138*b146d3b3SDamjan Jovanovic
139*b146d3b3SDamjan Jovanovic    ; Save our register arguments to the shadow space:
140*b146d3b3SDamjan Jovanovic    mov 16[rbp], rcx
141*b146d3b3SDamjan Jovanovic    mov 24[rbp], rdx
142*b146d3b3SDamjan Jovanovic    mov 32[rbp], r8
143*b146d3b3SDamjan Jovanovic    mov 40[rbp], r9
144*b146d3b3SDamjan Jovanovic
145*b146d3b3SDamjan Jovanovic    ; We must maintain the stack aligned to a 16 byte boundary:
146*b146d3b3SDamjan Jovanovic    mov eax, 56[rbp]
147*b146d3b3SDamjan Jovanovic    cmp rax, 0
148*b146d3b3SDamjan Jovanovic    je stackIsEmpty
149*b146d3b3SDamjan Jovanovic    mov r11, rax
150*b146d3b3SDamjan Jovanovic    test rax,1
151*b146d3b3SDamjan Jovanovic    jz stackSizeEven
152*b146d3b3SDamjan Jovanovic    sub rsp, 8
153*b146d3b3SDamjan JovanovicstackSizeEven:
154*b146d3b3SDamjan Jovanovic    mov r10, 48[rbp]
155*b146d3b3SDamjan Jovanovic    shl rax, 3        ; nStack is in units of sal_uInt64, and sizeof(sal_uInt64) == 8
156*b146d3b3SDamjan Jovanovic    add rax, r10
157*b146d3b3SDamjan Jovanovic
158*b146d3b3SDamjan JovanoviccopyStack:
159*b146d3b3SDamjan Jovanovic    sub rax, 8
160*b146d3b3SDamjan Jovanovic    push [rax]
161*b146d3b3SDamjan Jovanovic    dec r11
162*b146d3b3SDamjan Jovanovic    jne copyStack
163*b146d3b3SDamjan Jovanovic
164*b146d3b3SDamjan Jovanovic    ; First 4 args are passed in registers. Floating point args needs to be
165*b146d3b3SDamjan Jovanovic    ; in floating point registers, but those are free for us to clobber
166*b146d3b3SDamjan Jovanovic    ; anyway, and the callee knows where to look, so put each arg in both
167*b146d3b3SDamjan Jovanovic    ; its general purpose and its floating point register:
168*b146d3b3SDamjan Jovanovic    mov rcx, [rsp]
169*b146d3b3SDamjan Jovanovic    movsd xmm0, qword ptr [rsp]
170*b146d3b3SDamjan Jovanovic    mov rdx, 8[rsp]
171*b146d3b3SDamjan Jovanovic    movsd xmm1, qword ptr 8[rsp]
172*b146d3b3SDamjan Jovanovic    mov r8, 16[rsp]
173*b146d3b3SDamjan Jovanovic    movsd xmm2, qword ptr 16[rsp]
174*b146d3b3SDamjan Jovanovic    mov r9, 24[rsp]
175*b146d3b3SDamjan Jovanovic    movsd xmm3, qword ptr 24[rsp]
176*b146d3b3SDamjan Jovanovic    jmp callMethod
177*b146d3b3SDamjan Jovanovic
178*b146d3b3SDamjan JovanovicstackIsEmpty:
179*b146d3b3SDamjan Jovanovic    sub rsp, 32       ; we still need shadow space
180*b146d3b3SDamjan Jovanovic
181*b146d3b3SDamjan JovanoviccallMethod:
182*b146d3b3SDamjan Jovanovic    ; Find the method pointer
183*b146d3b3SDamjan Jovanovic    mov rax, 16[rbp]
184*b146d3b3SDamjan Jovanovic    mov r10, [rax]    ; pointer to vtable
185*b146d3b3SDamjan Jovanovic    mov r11d, 24[rbp]
186*b146d3b3SDamjan Jovanovic    shl r11, 3        ; sizeof(void*) == 8
187*b146d3b3SDamjan Jovanovic    add r10, r11
188*b146d3b3SDamjan Jovanovic    call qword ptr [r10]
189*b146d3b3SDamjan Jovanovic
190*b146d3b3SDamjan Jovanovic    mov r10d, 40[rbp]
191*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_VOID
192*b146d3b3SDamjan Jovanovic    je cleanup
193*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_LONG
194*b146d3b3SDamjan Jovanovic    je Lint32
195*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_UNSIGNED_LONG
196*b146d3b3SDamjan Jovanovic    je Lint32
197*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_ENUM
198*b146d3b3SDamjan Jovanovic    je Lint32
199*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_BOOLEAN
200*b146d3b3SDamjan Jovanovic    je Lint8
201*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_BYTE
202*b146d3b3SDamjan Jovanovic    je Lint8
203*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_CHAR
204*b146d3b3SDamjan Jovanovic    je Lint16
205*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_SHORT
206*b146d3b3SDamjan Jovanovic    je Lint16
207*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_UNSIGNED_SHORT
208*b146d3b3SDamjan Jovanovic    je Lint16
209*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_FLOAT
210*b146d3b3SDamjan Jovanovic    je Lfloat
211*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_DOUBLE
212*b146d3b3SDamjan Jovanovic    je Lfloat
213*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_HYPER
214*b146d3b3SDamjan Jovanovic    je Lint64
215*b146d3b3SDamjan Jovanovic    cmp r10, typelib_TypeClass_UNSIGNED_HYPER
216*b146d3b3SDamjan Jovanovic    je Lint64
217*b146d3b3SDamjan Jovanovic
218*b146d3b3SDamjan Jovanovic    ; https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
219*b146d3b3SDamjan Jovanovic    ; "The same pointer must be returned by the callee in RAX."
220*b146d3b3SDamjan Jovanovic    jmp Lint64
221*b146d3b3SDamjan Jovanovic
222*b146d3b3SDamjan JovanovicLint64:
223*b146d3b3SDamjan Jovanovic    mov 32[rbp], rax
224*b146d3b3SDamjan Jovanovic    jmp cleanup
225*b146d3b3SDamjan Jovanovic
226*b146d3b3SDamjan JovanovicLint32:
227*b146d3b3SDamjan Jovanovic    mov 32[rbp], eax
228*b146d3b3SDamjan Jovanovic    jmp cleanup
229*b146d3b3SDamjan Jovanovic
230*b146d3b3SDamjan JovanovicLint16:
231*b146d3b3SDamjan Jovanovic    mov 32[rbp], ax
232*b146d3b3SDamjan Jovanovic    jmp cleanup
233*b146d3b3SDamjan Jovanovic
234*b146d3b3SDamjan JovanovicLint8:
235*b146d3b3SDamjan Jovanovic    mov 32[rbp], al
236*b146d3b3SDamjan Jovanovic    jmp cleanup
237*b146d3b3SDamjan Jovanovic
238*b146d3b3SDamjan JovanovicLfloat:
239*b146d3b3SDamjan Jovanovic    movsd qword ptr 32[rbp], xmm0
240*b146d3b3SDamjan Jovanovic    jmp cleanup
241*b146d3b3SDamjan Jovanovic
242*b146d3b3SDamjan Jovanoviccleanup:
243*b146d3b3SDamjan Jovanovic    leave
244*b146d3b3SDamjan Jovanovic    ret
245*b146d3b3SDamjan Jovanovic
246*b146d3b3SDamjan JovanoviccallVirtualMethod ENDP
247*b146d3b3SDamjan Jovanovic
248*b146d3b3SDamjan Jovanovic
249*b146d3b3SDamjan JovanovicEND
250