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