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// unsigned char *pStack, // x4: packed overflow-argument bytes 36// sal_uInt32 nStackBytes, // x5: byte count 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 .cfi_offset x19, -32 55 .cfi_offset x20, -24 56 .cfi_offset x21, -48 57 .cfi_offset x22, -40 58 .cfi_offset x23, -64 59 .cfi_offset x24, -56 60 61 // stash inputs that must survive the call into callee-saved registers 62 mov x19, x0 // pFunction 63 mov x20, x2 // pGPR 64 mov x21, x3 // pFPR 65 mov x22, x6 // pGPRReturn 66 mov x23, x7 // pFPRReturn 67 mov x24, x1 // x8 indirect-result value 68 69 // allocate and copy the outgoing overflow stack arguments. 70 // Round the packed byte area up to preserve 16-byte SP alignment. 71 add x9, x5, #15 72 bic x9, x9, #15 73 sub sp, sp, x9 74 mov x10, #0 75Lcvf_copy: 76 cmp x10, x5 77 b.ge Lcvf_copied 78 ldrb w11, [x4, x10] 79 strb w11, [sp, x10] 80 add x10, x10, #1 81 b Lcvf_copy 82Lcvf_copied: 83 84 // load the FP/SIMD argument registers d0..d7 85 ldp d0, d1, [x21, #0] 86 ldp d2, d3, [x21, #16] 87 ldp d4, d5, [x21, #32] 88 ldp d6, d7, [x21, #48] 89 90 // load the GP argument registers x0..x7 and the x8 indirect-result reg 91 mov x8, x24 92 ldp x6, x7, [x20, #48] 93 ldp x4, x5, [x20, #32] 94 ldp x2, x3, [x20, #16] 95 ldp x0, x1, [x20, #0] 96 97 // perform the virtual call 98 blr x19 99 100 // store the return registers 101 str x0, [x22, #0] 102 str x1, [x22, #8] 103 str d0, [x23, #0] 104 str d1, [x23, #8] 105 str d2, [x23, #16] 106 str d3, [x23, #24] 107 108 // epilogue 109 mov sp, x29 110 ldp x23, x24, [sp], #16 111 ldp x21, x22, [sp], #16 112 ldp x19, x20, [sp], #16 113 ldp x29, x30, [sp], #16 114 ret 115 .cfi_endproc 116 117// --------------------------------------------------------------------------- 118// privateSnippetExecutor: the incoming (cpp2uno) register-spill executor. 119// 120// Reached by a BR from a per-vtable-slot code snippet (see codeSnippet() in 121// cpp2uno.cxx) with: 122// x16 = (nVtableOffset << 32) | nFunctionIndex (low bit 0x80000000 flags a 123// hidden/indirect return) 124// x0..x7, d0..d7, x8 = the original incoming arguments (untouched) 125// sp = the caller's stack-argument area (overflow) 126// x30 = return address back into the original C++ caller 127// 128// It spills the argument registers to a save area and calls cpp_vtable_call, 129// then loads the return value back into x0/x1 and d0/d1 (or d0 for fp). 130// 131// typelib_TypeClass cpp_vtable_call( 132// sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, 133// void** gpreg, void** fpreg, void** ovrflw, 134// void* pIndirectReturn, sal_uInt64* pRegisterReturn); 135// 136// Frame (176 bytes): [0]=x29,x30 [16..79]=x0..x7 [80..143]=d0..d7 137// [144..175]=return buffer (up to four HFA doubles). 138 .globl _privateSnippetExecutor 139 .p2align 2 140_privateSnippetExecutor: 141 .cfi_startproc 142 mov x17, sp // x17 = ovrflw (incoming stack args) 143 stp x29, x30, [sp, #-176]! 144 mov x29, sp 145 .cfi_def_cfa x29, 176 146 .cfi_offset x29, -176 147 .cfi_offset x30, -168 148 149 stp x0, x1, [sp, #16] // save GP argument registers x0..x7 150 stp x2, x3, [sp, #32] 151 stp x4, x5, [sp, #48] 152 stp x6, x7, [sp, #64] 153 154 stp d0, d1, [sp, #80] // save FP/SIMD argument registers d0..d7 155 stp d2, d3, [sp, #96] 156 stp d4, d5, [sp, #112] 157 stp d6, d7, [sp, #128] 158 159 mov w0, w16 // nFunctionIndex (low 32 bits) 160 lsr x1, x16, #32 // nVtableOffset (high 32 bits) 161 add x2, sp, #16 // gpreg 162 add x3, sp, #80 // fpreg 163 mov x4, x17 // ovrflw 164 mov x5, x8 // pIndirectReturn (x8 indirect-result reg) 165 add x6, sp, #144 // pRegisterReturn (32-byte buffer) 166 bl _cpp_vtable_call 167 168 cmp w0, #0x100 // RETURN_KIND_HFA_FLOAT 169 b.eq Lpse_hfa_float 170 cmp w0, #0x101 // RETURN_KIND_HFA_DOUBLE 171 b.eq Lpse_hfa_double 172 cmp w0, #10 // typelib_TypeClass_FLOAT 173 b.eq Lpse_float 174 cmp w0, #11 // typelib_TypeClass_DOUBLE 175 b.eq Lpse_float 176 cmp w0, #3 // typelib_TypeClass_BYTE 177 b.eq Lpse_signed_byte 178 cmp w0, #4 // typelib_TypeClass_SHORT 179 b.eq Lpse_signed_short 180 cmp w0, #1 // typelib_TypeClass_CHAR 181 b.eq Lpse_unsigned_short 182 cmp w0, #5 // typelib_TypeClass_UNSIGNED_SHORT 183 b.eq Lpse_unsigned_short 184 cmp w0, #2 // typelib_TypeClass_BOOLEAN 185 b.eq Lpse_unsigned_byte 186 cmp w0, #6 // typelib_TypeClass_LONG 187 b.eq Lpse_word 188 cmp w0, #7 // typelib_TypeClass_UNSIGNED_LONG 189 b.eq Lpse_word 190 cmp w0, #15 // typelib_TypeClass_ENUM 191 b.eq Lpse_word 192 // Integer / pointer / <=16B aggregate. 193 ldp x0, x1, [sp, #144] 194 b Lpse_done 195Lpse_float: 196 ldr d0, [sp, #144] 197 b Lpse_done 198Lpse_hfa_float: 199 ldr s0, [sp, #144] 200 ldr s1, [sp, #148] 201 ldr s2, [sp, #152] 202 ldr s3, [sp, #156] 203 b Lpse_done 204Lpse_hfa_double: 205 ldp d0, d1, [sp, #144] 206 ldp d2, d3, [sp, #160] 207 b Lpse_done 208Lpse_signed_byte: 209 ldrsb w0, [sp, #144] 210 b Lpse_done 211Lpse_unsigned_byte: 212 ldrb w0, [sp, #144] 213 b Lpse_done 214Lpse_signed_short: 215 ldrsh w0, [sp, #144] 216 b Lpse_done 217Lpse_unsigned_short: 218 ldrh w0, [sp, #144] 219 b Lpse_done 220Lpse_word: 221 ldr w0, [sp, #144] 222Lpse_done: 223 mov sp, x29 224 ldp x29, x30, [sp], #176 225 ret 226 .cfi_endproc 227