1d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* ----------------------------------------------------------------------- 246ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc. 3d4c9320412177895f598a93d73a0e654db27c351Thomas Heller Copyright (c) 2000 Hewlett Packard Company 446ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith Copyright (c) 2011 Anthony Green 5d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 6d4c9320412177895f598a93d73a0e654db27c351Thomas Heller IA64 Foreign Function Interface 7d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 8d4c9320412177895f598a93d73a0e654db27c351Thomas Heller Permission is hereby granted, free of charge, to any person obtaining 9d4c9320412177895f598a93d73a0e654db27c351Thomas Heller a copy of this software and associated documentation files (the 10d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ``Software''), to deal in the Software without restriction, including 11d4c9320412177895f598a93d73a0e654db27c351Thomas Heller without limitation the rights to use, copy, modify, merge, publish, 12d4c9320412177895f598a93d73a0e654db27c351Thomas Heller distribute, sublicense, and/or sell copies of the Software, and to 13d4c9320412177895f598a93d73a0e654db27c351Thomas Heller permit persons to whom the Software is furnished to do so, subject to 14d4c9320412177895f598a93d73a0e654db27c351Thomas Heller the following conditions: 15d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 16d4c9320412177895f598a93d73a0e654db27c351Thomas Heller The above copyright notice and this permission notice shall be included 17d4c9320412177895f598a93d73a0e654db27c351Thomas Heller in all copies or substantial portions of the Software. 18d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 198bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 208bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 218bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 228bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 238bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 248bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 258bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 268bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller DEALINGS IN THE SOFTWARE. 27d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ----------------------------------------------------------------------- */ 28d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 29d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <ffi.h> 30d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <ffi_common.h> 31d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 32d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <stdlib.h> 33d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <stdbool.h> 34d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <float.h> 35d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 36d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include "ia64_flags.h" 37d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 38d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* A 64-bit pointer value. In LP64 mode, this is effectively a plain 39d4c9320412177895f598a93d73a0e654db27c351Thomas Heller pointer. In ILP32 mode, it's a pointer that's been extended to 40d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 64 bits by "addp4". */ 41d4c9320412177895f598a93d73a0e654db27c351Thomas Hellertypedef void *PTR64 __attribute__((mode(DI))); 42d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 43d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Memory image of fp register contents. This is the implementation 44d4c9320412177895f598a93d73a0e654db27c351Thomas Heller specific format used by ldf.fill/stf.spill. All we care about is 45d4c9320412177895f598a93d73a0e654db27c351Thomas Heller that it wants a 16 byte aligned slot. */ 46d4c9320412177895f598a93d73a0e654db27c351Thomas Hellertypedef struct 47d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 48d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 x[2] __attribute__((aligned(16))); 49d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} fpreg; 50d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 51d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 52d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */ 53d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 54d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerstruct ia64_args 55d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 56d4c9320412177895f598a93d73a0e654db27c351Thomas Heller fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */ 57d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */ 58d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 other_args[]; /* Arguments passed on stack, variable size. */ 59d4c9320412177895f598a93d73a0e654db27c351Thomas Heller}; 60d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 61d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 62d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */ 63d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 64d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerstatic inline void * 65d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerendian_adjust (void *addr, size_t len) 66d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 67d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#ifdef __BIG_ENDIAN__ 68d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return addr + (8 - len); 69d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#else 70d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return addr; 71d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#endif 72d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 73d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 748bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller/* Store VALUE to ADDR in the current cpu implementation's fp spill format. 758bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller This is a macro instead of a function, so that it works for all 3 floating 768bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller point types without type conversions. Type conversion to long double breaks 778bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller the denorm support. */ 78d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 798bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller#define stf_spill(addr, value) \ 80d4c9320412177895f598a93d73a0e654db27c351Thomas Heller asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value)); 81d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 82d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Load a value from ADDR, which is in the current cpu implementation's 838bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller fp spill format. As above, this must also be a macro. */ 84d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 858bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller#define ldf_fill(result, addr) \ 868bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr)); 87d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 8846ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith/* Return the size of the C type associated with with TYPE. Which will 89d4c9320412177895f598a93d73a0e654db27c351Thomas Heller be one of the FFI_IA64_TYPE_HFA_* values. */ 90d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 91d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerstatic size_t 92d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerhfa_type_size (int type) 93d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 94d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch (type) 95d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 96d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_FLOAT: 97d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return sizeof(float); 98d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_DOUBLE: 99d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return sizeof(double); 100d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_LDOUBLE: 101d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return sizeof(__float80); 102d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 103d4c9320412177895f598a93d73a0e654db27c351Thomas Heller abort (); 104d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 105d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 106d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 107d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Load from ADDR a value indicated by TYPE. Which will be one of 108d4c9320412177895f598a93d73a0e654db27c351Thomas Heller the FFI_IA64_TYPE_HFA_* values. */ 109d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 1108bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Hellerstatic void 1118bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Hellerhfa_type_load (fpreg *fpaddr, int type, void *addr) 112d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 113d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch (type) 114d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 115d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_FLOAT: 1168bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller stf_spill (fpaddr, *(float *) addr); 1178bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller return; 118d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_DOUBLE: 1198bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller stf_spill (fpaddr, *(double *) addr); 1208bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller return; 121d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_LDOUBLE: 1228bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller stf_spill (fpaddr, *(__float80 *) addr); 1238bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller return; 124d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 125d4c9320412177895f598a93d73a0e654db27c351Thomas Heller abort (); 126d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 127d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 128d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 129d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Load VALUE into ADDR as indicated by TYPE. Which will be one of 130d4c9320412177895f598a93d73a0e654db27c351Thomas Heller the FFI_IA64_TYPE_HFA_* values. */ 131d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 132d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerstatic void 1338bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Hellerhfa_type_store (int type, void *addr, fpreg *fpaddr) 134d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 135d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch (type) 136d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 137d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_FLOAT: 1388bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller { 1398bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller float result; 1408bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ldf_fill (result, fpaddr); 1418bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller *(float *) addr = result; 1428bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller break; 1438bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller } 144d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_DOUBLE: 1458bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller { 1468bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller double result; 1478bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ldf_fill (result, fpaddr); 1488bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller *(double *) addr = result; 1498bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller break; 1508bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller } 151d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_IA64_TYPE_HFA_LDOUBLE: 1528bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller { 1538bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller __float80 result; 1548bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ldf_fill (result, fpaddr); 1558bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller *(__float80 *) addr = result; 1568bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller break; 1578bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller } 158d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 159d4c9320412177895f598a93d73a0e654db27c351Thomas Heller abort (); 160d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 161d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 162d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 163d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Is TYPE a struct containing floats, doubles, or extended doubles, 164d4c9320412177895f598a93d73a0e654db27c351Thomas Heller all of the same fp type? If so, return the element type. Return 165d4c9320412177895f598a93d73a0e654db27c351Thomas Heller FFI_TYPE_VOID if not. */ 166d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 167d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerstatic int 168d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerhfa_element_type (ffi_type *type, int nested) 169d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 170d4c9320412177895f598a93d73a0e654db27c351Thomas Heller int element = FFI_TYPE_VOID; 171d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 172d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch (type->type) 173d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 174d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_FLOAT: 175d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* We want to return VOID for raw floating-point types, but the 176d4c9320412177895f598a93d73a0e654db27c351Thomas Heller synthetic HFA type if we're nested within an aggregate. */ 177d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (nested) 178d4c9320412177895f598a93d73a0e654db27c351Thomas Heller element = FFI_IA64_TYPE_HFA_FLOAT; 179d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 180d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 181d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_DOUBLE: 182d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* Similarly. */ 183d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (nested) 184d4c9320412177895f598a93d73a0e654db27c351Thomas Heller element = FFI_IA64_TYPE_HFA_DOUBLE; 185d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 186d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 187d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_LONGDOUBLE: 18846ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith /* Similarly, except that that HFA is true for double extended, 189d4c9320412177895f598a93d73a0e654db27c351Thomas Heller but not quad precision. Both have sizeof == 16, so tell the 190d4c9320412177895f598a93d73a0e654db27c351Thomas Heller difference based on the precision. */ 191d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (LDBL_MANT_DIG == 64 && nested) 192d4c9320412177895f598a93d73a0e654db27c351Thomas Heller element = FFI_IA64_TYPE_HFA_LDOUBLE; 193d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 194d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 195d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_STRUCT: 196d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 197d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ffi_type **ptr = &type->elements[0]; 198d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 199d4c9320412177895f598a93d73a0e654db27c351Thomas Heller for (ptr = &type->elements[0]; *ptr ; ptr++) 200d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 201d4c9320412177895f598a93d73a0e654db27c351Thomas Heller int sub_element = hfa_element_type (*ptr, 1); 202d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (sub_element == FFI_TYPE_VOID) 203d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return FFI_TYPE_VOID; 204d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 205d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (element == FFI_TYPE_VOID) 206d4c9320412177895f598a93d73a0e654db27c351Thomas Heller element = sub_element; 207d4c9320412177895f598a93d73a0e654db27c351Thomas Heller else if (element != sub_element) 208d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return FFI_TYPE_VOID; 209d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 210d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 211d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 212d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 213d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 214d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return FFI_TYPE_VOID; 215d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 216d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 217d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return element; 218d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 219d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 220d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 221d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Perform machine dependent cif processing. */ 222d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 223d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerffi_status 224d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerffi_prep_cif_machdep(ffi_cif *cif) 225d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 226d4c9320412177895f598a93d73a0e654db27c351Thomas Heller int flags; 227d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 228d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* Adjust cif->bytes to include space for the bits of the ia64_args frame 22946ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith that precedes the integer register portion. The estimate that the 230d4c9320412177895f598a93d73a0e654db27c351Thomas Heller generic bits did for the argument space required is good enough for the 231d4c9320412177895f598a93d73a0e654db27c351Thomas Heller integer component. */ 232d4c9320412177895f598a93d73a0e654db27c351Thomas Heller cif->bytes += offsetof(struct ia64_args, gp_regs[0]); 233d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (cif->bytes < sizeof(struct ia64_args)) 234d4c9320412177895f598a93d73a0e654db27c351Thomas Heller cif->bytes = sizeof(struct ia64_args); 235d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 236d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* Set the return type flag. */ 237d4c9320412177895f598a93d73a0e654db27c351Thomas Heller flags = cif->rtype->type; 238d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch (cif->rtype->type) 239d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 240d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_LONGDOUBLE: 241d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision, 242d4c9320412177895f598a93d73a0e654db27c351Thomas Heller and encode quad precision as a two-word integer structure. */ 243d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (LDBL_MANT_DIG != 64) 244d4c9320412177895f598a93d73a0e654db27c351Thomas Heller flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8); 245d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 246d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 247d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_STRUCT: 248d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 249d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t size = cif->rtype->size; 250d4c9320412177895f598a93d73a0e654db27c351Thomas Heller int hfa_type = hfa_element_type (cif->rtype, 0); 251d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 252d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (hfa_type != FFI_TYPE_VOID) 253d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 254d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t nelts = size / hfa_type_size (hfa_type); 255d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (nelts <= 8) 256d4c9320412177895f598a93d73a0e654db27c351Thomas Heller flags = hfa_type | (size << 8); 257d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 258d4c9320412177895f598a93d73a0e654db27c351Thomas Heller else 259d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 260d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (size <= 32) 261d4c9320412177895f598a93d73a0e654db27c351Thomas Heller flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8); 262d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 263d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 264d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 265d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 266d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 267d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 268d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 269d4c9320412177895f598a93d73a0e654db27c351Thomas Heller cif->flags = flags; 270d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 271d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return FFI_OK; 272d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 273d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 274c740d834eee532f15c758c41fba08974cd300f9eNeal Norwitzextern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64); 275d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 276d4c9320412177895f598a93d73a0e654db27c351Thomas Hellervoid 277c740d834eee532f15c758c41fba08974cd300f9eNeal Norwitzffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 278d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 279d4c9320412177895f598a93d73a0e654db27c351Thomas Heller struct ia64_args *stack; 280d4c9320412177895f598a93d73a0e654db27c351Thomas Heller long i, avn, gpcount, fpcount; 281d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ffi_type **p_arg; 282d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 283d4c9320412177895f598a93d73a0e654db27c351Thomas Heller FFI_ASSERT (cif->abi == FFI_UNIX); 284d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 285d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* If we have no spot for a return value, make one. */ 286d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID) 287d4c9320412177895f598a93d73a0e654db27c351Thomas Heller rvalue = alloca (cif->rtype->size); 288d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 289d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* Allocate the stack frame. */ 290d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack = alloca (cif->bytes); 291d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 292d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount = fpcount = 0; 293d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avn = cif->nargs; 294d4c9320412177895f598a93d73a0e654db27c351Thomas Heller for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) 295d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 296d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch ((*p_arg)->type) 297d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 298d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT8: 299d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i]; 300d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 301d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT8: 302d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i]; 303d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 304d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT16: 305d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i]; 306d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 307d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT16: 308d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i]; 309d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 310d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT32: 311d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i]; 312d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 313d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT32: 314d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i]; 315d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 316d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT64: 317d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT64: 318d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i]; 319d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 320d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 321d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_POINTER: 322d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i]; 323d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 324d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 325d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_FLOAT: 326d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (gpcount < 8 && fpcount < 8) 327d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]); 32846ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith { 32946ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith UINT32 tmp; 33046ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith memcpy (&tmp, avalue[i], sizeof (UINT32)); 33146ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith stack->gp_regs[gpcount++] = tmp; 33246ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith } 333d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 334d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 335d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_DOUBLE: 336d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (gpcount < 8 && fpcount < 8) 337d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]); 33846ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64)); 339d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 340d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 341d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_LONGDOUBLE: 342d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (gpcount & 1) 343d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount++; 344d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) 345d4c9320412177895f598a93d73a0e654db27c351Thomas Heller stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]); 346d4c9320412177895f598a93d73a0e654db27c351Thomas Heller memcpy (&stack->gp_regs[gpcount], avalue[i], 16); 347d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount += 2; 348d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 349d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 350d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_STRUCT: 351d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 352d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t size = (*p_arg)->size; 353d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t align = (*p_arg)->alignment; 354d4c9320412177895f598a93d73a0e654db27c351Thomas Heller int hfa_type = hfa_element_type (*p_arg, 0); 355d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 356d4c9320412177895f598a93d73a0e654db27c351Thomas Heller FFI_ASSERT (align <= 16); 357d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (align == 16 && (gpcount & 1)) 358d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount++; 359d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 360d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (hfa_type != FFI_TYPE_VOID) 361d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 362d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t hfa_size = hfa_type_size (hfa_type); 363d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t offset = 0; 364d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t gp_offset = gpcount * 8; 365d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 366d4c9320412177895f598a93d73a0e654db27c351Thomas Heller while (fpcount < 8 367d4c9320412177895f598a93d73a0e654db27c351Thomas Heller && offset < size 368d4c9320412177895f598a93d73a0e654db27c351Thomas Heller && gp_offset < 8 * 8) 369d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 3708bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller hfa_type_load (&stack->fp_regs[fpcount], hfa_type, 3718bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller avalue[i] + offset); 372d4c9320412177895f598a93d73a0e654db27c351Thomas Heller offset += hfa_size; 373d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gp_offset += hfa_size; 374d4c9320412177895f598a93d73a0e654db27c351Thomas Heller fpcount += 1; 375d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 376d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 377d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 378d4c9320412177895f598a93d73a0e654db27c351Thomas Heller memcpy (&stack->gp_regs[gpcount], avalue[i], size); 379d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount += (size + 7) / 8; 380d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 381d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 382d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 383d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 384d4c9320412177895f598a93d73a0e654db27c351Thomas Heller abort (); 385d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 386d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 387d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 388d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ffi_call_unix (stack, rvalue, fn, cif->flags); 389d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 390d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 391d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Closures represent a pair consisting of a function pointer, and 392d4c9320412177895f598a93d73a0e654db27c351Thomas Heller some user data. A closure is invoked by reinterpreting the closure 393d4c9320412177895f598a93d73a0e654db27c351Thomas Heller as a function pointer, and branching to it. Thus we can make an 394d4c9320412177895f598a93d73a0e654db27c351Thomas Heller interpreted function callable as a C function: We turn the 395d4c9320412177895f598a93d73a0e654db27c351Thomas Heller interpreter itself, together with a pointer specifying the 396d4c9320412177895f598a93d73a0e654db27c351Thomas Heller interpreted procedure, into a closure. 397d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 398d4c9320412177895f598a93d73a0e654db27c351Thomas Heller For IA64, function pointer are already pairs consisting of a code 399d4c9320412177895f598a93d73a0e654db27c351Thomas Heller pointer, and a gp pointer. The latter is needed to access global 400d4c9320412177895f598a93d73a0e654db27c351Thomas Heller variables. Here we set up such a pair as the first two words of 401d4c9320412177895f598a93d73a0e654db27c351Thomas Heller the closure (in the "trampoline" area), but we replace the gp 402d4c9320412177895f598a93d73a0e654db27c351Thomas Heller pointer with a pointer to the closure itself. We also add the real 403d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gp pointer to the closure. This allows the function entry code to 404baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com both retrieve the user data, and to restore the correct gp pointer. */ 405d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 4068bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Hellerextern void ffi_closure_unix (); 407d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 408d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerffi_status 4098bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Hellerffi_prep_closure_loc (ffi_closure* closure, 4108bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ffi_cif* cif, 4118bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller void (*fun)(ffi_cif*,void*,void**,void*), 4128bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller void *user_data, 4138bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller void *codeloc) 414d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 415d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* The layout of a function descriptor. A C function pointer really 416d4c9320412177895f598a93d73a0e654db27c351Thomas Heller points to one of these. */ 417d4c9320412177895f598a93d73a0e654db27c351Thomas Heller struct ia64_fd 418d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 419d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 code_pointer; 420d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 gp; 421d4c9320412177895f598a93d73a0e654db27c351Thomas Heller }; 422d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 423d4c9320412177895f598a93d73a0e654db27c351Thomas Heller struct ffi_ia64_trampoline_struct 424d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 425d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 code_pointer; /* Pointer to ffi_closure_unix. */ 426d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 fake_gp; /* Pointer to closure, installed as gp. */ 427d4c9320412177895f598a93d73a0e654db27c351Thomas Heller UINT64 real_gp; /* Real gp value. */ 428d4c9320412177895f598a93d73a0e654db27c351Thomas Heller }; 429d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 430d4c9320412177895f598a93d73a0e654db27c351Thomas Heller struct ffi_ia64_trampoline_struct *tramp; 431d4c9320412177895f598a93d73a0e654db27c351Thomas Heller struct ia64_fd *fd; 432d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 43346ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith if (cif->abi != FFI_UNIX) 43446ce27ab1e22ca98957e0900c6a2415b86578b2eGregory P. Smith return FFI_BAD_ABI; 435d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 436d4c9320412177895f598a93d73a0e654db27c351Thomas Heller tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp; 437d4c9320412177895f598a93d73a0e654db27c351Thomas Heller fd = (struct ia64_fd *)(void *)ffi_closure_unix; 438d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 439d4c9320412177895f598a93d73a0e654db27c351Thomas Heller tramp->code_pointer = fd->code_pointer; 440d4c9320412177895f598a93d73a0e654db27c351Thomas Heller tramp->real_gp = fd->gp; 4418bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller tramp->fake_gp = (UINT64)(PTR64)codeloc; 442d4c9320412177895f598a93d73a0e654db27c351Thomas Heller closure->cif = cif; 443d4c9320412177895f598a93d73a0e654db27c351Thomas Heller closure->user_data = user_data; 444d4c9320412177895f598a93d73a0e654db27c351Thomas Heller closure->fun = fun; 445d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 446d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return FFI_OK; 447d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 448d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 449d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 450d4c9320412177895f598a93d73a0e654db27c351Thomas HellerUINT64 451d4c9320412177895f598a93d73a0e654db27c351Thomas Hellerffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, 452d4c9320412177895f598a93d73a0e654db27c351Thomas Heller void *rvalue, void *r8) 453d4c9320412177895f598a93d73a0e654db27c351Thomas Heller{ 454d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ffi_cif *cif; 455d4c9320412177895f598a93d73a0e654db27c351Thomas Heller void **avalue; 456d4c9320412177895f598a93d73a0e654db27c351Thomas Heller ffi_type **p_arg; 457d4c9320412177895f598a93d73a0e654db27c351Thomas Heller long i, avn, gpcount, fpcount; 458d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 459d4c9320412177895f598a93d73a0e654db27c351Thomas Heller cif = closure->cif; 460d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avn = cif->nargs; 461d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue = alloca (avn * sizeof (void *)); 462d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 463d4c9320412177895f598a93d73a0e654db27c351Thomas Heller /* If the structure return value is passed in memory get that location 464d4c9320412177895f598a93d73a0e654db27c351Thomas Heller from r8 so as to pass the value directly back to the caller. */ 465d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (cif->flags == FFI_TYPE_STRUCT) 466d4c9320412177895f598a93d73a0e654db27c351Thomas Heller rvalue = r8; 467d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 468d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount = fpcount = 0; 469d4c9320412177895f598a93d73a0e654db27c351Thomas Heller for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) 470d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 471d4c9320412177895f598a93d73a0e654db27c351Thomas Heller switch ((*p_arg)->type) 472d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 473d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT8: 474d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT8: 475d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1); 476d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 477d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT16: 478d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT16: 479d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2); 480d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 481d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT32: 482d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT32: 483d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4); 484d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 485d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_SINT64: 486d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_UINT64: 487d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = &stack->gp_regs[gpcount++]; 488d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 489d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_POINTER: 490d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*)); 491d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 492d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 493d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_FLOAT: 494d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (gpcount < 8 && fpcount < 8) 495d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 4968bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller fpreg *addr = &stack->fp_regs[fpcount++]; 4978bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller float result; 498d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = addr; 4998bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ldf_fill (result, addr); 5008bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller *(float *)addr = result; 501d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 502d4c9320412177895f598a93d73a0e654db27c351Thomas Heller else 503d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4); 504d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount++; 505d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 506d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 507d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_DOUBLE: 508d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (gpcount < 8 && fpcount < 8) 509d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 5108bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller fpreg *addr = &stack->fp_regs[fpcount++]; 5118bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller double result; 512d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = addr; 5138bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ldf_fill (result, addr); 5148bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller *(double *)addr = result; 515d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 516d4c9320412177895f598a93d73a0e654db27c351Thomas Heller else 517d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = &stack->gp_regs[gpcount]; 518d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount++; 519d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 520d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 521d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_LONGDOUBLE: 522d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (gpcount & 1) 523d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount++; 524d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) 525d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 5268bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller fpreg *addr = &stack->fp_regs[fpcount++]; 5278bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller __float80 result; 528d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = addr; 5298bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller ldf_fill (result, addr); 5308bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller *(__float80 *)addr = result; 531d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 532d4c9320412177895f598a93d73a0e654db27c351Thomas Heller else 533d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = &stack->gp_regs[gpcount]; 534d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount += 2; 535d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 536d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 537d4c9320412177895f598a93d73a0e654db27c351Thomas Heller case FFI_TYPE_STRUCT: 538d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 539d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t size = (*p_arg)->size; 540d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t align = (*p_arg)->alignment; 541d4c9320412177895f598a93d73a0e654db27c351Thomas Heller int hfa_type = hfa_element_type (*p_arg, 0); 542d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 543d4c9320412177895f598a93d73a0e654db27c351Thomas Heller FFI_ASSERT (align <= 16); 544d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (align == 16 && (gpcount & 1)) 545d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount++; 546d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 547d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (hfa_type != FFI_TYPE_VOID) 548d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 549d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t hfa_size = hfa_type_size (hfa_type); 550d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t offset = 0; 551d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size_t gp_offset = gpcount * 8; 552d4c9320412177895f598a93d73a0e654db27c351Thomas Heller void *addr = alloca (size); 553d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 554d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = addr; 555d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 556d4c9320412177895f598a93d73a0e654db27c351Thomas Heller while (fpcount < 8 557d4c9320412177895f598a93d73a0e654db27c351Thomas Heller && offset < size 558d4c9320412177895f598a93d73a0e654db27c351Thomas Heller && gp_offset < 8 * 8) 559d4c9320412177895f598a93d73a0e654db27c351Thomas Heller { 5608bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller hfa_type_store (hfa_type, addr + offset, 5618bdf81d2df388ce06088193f95c992a7ee1eb553Thomas Heller &stack->fp_regs[fpcount]); 562d4c9320412177895f598a93d73a0e654db27c351Thomas Heller offset += hfa_size; 563d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gp_offset += hfa_size; 564d4c9320412177895f598a93d73a0e654db27c351Thomas Heller fpcount += 1; 565d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 566d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 567d4c9320412177895f598a93d73a0e654db27c351Thomas Heller if (offset < size) 568d4c9320412177895f598a93d73a0e654db27c351Thomas Heller memcpy (addr + offset, (char *)stack->gp_regs + gp_offset, 569d4c9320412177895f598a93d73a0e654db27c351Thomas Heller size - offset); 570d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 571d4c9320412177895f598a93d73a0e654db27c351Thomas Heller else 572d4c9320412177895f598a93d73a0e654db27c351Thomas Heller avalue[i] = &stack->gp_regs[gpcount]; 573d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 574d4c9320412177895f598a93d73a0e654db27c351Thomas Heller gpcount += (size + 7) / 8; 575d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 576d4c9320412177895f598a93d73a0e654db27c351Thomas Heller break; 577d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 578d4c9320412177895f598a93d73a0e654db27c351Thomas Heller default: 579d4c9320412177895f598a93d73a0e654db27c351Thomas Heller abort (); 580d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 581d4c9320412177895f598a93d73a0e654db27c351Thomas Heller } 582d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 583d4c9320412177895f598a93d73a0e654db27c351Thomas Heller closure->fun (cif, rvalue, avalue, closure->user_data); 584d4c9320412177895f598a93d73a0e654db27c351Thomas Heller 585d4c9320412177895f598a93d73a0e654db27c351Thomas Heller return cif->flags; 586d4c9320412177895f598a93d73a0e654db27c351Thomas Heller} 587