xref: /trunk/main/bridges/source/cpp_uno/gcc3_freebsd_aarch64/abi.hxx (revision 9c15e1abd703a7953928d7a80655ae1a76a41f6d)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 
21 #ifndef _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_
22 #define _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_
23 
24 // This is an implementation of the AArch64 procedure call standard, as
25 // described in "Procedure Call Standard for the Arm 64-bit Architecture"
26 // (ARM IHI 0055). It is a clean-room implementation written from that
27 // public specification; see ../../../../AAPCS64_BRIDGE_SPEC.md.
28 
29 #include <typelib/typedescription.hxx>
30 
31 namespace aarch64
32 {
33 
34 /* 8 general purpose registers (x0..x7) are used for parameter passing.
35    Note: the indirect-result-location register x8 is *separate* and is NOT
36    part of this count. */
37 const sal_uInt32 MAX_GPR_REGS = 8;
38 
39 /* 8 SIMD/FP registers (v0..v7) are used for parameter passing. */
40 const sal_uInt32 MAX_FPR_REGS = 8;
41 
42 /* The largest number of registers a single aggregate can occupy: an HFA/HVA
43    may use up to 4 FP registers; a non-HFA aggregate passed in GPRs uses at
44    most 2 (16 bytes / 8). */
45 const sal_uInt32 MAX_AGGREGATE_REGS = 4;
46 
47 enum ReturnKind
48 {
49     RETURN_KIND_HFA_FLOAT = 0x100,
50     RETURN_KIND_HFA_DOUBLE = 0x101
51 };
52 
53 /* Count the number of registers required to pass the given type.
54 
55    Examines the argument and sets the number of GPR (x) and FPR (v) registers
56    it would consume.  For a Homogeneous Floating-point Aggregate the FPR count
57    is the number of members (<= 4); for a non-HFA aggregate <= 16 bytes the GPR
58    count is 1 or 2; scalars use exactly one register of the appropriate bank.
59 
60    Returns false iff the parameter must be passed indirectly (in memory): a
61    non-HFA aggregate larger than 16 bytes.  When bInReturn is true the same
62    classification answers "can this be returned in registers?" (false => the
63    caller must allocate a buffer and pass it in x8).
64 */
65 bool examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedFPR );
66 
67 /** Does a function returning this type use the hidden indirect-result pointer
68     (passed by the caller in x8), or can it return in registers?
69 
70     A scalar returns in x0 or v0; an HFA returns in v0..v3; a non-HFA aggregate
71     of <= 16 bytes returns in x0,x1.  Anything larger (non-HFA aggregate
72     > 16 bytes) is returned via the caller-allocated buffer addressed by x8 -
73     that is the "hidden param" case, for which this returns true.
74 */
75 bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef );
76 
77 /** Return the assembly return kind for an HFA, or the type class otherwise. */
78 sal_uInt32 get_return_kind( typelib_TypeDescriptionReference *pTypeRef );
79 
80 /** Scatter a register-resident return value (an HFA returned in v0..v3, or a
81     non-HFA aggregate <= 16 bytes returned in x0,x1) into the caller's struct.
82 
83     pGPR points at the saved x0,x1,... ; pFPR at the saved v0,v1,... (each
84     element the low 8 bytes of a v register, i.e. a double slot).  Only valid
85     when return_in_hidden_param() is false.
86 */
87 void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64* pGPR, const double* pFPR, void *pStruct );
88 
89 sal_uInt32 align_stack_offset(
90     sal_uInt32 offset, typelib_TypeDescriptionReference *pTypeRef );
91 
92 sal_uInt32 stack_size( typelib_TypeDescriptionReference *pTypeRef );
93 
94 } // namespace aarch64
95 
96 #endif // _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_
97