1*9c15e1abSPedro Giffuni/* 2*9c15e1abSPedro Giffuni * Licensed to the Apache Software Foundation (ASF) under one 3*9c15e1abSPedro Giffuni * or more contributor license agreements. See the NOTICE file 4*9c15e1abSPedro Giffuni * distributed with this work for additional information 5*9c15e1abSPedro Giffuni * regarding copyright ownership. The ASF licenses this file 6*9c15e1abSPedro Giffuni * to you under the Apache License, Version 2.0 (the 7*9c15e1abSPedro Giffuni * "License"); you may not use this file except in compliance 8*9c15e1abSPedro Giffuni * with the License. You may obtain a copy of the License at 9*9c15e1abSPedro Giffuni * 10*9c15e1abSPedro Giffuni * http://www.apache.org/licenses/LICENSE-2.0 11*9c15e1abSPedro Giffuni * 12*9c15e1abSPedro Giffuni * Unless required by applicable law or agreed to in writing, 13*9c15e1abSPedro Giffuni * software distributed under the License is distributed on an 14*9c15e1abSPedro Giffuni * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15*9c15e1abSPedro Giffuni * KIND, either express or implied. See the License for the 16*9c15e1abSPedro Giffuni * specific language governing permissions and limitations 17*9c15e1abSPedro Giffuni * under the License. 18*9c15e1abSPedro Giffuni */ 19*9c15e1abSPedro Giffuni 20*9c15e1abSPedro Giffuni// AArch64 (System V / FreeBSD) outgoing-call trampoline for the C++-UNO 21*9c15e1abSPedro Giffuni// bridge. Loads registers from caller-prepared arrays, copies overflow args 22*9c15e1abSPedro Giffuni// to the outgoing stack, performs the indirect call and stores return regs. 23*9c15e1abSPedro Giffuni 24*9c15e1abSPedro Giffuni .text 25*9c15e1abSPedro Giffuni .align 2 26*9c15e1abSPedro Giffuni .globl callVirtualFunction 27*9c15e1abSPedro Giffuni .type callVirtualFunction, @function 28*9c15e1abSPedro GiffunicallVirtualFunction: 29*9c15e1abSPedro Giffuni .cfi_startproc 30*9c15e1abSPedro Giffuni // prologue: save fp/lr and the callee-saved registers we use 31*9c15e1abSPedro Giffuni stp x29, x30, [sp, #-16]! 32*9c15e1abSPedro Giffuni stp x19, x20, [sp, #-16]! 33*9c15e1abSPedro Giffuni stp x21, x22, [sp, #-16]! 34*9c15e1abSPedro Giffuni stp x23, x24, [sp, #-16]! 35*9c15e1abSPedro Giffuni mov x29, sp 36*9c15e1abSPedro Giffuni .cfi_def_cfa x29, 64 37*9c15e1abSPedro Giffuni .cfi_offset x29, -16 38*9c15e1abSPedro Giffuni .cfi_offset x30, -8 39*9c15e1abSPedro Giffuni .cfi_offset x19, -32 40*9c15e1abSPedro Giffuni .cfi_offset x20, -24 41*9c15e1abSPedro Giffuni .cfi_offset x21, -48 42*9c15e1abSPedro Giffuni .cfi_offset x22, -40 43*9c15e1abSPedro Giffuni .cfi_offset x23, -64 44*9c15e1abSPedro Giffuni .cfi_offset x24, -56 45*9c15e1abSPedro Giffuni 46*9c15e1abSPedro Giffuni // stash inputs that must survive the call into callee-saved registers 47*9c15e1abSPedro Giffuni mov x19, x0 // pFunction 48*9c15e1abSPedro Giffuni mov x20, x2 // pGPR 49*9c15e1abSPedro Giffuni mov x21, x3 // pFPR 50*9c15e1abSPedro Giffuni mov x22, x6 // pGPRReturn 51*9c15e1abSPedro Giffuni mov x23, x7 // pFPRReturn 52*9c15e1abSPedro Giffuni mov x24, x1 // x8 indirect-result value 53*9c15e1abSPedro Giffuni 54*9c15e1abSPedro Giffuni // allocate and copy the outgoing overflow stack arguments. 55*9c15e1abSPedro Giffuni add x9, x5, #15 56*9c15e1abSPedro Giffuni bic x9, x9, #15 57*9c15e1abSPedro Giffuni sub sp, sp, x9 58*9c15e1abSPedro Giffuni mov x10, #0 59*9c15e1abSPedro GiffuniLcvf_copy: 60*9c15e1abSPedro Giffuni cmp x10, x5 61*9c15e1abSPedro Giffuni b.ge Lcvf_copied 62*9c15e1abSPedro Giffuni ldrb w11, [x4, x10] 63*9c15e1abSPedro Giffuni strb w11, [sp, x10] 64*9c15e1abSPedro Giffuni add x10, x10, #1 65*9c15e1abSPedro Giffuni b Lcvf_copy 66*9c15e1abSPedro GiffuniLcvf_copied: 67*9c15e1abSPedro Giffuni 68*9c15e1abSPedro Giffuni // load the FP/SIMD argument registers d0..d7 69*9c15e1abSPedro Giffuni ldp d0, d1, [x21, #0] 70*9c15e1abSPedro Giffuni ldp d2, d3, [x21, #16] 71*9c15e1abSPedro Giffuni ldp d4, d5, [x21, #32] 72*9c15e1abSPedro Giffuni ldp d6, d7, [x21, #48] 73*9c15e1abSPedro Giffuni 74*9c15e1abSPedro Giffuni // load the GP argument registers x0..x7 and the x8 indirect-result reg 75*9c15e1abSPedro Giffuni mov x8, x24 76*9c15e1abSPedro Giffuni ldp x6, x7, [x20, #48] 77*9c15e1abSPedro Giffuni ldp x4, x5, [x20, #32] 78*9c15e1abSPedro Giffuni ldp x2, x3, [x20, #16] 79*9c15e1abSPedro Giffuni ldp x0, x1, [x20, #0] 80*9c15e1abSPedro Giffuni 81*9c15e1abSPedro Giffuni // perform the virtual call 82*9c15e1abSPedro Giffuni blr x19 83*9c15e1abSPedro Giffuni 84*9c15e1abSPedro Giffuni // store the return registers 85*9c15e1abSPedro Giffuni str x0, [x22, #0] 86*9c15e1abSPedro Giffuni str x1, [x22, #8] 87*9c15e1abSPedro Giffuni str d0, [x23, #0] 88*9c15e1abSPedro Giffuni str d1, [x23, #8] 89*9c15e1abSPedro Giffuni str d2, [x23, #16] 90*9c15e1abSPedro Giffuni str d3, [x23, #24] 91*9c15e1abSPedro Giffuni 92*9c15e1abSPedro Giffuni // epilogue 93*9c15e1abSPedro Giffuni mov sp, x29 94*9c15e1abSPedro Giffuni ldp x23, x24, [sp], #16 95*9c15e1abSPedro Giffuni ldp x21, x22, [sp], #16 96*9c15e1abSPedro Giffuni ldp x19, x20, [sp], #16 97*9c15e1abSPedro Giffuni ldp x29, x30, [sp], #16 98*9c15e1abSPedro Giffuni ret 99*9c15e1abSPedro Giffuni .cfi_endproc 100*9c15e1abSPedro Giffuni 101*9c15e1abSPedro Giffuni// --------------------------------------------------------------------------- 102*9c15e1abSPedro Giffuni// privateSnippetExecutor: incoming (cpp2uno) register-spill executor. 103*9c15e1abSPedro Giffuni 104*9c15e1abSPedro Giffuni .globl privateSnippetExecutor 105*9c15e1abSPedro Giffuni .type privateSnippetExecutor, @function 106*9c15e1abSPedro GiffuniprivateSnippetExecutor: 107*9c15e1abSPedro Giffuni .cfi_startproc 108*9c15e1abSPedro Giffuni mov x17, sp // x17 = ovrflw (incoming stack args) 109*9c15e1abSPedro Giffuni stp x29, x30, [sp, #-176]! 110*9c15e1abSPedro Giffuni mov x29, sp 111*9c15e1abSPedro Giffuni .cfi_def_cfa x29, 176 112*9c15e1abSPedro Giffuni .cfi_offset x29, -176 113*9c15e1abSPedro Giffuni .cfi_offset x30, -168 114*9c15e1abSPedro Giffuni 115*9c15e1abSPedro Giffuni stp x0, x1, [sp, #16] // save GP argument registers x0..x7 116*9c15e1abSPedro Giffuni stp x2, x3, [sp, #32] 117*9c15e1abSPedro Giffuni stp x4, x5, [sp, #48] 118*9c15e1abSPedro Giffuni stp x6, x7, [sp, #64] 119*9c15e1abSPedro Giffuni 120*9c15e1abSPedro Giffuni stp d0, d1, [sp, #80] // save FP/SIMD argument registers d0..d7 121*9c15e1abSPedro Giffuni stp d2, d3, [sp, #96] 122*9c15e1abSPedro Giffuni stp d4, d5, [sp, #112] 123*9c15e1abSPedro Giffuni stp d6, d7, [sp, #128] 124*9c15e1abSPedro Giffuni 125*9c15e1abSPedro Giffuni mov w0, w16 // nFunctionIndex (low 32 bits) 126*9c15e1abSPedro Giffuni lsr x1, x16, #32 // nVtableOffset (high 32 bits) 127*9c15e1abSPedro Giffuni add x2, sp, #16 // gpreg 128*9c15e1abSPedro Giffuni add x3, sp, #80 // fpreg 129*9c15e1abSPedro Giffuni mov x4, x17 // ovrflw 130*9c15e1abSPedro Giffuni mov x5, x8 // pIndirectReturn (x8 indirect-result reg) 131*9c15e1abSPedro Giffuni add x6, sp, #144 // pRegisterReturn (32-byte buffer) 132*9c15e1abSPedro Giffuni bl cpp_vtable_call 133*9c15e1abSPedro Giffuni 134*9c15e1abSPedro Giffuni cmp w0, #0x100 // RETURN_KIND_HFA_FLOAT 135*9c15e1abSPedro Giffuni b.eq Lpse_hfa_float 136*9c15e1abSPedro Giffuni cmp w0, #0x101 // RETURN_KIND_HFA_DOUBLE 137*9c15e1abSPedro Giffuni b.eq Lpse_hfa_double 138*9c15e1abSPedro Giffuni cmp w0, #10 // typelib_TypeClass_FLOAT 139*9c15e1abSPedro Giffuni b.eq Lpse_float 140*9c15e1abSPedro Giffuni cmp w0, #11 // typelib_TypeClass_DOUBLE 141*9c15e1abSPedro Giffuni b.eq Lpse_float 142*9c15e1abSPedro Giffuni cmp w0, #3 // typelib_TypeClass_BYTE 143*9c15e1abSPedro Giffuni b.eq Lpse_signed_byte 144*9c15e1abSPedro Giffuni cmp w0, #4 // typelib_TypeClass_SHORT 145*9c15e1abSPedro Giffuni b.eq Lpse_signed_short 146*9c15e1abSPedro Giffuni cmp w0, #1 // typelib_TypeClass_VOID 147*9c15e1abSPedro Giffuni b.eq Lpse_void 148*9c15e1abSPedro Giffuni 149*9c15e1abSPedro Giffuni // integer / pointer return 150*9c15e1abSPedro Giffuni ldr x0, [x6, #0] 151*9c15e1abSPedro Giffuni ldr x1, [x6, #8] 152*9c15e1abSPedro Giffuni ldr d0, [x6, #16] 153*9c15e1abSPedro Giffuni ldr d1, [x6, #24] 154*9c15e1abSPedro Giffuni b Lpse_finish 155*9c15e1abSPedro Giffuni 156*9c15e1abSPedro GiffuniLpse_hfa_float: 157*9c15e1abSPedro Giffuni // HFA float: up to 4 floats in d0..d3 158*9c15e1abSPedro Giffuni ldr d0, [x6, #0] 159*9c15e1abSPedro Giffuni ldr d1, [x6, #8] 160*9c15e1abSPedro Giffuni ldr d2, [x6, #16] 161*9c15e1abSPedro Giffuni ldr d3, [x6, #24] 162*9c15e1abSPedro Giffuni b Lpse_finish 163*9c15e1abSPedro Giffuni 164*9c15e1abSPedro GiffuniLpse_hfa_double: 165*9c15e1abSPedro Giffuni // HFA double: up to 4 doubles in d0..d3 166*9c15e1abSPedro Giffuni ldr d0, [x6, #0] 167*9c15e1abSPedro Giffuni ldr d1, [x6, #8] 168*9c15e1abSPedro Giffuni ldr d2, [x6, #16] 169*9c15e1abSPedro Giffuni ldr d3, [x6, #24] 170*9c15e1abSPedro Giffuni b Lpse_finish 171*9c15e1abSPedro Giffuni 172*9c15e1abSPedro GiffuniLpse_float: 173*9c15e1abSPedro Giffuni // single float/double returned in d0 174*9c15e1abSPedro Giffuni ldr d0, [x6, #16] 175*9c15e1abSPedro Giffuni b Lpse_finish 176*9c15e1abSPedro Giffuni 177*9c15e1abSPedro GiffuniLpse_signed_byte: 178*9c15e1abSPedro Giffuni ldr x0, [x6, #0] 179*9c15e1abSPedro Giffuni b Lpse_finish 180*9c15e1abSPedro Giffuni 181*9c15e1abSPedro GiffuniLpse_signed_short: 182*9c15e1abSPedro Giffuni ldr x0, [x6, #0] 183*9c15e1abSPedro Giffuni b Lpse_finish 184*9c15e1abSPedro Giffuni 185*9c15e1abSPedro GiffuniLpse_void: 186*9c15e1abSPedro Giffuni mov x0, #0 187*9c15e1abSPedro Giffuni b Lpse_finish 188*9c15e1abSPedro Giffuni 189*9c15e1abSPedro GiffuniLpse_finish: 190*9c15e1abSPedro Giffuni ldp x23, x24, [sp], #16 191*9c15e1abSPedro Giffuni ldp x21, x22, [sp], #16 192*9c15e1abSPedro Giffuni ldp x19, x20, [sp], #16 193*9c15e1abSPedro Giffuni ldp x29, x30, [sp], #16 194*9c15e1abSPedro Giffuni ret 195*9c15e1abSPedro Giffuni .cfi_endproc 196*9c15e1abSPedro Giffuni 197*9c15e1abSPedro Giffuni .section .note.GNU-stack,"",@progbits 198