1/************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22// AArch64 (Apple Silicon, AAPCS64) outgoing-call trampoline for the C++-UNO 23// bridge. Loads the argument registers from caller-prepared arrays, copies 24// any overflow arguments to the outgoing stack, performs the indirect call, 25// and stores the integer and FP/SIMD return registers back. 26// 27// See AAPCS64_BRIDGE_SPEC.md. Mach-O assembler syntax; symbols are prefixed 28// with an underscore per the Darwin C ABI. 29// 30// extern "C" void callVirtualFunction( 31// sal_uInt64 pFunction, // x0: target C++ virtual method 32// sal_uInt64 pIndirectRet, // x1: value for x8 (indirect result ptr), 0 if none 33// sal_uInt64 *pGPR, // x2: 8 words -> x0..x7 34// double *pFPR, // x3: 8 doubles -> d0..d7 35// sal_uInt64 *pStack, // x4: overflow-arg words 36// sal_uInt32 nStackWords, // x5: number of 8-byte overflow words 37// sal_uInt64 *pGPRReturn, // x6: [out] x0,x1 38// double *pFPRReturn); // x7: [out] d0..d3 (HFA up to 4 elements) 39 40 .text 41 .globl _callVirtualFunction 42 .p2align 2 43_callVirtualFunction: 44 .cfi_startproc 45 // prologue: save fp/lr and the callee-saved registers we use 46 stp x29, x30, [sp, #-16]! 47 stp x19, x20, [sp, #-16]! 48 stp x21, x22, [sp, #-16]! 49 stp x23, x24, [sp, #-16]! 50 mov x29, sp 51 .cfi_def_cfa x29, 64 52 .cfi_offset x29, -16 53 .cfi_offset x30, -8 54 55 // stash inputs that must survive the call into callee-saved registers 56 mov x19, x0 // pFunction 57 mov x20, x2 // pGPR 58 mov x21, x3 // pFPR 59 mov x22, x6 // pGPRReturn 60 mov x23, x7 // pFPRReturn 61 mov x24, x1 // x8 indirect-result value 62 63 // allocate and copy the outgoing overflow stack arguments. 64 // bytes = ((nStackWords + 1) & ~1) * 8, to keep sp 16-byte aligned. 65 add x9, x5, #1 66 bic x9, x9, #1 67 lsl x9, x9, #3 68 sub sp, sp, x9 69 mov x10, #0 70Lcvf_copy: 71 cmp x10, x5 72 b.ge Lcvf_copied 73 ldr x11, [x4, x10, lsl #3] 74 str x11, [sp, x10, lsl #3] 75 add x10, x10, #1 76 b Lcvf_copy 77Lcvf_copied: 78 79 // load the FP/SIMD argument registers d0..d7 80 ldp d0, d1, [x21, #0] 81 ldp d2, d3, [x21, #16] 82 ldp d4, d5, [x21, #32] 83 ldp d6, d7, [x21, #48] 84 85 // load the GP argument registers x0..x7 and the x8 indirect-result reg 86 mov x8, x24 87 ldp x6, x7, [x20, #48] 88 ldp x4, x5, [x20, #32] 89 ldp x2, x3, [x20, #16] 90 ldp x0, x1, [x20, #0] 91 92 // perform the virtual call 93 blr x19 94 95 // store the return registers 96 str x0, [x22, #0] 97 str x1, [x22, #8] 98 str d0, [x23, #0] 99 str d1, [x23, #8] 100 str d2, [x23, #16] 101 str d3, [x23, #24] 102 103 // epilogue 104 mov sp, x29 105 ldp x23, x24, [sp], #16 106 ldp x21, x22, [sp], #16 107 ldp x19, x20, [sp], #16 108 ldp x29, x30, [sp], #16 109 ret 110 .cfi_endproc 111 112// --------------------------------------------------------------------------- 113// privateSnippetExecutor: the incoming (cpp2uno) register-spill executor. 114// 115// Reached by a BR from a per-vtable-slot code snippet (see codeSnippet() in 116// cpp2uno.cxx) with: 117// x16 = (nVtableOffset << 32) | nFunctionIndex (low bit 0x80000000 flags a 118// hidden/indirect return) 119// x0..x7, d0..d7, x8 = the original incoming arguments (untouched) 120// sp = the caller's stack-argument area (overflow) 121// x30 = return address back into the original C++ caller 122// 123// It spills the argument registers to a save area and calls cpp_vtable_call, 124// then loads the return value back into x0/x1 and d0/d1 (or d0 for fp). 125// 126// typelib_TypeClass cpp_vtable_call( 127// sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, 128// void** gpreg, void** fpreg, void** ovrflw, 129// void* pIndirectReturn, sal_uInt64* pRegisterReturn); 130// 131// Frame (176 bytes): [0]=x29,x30 [16..79]=x0..x7 [80..143]=d0..d7 132// [144..175]=return buffer (up to four HFA doubles). 133 .globl _privateSnippetExecutor 134 .p2align 2 135_privateSnippetExecutor: 136 .cfi_startproc 137 mov x17, sp // x17 = ovrflw (incoming stack args) 138 stp x29, x30, [sp, #-176]! 139 mov x29, sp 140 .cfi_def_cfa x29, 176 141 .cfi_offset x29, -176 142 .cfi_offset x30, -168 143 144 stp x0, x1, [sp, #16] // save GP argument registers x0..x7 145 stp x2, x3, [sp, #32] 146 stp x4, x5, [sp, #48] 147 stp x6, x7, [sp, #64] 148 149 stp d0, d1, [sp, #80] // save FP/SIMD argument registers d0..d7 150 stp d2, d3, [sp, #96] 151 stp d4, d5, [sp, #112] 152 stp d6, d7, [sp, #128] 153 154 mov w0, w16 // nFunctionIndex (low 32 bits) 155 lsr x1, x16, #32 // nVtableOffset (high 32 bits) 156 add x2, sp, #16 // gpreg 157 add x3, sp, #80 // fpreg 158 mov x4, x17 // ovrflw 159 mov x5, x8 // pIndirectReturn (x8 indirect-result reg) 160 add x6, sp, #144 // pRegisterReturn (16-byte buffer) 161 bl _cpp_vtable_call 162 163 cmp w0, #0x100 // RETURN_KIND_HFA_FLOAT 164 b.eq Lpse_hfa_float 165 cmp w0, #0x101 // RETURN_KIND_HFA_DOUBLE 166 b.eq Lpse_hfa_double 167 cmp w0, #10 // typelib_TypeClass_FLOAT 168 b.eq Lpse_float 169 cmp w0, #11 // typelib_TypeClass_DOUBLE 170 b.eq Lpse_float 171 // integer / pointer / <=16B aggregate: load both banks; caller reads the 172 // ones that matter for its return type. 173 ldp x0, x1, [sp, #144] 174 ldp d0, d1, [sp, #144] 175 b Lpse_done 176Lpse_float: 177 ldr d0, [sp, #144] 178 b Lpse_done 179Lpse_hfa_float: 180 ldr s0, [sp, #144] 181 ldr s1, [sp, #148] 182 ldr s2, [sp, #152] 183 ldr s3, [sp, #156] 184 b Lpse_done 185Lpse_hfa_double: 186 ldp d0, d1, [sp, #144] 187 ldp d2, d3, [sp, #160] 188Lpse_done: 189 mov sp, x29 190 ldp x29, x30, [sp], #176 191 ret 192 .cfi_endproc 193