xref: /trunk/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/call.s (revision 9c15e1abd703a7953928d7a80655ae1a76a41f6d)
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