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 21*9c15e1abSPedro Giffuni #ifndef _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_ 22*9c15e1abSPedro Giffuni #define _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_ 23*9c15e1abSPedro Giffuni 24*9c15e1abSPedro Giffuni // This is an implementation of the AArch64 procedure call standard, as 25*9c15e1abSPedro Giffuni // described in "Procedure Call Standard for the Arm 64-bit Architecture" 26*9c15e1abSPedro Giffuni // (ARM IHI 0055). It is a clean-room implementation written from that 27*9c15e1abSPedro Giffuni // public specification; see ../../../../AAPCS64_BRIDGE_SPEC.md. 28*9c15e1abSPedro Giffuni 29*9c15e1abSPedro Giffuni #include <typelib/typedescription.hxx> 30*9c15e1abSPedro Giffuni 31*9c15e1abSPedro Giffuni namespace aarch64 32*9c15e1abSPedro Giffuni { 33*9c15e1abSPedro Giffuni 34*9c15e1abSPedro Giffuni /* 8 general purpose registers (x0..x7) are used for parameter passing. 35*9c15e1abSPedro Giffuni Note: the indirect-result-location register x8 is *separate* and is NOT 36*9c15e1abSPedro Giffuni part of this count. */ 37*9c15e1abSPedro Giffuni const sal_uInt32 MAX_GPR_REGS = 8; 38*9c15e1abSPedro Giffuni 39*9c15e1abSPedro Giffuni /* 8 SIMD/FP registers (v0..v7) are used for parameter passing. */ 40*9c15e1abSPedro Giffuni const sal_uInt32 MAX_FPR_REGS = 8; 41*9c15e1abSPedro Giffuni 42*9c15e1abSPedro Giffuni /* The largest number of registers a single aggregate can occupy: an HFA/HVA 43*9c15e1abSPedro Giffuni may use up to 4 FP registers; a non-HFA aggregate passed in GPRs uses at 44*9c15e1abSPedro Giffuni most 2 (16 bytes / 8). */ 45*9c15e1abSPedro Giffuni const sal_uInt32 MAX_AGGREGATE_REGS = 4; 46*9c15e1abSPedro Giffuni 47*9c15e1abSPedro Giffuni enum ReturnKind 48*9c15e1abSPedro Giffuni { 49*9c15e1abSPedro Giffuni RETURN_KIND_HFA_FLOAT = 0x100, 50*9c15e1abSPedro Giffuni RETURN_KIND_HFA_DOUBLE = 0x101 51*9c15e1abSPedro Giffuni }; 52*9c15e1abSPedro Giffuni 53*9c15e1abSPedro Giffuni /* Count the number of registers required to pass the given type. 54*9c15e1abSPedro Giffuni 55*9c15e1abSPedro Giffuni Examines the argument and sets the number of GPR (x) and FPR (v) registers 56*9c15e1abSPedro Giffuni it would consume. For a Homogeneous Floating-point Aggregate the FPR count 57*9c15e1abSPedro Giffuni is the number of members (<= 4); for a non-HFA aggregate <= 16 bytes the GPR 58*9c15e1abSPedro Giffuni count is 1 or 2; scalars use exactly one register of the appropriate bank. 59*9c15e1abSPedro Giffuni 60*9c15e1abSPedro Giffuni Returns false iff the parameter must be passed indirectly (in memory): a 61*9c15e1abSPedro Giffuni non-HFA aggregate larger than 16 bytes. When bInReturn is true the same 62*9c15e1abSPedro Giffuni classification answers "can this be returned in registers?" (false => the 63*9c15e1abSPedro Giffuni caller must allocate a buffer and pass it in x8). 64*9c15e1abSPedro Giffuni */ 65*9c15e1abSPedro Giffuni bool examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedFPR ); 66*9c15e1abSPedro Giffuni 67*9c15e1abSPedro Giffuni /** Does a function returning this type use the hidden indirect-result pointer 68*9c15e1abSPedro Giffuni (passed by the caller in x8), or can it return in registers? 69*9c15e1abSPedro Giffuni 70*9c15e1abSPedro Giffuni A scalar returns in x0 or v0; an HFA returns in v0..v3; a non-HFA aggregate 71*9c15e1abSPedro Giffuni of <= 16 bytes returns in x0,x1. Anything larger (non-HFA aggregate 72*9c15e1abSPedro Giffuni > 16 bytes) is returned via the caller-allocated buffer addressed by x8 - 73*9c15e1abSPedro Giffuni that is the "hidden param" case, for which this returns true. 74*9c15e1abSPedro Giffuni */ 75*9c15e1abSPedro Giffuni bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ); 76*9c15e1abSPedro Giffuni 77*9c15e1abSPedro Giffuni /** Return the assembly return kind for an HFA, or the type class otherwise. */ 78*9c15e1abSPedro Giffuni sal_uInt32 get_return_kind( typelib_TypeDescriptionReference *pTypeRef ); 79*9c15e1abSPedro Giffuni 80*9c15e1abSPedro Giffuni /** Scatter a register-resident return value (an HFA returned in v0..v3, or a 81*9c15e1abSPedro Giffuni non-HFA aggregate <= 16 bytes returned in x0,x1) into the caller's struct. 82*9c15e1abSPedro Giffuni 83*9c15e1abSPedro Giffuni pGPR points at the saved x0,x1,... ; pFPR at the saved v0,v1,... (each 84*9c15e1abSPedro Giffuni element the low 8 bytes of a v register, i.e. a double slot). Only valid 85*9c15e1abSPedro Giffuni when return_in_hidden_param() is false. 86*9c15e1abSPedro Giffuni */ 87*9c15e1abSPedro Giffuni void fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64* pGPR, const double* pFPR, void *pStruct ); 88*9c15e1abSPedro Giffuni 89*9c15e1abSPedro Giffuni sal_uInt32 align_stack_offset( 90*9c15e1abSPedro Giffuni sal_uInt32 offset, typelib_TypeDescriptionReference *pTypeRef ); 91*9c15e1abSPedro Giffuni 92*9c15e1abSPedro Giffuni sal_uInt32 stack_size( typelib_TypeDescriptionReference *pTypeRef ); 93*9c15e1abSPedro Giffuni 94*9c15e1abSPedro Giffuni } // namespace aarch64 95*9c15e1abSPedro Giffuni 96*9c15e1abSPedro Giffuni #endif // _BRIDGES_CPP_UNO_AARCH64_ABI_HXX_ 97