xref: /AOO42X/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/call.s (revision a230972184deb427a995e0eb922a5743673d1d16)
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