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